genksyms: Track changes to enum constants
[linux-2.6.git] / scripts / genksyms / genksyms.c
1 /* Generate kernel symbol version hashes.
2    Copyright 1996, 1997 Linux International.
3
4    New implementation contributed by Richard Henderson <rth@tamu.edu>
5    Based on original work by Bjorn Ekwall <bj0rn@blox.se>
6
7    This file was part of the Linux modutils 2.4.22: moved back into the
8    kernel sources by Rusty Russell/Kai Germaschewski.
9
10    This program is free software; you can redistribute it and/or modify it
11    under the terms of the GNU General Public License as published by the
12    Free Software Foundation; either version 2 of the License, or (at your
13    option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software Foundation,
22    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <assert.h>
29 #include <stdarg.h>
30 #ifdef __GNU_LIBRARY__
31 #include <getopt.h>
32 #endif                          /* __GNU_LIBRARY__ */
33
34 #include "genksyms.h"
35 /*----------------------------------------------------------------------*/
36
37 #define HASH_BUCKETS  4096
38
39 static struct symbol *symtab[HASH_BUCKETS];
40 static FILE *debugfile;
41
42 int cur_line = 1;
43 char *cur_filename;
44
45 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
46            flag_preserve, flag_warnings;
47 static const char *arch = "";
48 static const char *mod_prefix = "";
49
50 static int errors;
51 static int nsyms;
52
53 static struct symbol *expansion_trail;
54 static struct symbol *visited_symbols;
55
56 static const struct {
57         int n;
58         const char *name;
59 } symbol_types[] = {
60         [SYM_NORMAL]     = { 0, NULL},
61         [SYM_TYPEDEF]    = {'t', "typedef"},
62         [SYM_ENUM]       = {'e', "enum"},
63         [SYM_STRUCT]     = {'s', "struct"},
64         [SYM_UNION]      = {'u', "union"},
65         [SYM_ENUM_CONST] = {'E', "enum constant"},
66 };
67
68 static int equal_list(struct string_list *a, struct string_list *b);
69 static void print_list(FILE * f, struct string_list *list);
70 static struct string_list *concat_list(struct string_list *start, ...);
71 static struct string_list *mk_node(const char *string);
72 static void print_location(void);
73 static void print_type_name(enum symbol_type type, const char *name);
74
75 /*----------------------------------------------------------------------*/
76
77 static const unsigned int crctab32[] = {
78         0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
79         0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
80         0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
81         0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
82         0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
83         0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
84         0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
85         0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
86         0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
87         0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
88         0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
89         0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
90         0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
91         0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
92         0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
93         0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
94         0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
95         0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
96         0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
97         0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
98         0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
99         0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
100         0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
101         0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
102         0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
103         0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
104         0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
105         0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
106         0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
107         0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
108         0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
109         0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
110         0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
111         0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
112         0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
113         0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
114         0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
115         0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
116         0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
117         0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
118         0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
119         0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
120         0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
121         0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
122         0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
123         0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
124         0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
125         0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
126         0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
127         0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
128         0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
129         0x2d02ef8dU
130 };
131
132 static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
133 {
134         return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
135 }
136
137 static unsigned long partial_crc32(const char *s, unsigned long crc)
138 {
139         while (*s)
140                 crc = partial_crc32_one(*s++, crc);
141         return crc;
142 }
143
144 static unsigned long crc32(const char *s)
145 {
146         return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
147 }
148
149 /*----------------------------------------------------------------------*/
150
151 static enum symbol_type map_to_ns(enum symbol_type t)
152 {
153         switch (t) {
154         case SYM_ENUM_CONST:
155         case SYM_NORMAL:
156         case SYM_TYPEDEF:
157                 return SYM_NORMAL;
158         case SYM_ENUM:
159         case SYM_STRUCT:
160         case SYM_UNION:
161                 return SYM_STRUCT;
162         }
163         return t;
164 }
165
166 struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
167 {
168         unsigned long h = crc32(name) % HASH_BUCKETS;
169         struct symbol *sym;
170
171         for (sym = symtab[h]; sym; sym = sym->hash_next)
172                 if (map_to_ns(sym->type) == map_to_ns(ns) &&
173                     strcmp(name, sym->name) == 0 &&
174                     sym->is_declared)
175                         break;
176
177         if (exact && sym && sym->type != ns)
178                 return NULL;
179         return sym;
180 }
181
182 static int is_unknown_symbol(struct symbol *sym)
183 {
184         struct string_list *defn;
185
186         return ((sym->type == SYM_STRUCT ||
187                  sym->type == SYM_UNION ||
188                  sym->type == SYM_ENUM) &&
189                 (defn = sym->defn)  && defn->tag == SYM_NORMAL &&
190                         strcmp(defn->string, "}") == 0 &&
191                 (defn = defn->next) && defn->tag == SYM_NORMAL &&
192                         strcmp(defn->string, "UNKNOWN") == 0 &&
193                 (defn = defn->next) && defn->tag == SYM_NORMAL &&
194                         strcmp(defn->string, "{") == 0);
195 }
196
197 static struct symbol *__add_symbol(const char *name, enum symbol_type type,
198                             struct string_list *defn, int is_extern,
199                             int is_reference)
200 {
201         unsigned long h;
202         struct symbol *sym;
203         enum symbol_status status = STATUS_UNCHANGED;
204         /* The parser adds symbols in the order their declaration completes,
205          * so it is safe to store the value of the previous enum constant in
206          * a static variable.
207          */
208         static int enum_counter;
209         static struct string_list *last_enum_expr;
210
211         if (type == SYM_ENUM_CONST) {
212                 if (defn) {
213                         free_list(last_enum_expr, NULL);
214                         last_enum_expr = copy_list_range(defn, NULL);
215                         enum_counter = 1;
216                 } else {
217                         struct string_list *expr;
218                         char buf[20];
219
220                         snprintf(buf, sizeof(buf), "%d", enum_counter++);
221                         if (last_enum_expr) {
222                                 expr = copy_list_range(last_enum_expr, NULL);
223                                 defn = concat_list(mk_node("("),
224                                                    expr,
225                                                    mk_node(")"),
226                                                    mk_node("+"),
227                                                    mk_node(buf), NULL);
228                         } else {
229                                 defn = mk_node(buf);
230                         }
231                 }
232         } else if (type == SYM_ENUM) {
233                 free_list(last_enum_expr, NULL);
234                 last_enum_expr = NULL;
235                 enum_counter = 0;
236                 if (!name)
237                         /* Anonymous enum definition, nothing more to do */
238                         return NULL;
239         }
240
241         h = crc32(name) % HASH_BUCKETS;
242         for (sym = symtab[h]; sym; sym = sym->hash_next) {
243                 if (map_to_ns(sym->type) == map_to_ns(type) &&
244                     strcmp(name, sym->name) == 0) {
245                         if (is_reference)
246                                 /* fall through */ ;
247                         else if (sym->type == type &&
248                                  equal_list(sym->defn, defn)) {
249                                 if (!sym->is_declared && sym->is_override) {
250                                         print_location();
251                                         print_type_name(type, name);
252                                         fprintf(stderr, " modversion is "
253                                                 "unchanged\n");
254                                 }
255                                 sym->is_declared = 1;
256                                 return sym;
257                         } else if (!sym->is_declared) {
258                                 if (sym->is_override && flag_preserve) {
259                                         print_location();
260                                         fprintf(stderr, "ignoring ");
261                                         print_type_name(type, name);
262                                         fprintf(stderr, " modversion change\n");
263                                         sym->is_declared = 1;
264                                         return sym;
265                                 } else {
266                                         status = is_unknown_symbol(sym) ?
267                                                 STATUS_DEFINED : STATUS_MODIFIED;
268                                 }
269                         } else {
270                                 error_with_pos("redefinition of %s", name);
271                                 return sym;
272                         }
273                         break;
274                 }
275         }
276
277         if (sym) {
278                 struct symbol **psym;
279
280                 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
281                         if (*psym == sym) {
282                                 *psym = sym->hash_next;
283                                 break;
284                         }
285                 }
286                 --nsyms;
287         }
288
289         sym = xmalloc(sizeof(*sym));
290         sym->name = name;
291         sym->type = type;
292         sym->defn = defn;
293         sym->expansion_trail = NULL;
294         sym->visited = NULL;
295         sym->is_extern = is_extern;
296
297         sym->hash_next = symtab[h];
298         symtab[h] = sym;
299
300         sym->is_declared = !is_reference;
301         sym->status = status;
302         sym->is_override = 0;
303
304         if (flag_debug) {
305                 if (symbol_types[type].name)
306                         fprintf(debugfile, "Defn for %s %s == <",
307                                 symbol_types[type].name, name);
308                 else
309                         fprintf(debugfile, "Defn for type%d %s == <",
310                                 type, name);
311                 if (is_extern)
312                         fputs("extern ", debugfile);
313                 print_list(debugfile, defn);
314                 fputs(">\n", debugfile);
315         }
316
317         ++nsyms;
318         return sym;
319 }
320
321 struct symbol *add_symbol(const char *name, enum symbol_type type,
322                           struct string_list *defn, int is_extern)
323 {
324         return __add_symbol(name, type, defn, is_extern, 0);
325 }
326
327 static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
328                                     struct string_list *defn, int is_extern)
329 {
330         return __add_symbol(name, type, defn, is_extern, 1);
331 }
332
333 /*----------------------------------------------------------------------*/
334
335 void free_node(struct string_list *node)
336 {
337         free(node->string);
338         free(node);
339 }
340
341 void free_list(struct string_list *s, struct string_list *e)
342 {
343         while (s != e) {
344                 struct string_list *next = s->next;
345                 free_node(s);
346                 s = next;
347         }
348 }
349
350 static struct string_list *mk_node(const char *string)
351 {
352         struct string_list *newnode;
353
354         newnode = xmalloc(sizeof(*newnode));
355         newnode->string = xstrdup(string);
356         newnode->tag = SYM_NORMAL;
357         newnode->next = NULL;
358
359         return newnode;
360 }
361
362 static struct string_list *concat_list(struct string_list *start, ...)
363 {
364         va_list ap;
365         struct string_list *n, *n2;
366
367         if (!start)
368                 return NULL;
369         for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
370                 for (n2 = n; n2->next; n2 = n2->next)
371                         ;
372                 n2->next = start;
373                 start = n;
374         }
375         va_end(ap);
376         return start;
377 }
378
379 struct string_list *copy_node(struct string_list *node)
380 {
381         struct string_list *newnode;
382
383         newnode = xmalloc(sizeof(*newnode));
384         newnode->string = xstrdup(node->string);
385         newnode->tag = node->tag;
386
387         return newnode;
388 }
389
390 struct string_list *copy_list_range(struct string_list *start,
391                                     struct string_list *end)
392 {
393         struct string_list *res, *n;
394
395         if (start == end)
396                 return NULL;
397         n = res = copy_node(start);
398         for (start = start->next; start != end; start = start->next) {
399                 n->next = copy_node(start);
400                 n = n->next;
401         }
402         n->next = NULL;
403         return res;
404 }
405
406 static int equal_list(struct string_list *a, struct string_list *b)
407 {
408         while (a && b) {
409                 if (a->tag != b->tag || strcmp(a->string, b->string))
410                         return 0;
411                 a = a->next;
412                 b = b->next;
413         }
414
415         return !a && !b;
416 }
417
418 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
419
420 static struct string_list *read_node(FILE *f)
421 {
422         char buffer[256];
423         struct string_list node = {
424                 .string = buffer,
425                 .tag = SYM_NORMAL };
426         int c;
427
428         while ((c = fgetc(f)) != EOF) {
429                 if (c == ' ') {
430                         if (node.string == buffer)
431                                 continue;
432                         break;
433                 } else if (c == '\n') {
434                         if (node.string == buffer)
435                                 return NULL;
436                         ungetc(c, f);
437                         break;
438                 }
439                 if (node.string >= buffer + sizeof(buffer) - 1) {
440                         fprintf(stderr, "Token too long\n");
441                         exit(1);
442                 }
443                 *node.string++ = c;
444         }
445         if (node.string == buffer)
446                 return NULL;
447         *node.string = 0;
448         node.string = buffer;
449
450         if (node.string[1] == '#') {
451                 int n;
452
453                 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
454                         if (node.string[0] == symbol_types[n].n) {
455                                 node.tag = n;
456                                 node.string += 2;
457                                 return copy_node(&node);
458                         }
459                 }
460                 fprintf(stderr, "Unknown type %c\n", node.string[0]);
461                 exit(1);
462         }
463         return copy_node(&node);
464 }
465
466 static void read_reference(FILE *f)
467 {
468         while (!feof(f)) {
469                 struct string_list *defn = NULL;
470                 struct string_list *sym, *def;
471                 int is_extern = 0, is_override = 0;
472                 struct symbol *subsym;
473
474                 sym = read_node(f);
475                 if (sym && sym->tag == SYM_NORMAL &&
476                     !strcmp(sym->string, "override")) {
477                         is_override = 1;
478                         free_node(sym);
479                         sym = read_node(f);
480                 }
481                 if (!sym)
482                         continue;
483                 def = read_node(f);
484                 if (def && def->tag == SYM_NORMAL &&
485                     !strcmp(def->string, "extern")) {
486                         is_extern = 1;
487                         free_node(def);
488                         def = read_node(f);
489                 }
490                 while (def) {
491                         def->next = defn;
492                         defn = def;
493                         def = read_node(f);
494                 }
495                 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
496                                               defn, is_extern);
497                 subsym->is_override = is_override;
498                 free_node(sym);
499         }
500 }
501
502 static void print_node(FILE * f, struct string_list *list)
503 {
504         if (symbol_types[list->tag].n) {
505                 putc(symbol_types[list->tag].n, f);
506                 putc('#', f);
507         }
508         fputs(list->string, f);
509 }
510
511 static void print_list(FILE * f, struct string_list *list)
512 {
513         struct string_list **e, **b;
514         struct string_list *tmp, **tmp2;
515         int elem = 1;
516
517         if (list == NULL) {
518                 fputs("(nil)", f);
519                 return;
520         }
521
522         tmp = list;
523         while ((tmp = tmp->next) != NULL)
524                 elem++;
525
526         b = alloca(elem * sizeof(*e));
527         e = b + elem;
528         tmp2 = e - 1;
529
530         (*tmp2--) = list;
531         while ((list = list->next) != NULL)
532                 *(tmp2--) = list;
533
534         while (b != e) {
535                 print_node(f, *b++);
536                 putc(' ', f);
537         }
538 }
539
540 static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
541 {
542         struct string_list *list = sym->defn;
543         struct string_list **e, **b;
544         struct string_list *tmp, **tmp2;
545         int elem = 1;
546
547         if (!list)
548                 return crc;
549
550         tmp = list;
551         while ((tmp = tmp->next) != NULL)
552                 elem++;
553
554         b = alloca(elem * sizeof(*e));
555         e = b + elem;
556         tmp2 = e - 1;
557
558         *(tmp2--) = list;
559         while ((list = list->next) != NULL)
560                 *(tmp2--) = list;
561
562         while (b != e) {
563                 struct string_list *cur;
564                 struct symbol *subsym;
565
566                 cur = *(b++);
567                 switch (cur->tag) {
568                 case SYM_NORMAL:
569                         if (flag_dump_defs)
570                                 fprintf(debugfile, "%s ", cur->string);
571                         crc = partial_crc32(cur->string, crc);
572                         crc = partial_crc32_one(' ', crc);
573                         break;
574
575                 case SYM_ENUM_CONST:
576                 case SYM_TYPEDEF:
577                         subsym = find_symbol(cur->string, cur->tag, 0);
578                         /* FIXME: Bad reference files can segfault here. */
579                         if (subsym->expansion_trail) {
580                                 if (flag_dump_defs)
581                                         fprintf(debugfile, "%s ", cur->string);
582                                 crc = partial_crc32(cur->string, crc);
583                                 crc = partial_crc32_one(' ', crc);
584                         } else {
585                                 subsym->expansion_trail = expansion_trail;
586                                 expansion_trail = subsym;
587                                 crc = expand_and_crc_sym(subsym, crc);
588                         }
589                         break;
590
591                 case SYM_STRUCT:
592                 case SYM_UNION:
593                 case SYM_ENUM:
594                         subsym = find_symbol(cur->string, cur->tag, 0);
595                         if (!subsym) {
596                                 struct string_list *n;
597
598                                 error_with_pos("expand undefined %s %s",
599                                                symbol_types[cur->tag].name,
600                                                cur->string);
601                                 n = concat_list(mk_node
602                                                 (symbol_types[cur->tag].name),
603                                                 mk_node(cur->string),
604                                                 mk_node("{"),
605                                                 mk_node("UNKNOWN"),
606                                                 mk_node("}"), NULL);
607                                 subsym =
608                                     add_symbol(cur->string, cur->tag, n, 0);
609                         }
610                         if (subsym->expansion_trail) {
611                                 if (flag_dump_defs) {
612                                         fprintf(debugfile, "%s %s ",
613                                                 symbol_types[cur->tag].name,
614                                                 cur->string);
615                                 }
616
617                                 crc = partial_crc32(symbol_types[cur->tag].name,
618                                                     crc);
619                                 crc = partial_crc32_one(' ', crc);
620                                 crc = partial_crc32(cur->string, crc);
621                                 crc = partial_crc32_one(' ', crc);
622                         } else {
623                                 subsym->expansion_trail = expansion_trail;
624                                 expansion_trail = subsym;
625                                 crc = expand_and_crc_sym(subsym, crc);
626                         }
627                         break;
628                 }
629         }
630
631         {
632                 static struct symbol **end = &visited_symbols;
633
634                 if (!sym->visited) {
635                         *end = sym;
636                         end = &sym->visited;
637                         sym->visited = (struct symbol *)-1L;
638                 }
639         }
640
641         return crc;
642 }
643
644 void export_symbol(const char *name)
645 {
646         struct symbol *sym;
647
648         sym = find_symbol(name, SYM_NORMAL, 0);
649         if (!sym)
650                 error_with_pos("export undefined symbol %s", name);
651         else {
652                 unsigned long crc;
653                 int has_changed = 0;
654
655                 if (flag_dump_defs)
656                         fprintf(debugfile, "Export %s == <", name);
657
658                 expansion_trail = (struct symbol *)-1L;
659
660                 sym->expansion_trail = expansion_trail;
661                 expansion_trail = sym;
662                 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
663
664                 sym = expansion_trail;
665                 while (sym != (struct symbol *)-1L) {
666                         struct symbol *n = sym->expansion_trail;
667
668                         if (sym->status != STATUS_UNCHANGED) {
669                                 if (!has_changed) {
670                                         print_location();
671                                         fprintf(stderr, "%s: %s: modversion "
672                                                 "changed because of changes "
673                                                 "in ", flag_preserve ? "error" :
674                                                        "warning", name);
675                                 } else
676                                         fprintf(stderr, ", ");
677                                 print_type_name(sym->type, sym->name);
678                                 if (sym->status == STATUS_DEFINED)
679                                         fprintf(stderr, " (became defined)");
680                                 has_changed = 1;
681                                 if (flag_preserve)
682                                         errors++;
683                         }
684                         sym->expansion_trail = 0;
685                         sym = n;
686                 }
687                 if (has_changed)
688                         fprintf(stderr, "\n");
689
690                 if (flag_dump_defs)
691                         fputs(">\n", debugfile);
692
693                 /* Used as a linker script. */
694                 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
695         }
696 }
697
698 /*----------------------------------------------------------------------*/
699
700 static void print_location(void)
701 {
702         fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
703 }
704
705 static void print_type_name(enum symbol_type type, const char *name)
706 {
707         if (symbol_types[type].name)
708                 fprintf(stderr, "%s %s", symbol_types[type].name, name);
709         else
710                 fprintf(stderr, "%s", name);
711 }
712
713 void error_with_pos(const char *fmt, ...)
714 {
715         va_list args;
716
717         if (flag_warnings) {
718                 print_location();
719
720                 va_start(args, fmt);
721                 vfprintf(stderr, fmt, args);
722                 va_end(args);
723                 putc('\n', stderr);
724
725                 errors++;
726         }
727 }
728
729 static void genksyms_usage(void)
730 {
731         fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
732 #ifdef __GNU_LIBRARY__
733               "  -a, --arch            Select architecture\n"
734               "  -d, --debug           Increment the debug level (repeatable)\n"
735               "  -D, --dump            Dump expanded symbol defs (for debugging only)\n"
736               "  -r, --reference file  Read reference symbols from a file\n"
737               "  -T, --dump-types file Dump expanded types into file\n"
738               "  -p, --preserve        Preserve reference modversions or fail\n"
739               "  -w, --warnings        Enable warnings\n"
740               "  -q, --quiet           Disable warnings (default)\n"
741               "  -h, --help            Print this message\n"
742               "  -V, --version         Print the release version\n"
743 #else                           /* __GNU_LIBRARY__ */
744               "  -a                    Select architecture\n"
745               "  -d                    Increment the debug level (repeatable)\n"
746               "  -D                    Dump expanded symbol defs (for debugging only)\n"
747               "  -r file               Read reference symbols from a file\n"
748               "  -T file               Dump expanded types into file\n"
749               "  -p                    Preserve reference modversions or fail\n"
750               "  -w                    Enable warnings\n"
751               "  -q                    Disable warnings (default)\n"
752               "  -h                    Print this message\n"
753               "  -V                    Print the release version\n"
754 #endif                          /* __GNU_LIBRARY__ */
755               , stderr);
756 }
757
758 int main(int argc, char **argv)
759 {
760         FILE *dumpfile = NULL, *ref_file = NULL;
761         int o;
762
763 #ifdef __GNU_LIBRARY__
764         struct option long_opts[] = {
765                 {"arch", 1, 0, 'a'},
766                 {"debug", 0, 0, 'd'},
767                 {"warnings", 0, 0, 'w'},
768                 {"quiet", 0, 0, 'q'},
769                 {"dump", 0, 0, 'D'},
770                 {"reference", 1, 0, 'r'},
771                 {"dump-types", 1, 0, 'T'},
772                 {"preserve", 0, 0, 'p'},
773                 {"version", 0, 0, 'V'},
774                 {"help", 0, 0, 'h'},
775                 {0, 0, 0, 0}
776         };
777
778         while ((o = getopt_long(argc, argv, "a:dwqVDr:T:ph",
779                                 &long_opts[0], NULL)) != EOF)
780 #else                           /* __GNU_LIBRARY__ */
781         while ((o = getopt(argc, argv, "a:dwqVDr:T:ph")) != EOF)
782 #endif                          /* __GNU_LIBRARY__ */
783                 switch (o) {
784                 case 'a':
785                         arch = optarg;
786                         break;
787                 case 'd':
788                         flag_debug++;
789                         break;
790                 case 'w':
791                         flag_warnings = 1;
792                         break;
793                 case 'q':
794                         flag_warnings = 0;
795                         break;
796                 case 'V':
797                         fputs("genksyms version 2.5.60\n", stderr);
798                         break;
799                 case 'D':
800                         flag_dump_defs = 1;
801                         break;
802                 case 'r':
803                         flag_reference = 1;
804                         ref_file = fopen(optarg, "r");
805                         if (!ref_file) {
806                                 perror(optarg);
807                                 return 1;
808                         }
809                         break;
810                 case 'T':
811                         flag_dump_types = 1;
812                         dumpfile = fopen(optarg, "w");
813                         if (!dumpfile) {
814                                 perror(optarg);
815                                 return 1;
816                         }
817                         break;
818                 case 'p':
819                         flag_preserve = 1;
820                         break;
821                 case 'h':
822                         genksyms_usage();
823                         return 0;
824                 default:
825                         genksyms_usage();
826                         return 1;
827                 }
828         if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0))
829                 mod_prefix = "_";
830         {
831                 extern int yydebug;
832                 extern int yy_flex_debug;
833
834                 yydebug = (flag_debug > 1);
835                 yy_flex_debug = (flag_debug > 2);
836
837                 debugfile = stderr;
838                 /* setlinebuf(debugfile); */
839         }
840
841         if (flag_reference) {
842                 read_reference(ref_file);
843                 fclose(ref_file);
844         }
845
846         yyparse();
847
848         if (flag_dump_types && visited_symbols) {
849                 while (visited_symbols != (struct symbol *)-1L) {
850                         struct symbol *sym = visited_symbols;
851
852                         if (sym->is_override)
853                                 fputs("override ", dumpfile);
854                         if (symbol_types[sym->type].n) {
855                                 putc(symbol_types[sym->type].n, dumpfile);
856                                 putc('#', dumpfile);
857                         }
858                         fputs(sym->name, dumpfile);
859                         putc(' ', dumpfile);
860                         if (sym->is_extern)
861                                 fputs("extern ", dumpfile);
862                         print_list(dumpfile, sym->defn);
863                         putc('\n', dumpfile);
864
865                         visited_symbols = sym->visited;
866                         sym->visited = NULL;
867                 }
868         }
869
870         if (flag_debug) {
871                 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
872                         nsyms, HASH_BUCKETS,
873                         (double)nsyms / (double)HASH_BUCKETS);
874         }
875
876         return errors != 0;
877 }