diff options
Diffstat (limited to 'scripts/genksyms/genksyms.c')
-rw-r--r-- | scripts/genksyms/genksyms.c | 192 |
1 files changed, 136 insertions, 56 deletions
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index f99115ebe925..f9e75531ea03 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c | |||
@@ -53,12 +53,22 @@ static int nsyms; | |||
53 | static struct symbol *expansion_trail; | 53 | static struct symbol *expansion_trail; |
54 | static struct symbol *visited_symbols; | 54 | static struct symbol *visited_symbols; |
55 | 55 | ||
56 | static const char *const symbol_type_name[] = { | 56 | static const struct { |
57 | "normal", "typedef", "enum", "struct", "union" | 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"}, | ||
58 | }; | 66 | }; |
59 | 67 | ||
60 | static int equal_list(struct string_list *a, struct string_list *b); | 68 | static int equal_list(struct string_list *a, struct string_list *b); |
61 | static void print_list(FILE * f, struct string_list *list); | 69 | static void print_list(FILE * f, struct string_list *list); |
70 | static struct string_list *concat_list(struct string_list *start, ...); | ||
71 | static struct string_list *mk_node(const char *string); | ||
62 | static void print_location(void); | 72 | static void print_location(void); |
63 | static void print_type_name(enum symbol_type type, const char *name); | 73 | static void print_type_name(enum symbol_type type, const char *name); |
64 | 74 | ||
@@ -140,14 +150,20 @@ static unsigned long crc32(const char *s) | |||
140 | 150 | ||
141 | static enum symbol_type map_to_ns(enum symbol_type t) | 151 | static enum symbol_type map_to_ns(enum symbol_type t) |
142 | { | 152 | { |
143 | if (t == SYM_TYPEDEF) | 153 | switch (t) { |
144 | t = SYM_NORMAL; | 154 | case SYM_ENUM_CONST: |
145 | else if (t == SYM_UNION) | 155 | case SYM_NORMAL: |
146 | t = SYM_STRUCT; | 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 | } | ||
147 | return t; | 163 | return t; |
148 | } | 164 | } |
149 | 165 | ||
150 | struct symbol *find_symbol(const char *name, enum symbol_type ns) | 166 | struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact) |
151 | { | 167 | { |
152 | unsigned long h = crc32(name) % HASH_BUCKETS; | 168 | unsigned long h = crc32(name) % HASH_BUCKETS; |
153 | struct symbol *sym; | 169 | struct symbol *sym; |
@@ -158,6 +174,8 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns) | |||
158 | sym->is_declared) | 174 | sym->is_declared) |
159 | break; | 175 | break; |
160 | 176 | ||
177 | if (exact && sym && sym->type != ns) | ||
178 | return NULL; | ||
161 | return sym; | 179 | return sym; |
162 | } | 180 | } |
163 | 181 | ||
@@ -180,10 +198,47 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type, | |||
180 | struct string_list *defn, int is_extern, | 198 | struct string_list *defn, int is_extern, |
181 | int is_reference) | 199 | int is_reference) |
182 | { | 200 | { |
183 | unsigned long h = crc32(name) % HASH_BUCKETS; | 201 | unsigned long h; |
184 | struct symbol *sym; | 202 | struct symbol *sym; |
185 | enum symbol_status status = STATUS_UNCHANGED; | 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 | } | ||
186 | 240 | ||
241 | h = crc32(name) % HASH_BUCKETS; | ||
187 | for (sym = symtab[h]; sym; sym = sym->hash_next) { | 242 | for (sym = symtab[h]; sym; sym = sym->hash_next) { |
188 | if (map_to_ns(sym->type) == map_to_ns(type) && | 243 | if (map_to_ns(sym->type) == map_to_ns(type) && |
189 | strcmp(name, sym->name) == 0) { | 244 | strcmp(name, sym->name) == 0) { |
@@ -247,8 +302,12 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type, | |||
247 | sym->is_override = 0; | 302 | sym->is_override = 0; |
248 | 303 | ||
249 | if (flag_debug) { | 304 | if (flag_debug) { |
250 | fprintf(debugfile, "Defn for %s %s == <", | 305 | if (symbol_types[type].name) |
251 | symbol_type_name[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); | ||
252 | if (is_extern) | 311 | if (is_extern) |
253 | fputs("extern ", debugfile); | 312 | fputs("extern ", debugfile); |
254 | print_list(debugfile, defn); | 313 | print_list(debugfile, defn); |
@@ -288,6 +347,35 @@ void free_list(struct string_list *s, struct string_list *e) | |||
288 | } | 347 | } |
289 | } | 348 | } |
290 | 349 | ||
350 | static 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 | |||
362 | static 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 | |||
291 | struct string_list *copy_node(struct string_list *node) | 379 | struct string_list *copy_node(struct string_list *node) |
292 | { | 380 | { |
293 | struct string_list *newnode; | 381 | struct string_list *newnode; |
@@ -299,6 +387,22 @@ struct string_list *copy_node(struct string_list *node) | |||
299 | return newnode; | 387 | return newnode; |
300 | } | 388 | } |
301 | 389 | ||
390 | struct 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 | |||
302 | static int equal_list(struct string_list *a, struct string_list *b) | 406 | static int equal_list(struct string_list *a, struct string_list *b) |
303 | { | 407 | { |
304 | while (a && b) { | 408 | while (a && b) { |
@@ -346,8 +450,8 @@ static struct string_list *read_node(FILE *f) | |||
346 | if (node.string[1] == '#') { | 450 | if (node.string[1] == '#') { |
347 | int n; | 451 | int n; |
348 | 452 | ||
349 | for (n = 0; n < ARRAY_SIZE(symbol_type_name); n++) { | 453 | for (n = 0; n < ARRAY_SIZE(symbol_types); n++) { |
350 | if (node.string[0] == symbol_type_name[n][0]) { | 454 | if (node.string[0] == symbol_types[n].n) { |
351 | node.tag = n; | 455 | node.tag = n; |
352 | node.string += 2; | 456 | node.string += 2; |
353 | return copy_node(&node); | 457 | return copy_node(&node); |
@@ -397,8 +501,8 @@ static void read_reference(FILE *f) | |||
397 | 501 | ||
398 | static void print_node(FILE * f, struct string_list *list) | 502 | static void print_node(FILE * f, struct string_list *list) |
399 | { | 503 | { |
400 | if (list->tag != SYM_NORMAL) { | 504 | if (symbol_types[list->tag].n) { |
401 | putc(symbol_type_name[list->tag][0], f); | 505 | putc(symbol_types[list->tag].n, f); |
402 | putc('#', f); | 506 | putc('#', f); |
403 | } | 507 | } |
404 | fputs(list->string, f); | 508 | fputs(list->string, f); |
@@ -468,8 +572,9 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) | |||
468 | crc = partial_crc32_one(' ', crc); | 572 | crc = partial_crc32_one(' ', crc); |
469 | break; | 573 | break; |
470 | 574 | ||
575 | case SYM_ENUM_CONST: | ||
471 | case SYM_TYPEDEF: | 576 | case SYM_TYPEDEF: |
472 | subsym = find_symbol(cur->string, cur->tag); | 577 | subsym = find_symbol(cur->string, cur->tag, 0); |
473 | /* FIXME: Bad reference files can segfault here. */ | 578 | /* FIXME: Bad reference files can segfault here. */ |
474 | if (subsym->expansion_trail) { | 579 | if (subsym->expansion_trail) { |
475 | if (flag_dump_defs) | 580 | if (flag_dump_defs) |
@@ -486,55 +591,30 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) | |||
486 | case SYM_STRUCT: | 591 | case SYM_STRUCT: |
487 | case SYM_UNION: | 592 | case SYM_UNION: |
488 | case SYM_ENUM: | 593 | case SYM_ENUM: |
489 | subsym = find_symbol(cur->string, cur->tag); | 594 | subsym = find_symbol(cur->string, cur->tag, 0); |
490 | if (!subsym) { | 595 | if (!subsym) { |
491 | struct string_list *n, *t = NULL; | 596 | struct string_list *n; |
492 | 597 | ||
493 | error_with_pos("expand undefined %s %s", | 598 | error_with_pos("expand undefined %s %s", |
494 | symbol_type_name[cur->tag], | 599 | symbol_types[cur->tag].name, |
495 | cur->string); | 600 | cur->string); |
496 | 601 | n = concat_list(mk_node | |
497 | n = xmalloc(sizeof(*n)); | 602 | (symbol_types[cur->tag].name), |
498 | n->string = xstrdup(symbol_type_name[cur->tag]); | 603 | mk_node(cur->string), |
499 | n->tag = SYM_NORMAL; | 604 | mk_node("{"), |
500 | n->next = t; | 605 | mk_node("UNKNOWN"), |
501 | t = n; | 606 | mk_node("}"), NULL); |
502 | |||
503 | n = xmalloc(sizeof(*n)); | ||
504 | n->string = xstrdup(cur->string); | ||
505 | n->tag = SYM_NORMAL; | ||
506 | n->next = t; | ||
507 | t = n; | ||
508 | |||
509 | n = xmalloc(sizeof(*n)); | ||
510 | n->string = xstrdup("{"); | ||
511 | n->tag = SYM_NORMAL; | ||
512 | n->next = t; | ||
513 | t = n; | ||
514 | |||
515 | n = xmalloc(sizeof(*n)); | ||
516 | n->string = xstrdup("UNKNOWN"); | ||
517 | n->tag = SYM_NORMAL; | ||
518 | n->next = t; | ||
519 | t = n; | ||
520 | |||
521 | n = xmalloc(sizeof(*n)); | ||
522 | n->string = xstrdup("}"); | ||
523 | n->tag = SYM_NORMAL; | ||
524 | n->next = t; | ||
525 | t = n; | ||
526 | |||
527 | subsym = | 607 | subsym = |
528 | add_symbol(cur->string, cur->tag, n, 0); | 608 | add_symbol(cur->string, cur->tag, n, 0); |
529 | } | 609 | } |
530 | if (subsym->expansion_trail) { | 610 | if (subsym->expansion_trail) { |
531 | if (flag_dump_defs) { | 611 | if (flag_dump_defs) { |
532 | fprintf(debugfile, "%s %s ", | 612 | fprintf(debugfile, "%s %s ", |
533 | symbol_type_name[cur->tag], | 613 | symbol_types[cur->tag].name, |
534 | cur->string); | 614 | cur->string); |
535 | } | 615 | } |
536 | 616 | ||
537 | crc = partial_crc32(symbol_type_name[cur->tag], | 617 | crc = partial_crc32(symbol_types[cur->tag].name, |
538 | crc); | 618 | crc); |
539 | crc = partial_crc32_one(' ', crc); | 619 | crc = partial_crc32_one(' ', crc); |
540 | crc = partial_crc32(cur->string, crc); | 620 | crc = partial_crc32(cur->string, crc); |
@@ -565,7 +645,7 @@ void export_symbol(const char *name) | |||
565 | { | 645 | { |
566 | struct symbol *sym; | 646 | struct symbol *sym; |
567 | 647 | ||
568 | sym = find_symbol(name, SYM_NORMAL); | 648 | sym = find_symbol(name, SYM_NORMAL, 0); |
569 | if (!sym) | 649 | if (!sym) |
570 | error_with_pos("export undefined symbol %s", name); | 650 | error_with_pos("export undefined symbol %s", name); |
571 | else { | 651 | else { |
@@ -624,8 +704,8 @@ static void print_location(void) | |||
624 | 704 | ||
625 | static void print_type_name(enum symbol_type type, const char *name) | 705 | static void print_type_name(enum symbol_type type, const char *name) |
626 | { | 706 | { |
627 | if (type != SYM_NORMAL) | 707 | if (symbol_types[type].name) |
628 | fprintf(stderr, "%s %s", symbol_type_name[type], name); | 708 | fprintf(stderr, "%s %s", symbol_types[type].name, name); |
629 | else | 709 | else |
630 | fprintf(stderr, "%s", name); | 710 | fprintf(stderr, "%s", name); |
631 | } | 711 | } |
@@ -771,8 +851,8 @@ int main(int argc, char **argv) | |||
771 | 851 | ||
772 | if (sym->is_override) | 852 | if (sym->is_override) |
773 | fputs("override ", dumpfile); | 853 | fputs("override ", dumpfile); |
774 | if (sym->type != SYM_NORMAL) { | 854 | if (symbol_types[sym->type].n) { |
775 | putc(symbol_type_name[sym->type][0], dumpfile); | 855 | putc(symbol_types[sym->type].n, dumpfile); |
776 | putc('#', dumpfile); | 856 | putc('#', dumpfile); |
777 | } | 857 | } |
778 | fputs(sym->name, dumpfile); | 858 | fputs(sym->name, dumpfile); |