blob: 5b0344e20d61a028bdf4d1e654f4cf86490cae94 [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];
Sam Ravnborgce560682006-03-12 23:26:29 +010040static FILE *debugfile;
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42int cur_line = 1;
Sam Ravnborgce560682006-03-12 23:26:29 +010043char *cur_filename;
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Sam Ravnborgce560682006-03-12 23:26:29 +010045static int flag_debug, flag_dump_defs, flag_warnings;
46static const char *arch = "";
47static const 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
Sam Ravnborgce560682006-03-12 23:26:29 +010058static int equal_list(struct string_list *a, struct string_list *b);
59static void print_list(FILE * f, struct string_list *list);
60
Linus Torvalds1da177e2005-04-16 15:20:36 -070061/*----------------------------------------------------------------------*/
62
Sam Ravnborg78c041532006-03-12 22:59:36 +010063static const unsigned int crctab32[] = {
64 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
65 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
66 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
67 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
68 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
69 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
70 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
71 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
72 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
73 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
74 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
75 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
76 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
77 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
78 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
79 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
80 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
81 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
82 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
83 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
84 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
85 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
86 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
87 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
88 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
89 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
90 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
91 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
92 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
93 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
94 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
95 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
96 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
97 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
98 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
99 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
100 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
101 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
102 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
103 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
104 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
105 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
106 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
107 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
108 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
109 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
110 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
111 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
112 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
113 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
114 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
115 0x2d02ef8dU
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116};
117
Sam Ravnborgce560682006-03-12 23:26:29 +0100118static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100120 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121}
122
Sam Ravnborgce560682006-03-12 23:26:29 +0100123static unsigned long partial_crc32(const char *s, unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100125 while (*s)
126 crc = partial_crc32_one(*s++, crc);
127 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128}
129
Sam Ravnborgce560682006-03-12 23:26:29 +0100130static unsigned long crc32(const char *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100132 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133}
134
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135/*----------------------------------------------------------------------*/
136
Sam Ravnborgce560682006-03-12 23:26:29 +0100137static enum symbol_type map_to_ns(enum symbol_type t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100139 if (t == SYM_TYPEDEF)
140 t = SYM_NORMAL;
141 else if (t == SYM_UNION)
142 t = SYM_STRUCT;
143 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144}
145
Sam Ravnborg78c041532006-03-12 22:59:36 +0100146struct symbol *find_symbol(const char *name, enum symbol_type ns)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100148 unsigned long h = crc32(name) % HASH_BUCKETS;
149 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Sam Ravnborg78c041532006-03-12 22:59:36 +0100151 for (sym = symtab[h]; sym; sym = sym->hash_next)
Sam Ravnborgce560682006-03-12 23:26:29 +0100152 if (map_to_ns(sym->type) == map_to_ns(ns) &&
153 strcmp(name, sym->name) == 0)
Sam Ravnborg78c041532006-03-12 22:59:36 +0100154 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 return sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157}
158
Sam Ravnborg78c041532006-03-12 22:59:36 +0100159struct symbol *add_symbol(const char *name, enum symbol_type type,
160 struct string_list *defn, int is_extern)
161{
162 unsigned long h = crc32(name) % HASH_BUCKETS;
163 struct symbol *sym;
164
Sam Ravnborgce560682006-03-12 23:26:29 +0100165 for (sym = symtab[h]; sym; sym = sym->hash_next) {
Sam Ravnborg78c041532006-03-12 22:59:36 +0100166 if (map_to_ns(sym->type) == map_to_ns(type)
167 && strcmp(name, sym->name) == 0) {
168 if (!equal_list(sym->defn, defn))
169 error_with_pos("redefinition of %s", name);
170 return sym;
171 }
Sam Ravnborgce560682006-03-12 23:26:29 +0100172 }
Sam Ravnborg78c041532006-03-12 22:59:36 +0100173
174 sym = xmalloc(sizeof(*sym));
175 sym->name = name;
176 sym->type = type;
177 sym->defn = defn;
178 sym->expansion_trail = NULL;
179 sym->is_extern = is_extern;
180
181 sym->hash_next = symtab[h];
182 symtab[h] = sym;
183
184 if (flag_debug) {
185 fprintf(debugfile, "Defn for %s %s == <",
186 symbol_type_name[type], name);
187 if (is_extern)
188 fputs("extern ", debugfile);
189 print_list(debugfile, defn);
190 fputs(">\n", debugfile);
191 }
192
193 ++nsyms;
194 return sym;
195}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
197/*----------------------------------------------------------------------*/
198
Sam Ravnborgce560682006-03-12 23:26:29 +0100199void free_node(struct string_list *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100201 free(node->string);
202 free(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203}
204
Sam Ravnborg78c041532006-03-12 22:59:36 +0100205void free_list(struct string_list *s, struct string_list *e)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100207 while (s != e) {
208 struct string_list *next = s->next;
209 free_node(s);
210 s = next;
211 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212}
213
Sam Ravnborgce560682006-03-12 23:26:29 +0100214struct string_list *copy_node(struct string_list *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100216 struct string_list *newnode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Sam Ravnborg78c041532006-03-12 22:59:36 +0100218 newnode = xmalloc(sizeof(*newnode));
219 newnode->string = xstrdup(node->string);
220 newnode->tag = node->tag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
Sam Ravnborg78c041532006-03-12 22:59:36 +0100222 return newnode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223}
224
Sam Ravnborgce560682006-03-12 23:26:29 +0100225static int equal_list(struct string_list *a, struct string_list *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100227 while (a && b) {
228 if (a->tag != b->tag || strcmp(a->string, b->string))
229 return 0;
230 a = a->next;
231 b = b->next;
232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
Sam Ravnborg78c041532006-03-12 22:59:36 +0100234 return !a && !b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235}
236
Sam Ravnborgce560682006-03-12 23:26:29 +0100237static void print_node(FILE * f, struct string_list *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100239 switch (list->tag) {
240 case SYM_STRUCT:
241 putc('s', f);
242 goto printit;
243 case SYM_UNION:
244 putc('u', f);
245 goto printit;
246 case SYM_ENUM:
247 putc('e', f);
248 goto printit;
249 case SYM_TYPEDEF:
250 putc('t', f);
251 goto printit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Sam Ravnborg78c041532006-03-12 22:59:36 +0100253 printit:
254 putc('#', f);
255 case SYM_NORMAL:
256 fputs(list->string, f);
257 break;
258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259}
260
Sam Ravnborgce560682006-03-12 23:26:29 +0100261static void print_list(FILE * f, struct string_list *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100263 struct string_list **e, **b;
264 struct string_list *tmp, **tmp2;
265 int elem = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
Sam Ravnborg78c041532006-03-12 22:59:36 +0100267 if (list == NULL) {
268 fputs("(nil)", f);
269 return;
270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
Sam Ravnborg78c041532006-03-12 22:59:36 +0100272 tmp = list;
273 while ((tmp = tmp->next) != NULL)
274 elem++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Sam Ravnborg78c041532006-03-12 22:59:36 +0100276 b = alloca(elem * sizeof(*e));
277 e = b + elem;
278 tmp2 = e - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Sam Ravnborg78c041532006-03-12 22:59:36 +0100280 (*tmp2--) = list;
281 while ((list = list->next) != NULL)
282 *(tmp2--) = list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
Sam Ravnborg78c041532006-03-12 22:59:36 +0100284 while (b != e) {
285 print_node(f, *b++);
286 putc(' ', f);
287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288}
289
Sam Ravnborgce560682006-03-12 23:26:29 +0100290static unsigned long expand_and_crc_list(struct string_list *list,
291 unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100293 struct string_list **e, **b;
294 struct string_list *tmp, **tmp2;
295 int elem = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Sam Ravnborg78c041532006-03-12 22:59:36 +0100297 if (!list)
298 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
Sam Ravnborg78c041532006-03-12 22:59:36 +0100300 tmp = list;
301 while ((tmp = tmp->next) != NULL)
302 elem++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Sam Ravnborg78c041532006-03-12 22:59:36 +0100304 b = alloca(elem * sizeof(*e));
305 e = b + elem;
306 tmp2 = e - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Sam Ravnborg78c041532006-03-12 22:59:36 +0100308 *(tmp2--) = list;
309 while ((list = list->next) != NULL)
310 *(tmp2--) = list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
Sam Ravnborg78c041532006-03-12 22:59:36 +0100312 while (b != e) {
313 struct string_list *cur;
314 struct symbol *subsym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
Sam Ravnborg78c041532006-03-12 22:59:36 +0100316 cur = *(b++);
317 switch (cur->tag) {
318 case SYM_NORMAL:
319 if (flag_dump_defs)
320 fprintf(debugfile, "%s ", cur->string);
321 crc = partial_crc32(cur->string, crc);
322 crc = partial_crc32_one(' ', crc);
323 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Sam Ravnborg78c041532006-03-12 22:59:36 +0100325 case SYM_TYPEDEF:
326 subsym = find_symbol(cur->string, cur->tag);
327 if (subsym->expansion_trail) {
328 if (flag_dump_defs)
329 fprintf(debugfile, "%s ", cur->string);
330 crc = partial_crc32(cur->string, crc);
331 crc = partial_crc32_one(' ', crc);
332 } else {
333 subsym->expansion_trail = expansion_trail;
334 expansion_trail = subsym;
335 crc = expand_and_crc_list(subsym->defn, crc);
336 }
337 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Sam Ravnborg78c041532006-03-12 22:59:36 +0100339 case SYM_STRUCT:
340 case SYM_UNION:
341 case SYM_ENUM:
342 subsym = find_symbol(cur->string, cur->tag);
343 if (!subsym) {
344 struct string_list *n, *t = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
Sam Ravnborg78c041532006-03-12 22:59:36 +0100346 error_with_pos("expand undefined %s %s",
347 symbol_type_name[cur->tag],
348 cur->string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
Sam Ravnborg78c041532006-03-12 22:59:36 +0100350 n = xmalloc(sizeof(*n));
351 n->string = xstrdup(symbol_type_name[cur->tag]);
352 n->tag = SYM_NORMAL;
353 n->next = t;
354 t = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
Sam Ravnborg78c041532006-03-12 22:59:36 +0100356 n = xmalloc(sizeof(*n));
357 n->string = xstrdup(cur->string);
358 n->tag = SYM_NORMAL;
359 n->next = t;
360 t = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
Sam Ravnborg78c041532006-03-12 22:59:36 +0100362 n = xmalloc(sizeof(*n));
363 n->string = xstrdup("{ UNKNOWN }");
364 n->tag = SYM_NORMAL;
365 n->next = t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Sam Ravnborg78c041532006-03-12 22:59:36 +0100367 subsym =
368 add_symbol(cur->string, cur->tag, n, 0);
369 }
370 if (subsym->expansion_trail) {
371 if (flag_dump_defs) {
372 fprintf(debugfile, "%s %s ",
373 symbol_type_name[cur->tag],
374 cur->string);
375 }
376
Sam Ravnborgce560682006-03-12 23:26:29 +0100377 crc = partial_crc32(symbol_type_name[cur->tag],
378 crc);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100379 crc = partial_crc32_one(' ', crc);
380 crc = partial_crc32(cur->string, crc);
381 crc = partial_crc32_one(' ', crc);
382 } else {
383 subsym->expansion_trail = expansion_trail;
384 expansion_trail = subsym;
385 crc = expand_and_crc_list(subsym->defn, crc);
386 }
387 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Sam Ravnborg78c041532006-03-12 22:59:36 +0100391 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392}
393
Sam Ravnborg78c041532006-03-12 22:59:36 +0100394void export_symbol(const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100396 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Sam Ravnborg78c041532006-03-12 22:59:36 +0100398 sym = find_symbol(name, SYM_NORMAL);
399 if (!sym)
400 error_with_pos("export undefined symbol %s", name);
401 else {
402 unsigned long crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Sam Ravnborg78c041532006-03-12 22:59:36 +0100404 if (flag_dump_defs)
405 fprintf(debugfile, "Export %s == <", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
Sam Ravnborg78c041532006-03-12 22:59:36 +0100407 expansion_trail = (struct symbol *)-1L;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Sam Ravnborg78c041532006-03-12 22:59:36 +0100409 crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Sam Ravnborg78c041532006-03-12 22:59:36 +0100411 sym = expansion_trail;
412 while (sym != (struct symbol *)-1L) {
413 struct symbol *n = sym->expansion_trail;
414 sym->expansion_trail = 0;
415 sym = n;
416 }
417
418 if (flag_dump_defs)
419 fputs(">\n", debugfile);
420
421 /* Used as a linker script. */
422 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424}
425
426/*----------------------------------------------------------------------*/
Sam Ravnborg78c041532006-03-12 22:59:36 +0100427void error_with_pos(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100429 va_list args;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Sam Ravnborg78c041532006-03-12 22:59:36 +0100431 if (flag_warnings) {
432 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>",
433 cur_line);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Sam Ravnborg78c041532006-03-12 22:59:36 +0100435 va_start(args, fmt);
436 vfprintf(stderr, fmt, args);
437 va_end(args);
438 putc('\n', stderr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Sam Ravnborg78c041532006-03-12 22:59:36 +0100440 errors++;
441 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442}
443
Sam Ravnborgce560682006-03-12 23:26:29 +0100444static void genksyms_usage(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100446 fputs("Usage:\n" "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" "\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447#ifdef __GNU_LIBRARY__
448 " -d, --debug Increment the debug level (repeatable)\n"
449 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
450 " -w, --warnings Enable warnings\n"
451 " -q, --quiet Disable warnings (default)\n"
452 " -h, --help Print this message\n"
453 " -V, --version Print the release version\n"
Sam Ravnborg78c041532006-03-12 22:59:36 +0100454#else /* __GNU_LIBRARY__ */
455 " -d Increment the debug level (repeatable)\n"
456 " -D Dump expanded symbol defs (for debugging only)\n"
457 " -w Enable warnings\n"
458 " -q Disable warnings (default)\n"
459 " -h Print this message\n"
460 " -V Print the release version\n"
461#endif /* __GNU_LIBRARY__ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 , stderr);
463}
464
Sam Ravnborg78c041532006-03-12 22:59:36 +0100465int main(int argc, char **argv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100467 int o;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
469#ifdef __GNU_LIBRARY__
Sam Ravnborg78c041532006-03-12 22:59:36 +0100470 struct option long_opts[] = {
471 {"arch", 1, 0, 'a'},
472 {"debug", 0, 0, 'd'},
473 {"warnings", 0, 0, 'w'},
474 {"quiet", 0, 0, 'q'},
475 {"dump", 0, 0, 'D'},
476 {"version", 0, 0, 'V'},
477 {"help", 0, 0, 'h'},
478 {0, 0, 0, 0}
479 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
Sam Ravnborg78c041532006-03-12 22:59:36 +0100481 while ((o = getopt_long(argc, argv, "a:dwqVDk:p:",
482 &long_opts[0], NULL)) != EOF)
483#else /* __GNU_LIBRARY__ */
484 while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF)
485#endif /* __GNU_LIBRARY__ */
486 switch (o) {
487 case 'a':
488 arch = optarg;
489 break;
490 case 'd':
491 flag_debug++;
492 break;
493 case 'w':
494 flag_warnings = 1;
495 break;
496 case 'q':
497 flag_warnings = 0;
498 break;
499 case 'V':
500 fputs("genksyms version 2.5.60\n", stderr);
501 break;
502 case 'D':
503 flag_dump_defs = 1;
504 break;
505 case 'h':
506 genksyms_usage();
507 return 0;
508 default:
509 genksyms_usage();
510 return 1;
511 }
512 if ((strcmp(arch, "v850") == 0) || (strcmp(arch, "h8300") == 0))
513 mod_prefix = "_";
514 {
515 extern int yydebug;
516 extern int yy_flex_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
Sam Ravnborg78c041532006-03-12 22:59:36 +0100518 yydebug = (flag_debug > 1);
519 yy_flex_debug = (flag_debug > 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
Sam Ravnborg78c041532006-03-12 22:59:36 +0100521 debugfile = stderr;
522 /* setlinebuf(debugfile); */
523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Sam Ravnborg78c041532006-03-12 22:59:36 +0100525 yyparse();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
Sam Ravnborg78c041532006-03-12 22:59:36 +0100527 if (flag_debug) {
528 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
529 nsyms, HASH_BUCKETS,
530 (double)nsyms / (double)HASH_BUCKETS);
531 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
Sam Ravnborg78c041532006-03-12 22:59:36 +0100533 return errors != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534}