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