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