Blame view

scripts/genksyms/genksyms.c 20.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  /* Generate kernel symbol version hashes.
     Copyright 1996, 1997 Linux International.
  
     New implementation contributed by Richard Henderson <rth@tamu.edu>
     Based on original work by Bjorn Ekwall <bj0rn@blox.se>
  
     This file was part of the Linux modutils 2.4.22: moved back into the
     kernel sources by Rusty Russell/Kai Germaschewski.
  
     This program is free software; you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation; either version 2 of the License, or (at your
     option) any later version.
  
     This program is distributed in the hope that it will be useful, but
     WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     General Public License for more details.
  
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software Foundation,
     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <assert.h>
  #include <stdarg.h>
  #ifdef __GNU_LIBRARY__
  #include <getopt.h>
78c041530   Sam Ravnborg   kbuild: Lindent g...
32
  #endif				/* __GNU_LIBRARY__ */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
  
  #include "genksyms.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
  /*----------------------------------------------------------------------*/
  
  #define HASH_BUCKETS  4096
  
  static struct symbol *symtab[HASH_BUCKETS];
ce5606869   Sam Ravnborg   kbuild: clean-up ...
40
  static FILE *debugfile;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
  
  int cur_line = 1;
ce5606869   Sam Ravnborg   kbuild: clean-up ...
43
  char *cur_filename;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44

64e6c1e12   Andreas Gruenbacher   genksyms: track s...
45
  static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
2ea038917   Sam Ravnborg   Revert "kbuild: s...
46
  	   flag_preserve, flag_warnings;
ce5606869   Sam Ravnborg   kbuild: clean-up ...
47
48
  static const char *arch = "";
  static const char *mod_prefix = "";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
  
  static int errors;
  static int nsyms;
  
  static struct symbol *expansion_trail;
15fde6751   Andreas Gruenbacher   kbuild: support f...
54
  static struct symbol *visited_symbols;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

78c041530   Sam Ravnborg   kbuild: Lindent g...
56
57
  static const char *const symbol_type_name[] = {
  	"normal", "typedef", "enum", "struct", "union"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  };
ce5606869   Sam Ravnborg   kbuild: clean-up ...
59
60
  static int equal_list(struct string_list *a, struct string_list *b);
  static void print_list(FILE * f, struct string_list *list);
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
61
62
  static void print_location(void);
  static void print_type_name(enum symbol_type type, const char *name);
ce5606869   Sam Ravnborg   kbuild: clean-up ...
63

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  /*----------------------------------------------------------------------*/
78c041530   Sam Ravnborg   kbuild: Lindent g...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  static const unsigned int crctab32[] = {
  	0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
  	0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
  	0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
  	0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
  	0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
  	0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
  	0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
  	0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
  	0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
  	0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
  	0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
  	0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
  	0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
  	0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
  	0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
  	0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
  	0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
  	0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
  	0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
  	0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
  	0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
  	0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
  	0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
  	0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
  	0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
  	0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
  	0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
  	0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
  	0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
  	0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
  	0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
  	0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
  	0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
  	0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
  	0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
  	0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
  	0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
  	0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
  	0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
  	0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
  	0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
  	0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
  	0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
  	0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
  	0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
  	0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
  	0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
  	0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
  	0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
  	0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
  	0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
  	0x2d02ef8dU
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  };
ce5606869   Sam Ravnborg   kbuild: clean-up ...
119
  static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
121
  	return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  }
ce5606869   Sam Ravnborg   kbuild: clean-up ...
123
  static unsigned long partial_crc32(const char *s, unsigned long crc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
125
126
127
  	while (*s)
  		crc = partial_crc32_one(*s++, crc);
  	return crc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  }
ce5606869   Sam Ravnborg   kbuild: clean-up ...
129
  static unsigned long crc32(const char *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
131
  	return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
  /*----------------------------------------------------------------------*/
ce5606869   Sam Ravnborg   kbuild: clean-up ...
134
  static enum symbol_type map_to_ns(enum symbol_type t)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
136
137
138
139
140
  	if (t == SYM_TYPEDEF)
  		t = SYM_NORMAL;
  	else if (t == SYM_UNION)
  		t = SYM_STRUCT;
  	return t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  }
78c041530   Sam Ravnborg   kbuild: Lindent g...
142
  struct symbol *find_symbol(const char *name, enum symbol_type ns)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
144
145
  	unsigned long h = crc32(name) % HASH_BUCKETS;
  	struct symbol *sym;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146

78c041530   Sam Ravnborg   kbuild: Lindent g...
147
  	for (sym = symtab[h]; sym; sym = sym->hash_next)
ce5606869   Sam Ravnborg   kbuild: clean-up ...
148
  		if (map_to_ns(sym->type) == map_to_ns(ns) &&
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
149
150
  		    strcmp(name, sym->name) == 0 &&
  		    sym->is_declared)
78c041530   Sam Ravnborg   kbuild: Lindent g...
151
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152

78c041530   Sam Ravnborg   kbuild: Lindent g...
153
  	return sym;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  }
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  static int is_unknown_symbol(struct symbol *sym)
  {
  	struct string_list *defn;
  
  	return ((sym->type == SYM_STRUCT ||
  		 sym->type == SYM_UNION ||
  		 sym->type == SYM_ENUM) &&
  		(defn = sym->defn)  && defn->tag == SYM_NORMAL &&
  			strcmp(defn->string, "}") == 0 &&
  		(defn = defn->next) && defn->tag == SYM_NORMAL &&
  			strcmp(defn->string, "UNKNOWN") == 0 &&
  		(defn = defn->next) && defn->tag == SYM_NORMAL &&
  			strcmp(defn->string, "{") == 0);
  }
b7ed698cc   Ladinu Chandrasinghe   Documentation/: f...
169
  static struct symbol *__add_symbol(const char *name, enum symbol_type type,
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
170
171
  			    struct string_list *defn, int is_extern,
  			    int is_reference)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
173
174
  	unsigned long h = crc32(name) % HASH_BUCKETS;
  	struct symbol *sym;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
175
  	enum symbol_status status = STATUS_UNCHANGED;
78c041530   Sam Ravnborg   kbuild: Lindent g...
176

ce5606869   Sam Ravnborg   kbuild: clean-up ...
177
  	for (sym = symtab[h]; sym; sym = sym->hash_next) {
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
178
179
180
181
182
183
  		if (map_to_ns(sym->type) == map_to_ns(type) &&
  		    strcmp(name, sym->name) == 0) {
  			if (is_reference)
  				/* fall through */ ;
  			else if (sym->type == type &&
  				 equal_list(sym->defn, defn)) {
5dae9a550   Andreas Gruenbacher   genksyms: allow t...
184
185
186
187
188
189
190
  				if (!sym->is_declared && sym->is_override) {
  					print_location();
  					print_type_name(type, name);
  					fprintf(stderr, " modversion is "
  						"unchanged
  ");
  				}
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
191
192
193
  				sym->is_declared = 1;
  				return sym;
  			} else if (!sym->is_declared) {
5dae9a550   Andreas Gruenbacher   genksyms: allow t...
194
195
196
197
198
199
200
201
202
203
204
205
  				if (sym->is_override && flag_preserve) {
  					print_location();
  					fprintf(stderr, "ignoring ");
  					print_type_name(type, name);
  					fprintf(stderr, " modversion change
  ");
  					sym->is_declared = 1;
  					return sym;
  				} else {
  					status = is_unknown_symbol(sym) ?
  						STATUS_DEFINED : STATUS_MODIFIED;
  				}
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
206
  			} else {
78c041530   Sam Ravnborg   kbuild: Lindent g...
207
  				error_with_pos("redefinition of %s", name);
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
208
209
210
  				return sym;
  			}
  			break;
78c041530   Sam Ravnborg   kbuild: Lindent g...
211
  		}
ce5606869   Sam Ravnborg   kbuild: clean-up ...
212
  	}
78c041530   Sam Ravnborg   kbuild: Lindent g...
213

64e6c1e12   Andreas Gruenbacher   genksyms: track s...
214
215
216
217
218
219
220
221
222
223
224
  	if (sym) {
  		struct symbol **psym;
  
  		for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
  			if (*psym == sym) {
  				*psym = sym->hash_next;
  				break;
  			}
  		}
  		--nsyms;
  	}
78c041530   Sam Ravnborg   kbuild: Lindent g...
225
226
227
228
229
  	sym = xmalloc(sizeof(*sym));
  	sym->name = name;
  	sym->type = type;
  	sym->defn = defn;
  	sym->expansion_trail = NULL;
15fde6751   Andreas Gruenbacher   kbuild: support f...
230
  	sym->visited = NULL;
78c041530   Sam Ravnborg   kbuild: Lindent g...
231
232
233
234
  	sym->is_extern = is_extern;
  
  	sym->hash_next = symtab[h];
  	symtab[h] = sym;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
235
236
  	sym->is_declared = !is_reference;
  	sym->status = status;
5dae9a550   Andreas Gruenbacher   genksyms: allow t...
237
  	sym->is_override = 0;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
238

78c041530   Sam Ravnborg   kbuild: Lindent g...
239
240
241
242
243
244
245
246
247
248
249
  	if (flag_debug) {
  		fprintf(debugfile, "Defn for %s %s == <",
  			symbol_type_name[type], name);
  		if (is_extern)
  			fputs("extern ", debugfile);
  		print_list(debugfile, defn);
  		fputs(">
  ", debugfile);
  	}
  
  	++nsyms;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  	return sym;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
  }
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
252
253
254
255
256
  struct symbol *add_symbol(const char *name, enum symbol_type type,
  			  struct string_list *defn, int is_extern)
  {
  	return __add_symbol(name, type, defn, is_extern, 0);
  }
b7ed698cc   Ladinu Chandrasinghe   Documentation/: f...
257
  static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
258
259
260
261
  				    struct string_list *defn, int is_extern)
  {
  	return __add_symbol(name, type, defn, is_extern, 1);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  /*----------------------------------------------------------------------*/
ce5606869   Sam Ravnborg   kbuild: clean-up ...
263
  void free_node(struct string_list *node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
265
266
  	free(node->string);
  	free(node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  }
78c041530   Sam Ravnborg   kbuild: Lindent g...
268
  void free_list(struct string_list *s, struct string_list *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
270
271
272
273
274
  	while (s != e) {
  		struct string_list *next = s->next;
  		free_node(s);
  		s = next;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
  }
ce5606869   Sam Ravnborg   kbuild: clean-up ...
276
  struct string_list *copy_node(struct string_list *node)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
278
  	struct string_list *newnode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279

78c041530   Sam Ravnborg   kbuild: Lindent g...
280
281
282
  	newnode = xmalloc(sizeof(*newnode));
  	newnode->string = xstrdup(node->string);
  	newnode->tag = node->tag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283

78c041530   Sam Ravnborg   kbuild: Lindent g...
284
  	return newnode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  }
ce5606869   Sam Ravnborg   kbuild: clean-up ...
286
  static int equal_list(struct string_list *a, struct string_list *b)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
288
289
290
291
292
293
  	while (a && b) {
  		if (a->tag != b->tag || strcmp(a->string, b->string))
  			return 0;
  		a = a->next;
  		b = b->next;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294

78c041530   Sam Ravnborg   kbuild: Lindent g...
295
  	return !a && !b;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
  }
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
297
  #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
b7ed698cc   Ladinu Chandrasinghe   Documentation/: f...
298
  static struct string_list *read_node(FILE *f)
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
  {
  	char buffer[256];
  	struct string_list node = {
  		.string = buffer,
  		.tag = SYM_NORMAL };
  	int c;
  
  	while ((c = fgetc(f)) != EOF) {
  		if (c == ' ') {
  			if (node.string == buffer)
  				continue;
  			break;
  		} else if (c == '
  ') {
  			if (node.string == buffer)
  				return NULL;
  			ungetc(c, f);
  			break;
  		}
  		if (node.string >= buffer + sizeof(buffer) - 1) {
  			fprintf(stderr, "Token too long
  ");
  			exit(1);
  		}
  		*node.string++ = c;
  	}
  	if (node.string == buffer)
  		return NULL;
  	*node.string = 0;
  	node.string = buffer;
  
  	if (node.string[1] == '#') {
  		int n;
  
  		for (n = 0; n < ARRAY_SIZE(symbol_type_name); n++) {
  			if (node.string[0] == symbol_type_name[n][0]) {
  				node.tag = n;
  				node.string += 2;
  				return copy_node(&node);
  			}
  		}
  		fprintf(stderr, "Unknown type %c
  ", node.string[0]);
  		exit(1);
  	}
  	return copy_node(&node);
  }
  
  static void read_reference(FILE *f)
  {
  	while (!feof(f)) {
  		struct string_list *defn = NULL;
  		struct string_list *sym, *def;
5dae9a550   Andreas Gruenbacher   genksyms: allow t...
352
353
  		int is_extern = 0, is_override = 0;
  		struct symbol *subsym;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
354
355
  
  		sym = read_node(f);
5dae9a550   Andreas Gruenbacher   genksyms: allow t...
356
357
358
359
360
361
  		if (sym && sym->tag == SYM_NORMAL &&
  		    !strcmp(sym->string, "override")) {
  			is_override = 1;
  			free_node(sym);
  			sym = read_node(f);
  		}
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  		if (!sym)
  			continue;
  		def = read_node(f);
  		if (def && def->tag == SYM_NORMAL &&
  		    !strcmp(def->string, "extern")) {
  			is_extern = 1;
  			free_node(def);
  			def = read_node(f);
  		}
  		while (def) {
  			def->next = defn;
  			defn = def;
  			def = read_node(f);
  		}
5dae9a550   Andreas Gruenbacher   genksyms: allow t...
376
  		subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
377
  					      defn, is_extern);
5dae9a550   Andreas Gruenbacher   genksyms: allow t...
378
  		subsym->is_override = is_override;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
379
380
381
  		free_node(sym);
  	}
  }
ce5606869   Sam Ravnborg   kbuild: clean-up ...
382
  static void print_node(FILE * f, struct string_list *list)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  {
15fde6751   Andreas Gruenbacher   kbuild: support f...
384
385
  	if (list->tag != SYM_NORMAL) {
  		putc(symbol_type_name[list->tag][0], f);
78c041530   Sam Ravnborg   kbuild: Lindent g...
386
  		putc('#', f);
78c041530   Sam Ravnborg   kbuild: Lindent g...
387
  	}
15fde6751   Andreas Gruenbacher   kbuild: support f...
388
  	fputs(list->string, f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  }
ce5606869   Sam Ravnborg   kbuild: clean-up ...
390
  static void print_list(FILE * f, struct string_list *list)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
392
393
394
  	struct string_list **e, **b;
  	struct string_list *tmp, **tmp2;
  	int elem = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395

78c041530   Sam Ravnborg   kbuild: Lindent g...
396
397
398
399
  	if (list == NULL) {
  		fputs("(nil)", f);
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400

78c041530   Sam Ravnborg   kbuild: Lindent g...
401
402
403
  	tmp = list;
  	while ((tmp = tmp->next) != NULL)
  		elem++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404

78c041530   Sam Ravnborg   kbuild: Lindent g...
405
406
407
  	b = alloca(elem * sizeof(*e));
  	e = b + elem;
  	tmp2 = e - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408

78c041530   Sam Ravnborg   kbuild: Lindent g...
409
410
411
  	(*tmp2--) = list;
  	while ((list = list->next) != NULL)
  		*(tmp2--) = list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412

78c041530   Sam Ravnborg   kbuild: Lindent g...
413
414
415
416
417
  	while (b != e) {
  		print_node(f, *b++);
  		putc(' ', f);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418

15fde6751   Andreas Gruenbacher   kbuild: support f...
419
  static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
78c041530   Sam Ravnborg   kbuild: Lindent g...
420
  {
15fde6751   Andreas Gruenbacher   kbuild: support f...
421
  	struct string_list *list = sym->defn;
78c041530   Sam Ravnborg   kbuild: Lindent g...
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  	struct string_list **e, **b;
  	struct string_list *tmp, **tmp2;
  	int elem = 1;
  
  	if (!list)
  		return crc;
  
  	tmp = list;
  	while ((tmp = tmp->next) != NULL)
  		elem++;
  
  	b = alloca(elem * sizeof(*e));
  	e = b + elem;
  	tmp2 = e - 1;
  
  	*(tmp2--) = list;
  	while ((list = list->next) != NULL)
  		*(tmp2--) = list;
  
  	while (b != e) {
  		struct string_list *cur;
  		struct symbol *subsym;
  
  		cur = *(b++);
  		switch (cur->tag) {
  		case SYM_NORMAL:
  			if (flag_dump_defs)
  				fprintf(debugfile, "%s ", cur->string);
  			crc = partial_crc32(cur->string, crc);
  			crc = partial_crc32_one(' ', crc);
  			break;
  
  		case SYM_TYPEDEF:
  			subsym = find_symbol(cur->string, cur->tag);
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
456
  			/* FIXME: Bad reference files can segfault here. */
78c041530   Sam Ravnborg   kbuild: Lindent g...
457
458
459
460
461
462
463
464
  			if (subsym->expansion_trail) {
  				if (flag_dump_defs)
  					fprintf(debugfile, "%s ", cur->string);
  				crc = partial_crc32(cur->string, crc);
  				crc = partial_crc32_one(' ', crc);
  			} else {
  				subsym->expansion_trail = expansion_trail;
  				expansion_trail = subsym;
15fde6751   Andreas Gruenbacher   kbuild: support f...
465
  				crc = expand_and_crc_sym(subsym, crc);
78c041530   Sam Ravnborg   kbuild: Lindent g...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  			}
  			break;
  
  		case SYM_STRUCT:
  		case SYM_UNION:
  		case SYM_ENUM:
  			subsym = find_symbol(cur->string, cur->tag);
  			if (!subsym) {
  				struct string_list *n, *t = NULL;
  
  				error_with_pos("expand undefined %s %s",
  					       symbol_type_name[cur->tag],
  					       cur->string);
  
  				n = xmalloc(sizeof(*n));
  				n->string = xstrdup(symbol_type_name[cur->tag]);
  				n->tag = SYM_NORMAL;
  				n->next = t;
  				t = n;
  
  				n = xmalloc(sizeof(*n));
  				n->string = xstrdup(cur->string);
  				n->tag = SYM_NORMAL;
  				n->next = t;
  				t = n;
  
  				n = xmalloc(sizeof(*n));
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
493
  				n->string = xstrdup("{");
78c041530   Sam Ravnborg   kbuild: Lindent g...
494
495
  				n->tag = SYM_NORMAL;
  				n->next = t;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
496
497
498
499
500
501
502
503
504
505
506
507
508
  				t = n;
  
  				n = xmalloc(sizeof(*n));
  				n->string = xstrdup("UNKNOWN");
  				n->tag = SYM_NORMAL;
  				n->next = t;
  				t = n;
  
  				n = xmalloc(sizeof(*n));
  				n->string = xstrdup("}");
  				n->tag = SYM_NORMAL;
  				n->next = t;
  				t = n;
78c041530   Sam Ravnborg   kbuild: Lindent g...
509
510
511
512
513
514
515
516
517
518
  
  				subsym =
  				    add_symbol(cur->string, cur->tag, n, 0);
  			}
  			if (subsym->expansion_trail) {
  				if (flag_dump_defs) {
  					fprintf(debugfile, "%s %s ",
  						symbol_type_name[cur->tag],
  						cur->string);
  				}
ce5606869   Sam Ravnborg   kbuild: clean-up ...
519
520
  				crc = partial_crc32(symbol_type_name[cur->tag],
  						    crc);
78c041530   Sam Ravnborg   kbuild: Lindent g...
521
522
523
524
525
526
  				crc = partial_crc32_one(' ', crc);
  				crc = partial_crc32(cur->string, crc);
  				crc = partial_crc32_one(' ', crc);
  			} else {
  				subsym->expansion_trail = expansion_trail;
  				expansion_trail = subsym;
15fde6751   Andreas Gruenbacher   kbuild: support f...
527
  				crc = expand_and_crc_sym(subsym, crc);
78c041530   Sam Ravnborg   kbuild: Lindent g...
528
529
  			}
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532

15fde6751   Andreas Gruenbacher   kbuild: support f...
533
534
535
536
537
538
539
540
541
  	{
  		static struct symbol **end = &visited_symbols;
  
  		if (!sym->visited) {
  			*end = sym;
  			end = &sym->visited;
  			sym->visited = (struct symbol *)-1L;
  		}
  	}
78c041530   Sam Ravnborg   kbuild: Lindent g...
542
  	return crc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
  }
78c041530   Sam Ravnborg   kbuild: Lindent g...
544
  void export_symbol(const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
546
  	struct symbol *sym;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547

78c041530   Sam Ravnborg   kbuild: Lindent g...
548
549
550
551
552
  	sym = find_symbol(name, SYM_NORMAL);
  	if (!sym)
  		error_with_pos("export undefined symbol %s", name);
  	else {
  		unsigned long crc;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
553
  		int has_changed = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554

78c041530   Sam Ravnborg   kbuild: Lindent g...
555
556
  		if (flag_dump_defs)
  			fprintf(debugfile, "Export %s == <", name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557

78c041530   Sam Ravnborg   kbuild: Lindent g...
558
  		expansion_trail = (struct symbol *)-1L;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559

64e6c1e12   Andreas Gruenbacher   genksyms: track s...
560
561
  		sym->expansion_trail = expansion_trail;
  		expansion_trail = sym;
15fde6751   Andreas Gruenbacher   kbuild: support f...
562
  		crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563

78c041530   Sam Ravnborg   kbuild: Lindent g...
564
565
566
  		sym = expansion_trail;
  		while (sym != (struct symbol *)-1L) {
  			struct symbol *n = sym->expansion_trail;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
  
  			if (sym->status != STATUS_UNCHANGED) {
  				if (!has_changed) {
  					print_location();
  					fprintf(stderr, "%s: %s: modversion "
  						"changed because of changes "
  						"in ", flag_preserve ? "error" :
  						       "warning", name);
  				} else
  					fprintf(stderr, ", ");
  				print_type_name(sym->type, sym->name);
  				if (sym->status == STATUS_DEFINED)
  					fprintf(stderr, " (became defined)");
  				has_changed = 1;
  				if (flag_preserve)
  					errors++;
  			}
78c041530   Sam Ravnborg   kbuild: Lindent g...
584
585
586
  			sym->expansion_trail = 0;
  			sym = n;
  		}
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
587
588
589
  		if (has_changed)
  			fprintf(stderr, "
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590

78c041530   Sam Ravnborg   kbuild: Lindent g...
591
592
593
  		if (flag_dump_defs)
  			fputs(">
  ", debugfile);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594

2ea038917   Sam Ravnborg   Revert "kbuild: s...
595
596
597
  		/* Used as a linker script. */
  		printf("%s__crc_%s = 0x%08lx ;
  ", mod_prefix, name, crc);
78c041530   Sam Ravnborg   kbuild: Lindent g...
598
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
601
  }
  
  /*----------------------------------------------------------------------*/
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
602
603
604
605
606
607
608
609
610
611
612
613
614
  
  static void print_location(void)
  {
  	fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
  }
  
  static void print_type_name(enum symbol_type type, const char *name)
  {
  	if (type != SYM_NORMAL)
  		fprintf(stderr, "%s %s", symbol_type_name[type], name);
  	else
  		fprintf(stderr, "%s", name);
  }
78c041530   Sam Ravnborg   kbuild: Lindent g...
615
  void error_with_pos(const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
  {
78c041530   Sam Ravnborg   kbuild: Lindent g...
617
  	va_list args;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618

78c041530   Sam Ravnborg   kbuild: Lindent g...
619
  	if (flag_warnings) {
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
620
  		print_location();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621

78c041530   Sam Ravnborg   kbuild: Lindent g...
622
623
624
625
626
  		va_start(args, fmt);
  		vfprintf(stderr, fmt, args);
  		va_end(args);
  		putc('
  ', stderr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627

78c041530   Sam Ravnborg   kbuild: Lindent g...
628
629
  		errors++;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  }
ce5606869   Sam Ravnborg   kbuild: clean-up ...
631
  static void genksyms_usage(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  {
2ea038917   Sam Ravnborg   Revert "kbuild: s...
633
634
635
636
  	fputs("Usage:
  " "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver
  " "
  "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
  #ifdef __GNU_LIBRARY__
36091fd34   Mike Frysinger   kbuild: fixup gen...
638
639
  	      "  -a, --arch            Select architecture
  "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
641
642
643
  	      "  -d, --debug           Increment the debug level (repeatable)
  "
  	      "  -D, --dump            Dump expanded symbol defs (for debugging only)
  "
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
644
645
646
647
648
649
  	      "  -r, --reference file  Read reference symbols from a file
  "
  	      "  -T, --dump-types file Dump expanded types into file
  "
  	      "  -p, --preserve        Preserve reference modversions or fail
  "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
652
653
654
655
656
657
  	      "  -w, --warnings        Enable warnings
  "
  	      "  -q, --quiet           Disable warnings (default)
  "
  	      "  -h, --help            Print this message
  "
  	      "  -V, --version         Print the release version
  "
78c041530   Sam Ravnborg   kbuild: Lindent g...
658
  #else				/* __GNU_LIBRARY__ */
36091fd34   Mike Frysinger   kbuild: fixup gen...
659
660
  	      "  -a                    Select architecture
  "
78c041530   Sam Ravnborg   kbuild: Lindent g...
661
662
663
664
  	      "  -d                    Increment the debug level (repeatable)
  "
  	      "  -D                    Dump expanded symbol defs (for debugging only)
  "
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
665
666
667
668
669
670
  	      "  -r file               Read reference symbols from a file
  "
  	      "  -T file               Dump expanded types into file
  "
  	      "  -p                    Preserve reference modversions or fail
  "
78c041530   Sam Ravnborg   kbuild: Lindent g...
671
672
673
674
675
676
677
678
679
  	      "  -w                    Enable warnings
  "
  	      "  -q                    Disable warnings (default)
  "
  	      "  -h                    Print this message
  "
  	      "  -V                    Print the release version
  "
  #endif				/* __GNU_LIBRARY__ */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
681
  	      , stderr);
  }
78c041530   Sam Ravnborg   kbuild: Lindent g...
682
  int main(int argc, char **argv)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
  {
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
684
  	FILE *dumpfile = NULL, *ref_file = NULL;
78c041530   Sam Ravnborg   kbuild: Lindent g...
685
  	int o;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
  
  #ifdef __GNU_LIBRARY__
78c041530   Sam Ravnborg   kbuild: Lindent g...
688
689
690
691
692
693
  	struct option long_opts[] = {
  		{"arch", 1, 0, 'a'},
  		{"debug", 0, 0, 'd'},
  		{"warnings", 0, 0, 'w'},
  		{"quiet", 0, 0, 'q'},
  		{"dump", 0, 0, 'D'},
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
694
  		{"reference", 1, 0, 'r'},
15fde6751   Andreas Gruenbacher   kbuild: support f...
695
  		{"dump-types", 1, 0, 'T'},
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
696
  		{"preserve", 0, 0, 'p'},
78c041530   Sam Ravnborg   kbuild: Lindent g...
697
698
699
700
  		{"version", 0, 0, 'V'},
  		{"help", 0, 0, 'h'},
  		{0, 0, 0, 0}
  	};
2ea038917   Sam Ravnborg   Revert "kbuild: s...
701
  	while ((o = getopt_long(argc, argv, "a:dwqVDr:T:ph",
78c041530   Sam Ravnborg   kbuild: Lindent g...
702
703
  				&long_opts[0], NULL)) != EOF)
  #else				/* __GNU_LIBRARY__ */
2ea038917   Sam Ravnborg   Revert "kbuild: s...
704
  	while ((o = getopt(argc, argv, "a:dwqVDr:T:ph")) != EOF)
78c041530   Sam Ravnborg   kbuild: Lindent g...
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
  #endif				/* __GNU_LIBRARY__ */
  		switch (o) {
  		case 'a':
  			arch = optarg;
  			break;
  		case 'd':
  			flag_debug++;
  			break;
  		case 'w':
  			flag_warnings = 1;
  			break;
  		case 'q':
  			flag_warnings = 0;
  			break;
  		case 'V':
  			fputs("genksyms version 2.5.60
  ", stderr);
  			break;
  		case 'D':
  			flag_dump_defs = 1;
  			break;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
726
727
728
729
730
731
732
733
  		case 'r':
  			flag_reference = 1;
  			ref_file = fopen(optarg, "r");
  			if (!ref_file) {
  				perror(optarg);
  				return 1;
  			}
  			break;
15fde6751   Andreas Gruenbacher   kbuild: support f...
734
735
736
737
738
739
740
741
  		case 'T':
  			flag_dump_types = 1;
  			dumpfile = fopen(optarg, "w");
  			if (!dumpfile) {
  				perror(optarg);
  				return 1;
  			}
  			break;
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
742
743
744
  		case 'p':
  			flag_preserve = 1;
  			break;
78c041530   Sam Ravnborg   kbuild: Lindent g...
745
746
747
748
749
750
751
  		case 'h':
  			genksyms_usage();
  			return 0;
  		default:
  			genksyms_usage();
  			return 1;
  		}
f606ddf42   Adrian Bunk   remove the v850 port
752
  	if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0))
78c041530   Sam Ravnborg   kbuild: Lindent g...
753
754
755
756
757
758
759
760
761
762
763
  		mod_prefix = "_";
  	{
  		extern int yydebug;
  		extern int yy_flex_debug;
  
  		yydebug = (flag_debug > 1);
  		yy_flex_debug = (flag_debug > 2);
  
  		debugfile = stderr;
  		/* setlinebuf(debugfile); */
  	}
c64152bfd   Alexander Beregalov   genksyms: close r...
764
  	if (flag_reference) {
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
765
  		read_reference(ref_file);
c64152bfd   Alexander Beregalov   genksyms: close r...
766
767
  		fclose(ref_file);
  	}
64e6c1e12   Andreas Gruenbacher   genksyms: track s...
768

78c041530   Sam Ravnborg   kbuild: Lindent g...
769
  	yyparse();
15fde6751   Andreas Gruenbacher   kbuild: support f...
770
771
772
  	if (flag_dump_types && visited_symbols) {
  		while (visited_symbols != (struct symbol *)-1L) {
  			struct symbol *sym = visited_symbols;
5dae9a550   Andreas Gruenbacher   genksyms: allow t...
773
774
  			if (sym->is_override)
  				fputs("override ", dumpfile);
15fde6751   Andreas Gruenbacher   kbuild: support f...
775
776
777
778
779
780
  			if (sym->type != SYM_NORMAL) {
  				putc(symbol_type_name[sym->type][0], dumpfile);
  				putc('#', dumpfile);
  			}
  			fputs(sym->name, dumpfile);
  			putc(' ', dumpfile);
3b40d3812   Andreas Gruenbacher   kbuild: genksyms:...
781
782
  			if (sym->is_extern)
  				fputs("extern ", dumpfile);
15fde6751   Andreas Gruenbacher   kbuild: support f...
783
784
785
786
787
788
789
790
  			print_list(dumpfile, sym->defn);
  			putc('
  ', dumpfile);
  
  			visited_symbols = sym->visited;
  			sym->visited = NULL;
  		}
  	}
78c041530   Sam Ravnborg   kbuild: Lindent g...
791
792
793
794
795
796
797
798
  	if (flag_debug) {
  		fprintf(debugfile, "Hash table occupancy %d/%d = %g
  ",
  			nsyms, HASH_BUCKETS,
  			(double)nsyms / (double)HASH_BUCKETS);
  	}
  
  	return errors != 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
  }