浏览代码

Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6

* 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6:
  kbuild: Make DEBUG_SECTION_MISMATCH selectable, but not on by default
  genksyms: Regenerate lexer and parser
  genksyms: Track changes to enum constants
  genksyms: simplify usage of find_symbol()
  genksyms: Add helpers for building string lists
  genksyms: Simplify printing of symbol types
  genksyms: Simplify lexer
  genksyms: Do not paste the bison header file to lex.c
  modpost: fix trailing comma
  KBuild: silence "'scripts/unifdef' is up to date."
  kbuild: Add extra gcc checks
  kbuild: reenable section mismatch analysis
  unifdef: update to upstream version 2.5
Linus Torvalds 14 年之前
父节点
当前提交
eddecbb601

+ 5 - 0
Documentation/kbuild/kbuild.txt

@@ -196,3 +196,8 @@ to be included in the databases, separated by blank space. E.g.:
 To get all available archs you can also specify all. E.g.:
 
     $ make ALLSOURCE_ARCHS=all tags
+
+KBUILD_ENABLE_EXTRA_GCC_CHECKS
+--------------------------------------------------
+If enabled over the make command line with "W=1", it turns on additional
+gcc -W... options for more extensive build-time checking.

+ 6 - 1
Makefile

@@ -102,6 +102,10 @@ ifeq ("$(origin O)", "command line")
   KBUILD_OUTPUT := $(O)
 endif
 
+ifeq ("$(origin W)", "command line")
+  export KBUILD_ENABLE_EXTRA_GCC_CHECKS := 1
+endif
+
 # That's our default target when none is given on the command line
 PHONY := _all
 _all:
@@ -1018,7 +1022,7 @@ hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
 
 PHONY += __headers
 __headers: include/linux/version.h scripts_basic FORCE
-	$(Q)$(MAKE) $(build)=scripts scripts/unifdef
+	$(Q)$(MAKE) $(build)=scripts build_unifdef
 
 PHONY += headers_install_all
 headers_install_all:
@@ -1263,6 +1267,7 @@ help:
 	@echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
 	@echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
 	@echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
+	@echo  '  make W=1   [targets] Enable extra gcc checks'
 	@echo  ''
 	@echo  'Execute "make" or "make all" to build all targets marked with [*] '
 	@echo  'For further info see the ./README file'

+ 0 - 5
lib/Kconfig.debug

@@ -102,11 +102,6 @@ config HEADERS_CHECK
 
 config DEBUG_SECTION_MISMATCH
 	bool "Enable full Section mismatch analysis"
-	depends on UNDEFINED || (BLACKFIN)
-	default y
-	# This option is on purpose disabled for now.
-	# It will be enabled when we are down to a reasonable number
-	# of section mismatch warnings (< 10 for an allyesconfig build)
 	help
 	  The section mismatch analysis checks if there are illegal
 	  references from one section to another section.

+ 5 - 0
scripts/Makefile

@@ -18,6 +18,11 @@ always		:= $(hostprogs-y) $(hostprogs-m)
 # The following hostprogs-y programs are only build on demand
 hostprogs-y += unifdef
 
+# This target is used internally to avoid "is up to date" messages
+PHONY += build_unifdef
+build_unifdef: scripts/unifdef FORCE
+	@:
+
 subdir-$(CONFIG_MODVERSIONS) += genksyms
 subdir-y                     += mod
 subdir-$(CONFIG_SECURITY_SELINUX) += selinux

+ 34 - 1
scripts/Makefile.build

@@ -49,6 +49,40 @@ ifeq ($(KBUILD_NOPEDANTIC),)
                 $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use EXTRA_CFLAGS)
         endif
 endif
+
+#
+# make W=1 settings
+#
+# $(call cc-option... ) handles gcc -W.. options which
+# are not supported by all versions of the compiler
+ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS
+KBUILD_EXTRA_WARNINGS := -Wextra
+KBUILD_EXTRA_WARNINGS += -Wunused -Wno-unused-parameter
+KBUILD_EXTRA_WARNINGS += -Waggregate-return
+KBUILD_EXTRA_WARNINGS += -Wbad-function-cast
+KBUILD_EXTRA_WARNINGS += -Wcast-qual
+KBUILD_EXTRA_WARNINGS += -Wcast-align
+KBUILD_EXTRA_WARNINGS += -Wconversion
+KBUILD_EXTRA_WARNINGS += -Wdisabled-optimization
+KBUILD_EXTRA_WARNINGS += -Wlogical-op
+KBUILD_EXTRA_WARNINGS += -Wmissing-declarations
+KBUILD_EXTRA_WARNINGS += -Wmissing-format-attribute
+KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wmissing-include-dirs,)
+KBUILD_EXTRA_WARNINGS += -Wmissing-prototypes
+KBUILD_EXTRA_WARNINGS += -Wnested-externs
+KBUILD_EXTRA_WARNINGS += -Wold-style-definition
+KBUILD_EXTRA_WARNINGS += $(call cc-option, -Woverlength-strings,)
+KBUILD_EXTRA_WARNINGS += -Wpacked
+KBUILD_EXTRA_WARNINGS += -Wpacked-bitfield-compat
+KBUILD_EXTRA_WARNINGS += -Wpadded
+KBUILD_EXTRA_WARNINGS += -Wpointer-arith
+KBUILD_EXTRA_WARNINGS += -Wredundant-decls
+KBUILD_EXTRA_WARNINGS += -Wshadow
+KBUILD_EXTRA_WARNINGS += -Wswitch-default
+KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wvla,)
+KBUILD_CFLAGS += $(KBUILD_EXTRA_WARNINGS)
+endif
+
 include scripts/Makefile.lib
 
 ifdef host-progs
@@ -403,7 +437,6 @@ ifneq ($(cmd_files),)
   include $(cmd_files)
 endif
 
-
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable se we can use it in if_changed and friends.
 

+ 2 - 2
scripts/genksyms/Makefile

@@ -28,9 +28,9 @@ $(obj)/keywords.c: $(obj)/keywords.gperf FORCE
 # flex
 
 quiet_cmd_lex.c = FLEX    $@
-      cmd_lex.c = flex -o$@ -d $< $(obj)/parse.h
+      cmd_lex.c = flex -o$@ -d $<
 
-$(obj)/lex.c: $(obj)/lex.l $(obj)/parse.h $(obj)/keywords.c FORCE
+$(obj)/lex.c: $(obj)/lex.l $(obj)/keywords.c FORCE
 	$(call if_changed,lex.c)
 	cp $@ $@_shipped
 

+ 136 - 56
scripts/genksyms/genksyms.c

@@ -53,12 +53,22 @@ static int nsyms;
 static struct symbol *expansion_trail;
 static struct symbol *visited_symbols;
 
-static const char *const symbol_type_name[] = {
-	"normal", "typedef", "enum", "struct", "union"
+static const struct {
+	int n;
+	const char *name;
+} symbol_types[] = {
+	[SYM_NORMAL]     = { 0, NULL},
+	[SYM_TYPEDEF]    = {'t', "typedef"},
+	[SYM_ENUM]       = {'e', "enum"},
+	[SYM_STRUCT]     = {'s', "struct"},
+	[SYM_UNION]      = {'u', "union"},
+	[SYM_ENUM_CONST] = {'E', "enum constant"},
 };
 
 static int equal_list(struct string_list *a, struct string_list *b);
 static void print_list(FILE * f, struct string_list *list);
+static struct string_list *concat_list(struct string_list *start, ...);
+static struct string_list *mk_node(const char *string);
 static void print_location(void);
 static void print_type_name(enum symbol_type type, const char *name);
 
@@ -140,14 +150,20 @@ static unsigned long crc32(const char *s)
 
 static enum symbol_type map_to_ns(enum symbol_type t)
 {
-	if (t == SYM_TYPEDEF)
-		t = SYM_NORMAL;
-	else if (t == SYM_UNION)
-		t = SYM_STRUCT;
+	switch (t) {
+	case SYM_ENUM_CONST:
+	case SYM_NORMAL:
+	case SYM_TYPEDEF:
+		return SYM_NORMAL;
+	case SYM_ENUM:
+	case SYM_STRUCT:
+	case SYM_UNION:
+		return SYM_STRUCT;
+	}
 	return t;
 }
 
-struct symbol *find_symbol(const char *name, enum symbol_type ns)
+struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
 {
 	unsigned long h = crc32(name) % HASH_BUCKETS;
 	struct symbol *sym;
@@ -158,6 +174,8 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns)
 		    sym->is_declared)
 			break;
 
+	if (exact && sym && sym->type != ns)
+		return NULL;
 	return sym;
 }
 
@@ -180,10 +198,47 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
 			    struct string_list *defn, int is_extern,
 			    int is_reference)
 {
-	unsigned long h = crc32(name) % HASH_BUCKETS;
+	unsigned long h;
 	struct symbol *sym;
 	enum symbol_status status = STATUS_UNCHANGED;
+	/* The parser adds symbols in the order their declaration completes,
+	 * so it is safe to store the value of the previous enum constant in
+	 * a static variable.
+	 */
+	static int enum_counter;
+	static struct string_list *last_enum_expr;
+
+	if (type == SYM_ENUM_CONST) {
+		if (defn) {
+			free_list(last_enum_expr, NULL);
+			last_enum_expr = copy_list_range(defn, NULL);
+			enum_counter = 1;
+		} else {
+			struct string_list *expr;
+			char buf[20];
+
+			snprintf(buf, sizeof(buf), "%d", enum_counter++);
+			if (last_enum_expr) {
+				expr = copy_list_range(last_enum_expr, NULL);
+				defn = concat_list(mk_node("("),
+						   expr,
+						   mk_node(")"),
+						   mk_node("+"),
+						   mk_node(buf), NULL);
+			} else {
+				defn = mk_node(buf);
+			}
+		}
+	} else if (type == SYM_ENUM) {
+		free_list(last_enum_expr, NULL);
+		last_enum_expr = NULL;
+		enum_counter = 0;
+		if (!name)
+			/* Anonymous enum definition, nothing more to do */
+			return NULL;
+	}
 
+	h = crc32(name) % HASH_BUCKETS;
 	for (sym = symtab[h]; sym; sym = sym->hash_next) {
 		if (map_to_ns(sym->type) == map_to_ns(type) &&
 		    strcmp(name, sym->name) == 0) {
@@ -247,8 +302,12 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
 	sym->is_override = 0;
 
 	if (flag_debug) {
-		fprintf(debugfile, "Defn for %s %s == <",
-			symbol_type_name[type], name);
+		if (symbol_types[type].name)
+			fprintf(debugfile, "Defn for %s %s == <",
+				symbol_types[type].name, name);
+		else
+			fprintf(debugfile, "Defn for type%d %s == <",
+				type, name);
 		if (is_extern)
 			fputs("extern ", debugfile);
 		print_list(debugfile, defn);
@@ -288,6 +347,35 @@ void free_list(struct string_list *s, struct string_list *e)
 	}
 }
 
+static struct string_list *mk_node(const char *string)
+{
+	struct string_list *newnode;
+
+	newnode = xmalloc(sizeof(*newnode));
+	newnode->string = xstrdup(string);
+	newnode->tag = SYM_NORMAL;
+	newnode->next = NULL;
+
+	return newnode;
+}
+
+static struct string_list *concat_list(struct string_list *start, ...)
+{
+	va_list ap;
+	struct string_list *n, *n2;
+
+	if (!start)
+		return NULL;
+	for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
+		for (n2 = n; n2->next; n2 = n2->next)
+			;
+		n2->next = start;
+		start = n;
+	}
+	va_end(ap);
+	return start;
+}
+
 struct string_list *copy_node(struct string_list *node)
 {
 	struct string_list *newnode;
@@ -299,6 +387,22 @@ struct string_list *copy_node(struct string_list *node)
 	return newnode;
 }
 
+struct string_list *copy_list_range(struct string_list *start,
+				    struct string_list *end)
+{
+	struct string_list *res, *n;
+
+	if (start == end)
+		return NULL;
+	n = res = copy_node(start);
+	for (start = start->next; start != end; start = start->next) {
+		n->next = copy_node(start);
+		n = n->next;
+	}
+	n->next = NULL;
+	return res;
+}
+
 static int equal_list(struct string_list *a, struct string_list *b)
 {
 	while (a && b) {
@@ -346,8 +450,8 @@ static struct string_list *read_node(FILE *f)
 	if (node.string[1] == '#') {
 		int n;
 
-		for (n = 0; n < ARRAY_SIZE(symbol_type_name); n++) {
-			if (node.string[0] == symbol_type_name[n][0]) {
+		for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
+			if (node.string[0] == symbol_types[n].n) {
 				node.tag = n;
 				node.string += 2;
 				return copy_node(&node);
@@ -397,8 +501,8 @@ static void read_reference(FILE *f)
 
 static void print_node(FILE * f, struct string_list *list)
 {
-	if (list->tag != SYM_NORMAL) {
-		putc(symbol_type_name[list->tag][0], f);
+	if (symbol_types[list->tag].n) {
+		putc(symbol_types[list->tag].n, f);
 		putc('#', f);
 	}
 	fputs(list->string, f);
@@ -468,8 +572,9 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
 			crc = partial_crc32_one(' ', crc);
 			break;
 
+		case SYM_ENUM_CONST:
 		case SYM_TYPEDEF:
-			subsym = find_symbol(cur->string, cur->tag);
+			subsym = find_symbol(cur->string, cur->tag, 0);
 			/* FIXME: Bad reference files can segfault here. */
 			if (subsym->expansion_trail) {
 				if (flag_dump_defs)
@@ -486,55 +591,30 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
 		case SYM_STRUCT:
 		case SYM_UNION:
 		case SYM_ENUM:
-			subsym = find_symbol(cur->string, cur->tag);
+			subsym = find_symbol(cur->string, cur->tag, 0);
 			if (!subsym) {
-				struct string_list *n, *t = NULL;
+				struct string_list *n;
 
 				error_with_pos("expand undefined %s %s",
-					       symbol_type_name[cur->tag],
+					       symbol_types[cur->tag].name,
 					       cur->string);
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup(symbol_type_name[cur->tag]);
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup(cur->string);
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup("{");
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup("UNKNOWN");
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup("}");
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
+				n = concat_list(mk_node
+						(symbol_types[cur->tag].name),
+						mk_node(cur->string),
+						mk_node("{"),
+						mk_node("UNKNOWN"),
+						mk_node("}"), NULL);
 				subsym =
 				    add_symbol(cur->string, cur->tag, n, 0);
 			}
 			if (subsym->expansion_trail) {
 				if (flag_dump_defs) {
 					fprintf(debugfile, "%s %s ",
-						symbol_type_name[cur->tag],
+						symbol_types[cur->tag].name,
 						cur->string);
 				}
 
-				crc = partial_crc32(symbol_type_name[cur->tag],
+				crc = partial_crc32(symbol_types[cur->tag].name,
 						    crc);
 				crc = partial_crc32_one(' ', crc);
 				crc = partial_crc32(cur->string, crc);
@@ -565,7 +645,7 @@ void export_symbol(const char *name)
 {
 	struct symbol *sym;
 
-	sym = find_symbol(name, SYM_NORMAL);
+	sym = find_symbol(name, SYM_NORMAL, 0);
 	if (!sym)
 		error_with_pos("export undefined symbol %s", name);
 	else {
@@ -624,8 +704,8 @@ static void print_location(void)
 
 static void print_type_name(enum symbol_type type, const char *name)
 {
-	if (type != SYM_NORMAL)
-		fprintf(stderr, "%s %s", symbol_type_name[type], name);
+	if (symbol_types[type].name)
+		fprintf(stderr, "%s %s", symbol_types[type].name, name);
 	else
 		fprintf(stderr, "%s", name);
 }
@@ -771,8 +851,8 @@ int main(int argc, char **argv)
 
 			if (sym->is_override)
 				fputs("override ", dumpfile);
-			if (sym->type != SYM_NORMAL) {
-				putc(symbol_type_name[sym->type][0], dumpfile);
+			if (symbol_types[sym->type].n) {
+				putc(symbol_types[sym->type].n, dumpfile);
 				putc('#', dumpfile);
 			}
 			fputs(sym->name, dumpfile);

+ 5 - 2
scripts/genksyms/genksyms.h

@@ -26,7 +26,8 @@
 #include <stdio.h>
 
 enum symbol_type {
-	SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION
+	SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION,
+	SYM_ENUM_CONST
 };
 
 enum symbol_status {
@@ -58,7 +59,7 @@ typedef struct string_list **yystype;
 extern int cur_line;
 extern char *cur_filename;
 
-struct symbol *find_symbol(const char *name, enum symbol_type ns);
+struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact);
 struct symbol *add_symbol(const char *name, enum symbol_type type,
 			  struct string_list *defn, int is_extern);
 void export_symbol(const char *);
@@ -66,6 +67,8 @@ void export_symbol(const char *);
 void free_node(struct string_list *list);
 void free_list(struct string_list *s, struct string_list *e);
 struct string_list *copy_node(struct string_list *);
+struct string_list *copy_list_range(struct string_list *start,
+				    struct string_list *end);
 
 int yylex(void);
 int yyparse(void);

+ 150 - 277
scripts/genksyms/lex.c_shipped

@@ -79,6 +79,7 @@ typedef int flex_int32_t;
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -109,8 +110,6 @@ typedef unsigned int flex_uint32_t;
 #define UINT32_MAX             (4294967295U)
 #endif
 
-#endif /* ! C99 */
-
 #endif /* ! FLEXINT_H */
 
 /* %endif */
@@ -456,16 +455,16 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[76] =
+static yyconst flex_int16_t yy_accept[73] =
     {   0,
-        0,    0,    0,    0,   14,   12,    4,    3,   12,    7,
-       12,   12,    7,   12,   12,   12,   12,   12,    9,    9,
-       12,   12,   12,    4,    0,    5,    0,    7,    0,    6,
-        0,    0,    0,    0,    0,    0,    2,    8,   10,   10,
-        9,    0,    0,    9,    9,    0,    9,    0,    0,   11,
-        0,    0,    0,   10,    0,   10,    9,    9,    0,    0,
-        0,    0,    0,    0,    0,   10,   10,    0,    0,    0,
-        0,    0,    0,    1,    0
+        0,    0,   14,   12,    4,    3,   12,    7,   12,   12,
+       12,   12,   12,    9,    9,   12,   12,    7,   12,   12,
+        4,    0,    5,    0,    7,    8,    0,    6,    0,    0,
+       10,   10,    9,    0,    0,    9,    9,    0,    9,    0,
+        0,    0,    0,    2,    0,    0,   11,    0,   10,    0,
+       10,    9,    9,    0,    0,    0,   10,   10,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        1,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -507,108 +506,104 @@ static yyconst flex_int32_t yy_meta[29] =
         8,    7,    3,    3,    3,    1,    3,    1
     } ;
 
-static yyconst flex_int16_t yy_base[88] =
+static yyconst flex_int16_t yy_base[85] =
     {   0,
-        0,  147,   21,  140,  145,  284,   39,  284,   26,    0,
-       32,  126,   40,   44,  115,   35,   36,   46,   50,   53,
-       39,   61,   54,   79,   65,  284,    0,    0,   66,  284,
-        0,  119,   79,   75,  123,  104,  284,  284,  107,    0,
-       79,   73,   76,   76,   66,    0,    0,   85,   86,  284,
-      133,   83,   91,  284,   99,  147,  284,  114,  122,   70,
-      107,  141,  172,  151,  135,  181,  284,  137,  114,  157,
-      149,   48,   45,  284,  284,  208,  214,  222,  230,  238,
-      246,  250,  255,  256,  261,  267,  275
+        0,  145,  150,  266,   27,  266,   25,    0,  131,   23,
+       23,   16,   23,   39,   31,   25,   39,   60,   22,   65,
+       57,   43,  266,    0,    0,  266,   61,  266,    0,  128,
+       74,    0,  113,   59,   62,  113,   52,    0,    0,   72,
+       66,  110,  100,  266,   73,   74,  266,   70,  266,   90,
+      103,  266,   84,  129,  108,  113,  143,  266,  107,   66,
+      118,  137,  168,  120,   80,   91,  145,  143,   83,   41,
+      266,  266,  190,  196,  204,  212,  220,  228,  232,  237,
+      238,  243,  249,  257
     } ;
 
-static yyconst flex_int16_t yy_def[88] =
+static yyconst flex_int16_t yy_def[85] =
     {   0,
-       75,    1,    1,    3,   75,   75,   75,   75,   76,   77,
-       78,   75,   77,   79,   75,   75,   75,   75,   75,   19,
-       75,   75,   75,   75,   76,   75,   80,   77,   78,   75,
-       81,   75,   76,   78,   79,   79,   75,   75,   75,   39,
-       19,   82,   83,   75,   75,   84,   20,   76,   78,   75,
-       79,   51,   85,   75,   75,   75,   75,   84,   79,   51,
-       79,   79,   79,   51,   75,   75,   75,   86,   79,   63,
-       86,   87,   87,   75,    0,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75
+       72,    1,   72,   72,   72,   72,   73,   74,   72,   72,
+       75,   72,   72,   72,   14,   72,   72,   74,   72,   76,
+       72,   73,   72,   77,   74,   72,   75,   72,   78,   72,
+       72,   31,   14,   79,   80,   72,   72,   81,   15,   73,
+       75,   76,   76,   72,   73,   75,   72,   82,   72,   72,
+       72,   72,   81,   76,   54,   72,   72,   72,   76,   54,
+       76,   76,   76,   54,   83,   76,   63,   83,   84,   84,
+       72,    0,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
     } ;
 
-static yyconst flex_int16_t yy_nxt[313] =
+static yyconst flex_int16_t yy_nxt[295] =
     {   0,
-        6,    7,    8,    7,    9,    6,   10,    6,    6,   11,
-        6,    6,   12,    6,    6,    6,    6,    6,    6,   10,
-       10,   10,   13,   10,   10,    6,   10,    6,   15,   16,
-       26,   15,   17,   18,   19,   20,   20,   21,   15,   22,
-       24,   30,   24,   38,   33,   36,   37,   74,   23,   34,
-       74,   27,   38,   38,   38,   38,   38,   31,   32,   39,
-       39,   39,   40,   41,   41,   42,   47,   47,   47,   26,
-       43,   38,   44,   45,   46,   30,   44,   75,   38,   38,
-       24,   38,   24,   26,   30,   40,   55,   55,   57,   26,
-       27,   31,   57,   43,   35,   30,   64,   64,   64,   57,
-
-       31,   65,   65,   75,   27,   36,   37,   35,   59,   37,
-       27,   31,   56,   56,   56,   59,   37,   51,   52,   52,
-       39,   39,   39,   59,   37,   37,   68,   53,   54,   54,
-       69,   50,   38,   54,   59,   37,   44,   45,   32,   37,
-       44,   35,   59,   37,   75,   14,   60,   60,   66,   66,
-       66,   37,   14,   72,   75,   61,   62,   63,   59,   61,
-       56,   56,   56,   69,   64,   64,   64,   69,   67,   67,
-       75,   75,   75,   67,   37,   35,   75,   75,   75,   61,
-       62,   75,   75,   61,   75,   70,   70,   70,   75,   75,
-       75,   70,   70,   70,   66,   66,   66,   75,   75,   75,
-
-       75,   75,   54,   54,   75,   75,   75,   54,   25,   25,
-       25,   25,   25,   25,   25,   25,   28,   75,   75,   28,
-       28,   28,   29,   29,   29,   29,   29,   29,   29,   29,
-       35,   35,   35,   35,   35,   35,   35,   35,   48,   75,
-       48,   48,   48,   48,   48,   48,   49,   75,   49,   49,
-       49,   49,   49,   49,   42,   42,   75,   42,   56,   75,
-       56,   58,   58,   58,   66,   75,   66,   71,   71,   71,
-       71,   71,   71,   71,   71,   73,   73,   73,   73,   73,
-       73,   73,   73,    5,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75
+        4,    5,    6,    5,    7,    4,    8,    9,   10,   11,
+        9,   12,   13,   14,   15,   15,   16,    9,   17,    8,
+        8,    8,   18,    8,    8,    4,    8,   19,   21,   23,
+       21,   26,   28,   26,   26,   30,   31,   31,   31,   26,
+       26,   26,   26,   71,   39,   39,   39,   23,   29,   26,
+       24,   32,   33,   33,   34,   72,   26,   26,   21,   35,
+       21,   36,   37,   38,   40,   36,   43,   44,   24,   41,
+       28,   32,   50,   50,   52,   28,   23,   23,   52,   35,
+       56,   56,   44,   28,   42,   71,   29,   31,   31,   31,
+       42,   29,   59,   44,   48,   49,   49,   24,   24,   29,
+
+       49,   43,   44,   51,   51,   51,   36,   37,   59,   44,
+       36,   65,   44,   54,   55,   55,   51,   51,   51,   59,
+       44,   64,   64,   64,   58,   58,   57,   57,   57,   58,
+       59,   44,   42,   64,   64,   64,   52,   72,   59,   44,
+       47,   66,   60,   60,   42,   44,   59,   69,   26,   72,
+       20,   61,   62,   63,   72,   61,   57,   57,   57,   66,
+       72,   72,   72,   66,   49,   49,   72,   61,   62,   49,
+       44,   61,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   67,   67,   67,   72,   72,   72,   67,   67,   67,
+       22,   22,   22,   22,   22,   22,   22,   22,   25,   72,
+
+       72,   25,   25,   25,   27,   27,   27,   27,   27,   27,
+       27,   27,   42,   42,   42,   42,   42,   42,   42,   42,
+       45,   72,   45,   45,   45,   45,   45,   45,   46,   72,
+       46,   46,   46,   46,   46,   46,   34,   34,   72,   34,
+       51,   72,   51,   53,   53,   53,   57,   72,   57,   68,
+       68,   68,   68,   68,   68,   68,   68,   70,   70,   70,
+       70,   70,   70,   70,   70,    3,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
+
     } ;
 
-static yyconst flex_int16_t yy_chk[313] =
+static yyconst flex_int16_t yy_chk[295] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    3,    3,
-        9,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        7,   11,    7,   16,   13,   14,   14,   73,    3,   13,
-       72,    9,   16,   17,   17,   21,   21,   11,   18,   18,
-       18,   18,   19,   19,   19,   19,   20,   20,   20,   25,
-       19,   23,   19,   19,   19,   29,   19,   20,   22,   22,
-       24,   23,   24,   33,   34,   42,   43,   43,   45,   48,
-       25,   29,   45,   42,   60,   49,   52,   52,   52,   44,
-
-       34,   53,   53,   41,   33,   36,   36,   52,   61,   61,
-       48,   49,   55,   55,   55,   69,   69,   36,   36,   36,
-       39,   39,   39,   59,   59,   35,   59,   39,   39,   39,
-       61,   32,   15,   39,   51,   51,   58,   58,   12,   68,
-       58,   68,   62,   62,    5,    4,   51,   51,   65,   65,
-       65,   71,    2,   71,    0,   51,   51,   51,   70,   51,
-       56,   56,   56,   62,   64,   64,   64,   62,   56,   56,
-        0,    0,    0,   56,   63,   64,    0,    0,    0,   70,
-       70,    0,    0,   70,    0,   63,   63,   63,    0,    0,
-        0,   63,   63,   63,   66,   66,   66,    0,    0,    0,
-
-        0,    0,   66,   66,    0,    0,    0,   66,   76,   76,
-       76,   76,   76,   76,   76,   76,   77,    0,    0,   77,
-       77,   77,   78,   78,   78,   78,   78,   78,   78,   78,
-       79,   79,   79,   79,   79,   79,   79,   79,   80,    0,
-       80,   80,   80,   80,   80,   80,   81,    0,   81,   81,
-       81,   81,   81,   81,   82,   82,    0,   82,   83,    0,
-       83,   84,   84,   84,   85,    0,   85,   86,   86,   86,
-       86,   86,   86,   86,   86,   87,   87,   87,   87,   87,
-       87,   87,   87,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75
+        1,    1,    1,    1,    1,    1,    1,    1,    5,    7,
+        5,   10,   11,   12,   12,   13,   13,   13,   13,   19,
+       10,   16,   16,   70,   15,   15,   15,   22,   11,   19,
+        7,   14,   14,   14,   14,   15,   17,   17,   21,   14,
+       21,   14,   14,   14,   18,   14,   20,   20,   22,   18,
+       27,   34,   35,   35,   37,   41,   40,   45,   37,   34,
+       48,   48,   65,   46,   65,   69,   27,   31,   31,   31,
+       60,   41,   66,   66,   31,   31,   31,   40,   45,   46,
+
+       31,   43,   43,   50,   50,   50,   53,   53,   59,   59,
+       53,   59,   42,   43,   43,   43,   51,   51,   51,   61,
+       61,   55,   55,   55,   51,   51,   56,   56,   56,   51,
+       54,   54,   55,   64,   64,   64,   36,   33,   62,   62,
+       30,   61,   54,   54,   64,   68,   67,   68,    9,    3,
+        2,   54,   54,   54,    0,   54,   57,   57,   57,   62,
+        0,    0,    0,   62,   57,   57,    0,   67,   67,   57,
+       63,   67,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,   63,   63,   63,    0,    0,    0,   63,   63,   63,
+       73,   73,   73,   73,   73,   73,   73,   73,   74,    0,
+
+        0,   74,   74,   74,   75,   75,   75,   75,   75,   75,
+       75,   75,   76,   76,   76,   76,   76,   76,   76,   76,
+       77,    0,   77,   77,   77,   77,   77,   77,   78,    0,
+       78,   78,   78,   78,   78,   78,   79,   79,    0,   79,
+       80,    0,   80,   81,   81,   81,   82,    0,   82,   83,
+       83,   83,   83,   83,   83,   83,   83,   84,   84,   84,
+       84,   84,   84,   84,   84,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
+
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -619,8 +614,8 @@ int yy_flex_debug = 1;
 
 static yyconst flex_int16_t yy_rule_linenum[13] =
     {   0,
-       71,   72,   73,   76,   79,   80,   81,   87,   88,   89,
-       91,   94
+       67,   68,   69,   72,   75,   76,   77,   83,   84,   85,
+       87,   90
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -667,15 +662,11 @@ char *yytext;
    and then we categorize those basic tokens in the second stage.  */
 #define YY_DECL		static int yylex1(void)
 
-/* Version 2 checksumming does proper tokenization; version 1 wasn't
-   quite so pedantic.  */
-
 /* We don't do multiple input files.  */
 #define YY_NO_INPUT 1
-#line 676 "scripts/genksyms/lex.c"
+#line 668 "scripts/genksyms/lex.c"
 
 #define INITIAL 0
-#define V2_TOKENS 1
 
 #ifndef YY_NO_UNISTD_H
 /* Special case for "unistd.h", since it is non-ANSI. We include it way
@@ -808,7 +799,7 @@ static int input (void );
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		size_t n; \
+		int n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -918,12 +909,12 @@ YY_DECL
 	register int yy_act;
     
 /* %% [7.0] user's declarations go here */
-#line 67 "scripts/genksyms/lex.l"
+#line 63 "scripts/genksyms/lex.l"
 
 
 
  /* Keep track of our location in the original source files.  */
-#line 927 "scripts/genksyms/lex.c"
+#line 918 "scripts/genksyms/lex.c"
 
 	if ( !(yy_init) )
 		{
@@ -987,13 +978,13 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 76 )
+				if ( yy_current_state >= 73 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			}
-		while ( yy_base[yy_current_state] != 284 );
+		while ( yy_base[yy_current_state] != 266 );
 
 yy_find_action:
 /* %% [10.0] code to find the action number goes here */
@@ -1041,42 +1032,42 @@ do_action:	/* This label is used only to access EOF actions. */
 case 1:
 /* rule 1 can match eol */
 YY_RULE_SETUP
-#line 71 "scripts/genksyms/lex.l"
+#line 67 "scripts/genksyms/lex.l"
 return FILENAME;
 	YY_BREAK
 case 2:
 /* rule 2 can match eol */
 YY_RULE_SETUP
-#line 72 "scripts/genksyms/lex.l"
+#line 68 "scripts/genksyms/lex.l"
 cur_line++;
 	YY_BREAK
 case 3:
 /* rule 3 can match eol */
 YY_RULE_SETUP
-#line 73 "scripts/genksyms/lex.l"
+#line 69 "scripts/genksyms/lex.l"
 cur_line++;
 	YY_BREAK
 /* Ignore all other whitespace.  */
 case 4:
 YY_RULE_SETUP
-#line 76 "scripts/genksyms/lex.l"
+#line 72 "scripts/genksyms/lex.l"
 ;
 	YY_BREAK
 case 5:
 /* rule 5 can match eol */
 YY_RULE_SETUP
-#line 79 "scripts/genksyms/lex.l"
+#line 75 "scripts/genksyms/lex.l"
 return STRING;
 	YY_BREAK
 case 6:
 /* rule 6 can match eol */
 YY_RULE_SETUP
-#line 80 "scripts/genksyms/lex.l"
+#line 76 "scripts/genksyms/lex.l"
 return CHAR;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 81 "scripts/genksyms/lex.l"
+#line 77 "scripts/genksyms/lex.l"
 return IDENT;
 	YY_BREAK
 /* The Pedant requires that the other C multi-character tokens be
@@ -1085,38 +1076,37 @@ return IDENT;
     around them properly.  */
 case 8:
 YY_RULE_SETUP
-#line 87 "scripts/genksyms/lex.l"
+#line 83 "scripts/genksyms/lex.l"
 return OTHER;
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 88 "scripts/genksyms/lex.l"
+#line 84 "scripts/genksyms/lex.l"
 return INT;
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 89 "scripts/genksyms/lex.l"
+#line 85 "scripts/genksyms/lex.l"
 return REAL;
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 91 "scripts/genksyms/lex.l"
+#line 87 "scripts/genksyms/lex.l"
 return DOTS;
 	YY_BREAK
 /* All other tokens are single characters.  */
 case 12:
 YY_RULE_SETUP
-#line 94 "scripts/genksyms/lex.l"
+#line 90 "scripts/genksyms/lex.l"
 return yytext[0];
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 97 "scripts/genksyms/lex.l"
+#line 93 "scripts/genksyms/lex.l"
 ECHO;
 	YY_BREAK
-#line 1118 "scripts/genksyms/lex.c"
+#line 1109 "scripts/genksyms/lex.c"
 case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(V2_TOKENS):
 	yyterminate();
 
 	case YY_END_OF_BUFFER:
@@ -1429,7 +1419,7 @@ static int yy_get_next_buffer (void)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 76 )
+			if ( yy_current_state >= 73 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1462,11 +1452,11 @@ static int yy_get_next_buffer (void)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 76 )
+		if ( yy_current_state >= 73 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 75);
+	yy_is_jam = (yy_current_state == 72);
 
 	return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2252,7 +2242,7 @@ void yyfree (void * ptr )
 
 /* %ok-for-header */
 
-#line 97 "scripts/genksyms/lex.l"
+#line 93 "scripts/genksyms/lex.l"
 
 
 
@@ -2263,12 +2253,23 @@ void yyfree (void * ptr )
 
 /* Macros to append to our phrase collection list.  */
 
+/*
+ * We mark any token, that that equals to a known enumerator, as
+ * SYM_ENUM_CONST. The parser will change this for struct and union tags later,
+ * the only problem is struct and union members:
+ *    enum e { a, b }; struct s { int a, b; }
+ * but in this case, the only effect will be, that the ABI checksums become
+ * more volatile, which is acceptable. Also, such collisions are quite rare,
+ * so far it was only observed in include/linux/telephony.h.
+ */
 #define _APP(T,L)	do {						   \
 			  cur_node = next_node;				   \
 			  next_node = xmalloc(sizeof(*next_node));	   \
 			  next_node->next = cur_node;			   \
 			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
-			  cur_node->tag = SYM_NORMAL;			   \
+			  cur_node->tag =				   \
+			    find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\
+			    SYM_ENUM_CONST : SYM_NORMAL ;		   \
 			} while (0)
 
 #define APP		_APP(yytext, yyleng)
@@ -2294,7 +2295,6 @@ yylex(void)
 
   if (lexstate == ST_NOTSTARTED)
     {
-      BEGIN(V2_TOKENS);
       next_node = xmalloc(sizeof(*next_node));
       next_node->next = NULL;
       lexstate = ST_NORMAL;
@@ -2347,8 +2347,8 @@ repeat:
 
 		  case STRUCT_KEYW:
 		  case UNION_KEYW:
-		    dont_want_brace_phrase = 3;
 		  case ENUM_KEYW:
+		    dont_want_brace_phrase = 3;
 		    suppress_type_lookup = 2;
 		    goto fini;
 
@@ -2358,8 +2358,7 @@ repeat:
 	      }
 	    if (!suppress_type_lookup)
 	      {
-		struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF);
-		if (sym && sym->type == SYM_TYPEDEF)
+		if (find_symbol(yytext, SYM_TYPEDEF, 1))
 		  token = TYPE;
 	      }
 	  }
@@ -2478,7 +2477,20 @@ repeat:
 	  ++count;
 	  APP;
 	  goto repeat;
-	case ')': case ']': case '}':
+	case '}':
+	  /* is this the last line of an enum declaration? */
+	  if (count == 0)
+	    {
+	      /* Put back the token we just read so's we can find it again
+		 after registering the expression.  */
+	      unput(token);
+
+	      lexstate = ST_NORMAL;
+	      token = EXPRESSION_PHRASE;
+	      break;
+	    }
+	  /* FALLTHRU */
+	case ')': case ']':
 	  --count;
 	  APP;
 	  goto repeat;
@@ -2567,143 +2579,4 @@ fini:
 
   return token;
 }
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     ASM_KEYW = 258,
-     ATTRIBUTE_KEYW = 259,
-     AUTO_KEYW = 260,
-     BOOL_KEYW = 261,
-     CHAR_KEYW = 262,
-     CONST_KEYW = 263,
-     DOUBLE_KEYW = 264,
-     ENUM_KEYW = 265,
-     EXTERN_KEYW = 266,
-     EXTENSION_KEYW = 267,
-     FLOAT_KEYW = 268,
-     INLINE_KEYW = 269,
-     INT_KEYW = 270,
-     LONG_KEYW = 271,
-     REGISTER_KEYW = 272,
-     RESTRICT_KEYW = 273,
-     SHORT_KEYW = 274,
-     SIGNED_KEYW = 275,
-     STATIC_KEYW = 276,
-     STRUCT_KEYW = 277,
-     TYPEDEF_KEYW = 278,
-     UNION_KEYW = 279,
-     UNSIGNED_KEYW = 280,
-     VOID_KEYW = 281,
-     VOLATILE_KEYW = 282,
-     TYPEOF_KEYW = 283,
-     EXPORT_SYMBOL_KEYW = 284,
-     ASM_PHRASE = 285,
-     ATTRIBUTE_PHRASE = 286,
-     BRACE_PHRASE = 287,
-     BRACKET_PHRASE = 288,
-     EXPRESSION_PHRASE = 289,
-     CHAR = 290,
-     DOTS = 291,
-     IDENT = 292,
-     INT = 293,
-     REAL = 294,
-     STRING = 295,
-     TYPE = 296,
-     OTHER = 297,
-     FILENAME = 298
-   };
-#endif
-/* Tokens.  */
-#define ASM_KEYW 258
-#define ATTRIBUTE_KEYW 259
-#define AUTO_KEYW 260
-#define BOOL_KEYW 261
-#define CHAR_KEYW 262
-#define CONST_KEYW 263
-#define DOUBLE_KEYW 264
-#define ENUM_KEYW 265
-#define EXTERN_KEYW 266
-#define EXTENSION_KEYW 267
-#define FLOAT_KEYW 268
-#define INLINE_KEYW 269
-#define INT_KEYW 270
-#define LONG_KEYW 271
-#define REGISTER_KEYW 272
-#define RESTRICT_KEYW 273
-#define SHORT_KEYW 274
-#define SIGNED_KEYW 275
-#define STATIC_KEYW 276
-#define STRUCT_KEYW 277
-#define TYPEDEF_KEYW 278
-#define UNION_KEYW 279
-#define UNSIGNED_KEYW 280
-#define VOID_KEYW 281
-#define VOLATILE_KEYW 282
-#define TYPEOF_KEYW 283
-#define EXPORT_SYMBOL_KEYW 284
-#define ASM_PHRASE 285
-#define ATTRIBUTE_PHRASE 286
-#define BRACE_PHRASE 287
-#define BRACKET_PHRASE 288
-#define EXPRESSION_PHRASE 289
-#define CHAR 290
-#define DOTS 291
-#define IDENT 292
-#define INT 293
-#define REAL 294
-#define STRING 295
-#define TYPE 296
-#define OTHER 297
-#define FILENAME 298
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
 

+ 31 - 13
scripts/genksyms/lex.l

@@ -55,10 +55,6 @@ CHAR			L?\'([^\\\']*\\.)*[^\\\']*\'
 
 MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
 
-/* Version 2 checksumming does proper tokenization; version 1 wasn't
-   quite so pedantic.  */
-%s V2_TOKENS
-
 /* We don't do multiple input files.  */
 %option noyywrap
 
@@ -84,9 +80,9 @@ MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
     recognized as tokens.  We don't actually use them since we don't
     parse expressions, but we do want whitespace to be arranged
     around them properly.  */
-<V2_TOKENS>{MC_TOKEN}			return OTHER;
-<V2_TOKENS>{INT}			return INT;
-<V2_TOKENS>{REAL}			return REAL;
+{MC_TOKEN}				return OTHER;
+{INT}					return INT;
+{REAL}					return REAL;
 
 "..."					return DOTS;
 
@@ -103,12 +99,23 @@ MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
 
 /* Macros to append to our phrase collection list.  */
 
+/*
+ * We mark any token, that that equals to a known enumerator, as
+ * SYM_ENUM_CONST. The parser will change this for struct and union tags later,
+ * the only problem is struct and union members:
+ *    enum e { a, b }; struct s { int a, b; }
+ * but in this case, the only effect will be, that the ABI checksums become
+ * more volatile, which is acceptable. Also, such collisions are quite rare,
+ * so far it was only observed in include/linux/telephony.h.
+ */
 #define _APP(T,L)	do {						   \
 			  cur_node = next_node;				   \
 			  next_node = xmalloc(sizeof(*next_node));	   \
 			  next_node->next = cur_node;			   \
 			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
-			  cur_node->tag = SYM_NORMAL;			   \
+			  cur_node->tag =				   \
+			    find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\
+			    SYM_ENUM_CONST : SYM_NORMAL ;		   \
 			} while (0)
 
 #define APP		_APP(yytext, yyleng)
@@ -134,7 +141,6 @@ yylex(void)
 
   if (lexstate == ST_NOTSTARTED)
     {
-      BEGIN(V2_TOKENS);
       next_node = xmalloc(sizeof(*next_node));
       next_node->next = NULL;
       lexstate = ST_NORMAL;
@@ -187,8 +193,8 @@ repeat:
 
 		  case STRUCT_KEYW:
 		  case UNION_KEYW:
-		    dont_want_brace_phrase = 3;
 		  case ENUM_KEYW:
+		    dont_want_brace_phrase = 3;
 		    suppress_type_lookup = 2;
 		    goto fini;
 
@@ -198,8 +204,7 @@ repeat:
 	      }
 	    if (!suppress_type_lookup)
 	      {
-		struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF);
-		if (sym && sym->type == SYM_TYPEDEF)
+		if (find_symbol(yytext, SYM_TYPEDEF, 1))
 		  token = TYPE;
 	      }
 	  }
@@ -318,7 +323,20 @@ repeat:
 	  ++count;
 	  APP;
 	  goto repeat;
-	case ')': case ']': case '}':
+	case '}':
+	  /* is this the last line of an enum declaration? */
+	  if (count == 0)
+	    {
+	      /* Put back the token we just read so's we can find it again
+		 after registering the expression.  */
+	      unput(token);
+
+	      lexstate = ST_NORMAL;
+	      token = EXPRESSION_PHRASE;
+	      break;
+	    }
+	  /* FALLTHRU */
+	case ')': case ']':
 	  --count;
 	  APP;
 	  goto repeat;

文件差异内容过多而无法显示
+ 330 - 349
scripts/genksyms/parse.c_shipped


+ 15 - 57
scripts/genksyms/parse.h_shipped

@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1.  */
 
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton interface for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
+   
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
+   
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -29,10 +28,11 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-
+   
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
@@ -82,58 +82,16 @@
      FILENAME = 298
    };
 #endif
-/* Tokens.  */
-#define ASM_KEYW 258
-#define ATTRIBUTE_KEYW 259
-#define AUTO_KEYW 260
-#define BOOL_KEYW 261
-#define CHAR_KEYW 262
-#define CONST_KEYW 263
-#define DOUBLE_KEYW 264
-#define ENUM_KEYW 265
-#define EXTERN_KEYW 266
-#define EXTENSION_KEYW 267
-#define FLOAT_KEYW 268
-#define INLINE_KEYW 269
-#define INT_KEYW 270
-#define LONG_KEYW 271
-#define REGISTER_KEYW 272
-#define RESTRICT_KEYW 273
-#define SHORT_KEYW 274
-#define SIGNED_KEYW 275
-#define STATIC_KEYW 276
-#define STRUCT_KEYW 277
-#define TYPEDEF_KEYW 278
-#define UNION_KEYW 279
-#define UNSIGNED_KEYW 280
-#define VOID_KEYW 281
-#define VOLATILE_KEYW 282
-#define TYPEOF_KEYW 283
-#define EXPORT_SYMBOL_KEYW 284
-#define ASM_PHRASE 285
-#define ATTRIBUTE_PHRASE 286
-#define BRACE_PHRASE 287
-#define BRACKET_PHRASE 288
-#define EXPRESSION_PHRASE 289
-#define CHAR 290
-#define DOTS 291
-#define IDENT 292
-#define INT 293
-#define REAL 294
-#define STRING 295
-#define TYPE 296
-#define OTHER 297
-#define FILENAME 298
-
 
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 extern YYSTYPE yylval;
 
+

+ 30 - 4
scripts/genksyms/parse.y

@@ -25,6 +25,7 @@
 
 #include <assert.h>
 #include <stdlib.h>
+#include <string.h>
 #include "genksyms.h"
 
 static int is_typedef;
@@ -227,16 +228,19 @@ type_specifier:
 		  add_symbol(i->string, SYM_UNION, s, is_extern);
 		  $$ = $3;
 		}
-	| ENUM_KEYW IDENT BRACE_PHRASE
+	| ENUM_KEYW IDENT enum_body
 		{ struct string_list *s = *$3, *i = *$2, *r;
 		  r = copy_node(i); r->tag = SYM_ENUM;
 		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL;
 		  add_symbol(i->string, SYM_ENUM, s, is_extern);
 		  $$ = $3;
 		}
-
-	/* Anonymous s/u/e definitions.  Nothing needs doing.  */
-	| ENUM_KEYW BRACE_PHRASE			{ $$ = $2; }
+	/*
+	 * Anonymous enum definition. Tell add_symbol() to restart its counter.
+	 */
+	| ENUM_KEYW enum_body
+		{ add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; }
+	/* Anonymous s/u definitions.  Nothing needs doing.  */
 	| STRUCT_KEYW class_body			{ $$ = $2; }
 	| UNION_KEYW class_body				{ $$ = $2; }
 	;
@@ -449,6 +453,28 @@ attribute_opt:
 	| attribute_opt ATTRIBUTE_PHRASE
 	;
 
+enum_body:
+	'{' enumerator_list '}'				{ $$ = $3; }
+	| '{' enumerator_list ',' '}'			{ $$ = $4; }
+	 ;
+
+enumerator_list:
+	enumerator
+	| enumerator_list ',' enumerator
+
+enumerator:
+	IDENT
+		{
+			const char *name = strdup((*$1)->string);
+			add_symbol(name, SYM_ENUM_CONST, NULL, 0);
+		}
+	| IDENT '=' EXPRESSION_PHRASE
+		{
+			const char *name = strdup((*$1)->string);
+			struct string_list *expr = copy_list_range(*$3, *$2);
+			add_symbol(name, SYM_ENUM_CONST, expr, 0);
+		}
+
 asm_definition:
 	ASM_PHRASE ';'					{ $$ = $2; }
 	;

+ 15 - 8
scripts/mod/modpost.c

@@ -1248,6 +1248,19 @@ static int is_function(Elf_Sym *sym)
 		return -1;
 }
 
+static void print_section_list(const char * const list[20])
+{
+	const char *const *s = list;
+
+	while (*s) {
+		fprintf(stderr, "%s", *s);
+		s++;
+		if (*s)
+			fprintf(stderr, ", ");
+	}
+	fprintf(stderr, "\n");
+}
+
 /*
  * Print a warning about a section mismatch.
  * Try to find symbols near it so user can find it.
@@ -1304,7 +1317,6 @@ static void report_sec_mismatch(const char *modname,
 		break;
 	case DATA_TO_ANY_INIT: {
 		prl_to = sec2annotation(tosec);
-		const char *const *s = mismatch->symbol_white_list;
 		fprintf(stderr,
 		"The variable %s references\n"
 		"the %s %s%s%s\n"
@@ -1312,9 +1324,7 @@ static void report_sec_mismatch(const char *modname,
 		"variable with __init* or __refdata (see linux/init.h) "
 		"or name the variable:\n",
 		fromsym, to, prl_to, tosym, to_p);
-		while (*s)
-			fprintf(stderr, "%s, ", *s++);
-		fprintf(stderr, "\n");
+		print_section_list(mismatch->symbol_white_list);
 		free(prl_to);
 		break;
 	}
@@ -1329,7 +1339,6 @@ static void report_sec_mismatch(const char *modname,
 		break;
 	case DATA_TO_ANY_EXIT: {
 		prl_to = sec2annotation(tosec);
-		const char *const *s = mismatch->symbol_white_list;
 		fprintf(stderr,
 		"The variable %s references\n"
 		"the %s %s%s%s\n"
@@ -1337,9 +1346,7 @@ static void report_sec_mismatch(const char *modname,
 		"variable with __exit* (see linux/init.h) or "
 		"name the variable:\n",
 		fromsym, to, prl_to, tosym, to_p);
-		while (*s)
-			fprintf(stderr, "%s, ", *s++);
-		fprintf(stderr, "\n");
+		print_section_list(mismatch->symbol_white_list);
 		free(prl_to);
 		break;
 	}

+ 184 - 63
scripts/unifdef.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>
+ * Copyright (c) 2002 - 2011 Tony Finch <dot@dotat.at>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -24,23 +24,14 @@
  */
 
 /*
+ * unifdef - remove ifdef'ed lines
+ *
  * This code was derived from software contributed to Berkeley by Dave Yost.
  * It was rewritten to support ANSI C by Tony Finch. The original version
  * of unifdef carried the 4-clause BSD copyright licence. None of its code
  * remains in this version (though some of the names remain) so it now
  * carries a more liberal licence.
  *
- * The latest version is available from http://dotat.at/prog/unifdef
- */
-
-static const char * const copyright[] = {
-    "@(#) Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>\n",
-    "$dotat: unifdef/unifdef.c,v 1.190 2009/11/27 17:21:26 fanf2 Exp $",
-};
-
-/*
- * unifdef - remove ifdef'ed lines
- *
  *  Wishlist:
  *      provide an option which will append the name of the
  *        appropriate symbol after #else's and #endif's
@@ -48,12 +39,16 @@ static const char * const copyright[] = {
  *        #else's and #endif's to see that they match their
  *        corresponding #ifdef or #ifndef
  *
- *   The first two items above require better buffer handling, which would
- *     also make it possible to handle all "dodgy" directives correctly.
+ *   These require better buffer handling, which would also make
+ *   it possible to handle all "dodgy" directives correctly.
  */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -61,6 +56,12 @@ static const char * const copyright[] = {
 #include <string.h>
 #include <unistd.h>
 
+const char copyright[] =
+    "@(#) $Version: unifdef-2.5 $\n"
+    "@(#) $Author: Tony Finch (dot@dotat.at) $\n"
+    "@(#) $URL: http://dotat.at/prog/unifdef $\n"
+;
+
 /* types of input lines: */
 typedef enum {
 	LT_TRUEI,		/* a true #if with ignore flag */
@@ -152,6 +153,11 @@ static char const * const linestate_name[] = {
  */
 #define	EDITSLOP        10
 
+/*
+ * For temporary filenames
+ */
+#define TEMPLATE        "unifdef.XXXXXX"
+
 /*
  * Globals.
  */
@@ -165,6 +171,7 @@ static bool             strictlogic;		/* -K: keep ambiguous #ifs */
 static bool             killconsts;		/* -k: eval constant #ifs */
 static bool             lnnum;			/* -n: add #line directives */
 static bool             symlist;		/* -s: output symbol list */
+static bool             symdepth;		/* -S: output symbol depth */
 static bool             text;			/* -t: this is a text file */
 
 static const char      *symname[MAXSYMS];	/* symbol name */
@@ -175,10 +182,18 @@ static int              nsyms;			/* number of symbols */
 static FILE            *input;			/* input file pointer */
 static const char      *filename;		/* input file name */
 static int              linenum;		/* current line number */
+static FILE            *output;			/* output file pointer */
+static const char      *ofilename;		/* output file name */
+static bool             overwriting;		/* output overwrites input */
+static char             tempname[FILENAME_MAX];	/* used when overwriting */
 
 static char             tline[MAXLINE+EDITSLOP];/* input buffer plus space */
 static char            *keyword;		/* used for editing #elif's */
 
+static const char      *newline;		/* input file format */
+static const char       newline_unix[] = "\n";
+static const char       newline_crlf[] = "\r\n";
+
 static Comment_state    incomment;		/* comment parser state */
 static Line_state       linestate;		/* #if line parser state */
 static Ifstate          ifstate[MAXDEPTH];	/* #if processor state */
@@ -189,10 +204,13 @@ static int              delcount;		/* count of deleted lines */
 static unsigned         blankcount;		/* count of blank lines */
 static unsigned         blankmax;		/* maximum recent blankcount */
 static bool             constexpr;		/* constant #if expression */
+static bool             zerosyms = true;	/* to format symdepth output */
+static bool             firstsym;		/* ditto */
 
 static int              exitstat;		/* program exit status */
 
 static void             addsym(bool, bool, char *);
+static void             closeout(void);
 static void             debug(const char *, ...);
 static void             done(void);
 static void             error(const char *);
@@ -212,6 +230,7 @@ static void             state(Ifstate);
 static int              strlcmp(const char *, const char *, size_t);
 static void             unnest(void);
 static void             usage(void);
+static void             version(void);
 
 #define endsym(c) (!isalnum((unsigned char)c) && c != '_')
 
@@ -223,7 +242,7 @@ main(int argc, char *argv[])
 {
 	int opt;
 
-	while ((opt = getopt(argc, argv, "i:D:U:I:BbcdeKklnst")) != -1)
+	while ((opt = getopt(argc, argv, "i:D:U:I:o:bBcdeKklnsStV")) != -1)
 		switch (opt) {
 		case 'i': /* treat stuff controlled by these symbols as text */
 			/*
@@ -245,16 +264,15 @@ main(int argc, char *argv[])
 		case 'U': /* undef a symbol */
 			addsym(false, false, optarg);
 			break;
-		case 'I':
-			/* no-op for compatibility with cpp */
-			break;
-		case 'B': /* compress blank lines around removed section */
-			compblank = true;
+		case 'I': /* no-op for compatibility with cpp */
 			break;
 		case 'b': /* blank deleted lines instead of omitting them */
 		case 'l': /* backwards compatibility */
 			lnblank = true;
 			break;
+		case 'B': /* compress blank lines around removed section */
+			compblank = true;
+			break;
 		case 'c': /* treat -D as -U and vice versa */
 			complement = true;
 			break;
@@ -273,12 +291,20 @@ main(int argc, char *argv[])
 		case 'n': /* add #line directive after deleted lines */
 			lnnum = true;
 			break;
+		case 'o': /* output to a file */
+			ofilename = optarg;
+			break;
 		case 's': /* only output list of symbols that control #ifs */
 			symlist = true;
 			break;
+		case 'S': /* list symbols with their nesting depth */
+			symlist = symdepth = true;
+			break;
 		case 't': /* don't parse C comments */
 			text = true;
 			break;
+		case 'V': /* print version */
+			version();
 		default:
 			usage();
 		}
@@ -290,21 +316,68 @@ main(int argc, char *argv[])
 		errx(2, "can only do one file");
 	} else if (argc == 1 && strcmp(*argv, "-") != 0) {
 		filename = *argv;
-		input = fopen(filename, "r");
+		input = fopen(filename, "rb");
 		if (input == NULL)
 			err(2, "can't open %s", filename);
 	} else {
 		filename = "[stdin]";
 		input = stdin;
 	}
+	if (ofilename == NULL) {
+		ofilename = "[stdout]";
+		output = stdout;
+	} else {
+		struct stat ist, ost;
+		if (stat(ofilename, &ost) == 0 &&
+		    fstat(fileno(input), &ist) == 0)
+			overwriting = (ist.st_dev == ost.st_dev
+				    && ist.st_ino == ost.st_ino);
+		if (overwriting) {
+			const char *dirsep;
+			int ofd;
+
+			dirsep = strrchr(ofilename, '/');
+			if (dirsep != NULL)
+				snprintf(tempname, sizeof(tempname),
+				    "%.*s/" TEMPLATE,
+				    (int)(dirsep - ofilename), ofilename);
+			else
+				snprintf(tempname, sizeof(tempname),
+				    TEMPLATE);
+			ofd = mkstemp(tempname);
+			if (ofd != -1)
+				output = fdopen(ofd, "wb+");
+			if (output == NULL)
+				err(2, "can't create temporary file");
+			fchmod(ofd, ist.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO));
+		} else {
+			output = fopen(ofilename, "wb");
+			if (output == NULL)
+				err(2, "can't open %s", ofilename);
+		}
+	}
 	process();
 	abort(); /* bug */
 }
 
+static void
+version(void)
+{
+	const char *c = copyright;
+	for (;;) {
+		while (*++c != '$')
+			if (*c == '\0')
+				exit(0);
+		while (*++c != '$')
+			putc(*c, stderr);
+		putc('\n', stderr);
+	}
+}
+
 static void
 usage(void)
 {
-	fprintf(stderr, "usage: unifdef [-BbcdeKknst] [-Ipath]"
+	fprintf(stderr, "usage: unifdef [-bBcdeKknsStV] [-Ipath]"
 	    " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n");
 	exit(2);
 }
@@ -322,7 +395,8 @@ usage(void)
  * When we have processed a group that starts off with a known-false
  * #if/#elif sequence (which has therefore been deleted) followed by a
  * #elif that we don't understand and therefore must keep, we edit the
- * latter into a #if to keep the nesting correct.
+ * latter into a #if to keep the nesting correct. We use strncpy() to
+ * overwrite the 4 byte token "elif" with "if  " without a '\0' byte.
  *
  * When we find a true #elif in a group, the following block will
  * always be kept and the rest of the sequence after the next #elif or
@@ -375,11 +449,11 @@ static void Oelif (void) { if (!iocccok) Eioccc(); Pelif(); }
 static void Idrop (void) { Fdrop();  ignoreon(); }
 static void Itrue (void) { Ftrue();  ignoreon(); }
 static void Ifalse(void) { Ffalse(); ignoreon(); }
-/* edit this line */
+/* modify this line */
 static void Mpass (void) { strncpy(keyword, "if  ", 4); Pelif(); }
-static void Mtrue (void) { keywordedit("else\n");  state(IS_TRUE_MIDDLE); }
-static void Melif (void) { keywordedit("endif\n"); state(IS_FALSE_TRAILER); }
-static void Melse (void) { keywordedit("endif\n"); state(IS_FALSE_ELSE); }
+static void Mtrue (void) { keywordedit("else");  state(IS_TRUE_MIDDLE); }
+static void Melif (void) { keywordedit("endif"); state(IS_FALSE_TRAILER); }
+static void Melse (void) { keywordedit("endif"); state(IS_FALSE_ELSE); }
 
 static state_fn * const trans_table[IS_COUNT][LT_COUNT] = {
 /* IS_OUTSIDE */
@@ -431,13 +505,6 @@ static state_fn * const trans_table[IS_COUNT][LT_COUNT] = {
  * State machine utility functions
  */
 static void
-done(void)
-{
-	if (incomment)
-		error("EOF in comment");
-	exit(exitstat);
-}
-static void
 ignoreoff(void)
 {
 	if (depth == 0)
@@ -452,14 +519,8 @@ ignoreon(void)
 static void
 keywordedit(const char *replacement)
 {
-	size_t size = tline + sizeof(tline) - keyword;
-	char *dst = keyword;
-	const char *src = replacement;
-	if (size != 0) {
-		while ((--size != 0) && (*src != '\0'))
-			*dst++ = *src++;
-		*dst = '\0';
-	}
+	snprintf(keyword, tline + sizeof(tline) - keyword,
+	    "%s%s", replacement, newline);
 	print();
 }
 static void
@@ -494,24 +555,26 @@ flushline(bool keep)
 	if (symlist)
 		return;
 	if (keep ^ complement) {
-		bool blankline = tline[strspn(tline, " \t\n")] == '\0';
+		bool blankline = tline[strspn(tline, " \t\r\n")] == '\0';
 		if (blankline && compblank && blankcount != blankmax) {
 			delcount += 1;
 			blankcount += 1;
 		} else {
 			if (lnnum && delcount > 0)
-				printf("#line %d\n", linenum);
-			fputs(tline, stdout);
+				printf("#line %d%s", linenum, newline);
+			fputs(tline, output);
 			delcount = 0;
 			blankmax = blankcount = blankline ? blankcount + 1 : 0;
 		}
 	} else {
 		if (lnblank)
-			putc('\n', stdout);
+			fputs(newline, output);
 		exitstat = 1;
 		delcount += 1;
 		blankcount = 0;
 	}
+	if (debugging)
+		fflush(output);
 }
 
 /*
@@ -520,21 +583,54 @@ flushline(bool keep)
 static void
 process(void)
 {
-	Linetype lineval;
-
 	/* When compressing blank lines, act as if the file
 	   is preceded by a large number of blank lines. */
 	blankmax = blankcount = 1000;
 	for (;;) {
-		linenum++;
-		lineval = parseline();
+		Linetype lineval = parseline();
 		trans_table[ifstate[depth]][lineval]();
-		debug("process %s -> %s depth %d",
-		    linetype_name[lineval],
+		debug("process line %d %s -> %s depth %d",
+		    linenum, linetype_name[lineval],
 		    ifstate_name[ifstate[depth]], depth);
 	}
 }
 
+/*
+ * Flush the output and handle errors.
+ */
+static void
+closeout(void)
+{
+	if (symdepth && !zerosyms)
+		printf("\n");
+	if (fclose(output) == EOF) {
+		warn("couldn't write to %s", ofilename);
+		if (overwriting) {
+			unlink(tempname);
+			errx(2, "%s unchanged", filename);
+		} else {
+			exit(2);
+		}
+	}
+}
+
+/*
+ * Clean up and exit.
+ */
+static void
+done(void)
+{
+	if (incomment)
+		error("EOF in comment");
+	closeout();
+	if (overwriting && rename(tempname, ofilename) == -1) {
+		warn("couldn't rename temporary file");
+		unlink(tempname);
+		errx(2, "%s unchanged", ofilename);
+	}
+	exit(exitstat);
+}
+
 /*
  * Parse a line and determine its type. We keep the preprocessor line
  * parser state between calls in the global variable linestate, with
@@ -549,14 +645,22 @@ parseline(void)
 	Linetype retval;
 	Comment_state wascomment;
 
+	linenum++;
 	if (fgets(tline, MAXLINE, input) == NULL)
 		return (LT_EOF);
+	if (newline == NULL) {
+		if (strrchr(tline, '\n') == strrchr(tline, '\r') + 1)
+			newline = newline_crlf;
+		else
+			newline = newline_unix;
+	}
 	retval = LT_PLAIN;
 	wascomment = incomment;
 	cp = skipcomment(tline);
 	if (linestate == LS_START) {
 		if (*cp == '#') {
 			linestate = LS_HASH;
+			firstsym = true;
 			cp = skipcomment(cp + 1);
 		} else if (*cp != '\0')
 			linestate = LS_DIRTY;
@@ -566,7 +670,8 @@ parseline(void)
 		cp = skipsym(cp);
 		kwlen = cp - keyword;
 		/* no way can we deal with a continuation inside a keyword */
-		if (strncmp(cp, "\\\n", 2) == 0)
+		if (strncmp(cp, "\\\r\n", 3) == 0 ||
+		    strncmp(cp, "\\\n", 2) == 0)
 			Eioccc();
 		if (strlcmp("ifdef", keyword, kwlen) == 0 ||
 		    strlcmp("ifndef", keyword, kwlen) == 0) {
@@ -617,9 +722,8 @@ parseline(void)
 			size_t len = cp - tline;
 			if (fgets(tline + len, MAXLINE - len, input) == NULL) {
 				/* append the missing newline */
-				tline[len+0] = '\n';
-				tline[len+1] = '\0';
-				cp++;
+				strcpy(tline + len, newline);
+				cp += strlen(newline);
 				linestate = LS_START;
 			} else {
 				linestate = LS_DIRTY;
@@ -630,7 +734,7 @@ parseline(void)
 		while (*cp != '\0')
 			cp = skipcomment(cp + 1);
 	}
-	debug("parser %s comment %s line",
+	debug("parser line %d state %s comment %s line", linenum,
 	    comment_name[incomment], linestate_name[linestate]);
 	return (retval);
 }
@@ -875,11 +979,16 @@ skipcomment(const char *cp)
 	}
 	while (*cp != '\0')
 		/* don't reset to LS_START after a line continuation */
-		if (strncmp(cp, "\\\n", 2) == 0)
+		if (strncmp(cp, "\\\r\n", 3) == 0)
+			cp += 3;
+		else if (strncmp(cp, "\\\n", 2) == 0)
 			cp += 2;
 		else switch (incomment) {
 		case NO_COMMENT:
-			if (strncmp(cp, "/\\\n", 3) == 0) {
+			if (strncmp(cp, "/\\\r\n", 4) == 0) {
+				incomment = STARTING_COMMENT;
+				cp += 4;
+			} else if (strncmp(cp, "/\\\n", 3) == 0) {
 				incomment = STARTING_COMMENT;
 				cp += 3;
 			} else if (strncmp(cp, "/*", 2) == 0) {
@@ -899,7 +1008,7 @@ skipcomment(const char *cp)
 			} else if (strncmp(cp, "\n", 1) == 0) {
 				linestate = LS_START;
 				cp += 1;
-			} else if (strchr(" \t", *cp) != NULL) {
+			} else if (strchr(" \r\t", *cp) != NULL) {
 				cp += 1;
 			} else
 				return (cp);
@@ -931,7 +1040,10 @@ skipcomment(const char *cp)
 				cp += 1;
 			continue;
 		case C_COMMENT:
-			if (strncmp(cp, "*\\\n", 3) == 0) {
+			if (strncmp(cp, "*\\\r\n", 4) == 0) {
+				incomment = FINISHING_COMMENT;
+				cp += 4;
+			} else if (strncmp(cp, "*\\\n", 3) == 0) {
 				incomment = FINISHING_COMMENT;
 				cp += 3;
 			} else if (strncmp(cp, "*/", 2) == 0) {
@@ -1015,7 +1127,13 @@ findsym(const char *str)
 	if (cp == str)
 		return (-1);
 	if (symlist) {
-		printf("%.*s\n", (int)(cp-str), str);
+		if (symdepth && firstsym)
+			printf("%s%3d", zerosyms ? "" : "\n", depth);
+		firstsym = zerosyms = false;
+		printf("%s%.*s%s",
+		    symdepth ? " " : "",
+		    (int)(cp-str), str,
+		    symdepth ? "" : "\n");
 		/* we don't care about the value of the symbol */
 		return (0);
 	}
@@ -1052,7 +1170,7 @@ addsym(bool ignorethis, bool definethis, char *sym)
 			value[symind] = val+1;
 			*val = '\0';
 		} else if (*val == '\0')
-			value[symind] = "";
+			value[symind] = "1";
 		else
 			usage();
 	} else {
@@ -1060,6 +1178,8 @@ addsym(bool ignorethis, bool definethis, char *sym)
 			usage();
 		value[symind] = NULL;
 	}
+	debug("addsym %s=%s", symname[symind],
+	    value[symind] ? value[symind] : "undef");
 }
 
 /*
@@ -1100,5 +1220,6 @@ error(const char *msg)
 	else
 		warnx("%s: %d: %s (#if line %d depth %d)",
 		    filename, linenum, msg, stifline[depth], depth);
+	closeout();
 	errx(2, "output may be truncated");
 }

部分文件因为文件数量过多而无法显示