Merge branch 'upstream-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[powerpc.git] / scripts / genksyms / genksyms.c
index b798e28..b038182 100644 (file)
 #define HASH_BUCKETS  4096
 
 static struct symbol *symtab[HASH_BUCKETS];
-FILE *debugfile;
+static FILE *debugfile;
 
 int cur_line = 1;
-char *cur_filename, *output_directory;
+char *cur_filename;
 
-int flag_debug, flag_dump_defs, flag_warnings;
-const char *arch = "";
-const char *mod_prefix = "";
+static int flag_debug, flag_dump_defs, flag_dump_types, flag_warnings;
+static const char *arch = "";
+static const char *mod_prefix = "";
 
 static int errors;
 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 int equal_list(struct string_list *a, struct string_list *b);
+static void print_list(FILE * f, struct string_list *list);
+
 /*----------------------------------------------------------------------*/
 
 static const unsigned int crctab32[] = {
@@ -112,27 +116,26 @@ static const unsigned int crctab32[] = {
        0x2d02ef8dU
 };
 
-static inline unsigned long
-partial_crc32_one(unsigned char c, unsigned long crc)
+static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
 {
        return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
 }
 
-static inline unsigned long partial_crc32(const char *s, unsigned long crc)
+static unsigned long partial_crc32(const char *s, unsigned long crc)
 {
        while (*s)
                crc = partial_crc32_one(*s++, crc);
        return crc;
 }
 
-static inline unsigned long crc32(const char *s)
+static unsigned long crc32(const char *s)
 {
        return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
 }
 
 /*----------------------------------------------------------------------*/
 
-static inline enum symbol_type map_to_ns(enum symbol_type t)
+static enum symbol_type map_to_ns(enum symbol_type t)
 {
        if (t == SYM_TYPEDEF)
                t = SYM_NORMAL;
@@ -147,8 +150,8 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns)
        struct symbol *sym;
 
        for (sym = symtab[h]; sym; sym = sym->hash_next)
-               if (map_to_ns(sym->type) == map_to_ns(ns)
-                   && strcmp(name, sym->name) == 0)
+               if (map_to_ns(sym->type) == map_to_ns(ns) &&
+                   strcmp(name, sym->name) == 0)
                        break;
 
        return sym;
@@ -160,19 +163,21 @@ struct symbol *add_symbol(const char *name, enum symbol_type type,
        unsigned long h = crc32(name) % HASH_BUCKETS;
        struct symbol *sym;
 
-       for (sym = symtab[h]; sym; sym = sym->hash_next)
+       for (sym = symtab[h]; sym; sym = sym->hash_next) {
                if (map_to_ns(sym->type) == map_to_ns(type)
                    && strcmp(name, sym->name) == 0) {
                        if (!equal_list(sym->defn, defn))
                                error_with_pos("redefinition of %s", name);
                        return sym;
                }
+       }
 
        sym = xmalloc(sizeof(*sym));
        sym->name = name;
        sym->type = type;
        sym->defn = defn;
        sym->expansion_trail = NULL;
+       sym->visited = NULL;
        sym->is_extern = is_extern;
 
        sym->hash_next = symtab[h];
@@ -193,7 +198,7 @@ struct symbol *add_symbol(const char *name, enum symbol_type type,
 
 /*----------------------------------------------------------------------*/
 
-inline void free_node(struct string_list *node)
+void free_node(struct string_list *node)
 {
        free(node->string);
        free(node);
@@ -208,7 +213,7 @@ void free_list(struct string_list *s, struct string_list *e)
        }
 }
 
-inline struct string_list *copy_node(struct string_list *node)
+struct string_list *copy_node(struct string_list *node)
 {
        struct string_list *newnode;
 
@@ -219,22 +224,7 @@ inline struct string_list *copy_node(struct string_list *node)
        return newnode;
 }
 
-struct string_list *copy_list(struct string_list *s, struct string_list *e)
-{
-       struct string_list *h, *p;
-
-       if (s == e)
-               return NULL;
-
-       p = h = copy_node(s);
-       while ((s = s->next) != e)
-               p = p->next = copy_node(s);
-       p->next = NULL;
-
-       return h;
-}
-
-int equal_list(struct string_list *a, struct string_list *b)
+static int equal_list(struct string_list *a, struct string_list *b)
 {
        while (a && b) {
                if (a->tag != b->tag || strcmp(a->string, b->string))
@@ -246,31 +236,16 @@ int equal_list(struct string_list *a, struct string_list *b)
        return !a && !b;
 }
 
-static inline void print_node(FILE * f, struct string_list *list)
+static void print_node(FILE * f, struct string_list *list)
 {
-       switch (list->tag) {
-       case SYM_STRUCT:
-               putc('s', f);
-               goto printit;
-       case SYM_UNION:
-               putc('u', f);
-               goto printit;
-       case SYM_ENUM:
-               putc('e', f);
-               goto printit;
-       case SYM_TYPEDEF:
-               putc('t', f);
-               goto printit;
-
-             printit:
+       if (list->tag != SYM_NORMAL) {
+               putc(symbol_type_name[list->tag][0], f);
                putc('#', f);
-       case SYM_NORMAL:
-               fputs(list->string, f);
-               break;
        }
+       fputs(list->string, f);
 }
 
-void print_list(FILE * f, struct string_list *list)
+static void print_list(FILE * f, struct string_list *list)
 {
        struct string_list **e, **b;
        struct string_list *tmp, **tmp2;
@@ -299,9 +274,9 @@ void print_list(FILE * f, struct string_list *list)
        }
 }
 
-static unsigned long
-expand_and_crc_list(struct string_list *list, unsigned long crc)
+static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
 {
+       struct string_list *list = sym->defn;
        struct string_list **e, **b;
        struct string_list *tmp, **tmp2;
        int elem = 1;
@@ -344,7 +319,7 @@ expand_and_crc_list(struct string_list *list, unsigned long crc)
                        } else {
                                subsym->expansion_trail = expansion_trail;
                                expansion_trail = subsym;
-                               crc = expand_and_crc_list(subsym->defn, crc);
+                               crc = expand_and_crc_sym(subsym, crc);
                        }
                        break;
 
@@ -386,21 +361,30 @@ expand_and_crc_list(struct string_list *list, unsigned long crc)
                                                cur->string);
                                }
 
-                               crc =
-                                   partial_crc32(symbol_type_name[cur->tag],
-                                                 crc);
+                               crc = partial_crc32(symbol_type_name[cur->tag],
+                                                   crc);
                                crc = partial_crc32_one(' ', crc);
                                crc = partial_crc32(cur->string, crc);
                                crc = partial_crc32_one(' ', crc);
                        } else {
                                subsym->expansion_trail = expansion_trail;
                                expansion_trail = subsym;
-                               crc = expand_and_crc_list(subsym->defn, crc);
+                               crc = expand_and_crc_sym(subsym, crc);
                        }
                        break;
                }
        }
 
+       {
+               static struct symbol **end = &visited_symbols;
+
+               if (!sym->visited) {
+                       *end = sym;
+                       end = &sym->visited;
+                       sym->visited = (struct symbol *)-1L;
+               }
+       }
+
        return crc;
 }
 
@@ -419,7 +403,7 @@ void export_symbol(const char *name)
 
                expansion_trail = (struct symbol *)-1L;
 
-               crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
+               crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
 
                sym = expansion_trail;
                while (sym != (struct symbol *)-1L) {
@@ -437,21 +421,6 @@ void export_symbol(const char *name)
 }
 
 /*----------------------------------------------------------------------*/
-
-void error(const char *fmt, ...)
-{
-       va_list args;
-
-       if (flag_warnings) {
-               va_start(args, fmt);
-               vfprintf(stderr, fmt, args);
-               va_end(args);
-               putc('\n', stderr);
-
-               errors++;
-       }
-}
-
 void error_with_pos(const char *fmt, ...)
 {
        va_list args;
@@ -469,7 +438,7 @@ void error_with_pos(const char *fmt, ...)
        }
 }
 
-void genksyms_usage(void)
+static void genksyms_usage(void)
 {
        fputs("Usage:\n" "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" "\n"
 #ifdef __GNU_LIBRARY__
@@ -492,6 +461,7 @@ void genksyms_usage(void)
 
 int main(int argc, char **argv)
 {
+       FILE *dumpfile = NULL;
        int o;
 
 #ifdef __GNU_LIBRARY__
@@ -501,15 +471,16 @@ int main(int argc, char **argv)
                {"warnings", 0, 0, 'w'},
                {"quiet", 0, 0, 'q'},
                {"dump", 0, 0, 'D'},
+               {"dump-types", 1, 0, 'T'},
                {"version", 0, 0, 'V'},
                {"help", 0, 0, 'h'},
                {0, 0, 0, 0}
        };
 
-       while ((o = getopt_long(argc, argv, "a:dwqVDk:p:",
+       while ((o = getopt_long(argc, argv, "a:dwqVDT:k:p:",
                                &long_opts[0], NULL)) != EOF)
 #else                          /* __GNU_LIBRARY__ */
-       while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF)
+       while ((o = getopt(argc, argv, "a:dwqVDT:k:p:")) != EOF)
 #endif                         /* __GNU_LIBRARY__ */
                switch (o) {
                case 'a':
@@ -530,6 +501,14 @@ int main(int argc, char **argv)
                case 'D':
                        flag_dump_defs = 1;
                        break;
+               case 'T':
+                       flag_dump_types = 1;
+                       dumpfile = fopen(optarg, "w");
+                       if (!dumpfile) {
+                               perror(optarg);
+                               return 1;
+                       }
+                       break;
                case 'h':
                        genksyms_usage();
                        return 0;
@@ -552,6 +531,24 @@ int main(int argc, char **argv)
 
        yyparse();
 
+       if (flag_dump_types && visited_symbols) {
+               while (visited_symbols != (struct symbol *)-1L) {
+                       struct symbol *sym = visited_symbols;
+
+                       if (sym->type != SYM_NORMAL) {
+                               putc(symbol_type_name[sym->type][0], dumpfile);
+                               putc('#', dumpfile);
+                       }
+                       fputs(sym->name, dumpfile);
+                       putc(' ', dumpfile);
+                       print_list(dumpfile, sym->defn);
+                       putc('\n', dumpfile);
+
+                       visited_symbols = sym->visited;
+                       sym->visited = NULL;
+               }
+       }
+
        if (flag_debug) {
                fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
                        nsyms, HASH_BUCKETS,