scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 711bace8774f91a3254ae7ef98166a2b2906f353
parent 12d82a8fefc00b701aa55f957a2a8da22e72885a
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 29 Jul 2012 08:44:48 +0200

Rewriting of symbol module

Before of this re-writing the module was too much complex and has some
errors. This module is clever now and doesn't break in any
conditions. Instead of having different hash for each name space, we will
have only one (splitting the hash using the ns field), and instead of having
and array marking the end of each context, we have a field in the symbol
which indicate the context of each one.

Diffstat:
decl.c | 4++--
flow.c | 4+---
keyword.c | 3+--
main.c | 1-
symbol.c | 107+++++++++++++++++++++++++++++++++----------------------------------------------
symbol.h | 26++++++++++----------------
syntax.h | 2+-
types.c | 6+++---
8 files changed, 63 insertions(+), 90 deletions(-)

diff --git a/decl.c b/decl.c @@ -19,7 +19,7 @@ static struct symbol *newiden(char *s) if (!sym) sym = install(yytext); - else if (sym->level == nested_level) + else if (sym->ctx == curctx) error("redeclaration of '%s'", yytext); return sym; } @@ -154,7 +154,7 @@ unsigned char decl(void) tp = newctype(); if (!spec(tp)) { - if (nested_level != 0) + if (curctx != OUTER_CTX) return 0; warning("data definition has no type or storage class"); } diff --git a/flow.c b/flow.c @@ -114,9 +114,7 @@ void stmt(void) void compound(void) { if (accept('{')) { - struct symctx ctx; - - new_ctx(&ctx); + new_ctx(); while (decl()) /* nothing */; while (!accept('}')) diff --git a/keyword.c b/keyword.c @@ -48,12 +48,11 @@ void init_keywords(void) { register struct keyword *bp; register struct symbol *sym; - extern void init_symbol(void); - init_symbol(); for (bp = keywords; bp->str; bp++) { sym = install(bp->str); sym->tok = bp->tok; sym->ns = NS_KEYWORD; } + new_ctx(); } diff --git a/main.c b/main.c @@ -6,7 +6,6 @@ #include "syntax.h" extern void open_file(const char *file); -extern void init_symbol(); struct user_opt user_opt; diff --git a/symbol.c b/symbol.c @@ -7,94 +7,77 @@ #define NR_SYM_HASH 32 -struct symhash { - struct symbol buf[NR_SYM_HASH]; - struct symbol *top; -}; +unsigned char curctx; +static struct symbol *htab[NR_SYM_HASH]; +static struct symbol *head; -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) +static inline unsigned char hash(register const char *s) { - 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); - } -} + register unsigned char h, ch; -void new_ctx(struct symctx *ctx) -{ - ++nested_level; - ctx->next = ctx_head; - ctx_head = ctx; - ctx->iden = iden_hash.top; + for (h = 0; ch = *s++; h += ch) + /* nothing */; + return h & NR_SYM_HASH - 1; } -void del_ctx(void) +void new_ctx(void) { - --nested_level; - del_hash_ctx(&iden_hash, ctx_head->next->iden); + ++curctx; } -static inline unsigned char hashfun(register const char *s) +void del_ctx(void) { - register unsigned char h, ch; - - for (h = 0; ch = *s++; h += ch) - /* nothing */; - return h & NR_SYM_HASH - 1; + register struct symbol *sym, *aux; + static char *s; + + --curctx; + for (sym = head; sym; sym = aux) { + if (sym->ctx <= curctx) + break; + if ((s = sym->name) != NULL) { + htab[hash(s)] = sym->hash; + free(s); + } + aux = sym->next; + free(sym); + /* TODO: unlink type */ + } } struct symbol *install(const char *s) { - static struct symbol *head; - register struct symbol *sym, *next; + register struct symbol *sym; + register unsigned char key; sym = xmalloc(sizeof(*sym)); - sym->next = iden_hash.top; - iden_hash.top = sym; + sym->ctx = curctx; + sym->next = head; + head = sym; if (s) { - sym->str = xstrdup(s); + sym->name = xstrdup(s); + key = hash(s); + sym->hash = htab[key]; + htab[key] = sym; sym->ns = NS_IDEN; - head = &iden_hash.buf[hashfun(s)]; - 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; + sym->hash = NULL; + sym->name = NULL; } return sym; } -struct symbol *lookup(char *s) +struct symbol *lookup(const char *s) { - register struct symbol *bp, *head; + register struct symbol *sym; + static unsigned char l; - head = &iden_hash.buf[hashfun(s)]; - for (bp = head->h_next; bp != head; bp = bp->h_next) { - if (!strcmp(bp->str, s)) - return bp; + l = strlen(s); + for (sym = htab[hash(s)]; sym; sym = sym->hash) { + if (!memcmp(sym->name, s, l)) + break; } - 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; + return sym; } diff --git a/symbol.h b/symbol.h @@ -7,6 +7,7 @@ # include <stdbool.h> #endif +#define OUTER_CTX 1 enum namespace { NS_IDEN, NS_KEYWORD, @@ -32,24 +33,17 @@ struct ctype { struct symbol { struct ctype ctype; + unsigned char ctx; unsigned char ns; - union { - struct { - char *str; - union { - unsigned char level;/* used in usual symbols */ - unsigned char tok; /* used in keywords */ - }; + char *name; + struct { + union { + unsigned char tok; /* used in keywords */ + short val; /* used in integer constant */ }; - short val; /* used in integer constant */ }; struct symbol *next; - struct symbol *h_next, *h_prev; -}; - -struct symctx { - struct symbol *iden; - struct symctx *next; + struct symbol *hash; }; extern struct type tchar, tshort, tint, tulong, tllong, tvoid, tkeyword; @@ -59,10 +53,10 @@ extern struct type tfloat, tdouble, tldouble, tlong; extern struct ctype *decl_type(struct ctype *t); extern void pushtype(unsigned char mod); extern unsigned char btype(unsigned char, unsigned char tok); -extern void new_ctx(struct symctx *ctx); +extern void new_ctx(void); extern void del_ctx(void); extern struct symbol *install(const char *s); -extern struct symbol *lookup(char *s); +extern struct symbol *lookup(const char *s); extern void ctype(struct ctype *cp, unsigned char mod); extern struct ctype *newctype(void); extern void delctype(register struct ctype *tp); diff --git a/syntax.h b/syntax.h @@ -1,7 +1,7 @@ #ifndef SYNTAX_H #define SYNTAX_H -extern unsigned char nested_level; +extern unsigned char curctx; enum { OARY, OCALL, OFIELD, OPTR, OPOSTINC, OPOSTDEC, diff --git a/types.c b/types.c @@ -126,7 +126,7 @@ unsigned char btype(unsigned char type, unsigned char tok) void ctype(struct ctype *cp, unsigned char mod) { - extern unsigned char nested_level; + extern unsigned char curctx; switch (mod) { case TYPEDEF: @@ -151,7 +151,7 @@ void ctype(struct ctype *cp, unsigned char mod) cp->c_static = 1; return; case AUTO: - if (nested_level != 0) + if (curctx != OUTER_CTX) goto bad_file_scope_storage; if (cp->c_type | cp->c_extern | cp->c_static | cp->c_reg) goto two_storage; @@ -160,7 +160,7 @@ void ctype(struct ctype *cp, unsigned char mod) cp->c_static = 1; return; case REGISTER: - if (nested_level != 0) + if (curctx != OUTER_CTX) goto bad_file_scope_storage; if (cp->c_type | cp->c_extern | cp->c_auto | cp->c_static) goto two_storage;