symbol.c (1654B)
1 static char sccsid[] = "@(#) ./cc2/symbol.c"; 2 #include <limits.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include "../inc/scc.h" 8 9 #include "cc2.h" 10 11 #define NR_SYMHASH 64 12 13 Symbol *locals; 14 15 static Symbol *symtab[NR_SYMHASH], *curlocal; 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, *next; 36 37 infunction = 0; 38 for (sym = locals; sym; sym = next) { 39 next = sym->next; 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 curlocal = locals = 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 htab = &symtab[id & NR_SYMHASH-1]; 68 for (sym = *htab; sym; sym = sym->h_next) { 69 if (sym->id > 0 && sym->id == id) 70 break; 71 } 72 if (!sym) { 73 sym = xcalloc(1, sizeof(*sym)); 74 sym->id = id; 75 if ((sym->numid = ++num) == 0) 76 error(EIDOVER); 77 if (infunction) { 78 if (!locals) 79 locals = sym; 80 if (curlocal) 81 curlocal->next = sym; 82 curlocal = sym; 83 } 84 if (id != TMPSYM) { 85 sym->h_next = *htab; 86 *htab = sym; 87 } 88 } 89 return sym; 90 }