genksyms: Add helpers for building string lists
[deliverable/linux.git] / scripts / genksyms / genksyms.c
1 /* Generate kernel symbol version hashes.
2 Copyright 1996, 1997 Linux International.
3
4 New implementation contributed by Richard Henderson <rth@tamu.edu>
5 Based on original work by Bjorn Ekwall <bj0rn@blox.se>
6
7 This file was part of the Linux modutils 2.4.22: moved back into the
8 kernel sources by Rusty Russell/Kai Germaschewski.
9
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2 of the License, or (at your
13 option) any later version.
14
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation,
22 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <assert.h>
29 #include <stdarg.h>
30 #ifdef __GNU_LIBRARY__
31 #include <getopt.h>
32 #endif /* __GNU_LIBRARY__ */
33
34 #include "genksyms.h"
35 /*----------------------------------------------------------------------*/
36
37 #define HASH_BUCKETS 4096
38
39 static struct symbol *symtab[HASH_BUCKETS];
40 static FILE *debugfile;
41
42 int cur_line = 1;
43 char *cur_filename;
44
45 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
46 flag_preserve, flag_warnings;
47 static const char *arch = "";
48 static const char *mod_prefix = "";
49
50 static int errors;
51 static int nsyms;
52
53 static struct symbol *expansion_trail;
54 static struct symbol *visited_symbols;
55
56 static 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"},
65 };
66
67 static int equal_list(struct string_list *a, struct string_list *b);
68 static void print_list(FILE * f, struct string_list *list);
69 static struct string_list *concat_list(struct string_list *start, ...);
70 static struct string_list *mk_node(const char *string);
71 static void print_location(void);
72 static void print_type_name(enum symbol_type type, const char *name);
73
74 /*----------------------------------------------------------------------*/
75
76 static 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
129 };
130
131 static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
132 {
133 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
134 }
135
136 static unsigned long partial_crc32(const char *s, unsigned long crc)
137 {
138 while (*s)
139 crc = partial_crc32_one(*s++, crc);
140 return crc;
141 }
142
143 static unsigned long crc32(const char *s)
144 {
145 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
146 }
147
148 /*----------------------------------------------------------------------*/
149
150 static enum symbol_type map_to_ns(enum symbol_type t)
151 {
152 if (t == SYM_TYPEDEF)
153 t = SYM_NORMAL;
154 else if (t == SYM_UNION)
155 t = SYM_STRUCT;
156 return t;
157 }
158
159 struct symbol *find_symbol(const char *name, enum symbol_type ns)
160 {
161 unsigned long h = crc32(name) % HASH_BUCKETS;
162 struct symbol *sym;
163
164 for (sym = symtab[h]; sym; sym = sym->hash_next)
165 if (map_to_ns(sym->type) == map_to_ns(ns) &&
166 strcmp(name, sym->name) == 0 &&
167 sym->is_declared)
168 break;
169
170 return sym;
171 }
172
173 static int is_unknown_symbol(struct symbol *sym)
174 {
175 struct string_list *defn;
176
177 return ((sym->type == SYM_STRUCT ||
178 sym->type == SYM_UNION ||
179 sym->type == SYM_ENUM) &&
180 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
181 strcmp(defn->string, "}") == 0 &&
182 (defn = defn->next) && defn->tag == SYM_NORMAL &&
183 strcmp(defn->string, "UNKNOWN") == 0 &&
184 (defn = defn->next) && defn->tag == SYM_NORMAL &&
185 strcmp(defn->string, "{") == 0);
186 }
187
188 static struct symbol *__add_symbol(const char *name, enum symbol_type type,
189 struct string_list *defn, int is_extern,
190 int is_reference)
191 {
192 unsigned long h = crc32(name) % HASH_BUCKETS;
193 struct symbol *sym;
194 enum symbol_status status = STATUS_UNCHANGED;
195
196 for (sym = symtab[h]; sym; sym = sym->hash_next) {
197 if (map_to_ns(sym->type) == map_to_ns(type) &&
198 strcmp(name, sym->name) == 0) {
199 if (is_reference)
200 /* fall through */ ;
201 else if (sym->type == type &&
202 equal_list(sym->defn, defn)) {
203 if (!sym->is_declared && sym->is_override) {
204 print_location();
205 print_type_name(type, name);
206 fprintf(stderr, " modversion is "
207 "unchanged\n");
208 }
209 sym->is_declared = 1;
210 return sym;
211 } else if (!sym->is_declared) {
212 if (sym->is_override && flag_preserve) {
213 print_location();
214 fprintf(stderr, "ignoring ");
215 print_type_name(type, name);
216 fprintf(stderr, " modversion change\n");
217 sym->is_declared = 1;
218 return sym;
219 } else {
220 status = is_unknown_symbol(sym) ?
221 STATUS_DEFINED : STATUS_MODIFIED;
222 }
223 } else {
224 error_with_pos("redefinition of %s", name);
225 return sym;
226 }
227 break;
228 }
229 }
230
231 if (sym) {
232 struct symbol **psym;
233
234 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
235 if (*psym == sym) {
236 *psym = sym->hash_next;
237 break;
238 }
239 }
240 --nsyms;
241 }
242
243 sym = xmalloc(sizeof(*sym));
244 sym->name = name;
245 sym->type = type;
246 sym->defn = defn;
247 sym->expansion_trail = NULL;
248 sym->visited = NULL;
249 sym->is_extern = is_extern;
250
251 sym->hash_next = symtab[h];
252 symtab[h] = sym;
253
254 sym->is_declared = !is_reference;
255 sym->status = status;
256 sym->is_override = 0;
257
258 if (flag_debug) {
259 if (symbol_types[type].name)
260 fprintf(debugfile, "Defn for %s %s == <",
261 symbol_types[type].name, name);
262 else
263 fprintf(debugfile, "Defn for type%d %s == <",
264 type, name);
265 if (is_extern)
266 fputs("extern ", debugfile);
267 print_list(debugfile, defn);
268 fputs(">\n", debugfile);
269 }
270
271 ++nsyms;
272 return sym;
273 }
274
275 struct symbol *add_symbol(const char *name, enum symbol_type type,
276 struct string_list *defn, int is_extern)
277 {
278 return __add_symbol(name, type, defn, is_extern, 0);
279 }
280
281 static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
282 struct string_list *defn, int is_extern)
283 {
284 return __add_symbol(name, type, defn, is_extern, 1);
285 }
286
287 /*----------------------------------------------------------------------*/
288
289 void free_node(struct string_list *node)
290 {
291 free(node->string);
292 free(node);
293 }
294
295 void free_list(struct string_list *s, struct string_list *e)
296 {
297 while (s != e) {
298 struct string_list *next = s->next;
299 free_node(s);
300 s = next;
301 }
302 }
303
304 static struct string_list *mk_node(const char *string)
305 {
306 struct string_list *newnode;
307
308 newnode = xmalloc(sizeof(*newnode));
309 newnode->string = xstrdup(string);
310 newnode->tag = SYM_NORMAL;
311 newnode->next = NULL;
312
313 return newnode;
314 }
315
316 static struct string_list *concat_list(struct string_list *start, ...)
317 {
318 va_list ap;
319 struct string_list *n, *n2;
320
321 if (!start)
322 return NULL;
323 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
324 for (n2 = n; n2->next; n2 = n2->next)
325 ;
326 n2->next = start;
327 start = n;
328 }
329 va_end(ap);
330 return start;
331 }
332
333 struct string_list *copy_node(struct string_list *node)
334 {
335 struct string_list *newnode;
336
337 newnode = xmalloc(sizeof(*newnode));
338 newnode->string = xstrdup(node->string);
339 newnode->tag = node->tag;
340
341 return newnode;
342 }
343
344 static int equal_list(struct string_list *a, struct string_list *b)
345 {
346 while (a && b) {
347 if (a->tag != b->tag || strcmp(a->string, b->string))
348 return 0;
349 a = a->next;
350 b = b->next;
351 }
352
353 return !a && !b;
354 }
355
356 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
357
358 static struct string_list *read_node(FILE *f)
359 {
360 char buffer[256];
361 struct string_list node = {
362 .string = buffer,
363 .tag = SYM_NORMAL };
364 int c;
365
366 while ((c = fgetc(f)) != EOF) {
367 if (c == ' ') {
368 if (node.string == buffer)
369 continue;
370 break;
371 } else if (c == '\n') {
372 if (node.string == buffer)
373 return NULL;
374 ungetc(c, f);
375 break;
376 }
377 if (node.string >= buffer + sizeof(buffer) - 1) {
378 fprintf(stderr, "Token too long\n");
379 exit(1);
380 }
381 *node.string++ = c;
382 }
383 if (node.string == buffer)
384 return NULL;
385 *node.string = 0;
386 node.string = buffer;
387
388 if (node.string[1] == '#') {
389 int n;
390
391 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
392 if (node.string[0] == symbol_types[n].n) {
393 node.tag = n;
394 node.string += 2;
395 return copy_node(&node);
396 }
397 }
398 fprintf(stderr, "Unknown type %c\n", node.string[0]);
399 exit(1);
400 }
401 return copy_node(&node);
402 }
403
404 static void read_reference(FILE *f)
405 {
406 while (!feof(f)) {
407 struct string_list *defn = NULL;
408 struct string_list *sym, *def;
409 int is_extern = 0, is_override = 0;
410 struct symbol *subsym;
411
412 sym = read_node(f);
413 if (sym && sym->tag == SYM_NORMAL &&
414 !strcmp(sym->string, "override")) {
415 is_override = 1;
416 free_node(sym);
417 sym = read_node(f);
418 }
419 if (!sym)
420 continue;
421 def = read_node(f);
422 if (def && def->tag == SYM_NORMAL &&
423 !strcmp(def->string, "extern")) {
424 is_extern = 1;
425 free_node(def);
426 def = read_node(f);
427 }
428 while (def) {
429 def->next = defn;
430 defn = def;
431 def = read_node(f);
432 }
433 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
434 defn, is_extern);
435 subsym->is_override = is_override;
436 free_node(sym);
437 }
438 }
439
440 static void print_node(FILE * f, struct string_list *list)
441 {
442 if (symbol_types[list->tag].n) {
443 putc(symbol_types[list->tag].n, f);
444 putc('#', f);
445 }
446 fputs(list->string, f);
447 }
448
449 static void print_list(FILE * f, struct string_list *list)
450 {
451 struct string_list **e, **b;
452 struct string_list *tmp, **tmp2;
453 int elem = 1;
454
455 if (list == NULL) {
456 fputs("(nil)", f);
457 return;
458 }
459
460 tmp = list;
461 while ((tmp = tmp->next) != NULL)
462 elem++;
463
464 b = alloca(elem * sizeof(*e));
465 e = b + elem;
466 tmp2 = e - 1;
467
468 (*tmp2--) = list;
469 while ((list = list->next) != NULL)
470 *(tmp2--) = list;
471
472 while (b != e) {
473 print_node(f, *b++);
474 putc(' ', f);
475 }
476 }
477
478 static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
479 {
480 struct string_list *list = sym->defn;
481 struct string_list **e, **b;
482 struct string_list *tmp, **tmp2;
483 int elem = 1;
484
485 if (!list)
486 return crc;
487
488 tmp = list;
489 while ((tmp = tmp->next) != NULL)
490 elem++;
491
492 b = alloca(elem * sizeof(*e));
493 e = b + elem;
494 tmp2 = e - 1;
495
496 *(tmp2--) = list;
497 while ((list = list->next) != NULL)
498 *(tmp2--) = list;
499
500 while (b != e) {
501 struct string_list *cur;
502 struct symbol *subsym;
503
504 cur = *(b++);
505 switch (cur->tag) {
506 case SYM_NORMAL:
507 if (flag_dump_defs)
508 fprintf(debugfile, "%s ", cur->string);
509 crc = partial_crc32(cur->string, crc);
510 crc = partial_crc32_one(' ', crc);
511 break;
512
513 case SYM_TYPEDEF:
514 subsym = find_symbol(cur->string, cur->tag);
515 /* FIXME: Bad reference files can segfault here. */
516 if (subsym->expansion_trail) {
517 if (flag_dump_defs)
518 fprintf(debugfile, "%s ", cur->string);
519 crc = partial_crc32(cur->string, crc);
520 crc = partial_crc32_one(' ', crc);
521 } else {
522 subsym->expansion_trail = expansion_trail;
523 expansion_trail = subsym;
524 crc = expand_and_crc_sym(subsym, crc);
525 }
526 break;
527
528 case SYM_STRUCT:
529 case SYM_UNION:
530 case SYM_ENUM:
531 subsym = find_symbol(cur->string, cur->tag);
532 if (!subsym) {
533 struct string_list *n;
534
535 error_with_pos("expand undefined %s %s",
536 symbol_types[cur->tag].name,
537 cur->string);
538 n = concat_list(mk_node
539 (symbol_types[cur->tag].name),
540 mk_node(cur->string),
541 mk_node("{"),
542 mk_node("UNKNOWN"),
543 mk_node("}"), NULL);
544 subsym =
545 add_symbol(cur->string, cur->tag, n, 0);
546 }
547 if (subsym->expansion_trail) {
548 if (flag_dump_defs) {
549 fprintf(debugfile, "%s %s ",
550 symbol_types[cur->tag].name,
551 cur->string);
552 }
553
554 crc = partial_crc32(symbol_types[cur->tag].name,
555 crc);
556 crc = partial_crc32_one(' ', crc);
557 crc = partial_crc32(cur->string, crc);
558 crc = partial_crc32_one(' ', crc);
559 } else {
560 subsym->expansion_trail = expansion_trail;
561 expansion_trail = subsym;
562 crc = expand_and_crc_sym(subsym, crc);
563 }
564 break;
565 }
566 }
567
568 {
569 static struct symbol **end = &visited_symbols;
570
571 if (!sym->visited) {
572 *end = sym;
573 end = &sym->visited;
574 sym->visited = (struct symbol *)-1L;
575 }
576 }
577
578 return crc;
579 }
580
581 void export_symbol(const char *name)
582 {
583 struct symbol *sym;
584
585 sym = find_symbol(name, SYM_NORMAL);
586 if (!sym)
587 error_with_pos("export undefined symbol %s", name);
588 else {
589 unsigned long crc;
590 int has_changed = 0;
591
592 if (flag_dump_defs)
593 fprintf(debugfile, "Export %s == <", name);
594
595 expansion_trail = (struct symbol *)-1L;
596
597 sym->expansion_trail = expansion_trail;
598 expansion_trail = sym;
599 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
600
601 sym = expansion_trail;
602 while (sym != (struct symbol *)-1L) {
603 struct symbol *n = sym->expansion_trail;
604
605 if (sym->status != STATUS_UNCHANGED) {
606 if (!has_changed) {
607 print_location();
608 fprintf(stderr, "%s: %s: modversion "
609 "changed because of changes "
610 "in ", flag_preserve ? "error" :
611 "warning", name);
612 } else
613 fprintf(stderr, ", ");
614 print_type_name(sym->type, sym->name);
615 if (sym->status == STATUS_DEFINED)
616 fprintf(stderr, " (became defined)");
617 has_changed = 1;
618 if (flag_preserve)
619 errors++;
620 }
621 sym->expansion_trail = 0;
622 sym = n;
623 }
624 if (has_changed)
625 fprintf(stderr, "\n");
626
627 if (flag_dump_defs)
628 fputs(">\n", debugfile);
629
630 /* Used as a linker script. */
631 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
632 }
633 }
634
635 /*----------------------------------------------------------------------*/
636
637 static void print_location(void)
638 {
639 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
640 }
641
642 static void print_type_name(enum symbol_type type, const char *name)
643 {
644 if (symbol_types[type].name)
645 fprintf(stderr, "%s %s", symbol_types[type].name, name);
646 else
647 fprintf(stderr, "%s", name);
648 }
649
650 void error_with_pos(const char *fmt, ...)
651 {
652 va_list args;
653
654 if (flag_warnings) {
655 print_location();
656
657 va_start(args, fmt);
658 vfprintf(stderr, fmt, args);
659 va_end(args);
660 putc('\n', stderr);
661
662 errors++;
663 }
664 }
665
666 static void genksyms_usage(void)
667 {
668 fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
669 #ifdef __GNU_LIBRARY__
670 " -a, --arch Select architecture\n"
671 " -d, --debug Increment the debug level (repeatable)\n"
672 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
673 " -r, --reference file Read reference symbols from a file\n"
674 " -T, --dump-types file Dump expanded types into file\n"
675 " -p, --preserve Preserve reference modversions or fail\n"
676 " -w, --warnings Enable warnings\n"
677 " -q, --quiet Disable warnings (default)\n"
678 " -h, --help Print this message\n"
679 " -V, --version Print the release version\n"
680 #else /* __GNU_LIBRARY__ */
681 " -a Select architecture\n"
682 " -d Increment the debug level (repeatable)\n"
683 " -D Dump expanded symbol defs (for debugging only)\n"
684 " -r file Read reference symbols from a file\n"
685 " -T file Dump expanded types into file\n"
686 " -p Preserve reference modversions or fail\n"
687 " -w Enable warnings\n"
688 " -q Disable warnings (default)\n"
689 " -h Print this message\n"
690 " -V Print the release version\n"
691 #endif /* __GNU_LIBRARY__ */
692 , stderr);
693 }
694
695 int main(int argc, char **argv)
696 {
697 FILE *dumpfile = NULL, *ref_file = NULL;
698 int o;
699
700 #ifdef __GNU_LIBRARY__
701 struct option long_opts[] = {
702 {"arch", 1, 0, 'a'},
703 {"debug", 0, 0, 'd'},
704 {"warnings", 0, 0, 'w'},
705 {"quiet", 0, 0, 'q'},
706 {"dump", 0, 0, 'D'},
707 {"reference", 1, 0, 'r'},
708 {"dump-types", 1, 0, 'T'},
709 {"preserve", 0, 0, 'p'},
710 {"version", 0, 0, 'V'},
711 {"help", 0, 0, 'h'},
712 {0, 0, 0, 0}
713 };
714
715 while ((o = getopt_long(argc, argv, "a:dwqVDr:T:ph",
716 &long_opts[0], NULL)) != EOF)
717 #else /* __GNU_LIBRARY__ */
718 while ((o = getopt(argc, argv, "a:dwqVDr:T:ph")) != EOF)
719 #endif /* __GNU_LIBRARY__ */
720 switch (o) {
721 case 'a':
722 arch = optarg;
723 break;
724 case 'd':
725 flag_debug++;
726 break;
727 case 'w':
728 flag_warnings = 1;
729 break;
730 case 'q':
731 flag_warnings = 0;
732 break;
733 case 'V':
734 fputs("genksyms version 2.5.60\n", stderr);
735 break;
736 case 'D':
737 flag_dump_defs = 1;
738 break;
739 case 'r':
740 flag_reference = 1;
741 ref_file = fopen(optarg, "r");
742 if (!ref_file) {
743 perror(optarg);
744 return 1;
745 }
746 break;
747 case 'T':
748 flag_dump_types = 1;
749 dumpfile = fopen(optarg, "w");
750 if (!dumpfile) {
751 perror(optarg);
752 return 1;
753 }
754 break;
755 case 'p':
756 flag_preserve = 1;
757 break;
758 case 'h':
759 genksyms_usage();
760 return 0;
761 default:
762 genksyms_usage();
763 return 1;
764 }
765 if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0))
766 mod_prefix = "_";
767 {
768 extern int yydebug;
769 extern int yy_flex_debug;
770
771 yydebug = (flag_debug > 1);
772 yy_flex_debug = (flag_debug > 2);
773
774 debugfile = stderr;
775 /* setlinebuf(debugfile); */
776 }
777
778 if (flag_reference) {
779 read_reference(ref_file);
780 fclose(ref_file);
781 }
782
783 yyparse();
784
785 if (flag_dump_types && visited_symbols) {
786 while (visited_symbols != (struct symbol *)-1L) {
787 struct symbol *sym = visited_symbols;
788
789 if (sym->is_override)
790 fputs("override ", dumpfile);
791 if (symbol_types[sym->type].n) {
792 putc(symbol_types[sym->type].n, dumpfile);
793 putc('#', dumpfile);
794 }
795 fputs(sym->name, dumpfile);
796 putc(' ', dumpfile);
797 if (sym->is_extern)
798 fputs("extern ", dumpfile);
799 print_list(dumpfile, sym->defn);
800 putc('\n', dumpfile);
801
802 visited_symbols = sym->visited;
803 sym->visited = NULL;
804 }
805 }
806
807 if (flag_debug) {
808 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
809 nsyms, HASH_BUCKETS,
810 (double)nsyms / (double)HASH_BUCKETS);
811 }
812
813 return errors != 0;
814 }
This page took 0.046634 seconds and 6 git commands to generate.