/* * picasm -- symtab.c * * Copyright 1995-2004 Timo Rossi, * See the file LICENSE for license terms. * * symbol table handling * */ #include #include #include #include #include "picasm.h" #include "symtab.h" #define HASH_TABLE_SIZE 127 typedef struct symbol *symtable[HASH_TABLE_SIZE]; /* structure for list of local symbol tables */ struct localtab { struct localtab *next; struct patch *patch_list; symtable table; }; static symtable global_symbol_table; static struct localtab *local_table_list; /* * Compute a hash value from a string */ static unsigned int hash(char *str) { unsigned int h, a; h = 0; while((a = *str++) != '\0') { h = 17*h + a; } return h % HASH_TABLE_SIZE; } /* * Initialize global and local symbol tables */ void init_symtab(void) { struct symbol **sym; int n; for(sym = global_symbol_table, n = HASH_TABLE_SIZE; n-- > 0; *sym++ = NULL) ; local_table_list = NULL; } /* * Add a new local symbol table */ void add_local_symtab(void) { struct localtab *tab; struct symbol **symp; int n; tab = mem_alloc(sizeof(struct localtab)); for(symp = &tab->table[0], n = HASH_TABLE_SIZE; n-- > 0; *symp++ = NULL) ; tab->patch_list = NULL; local_patch_list_ptr = &tab->patch_list; tab->next = local_table_list; local_table_list = tab; local_level++; } /* * Remove a local symbol table. * The caller should check that local_level > 0 before calling this */ void remove_local_symtab(void) { int i; struct localtab *tab; struct symbol *sym, *sym2; tab = local_table_list; for(i = 0; i < HASH_TABLE_SIZE; i++) { for(sym = tab->table[i]; sym != NULL; sym = sym2) { sym2 = sym->next; mem_free(sym); } } local_table_list = tab->next; if(local_table_list != NULL) local_patch_list_ptr = &local_table_list->patch_list; mem_free(tab); local_level--; } /* * Add a new symbol to the symbol table */ struct symbol * add_symbol(char *name, int tab) { struct symbol *sym; symtable *table; int i; table = (tab == SYMTAB_LOCAL ? &local_table_list->table : &global_symbol_table); if((sym = mem_alloc(sizeof(struct symbol) + strlen(name))) == NULL) return NULL; i = hash(name); sym->next = (*table)[i]; (*table)[i] = sym; sym->type2 = SYMT_UNKNOWN; strcpy(sym->name, name); /* the caller must fill the value, type and flags fields */ return sym; } /* * Try to find a symbol from the symbol table */ struct symbol * lookup_symbol(char *name, int tab) { symtable *table; struct symbol *sym; int i; table = (tab == SYMTAB_LOCAL ? &local_table_list->table : &global_symbol_table); i = hash(name); for(sym = (*table)[i]; sym != NULL; sym = sym->next) { if(strcmp(sym->name, name) == 0) return sym; } return NULL; } /* * symbol table output for listing (global symbols only) * * if level >= 2, all symbols are displayed, else symbols beginning * with '__' are omitted. * */ void dump_symtab(FILE *fp, int level) { int i; struct symbol *sym, *nsym, *s0, *s1; struct symbol *syms = NULL; for(i = 0; i < HASH_TABLE_SIZE; i++) { for(sym = global_symbol_table[i]; sym != NULL; sym = nsym) { nsym = sym->next; for(s0 = NULL, s1 = syms; s1 != NULL; s0 = s1, s1 = s1->next) { if(strcmp(s1->name, sym->name) > 0) break; } if(s0 == NULL) { sym->next = syms; syms = sym; } else { sym->next = s0->next; s0->next = sym; } } } fputs("\n\nSymbol Table:\nname decimal hex\n", fp); for(sym = syms; sym != NULL; sym = sym->next) { if(level < 2 && sym->name[0] == '_' && sym->name[1] == '_') continue; switch(sym->type) { case SYM_MACRO: fprintf(fp, "%-20s MACRO\n", sym->name); break; case SYM_FORWARD: fprintf(fp, "%-20s UNDEFINED\n", sym->name); break; case SYM_SET: fprintf(fp, "%-20s %6ld 0x%04lx (set)\n", sym->name, sym->v.value, sym->v.value); break; case SYM_DEFINED: fprintf(fp, "%-20s %6ld 0x%04lx", sym->name, sym->v.value, sym->v.value); switch(sym->type2) { case SYMT_LABEL: fputs(" (label)", fp); break; case SYMT_REGFILE: fputs(" (regfile)", fp); break; } fputc('\n', fp); break; default: fprintf(fp, "%-20s (type 0x%x ??" "?)\n", sym->name, sym->type); break; } } }