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