symbol.c (1627B)
1 #include <limits.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #include <scc/scc.h> 7 8 #include "cc2.h" 9 10 #define NR_SYMHASH 64 11 12 Symbol *locals; 13 static Symbol *tail; 14 15 static Symbol *symtab[NR_SYMHASH]; 16 static int infunction; 17 18 19 void 20 freesym(Symbol *sym) 21 { 22 free(sym->name); 23 free(sym); 24 } 25 26 void 27 pushctx(void) 28 { 29 infunction = 1; 30 } 31 32 void 33 popctx(void) 34 { 35 Symbol *sym, *prev; 36 37 infunction = 0; 38 for (sym = tail; sym; sym = prev) { 39 prev = sym->prev; 40 /* 41 * Symbols are inserted in the hash in the inverted 42 * order they are found in locals and it is impossible 43 * to have a global over a local, because a local is 44 * any symbol defined in the body of a function, 45 * even if it has extern linkage. 46 * For this reason when we reach a symbol in the 47 * locals list we know that it is the head of it 48 * collision list and we can remove it assigning 49 * it h_next to the hash table position 50 */ 51 if (sym->id != TMPSYM) 52 symtab[sym->id & NR_SYMHASH-1] = sym->h_next; 53 freesym(sym); 54 } 55 locals = tail = NULL; 56 } 57 58 Symbol * 59 getsym(unsigned id) 60 { 61 Symbol **htab, *sym; 62 static unsigned short num; 63 64 if (id >= USHRT_MAX) 65 error(EBADID); 66 67 if (id != TMPSYM) { 68 htab = &symtab[id & NR_SYMHASH-1]; 69 for (sym = *htab; sym; sym = sym->h_next) { 70 if (sym->id == id) 71 return sym; 72 } 73 } 74 75 sym = xcalloc(1, sizeof(*sym)); 76 sym->id = id; 77 if (infunction) { 78 sym->next = NULL; 79 sym->prev = tail; 80 if (tail) 81 tail->next = sym; 82 tail = sym; 83 if (!locals) 84 locals = sym; 85 } 86 if (id != TMPSYM) { 87 sym->h_next = *htab; 88 *htab = sym; 89 } 90 if ((sym->numid = ++num) == 0) 91 error(EIDOVER); 92 93 return sym; 94 }