]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/blame - scripts/genksyms/genksyms.c
UBUNTU: Ubuntu-5.0.0-29.31
[mirror_ubuntu-disco-kernel.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;
2c5925d6
MM
43char *cur_filename, *source_file;
44int in_source_file;
1da177e4 45
64e6c1e1 46static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
56067812 47 flag_preserve, flag_warnings, flag_rel_crcs;
1da177e4
LT
48
49static int errors;
50static int nsyms;
51
52static struct symbol *expansion_trail;
15fde675 53static struct symbol *visited_symbols;
1da177e4 54
7ec8eda1
MM
55static const struct {
56 int n;
57 const char *name;
58} symbol_types[] = {
59 [SYM_NORMAL] = { 0, NULL},
60 [SYM_TYPEDEF] = {'t', "typedef"},
61 [SYM_ENUM] = {'e', "enum"},
62 [SYM_STRUCT] = {'s', "struct"},
63 [SYM_UNION] = {'u', "union"},
e37ddb82 64 [SYM_ENUM_CONST] = {'E', "enum constant"},
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{
e37ddb82
MM
152 switch (t) {
153 case SYM_ENUM_CONST:
154 case SYM_NORMAL:
155 case SYM_TYPEDEF:
156 return SYM_NORMAL;
157 case SYM_ENUM:
158 case SYM_STRUCT:
159 case SYM_UNION:
160 return SYM_STRUCT;
161 }
78c04153 162 return t;
1da177e4
LT
163}
164
01762c4e 165struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
1da177e4 166{
78c04153
SR
167 unsigned long h = crc32(name) % HASH_BUCKETS;
168 struct symbol *sym;
1da177e4 169
78c04153 170 for (sym = symtab[h]; sym; sym = sym->hash_next)
ce560686 171 if (map_to_ns(sym->type) == map_to_ns(ns) &&
64e6c1e1
AG
172 strcmp(name, sym->name) == 0 &&
173 sym->is_declared)
78c04153 174 break;
1da177e4 175
01762c4e
MM
176 if (exact && sym && sym->type != ns)
177 return NULL;
78c04153 178 return sym;
1da177e4
LT
179}
180
64e6c1e1
AG
181static int is_unknown_symbol(struct symbol *sym)
182{
183 struct string_list *defn;
184
185 return ((sym->type == SYM_STRUCT ||
186 sym->type == SYM_UNION ||
187 sym->type == SYM_ENUM) &&
188 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
189 strcmp(defn->string, "}") == 0 &&
190 (defn = defn->next) && defn->tag == SYM_NORMAL &&
191 strcmp(defn->string, "UNKNOWN") == 0 &&
192 (defn = defn->next) && defn->tag == SYM_NORMAL &&
193 strcmp(defn->string, "{") == 0);
194}
195
b7ed698c 196static struct symbol *__add_symbol(const char *name, enum symbol_type type,
64e6c1e1
AG
197 struct string_list *defn, int is_extern,
198 int is_reference)
1da177e4 199{
e37ddb82 200 unsigned long h;
78c04153 201 struct symbol *sym;
64e6c1e1 202 enum symbol_status status = STATUS_UNCHANGED;
e37ddb82
MM
203 /* The parser adds symbols in the order their declaration completes,
204 * so it is safe to store the value of the previous enum constant in
205 * a static variable.
206 */
207 static int enum_counter;
208 static struct string_list *last_enum_expr;
209
210 if (type == SYM_ENUM_CONST) {
211 if (defn) {
212 free_list(last_enum_expr, NULL);
213 last_enum_expr = copy_list_range(defn, NULL);
214 enum_counter = 1;
215 } else {
216 struct string_list *expr;
217 char buf[20];
218
219 snprintf(buf, sizeof(buf), "%d", enum_counter++);
220 if (last_enum_expr) {
221 expr = copy_list_range(last_enum_expr, NULL);
222 defn = concat_list(mk_node("("),
223 expr,
224 mk_node(")"),
225 mk_node("+"),
226 mk_node(buf), NULL);
227 } else {
228 defn = mk_node(buf);
229 }
230 }
231 } else if (type == SYM_ENUM) {
232 free_list(last_enum_expr, NULL);
233 last_enum_expr = NULL;
234 enum_counter = 0;
235 if (!name)
236 /* Anonymous enum definition, nothing more to do */
237 return NULL;
238 }
78c04153 239
e37ddb82 240 h = crc32(name) % HASH_BUCKETS;
ce560686 241 for (sym = symtab[h]; sym; sym = sym->hash_next) {
64e6c1e1
AG
242 if (map_to_ns(sym->type) == map_to_ns(type) &&
243 strcmp(name, sym->name) == 0) {
244 if (is_reference)
245 /* fall through */ ;
246 else if (sym->type == type &&
247 equal_list(sym->defn, defn)) {
5dae9a55
AG
248 if (!sym->is_declared && sym->is_override) {
249 print_location();
250 print_type_name(type, name);
251 fprintf(stderr, " modversion is "
252 "unchanged\n");
253 }
64e6c1e1
AG
254 sym->is_declared = 1;
255 return sym;
256 } else if (!sym->is_declared) {
5dae9a55
AG
257 if (sym->is_override && flag_preserve) {
258 print_location();
259 fprintf(stderr, "ignoring ");
260 print_type_name(type, name);
261 fprintf(stderr, " modversion change\n");
262 sym->is_declared = 1;
263 return sym;
264 } else {
265 status = is_unknown_symbol(sym) ?
266 STATUS_DEFINED : STATUS_MODIFIED;
267 }
64e6c1e1 268 } else {
78c04153 269 error_with_pos("redefinition of %s", name);
64e6c1e1
AG
270 return sym;
271 }
272 break;
78c04153 273 }
ce560686 274 }
78c04153 275
64e6c1e1
AG
276 if (sym) {
277 struct symbol **psym;
278
279 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
280 if (*psym == sym) {
281 *psym = sym->hash_next;
282 break;
283 }
284 }
285 --nsyms;
286 }
287
78c04153
SR
288 sym = xmalloc(sizeof(*sym));
289 sym->name = name;
290 sym->type = type;
291 sym->defn = defn;
292 sym->expansion_trail = NULL;
15fde675 293 sym->visited = NULL;
78c04153
SR
294 sym->is_extern = is_extern;
295
296 sym->hash_next = symtab[h];
297 symtab[h] = sym;
298
64e6c1e1
AG
299 sym->is_declared = !is_reference;
300 sym->status = status;
5dae9a55 301 sym->is_override = 0;
64e6c1e1 302
78c04153 303 if (flag_debug) {
7ec8eda1
MM
304 if (symbol_types[type].name)
305 fprintf(debugfile, "Defn for %s %s == <",
306 symbol_types[type].name, name);
307 else
308 fprintf(debugfile, "Defn for type%d %s == <",
309 type, name);
78c04153
SR
310 if (is_extern)
311 fputs("extern ", debugfile);
312 print_list(debugfile, defn);
313 fputs(">\n", debugfile);
314 }
315
316 ++nsyms;
1da177e4 317 return sym;
1da177e4
LT
318}
319
64e6c1e1
AG
320struct symbol *add_symbol(const char *name, enum symbol_type type,
321 struct string_list *defn, int is_extern)
322{
323 return __add_symbol(name, type, defn, is_extern, 0);
324}
325
b7ed698c 326static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
64e6c1e1
AG
327 struct string_list *defn, int is_extern)
328{
329 return __add_symbol(name, type, defn, is_extern, 1);
330}
331
1da177e4
LT
332/*----------------------------------------------------------------------*/
333
ce560686 334void free_node(struct string_list *node)
1da177e4 335{
78c04153
SR
336 free(node->string);
337 free(node);
1da177e4
LT
338}
339
78c04153 340void free_list(struct string_list *s, struct string_list *e)
1da177e4 341{
78c04153
SR
342 while (s != e) {
343 struct string_list *next = s->next;
344 free_node(s);
345 s = next;
346 }
1da177e4
LT
347}
348
68eb8563
MM
349static struct string_list *mk_node(const char *string)
350{
351 struct string_list *newnode;
352
353 newnode = xmalloc(sizeof(*newnode));
354 newnode->string = xstrdup(string);
355 newnode->tag = SYM_NORMAL;
356 newnode->next = NULL;
357
358 return newnode;
359}
360
361static struct string_list *concat_list(struct string_list *start, ...)
362{
363 va_list ap;
364 struct string_list *n, *n2;
365
366 if (!start)
367 return NULL;
368 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
369 for (n2 = n; n2->next; n2 = n2->next)
370 ;
371 n2->next = start;
372 start = n;
373 }
374 va_end(ap);
375 return start;
376}
377
ce560686 378struct string_list *copy_node(struct string_list *node)
1da177e4 379{
78c04153 380 struct string_list *newnode;
1da177e4 381
78c04153
SR
382 newnode = xmalloc(sizeof(*newnode));
383 newnode->string = xstrdup(node->string);
384 newnode->tag = node->tag;
1da177e4 385
78c04153 386 return newnode;
1da177e4
LT
387}
388
e37ddb82
MM
389struct string_list *copy_list_range(struct string_list *start,
390 struct string_list *end)
391{
392 struct string_list *res, *n;
393
394 if (start == end)
395 return NULL;
396 n = res = copy_node(start);
397 for (start = start->next; start != end; start = start->next) {
398 n->next = copy_node(start);
399 n = n->next;
400 }
401 n->next = NULL;
402 return res;
403}
404
ce560686 405static int equal_list(struct string_list *a, struct string_list *b)
1da177e4 406{
78c04153
SR
407 while (a && b) {
408 if (a->tag != b->tag || strcmp(a->string, b->string))
409 return 0;
410 a = a->next;
411 b = b->next;
412 }
1da177e4 413
78c04153 414 return !a && !b;
1da177e4
LT
415}
416
64e6c1e1
AG
417#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
418
b7ed698c 419static struct string_list *read_node(FILE *f)
64e6c1e1
AG
420{
421 char buffer[256];
422 struct string_list node = {
423 .string = buffer,
424 .tag = SYM_NORMAL };
a78f70e8 425 int c, in_string = 0;
64e6c1e1
AG
426
427 while ((c = fgetc(f)) != EOF) {
a78f70e8 428 if (!in_string && c == ' ') {
64e6c1e1
AG
429 if (node.string == buffer)
430 continue;
431 break;
a78f70e8
MM
432 } else if (c == '"') {
433 in_string = !in_string;
64e6c1e1
AG
434 } else if (c == '\n') {
435 if (node.string == buffer)
436 return NULL;
437 ungetc(c, f);
438 break;
439 }
440 if (node.string >= buffer + sizeof(buffer) - 1) {
441 fprintf(stderr, "Token too long\n");
442 exit(1);
443 }
444 *node.string++ = c;
445 }
446 if (node.string == buffer)
447 return NULL;
448 *node.string = 0;
449 node.string = buffer;
450
451 if (node.string[1] == '#') {
1ae14703 452 size_t n;
64e6c1e1 453
7ec8eda1
MM
454 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
455 if (node.string[0] == symbol_types[n].n) {
64e6c1e1
AG
456 node.tag = n;
457 node.string += 2;
458 return copy_node(&node);
459 }
460 }
461 fprintf(stderr, "Unknown type %c\n", node.string[0]);
462 exit(1);
463 }
464 return copy_node(&node);
465}
466
467static void read_reference(FILE *f)
468{
469 while (!feof(f)) {
470 struct string_list *defn = NULL;
471 struct string_list *sym, *def;
5dae9a55
AG
472 int is_extern = 0, is_override = 0;
473 struct symbol *subsym;
64e6c1e1
AG
474
475 sym = read_node(f);
5dae9a55
AG
476 if (sym && sym->tag == SYM_NORMAL &&
477 !strcmp(sym->string, "override")) {
478 is_override = 1;
479 free_node(sym);
480 sym = read_node(f);
481 }
64e6c1e1
AG
482 if (!sym)
483 continue;
484 def = read_node(f);
485 if (def && def->tag == SYM_NORMAL &&
486 !strcmp(def->string, "extern")) {
487 is_extern = 1;
488 free_node(def);
489 def = read_node(f);
490 }
491 while (def) {
492 def->next = defn;
493 defn = def;
494 def = read_node(f);
495 }
5dae9a55 496 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
64e6c1e1 497 defn, is_extern);
5dae9a55 498 subsym->is_override = is_override;
64e6c1e1
AG
499 free_node(sym);
500 }
501}
502
ce560686 503static void print_node(FILE * f, struct string_list *list)
1da177e4 504{
7ec8eda1
MM
505 if (symbol_types[list->tag].n) {
506 putc(symbol_types[list->tag].n, f);
78c04153 507 putc('#', f);
78c04153 508 }
15fde675 509 fputs(list->string, f);
1da177e4
LT
510}
511
ce560686 512static void print_list(FILE * f, struct string_list *list)
1da177e4 513{
78c04153
SR
514 struct string_list **e, **b;
515 struct string_list *tmp, **tmp2;
516 int elem = 1;
1da177e4 517
78c04153
SR
518 if (list == NULL) {
519 fputs("(nil)", f);
520 return;
521 }
1da177e4 522
78c04153
SR
523 tmp = list;
524 while ((tmp = tmp->next) != NULL)
525 elem++;
1da177e4 526
78c04153
SR
527 b = alloca(elem * sizeof(*e));
528 e = b + elem;
529 tmp2 = e - 1;
1da177e4 530
78c04153
SR
531 (*tmp2--) = list;
532 while ((list = list->next) != NULL)
533 *(tmp2--) = list;
1da177e4 534
78c04153
SR
535 while (b != e) {
536 print_node(f, *b++);
537 putc(' ', f);
538 }
539}
1da177e4 540
15fde675 541static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
78c04153 542{
15fde675 543 struct string_list *list = sym->defn;
78c04153
SR
544 struct string_list **e, **b;
545 struct string_list *tmp, **tmp2;
546 int elem = 1;
547
548 if (!list)
549 return crc;
550
551 tmp = list;
552 while ((tmp = tmp->next) != NULL)
553 elem++;
554
555 b = alloca(elem * sizeof(*e));
556 e = b + elem;
557 tmp2 = e - 1;
558
559 *(tmp2--) = list;
560 while ((list = list->next) != NULL)
561 *(tmp2--) = list;
562
563 while (b != e) {
564 struct string_list *cur;
565 struct symbol *subsym;
566
567 cur = *(b++);
568 switch (cur->tag) {
569 case SYM_NORMAL:
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 break;
575
e37ddb82 576 case SYM_ENUM_CONST:
78c04153 577 case SYM_TYPEDEF:
01762c4e 578 subsym = find_symbol(cur->string, cur->tag, 0);
64e6c1e1 579 /* FIXME: Bad reference files can segfault here. */
78c04153
SR
580 if (subsym->expansion_trail) {
581 if (flag_dump_defs)
582 fprintf(debugfile, "%s ", cur->string);
583 crc = partial_crc32(cur->string, crc);
584 crc = partial_crc32_one(' ', crc);
585 } else {
586 subsym->expansion_trail = expansion_trail;
587 expansion_trail = subsym;
15fde675 588 crc = expand_and_crc_sym(subsym, crc);
78c04153
SR
589 }
590 break;
591
592 case SYM_STRUCT:
593 case SYM_UNION:
594 case SYM_ENUM:
01762c4e 595 subsym = find_symbol(cur->string, cur->tag, 0);
78c04153 596 if (!subsym) {
68eb8563 597 struct string_list *n;
78c04153
SR
598
599 error_with_pos("expand undefined %s %s",
7ec8eda1 600 symbol_types[cur->tag].name,
78c04153 601 cur->string);
68eb8563
MM
602 n = concat_list(mk_node
603 (symbol_types[cur->tag].name),
604 mk_node(cur->string),
605 mk_node("{"),
606 mk_node("UNKNOWN"),
607 mk_node("}"), NULL);
78c04153
SR
608 subsym =
609 add_symbol(cur->string, cur->tag, n, 0);
610 }
611 if (subsym->expansion_trail) {
612 if (flag_dump_defs) {
613 fprintf(debugfile, "%s %s ",
7ec8eda1 614 symbol_types[cur->tag].name,
78c04153
SR
615 cur->string);
616 }
617
7ec8eda1 618 crc = partial_crc32(symbol_types[cur->tag].name,
ce560686 619 crc);
78c04153
SR
620 crc = partial_crc32_one(' ', crc);
621 crc = partial_crc32(cur->string, crc);
622 crc = partial_crc32_one(' ', crc);
623 } else {
624 subsym->expansion_trail = expansion_trail;
625 expansion_trail = subsym;
15fde675 626 crc = expand_and_crc_sym(subsym, crc);
78c04153
SR
627 }
628 break;
1da177e4 629 }
1da177e4 630 }
1da177e4 631
15fde675
AG
632 {
633 static struct symbol **end = &visited_symbols;
634
635 if (!sym->visited) {
636 *end = sym;
637 end = &sym->visited;
638 sym->visited = (struct symbol *)-1L;
639 }
640 }
641
78c04153 642 return crc;
1da177e4
LT
643}
644
78c04153 645void export_symbol(const char *name)
1da177e4 646{
78c04153 647 struct symbol *sym;
1da177e4 648
01762c4e 649 sym = find_symbol(name, SYM_NORMAL, 0);
78c04153
SR
650 if (!sym)
651 error_with_pos("export undefined symbol %s", name);
652 else {
653 unsigned long crc;
64e6c1e1 654 int has_changed = 0;
1da177e4 655
78c04153
SR
656 if (flag_dump_defs)
657 fprintf(debugfile, "Export %s == <", name);
1da177e4 658
78c04153 659 expansion_trail = (struct symbol *)-1L;
1da177e4 660
64e6c1e1
AG
661 sym->expansion_trail = expansion_trail;
662 expansion_trail = sym;
15fde675 663 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
1da177e4 664
78c04153
SR
665 sym = expansion_trail;
666 while (sym != (struct symbol *)-1L) {
667 struct symbol *n = sym->expansion_trail;
64e6c1e1
AG
668
669 if (sym->status != STATUS_UNCHANGED) {
670 if (!has_changed) {
671 print_location();
672 fprintf(stderr, "%s: %s: modversion "
673 "changed because of changes "
674 "in ", flag_preserve ? "error" :
675 "warning", name);
676 } else
677 fprintf(stderr, ", ");
678 print_type_name(sym->type, sym->name);
679 if (sym->status == STATUS_DEFINED)
680 fprintf(stderr, " (became defined)");
681 has_changed = 1;
682 if (flag_preserve)
683 errors++;
684 }
78c04153
SR
685 sym->expansion_trail = 0;
686 sym = n;
687 }
64e6c1e1
AG
688 if (has_changed)
689 fprintf(stderr, "\n");
1da177e4 690
78c04153
SR
691 if (flag_dump_defs)
692 fputs(">\n", debugfile);
1da177e4 693
2ea03891 694 /* Used as a linker script. */
74d93171 695 printf(!flag_rel_crcs ? "__crc_%s = 0x%08lx;\n" :
56067812 696 "SECTIONS { .rodata : ALIGN(4) { "
74d93171
MY
697 "__crc_%s = .; LONG(0x%08lx); } }\n",
698 name, crc);
78c04153 699 }
1da177e4
LT
700}
701
702/*----------------------------------------------------------------------*/
64e6c1e1
AG
703
704static void print_location(void)
705{
706 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
707}
708
709static void print_type_name(enum symbol_type type, const char *name)
710{
7ec8eda1
MM
711 if (symbol_types[type].name)
712 fprintf(stderr, "%s %s", symbol_types[type].name, name);
64e6c1e1
AG
713 else
714 fprintf(stderr, "%s", name);
715}
716
78c04153 717void error_with_pos(const char *fmt, ...)
1da177e4 718{
78c04153 719 va_list args;
1da177e4 720
78c04153 721 if (flag_warnings) {
64e6c1e1 722 print_location();
1da177e4 723
78c04153
SR
724 va_start(args, fmt);
725 vfprintf(stderr, fmt, args);
726 va_end(args);
727 putc('\n', stderr);
1da177e4 728
78c04153
SR
729 errors++;
730 }
1da177e4
LT
731}
732
ce560686 733static void genksyms_usage(void)
1da177e4 734{
56067812 735 fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
1da177e4 736#ifdef __GNU_LIBRARY__
d70f82ac 737 " -s, --symbol-prefix Select symbol prefix\n"
1da177e4
LT
738 " -d, --debug Increment the debug level (repeatable)\n"
739 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
64e6c1e1
AG
740 " -r, --reference file Read reference symbols from a file\n"
741 " -T, --dump-types file Dump expanded types into file\n"
742 " -p, --preserve Preserve reference modversions or fail\n"
1da177e4
LT
743 " -w, --warnings Enable warnings\n"
744 " -q, --quiet Disable warnings (default)\n"
745 " -h, --help Print this message\n"
746 " -V, --version Print the release version\n"
56067812 747 " -R, --relative-crc Emit section relative symbol CRCs\n"
78c04153 748#else /* __GNU_LIBRARY__ */
d70f82ac 749 " -s Select symbol prefix\n"
78c04153
SR
750 " -d Increment the debug level (repeatable)\n"
751 " -D Dump expanded symbol defs (for debugging only)\n"
64e6c1e1
AG
752 " -r file Read reference symbols from a file\n"
753 " -T file Dump expanded types into file\n"
754 " -p Preserve reference modversions or fail\n"
78c04153
SR
755 " -w Enable warnings\n"
756 " -q Disable warnings (default)\n"
757 " -h Print this message\n"
758 " -V Print the release version\n"
56067812 759 " -R Emit section relative symbol CRCs\n"
78c04153 760#endif /* __GNU_LIBRARY__ */
1da177e4
LT
761 , stderr);
762}
763
78c04153 764int main(int argc, char **argv)
1da177e4 765{
64e6c1e1 766 FILE *dumpfile = NULL, *ref_file = NULL;
78c04153 767 int o;
1da177e4
LT
768
769#ifdef __GNU_LIBRARY__
78c04153 770 struct option long_opts[] = {
78c04153
SR
771 {"debug", 0, 0, 'd'},
772 {"warnings", 0, 0, 'w'},
773 {"quiet", 0, 0, 'q'},
774 {"dump", 0, 0, 'D'},
64e6c1e1 775 {"reference", 1, 0, 'r'},
15fde675 776 {"dump-types", 1, 0, 'T'},
64e6c1e1 777 {"preserve", 0, 0, 'p'},
78c04153
SR
778 {"version", 0, 0, 'V'},
779 {"help", 0, 0, 'h'},
56067812 780 {"relative-crc", 0, 0, 'R'},
78c04153
SR
781 {0, 0, 0, 0}
782 };
783
56067812 784 while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
78c04153
SR
785 &long_opts[0], NULL)) != EOF)
786#else /* __GNU_LIBRARY__ */
56067812 787 while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
78c04153
SR
788#endif /* __GNU_LIBRARY__ */
789 switch (o) {
78c04153
SR
790 case 'd':
791 flag_debug++;
792 break;
793 case 'w':
794 flag_warnings = 1;
795 break;
796 case 'q':
797 flag_warnings = 0;
798 break;
799 case 'V':
800 fputs("genksyms version 2.5.60\n", stderr);
801 break;
802 case 'D':
803 flag_dump_defs = 1;
804 break;
64e6c1e1
AG
805 case 'r':
806 flag_reference = 1;
807 ref_file = fopen(optarg, "r");
808 if (!ref_file) {
809 perror(optarg);
810 return 1;
811 }
812 break;
15fde675
AG
813 case 'T':
814 flag_dump_types = 1;
815 dumpfile = fopen(optarg, "w");
816 if (!dumpfile) {
817 perror(optarg);
818 return 1;
819 }
820 break;
64e6c1e1
AG
821 case 'p':
822 flag_preserve = 1;
823 break;
78c04153
SR
824 case 'h':
825 genksyms_usage();
826 return 0;
56067812
AB
827 case 'R':
828 flag_rel_crcs = 1;
829 break;
78c04153
SR
830 default:
831 genksyms_usage();
832 return 1;
833 }
78c04153
SR
834 {
835 extern int yydebug;
836 extern int yy_flex_debug;
837
838 yydebug = (flag_debug > 1);
839 yy_flex_debug = (flag_debug > 2);
840
841 debugfile = stderr;
842 /* setlinebuf(debugfile); */
843 }
844
c64152bf 845 if (flag_reference) {
64e6c1e1 846 read_reference(ref_file);
c64152bf
AB
847 fclose(ref_file);
848 }
64e6c1e1 849
78c04153
SR
850 yyparse();
851
15fde675
AG
852 if (flag_dump_types && visited_symbols) {
853 while (visited_symbols != (struct symbol *)-1L) {
854 struct symbol *sym = visited_symbols;
855
5dae9a55
AG
856 if (sym->is_override)
857 fputs("override ", dumpfile);
7ec8eda1
MM
858 if (symbol_types[sym->type].n) {
859 putc(symbol_types[sym->type].n, dumpfile);
15fde675
AG
860 putc('#', dumpfile);
861 }
862 fputs(sym->name, dumpfile);
863 putc(' ', dumpfile);
3b40d381
AG
864 if (sym->is_extern)
865 fputs("extern ", dumpfile);
15fde675
AG
866 print_list(dumpfile, sym->defn);
867 putc('\n', dumpfile);
868
869 visited_symbols = sym->visited;
870 sym->visited = NULL;
871 }
872 }
873
78c04153
SR
874 if (flag_debug) {
875 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
876 nsyms, HASH_BUCKETS,
877 (double)nsyms / (double)HASH_BUCKETS);
878 }
879
4deaaa4d
MZ
880 if (dumpfile)
881 fclose(dumpfile);
882
78c04153 883 return errors != 0;
1da177e4 884}