1/* Generate kernel symbol version hashes.
2   Copyright 1996, 1997 Linux International.
3
4   New implementation contributed by Richard Henderson <rth@tamu.edu>
5   Based on original work by Bjorn Ekwall <bj0rn@blox.se>
6
7   This file was part of the Linux modutils 2.4.22: moved back into the
8   kernel sources by Rusty Russell/Kai Germaschewski.
9
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2 of the License, or (at your
13   option) any later version.
14
15   This program is distributed in the hope that it will be useful, but
16   WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18   General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software Foundation,
22   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <assert.h>
29#include <stdarg.h>
30#ifdef __GNU_LIBRARY__
31#include <getopt.h>
32#endif				/* __GNU_LIBRARY__ */
33
34#include "genksyms.h"
35/*----------------------------------------------------------------------*/
36
37#define HASH_BUCKETS  4096
38
39static struct symbol *symtab[HASH_BUCKETS];
40static FILE *debugfile;
41
42int cur_line = 1;
43char *cur_filename, *source_file;
44int in_source_file;
45
46static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
47	   flag_preserve, flag_warnings;
48static const char *mod_prefix = "";
49
50static int errors;
51static int nsyms;
52
53static struct symbol *expansion_trail;
54static struct symbol *visited_symbols;
55
56static const struct {
57	int n;
58	const char *name;
59} symbol_types[] = {
60	[SYM_NORMAL]     = { 0, NULL},
61	[SYM_TYPEDEF]    = {'t', "typedef"},
62	[SYM_ENUM]       = {'e', "enum"},
63	[SYM_STRUCT]     = {'s', "struct"},
64	[SYM_UNION]      = {'u', "union"},
65	[SYM_ENUM_CONST] = {'E', "enum constant"},
66};
67
68static int equal_list(struct string_list *a, struct string_list *b);
69static void print_list(FILE * f, struct string_list *list);
70static struct string_list *concat_list(struct string_list *start, ...);
71static struct string_list *mk_node(const char *string);
72static void print_location(void);
73static void print_type_name(enum symbol_type type, const char *name);
74
75/*----------------------------------------------------------------------*/
76
77static const unsigned int crctab32[] = {
78	0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
79	0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
80	0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
81	0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
82	0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
83	0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
84	0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
85	0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
86	0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
87	0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
88	0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
89	0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
90	0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
91	0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
92	0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
93	0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
94	0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
95	0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
96	0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
97	0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
98	0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
99	0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
100	0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
101	0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
102	0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
103	0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
104	0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
105	0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
106	0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
107	0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
108	0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
109	0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
110	0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
111	0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
112	0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
113	0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
114	0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
115	0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
116	0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
117	0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
118	0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
119	0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
120	0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
121	0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
122	0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
123	0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
124	0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
125	0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
126	0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
127	0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
128	0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
129	0x2d02ef8dU
130};
131
132static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
133{
134	return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
135}
136
137static unsigned long partial_crc32(const char *s, unsigned long crc)
138{
139	while (*s)
140		crc = partial_crc32_one(*s++, crc);
141	return crc;
142}
143
144static unsigned long crc32(const char *s)
145{
146	return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
147}
148
149/*----------------------------------------------------------------------*/
150
151static enum symbol_type map_to_ns(enum symbol_type t)
152{
153	switch (t) {
154	case SYM_ENUM_CONST:
155	case SYM_NORMAL:
156	case SYM_TYPEDEF:
157		return SYM_NORMAL;
158	case SYM_ENUM:
159	case SYM_STRUCT:
160	case SYM_UNION:
161		return SYM_STRUCT;
162	}
163	return t;
164}
165
166struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
167{
168	unsigned long h = crc32(name) % HASH_BUCKETS;
169	struct symbol *sym;
170
171	for (sym = symtab[h]; sym; sym = sym->hash_next)
172		if (map_to_ns(sym->type) == map_to_ns(ns) &&
173		    strcmp(name, sym->name) == 0 &&
174		    sym->is_declared)
175			break;
176
177	if (exact && sym && sym->type != ns)
178		return NULL;
179	return sym;
180}
181
182static int is_unknown_symbol(struct symbol *sym)
183{
184	struct string_list *defn;
185
186	return ((sym->type == SYM_STRUCT ||
187		 sym->type == SYM_UNION ||
188		 sym->type == SYM_ENUM) &&
189		(defn = sym->defn)  && defn->tag == SYM_NORMAL &&
190			strcmp(defn->string, "}") == 0 &&
191		(defn = defn->next) && defn->tag == SYM_NORMAL &&
192			strcmp(defn->string, "UNKNOWN") == 0 &&
193		(defn = defn->next) && defn->tag == SYM_NORMAL &&
194			strcmp(defn->string, "{") == 0);
195}
196
197static struct symbol *__add_symbol(const char *name, enum symbol_type type,
198			    struct string_list *defn, int is_extern,
199			    int is_reference)
200{
201	unsigned long h;
202	struct symbol *sym;
203	enum symbol_status status = STATUS_UNCHANGED;
204	/* The parser adds symbols in the order their declaration completes,
205	 * so it is safe to store the value of the previous enum constant in
206	 * a static variable.
207	 */
208	static int enum_counter;
209	static struct string_list *last_enum_expr;
210
211	if (type == SYM_ENUM_CONST) {
212		if (defn) {
213			free_list(last_enum_expr, NULL);
214			last_enum_expr = copy_list_range(defn, NULL);
215			enum_counter = 1;
216		} else {
217			struct string_list *expr;
218			char buf[20];
219
220			snprintf(buf, sizeof(buf), "%d", enum_counter++);
221			if (last_enum_expr) {
222				expr = copy_list_range(last_enum_expr, NULL);
223				defn = concat_list(mk_node("("),
224						   expr,
225						   mk_node(")"),
226						   mk_node("+"),
227						   mk_node(buf), NULL);
228			} else {
229				defn = mk_node(buf);
230			}
231		}
232	} else if (type == SYM_ENUM) {
233		free_list(last_enum_expr, NULL);
234		last_enum_expr = NULL;
235		enum_counter = 0;
236		if (!name)
237			/* Anonymous enum definition, nothing more to do */
238			return NULL;
239	}
240
241	h = crc32(name) % HASH_BUCKETS;
242	for (sym = symtab[h]; sym; sym = sym->hash_next) {
243		if (map_to_ns(sym->type) == map_to_ns(type) &&
244		    strcmp(name, sym->name) == 0) {
245			if (is_reference)
246				/* fall through */ ;
247			else if (sym->type == type &&
248				 equal_list(sym->defn, defn)) {
249				if (!sym->is_declared && sym->is_override) {
250					print_location();
251					print_type_name(type, name);
252					fprintf(stderr, " modversion is "
253						"unchanged\n");
254				}
255				sym->is_declared = 1;
256				return sym;
257			} else if (!sym->is_declared) {
258				if (sym->is_override && flag_preserve) {
259					print_location();
260					fprintf(stderr, "ignoring ");
261					print_type_name(type, name);
262					fprintf(stderr, " modversion change\n");
263					sym->is_declared = 1;
264					return sym;
265				} else {
266					status = is_unknown_symbol(sym) ?
267						STATUS_DEFINED : STATUS_MODIFIED;
268				}
269			} else {
270				error_with_pos("redefinition of %s", name);
271				return sym;
272			}
273			break;
274		}
275	}
276
277	if (sym) {
278		struct symbol **psym;
279
280		for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
281			if (*psym == sym) {
282				*psym = sym->hash_next;
283				break;
284			}
285		}
286		--nsyms;
287	}
288
289	sym = xmalloc(sizeof(*sym));
290	sym->name = name;
291	sym->type = type;
292	sym->defn = defn;
293	sym->expansion_trail = NULL;
294	sym->visited = NULL;
295	sym->is_extern = is_extern;
296
297	sym->hash_next = symtab[h];
298	symtab[h] = sym;
299
300	sym->is_declared = !is_reference;
301	sym->status = status;
302	sym->is_override = 0;
303
304	if (flag_debug) {
305		if (symbol_types[type].name)
306			fprintf(debugfile, "Defn for %s %s == <",
307				symbol_types[type].name, name);
308		else
309			fprintf(debugfile, "Defn for type%d %s == <",
310				type, name);
311		if (is_extern)
312			fputs("extern ", debugfile);
313		print_list(debugfile, defn);
314		fputs(">\n", debugfile);
315	}
316
317	++nsyms;
318	return sym;
319}
320
321struct symbol *add_symbol(const char *name, enum symbol_type type,
322			  struct string_list *defn, int is_extern)
323{
324	return __add_symbol(name, type, defn, is_extern, 0);
325}
326
327static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
328				    struct string_list *defn, int is_extern)
329{
330	return __add_symbol(name, type, defn, is_extern, 1);
331}
332
333/*----------------------------------------------------------------------*/
334
335void free_node(struct string_list *node)
336{
337	free(node->string);
338	free(node);
339}
340
341void free_list(struct string_list *s, struct string_list *e)
342{
343	while (s != e) {
344		struct string_list *next = s->next;
345		free_node(s);
346		s = next;
347	}
348}
349
350static struct string_list *mk_node(const char *string)
351{
352	struct string_list *newnode;
353
354	newnode = xmalloc(sizeof(*newnode));
355	newnode->string = xstrdup(string);
356	newnode->tag = SYM_NORMAL;
357	newnode->next = NULL;
358
359	return newnode;
360}
361
362static struct string_list *concat_list(struct string_list *start, ...)
363{
364	va_list ap;
365	struct string_list *n, *n2;
366
367	if (!start)
368		return NULL;
369	for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
370		for (n2 = n; n2->next; n2 = n2->next)
371			;
372		n2->next = start;
373		start = n;
374	}
375	va_end(ap);
376	return start;
377}
378
379struct string_list *copy_node(struct string_list *node)
380{
381	struct string_list *newnode;
382
383	newnode = xmalloc(sizeof(*newnode));
384	newnode->string = xstrdup(node->string);
385	newnode->tag = node->tag;
386
387	return newnode;
388}
389
390struct string_list *copy_list_range(struct string_list *start,
391				    struct string_list *end)
392{
393	struct string_list *res, *n;
394
395	if (start == end)
396		return NULL;
397	n = res = copy_node(start);
398	for (start = start->next; start != end; start = start->next) {
399		n->next = copy_node(start);
400		n = n->next;
401	}
402	n->next = NULL;
403	return res;
404}
405
406static int equal_list(struct string_list *a, struct string_list *b)
407{
408	while (a && b) {
409		if (a->tag != b->tag || strcmp(a->string, b->string))
410			return 0;
411		a = a->next;
412		b = b->next;
413	}
414
415	return !a && !b;
416}
417
418#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
419
420static struct string_list *read_node(FILE *f)
421{
422	char buffer[256];
423	struct string_list node = {
424		.string = buffer,
425		.tag = SYM_NORMAL };
426	int c;
427
428	while ((c = fgetc(f)) != EOF) {
429		if (c == ' ') {
430			if (node.string == buffer)
431				continue;
432			break;
433		} else if (c == '\n') {
434			if (node.string == buffer)
435				return NULL;
436			ungetc(c, f);
437			break;
438		}
439		if (node.string >= buffer + sizeof(buffer) - 1) {
440			fprintf(stderr, "Token too long\n");
441			exit(1);
442		}
443		*node.string++ = c;
444	}
445	if (node.string == buffer)
446		return NULL;
447	*node.string = 0;
448	node.string = buffer;
449
450	if (node.string[1] == '#') {
451		size_t n;
452
453		for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
454			if (node.string[0] == symbol_types[n].n) {
455				node.tag = n;
456				node.string += 2;
457				return copy_node(&node);
458			}
459		}
460		fprintf(stderr, "Unknown type %c\n", node.string[0]);
461		exit(1);
462	}
463	return copy_node(&node);
464}
465
466static void read_reference(FILE *f)
467{
468	while (!feof(f)) {
469		struct string_list *defn = NULL;
470		struct string_list *sym, *def;
471		int is_extern = 0, is_override = 0;
472		struct symbol *subsym;
473
474		sym = read_node(f);
475		if (sym && sym->tag == SYM_NORMAL &&
476		    !strcmp(sym->string, "override")) {
477			is_override = 1;
478			free_node(sym);
479			sym = read_node(f);
480		}
481		if (!sym)
482			continue;
483		def = read_node(f);
484		if (def && def->tag == SYM_NORMAL &&
485		    !strcmp(def->string, "extern")) {
486			is_extern = 1;
487			free_node(def);
488			def = read_node(f);
489		}
490		while (def) {
491			def->next = defn;
492			defn = def;
493			def = read_node(f);
494		}
495		subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
496					      defn, is_extern);
497		subsym->is_override = is_override;
498		free_node(sym);
499	}
500}
501
502static void print_node(FILE * f, struct string_list *list)
503{
504	if (symbol_types[list->tag].n) {
505		putc(symbol_types[list->tag].n, f);
506		putc('#', f);
507	}
508	fputs(list->string, f);
509}
510
511static void print_list(FILE * f, struct string_list *list)
512{
513	struct string_list **e, **b;
514	struct string_list *tmp, **tmp2;
515	int elem = 1;
516
517	if (list == NULL) {
518		fputs("(nil)", f);
519		return;
520	}
521
522	tmp = list;
523	while ((tmp = tmp->next) != NULL)
524		elem++;
525
526	b = alloca(elem * sizeof(*e));
527	e = b + elem;
528	tmp2 = e - 1;
529
530	(*tmp2--) = list;
531	while ((list = list->next) != NULL)
532		*(tmp2--) = list;
533
534	while (b != e) {
535		print_node(f, *b++);
536		putc(' ', f);
537	}
538}
539
540static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
541{
542	struct string_list *list = sym->defn;
543	struct string_list **e, **b;
544	struct string_list *tmp, **tmp2;
545	int elem = 1;
546
547	if (!list)
548		return crc;
549
550	tmp = list;
551	while ((tmp = tmp->next) != NULL)
552		elem++;
553
554	b = alloca(elem * sizeof(*e));
555	e = b + elem;
556	tmp2 = e - 1;
557
558	*(tmp2--) = list;
559	while ((list = list->next) != NULL)
560		*(tmp2--) = list;
561
562	while (b != e) {
563		struct string_list *cur;
564		struct symbol *subsym;
565
566		cur = *(b++);
567		switch (cur->tag) {
568		case SYM_NORMAL:
569			if (flag_dump_defs)
570				fprintf(debugfile, "%s ", cur->string);
571			crc = partial_crc32(cur->string, crc);
572			crc = partial_crc32_one(' ', crc);
573			break;
574
575		case SYM_ENUM_CONST:
576		case SYM_TYPEDEF:
577			subsym = find_symbol(cur->string, cur->tag, 0);
578			/* FIXME: Bad reference files can segfault here. */
579			if (subsym->expansion_trail) {
580				if (flag_dump_defs)
581					fprintf(debugfile, "%s ", cur->string);
582				crc = partial_crc32(cur->string, crc);
583				crc = partial_crc32_one(' ', crc);
584			} else {
585				subsym->expansion_trail = expansion_trail;
586				expansion_trail = subsym;
587				crc = expand_and_crc_sym(subsym, crc);
588			}
589			break;
590
591		case SYM_STRUCT:
592		case SYM_UNION:
593		case SYM_ENUM:
594			subsym = find_symbol(cur->string, cur->tag, 0);
595			if (!subsym) {
596				struct string_list *n;
597
598				error_with_pos("expand undefined %s %s",
599					       symbol_types[cur->tag].name,
600					       cur->string);
601				n = concat_list(mk_node
602						(symbol_types[cur->tag].name),
603						mk_node(cur->string),
604						mk_node("{"),
605						mk_node("UNKNOWN"),
606						mk_node("}"), NULL);
607				subsym =
608				    add_symbol(cur->string, cur->tag, n, 0);
609			}
610			if (subsym->expansion_trail) {
611				if (flag_dump_defs) {
612					fprintf(debugfile, "%s %s ",
613						symbol_types[cur->tag].name,
614						cur->string);
615				}
616
617				crc = partial_crc32(symbol_types[cur->tag].name,
618						    crc);
619				crc = partial_crc32_one(' ', crc);
620				crc = partial_crc32(cur->string, crc);
621				crc = partial_crc32_one(' ', crc);
622			} else {
623				subsym->expansion_trail = expansion_trail;
624				expansion_trail = subsym;
625				crc = expand_and_crc_sym(subsym, crc);
626			}
627			break;
628		}
629	}
630
631	{
632		static struct symbol **end = &visited_symbols;
633
634		if (!sym->visited) {
635			*end = sym;
636			end = &sym->visited;
637			sym->visited = (struct symbol *)-1L;
638		}
639	}
640
641	return crc;
642}
643
644void export_symbol(const char *name)
645{
646	struct symbol *sym;
647
648	sym = find_symbol(name, SYM_NORMAL, 0);
649	if (!sym)
650		error_with_pos("export undefined symbol %s", name);
651	else {
652		unsigned long crc;
653		int has_changed = 0;
654
655		if (flag_dump_defs)
656			fprintf(debugfile, "Export %s == <", name);
657
658		expansion_trail = (struct symbol *)-1L;
659
660		sym->expansion_trail = expansion_trail;
661		expansion_trail = sym;
662		crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
663
664		sym = expansion_trail;
665		while (sym != (struct symbol *)-1L) {
666			struct symbol *n = sym->expansion_trail;
667
668			if (sym->status != STATUS_UNCHANGED) {
669				if (!has_changed) {
670					print_location();
671					fprintf(stderr, "%s: %s: modversion "
672						"changed because of changes "
673						"in ", flag_preserve ? "error" :
674						       "warning", name);
675				} else
676					fprintf(stderr, ", ");
677				print_type_name(sym->type, sym->name);
678				if (sym->status == STATUS_DEFINED)
679					fprintf(stderr, " (became defined)");
680				has_changed = 1;
681				if (flag_preserve)
682					errors++;
683			}
684			sym->expansion_trail = 0;
685			sym = n;
686		}
687		if (has_changed)
688			fprintf(stderr, "\n");
689
690		if (flag_dump_defs)
691			fputs(">\n", debugfile);
692
693		/* Used as a linker script. */
694		printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
695	}
696}
697
698/*----------------------------------------------------------------------*/
699
700static void print_location(void)
701{
702	fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
703}
704
705static void print_type_name(enum symbol_type type, const char *name)
706{
707	if (symbol_types[type].name)
708		fprintf(stderr, "%s %s", symbol_types[type].name, name);
709	else
710		fprintf(stderr, "%s", name);
711}
712
713void error_with_pos(const char *fmt, ...)
714{
715	va_list args;
716
717	if (flag_warnings) {
718		print_location();
719
720		va_start(args, fmt);
721		vfprintf(stderr, fmt, args);
722		va_end(args);
723		putc('\n', stderr);
724
725		errors++;
726	}
727}
728
729static void genksyms_usage(void)
730{
731	fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
732#ifdef __GNU_LIBRARY__
733	      "  -s, --symbol-prefix   Select symbol prefix\n"
734	      "  -d, --debug           Increment the debug level (repeatable)\n"
735	      "  -D, --dump            Dump expanded symbol defs (for debugging only)\n"
736	      "  -r, --reference file  Read reference symbols from a file\n"
737	      "  -T, --dump-types file Dump expanded types into file\n"
738	      "  -p, --preserve        Preserve reference modversions or fail\n"
739	      "  -w, --warnings        Enable warnings\n"
740	      "  -q, --quiet           Disable warnings (default)\n"
741	      "  -h, --help            Print this message\n"
742	      "  -V, --version         Print the release version\n"
743#else				/* __GNU_LIBRARY__ */
744	      "  -s                    Select symbol prefix\n"
745	      "  -d                    Increment the debug level (repeatable)\n"
746	      "  -D                    Dump expanded symbol defs (for debugging only)\n"
747	      "  -r file               Read reference symbols from a file\n"
748	      "  -T file               Dump expanded types into file\n"
749	      "  -p                    Preserve reference modversions or fail\n"
750	      "  -w                    Enable warnings\n"
751	      "  -q                    Disable warnings (default)\n"
752	      "  -h                    Print this message\n"
753	      "  -V                    Print the release version\n"
754#endif				/* __GNU_LIBRARY__ */
755	      , stderr);
756}
757
758int main(int argc, char **argv)
759{
760	FILE *dumpfile = NULL, *ref_file = NULL;
761	int o;
762
763#ifdef __GNU_LIBRARY__
764	struct option long_opts[] = {
765		{"symbol-prefix", 1, 0, 's'},
766		{"debug", 0, 0, 'd'},
767		{"warnings", 0, 0, 'w'},
768		{"quiet", 0, 0, 'q'},
769		{"dump", 0, 0, 'D'},
770		{"reference", 1, 0, 'r'},
771		{"dump-types", 1, 0, 'T'},
772		{"preserve", 0, 0, 'p'},
773		{"version", 0, 0, 'V'},
774		{"help", 0, 0, 'h'},
775		{0, 0, 0, 0}
776	};
777
778	while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
779				&long_opts[0], NULL)) != EOF)
780#else				/* __GNU_LIBRARY__ */
781	while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
782#endif				/* __GNU_LIBRARY__ */
783		switch (o) {
784		case 's':
785			mod_prefix = optarg;
786			break;
787		case 'd':
788			flag_debug++;
789			break;
790		case 'w':
791			flag_warnings = 1;
792			break;
793		case 'q':
794			flag_warnings = 0;
795			break;
796		case 'V':
797			fputs("genksyms version 2.5.60\n", stderr);
798			break;
799		case 'D':
800			flag_dump_defs = 1;
801			break;
802		case 'r':
803			flag_reference = 1;
804			ref_file = fopen(optarg, "r");
805			if (!ref_file) {
806				perror(optarg);
807				return 1;
808			}
809			break;
810		case 'T':
811			flag_dump_types = 1;
812			dumpfile = fopen(optarg, "w");
813			if (!dumpfile) {
814				perror(optarg);
815				return 1;
816			}
817			break;
818		case 'p':
819			flag_preserve = 1;
820			break;
821		case 'h':
822			genksyms_usage();
823			return 0;
824		default:
825			genksyms_usage();
826			return 1;
827		}
828	{
829		extern int yydebug;
830		extern int yy_flex_debug;
831
832		yydebug = (flag_debug > 1);
833		yy_flex_debug = (flag_debug > 2);
834
835		debugfile = stderr;
836		/* setlinebuf(debugfile); */
837	}
838
839	if (flag_reference) {
840		read_reference(ref_file);
841		fclose(ref_file);
842	}
843
844	yyparse();
845
846	if (flag_dump_types && visited_symbols) {
847		while (visited_symbols != (struct symbol *)-1L) {
848			struct symbol *sym = visited_symbols;
849
850			if (sym->is_override)
851				fputs("override ", dumpfile);
852			if (symbol_types[sym->type].n) {
853				putc(symbol_types[sym->type].n, dumpfile);
854				putc('#', dumpfile);
855			}
856			fputs(sym->name, dumpfile);
857			putc(' ', dumpfile);
858			if (sym->is_extern)
859				fputs("extern ", dumpfile);
860			print_list(dumpfile, sym->defn);
861			putc('\n', dumpfile);
862
863			visited_symbols = sym->visited;
864			sym->visited = NULL;
865		}
866	}
867
868	if (flag_debug) {
869		fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
870			nsyms, HASH_BUCKETS,
871			(double)nsyms / (double)HASH_BUCKETS);
872	}
873
874	return errors != 0;
875}
876