scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit d93d39b724055b9e8b8f342481308d0e0f634b7a
parent c821608f58c35cdcd45433f0173ab1ad84ba8093
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 26 Aug 2012 09:43:43 +0200

Added support for different namespace in the symbol table

The symbol table hold symbols relative to different namespaces, (keywords,
identifiers, labels ...). So we need can lookup only in one namespace. When
the lexical analysis is done, we don't have this information, but we need
the symbol pointer requested later. The aproach used in this patch consist
in assume number of duplicated symbol names is low, so we usually will catch
the correct one without be worried in the namespace, and later, in the moment
that we have enough information of the symbol, check is the namespace is
correct or we have to do a new lookup with the correct namespace.

Diffstat:
Mdecl.c | 28+++++++++++++++++-----------
Mkeyword.c | 3+--
Mlex.c | 12+++++-------
Msymbol.c | 45+++++++++++++++++----------------------------
Msymbol.h | 10++++++----
Mtypes.c | 4++--
6 files changed, 48 insertions(+), 54 deletions(-)

diff --git a/decl.c b/decl.c @@ -13,16 +13,22 @@ char parser_out_home; static void declarator(void); -static struct symbol * -newiden(char *s) +static void +newiden(void) { - register struct symbol *sym = lookup(yytext); - - if (!sym) - sym = install(yytext); - else if (sym->ctx == curctx) - error("redeclaration of '%s'", yytext); - return sym; + switch (yyval.sym->ns) { + case NS_ANY: /* First aparrence of the symbol */ + yyval.sym->ns = NS_IDEN; + yyval.sym->ctx = curctx; + break; + case NS_STRUCT: case NS_LABEL: case NS_TYPEDEF: + lookup(yytext, NS_IDEN, CTX_ANY); + case NS_IDEN: + if (yyval.sym->ctx == curctx) + error("redeclaration of '%s'", yytext); + default: + lookup(yytext, NS_IDEN, curctx); + } } static void @@ -32,7 +38,7 @@ dirdcl(void) declarator(); expect(')'); } else if (yytoken == IDEN) { - newiden(yytext); + newiden(); next(); } else { error("expected '(' or identifier before of '%s'", yytext); @@ -162,7 +168,7 @@ decl(void) tp = newctype(); if (!spec(tp)) { - if (curctx != OUTER_CTX) + if (curctx != CTX_OUTER) return 0; warning("data definition has no type or storage class"); } diff --git a/keyword.c b/keyword.c @@ -51,9 +51,8 @@ init_keywords(void) register struct symbol *sym; for (bp = keywords; bp->str; bp++) { - sym = install(bp->str); + sym = lookup(bp->str, NS_KEYWORD, CTX_ANY); sym->tok = bp->tok; - sym->ns = NS_KEYWORD; } new_ctx(); } diff --git a/lex.c b/lex.c @@ -24,7 +24,6 @@ number(void) { register char *bp; register char ch; - register struct symbol *sym; for (bp = yytext; bp < yytext + TOKSIZ_MAX; *bp++ = ch) { if (!isdigit(ch = getc(yyin))) @@ -34,8 +33,8 @@ number(void) error("identifier too long %s", yytext); *bp = '\0'; ungetc(ch, yyin); - yyval.sym = sym = install(NULL); - sym->val = atoi(yytext); + yyval.sym = lookup(yytext, NS_ANY, CTX_ANY); + yyval.sym->val = atoi(yytext); return CONSTANT; } @@ -54,10 +53,9 @@ iden(void) error("identifier too long %s", yytext); *bp = '\0'; ungetc(ch, yyin); - if ((sym = lookup(yytext)) && sym->ns == NS_KEYWORD) - return sym->tok; - yyval.sym = sym; - return IDEN; + yyval.sym = lookup(yytext, NS_ANY, CTX_ANY); + + return (yyval.sym->ns == NS_KEYWORD) ? yyval.sym->tok : IDEN; } static unsigned char diff --git a/symbol.c b/symbol.c @@ -52,7 +52,7 @@ freesyms(void) { register struct symbol *sym, *next; - if (curctx == OUTER_CTX) { + if (curctx == CTX_OUTER) { for (sym = headfun; sym; sym = next) { next = sym->next; free(sym->name); @@ -62,39 +62,28 @@ freesyms(void) } struct symbol * -install(const char *s) +lookup(register const char *s, unsigned char ns, unsigned char ctx) { register struct symbol *sym; - register unsigned char key; + static unsigned char l, key; + l = strlen(s); + for (sym = htab[hash(s)]; sym; sym = sym->hash) { + if (!memcmp(sym->name, s, l) && + (ns == NS_ANY || ns == sym->ns) && + (sym->ctx == ctx || ctx == CTX_ANY)) { + return sym; + } + } sym = xmalloc(sizeof(*sym)); - sym->ctx = curctx; + sym->name = xstrdup(s); + sym->ns = ns; + sym->ctx = CTX_ANY; sym->next = head; head = sym; + key = hash(s); + sym->hash = htab[key]; + htab[key] = sym; - if (s) { - sym->name = xstrdup(s); - key = hash(s); - sym->hash = htab[key]; - htab[key] = sym; - sym->ns = NS_IDEN; - } else { - sym->hash = NULL; - sym->name = NULL; - } - return sym; -} - -struct symbol * -lookup(const char *s) -{ - register struct symbol *sym; - static unsigned char l; - - l = strlen(s); - for (sym = htab[hash(s)]; sym; sym = sym->hash) { - if (!memcmp(sym->name, s, l)) - break; - } return sym; } diff --git a/symbol.h b/symbol.h @@ -7,13 +7,15 @@ # include <stdbool.h> #endif -#define OUTER_CTX 1 +#define CTX_OUTER 1 +#define CTX_ANY 0 enum namespace { NS_IDEN, NS_KEYWORD, NS_STRUCT, NS_LABEL, - NS_TYPEDEF + NS_TYPEDEF, + NS_ANY }; struct ctype { @@ -56,8 +58,8 @@ extern unsigned char btype(unsigned char, unsigned char tok); extern void new_ctx(void); extern void del_ctx(void); extern void freesyms(void); -extern struct symbol *install(const char *s); -extern struct symbol *lookup(const char *s); +extern struct symbol *lookup(register const char *s, + unsigned char ns, unsigned char ctx); extern void ctype(struct ctype *cp, unsigned char mod); extern struct ctype *newctype(void); extern void delctype(register struct ctype *tp); diff --git a/types.c b/types.c @@ -157,7 +157,7 @@ ctype(struct ctype *cp, unsigned char mod) cp->c_static = 1; return; case AUTO: - if (curctx != OUTER_CTX) + if (curctx != CTX_OUTER) goto bad_file_scope_storage; if (cp->c_type | cp->c_extern | cp->c_static | cp->c_reg) goto two_storage; @@ -166,7 +166,7 @@ ctype(struct ctype *cp, unsigned char mod) cp->c_static = 1; return; case REGISTER: - if (curctx != OUTER_CTX) + if (curctx != CTX_OUTER) goto bad_file_scope_storage; if (cp->c_type | cp->c_extern | cp->c_auto | cp->c_static) goto two_storage;