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