162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* Generate kernel symbol version hashes. 362306a36Sopenharmony_ci Copyright 1996, 1997 Linux International. 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci New implementation contributed by Richard Henderson <rth@tamu.edu> 662306a36Sopenharmony_ci Based on original work by Bjorn Ekwall <bj0rn@blox.se> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci This file was part of the Linux modutils 2.4.22: moved back into the 962306a36Sopenharmony_ci kernel sources by Rusty Russell/Kai Germaschewski. 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <stdio.h> 1462306a36Sopenharmony_ci#include <string.h> 1562306a36Sopenharmony_ci#include <stdlib.h> 1662306a36Sopenharmony_ci#include <unistd.h> 1762306a36Sopenharmony_ci#include <assert.h> 1862306a36Sopenharmony_ci#include <stdarg.h> 1962306a36Sopenharmony_ci#ifdef __GNU_LIBRARY__ 2062306a36Sopenharmony_ci#include <getopt.h> 2162306a36Sopenharmony_ci#endif /* __GNU_LIBRARY__ */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "genksyms.h" 2462306a36Sopenharmony_ci/*----------------------------------------------------------------------*/ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define HASH_BUCKETS 4096 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic struct symbol *symtab[HASH_BUCKETS]; 2962306a36Sopenharmony_cistatic FILE *debugfile; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciint cur_line = 1; 3262306a36Sopenharmony_cichar *cur_filename; 3362306a36Sopenharmony_ciint in_source_file; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic int flag_debug, flag_dump_defs, flag_reference, flag_dump_types, 3662306a36Sopenharmony_ci flag_preserve, flag_warnings; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic int errors; 3962306a36Sopenharmony_cistatic int nsyms; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic struct symbol *expansion_trail; 4262306a36Sopenharmony_cistatic struct symbol *visited_symbols; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct { 4562306a36Sopenharmony_ci int n; 4662306a36Sopenharmony_ci const char *name; 4762306a36Sopenharmony_ci} symbol_types[] = { 4862306a36Sopenharmony_ci [SYM_NORMAL] = { 0, NULL}, 4962306a36Sopenharmony_ci [SYM_TYPEDEF] = {'t', "typedef"}, 5062306a36Sopenharmony_ci [SYM_ENUM] = {'e', "enum"}, 5162306a36Sopenharmony_ci [SYM_STRUCT] = {'s', "struct"}, 5262306a36Sopenharmony_ci [SYM_UNION] = {'u', "union"}, 5362306a36Sopenharmony_ci [SYM_ENUM_CONST] = {'E', "enum constant"}, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic int equal_list(struct string_list *a, struct string_list *b); 5762306a36Sopenharmony_cistatic void print_list(FILE * f, struct string_list *list); 5862306a36Sopenharmony_cistatic struct string_list *concat_list(struct string_list *start, ...); 5962306a36Sopenharmony_cistatic struct string_list *mk_node(const char *string); 6062306a36Sopenharmony_cistatic void print_location(void); 6162306a36Sopenharmony_cistatic void print_type_name(enum symbol_type type, const char *name); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/*----------------------------------------------------------------------*/ 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic const unsigned int crctab32[] = { 6662306a36Sopenharmony_ci 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 6762306a36Sopenharmony_ci 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 6862306a36Sopenharmony_ci 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 6962306a36Sopenharmony_ci 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 7062306a36Sopenharmony_ci 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, 7162306a36Sopenharmony_ci 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, 7262306a36Sopenharmony_ci 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 7362306a36Sopenharmony_ci 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 7462306a36Sopenharmony_ci 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 7562306a36Sopenharmony_ci 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, 7662306a36Sopenharmony_ci 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 7762306a36Sopenharmony_ci 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 7862306a36Sopenharmony_ci 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, 7962306a36Sopenharmony_ci 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 8062306a36Sopenharmony_ci 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 8162306a36Sopenharmony_ci 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, 8262306a36Sopenharmony_ci 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, 8362306a36Sopenharmony_ci 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, 8462306a36Sopenharmony_ci 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 8562306a36Sopenharmony_ci 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 8662306a36Sopenharmony_ci 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, 8762306a36Sopenharmony_ci 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 8862306a36Sopenharmony_ci 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 8962306a36Sopenharmony_ci 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, 9062306a36Sopenharmony_ci 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 9162306a36Sopenharmony_ci 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 9262306a36Sopenharmony_ci 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, 9362306a36Sopenharmony_ci 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 9462306a36Sopenharmony_ci 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, 9562306a36Sopenharmony_ci 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 9662306a36Sopenharmony_ci 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 9762306a36Sopenharmony_ci 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 9862306a36Sopenharmony_ci 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 9962306a36Sopenharmony_ci 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, 10062306a36Sopenharmony_ci 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 10162306a36Sopenharmony_ci 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 10262306a36Sopenharmony_ci 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, 10362306a36Sopenharmony_ci 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 10462306a36Sopenharmony_ci 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 10562306a36Sopenharmony_ci 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, 10662306a36Sopenharmony_ci 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, 10762306a36Sopenharmony_ci 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, 10862306a36Sopenharmony_ci 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 10962306a36Sopenharmony_ci 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 11062306a36Sopenharmony_ci 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, 11162306a36Sopenharmony_ci 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 11262306a36Sopenharmony_ci 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 11362306a36Sopenharmony_ci 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, 11462306a36Sopenharmony_ci 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 11562306a36Sopenharmony_ci 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 11662306a36Sopenharmony_ci 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 11762306a36Sopenharmony_ci 0x2d02ef8dU 11862306a36Sopenharmony_ci}; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic unsigned long partial_crc32_one(unsigned char c, unsigned long crc) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic unsigned long partial_crc32(const char *s, unsigned long crc) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci while (*s) 12862306a36Sopenharmony_ci crc = partial_crc32_one(*s++, crc); 12962306a36Sopenharmony_ci return crc; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic unsigned long crc32(const char *s) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci return partial_crc32(s, 0xffffffff) ^ 0xffffffff; 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/*----------------------------------------------------------------------*/ 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic enum symbol_type map_to_ns(enum symbol_type t) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci switch (t) { 14262306a36Sopenharmony_ci case SYM_ENUM_CONST: 14362306a36Sopenharmony_ci case SYM_NORMAL: 14462306a36Sopenharmony_ci case SYM_TYPEDEF: 14562306a36Sopenharmony_ci return SYM_NORMAL; 14662306a36Sopenharmony_ci case SYM_ENUM: 14762306a36Sopenharmony_ci case SYM_STRUCT: 14862306a36Sopenharmony_ci case SYM_UNION: 14962306a36Sopenharmony_ci return SYM_STRUCT; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci return t; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistruct symbol *find_symbol(const char *name, enum symbol_type ns, int exact) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci unsigned long h = crc32(name) % HASH_BUCKETS; 15762306a36Sopenharmony_ci struct symbol *sym; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci for (sym = symtab[h]; sym; sym = sym->hash_next) 16062306a36Sopenharmony_ci if (map_to_ns(sym->type) == map_to_ns(ns) && 16162306a36Sopenharmony_ci strcmp(name, sym->name) == 0 && 16262306a36Sopenharmony_ci sym->is_declared) 16362306a36Sopenharmony_ci break; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci if (exact && sym && sym->type != ns) 16662306a36Sopenharmony_ci return NULL; 16762306a36Sopenharmony_ci return sym; 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic int is_unknown_symbol(struct symbol *sym) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct string_list *defn; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci return ((sym->type == SYM_STRUCT || 17562306a36Sopenharmony_ci sym->type == SYM_UNION || 17662306a36Sopenharmony_ci sym->type == SYM_ENUM) && 17762306a36Sopenharmony_ci (defn = sym->defn) && defn->tag == SYM_NORMAL && 17862306a36Sopenharmony_ci strcmp(defn->string, "}") == 0 && 17962306a36Sopenharmony_ci (defn = defn->next) && defn->tag == SYM_NORMAL && 18062306a36Sopenharmony_ci strcmp(defn->string, "UNKNOWN") == 0 && 18162306a36Sopenharmony_ci (defn = defn->next) && defn->tag == SYM_NORMAL && 18262306a36Sopenharmony_ci strcmp(defn->string, "{") == 0); 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic struct symbol *__add_symbol(const char *name, enum symbol_type type, 18662306a36Sopenharmony_ci struct string_list *defn, int is_extern, 18762306a36Sopenharmony_ci int is_reference) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci unsigned long h; 19062306a36Sopenharmony_ci struct symbol *sym; 19162306a36Sopenharmony_ci enum symbol_status status = STATUS_UNCHANGED; 19262306a36Sopenharmony_ci /* The parser adds symbols in the order their declaration completes, 19362306a36Sopenharmony_ci * so it is safe to store the value of the previous enum constant in 19462306a36Sopenharmony_ci * a static variable. 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ci static int enum_counter; 19762306a36Sopenharmony_ci static struct string_list *last_enum_expr; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci if (type == SYM_ENUM_CONST) { 20062306a36Sopenharmony_ci if (defn) { 20162306a36Sopenharmony_ci free_list(last_enum_expr, NULL); 20262306a36Sopenharmony_ci last_enum_expr = copy_list_range(defn, NULL); 20362306a36Sopenharmony_ci enum_counter = 1; 20462306a36Sopenharmony_ci } else { 20562306a36Sopenharmony_ci struct string_list *expr; 20662306a36Sopenharmony_ci char buf[20]; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "%d", enum_counter++); 20962306a36Sopenharmony_ci if (last_enum_expr) { 21062306a36Sopenharmony_ci expr = copy_list_range(last_enum_expr, NULL); 21162306a36Sopenharmony_ci defn = concat_list(mk_node("("), 21262306a36Sopenharmony_ci expr, 21362306a36Sopenharmony_ci mk_node(")"), 21462306a36Sopenharmony_ci mk_node("+"), 21562306a36Sopenharmony_ci mk_node(buf), NULL); 21662306a36Sopenharmony_ci } else { 21762306a36Sopenharmony_ci defn = mk_node(buf); 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci } else if (type == SYM_ENUM) { 22162306a36Sopenharmony_ci free_list(last_enum_expr, NULL); 22262306a36Sopenharmony_ci last_enum_expr = NULL; 22362306a36Sopenharmony_ci enum_counter = 0; 22462306a36Sopenharmony_ci if (!name) 22562306a36Sopenharmony_ci /* Anonymous enum definition, nothing more to do */ 22662306a36Sopenharmony_ci return NULL; 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci h = crc32(name) % HASH_BUCKETS; 23062306a36Sopenharmony_ci for (sym = symtab[h]; sym; sym = sym->hash_next) { 23162306a36Sopenharmony_ci if (map_to_ns(sym->type) == map_to_ns(type) && 23262306a36Sopenharmony_ci strcmp(name, sym->name) == 0) { 23362306a36Sopenharmony_ci if (is_reference) 23462306a36Sopenharmony_ci /* fall through */ ; 23562306a36Sopenharmony_ci else if (sym->type == type && 23662306a36Sopenharmony_ci equal_list(sym->defn, defn)) { 23762306a36Sopenharmony_ci if (!sym->is_declared && sym->is_override) { 23862306a36Sopenharmony_ci print_location(); 23962306a36Sopenharmony_ci print_type_name(type, name); 24062306a36Sopenharmony_ci fprintf(stderr, " modversion is " 24162306a36Sopenharmony_ci "unchanged\n"); 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci sym->is_declared = 1; 24462306a36Sopenharmony_ci return sym; 24562306a36Sopenharmony_ci } else if (!sym->is_declared) { 24662306a36Sopenharmony_ci if (sym->is_override && flag_preserve) { 24762306a36Sopenharmony_ci print_location(); 24862306a36Sopenharmony_ci fprintf(stderr, "ignoring "); 24962306a36Sopenharmony_ci print_type_name(type, name); 25062306a36Sopenharmony_ci fprintf(stderr, " modversion change\n"); 25162306a36Sopenharmony_ci sym->is_declared = 1; 25262306a36Sopenharmony_ci return sym; 25362306a36Sopenharmony_ci } else { 25462306a36Sopenharmony_ci status = is_unknown_symbol(sym) ? 25562306a36Sopenharmony_ci STATUS_DEFINED : STATUS_MODIFIED; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci } else { 25862306a36Sopenharmony_ci error_with_pos("redefinition of %s", name); 25962306a36Sopenharmony_ci return sym; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (sym) { 26662306a36Sopenharmony_ci struct symbol **psym; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) { 26962306a36Sopenharmony_ci if (*psym == sym) { 27062306a36Sopenharmony_ci *psym = sym->hash_next; 27162306a36Sopenharmony_ci break; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci --nsyms; 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci sym = xmalloc(sizeof(*sym)); 27862306a36Sopenharmony_ci sym->name = name; 27962306a36Sopenharmony_ci sym->type = type; 28062306a36Sopenharmony_ci sym->defn = defn; 28162306a36Sopenharmony_ci sym->expansion_trail = NULL; 28262306a36Sopenharmony_ci sym->visited = NULL; 28362306a36Sopenharmony_ci sym->is_extern = is_extern; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci sym->hash_next = symtab[h]; 28662306a36Sopenharmony_ci symtab[h] = sym; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci sym->is_declared = !is_reference; 28962306a36Sopenharmony_ci sym->status = status; 29062306a36Sopenharmony_ci sym->is_override = 0; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (flag_debug) { 29362306a36Sopenharmony_ci if (symbol_types[type].name) 29462306a36Sopenharmony_ci fprintf(debugfile, "Defn for %s %s == <", 29562306a36Sopenharmony_ci symbol_types[type].name, name); 29662306a36Sopenharmony_ci else 29762306a36Sopenharmony_ci fprintf(debugfile, "Defn for type%d %s == <", 29862306a36Sopenharmony_ci type, name); 29962306a36Sopenharmony_ci if (is_extern) 30062306a36Sopenharmony_ci fputs("extern ", debugfile); 30162306a36Sopenharmony_ci print_list(debugfile, defn); 30262306a36Sopenharmony_ci fputs(">\n", debugfile); 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci ++nsyms; 30662306a36Sopenharmony_ci return sym; 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistruct symbol *add_symbol(const char *name, enum symbol_type type, 31062306a36Sopenharmony_ci struct string_list *defn, int is_extern) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci return __add_symbol(name, type, defn, is_extern, 0); 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic struct symbol *add_reference_symbol(const char *name, enum symbol_type type, 31662306a36Sopenharmony_ci struct string_list *defn, int is_extern) 31762306a36Sopenharmony_ci{ 31862306a36Sopenharmony_ci return __add_symbol(name, type, defn, is_extern, 1); 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/*----------------------------------------------------------------------*/ 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_civoid free_node(struct string_list *node) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci free(node->string); 32662306a36Sopenharmony_ci free(node); 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_civoid free_list(struct string_list *s, struct string_list *e) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci while (s != e) { 33262306a36Sopenharmony_ci struct string_list *next = s->next; 33362306a36Sopenharmony_ci free_node(s); 33462306a36Sopenharmony_ci s = next; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic struct string_list *mk_node(const char *string) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci struct string_list *newnode; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci newnode = xmalloc(sizeof(*newnode)); 34362306a36Sopenharmony_ci newnode->string = xstrdup(string); 34462306a36Sopenharmony_ci newnode->tag = SYM_NORMAL; 34562306a36Sopenharmony_ci newnode->next = NULL; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci return newnode; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic struct string_list *concat_list(struct string_list *start, ...) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci va_list ap; 35362306a36Sopenharmony_ci struct string_list *n, *n2; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (!start) 35662306a36Sopenharmony_ci return NULL; 35762306a36Sopenharmony_ci for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) { 35862306a36Sopenharmony_ci for (n2 = n; n2->next; n2 = n2->next) 35962306a36Sopenharmony_ci ; 36062306a36Sopenharmony_ci n2->next = start; 36162306a36Sopenharmony_ci start = n; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci va_end(ap); 36462306a36Sopenharmony_ci return start; 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistruct string_list *copy_node(struct string_list *node) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci struct string_list *newnode; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci newnode = xmalloc(sizeof(*newnode)); 37262306a36Sopenharmony_ci newnode->string = xstrdup(node->string); 37362306a36Sopenharmony_ci newnode->tag = node->tag; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci return newnode; 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistruct string_list *copy_list_range(struct string_list *start, 37962306a36Sopenharmony_ci struct string_list *end) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci struct string_list *res, *n; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci if (start == end) 38462306a36Sopenharmony_ci return NULL; 38562306a36Sopenharmony_ci n = res = copy_node(start); 38662306a36Sopenharmony_ci for (start = start->next; start != end; start = start->next) { 38762306a36Sopenharmony_ci n->next = copy_node(start); 38862306a36Sopenharmony_ci n = n->next; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci n->next = NULL; 39162306a36Sopenharmony_ci return res; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_cistatic int equal_list(struct string_list *a, struct string_list *b) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci while (a && b) { 39762306a36Sopenharmony_ci if (a->tag != b->tag || strcmp(a->string, b->string)) 39862306a36Sopenharmony_ci return 0; 39962306a36Sopenharmony_ci a = a->next; 40062306a36Sopenharmony_ci b = b->next; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci return !a && !b; 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic struct string_list *read_node(FILE *f) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci char buffer[256]; 41162306a36Sopenharmony_ci struct string_list node = { 41262306a36Sopenharmony_ci .string = buffer, 41362306a36Sopenharmony_ci .tag = SYM_NORMAL }; 41462306a36Sopenharmony_ci int c, in_string = 0; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci while ((c = fgetc(f)) != EOF) { 41762306a36Sopenharmony_ci if (!in_string && c == ' ') { 41862306a36Sopenharmony_ci if (node.string == buffer) 41962306a36Sopenharmony_ci continue; 42062306a36Sopenharmony_ci break; 42162306a36Sopenharmony_ci } else if (c == '"') { 42262306a36Sopenharmony_ci in_string = !in_string; 42362306a36Sopenharmony_ci } else if (c == '\n') { 42462306a36Sopenharmony_ci if (node.string == buffer) 42562306a36Sopenharmony_ci return NULL; 42662306a36Sopenharmony_ci ungetc(c, f); 42762306a36Sopenharmony_ci break; 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci if (node.string >= buffer + sizeof(buffer) - 1) { 43062306a36Sopenharmony_ci fprintf(stderr, "Token too long\n"); 43162306a36Sopenharmony_ci exit(1); 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci *node.string++ = c; 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci if (node.string == buffer) 43662306a36Sopenharmony_ci return NULL; 43762306a36Sopenharmony_ci *node.string = 0; 43862306a36Sopenharmony_ci node.string = buffer; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci if (node.string[1] == '#') { 44162306a36Sopenharmony_ci size_t n; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci for (n = 0; n < ARRAY_SIZE(symbol_types); n++) { 44462306a36Sopenharmony_ci if (node.string[0] == symbol_types[n].n) { 44562306a36Sopenharmony_ci node.tag = n; 44662306a36Sopenharmony_ci node.string += 2; 44762306a36Sopenharmony_ci return copy_node(&node); 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci fprintf(stderr, "Unknown type %c\n", node.string[0]); 45162306a36Sopenharmony_ci exit(1); 45262306a36Sopenharmony_ci } 45362306a36Sopenharmony_ci return copy_node(&node); 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cistatic void read_reference(FILE *f) 45762306a36Sopenharmony_ci{ 45862306a36Sopenharmony_ci while (!feof(f)) { 45962306a36Sopenharmony_ci struct string_list *defn = NULL; 46062306a36Sopenharmony_ci struct string_list *sym, *def; 46162306a36Sopenharmony_ci int is_extern = 0, is_override = 0; 46262306a36Sopenharmony_ci struct symbol *subsym; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci sym = read_node(f); 46562306a36Sopenharmony_ci if (sym && sym->tag == SYM_NORMAL && 46662306a36Sopenharmony_ci !strcmp(sym->string, "override")) { 46762306a36Sopenharmony_ci is_override = 1; 46862306a36Sopenharmony_ci free_node(sym); 46962306a36Sopenharmony_ci sym = read_node(f); 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci if (!sym) 47262306a36Sopenharmony_ci continue; 47362306a36Sopenharmony_ci def = read_node(f); 47462306a36Sopenharmony_ci if (def && def->tag == SYM_NORMAL && 47562306a36Sopenharmony_ci !strcmp(def->string, "extern")) { 47662306a36Sopenharmony_ci is_extern = 1; 47762306a36Sopenharmony_ci free_node(def); 47862306a36Sopenharmony_ci def = read_node(f); 47962306a36Sopenharmony_ci } 48062306a36Sopenharmony_ci while (def) { 48162306a36Sopenharmony_ci def->next = defn; 48262306a36Sopenharmony_ci defn = def; 48362306a36Sopenharmony_ci def = read_node(f); 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci subsym = add_reference_symbol(xstrdup(sym->string), sym->tag, 48662306a36Sopenharmony_ci defn, is_extern); 48762306a36Sopenharmony_ci subsym->is_override = is_override; 48862306a36Sopenharmony_ci free_node(sym); 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cistatic void print_node(FILE * f, struct string_list *list) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci if (symbol_types[list->tag].n) { 49562306a36Sopenharmony_ci putc(symbol_types[list->tag].n, f); 49662306a36Sopenharmony_ci putc('#', f); 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci fputs(list->string, f); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic void print_list(FILE * f, struct string_list *list) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci struct string_list **e, **b; 50462306a36Sopenharmony_ci struct string_list *tmp, **tmp2; 50562306a36Sopenharmony_ci int elem = 1; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci if (list == NULL) { 50862306a36Sopenharmony_ci fputs("(nil)", f); 50962306a36Sopenharmony_ci return; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci tmp = list; 51362306a36Sopenharmony_ci while ((tmp = tmp->next) != NULL) 51462306a36Sopenharmony_ci elem++; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci b = alloca(elem * sizeof(*e)); 51762306a36Sopenharmony_ci e = b + elem; 51862306a36Sopenharmony_ci tmp2 = e - 1; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci (*tmp2--) = list; 52162306a36Sopenharmony_ci while ((list = list->next) != NULL) 52262306a36Sopenharmony_ci *(tmp2--) = list; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci while (b != e) { 52562306a36Sopenharmony_ci print_node(f, *b++); 52662306a36Sopenharmony_ci putc(' ', f); 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_cistatic unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci struct string_list *list = sym->defn; 53362306a36Sopenharmony_ci struct string_list **e, **b; 53462306a36Sopenharmony_ci struct string_list *tmp, **tmp2; 53562306a36Sopenharmony_ci int elem = 1; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci if (!list) 53862306a36Sopenharmony_ci return crc; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci tmp = list; 54162306a36Sopenharmony_ci while ((tmp = tmp->next) != NULL) 54262306a36Sopenharmony_ci elem++; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci b = alloca(elem * sizeof(*e)); 54562306a36Sopenharmony_ci e = b + elem; 54662306a36Sopenharmony_ci tmp2 = e - 1; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci *(tmp2--) = list; 54962306a36Sopenharmony_ci while ((list = list->next) != NULL) 55062306a36Sopenharmony_ci *(tmp2--) = list; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci while (b != e) { 55362306a36Sopenharmony_ci struct string_list *cur; 55462306a36Sopenharmony_ci struct symbol *subsym; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci cur = *(b++); 55762306a36Sopenharmony_ci switch (cur->tag) { 55862306a36Sopenharmony_ci case SYM_NORMAL: 55962306a36Sopenharmony_ci if (flag_dump_defs) 56062306a36Sopenharmony_ci fprintf(debugfile, "%s ", cur->string); 56162306a36Sopenharmony_ci crc = partial_crc32(cur->string, crc); 56262306a36Sopenharmony_ci crc = partial_crc32_one(' ', crc); 56362306a36Sopenharmony_ci break; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci case SYM_ENUM_CONST: 56662306a36Sopenharmony_ci case SYM_TYPEDEF: 56762306a36Sopenharmony_ci subsym = find_symbol(cur->string, cur->tag, 0); 56862306a36Sopenharmony_ci /* FIXME: Bad reference files can segfault here. */ 56962306a36Sopenharmony_ci if (subsym->expansion_trail) { 57062306a36Sopenharmony_ci if (flag_dump_defs) 57162306a36Sopenharmony_ci fprintf(debugfile, "%s ", cur->string); 57262306a36Sopenharmony_ci crc = partial_crc32(cur->string, crc); 57362306a36Sopenharmony_ci crc = partial_crc32_one(' ', crc); 57462306a36Sopenharmony_ci } else { 57562306a36Sopenharmony_ci subsym->expansion_trail = expansion_trail; 57662306a36Sopenharmony_ci expansion_trail = subsym; 57762306a36Sopenharmony_ci crc = expand_and_crc_sym(subsym, crc); 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci break; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci case SYM_STRUCT: 58262306a36Sopenharmony_ci case SYM_UNION: 58362306a36Sopenharmony_ci case SYM_ENUM: 58462306a36Sopenharmony_ci subsym = find_symbol(cur->string, cur->tag, 0); 58562306a36Sopenharmony_ci if (!subsym) { 58662306a36Sopenharmony_ci struct string_list *n; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci error_with_pos("expand undefined %s %s", 58962306a36Sopenharmony_ci symbol_types[cur->tag].name, 59062306a36Sopenharmony_ci cur->string); 59162306a36Sopenharmony_ci n = concat_list(mk_node 59262306a36Sopenharmony_ci (symbol_types[cur->tag].name), 59362306a36Sopenharmony_ci mk_node(cur->string), 59462306a36Sopenharmony_ci mk_node("{"), 59562306a36Sopenharmony_ci mk_node("UNKNOWN"), 59662306a36Sopenharmony_ci mk_node("}"), NULL); 59762306a36Sopenharmony_ci subsym = 59862306a36Sopenharmony_ci add_symbol(cur->string, cur->tag, n, 0); 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci if (subsym->expansion_trail) { 60162306a36Sopenharmony_ci if (flag_dump_defs) { 60262306a36Sopenharmony_ci fprintf(debugfile, "%s %s ", 60362306a36Sopenharmony_ci symbol_types[cur->tag].name, 60462306a36Sopenharmony_ci cur->string); 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci crc = partial_crc32(symbol_types[cur->tag].name, 60862306a36Sopenharmony_ci crc); 60962306a36Sopenharmony_ci crc = partial_crc32_one(' ', crc); 61062306a36Sopenharmony_ci crc = partial_crc32(cur->string, crc); 61162306a36Sopenharmony_ci crc = partial_crc32_one(' ', crc); 61262306a36Sopenharmony_ci } else { 61362306a36Sopenharmony_ci subsym->expansion_trail = expansion_trail; 61462306a36Sopenharmony_ci expansion_trail = subsym; 61562306a36Sopenharmony_ci crc = expand_and_crc_sym(subsym, crc); 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci break; 61862306a36Sopenharmony_ci } 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci { 62262306a36Sopenharmony_ci static struct symbol **end = &visited_symbols; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci if (!sym->visited) { 62562306a36Sopenharmony_ci *end = sym; 62662306a36Sopenharmony_ci end = &sym->visited; 62762306a36Sopenharmony_ci sym->visited = (struct symbol *)-1L; 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci } 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci return crc; 63262306a36Sopenharmony_ci} 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_civoid export_symbol(const char *name) 63562306a36Sopenharmony_ci{ 63662306a36Sopenharmony_ci struct symbol *sym; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci sym = find_symbol(name, SYM_NORMAL, 0); 63962306a36Sopenharmony_ci if (!sym) 64062306a36Sopenharmony_ci error_with_pos("export undefined symbol %s", name); 64162306a36Sopenharmony_ci else { 64262306a36Sopenharmony_ci unsigned long crc; 64362306a36Sopenharmony_ci int has_changed = 0; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci if (flag_dump_defs) 64662306a36Sopenharmony_ci fprintf(debugfile, "Export %s == <", name); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci expansion_trail = (struct symbol *)-1L; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci sym->expansion_trail = expansion_trail; 65162306a36Sopenharmony_ci expansion_trail = sym; 65262306a36Sopenharmony_ci crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci sym = expansion_trail; 65562306a36Sopenharmony_ci while (sym != (struct symbol *)-1L) { 65662306a36Sopenharmony_ci struct symbol *n = sym->expansion_trail; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci if (sym->status != STATUS_UNCHANGED) { 65962306a36Sopenharmony_ci if (!has_changed) { 66062306a36Sopenharmony_ci print_location(); 66162306a36Sopenharmony_ci fprintf(stderr, "%s: %s: modversion " 66262306a36Sopenharmony_ci "changed because of changes " 66362306a36Sopenharmony_ci "in ", flag_preserve ? "error" : 66462306a36Sopenharmony_ci "warning", name); 66562306a36Sopenharmony_ci } else 66662306a36Sopenharmony_ci fprintf(stderr, ", "); 66762306a36Sopenharmony_ci print_type_name(sym->type, sym->name); 66862306a36Sopenharmony_ci if (sym->status == STATUS_DEFINED) 66962306a36Sopenharmony_ci fprintf(stderr, " (became defined)"); 67062306a36Sopenharmony_ci has_changed = 1; 67162306a36Sopenharmony_ci if (flag_preserve) 67262306a36Sopenharmony_ci errors++; 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci sym->expansion_trail = 0; 67562306a36Sopenharmony_ci sym = n; 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci if (has_changed) 67862306a36Sopenharmony_ci fprintf(stderr, "\n"); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci if (flag_dump_defs) 68162306a36Sopenharmony_ci fputs(">\n", debugfile); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci printf("#SYMVER %s 0x%08lx\n", name, crc); 68462306a36Sopenharmony_ci } 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci/*----------------------------------------------------------------------*/ 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic void print_location(void) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line); 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_cistatic void print_type_name(enum symbol_type type, const char *name) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci if (symbol_types[type].name) 69762306a36Sopenharmony_ci fprintf(stderr, "%s %s", symbol_types[type].name, name); 69862306a36Sopenharmony_ci else 69962306a36Sopenharmony_ci fprintf(stderr, "%s", name); 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_civoid error_with_pos(const char *fmt, ...) 70362306a36Sopenharmony_ci{ 70462306a36Sopenharmony_ci va_list args; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci if (flag_warnings) { 70762306a36Sopenharmony_ci print_location(); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci va_start(args, fmt); 71062306a36Sopenharmony_ci vfprintf(stderr, fmt, args); 71162306a36Sopenharmony_ci va_end(args); 71262306a36Sopenharmony_ci putc('\n', stderr); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci errors++; 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci} 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_cistatic void genksyms_usage(void) 71962306a36Sopenharmony_ci{ 72062306a36Sopenharmony_ci fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n" 72162306a36Sopenharmony_ci#ifdef __GNU_LIBRARY__ 72262306a36Sopenharmony_ci " -s, --symbol-prefix Select symbol prefix\n" 72362306a36Sopenharmony_ci " -d, --debug Increment the debug level (repeatable)\n" 72462306a36Sopenharmony_ci " -D, --dump Dump expanded symbol defs (for debugging only)\n" 72562306a36Sopenharmony_ci " -r, --reference file Read reference symbols from a file\n" 72662306a36Sopenharmony_ci " -T, --dump-types file Dump expanded types into file\n" 72762306a36Sopenharmony_ci " -p, --preserve Preserve reference modversions or fail\n" 72862306a36Sopenharmony_ci " -w, --warnings Enable warnings\n" 72962306a36Sopenharmony_ci " -q, --quiet Disable warnings (default)\n" 73062306a36Sopenharmony_ci " -h, --help Print this message\n" 73162306a36Sopenharmony_ci " -V, --version Print the release version\n" 73262306a36Sopenharmony_ci#else /* __GNU_LIBRARY__ */ 73362306a36Sopenharmony_ci " -s Select symbol prefix\n" 73462306a36Sopenharmony_ci " -d Increment the debug level (repeatable)\n" 73562306a36Sopenharmony_ci " -D Dump expanded symbol defs (for debugging only)\n" 73662306a36Sopenharmony_ci " -r file Read reference symbols from a file\n" 73762306a36Sopenharmony_ci " -T file Dump expanded types into file\n" 73862306a36Sopenharmony_ci " -p Preserve reference modversions or fail\n" 73962306a36Sopenharmony_ci " -w Enable warnings\n" 74062306a36Sopenharmony_ci " -q Disable warnings (default)\n" 74162306a36Sopenharmony_ci " -h Print this message\n" 74262306a36Sopenharmony_ci " -V Print the release version\n" 74362306a36Sopenharmony_ci#endif /* __GNU_LIBRARY__ */ 74462306a36Sopenharmony_ci , stderr); 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ciint main(int argc, char **argv) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci FILE *dumpfile = NULL, *ref_file = NULL; 75062306a36Sopenharmony_ci int o; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci#ifdef __GNU_LIBRARY__ 75362306a36Sopenharmony_ci struct option long_opts[] = { 75462306a36Sopenharmony_ci {"debug", 0, 0, 'd'}, 75562306a36Sopenharmony_ci {"warnings", 0, 0, 'w'}, 75662306a36Sopenharmony_ci {"quiet", 0, 0, 'q'}, 75762306a36Sopenharmony_ci {"dump", 0, 0, 'D'}, 75862306a36Sopenharmony_ci {"reference", 1, 0, 'r'}, 75962306a36Sopenharmony_ci {"dump-types", 1, 0, 'T'}, 76062306a36Sopenharmony_ci {"preserve", 0, 0, 'p'}, 76162306a36Sopenharmony_ci {"version", 0, 0, 'V'}, 76262306a36Sopenharmony_ci {"help", 0, 0, 'h'}, 76362306a36Sopenharmony_ci {0, 0, 0, 0} 76462306a36Sopenharmony_ci }; 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph", 76762306a36Sopenharmony_ci &long_opts[0], NULL)) != EOF) 76862306a36Sopenharmony_ci#else /* __GNU_LIBRARY__ */ 76962306a36Sopenharmony_ci while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF) 77062306a36Sopenharmony_ci#endif /* __GNU_LIBRARY__ */ 77162306a36Sopenharmony_ci switch (o) { 77262306a36Sopenharmony_ci case 'd': 77362306a36Sopenharmony_ci flag_debug++; 77462306a36Sopenharmony_ci break; 77562306a36Sopenharmony_ci case 'w': 77662306a36Sopenharmony_ci flag_warnings = 1; 77762306a36Sopenharmony_ci break; 77862306a36Sopenharmony_ci case 'q': 77962306a36Sopenharmony_ci flag_warnings = 0; 78062306a36Sopenharmony_ci break; 78162306a36Sopenharmony_ci case 'V': 78262306a36Sopenharmony_ci fputs("genksyms version 2.5.60\n", stderr); 78362306a36Sopenharmony_ci break; 78462306a36Sopenharmony_ci case 'D': 78562306a36Sopenharmony_ci flag_dump_defs = 1; 78662306a36Sopenharmony_ci break; 78762306a36Sopenharmony_ci case 'r': 78862306a36Sopenharmony_ci flag_reference = 1; 78962306a36Sopenharmony_ci ref_file = fopen(optarg, "r"); 79062306a36Sopenharmony_ci if (!ref_file) { 79162306a36Sopenharmony_ci perror(optarg); 79262306a36Sopenharmony_ci return 1; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci break; 79562306a36Sopenharmony_ci case 'T': 79662306a36Sopenharmony_ci flag_dump_types = 1; 79762306a36Sopenharmony_ci dumpfile = fopen(optarg, "w"); 79862306a36Sopenharmony_ci if (!dumpfile) { 79962306a36Sopenharmony_ci perror(optarg); 80062306a36Sopenharmony_ci return 1; 80162306a36Sopenharmony_ci } 80262306a36Sopenharmony_ci break; 80362306a36Sopenharmony_ci case 'p': 80462306a36Sopenharmony_ci flag_preserve = 1; 80562306a36Sopenharmony_ci break; 80662306a36Sopenharmony_ci case 'h': 80762306a36Sopenharmony_ci genksyms_usage(); 80862306a36Sopenharmony_ci return 0; 80962306a36Sopenharmony_ci default: 81062306a36Sopenharmony_ci genksyms_usage(); 81162306a36Sopenharmony_ci return 1; 81262306a36Sopenharmony_ci } 81362306a36Sopenharmony_ci { 81462306a36Sopenharmony_ci extern int yydebug; 81562306a36Sopenharmony_ci extern int yy_flex_debug; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci yydebug = (flag_debug > 1); 81862306a36Sopenharmony_ci yy_flex_debug = (flag_debug > 2); 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci debugfile = stderr; 82162306a36Sopenharmony_ci /* setlinebuf(debugfile); */ 82262306a36Sopenharmony_ci } 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci if (flag_reference) { 82562306a36Sopenharmony_ci read_reference(ref_file); 82662306a36Sopenharmony_ci fclose(ref_file); 82762306a36Sopenharmony_ci } 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci yyparse(); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci if (flag_dump_types && visited_symbols) { 83262306a36Sopenharmony_ci while (visited_symbols != (struct symbol *)-1L) { 83362306a36Sopenharmony_ci struct symbol *sym = visited_symbols; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci if (sym->is_override) 83662306a36Sopenharmony_ci fputs("override ", dumpfile); 83762306a36Sopenharmony_ci if (symbol_types[sym->type].n) { 83862306a36Sopenharmony_ci putc(symbol_types[sym->type].n, dumpfile); 83962306a36Sopenharmony_ci putc('#', dumpfile); 84062306a36Sopenharmony_ci } 84162306a36Sopenharmony_ci fputs(sym->name, dumpfile); 84262306a36Sopenharmony_ci putc(' ', dumpfile); 84362306a36Sopenharmony_ci if (sym->is_extern) 84462306a36Sopenharmony_ci fputs("extern ", dumpfile); 84562306a36Sopenharmony_ci print_list(dumpfile, sym->defn); 84662306a36Sopenharmony_ci putc('\n', dumpfile); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci visited_symbols = sym->visited; 84962306a36Sopenharmony_ci sym->visited = NULL; 85062306a36Sopenharmony_ci } 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci if (flag_debug) { 85462306a36Sopenharmony_ci fprintf(debugfile, "Hash table occupancy %d/%d = %g\n", 85562306a36Sopenharmony_ci nsyms, HASH_BUCKETS, 85662306a36Sopenharmony_ci (double)nsyms / (double)HASH_BUCKETS); 85762306a36Sopenharmony_ci } 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci if (dumpfile) 86062306a36Sopenharmony_ci fclose(dumpfile); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci return errors != 0; 86362306a36Sopenharmony_ci} 864