diff -Burw indent.c indent.c
--- indent.c	2014-01-31 04:06:43.000000000 +0100
+++ indent.c	2016-05-22 19:24:01.666077311 +0200
@@ -568,7 +568,9 @@
 						 * happy */
 			if (ps.want_blank && *token != '[' &&
 			    (ps.last_token != ident || proc_calls_space
-				|| (ps.its_a_keyword && (!ps.sizeof_keyword || Bill_Shannon))))
+			    /* offsetof (1) is never allowed a space; sizeof (2) iff -bs;
+			     * all other keywords (>2) always get a space before lparen */
+				|| (ps.keyword + Bill_Shannon > 2)))
 				*e_code++ = ' ';
 			if (ps.in_decl && !ps.block_init) {
 				if (troff && !ps.dumped_decl_indent && !is_procname && ps.last_token == decl) {
@@ -601,17 +603,19 @@
 							 * structure decl or
 							 * initialization */
 			}
-			if (ps.sizeof_keyword)
-				ps.sizeof_mask |= 1 << ps.p_l_follow;
+			/* a parenthesized type name following sizeof or offsetof is not
+			 * a cast */
+			if (ps.keyword == 1 || ps.keyword == 2)
+				ps.not_cast_mask |= 1 << ps.p_l_follow;
 			break;
 
 		case rparen:	/* got a ')' or ']' */
 			rparen_count--;
-			if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) {
+			if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) {
 				ps.last_u_d = true;
 				ps.cast_mask &= (1 << ps.p_l_follow) - 1;
 			}
-			ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
+			ps.not_cast_mask &= (1 << ps.p_l_follow) - 1;
 			if (--ps.p_l_follow < 0) {
 				ps.p_l_follow = 0;
 				diag(0, "Extra %c", *token);
@@ -780,7 +784,7 @@
 			if (ps.last_token == rparen && rparen_count == 0)
 				ps.in_parameter_declaration = 0;
 			ps.cast_mask = 0;
-			ps.sizeof_mask = 0;
+			ps.not_cast_mask = 0;
 			ps.block_init = 0;
 			ps.block_init_level = 0;
 			ps.just_saw_decl--;
@@ -1042,7 +1046,7 @@
 	copy_id:
 			if (ps.want_blank)
 				*e_code++ = ' ';
-			if (troff && ps.its_a_keyword) {
+			if (troff && ps.keyword) {
 				e_code = chfont(&bodyf, &keywordf, e_code);
 				for (t_ptr = token; *t_ptr; ++t_ptr) {
 					CHECK_SIZE_CODE;
diff -Burw indent_globs.h indent_globs.h
--- indent_globs.h	2005-11-15 01:30:24.000000000 +0100
+++ indent_globs.h	2016-05-22 19:23:45.067093287 +0200
@@ -255,10 +255,10 @@
 				 * comment. In that case, the first non-blank
 				 * char should be lined up with the comment / */
 	int     comment_delta, n_comment_delta;
-	int     cast_mask;	/* indicates which close parens close off
-				 * casts */
-	int     sizeof_mask;	/* indicates which close parens close off
-				 * sizeof''s */
+	int     cast_mask;	/* indicates which close parens potentially
+				 * close off casts */
+	int     not_cast_mask;	/* indicates which close parens definitely
+				 * close off something else than casts */
 	int     block_init;	/* true iff inside a block initialization */
 	int     block_init_level;	/* The level of brace nesting in an
 					 * initialization */
@@ -327,8 +327,7 @@
 	int     else_if;	/* True iff else if pairs should be handled
 				 * specially */
 	int     decl_indent;	/* column to indent declared identifiers to */
-	int     its_a_keyword;
-	int     sizeof_keyword;
+	int     keyword; /* the type of a keyword or 0 */
 	int     dumped_decl_indent;
 	float   case_indent;	/* The distance to indent case labels from the
 				 * switch statement */
Binary files indent.o and indent.o differ
Binary files io.o and io.o differ
diff -Burw lexi.c lexi.c
--- lexi.c	2005-11-15 01:30:24.000000000 +0100
+++ lexi.c	2016-05-22 19:24:06.591072566 +0200
@@ -95,13 +95,13 @@
 
 struct templ specials[16384] =
 {
-	{"switch", 1},
-	{"case", 2},
-	{"break", 0},
+	{"switch", 7},
+	{"case", 8},
+	{"break", 9},
 	{"struct", 3},
 	{"union", 3},
 	{"enum", 3},
-	{"default", 2},
+	{"default", 8},
 	{"int", 4},
 	{"char", 4},
 	{"float", 4},
@@ -115,14 +115,15 @@
 	{"global", 4},
 	{"extern", 4},
 	{"void", 4},
-	{"goto", 0},
-	{"return", 0},
+	{"goto", 9},
+	{"return", 9},
 	{"if", 5},
 	{"while", 5},
 	{"for", 5},
 	{"else", 6},
 	{"do", 6},
-	{"sizeof", 7},
+	{"sizeof", 2},
+	{"offsetof", 1},
 	{0, 0}
 };
 
@@ -262,8 +263,7 @@
 			if (++buf_ptr >= buf_end)
 				fill_buffer();
 		}
-		ps.its_a_keyword = false;
-		ps.sizeof_keyword = false;
+		ps.keyword = 0;
 		if (l_struct) {	/* if last token was 'struct', then this token
 				 * should be treated as a declaration */
 			l_struct = false;
@@ -297,12 +297,12 @@
 		}
 		if (p->rwd) {	/* we have a keyword */
 	found_keyword:
-			ps.its_a_keyword = true;
+			ps.keyword = p->rwcode;
 			ps.last_u_d = true;
 			switch (p->rwcode) {
-			case 1:/* it is a switch */
+			case 7:/* it is a switch */
 				return (swstmt);
-			case 2:/* a case or default */
+			case 8:/* a case or default */
 				return (casestmt);
 
 			case 3:/* a "struct" */
@@ -316,7 +316,11 @@
 				 */
 			case 4:/* one of the declaration keywords */
 				if (ps.p_l_follow) {
-					ps.cast_mask |= 1 << ps.p_l_follow;
+					/* A type name following an lparen is a cast unless it's
+					 * a part of a function declarator, or an operand of the
+					 * sizeof operator, or an argument of the offsetof macro
+					 */
+					ps.cast_mask |= (1 << ps.p_l_follow & ~ps.not_cast_mask);
 					break;	/* inside parens: cast */
 				}
 				last_code = decl;
@@ -328,8 +332,6 @@
 			case 6:/* do, else */
 				return (sp_nparen);
 
-			case 7:
-				ps.sizeof_keyword = true;
 			default:	/* all others are treated like any
 					 * other identifier */
 				return (ident);
@@ -357,7 +359,7 @@
 		    && (ps.last_token == rparen || ps.last_token == semicolon ||
 			ps.last_token == decl ||
 			ps.last_token == lbrace || ps.last_token == rbrace)) {
-			ps.its_a_keyword = true;
+			ps.keyword = 4; /* a type name */
 			ps.last_u_d = true;
 			last_code = decl;
 			return decl;
