1#include <limits.h>2#include <stdio.h>3#include <stdlib.h>4#include <string.h>56#include <scc/scc.h>78#include "cc2.h"910#define NR_SYMHASH 641112Symbol *locals;13static Symbol *tail;1415static Symbol *symtab[NR_SYMHASH];16static int infunction;171819void20freesym(Symbol *sym)21{22 free(sym->name);23 free(sym);24}2526void27pushctx(void)28{29 infunction = 1;30}3132void33popctx(void)34{35 Symbol *sym, *prev;3637 infunction = 0;38 for (sym = tail; sym; sym = prev) {39 prev = sym->prev;40 /*41 * Symbols are inserted in the hash in the inverted42 * order they are found in locals and it is impossible43 * to have a global over a local, because a local is44 * 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 the47 * locals list we know that it is the head of it48 * collision list and we can remove it assigning49 * it h_next to the hash table position50 */51 if (sym->id != TMPSYM)52 symtab[sym->id & NR_SYMHASH-1] = sym->h_next;53 freesym(sym);54 }55 locals = tail = NULL;56}5758Symbol *59getsym(unsigned id)60{61 Symbol **htab, *sym;62 static unsigned short num;6364 if (id >= USHRT_MAX)65 error(EBADID);6667 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 }7475 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);9293 return sym;94}