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