kbuild: fix silentoldconfig recursion
[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
ce560686
SR
45static int flag_debug, flag_dump_defs, flag_warnings;
46static const char *arch = "";
47static const char *mod_prefix = "";
1da177e4
LT
48
49static int errors;
50static int nsyms;
51
52static struct symbol *expansion_trail;
53
78c04153
SR
54static const char *const symbol_type_name[] = {
55 "normal", "typedef", "enum", "struct", "union"
1da177e4
LT
56};
57
ce560686
SR
58static int equal_list(struct string_list *a, struct string_list *b);
59static void print_list(FILE * f, struct string_list *list);
60
1da177e4
LT
61/*----------------------------------------------------------------------*/
62
78c04153
SR
63static const unsigned int crctab32[] = {
64 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
65 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
66 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
67 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
68 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
69 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
70 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
71 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
72 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
73 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
74 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
75 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
76 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
77 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
78 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
79 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
80 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
81 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
82 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
83 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
84 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
85 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
86 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
87 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
88 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
89 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
90 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
91 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
92 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
93 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
94 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
95 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
96 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
97 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
98 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
99 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
100 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
101 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
102 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
103 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
104 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
105 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
106 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
107 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
108 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
109 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
110 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
111 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
112 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
113 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
114 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
115 0x2d02ef8dU
1da177e4
LT
116};
117
ce560686 118static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
1da177e4 119{
78c04153 120 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
1da177e4
LT
121}
122
ce560686 123static unsigned long partial_crc32(const char *s, unsigned long crc)
1da177e4 124{
78c04153
SR
125 while (*s)
126 crc = partial_crc32_one(*s++, crc);
127 return crc;
1da177e4
LT
128}
129
ce560686 130static unsigned long crc32(const char *s)
1da177e4 131{
78c04153 132 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
1da177e4
LT
133}
134
1da177e4
LT
135/*----------------------------------------------------------------------*/
136
ce560686 137static enum symbol_type map_to_ns(enum symbol_type t)
1da177e4 138{
78c04153
SR
139 if (t == SYM_TYPEDEF)
140 t = SYM_NORMAL;
141 else if (t == SYM_UNION)
142 t = SYM_STRUCT;
143 return t;
1da177e4
LT
144}
145
78c04153 146struct symbol *find_symbol(const char *name, enum symbol_type ns)
1da177e4 147{
78c04153
SR
148 unsigned long h = crc32(name) % HASH_BUCKETS;
149 struct symbol *sym;
1da177e4 150
78c04153 151 for (sym = symtab[h]; sym; sym = sym->hash_next)
ce560686
SR
152 if (map_to_ns(sym->type) == map_to_ns(ns) &&
153 strcmp(name, sym->name) == 0)
78c04153 154 break;
1da177e4 155
78c04153 156 return sym;
1da177e4
LT
157}
158
78c04153
SR
159struct symbol *add_symbol(const char *name, enum symbol_type type,
160 struct string_list *defn, int is_extern)
1da177e4 161{
78c04153
SR
162 unsigned long h = crc32(name) % HASH_BUCKETS;
163 struct symbol *sym;
164
ce560686 165 for (sym = symtab[h]; sym; sym = sym->hash_next) {
78c04153
SR
166 if (map_to_ns(sym->type) == map_to_ns(type)
167 && strcmp(name, sym->name) == 0) {
168 if (!equal_list(sym->defn, defn))
169 error_with_pos("redefinition of %s", name);
170 return sym;
171 }
ce560686 172 }
78c04153
SR
173
174 sym = xmalloc(sizeof(*sym));
175 sym->name = name;
176 sym->type = type;
177 sym->defn = defn;
178 sym->expansion_trail = NULL;
179 sym->is_extern = is_extern;
180
181 sym->hash_next = symtab[h];
182 symtab[h] = sym;
183
184 if (flag_debug) {
185 fprintf(debugfile, "Defn for %s %s == <",
186 symbol_type_name[type], name);
187 if (is_extern)
188 fputs("extern ", debugfile);
189 print_list(debugfile, defn);
190 fputs(">\n", debugfile);
191 }
192
193 ++nsyms;
1da177e4 194 return sym;
1da177e4
LT
195}
196
1da177e4
LT
197/*----------------------------------------------------------------------*/
198
ce560686 199void free_node(struct string_list *node)
1da177e4 200{
78c04153
SR
201 free(node->string);
202 free(node);
1da177e4
LT
203}
204
78c04153 205void free_list(struct string_list *s, struct string_list *e)
1da177e4 206{
78c04153
SR
207 while (s != e) {
208 struct string_list *next = s->next;
209 free_node(s);
210 s = next;
211 }
1da177e4
LT
212}
213
ce560686 214struct string_list *copy_node(struct string_list *node)
1da177e4 215{
78c04153 216 struct string_list *newnode;
1da177e4 217
78c04153
SR
218 newnode = xmalloc(sizeof(*newnode));
219 newnode->string = xstrdup(node->string);
220 newnode->tag = node->tag;
1da177e4 221
78c04153 222 return newnode;
1da177e4
LT
223}
224
ce560686 225static int equal_list(struct string_list *a, struct string_list *b)
1da177e4 226{
78c04153
SR
227 while (a && b) {
228 if (a->tag != b->tag || strcmp(a->string, b->string))
229 return 0;
230 a = a->next;
231 b = b->next;
232 }
1da177e4 233
78c04153 234 return !a && !b;
1da177e4
LT
235}
236
ce560686 237static void print_node(FILE * f, struct string_list *list)
1da177e4 238{
78c04153
SR
239 switch (list->tag) {
240 case SYM_STRUCT:
241 putc('s', f);
242 goto printit;
243 case SYM_UNION:
244 putc('u', f);
245 goto printit;
246 case SYM_ENUM:
247 putc('e', f);
248 goto printit;
249 case SYM_TYPEDEF:
250 putc('t', f);
251 goto printit;
252
253 printit:
254 putc('#', f);
255 case SYM_NORMAL:
256 fputs(list->string, f);
257 break;
258 }
1da177e4
LT
259}
260
ce560686 261static void print_list(FILE * f, struct string_list *list)
1da177e4 262{
78c04153
SR
263 struct string_list **e, **b;
264 struct string_list *tmp, **tmp2;
265 int elem = 1;
1da177e4 266
78c04153
SR
267 if (list == NULL) {
268 fputs("(nil)", f);
269 return;
270 }
1da177e4 271
78c04153
SR
272 tmp = list;
273 while ((tmp = tmp->next) != NULL)
274 elem++;
1da177e4 275
78c04153
SR
276 b = alloca(elem * sizeof(*e));
277 e = b + elem;
278 tmp2 = e - 1;
1da177e4 279
78c04153
SR
280 (*tmp2--) = list;
281 while ((list = list->next) != NULL)
282 *(tmp2--) = list;
1da177e4 283
78c04153
SR
284 while (b != e) {
285 print_node(f, *b++);
286 putc(' ', f);
287 }
288}
1da177e4 289
ce560686
SR
290static unsigned long expand_and_crc_list(struct string_list *list,
291 unsigned long crc)
78c04153
SR
292{
293 struct string_list **e, **b;
294 struct string_list *tmp, **tmp2;
295 int elem = 1;
296
297 if (!list)
298 return crc;
299
300 tmp = list;
301 while ((tmp = tmp->next) != NULL)
302 elem++;
303
304 b = alloca(elem * sizeof(*e));
305 e = b + elem;
306 tmp2 = e - 1;
307
308 *(tmp2--) = list;
309 while ((list = list->next) != NULL)
310 *(tmp2--) = list;
311
312 while (b != e) {
313 struct string_list *cur;
314 struct symbol *subsym;
315
316 cur = *(b++);
317 switch (cur->tag) {
318 case SYM_NORMAL:
319 if (flag_dump_defs)
320 fprintf(debugfile, "%s ", cur->string);
321 crc = partial_crc32(cur->string, crc);
322 crc = partial_crc32_one(' ', crc);
323 break;
324
325 case SYM_TYPEDEF:
326 subsym = find_symbol(cur->string, cur->tag);
327 if (subsym->expansion_trail) {
328 if (flag_dump_defs)
329 fprintf(debugfile, "%s ", cur->string);
330 crc = partial_crc32(cur->string, crc);
331 crc = partial_crc32_one(' ', crc);
332 } else {
333 subsym->expansion_trail = expansion_trail;
334 expansion_trail = subsym;
335 crc = expand_and_crc_list(subsym->defn, crc);
336 }
337 break;
338
339 case SYM_STRUCT:
340 case SYM_UNION:
341 case SYM_ENUM:
342 subsym = find_symbol(cur->string, cur->tag);
343 if (!subsym) {
344 struct string_list *n, *t = NULL;
345
346 error_with_pos("expand undefined %s %s",
347 symbol_type_name[cur->tag],
348 cur->string);
349
350 n = xmalloc(sizeof(*n));
351 n->string = xstrdup(symbol_type_name[cur->tag]);
352 n->tag = SYM_NORMAL;
353 n->next = t;
354 t = n;
355
356 n = xmalloc(sizeof(*n));
357 n->string = xstrdup(cur->string);
358 n->tag = SYM_NORMAL;
359 n->next = t;
360 t = n;
361
362 n = xmalloc(sizeof(*n));
363 n->string = xstrdup("{ UNKNOWN }");
364 n->tag = SYM_NORMAL;
365 n->next = t;
366
367 subsym =
368 add_symbol(cur->string, cur->tag, n, 0);
369 }
370 if (subsym->expansion_trail) {
371 if (flag_dump_defs) {
372 fprintf(debugfile, "%s %s ",
373 symbol_type_name[cur->tag],
374 cur->string);
375 }
376
ce560686
SR
377 crc = partial_crc32(symbol_type_name[cur->tag],
378 crc);
78c04153
SR
379 crc = partial_crc32_one(' ', crc);
380 crc = partial_crc32(cur->string, crc);
381 crc = partial_crc32_one(' ', crc);
382 } else {
383 subsym->expansion_trail = expansion_trail;
384 expansion_trail = subsym;
385 crc = expand_and_crc_list(subsym->defn, crc);
386 }
387 break;
1da177e4 388 }
1da177e4 389 }
1da177e4 390
78c04153 391 return crc;
1da177e4
LT
392}
393
78c04153 394void export_symbol(const char *name)
1da177e4 395{
78c04153 396 struct symbol *sym;
1da177e4 397
78c04153
SR
398 sym = find_symbol(name, SYM_NORMAL);
399 if (!sym)
400 error_with_pos("export undefined symbol %s", name);
401 else {
402 unsigned long crc;
1da177e4 403
78c04153
SR
404 if (flag_dump_defs)
405 fprintf(debugfile, "Export %s == <", name);
1da177e4 406
78c04153 407 expansion_trail = (struct symbol *)-1L;
1da177e4 408
78c04153 409 crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
1da177e4 410
78c04153
SR
411 sym = expansion_trail;
412 while (sym != (struct symbol *)-1L) {
413 struct symbol *n = sym->expansion_trail;
414 sym->expansion_trail = 0;
415 sym = n;
416 }
1da177e4 417
78c04153
SR
418 if (flag_dump_defs)
419 fputs(">\n", debugfile);
1da177e4 420
78c04153
SR
421 /* Used as a linker script. */
422 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
423 }
1da177e4
LT
424}
425
426/*----------------------------------------------------------------------*/
78c04153 427void error_with_pos(const char *fmt, ...)
1da177e4 428{
78c04153 429 va_list args;
1da177e4 430
78c04153
SR
431 if (flag_warnings) {
432 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>",
433 cur_line);
1da177e4 434
78c04153
SR
435 va_start(args, fmt);
436 vfprintf(stderr, fmt, args);
437 va_end(args);
438 putc('\n', stderr);
1da177e4 439
78c04153
SR
440 errors++;
441 }
1da177e4
LT
442}
443
ce560686 444static void genksyms_usage(void)
1da177e4 445{
78c04153 446 fputs("Usage:\n" "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" "\n"
1da177e4
LT
447#ifdef __GNU_LIBRARY__
448 " -d, --debug Increment the debug level (repeatable)\n"
449 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
450 " -w, --warnings Enable warnings\n"
451 " -q, --quiet Disable warnings (default)\n"
452 " -h, --help Print this message\n"
453 " -V, --version Print the release version\n"
78c04153
SR
454#else /* __GNU_LIBRARY__ */
455 " -d Increment the debug level (repeatable)\n"
456 " -D Dump expanded symbol defs (for debugging only)\n"
457 " -w Enable warnings\n"
458 " -q Disable warnings (default)\n"
459 " -h Print this message\n"
460 " -V Print the release version\n"
461#endif /* __GNU_LIBRARY__ */
1da177e4
LT
462 , stderr);
463}
464
78c04153 465int main(int argc, char **argv)
1da177e4 466{
78c04153 467 int o;
1da177e4
LT
468
469#ifdef __GNU_LIBRARY__
78c04153
SR
470 struct option long_opts[] = {
471 {"arch", 1, 0, 'a'},
472 {"debug", 0, 0, 'd'},
473 {"warnings", 0, 0, 'w'},
474 {"quiet", 0, 0, 'q'},
475 {"dump", 0, 0, 'D'},
476 {"version", 0, 0, 'V'},
477 {"help", 0, 0, 'h'},
478 {0, 0, 0, 0}
479 };
480
481 while ((o = getopt_long(argc, argv, "a:dwqVDk:p:",
482 &long_opts[0], NULL)) != EOF)
483#else /* __GNU_LIBRARY__ */
484 while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF)
485#endif /* __GNU_LIBRARY__ */
486 switch (o) {
487 case 'a':
488 arch = optarg;
489 break;
490 case 'd':
491 flag_debug++;
492 break;
493 case 'w':
494 flag_warnings = 1;
495 break;
496 case 'q':
497 flag_warnings = 0;
498 break;
499 case 'V':
500 fputs("genksyms version 2.5.60\n", stderr);
501 break;
502 case 'D':
503 flag_dump_defs = 1;
504 break;
505 case 'h':
506 genksyms_usage();
507 return 0;
508 default:
509 genksyms_usage();
510 return 1;
511 }
512 if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0))
513 mod_prefix = "_";
514 {
515 extern int yydebug;
516 extern int yy_flex_debug;
517
518 yydebug = (flag_debug > 1);
519 yy_flex_debug = (flag_debug > 2);
520
521 debugfile = stderr;
522 /* setlinebuf(debugfile); */
523 }
524
525 yyparse();
526
527 if (flag_debug) {
528 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
529 nsyms, HASH_BUCKETS,
530 (double)nsyms / (double)HASH_BUCKETS);
531 }
532
533 return errors != 0;
1da177e4 534}
This page took 0.134625 seconds and 5 git commands to generate.