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