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