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