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