blob: b798e284e1fc4aeafca48e5bbb16f03758773711 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* 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>
Sam Ravnborg78c041532006-03-12 22:59:36 +010032#endif /* __GNU_LIBRARY__ */
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#include "genksyms.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035/*----------------------------------------------------------------------*/
36
37#define HASH_BUCKETS 4096
38
39static struct symbol *symtab[HASH_BUCKETS];
40FILE *debugfile;
41
42int cur_line = 1;
43char *cur_filename, *output_directory;
44
45int flag_debug, flag_dump_defs, flag_warnings;
Sam Ravnborgc79c7b02006-03-12 22:54:34 +010046const char *arch = "";
47const char *mod_prefix = "";
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49static int errors;
50static int nsyms;
51
52static struct symbol *expansion_trail;
53
Sam Ravnborg78c041532006-03-12 22:59:36 +010054static const char *const symbol_type_name[] = {
55 "normal", "typedef", "enum", "struct", "union"
Linus Torvalds1da177e2005-04-16 15:20:36 -070056};
57
58/*----------------------------------------------------------------------*/
59
Sam Ravnborg78c041532006-03-12 22:59:36 +010060static const unsigned int crctab32[] = {
61 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
62 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
63 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
64 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
65 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
66 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
67 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
68 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
69 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
70 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
71 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
72 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
73 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
74 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
75 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
76 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
77 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
78 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
79 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
80 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
81 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
82 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
83 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
84 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
85 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
86 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
87 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
88 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
89 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
90 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
91 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
92 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
93 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
94 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
95 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
96 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
97 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
98 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
99 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
100 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
101 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
102 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
103 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
104 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
105 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
106 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
107 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
108 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
109 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
110 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
111 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
112 0x2d02ef8dU
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113};
114
115static inline unsigned long
116partial_crc32_one(unsigned char c, unsigned long crc)
117{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100118 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119}
120
Sam Ravnborg78c041532006-03-12 22:59:36 +0100121static inline unsigned long partial_crc32(const char *s, unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100123 while (*s)
124 crc = partial_crc32_one(*s++, crc);
125 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126}
127
Sam Ravnborg78c041532006-03-12 22:59:36 +0100128static inline unsigned long crc32(const char *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100130 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131}
132
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133/*----------------------------------------------------------------------*/
134
Sam Ravnborg78c041532006-03-12 22:59:36 +0100135static inline enum symbol_type map_to_ns(enum symbol_type t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100137 if (t == SYM_TYPEDEF)
138 t = SYM_NORMAL;
139 else if (t == SYM_UNION)
140 t = SYM_STRUCT;
141 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142}
143
Sam Ravnborg78c041532006-03-12 22:59:36 +0100144struct symbol *find_symbol(const char *name, enum symbol_type ns)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100146 unsigned long h = crc32(name) % HASH_BUCKETS;
147 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
Sam Ravnborg78c041532006-03-12 22:59:36 +0100149 for (sym = symtab[h]; sym; sym = sym->hash_next)
150 if (map_to_ns(sym->type) == map_to_ns(ns)
151 && strcmp(name, sym->name) == 0)
152 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 return sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155}
156
Sam Ravnborg78c041532006-03-12 22:59:36 +0100157struct symbol *add_symbol(const char *name, enum symbol_type type,
158 struct string_list *defn, int is_extern)
159{
160 unsigned long h = crc32(name) % HASH_BUCKETS;
161 struct symbol *sym;
162
163 for (sym = symtab[h]; sym; sym = sym->hash_next)
164 if (map_to_ns(sym->type) == map_to_ns(type)
165 && strcmp(name, sym->name) == 0) {
166 if (!equal_list(sym->defn, defn))
167 error_with_pos("redefinition of %s", name);
168 return sym;
169 }
170
171 sym = xmalloc(sizeof(*sym));
172 sym->name = name;
173 sym->type = type;
174 sym->defn = defn;
175 sym->expansion_trail = NULL;
176 sym->is_extern = is_extern;
177
178 sym->hash_next = symtab[h];
179 symtab[h] = sym;
180
181 if (flag_debug) {
182 fprintf(debugfile, "Defn for %s %s == <",
183 symbol_type_name[type], name);
184 if (is_extern)
185 fputs("extern ", debugfile);
186 print_list(debugfile, defn);
187 fputs(">\n", debugfile);
188 }
189
190 ++nsyms;
191 return sym;
192}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194/*----------------------------------------------------------------------*/
195
Sam Ravnborg78c041532006-03-12 22:59:36 +0100196inline void free_node(struct string_list *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100198 free(node->string);
199 free(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200}
201
Sam Ravnborg78c041532006-03-12 22:59:36 +0100202void free_list(struct string_list *s, struct string_list *e)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100204 while (s != e) {
205 struct string_list *next = s->next;
206 free_node(s);
207 s = next;
208 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209}
210
Sam Ravnborg78c041532006-03-12 22:59:36 +0100211inline struct string_list *copy_node(struct string_list *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100213 struct string_list *newnode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
Sam Ravnborg78c041532006-03-12 22:59:36 +0100215 newnode = xmalloc(sizeof(*newnode));
216 newnode->string = xstrdup(node->string);
217 newnode->tag = node->tag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Sam Ravnborg78c041532006-03-12 22:59:36 +0100219 return newnode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220}
221
Sam Ravnborg78c041532006-03-12 22:59:36 +0100222struct string_list *copy_list(struct string_list *s, struct string_list *e)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100224 struct string_list *h, *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Sam Ravnborg78c041532006-03-12 22:59:36 +0100226 if (s == e)
227 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
Sam Ravnborg78c041532006-03-12 22:59:36 +0100229 p = h = copy_node(s);
230 while ((s = s->next) != e)
231 p = p->next = copy_node(s);
232 p->next = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
Sam Ravnborg78c041532006-03-12 22:59:36 +0100234 return h;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235}
236
Sam Ravnborg78c041532006-03-12 22:59:36 +0100237int equal_list(struct string_list *a, struct string_list *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100239 while (a && b) {
240 if (a->tag != b->tag || strcmp(a->string, b->string))
241 return 0;
242 a = a->next;
243 b = b->next;
244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
Sam Ravnborg78c041532006-03-12 22:59:36 +0100246 return !a && !b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247}
248
Sam Ravnborg78c041532006-03-12 22:59:36 +0100249static inline void print_node(FILE * f, struct string_list *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100251 switch (list->tag) {
252 case SYM_STRUCT:
253 putc('s', f);
254 goto printit;
255 case SYM_UNION:
256 putc('u', f);
257 goto printit;
258 case SYM_ENUM:
259 putc('e', f);
260 goto printit;
261 case SYM_TYPEDEF:
262 putc('t', f);
263 goto printit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Sam Ravnborg78c041532006-03-12 22:59:36 +0100265 printit:
266 putc('#', f);
267 case SYM_NORMAL:
268 fputs(list->string, f);
269 break;
270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271}
272
Sam Ravnborg78c041532006-03-12 22:59:36 +0100273void print_list(FILE * f, struct string_list *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100275 struct string_list **e, **b;
276 struct string_list *tmp, **tmp2;
277 int elem = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Sam Ravnborg78c041532006-03-12 22:59:36 +0100279 if (list == NULL) {
280 fputs("(nil)", f);
281 return;
282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
Sam Ravnborg78c041532006-03-12 22:59:36 +0100284 tmp = list;
285 while ((tmp = tmp->next) != NULL)
286 elem++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Sam Ravnborg78c041532006-03-12 22:59:36 +0100288 b = alloca(elem * sizeof(*e));
289 e = b + elem;
290 tmp2 = e - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
Sam Ravnborg78c041532006-03-12 22:59:36 +0100292 (*tmp2--) = list;
293 while ((list = list->next) != NULL)
294 *(tmp2--) = list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
Sam Ravnborg78c041532006-03-12 22:59:36 +0100296 while (b != e) {
297 print_node(f, *b++);
298 putc(' ', f);
299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300}
301
302static unsigned long
303expand_and_crc_list(struct string_list *list, unsigned long crc)
304{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100305 struct string_list **e, **b;
306 struct string_list *tmp, **tmp2;
307 int elem = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Sam Ravnborg78c041532006-03-12 22:59:36 +0100309 if (!list)
310 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
Sam Ravnborg78c041532006-03-12 22:59:36 +0100312 tmp = list;
313 while ((tmp = tmp->next) != NULL)
314 elem++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
Sam Ravnborg78c041532006-03-12 22:59:36 +0100316 b = alloca(elem * sizeof(*e));
317 e = b + elem;
318 tmp2 = e - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
Sam Ravnborg78c041532006-03-12 22:59:36 +0100320 *(tmp2--) = list;
321 while ((list = list->next) != NULL)
322 *(tmp2--) = list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
Sam Ravnborg78c041532006-03-12 22:59:36 +0100324 while (b != e) {
325 struct string_list *cur;
326 struct symbol *subsym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Sam Ravnborg78c041532006-03-12 22:59:36 +0100328 cur = *(b++);
329 switch (cur->tag) {
330 case SYM_NORMAL:
331 if (flag_dump_defs)
332 fprintf(debugfile, "%s ", cur->string);
333 crc = partial_crc32(cur->string, crc);
334 crc = partial_crc32_one(' ', crc);
335 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
Sam Ravnborg78c041532006-03-12 22:59:36 +0100337 case SYM_TYPEDEF:
338 subsym = find_symbol(cur->string, cur->tag);
339 if (subsym->expansion_trail) {
340 if (flag_dump_defs)
341 fprintf(debugfile, "%s ", cur->string);
342 crc = partial_crc32(cur->string, crc);
343 crc = partial_crc32_one(' ', crc);
344 } else {
345 subsym->expansion_trail = expansion_trail;
346 expansion_trail = subsym;
347 crc = expand_and_crc_list(subsym->defn, crc);
348 }
349 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
Sam Ravnborg78c041532006-03-12 22:59:36 +0100351 case SYM_STRUCT:
352 case SYM_UNION:
353 case SYM_ENUM:
354 subsym = find_symbol(cur->string, cur->tag);
355 if (!subsym) {
356 struct string_list *n, *t = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Sam Ravnborg78c041532006-03-12 22:59:36 +0100358 error_with_pos("expand undefined %s %s",
359 symbol_type_name[cur->tag],
360 cur->string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
Sam Ravnborg78c041532006-03-12 22:59:36 +0100362 n = xmalloc(sizeof(*n));
363 n->string = xstrdup(symbol_type_name[cur->tag]);
364 n->tag = SYM_NORMAL;
365 n->next = t;
366 t = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
Sam Ravnborg78c041532006-03-12 22:59:36 +0100368 n = xmalloc(sizeof(*n));
369 n->string = xstrdup(cur->string);
370 n->tag = SYM_NORMAL;
371 n->next = t;
372 t = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Sam Ravnborg78c041532006-03-12 22:59:36 +0100374 n = xmalloc(sizeof(*n));
375 n->string = xstrdup("{ UNKNOWN }");
376 n->tag = SYM_NORMAL;
377 n->next = t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
Sam Ravnborg78c041532006-03-12 22:59:36 +0100379 subsym =
380 add_symbol(cur->string, cur->tag, n, 0);
381 }
382 if (subsym->expansion_trail) {
383 if (flag_dump_defs) {
384 fprintf(debugfile, "%s %s ",
385 symbol_type_name[cur->tag],
386 cur->string);
387 }
388
389 crc =
390 partial_crc32(symbol_type_name[cur->tag],
391 crc);
392 crc = partial_crc32_one(' ', crc);
393 crc = partial_crc32(cur->string, crc);
394 crc = partial_crc32_one(' ', crc);
395 } else {
396 subsym->expansion_trail = expansion_trail;
397 expansion_trail = subsym;
398 crc = expand_and_crc_list(subsym->defn, crc);
399 }
400 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Sam Ravnborg78c041532006-03-12 22:59:36 +0100404 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405}
406
Sam Ravnborg78c041532006-03-12 22:59:36 +0100407void export_symbol(const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100409 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Sam Ravnborg78c041532006-03-12 22:59:36 +0100411 sym = find_symbol(name, SYM_NORMAL);
412 if (!sym)
413 error_with_pos("export undefined symbol %s", name);
414 else {
415 unsigned long crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
Sam Ravnborg78c041532006-03-12 22:59:36 +0100417 if (flag_dump_defs)
418 fprintf(debugfile, "Export %s == <", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Sam Ravnborg78c041532006-03-12 22:59:36 +0100420 expansion_trail = (struct symbol *)-1L;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Sam Ravnborg78c041532006-03-12 22:59:36 +0100422 crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Sam Ravnborg78c041532006-03-12 22:59:36 +0100424 sym = expansion_trail;
425 while (sym != (struct symbol *)-1L) {
426 struct symbol *n = sym->expansion_trail;
427 sym->expansion_trail = 0;
428 sym = n;
429 }
430
431 if (flag_dump_defs)
432 fputs(">\n", debugfile);
433
434 /* Used as a linker script. */
435 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437}
438
439/*----------------------------------------------------------------------*/
440
Sam Ravnborg78c041532006-03-12 22:59:36 +0100441void error(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100443 va_list args;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
Sam Ravnborg78c041532006-03-12 22:59:36 +0100445 if (flag_warnings) {
446 va_start(args, fmt);
447 vfprintf(stderr, fmt, args);
448 va_end(args);
449 putc('\n', stderr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Sam Ravnborg78c041532006-03-12 22:59:36 +0100451 errors++;
452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453}
454
Sam Ravnborg78c041532006-03-12 22:59:36 +0100455void error_with_pos(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100457 va_list args;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
Sam Ravnborg78c041532006-03-12 22:59:36 +0100459 if (flag_warnings) {
460 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>",
461 cur_line);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
Sam Ravnborg78c041532006-03-12 22:59:36 +0100463 va_start(args, fmt);
464 vfprintf(stderr, fmt, args);
465 va_end(args);
466 putc('\n', stderr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467
Sam Ravnborg78c041532006-03-12 22:59:36 +0100468 errors++;
469 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470}
471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472void genksyms_usage(void)
473{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100474 fputs("Usage:\n" "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" "\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475#ifdef __GNU_LIBRARY__
476 " -d, --debug Increment the debug level (repeatable)\n"
477 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
478 " -w, --warnings Enable warnings\n"
479 " -q, --quiet Disable warnings (default)\n"
480 " -h, --help Print this message\n"
481 " -V, --version Print the release version\n"
Sam Ravnborg78c041532006-03-12 22:59:36 +0100482#else /* __GNU_LIBRARY__ */
483 " -d Increment the debug level (repeatable)\n"
484 " -D Dump expanded symbol defs (for debugging only)\n"
485 " -w Enable warnings\n"
486 " -q Disable warnings (default)\n"
487 " -h Print this message\n"
488 " -V Print the release version\n"
489#endif /* __GNU_LIBRARY__ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 , stderr);
491}
492
Sam Ravnborg78c041532006-03-12 22:59:36 +0100493int main(int argc, char **argv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100495 int o;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
497#ifdef __GNU_LIBRARY__
Sam Ravnborg78c041532006-03-12 22:59:36 +0100498 struct option long_opts[] = {
499 {"arch", 1, 0, 'a'},
500 {"debug", 0, 0, 'd'},
501 {"warnings", 0, 0, 'w'},
502 {"quiet", 0, 0, 'q'},
503 {"dump", 0, 0, 'D'},
504 {"version", 0, 0, 'V'},
505 {"help", 0, 0, 'h'},
506 {0, 0, 0, 0}
507 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
Sam Ravnborg78c041532006-03-12 22:59:36 +0100509 while ((o = getopt_long(argc, argv, "a:dwqVDk:p:",
510 &long_opts[0], NULL)) != EOF)
511#else /* __GNU_LIBRARY__ */
512 while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF)
513#endif /* __GNU_LIBRARY__ */
514 switch (o) {
515 case 'a':
516 arch = optarg;
517 break;
518 case 'd':
519 flag_debug++;
520 break;
521 case 'w':
522 flag_warnings = 1;
523 break;
524 case 'q':
525 flag_warnings = 0;
526 break;
527 case 'V':
528 fputs("genksyms version 2.5.60\n", stderr);
529 break;
530 case 'D':
531 flag_dump_defs = 1;
532 break;
533 case 'h':
534 genksyms_usage();
535 return 0;
536 default:
537 genksyms_usage();
538 return 1;
539 }
540 if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0))
541 mod_prefix = "_";
542 {
543 extern int yydebug;
544 extern int yy_flex_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
Sam Ravnborg78c041532006-03-12 22:59:36 +0100546 yydebug = (flag_debug > 1);
547 yy_flex_debug = (flag_debug > 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Sam Ravnborg78c041532006-03-12 22:59:36 +0100549 debugfile = stderr;
550 /* setlinebuf(debugfile); */
551 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
Sam Ravnborg78c041532006-03-12 22:59:36 +0100553 yyparse();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Sam Ravnborg78c041532006-03-12 22:59:36 +0100555 if (flag_debug) {
556 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
557 nsyms, HASH_BUCKETS,
558 (double)nsyms / (double)HASH_BUCKETS);
559 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Sam Ravnborg78c041532006-03-12 22:59:36 +0100561 return errors != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562}