0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <stdio.h>
0014 #include <string.h>
0015 #include <stdlib.h>
0016 #include <unistd.h>
0017 #include <assert.h>
0018 #include <stdarg.h>
0019 #ifdef __GNU_LIBRARY__
0020 #include <getopt.h>
0021 #endif
0022
0023 #include "genksyms.h"
0024
0025
0026 #define HASH_BUCKETS 4096
0027
0028 static struct symbol *symtab[HASH_BUCKETS];
0029 static FILE *debugfile;
0030
0031 int cur_line = 1;
0032 char *cur_filename;
0033 int in_source_file;
0034
0035 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
0036 flag_preserve, flag_warnings;
0037
0038 static int errors;
0039 static int nsyms;
0040
0041 static struct symbol *expansion_trail;
0042 static struct symbol *visited_symbols;
0043
0044 static const struct {
0045 int n;
0046 const char *name;
0047 } symbol_types[] = {
0048 [SYM_NORMAL] = { 0, NULL},
0049 [SYM_TYPEDEF] = {'t', "typedef"},
0050 [SYM_ENUM] = {'e', "enum"},
0051 [SYM_STRUCT] = {'s', "struct"},
0052 [SYM_UNION] = {'u', "union"},
0053 [SYM_ENUM_CONST] = {'E', "enum constant"},
0054 };
0055
0056 static int equal_list(struct string_list *a, struct string_list *b);
0057 static void print_list(FILE * f, struct string_list *list);
0058 static struct string_list *concat_list(struct string_list *start, ...);
0059 static struct string_list *mk_node(const char *string);
0060 static void print_location(void);
0061 static void print_type_name(enum symbol_type type, const char *name);
0062
0063
0064
0065 static const unsigned int crctab32[] = {
0066 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
0067 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
0068 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
0069 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
0070 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
0071 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
0072 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
0073 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
0074 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
0075 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
0076 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
0077 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
0078 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
0079 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
0080 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
0081 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
0082 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
0083 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
0084 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
0085 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
0086 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
0087 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
0088 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
0089 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
0090 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
0091 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
0092 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
0093 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
0094 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
0095 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
0096 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
0097 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
0098 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
0099 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
0100 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
0101 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
0102 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
0103 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
0104 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
0105 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
0106 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
0107 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
0108 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
0109 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
0110 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
0111 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
0112 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
0113 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
0114 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
0115 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
0116 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
0117 0x2d02ef8dU
0118 };
0119
0120 static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
0121 {
0122 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
0123 }
0124
0125 static unsigned long partial_crc32(const char *s, unsigned long crc)
0126 {
0127 while (*s)
0128 crc = partial_crc32_one(*s++, crc);
0129 return crc;
0130 }
0131
0132 static unsigned long crc32(const char *s)
0133 {
0134 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
0135 }
0136
0137
0138
0139 static enum symbol_type map_to_ns(enum symbol_type t)
0140 {
0141 switch (t) {
0142 case SYM_ENUM_CONST:
0143 case SYM_NORMAL:
0144 case SYM_TYPEDEF:
0145 return SYM_NORMAL;
0146 case SYM_ENUM:
0147 case SYM_STRUCT:
0148 case SYM_UNION:
0149 return SYM_STRUCT;
0150 }
0151 return t;
0152 }
0153
0154 struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
0155 {
0156 unsigned long h = crc32(name) % HASH_BUCKETS;
0157 struct symbol *sym;
0158
0159 for (sym = symtab[h]; sym; sym = sym->hash_next)
0160 if (map_to_ns(sym->type) == map_to_ns(ns) &&
0161 strcmp(name, sym->name) == 0 &&
0162 sym->is_declared)
0163 break;
0164
0165 if (exact && sym && sym->type != ns)
0166 return NULL;
0167 return sym;
0168 }
0169
0170 static int is_unknown_symbol(struct symbol *sym)
0171 {
0172 struct string_list *defn;
0173
0174 return ((sym->type == SYM_STRUCT ||
0175 sym->type == SYM_UNION ||
0176 sym->type == SYM_ENUM) &&
0177 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
0178 strcmp(defn->string, "}") == 0 &&
0179 (defn = defn->next) && defn->tag == SYM_NORMAL &&
0180 strcmp(defn->string, "UNKNOWN") == 0 &&
0181 (defn = defn->next) && defn->tag == SYM_NORMAL &&
0182 strcmp(defn->string, "{") == 0);
0183 }
0184
0185 static struct symbol *__add_symbol(const char *name, enum symbol_type type,
0186 struct string_list *defn, int is_extern,
0187 int is_reference)
0188 {
0189 unsigned long h;
0190 struct symbol *sym;
0191 enum symbol_status status = STATUS_UNCHANGED;
0192
0193
0194
0195
0196 static int enum_counter;
0197 static struct string_list *last_enum_expr;
0198
0199 if (type == SYM_ENUM_CONST) {
0200 if (defn) {
0201 free_list(last_enum_expr, NULL);
0202 last_enum_expr = copy_list_range(defn, NULL);
0203 enum_counter = 1;
0204 } else {
0205 struct string_list *expr;
0206 char buf[20];
0207
0208 snprintf(buf, sizeof(buf), "%d", enum_counter++);
0209 if (last_enum_expr) {
0210 expr = copy_list_range(last_enum_expr, NULL);
0211 defn = concat_list(mk_node("("),
0212 expr,
0213 mk_node(")"),
0214 mk_node("+"),
0215 mk_node(buf), NULL);
0216 } else {
0217 defn = mk_node(buf);
0218 }
0219 }
0220 } else if (type == SYM_ENUM) {
0221 free_list(last_enum_expr, NULL);
0222 last_enum_expr = NULL;
0223 enum_counter = 0;
0224 if (!name)
0225
0226 return NULL;
0227 }
0228
0229 h = crc32(name) % HASH_BUCKETS;
0230 for (sym = symtab[h]; sym; sym = sym->hash_next) {
0231 if (map_to_ns(sym->type) == map_to_ns(type) &&
0232 strcmp(name, sym->name) == 0) {
0233 if (is_reference)
0234 ;
0235 else if (sym->type == type &&
0236 equal_list(sym->defn, defn)) {
0237 if (!sym->is_declared && sym->is_override) {
0238 print_location();
0239 print_type_name(type, name);
0240 fprintf(stderr, " modversion is "
0241 "unchanged\n");
0242 }
0243 sym->is_declared = 1;
0244 return sym;
0245 } else if (!sym->is_declared) {
0246 if (sym->is_override && flag_preserve) {
0247 print_location();
0248 fprintf(stderr, "ignoring ");
0249 print_type_name(type, name);
0250 fprintf(stderr, " modversion change\n");
0251 sym->is_declared = 1;
0252 return sym;
0253 } else {
0254 status = is_unknown_symbol(sym) ?
0255 STATUS_DEFINED : STATUS_MODIFIED;
0256 }
0257 } else {
0258 error_with_pos("redefinition of %s", name);
0259 return sym;
0260 }
0261 break;
0262 }
0263 }
0264
0265 if (sym) {
0266 struct symbol **psym;
0267
0268 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
0269 if (*psym == sym) {
0270 *psym = sym->hash_next;
0271 break;
0272 }
0273 }
0274 --nsyms;
0275 }
0276
0277 sym = xmalloc(sizeof(*sym));
0278 sym->name = name;
0279 sym->type = type;
0280 sym->defn = defn;
0281 sym->expansion_trail = NULL;
0282 sym->visited = NULL;
0283 sym->is_extern = is_extern;
0284
0285 sym->hash_next = symtab[h];
0286 symtab[h] = sym;
0287
0288 sym->is_declared = !is_reference;
0289 sym->status = status;
0290 sym->is_override = 0;
0291
0292 if (flag_debug) {
0293 if (symbol_types[type].name)
0294 fprintf(debugfile, "Defn for %s %s == <",
0295 symbol_types[type].name, name);
0296 else
0297 fprintf(debugfile, "Defn for type%d %s == <",
0298 type, name);
0299 if (is_extern)
0300 fputs("extern ", debugfile);
0301 print_list(debugfile, defn);
0302 fputs(">\n", debugfile);
0303 }
0304
0305 ++nsyms;
0306 return sym;
0307 }
0308
0309 struct symbol *add_symbol(const char *name, enum symbol_type type,
0310 struct string_list *defn, int is_extern)
0311 {
0312 return __add_symbol(name, type, defn, is_extern, 0);
0313 }
0314
0315 static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
0316 struct string_list *defn, int is_extern)
0317 {
0318 return __add_symbol(name, type, defn, is_extern, 1);
0319 }
0320
0321
0322
0323 void free_node(struct string_list *node)
0324 {
0325 free(node->string);
0326 free(node);
0327 }
0328
0329 void free_list(struct string_list *s, struct string_list *e)
0330 {
0331 while (s != e) {
0332 struct string_list *next = s->next;
0333 free_node(s);
0334 s = next;
0335 }
0336 }
0337
0338 static struct string_list *mk_node(const char *string)
0339 {
0340 struct string_list *newnode;
0341
0342 newnode = xmalloc(sizeof(*newnode));
0343 newnode->string = xstrdup(string);
0344 newnode->tag = SYM_NORMAL;
0345 newnode->next = NULL;
0346
0347 return newnode;
0348 }
0349
0350 static struct string_list *concat_list(struct string_list *start, ...)
0351 {
0352 va_list ap;
0353 struct string_list *n, *n2;
0354
0355 if (!start)
0356 return NULL;
0357 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
0358 for (n2 = n; n2->next; n2 = n2->next)
0359 ;
0360 n2->next = start;
0361 start = n;
0362 }
0363 va_end(ap);
0364 return start;
0365 }
0366
0367 struct string_list *copy_node(struct string_list *node)
0368 {
0369 struct string_list *newnode;
0370
0371 newnode = xmalloc(sizeof(*newnode));
0372 newnode->string = xstrdup(node->string);
0373 newnode->tag = node->tag;
0374
0375 return newnode;
0376 }
0377
0378 struct string_list *copy_list_range(struct string_list *start,
0379 struct string_list *end)
0380 {
0381 struct string_list *res, *n;
0382
0383 if (start == end)
0384 return NULL;
0385 n = res = copy_node(start);
0386 for (start = start->next; start != end; start = start->next) {
0387 n->next = copy_node(start);
0388 n = n->next;
0389 }
0390 n->next = NULL;
0391 return res;
0392 }
0393
0394 static int equal_list(struct string_list *a, struct string_list *b)
0395 {
0396 while (a && b) {
0397 if (a->tag != b->tag || strcmp(a->string, b->string))
0398 return 0;
0399 a = a->next;
0400 b = b->next;
0401 }
0402
0403 return !a && !b;
0404 }
0405
0406 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
0407
0408 static struct string_list *read_node(FILE *f)
0409 {
0410 char buffer[256];
0411 struct string_list node = {
0412 .string = buffer,
0413 .tag = SYM_NORMAL };
0414 int c, in_string = 0;
0415
0416 while ((c = fgetc(f)) != EOF) {
0417 if (!in_string && c == ' ') {
0418 if (node.string == buffer)
0419 continue;
0420 break;
0421 } else if (c == '"') {
0422 in_string = !in_string;
0423 } else if (c == '\n') {
0424 if (node.string == buffer)
0425 return NULL;
0426 ungetc(c, f);
0427 break;
0428 }
0429 if (node.string >= buffer + sizeof(buffer) - 1) {
0430 fprintf(stderr, "Token too long\n");
0431 exit(1);
0432 }
0433 *node.string++ = c;
0434 }
0435 if (node.string == buffer)
0436 return NULL;
0437 *node.string = 0;
0438 node.string = buffer;
0439
0440 if (node.string[1] == '#') {
0441 size_t n;
0442
0443 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
0444 if (node.string[0] == symbol_types[n].n) {
0445 node.tag = n;
0446 node.string += 2;
0447 return copy_node(&node);
0448 }
0449 }
0450 fprintf(stderr, "Unknown type %c\n", node.string[0]);
0451 exit(1);
0452 }
0453 return copy_node(&node);
0454 }
0455
0456 static void read_reference(FILE *f)
0457 {
0458 while (!feof(f)) {
0459 struct string_list *defn = NULL;
0460 struct string_list *sym, *def;
0461 int is_extern = 0, is_override = 0;
0462 struct symbol *subsym;
0463
0464 sym = read_node(f);
0465 if (sym && sym->tag == SYM_NORMAL &&
0466 !strcmp(sym->string, "override")) {
0467 is_override = 1;
0468 free_node(sym);
0469 sym = read_node(f);
0470 }
0471 if (!sym)
0472 continue;
0473 def = read_node(f);
0474 if (def && def->tag == SYM_NORMAL &&
0475 !strcmp(def->string, "extern")) {
0476 is_extern = 1;
0477 free_node(def);
0478 def = read_node(f);
0479 }
0480 while (def) {
0481 def->next = defn;
0482 defn = def;
0483 def = read_node(f);
0484 }
0485 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
0486 defn, is_extern);
0487 subsym->is_override = is_override;
0488 free_node(sym);
0489 }
0490 }
0491
0492 static void print_node(FILE * f, struct string_list *list)
0493 {
0494 if (symbol_types[list->tag].n) {
0495 putc(symbol_types[list->tag].n, f);
0496 putc('#', f);
0497 }
0498 fputs(list->string, f);
0499 }
0500
0501 static void print_list(FILE * f, struct string_list *list)
0502 {
0503 struct string_list **e, **b;
0504 struct string_list *tmp, **tmp2;
0505 int elem = 1;
0506
0507 if (list == NULL) {
0508 fputs("(nil)", f);
0509 return;
0510 }
0511
0512 tmp = list;
0513 while ((tmp = tmp->next) != NULL)
0514 elem++;
0515
0516 b = alloca(elem * sizeof(*e));
0517 e = b + elem;
0518 tmp2 = e - 1;
0519
0520 (*tmp2--) = list;
0521 while ((list = list->next) != NULL)
0522 *(tmp2--) = list;
0523
0524 while (b != e) {
0525 print_node(f, *b++);
0526 putc(' ', f);
0527 }
0528 }
0529
0530 static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
0531 {
0532 struct string_list *list = sym->defn;
0533 struct string_list **e, **b;
0534 struct string_list *tmp, **tmp2;
0535 int elem = 1;
0536
0537 if (!list)
0538 return crc;
0539
0540 tmp = list;
0541 while ((tmp = tmp->next) != NULL)
0542 elem++;
0543
0544 b = alloca(elem * sizeof(*e));
0545 e = b + elem;
0546 tmp2 = e - 1;
0547
0548 *(tmp2--) = list;
0549 while ((list = list->next) != NULL)
0550 *(tmp2--) = list;
0551
0552 while (b != e) {
0553 struct string_list *cur;
0554 struct symbol *subsym;
0555
0556 cur = *(b++);
0557 switch (cur->tag) {
0558 case SYM_NORMAL:
0559 if (flag_dump_defs)
0560 fprintf(debugfile, "%s ", cur->string);
0561 crc = partial_crc32(cur->string, crc);
0562 crc = partial_crc32_one(' ', crc);
0563 break;
0564
0565 case SYM_ENUM_CONST:
0566 case SYM_TYPEDEF:
0567 subsym = find_symbol(cur->string, cur->tag, 0);
0568
0569 if (subsym->expansion_trail) {
0570 if (flag_dump_defs)
0571 fprintf(debugfile, "%s ", cur->string);
0572 crc = partial_crc32(cur->string, crc);
0573 crc = partial_crc32_one(' ', crc);
0574 } else {
0575 subsym->expansion_trail = expansion_trail;
0576 expansion_trail = subsym;
0577 crc = expand_and_crc_sym(subsym, crc);
0578 }
0579 break;
0580
0581 case SYM_STRUCT:
0582 case SYM_UNION:
0583 case SYM_ENUM:
0584 subsym = find_symbol(cur->string, cur->tag, 0);
0585 if (!subsym) {
0586 struct string_list *n;
0587
0588 error_with_pos("expand undefined %s %s",
0589 symbol_types[cur->tag].name,
0590 cur->string);
0591 n = concat_list(mk_node
0592 (symbol_types[cur->tag].name),
0593 mk_node(cur->string),
0594 mk_node("{"),
0595 mk_node("UNKNOWN"),
0596 mk_node("}"), NULL);
0597 subsym =
0598 add_symbol(cur->string, cur->tag, n, 0);
0599 }
0600 if (subsym->expansion_trail) {
0601 if (flag_dump_defs) {
0602 fprintf(debugfile, "%s %s ",
0603 symbol_types[cur->tag].name,
0604 cur->string);
0605 }
0606
0607 crc = partial_crc32(symbol_types[cur->tag].name,
0608 crc);
0609 crc = partial_crc32_one(' ', crc);
0610 crc = partial_crc32(cur->string, crc);
0611 crc = partial_crc32_one(' ', crc);
0612 } else {
0613 subsym->expansion_trail = expansion_trail;
0614 expansion_trail = subsym;
0615 crc = expand_and_crc_sym(subsym, crc);
0616 }
0617 break;
0618 }
0619 }
0620
0621 {
0622 static struct symbol **end = &visited_symbols;
0623
0624 if (!sym->visited) {
0625 *end = sym;
0626 end = &sym->visited;
0627 sym->visited = (struct symbol *)-1L;
0628 }
0629 }
0630
0631 return crc;
0632 }
0633
0634 void export_symbol(const char *name)
0635 {
0636 struct symbol *sym;
0637
0638 sym = find_symbol(name, SYM_NORMAL, 0);
0639 if (!sym)
0640 error_with_pos("export undefined symbol %s", name);
0641 else {
0642 unsigned long crc;
0643 int has_changed = 0;
0644
0645 if (flag_dump_defs)
0646 fprintf(debugfile, "Export %s == <", name);
0647
0648 expansion_trail = (struct symbol *)-1L;
0649
0650 sym->expansion_trail = expansion_trail;
0651 expansion_trail = sym;
0652 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
0653
0654 sym = expansion_trail;
0655 while (sym != (struct symbol *)-1L) {
0656 struct symbol *n = sym->expansion_trail;
0657
0658 if (sym->status != STATUS_UNCHANGED) {
0659 if (!has_changed) {
0660 print_location();
0661 fprintf(stderr, "%s: %s: modversion "
0662 "changed because of changes "
0663 "in ", flag_preserve ? "error" :
0664 "warning", name);
0665 } else
0666 fprintf(stderr, ", ");
0667 print_type_name(sym->type, sym->name);
0668 if (sym->status == STATUS_DEFINED)
0669 fprintf(stderr, " (became defined)");
0670 has_changed = 1;
0671 if (flag_preserve)
0672 errors++;
0673 }
0674 sym->expansion_trail = 0;
0675 sym = n;
0676 }
0677 if (has_changed)
0678 fprintf(stderr, "\n");
0679
0680 if (flag_dump_defs)
0681 fputs(">\n", debugfile);
0682
0683 printf("#SYMVER %s 0x%08lx\n", name, crc);
0684 }
0685 }
0686
0687
0688
0689 static void print_location(void)
0690 {
0691 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
0692 }
0693
0694 static void print_type_name(enum symbol_type type, const char *name)
0695 {
0696 if (symbol_types[type].name)
0697 fprintf(stderr, "%s %s", symbol_types[type].name, name);
0698 else
0699 fprintf(stderr, "%s", name);
0700 }
0701
0702 void error_with_pos(const char *fmt, ...)
0703 {
0704 va_list args;
0705
0706 if (flag_warnings) {
0707 print_location();
0708
0709 va_start(args, fmt);
0710 vfprintf(stderr, fmt, args);
0711 va_end(args);
0712 putc('\n', stderr);
0713
0714 errors++;
0715 }
0716 }
0717
0718 static void genksyms_usage(void)
0719 {
0720 fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
0721 #ifdef __GNU_LIBRARY__
0722 " -s, --symbol-prefix Select symbol prefix\n"
0723 " -d, --debug Increment the debug level (repeatable)\n"
0724 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
0725 " -r, --reference file Read reference symbols from a file\n"
0726 " -T, --dump-types file Dump expanded types into file\n"
0727 " -p, --preserve Preserve reference modversions or fail\n"
0728 " -w, --warnings Enable warnings\n"
0729 " -q, --quiet Disable warnings (default)\n"
0730 " -h, --help Print this message\n"
0731 " -V, --version Print the release version\n"
0732 #else
0733 " -s Select symbol prefix\n"
0734 " -d Increment the debug level (repeatable)\n"
0735 " -D Dump expanded symbol defs (for debugging only)\n"
0736 " -r file Read reference symbols from a file\n"
0737 " -T file Dump expanded types into file\n"
0738 " -p Preserve reference modversions or fail\n"
0739 " -w Enable warnings\n"
0740 " -q Disable warnings (default)\n"
0741 " -h Print this message\n"
0742 " -V Print the release version\n"
0743 #endif
0744 , stderr);
0745 }
0746
0747 int main(int argc, char **argv)
0748 {
0749 FILE *dumpfile = NULL, *ref_file = NULL;
0750 int o;
0751
0752 #ifdef __GNU_LIBRARY__
0753 struct option long_opts[] = {
0754 {"debug", 0, 0, 'd'},
0755 {"warnings", 0, 0, 'w'},
0756 {"quiet", 0, 0, 'q'},
0757 {"dump", 0, 0, 'D'},
0758 {"reference", 1, 0, 'r'},
0759 {"dump-types", 1, 0, 'T'},
0760 {"preserve", 0, 0, 'p'},
0761 {"version", 0, 0, 'V'},
0762 {"help", 0, 0, 'h'},
0763 {0, 0, 0, 0}
0764 };
0765
0766 while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
0767 &long_opts[0], NULL)) != EOF)
0768 #else
0769 while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
0770 #endif
0771 switch (o) {
0772 case 'd':
0773 flag_debug++;
0774 break;
0775 case 'w':
0776 flag_warnings = 1;
0777 break;
0778 case 'q':
0779 flag_warnings = 0;
0780 break;
0781 case 'V':
0782 fputs("genksyms version 2.5.60\n", stderr);
0783 break;
0784 case 'D':
0785 flag_dump_defs = 1;
0786 break;
0787 case 'r':
0788 flag_reference = 1;
0789 ref_file = fopen(optarg, "r");
0790 if (!ref_file) {
0791 perror(optarg);
0792 return 1;
0793 }
0794 break;
0795 case 'T':
0796 flag_dump_types = 1;
0797 dumpfile = fopen(optarg, "w");
0798 if (!dumpfile) {
0799 perror(optarg);
0800 return 1;
0801 }
0802 break;
0803 case 'p':
0804 flag_preserve = 1;
0805 break;
0806 case 'h':
0807 genksyms_usage();
0808 return 0;
0809 default:
0810 genksyms_usage();
0811 return 1;
0812 }
0813 {
0814 extern int yydebug;
0815 extern int yy_flex_debug;
0816
0817 yydebug = (flag_debug > 1);
0818 yy_flex_debug = (flag_debug > 2);
0819
0820 debugfile = stderr;
0821
0822 }
0823
0824 if (flag_reference) {
0825 read_reference(ref_file);
0826 fclose(ref_file);
0827 }
0828
0829 yyparse();
0830
0831 if (flag_dump_types && visited_symbols) {
0832 while (visited_symbols != (struct symbol *)-1L) {
0833 struct symbol *sym = visited_symbols;
0834
0835 if (sym->is_override)
0836 fputs("override ", dumpfile);
0837 if (symbol_types[sym->type].n) {
0838 putc(symbol_types[sym->type].n, dumpfile);
0839 putc('#', dumpfile);
0840 }
0841 fputs(sym->name, dumpfile);
0842 putc(' ', dumpfile);
0843 if (sym->is_extern)
0844 fputs("extern ", dumpfile);
0845 print_list(dumpfile, sym->defn);
0846 putc('\n', dumpfile);
0847
0848 visited_symbols = sym->visited;
0849 sym->visited = NULL;
0850 }
0851 }
0852
0853 if (flag_debug) {
0854 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
0855 nsyms, HASH_BUCKETS,
0856 (double)nsyms / (double)HASH_BUCKETS);
0857 }
0858
0859 if (dumpfile)
0860 fclose(dumpfile);
0861
0862 return errors != 0;
0863 }