blob: 8a106499ec4fd627c183dc12eac1a607f2fabd80 [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;
Michal Marek2c5925d2011-10-08 01:18:35 +020043char *cur_filename, *source_file;
44int in_source_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -080046static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
Sam Ravnborg2ea03892009-01-14 21:38:20 +010047 flag_preserve, flag_warnings;
Sam Ravnborgce560682006-03-12 23:26:29 +010048static const char *arch = "";
49static const char *mod_prefix = "";
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51static int errors;
52static int nsyms;
53
54static struct symbol *expansion_trail;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +020055static struct symbol *visited_symbols;
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
Michal Marek7ec8eda2011-01-18 16:28:06 +010057static const struct {
58 int n;
59 const char *name;
60} symbol_types[] = {
61 [SYM_NORMAL] = { 0, NULL},
62 [SYM_TYPEDEF] = {'t', "typedef"},
63 [SYM_ENUM] = {'e', "enum"},
64 [SYM_STRUCT] = {'s', "struct"},
65 [SYM_UNION] = {'u', "union"},
Michal Mareke37ddb82011-02-03 23:57:09 +010066 [SYM_ENUM_CONST] = {'E', "enum constant"},
Linus Torvalds1da177e2005-04-16 15:20:36 -070067};
68
Sam Ravnborgce560682006-03-12 23:26:29 +010069static int equal_list(struct string_list *a, struct string_list *b);
70static void print_list(FILE * f, struct string_list *list);
Michal Marek68eb8562011-02-02 23:52:13 +010071static struct string_list *concat_list(struct string_list *start, ...);
72static struct string_list *mk_node(const char *string);
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -080073static void print_location(void);
74static void print_type_name(enum symbol_type type, const char *name);
Sam Ravnborgce560682006-03-12 23:26:29 +010075
Linus Torvalds1da177e2005-04-16 15:20:36 -070076/*----------------------------------------------------------------------*/
77
Sam Ravnborg78c041532006-03-12 22:59:36 +010078static const unsigned int crctab32[] = {
79 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
80 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
81 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
82 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
83 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
84 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
85 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
86 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
87 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
88 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
89 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
90 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
91 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
92 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
93 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
94 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
95 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
96 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
97 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
98 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
99 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
100 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
101 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
102 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
103 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
104 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
105 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
106 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
107 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
108 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
109 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
110 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
111 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
112 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
113 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
114 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
115 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
116 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
117 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
118 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
119 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
120 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
121 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
122 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
123 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
124 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
125 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
126 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
127 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
128 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
129 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
130 0x2d02ef8dU
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131};
132
Sam Ravnborgce560682006-03-12 23:26:29 +0100133static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100135 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136}
137
Sam Ravnborgce560682006-03-12 23:26:29 +0100138static unsigned long partial_crc32(const char *s, unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100140 while (*s)
141 crc = partial_crc32_one(*s++, crc);
142 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143}
144
Sam Ravnborgce560682006-03-12 23:26:29 +0100145static unsigned long crc32(const char *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100147 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148}
149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150/*----------------------------------------------------------------------*/
151
Sam Ravnborgce560682006-03-12 23:26:29 +0100152static enum symbol_type map_to_ns(enum symbol_type t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153{
Michal Mareke37ddb82011-02-03 23:57:09 +0100154 switch (t) {
155 case SYM_ENUM_CONST:
156 case SYM_NORMAL:
157 case SYM_TYPEDEF:
158 return SYM_NORMAL;
159 case SYM_ENUM:
160 case SYM_STRUCT:
161 case SYM_UNION:
162 return SYM_STRUCT;
163 }
Sam Ravnborg78c041532006-03-12 22:59:36 +0100164 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165}
166
Michal Marek01762c42011-02-15 15:11:36 +0100167struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100169 unsigned long h = crc32(name) % HASH_BUCKETS;
170 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Sam Ravnborg78c041532006-03-12 22:59:36 +0100172 for (sym = symtab[h]; sym; sym = sym->hash_next)
Sam Ravnborgce560682006-03-12 23:26:29 +0100173 if (map_to_ns(sym->type) == map_to_ns(ns) &&
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800174 strcmp(name, sym->name) == 0 &&
175 sym->is_declared)
Sam Ravnborg78c041532006-03-12 22:59:36 +0100176 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
Michal Marek01762c42011-02-15 15:11:36 +0100178 if (exact && sym && sym->type != ns)
179 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 return sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181}
182
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800183static int is_unknown_symbol(struct symbol *sym)
184{
185 struct string_list *defn;
186
187 return ((sym->type == SYM_STRUCT ||
188 sym->type == SYM_UNION ||
189 sym->type == SYM_ENUM) &&
190 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
191 strcmp(defn->string, "}") == 0 &&
192 (defn = defn->next) && defn->tag == SYM_NORMAL &&
193 strcmp(defn->string, "UNKNOWN") == 0 &&
194 (defn = defn->next) && defn->tag == SYM_NORMAL &&
195 strcmp(defn->string, "{") == 0);
196}
197
Ladinu Chandrasingheb7ed6982009-09-22 16:43:42 -0700198static struct symbol *__add_symbol(const char *name, enum symbol_type type,
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800199 struct string_list *defn, int is_extern,
200 int is_reference)
Sam Ravnborg78c041532006-03-12 22:59:36 +0100201{
Michal Mareke37ddb82011-02-03 23:57:09 +0100202 unsigned long h;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100203 struct symbol *sym;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800204 enum symbol_status status = STATUS_UNCHANGED;
Michal Mareke37ddb82011-02-03 23:57:09 +0100205 /* The parser adds symbols in the order their declaration completes,
206 * so it is safe to store the value of the previous enum constant in
207 * a static variable.
208 */
209 static int enum_counter;
210 static struct string_list *last_enum_expr;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100211
Michal Mareke37ddb82011-02-03 23:57:09 +0100212 if (type == SYM_ENUM_CONST) {
213 if (defn) {
214 free_list(last_enum_expr, NULL);
215 last_enum_expr = copy_list_range(defn, NULL);
216 enum_counter = 1;
217 } else {
218 struct string_list *expr;
219 char buf[20];
220
221 snprintf(buf, sizeof(buf), "%d", enum_counter++);
222 if (last_enum_expr) {
223 expr = copy_list_range(last_enum_expr, NULL);
224 defn = concat_list(mk_node("("),
225 expr,
226 mk_node(")"),
227 mk_node("+"),
228 mk_node(buf), NULL);
229 } else {
230 defn = mk_node(buf);
231 }
232 }
233 } else if (type == SYM_ENUM) {
234 free_list(last_enum_expr, NULL);
235 last_enum_expr = NULL;
236 enum_counter = 0;
237 if (!name)
238 /* Anonymous enum definition, nothing more to do */
239 return NULL;
240 }
241
242 h = crc32(name) % HASH_BUCKETS;
Sam Ravnborgce560682006-03-12 23:26:29 +0100243 for (sym = symtab[h]; sym; sym = sym->hash_next) {
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800244 if (map_to_ns(sym->type) == map_to_ns(type) &&
245 strcmp(name, sym->name) == 0) {
246 if (is_reference)
247 /* fall through */ ;
248 else if (sym->type == type &&
249 equal_list(sym->defn, defn)) {
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800250 if (!sym->is_declared && sym->is_override) {
251 print_location();
252 print_type_name(type, name);
253 fprintf(stderr, " modversion is "
254 "unchanged\n");
255 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800256 sym->is_declared = 1;
257 return sym;
258 } else if (!sym->is_declared) {
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800259 if (sym->is_override && flag_preserve) {
260 print_location();
261 fprintf(stderr, "ignoring ");
262 print_type_name(type, name);
263 fprintf(stderr, " modversion change\n");
264 sym->is_declared = 1;
265 return sym;
266 } else {
267 status = is_unknown_symbol(sym) ?
268 STATUS_DEFINED : STATUS_MODIFIED;
269 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800270 } else {
Sam Ravnborg78c041532006-03-12 22:59:36 +0100271 error_with_pos("redefinition of %s", name);
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800272 return sym;
273 }
274 break;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100275 }
Sam Ravnborgce560682006-03-12 23:26:29 +0100276 }
Sam Ravnborg78c041532006-03-12 22:59:36 +0100277
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800278 if (sym) {
279 struct symbol **psym;
280
281 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
282 if (*psym == sym) {
283 *psym = sym->hash_next;
284 break;
285 }
286 }
287 --nsyms;
288 }
289
Sam Ravnborg78c041532006-03-12 22:59:36 +0100290 sym = xmalloc(sizeof(*sym));
291 sym->name = name;
292 sym->type = type;
293 sym->defn = defn;
294 sym->expansion_trail = NULL;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200295 sym->visited = NULL;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100296 sym->is_extern = is_extern;
297
298 sym->hash_next = symtab[h];
299 symtab[h] = sym;
300
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800301 sym->is_declared = !is_reference;
302 sym->status = status;
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800303 sym->is_override = 0;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800304
Sam Ravnborg78c041532006-03-12 22:59:36 +0100305 if (flag_debug) {
Michal Marek7ec8eda2011-01-18 16:28:06 +0100306 if (symbol_types[type].name)
307 fprintf(debugfile, "Defn for %s %s == <",
308 symbol_types[type].name, name);
309 else
310 fprintf(debugfile, "Defn for type%d %s == <",
311 type, name);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100312 if (is_extern)
313 fputs("extern ", debugfile);
314 print_list(debugfile, defn);
315 fputs(">\n", debugfile);
316 }
317
318 ++nsyms;
319 return sym;
320}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800322struct symbol *add_symbol(const char *name, enum symbol_type type,
323 struct string_list *defn, int is_extern)
324{
325 return __add_symbol(name, type, defn, is_extern, 0);
326}
327
Ladinu Chandrasingheb7ed6982009-09-22 16:43:42 -0700328static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800329 struct string_list *defn, int is_extern)
330{
331 return __add_symbol(name, type, defn, is_extern, 1);
332}
333
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334/*----------------------------------------------------------------------*/
335
Sam Ravnborgce560682006-03-12 23:26:29 +0100336void free_node(struct string_list *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100338 free(node->string);
339 free(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340}
341
Sam Ravnborg78c041532006-03-12 22:59:36 +0100342void free_list(struct string_list *s, struct string_list *e)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100344 while (s != e) {
345 struct string_list *next = s->next;
346 free_node(s);
347 s = next;
348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349}
350
Michal Marek68eb8562011-02-02 23:52:13 +0100351static struct string_list *mk_node(const char *string)
352{
353 struct string_list *newnode;
354
355 newnode = xmalloc(sizeof(*newnode));
356 newnode->string = xstrdup(string);
357 newnode->tag = SYM_NORMAL;
358 newnode->next = NULL;
359
360 return newnode;
361}
362
363static struct string_list *concat_list(struct string_list *start, ...)
364{
365 va_list ap;
366 struct string_list *n, *n2;
367
368 if (!start)
369 return NULL;
370 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
371 for (n2 = n; n2->next; n2 = n2->next)
372 ;
373 n2->next = start;
374 start = n;
375 }
376 va_end(ap);
377 return start;
378}
379
Sam Ravnborgce560682006-03-12 23:26:29 +0100380struct string_list *copy_node(struct string_list *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100382 struct string_list *newnode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Sam Ravnborg78c041532006-03-12 22:59:36 +0100384 newnode = xmalloc(sizeof(*newnode));
385 newnode->string = xstrdup(node->string);
386 newnode->tag = node->tag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Sam Ravnborg78c041532006-03-12 22:59:36 +0100388 return newnode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389}
390
Michal Mareke37ddb82011-02-03 23:57:09 +0100391struct string_list *copy_list_range(struct string_list *start,
392 struct string_list *end)
393{
394 struct string_list *res, *n;
395
396 if (start == end)
397 return NULL;
398 n = res = copy_node(start);
399 for (start = start->next; start != end; start = start->next) {
400 n->next = copy_node(start);
401 n = n->next;
402 }
403 n->next = NULL;
404 return res;
405}
406
Sam Ravnborgce560682006-03-12 23:26:29 +0100407static int equal_list(struct string_list *a, struct string_list *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100409 while (a && b) {
410 if (a->tag != b->tag || strcmp(a->string, b->string))
411 return 0;
412 a = a->next;
413 b = b->next;
414 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Sam Ravnborg78c041532006-03-12 22:59:36 +0100416 return !a && !b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417}
418
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800419#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
420
Ladinu Chandrasingheb7ed6982009-09-22 16:43:42 -0700421static struct string_list *read_node(FILE *f)
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800422{
423 char buffer[256];
424 struct string_list node = {
425 .string = buffer,
426 .tag = SYM_NORMAL };
427 int c;
428
429 while ((c = fgetc(f)) != EOF) {
430 if (c == ' ') {
431 if (node.string == buffer)
432 continue;
433 break;
434 } else if (c == '\n') {
435 if (node.string == buffer)
436 return NULL;
437 ungetc(c, f);
438 break;
439 }
440 if (node.string >= buffer + sizeof(buffer) - 1) {
441 fprintf(stderr, "Token too long\n");
442 exit(1);
443 }
444 *node.string++ = c;
445 }
446 if (node.string == buffer)
447 return NULL;
448 *node.string = 0;
449 node.string = buffer;
450
451 if (node.string[1] == '#') {
Jesper Juhl1ae14702011-07-12 00:32:04 +0200452 size_t n;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800453
Michal Marek7ec8eda2011-01-18 16:28:06 +0100454 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
455 if (node.string[0] == symbol_types[n].n) {
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800456 node.tag = n;
457 node.string += 2;
458 return copy_node(&node);
459 }
460 }
461 fprintf(stderr, "Unknown type %c\n", node.string[0]);
462 exit(1);
463 }
464 return copy_node(&node);
465}
466
467static void read_reference(FILE *f)
468{
469 while (!feof(f)) {
470 struct string_list *defn = NULL;
471 struct string_list *sym, *def;
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800472 int is_extern = 0, is_override = 0;
473 struct symbol *subsym;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800474
475 sym = read_node(f);
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800476 if (sym && sym->tag == SYM_NORMAL &&
477 !strcmp(sym->string, "override")) {
478 is_override = 1;
479 free_node(sym);
480 sym = read_node(f);
481 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800482 if (!sym)
483 continue;
484 def = read_node(f);
485 if (def && def->tag == SYM_NORMAL &&
486 !strcmp(def->string, "extern")) {
487 is_extern = 1;
488 free_node(def);
489 def = read_node(f);
490 }
491 while (def) {
492 def->next = defn;
493 defn = def;
494 def = read_node(f);
495 }
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800496 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800497 defn, is_extern);
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800498 subsym->is_override = is_override;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800499 free_node(sym);
500 }
501}
502
Sam Ravnborgce560682006-03-12 23:26:29 +0100503static void print_node(FILE * f, struct string_list *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
Michal Marek7ec8eda2011-01-18 16:28:06 +0100505 if (symbol_types[list->tag].n) {
506 putc(symbol_types[list->tag].n, f);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100507 putc('#', f);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100508 }
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200509 fputs(list->string, f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510}
511
Sam Ravnborgce560682006-03-12 23:26:29 +0100512static void print_list(FILE * f, struct string_list *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100514 struct string_list **e, **b;
515 struct string_list *tmp, **tmp2;
516 int elem = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
Sam Ravnborg78c041532006-03-12 22:59:36 +0100518 if (list == NULL) {
519 fputs("(nil)", f);
520 return;
521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
Sam Ravnborg78c041532006-03-12 22:59:36 +0100523 tmp = list;
524 while ((tmp = tmp->next) != NULL)
525 elem++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
Sam Ravnborg78c041532006-03-12 22:59:36 +0100527 b = alloca(elem * sizeof(*e));
528 e = b + elem;
529 tmp2 = e - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
Sam Ravnborg78c041532006-03-12 22:59:36 +0100531 (*tmp2--) = list;
532 while ((list = list->next) != NULL)
533 *(tmp2--) = list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
Sam Ravnborg78c041532006-03-12 22:59:36 +0100535 while (b != e) {
536 print_node(f, *b++);
537 putc(' ', f);
538 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539}
540
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200541static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542{
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200543 struct string_list *list = sym->defn;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100544 struct string_list **e, **b;
545 struct string_list *tmp, **tmp2;
546 int elem = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Sam Ravnborg78c041532006-03-12 22:59:36 +0100548 if (!list)
549 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Sam Ravnborg78c041532006-03-12 22:59:36 +0100551 tmp = list;
552 while ((tmp = tmp->next) != NULL)
553 elem++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Sam Ravnborg78c041532006-03-12 22:59:36 +0100555 b = alloca(elem * sizeof(*e));
556 e = b + elem;
557 tmp2 = e - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
Sam Ravnborg78c041532006-03-12 22:59:36 +0100559 *(tmp2--) = list;
560 while ((list = list->next) != NULL)
561 *(tmp2--) = list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
Sam Ravnborg78c041532006-03-12 22:59:36 +0100563 while (b != e) {
564 struct string_list *cur;
565 struct symbol *subsym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Sam Ravnborg78c041532006-03-12 22:59:36 +0100567 cur = *(b++);
568 switch (cur->tag) {
569 case SYM_NORMAL:
570 if (flag_dump_defs)
571 fprintf(debugfile, "%s ", cur->string);
572 crc = partial_crc32(cur->string, crc);
573 crc = partial_crc32_one(' ', crc);
574 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
Michal Mareke37ddb82011-02-03 23:57:09 +0100576 case SYM_ENUM_CONST:
Sam Ravnborg78c041532006-03-12 22:59:36 +0100577 case SYM_TYPEDEF:
Michal Marek01762c42011-02-15 15:11:36 +0100578 subsym = find_symbol(cur->string, cur->tag, 0);
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800579 /* FIXME: Bad reference files can segfault here. */
Sam Ravnborg78c041532006-03-12 22:59:36 +0100580 if (subsym->expansion_trail) {
581 if (flag_dump_defs)
582 fprintf(debugfile, "%s ", cur->string);
583 crc = partial_crc32(cur->string, crc);
584 crc = partial_crc32_one(' ', crc);
585 } else {
586 subsym->expansion_trail = expansion_trail;
587 expansion_trail = subsym;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200588 crc = expand_and_crc_sym(subsym, crc);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100589 }
590 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
Sam Ravnborg78c041532006-03-12 22:59:36 +0100592 case SYM_STRUCT:
593 case SYM_UNION:
594 case SYM_ENUM:
Michal Marek01762c42011-02-15 15:11:36 +0100595 subsym = find_symbol(cur->string, cur->tag, 0);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100596 if (!subsym) {
Michal Marek68eb8562011-02-02 23:52:13 +0100597 struct string_list *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
Sam Ravnborg78c041532006-03-12 22:59:36 +0100599 error_with_pos("expand undefined %s %s",
Michal Marek7ec8eda2011-01-18 16:28:06 +0100600 symbol_types[cur->tag].name,
Sam Ravnborg78c041532006-03-12 22:59:36 +0100601 cur->string);
Michal Marek68eb8562011-02-02 23:52:13 +0100602 n = concat_list(mk_node
603 (symbol_types[cur->tag].name),
604 mk_node(cur->string),
605 mk_node("{"),
606 mk_node("UNKNOWN"),
607 mk_node("}"), NULL);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100608 subsym =
609 add_symbol(cur->string, cur->tag, n, 0);
610 }
611 if (subsym->expansion_trail) {
612 if (flag_dump_defs) {
613 fprintf(debugfile, "%s %s ",
Michal Marek7ec8eda2011-01-18 16:28:06 +0100614 symbol_types[cur->tag].name,
Sam Ravnborg78c041532006-03-12 22:59:36 +0100615 cur->string);
616 }
617
Michal Marek7ec8eda2011-01-18 16:28:06 +0100618 crc = partial_crc32(symbol_types[cur->tag].name,
Sam Ravnborgce560682006-03-12 23:26:29 +0100619 crc);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100620 crc = partial_crc32_one(' ', crc);
621 crc = partial_crc32(cur->string, crc);
622 crc = partial_crc32_one(' ', crc);
623 } else {
624 subsym->expansion_trail = expansion_trail;
625 expansion_trail = subsym;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200626 crc = expand_and_crc_sym(subsym, crc);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100627 }
628 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200632 {
633 static struct symbol **end = &visited_symbols;
634
635 if (!sym->visited) {
636 *end = sym;
637 end = &sym->visited;
638 sym->visited = (struct symbol *)-1L;
639 }
640 }
641
Sam Ravnborg78c041532006-03-12 22:59:36 +0100642 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643}
644
Sam Ravnborg78c041532006-03-12 22:59:36 +0100645void export_symbol(const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100647 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
Michal Marek01762c42011-02-15 15:11:36 +0100649 sym = find_symbol(name, SYM_NORMAL, 0);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100650 if (!sym)
651 error_with_pos("export undefined symbol %s", name);
652 else {
653 unsigned long crc;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800654 int has_changed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Sam Ravnborg78c041532006-03-12 22:59:36 +0100656 if (flag_dump_defs)
657 fprintf(debugfile, "Export %s == <", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
Sam Ravnborg78c041532006-03-12 22:59:36 +0100659 expansion_trail = (struct symbol *)-1L;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800661 sym->expansion_trail = expansion_trail;
662 expansion_trail = sym;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200663 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
Sam Ravnborg78c041532006-03-12 22:59:36 +0100665 sym = expansion_trail;
666 while (sym != (struct symbol *)-1L) {
667 struct symbol *n = sym->expansion_trail;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800668
669 if (sym->status != STATUS_UNCHANGED) {
670 if (!has_changed) {
671 print_location();
672 fprintf(stderr, "%s: %s: modversion "
673 "changed because of changes "
674 "in ", flag_preserve ? "error" :
675 "warning", name);
676 } else
677 fprintf(stderr, ", ");
678 print_type_name(sym->type, sym->name);
679 if (sym->status == STATUS_DEFINED)
680 fprintf(stderr, " (became defined)");
681 has_changed = 1;
682 if (flag_preserve)
683 errors++;
684 }
Sam Ravnborg78c041532006-03-12 22:59:36 +0100685 sym->expansion_trail = 0;
686 sym = n;
687 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800688 if (has_changed)
689 fprintf(stderr, "\n");
Sam Ravnborg78c041532006-03-12 22:59:36 +0100690
691 if (flag_dump_defs)
692 fputs(">\n", debugfile);
693
Sam Ravnborg2ea03892009-01-14 21:38:20 +0100694 /* Used as a linker script. */
695 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697}
698
699/*----------------------------------------------------------------------*/
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800700
701static void print_location(void)
702{
703 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
704}
705
706static void print_type_name(enum symbol_type type, const char *name)
707{
Michal Marek7ec8eda2011-01-18 16:28:06 +0100708 if (symbol_types[type].name)
709 fprintf(stderr, "%s %s", symbol_types[type].name, name);
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800710 else
711 fprintf(stderr, "%s", name);
712}
713
Sam Ravnborg78c041532006-03-12 22:59:36 +0100714void error_with_pos(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100716 va_list args;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
Sam Ravnborg78c041532006-03-12 22:59:36 +0100718 if (flag_warnings) {
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800719 print_location();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
Sam Ravnborg78c041532006-03-12 22:59:36 +0100721 va_start(args, fmt);
722 vfprintf(stderr, fmt, args);
723 va_end(args);
724 putc('\n', stderr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
Sam Ravnborg78c041532006-03-12 22:59:36 +0100726 errors++;
727 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728}
729
Sam Ravnborgce560682006-03-12 23:26:29 +0100730static void genksyms_usage(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731{
Sam Ravnborg2ea03892009-01-14 21:38:20 +0100732 fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733#ifdef __GNU_LIBRARY__
Mike Frysinger36091fd2007-11-10 09:32:20 -0500734 " -a, --arch Select architecture\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 " -d, --debug Increment the debug level (repeatable)\n"
736 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800737 " -r, --reference file Read reference symbols from a file\n"
738 " -T, --dump-types file Dump expanded types into file\n"
739 " -p, --preserve Preserve reference modversions or fail\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 " -w, --warnings Enable warnings\n"
741 " -q, --quiet Disable warnings (default)\n"
742 " -h, --help Print this message\n"
743 " -V, --version Print the release version\n"
Sam Ravnborg78c041532006-03-12 22:59:36 +0100744#else /* __GNU_LIBRARY__ */
Mike Frysinger36091fd2007-11-10 09:32:20 -0500745 " -a Select architecture\n"
Sam Ravnborg78c041532006-03-12 22:59:36 +0100746 " -d Increment the debug level (repeatable)\n"
747 " -D Dump expanded symbol defs (for debugging only)\n"
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800748 " -r file Read reference symbols from a file\n"
749 " -T file Dump expanded types into file\n"
750 " -p Preserve reference modversions or fail\n"
Sam Ravnborg78c041532006-03-12 22:59:36 +0100751 " -w Enable warnings\n"
752 " -q Disable warnings (default)\n"
753 " -h Print this message\n"
754 " -V Print the release version\n"
755#endif /* __GNU_LIBRARY__ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 , stderr);
757}
758
Sam Ravnborg78c041532006-03-12 22:59:36 +0100759int main(int argc, char **argv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760{
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800761 FILE *dumpfile = NULL, *ref_file = NULL;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100762 int o;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
764#ifdef __GNU_LIBRARY__
Sam Ravnborg78c041532006-03-12 22:59:36 +0100765 struct option long_opts[] = {
766 {"arch", 1, 0, 'a'},
767 {"debug", 0, 0, 'd'},
768 {"warnings", 0, 0, 'w'},
769 {"quiet", 0, 0, 'q'},
770 {"dump", 0, 0, 'D'},
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800771 {"reference", 1, 0, 'r'},
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200772 {"dump-types", 1, 0, 'T'},
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800773 {"preserve", 0, 0, 'p'},
Sam Ravnborg78c041532006-03-12 22:59:36 +0100774 {"version", 0, 0, 'V'},
775 {"help", 0, 0, 'h'},
776 {0, 0, 0, 0}
777 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778
Sam Ravnborg2ea03892009-01-14 21:38:20 +0100779 while ((o = getopt_long(argc, argv, "a:dwqVDr:T:ph",
Sam Ravnborg78c041532006-03-12 22:59:36 +0100780 &long_opts[0], NULL)) != EOF)
781#else /* __GNU_LIBRARY__ */
Sam Ravnborg2ea03892009-01-14 21:38:20 +0100782 while ((o = getopt(argc, argv, "a:dwqVDr:T:ph")) != EOF)
Sam Ravnborg78c041532006-03-12 22:59:36 +0100783#endif /* __GNU_LIBRARY__ */
784 switch (o) {
785 case 'a':
786 arch = optarg;
787 break;
788 case 'd':
789 flag_debug++;
790 break;
791 case 'w':
792 flag_warnings = 1;
793 break;
794 case 'q':
795 flag_warnings = 0;
796 break;
797 case 'V':
798 fputs("genksyms version 2.5.60\n", stderr);
799 break;
800 case 'D':
801 flag_dump_defs = 1;
802 break;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800803 case 'r':
804 flag_reference = 1;
805 ref_file = fopen(optarg, "r");
806 if (!ref_file) {
807 perror(optarg);
808 return 1;
809 }
810 break;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200811 case 'T':
812 flag_dump_types = 1;
813 dumpfile = fopen(optarg, "w");
814 if (!dumpfile) {
815 perror(optarg);
816 return 1;
817 }
818 break;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800819 case 'p':
820 flag_preserve = 1;
821 break;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100822 case 'h':
823 genksyms_usage();
824 return 0;
825 default:
826 genksyms_usage();
827 return 1;
828 }
Adrian Bunkf606ddf2008-07-23 21:28:50 -0700829 if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0))
Sam Ravnborg78c041532006-03-12 22:59:36 +0100830 mod_prefix = "_";
831 {
832 extern int yydebug;
833 extern int yy_flex_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
Sam Ravnborg78c041532006-03-12 22:59:36 +0100835 yydebug = (flag_debug > 1);
836 yy_flex_debug = (flag_debug > 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837
Sam Ravnborg78c041532006-03-12 22:59:36 +0100838 debugfile = stderr;
839 /* setlinebuf(debugfile); */
840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Alexander Beregalovc64152b2010-01-07 05:22:41 +0300842 if (flag_reference) {
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800843 read_reference(ref_file);
Alexander Beregalovc64152b2010-01-07 05:22:41 +0300844 fclose(ref_file);
845 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800846
Sam Ravnborg78c041532006-03-12 22:59:36 +0100847 yyparse();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200849 if (flag_dump_types && visited_symbols) {
850 while (visited_symbols != (struct symbol *)-1L) {
851 struct symbol *sym = visited_symbols;
852
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800853 if (sym->is_override)
854 fputs("override ", dumpfile);
Michal Marek7ec8eda2011-01-18 16:28:06 +0100855 if (symbol_types[sym->type].n) {
856 putc(symbol_types[sym->type].n, dumpfile);
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200857 putc('#', dumpfile);
858 }
859 fputs(sym->name, dumpfile);
860 putc(' ', dumpfile);
Andreas Gruenbacher3b40d382008-07-21 04:28:25 +0200861 if (sym->is_extern)
862 fputs("extern ", dumpfile);
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200863 print_list(dumpfile, sym->defn);
864 putc('\n', dumpfile);
865
866 visited_symbols = sym->visited;
867 sym->visited = NULL;
868 }
869 }
870
Sam Ravnborg78c041532006-03-12 22:59:36 +0100871 if (flag_debug) {
872 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
873 nsyms, HASH_BUCKETS,
874 (double)nsyms / (double)HASH_BUCKETS);
875 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
Sam Ravnborg78c041532006-03-12 22:59:36 +0100877 return errors != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878}