ref: bc40f94fdda9ad39a8cc71a9b5a4c80eebe210a8
dir: /symbol.c/
#include <stdlib.h> #include <string.h> #include "cc.h" #include "symbol.h" #include "tokens.h" #define xmalloc malloc #define xstrdup strdup #define NR_SYM_HASH 32 struct symhash { struct symbol buf[NR_SYM_HASH]; struct symbol *top; }; unsigned char nested_level; static struct symhash iden_hash; static struct symctx ctx_base; static struct symctx *ctx_head = &ctx_base; static void del_hash_ctx(struct symhash *htable, struct symbol *lim) { register struct symbol *bp, *next, *prev; for (bp = htable->top; bp && bp != lim; bp = bp->next) { next = bp->h_next, prev = bp->h_prev; prev->h_next = next; next->h_prev = prev; free(bp->str); free(bp); } } void new_ctx(struct symctx *ctx) { ++nested_level; ctx->next = ctx_head; ctx_head = ctx; ctx->iden = iden_hash.top; } void del_ctx(void) { --nested_level; del_hash_ctx(&iden_hash, ctx_head->next->iden); } struct symbol *install(const char *s, unsigned char key) { static struct symbol *head; register struct symbol *sym, *next; sym = xmalloc(sizeof(*sym)); sym->next = iden_hash.top; iden_hash.top = sym; if (s) { sym->str = xstrdup(s); sym->ns = NS_IDEN; head = &iden_hash.buf[key & NR_SYM_HASH-1]; next = head->h_next; sym->h_next = next; sym->h_prev = next->h_prev; head->h_next = sym; next->h_prev = sym; } else { sym->h_next = sym->h_prev = NULL; sym->str = NULL; } return sym; } struct symbol *lookup(char *s, unsigned char key) { register struct symbol *bp, *head; head = &iden_hash.buf[key & NR_SYM_HASH-1]; for (bp = head->h_next; bp != head; bp = bp->h_next) { if (!strcmp(bp->str, s)) return bp; } return NULL; } void init_symbol(void) { register struct symbol *bp; for (bp = iden_hash.buf; bp < &iden_hash.buf[NR_SYM_HASH]; ++bp) bp->h_next = bp->h_prev = bp; } unsigned char hashfun(register const char *s) { register unsigned char h, ch; for (h = 0; ch = *s++; h += ch) /* nothing */; return h; } void ctype(struct ctype *cp, unsigned char mod) { extern unsigned char nested_level; switch (mod) { case TYPEDEF: if (cp->c_type) goto duplicated; if (cp->c_extrn | cp->c_auto | cp->c_reg | cp->c_static) goto two_storage; cp->c_type = 1; return; case EXTERN: if (cp->c_extrn) goto duplicated; if (cp->c_type | cp->c_auto | cp->c_reg | cp->c_static) goto two_storage; cp->c_extrn = 1; return; case STATIC: if (cp->c_static) goto duplicated; if (cp->c_type | cp->c_extrn | cp->c_auto | cp->c_reg) goto two_storage; cp->c_static = 1; return; case AUTO: if (nested_level != 0) goto bad_file_scope_storage; if (cp->c_type | cp->c_extrn | cp->c_static | cp->c_reg) goto two_storage; if (cp->c_auto) goto duplicated; cp->c_static = 1; return; case REGISTER: if (nested_level != 0) goto bad_file_scope_storage; if (cp->c_type | cp->c_extrn | cp->c_auto | cp->c_static) goto two_storage; if (cp->c_reg) goto duplicated; cp->c_reg = 1; return; case CONST: if (user_opt.typeqlf_repeat && cp->c_reg) goto duplicated; cp->c_const = 1; return; case VOLATILE: if (user_opt.typeqlf_repeat && cp->c_vol) goto duplicated; cp->c_vol = 1; return; } bad_file_scope_storage: error("file-scope declaration specifies ‘%s’", yytext); two_storage: error("Two or more storage specifier"); duplicated: error("duplicated '%s'", yytext); }