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