scc

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

commit 34a81d796b32081310c4232f2955cd31fc84bc00
parent d3f766992c8196bd3fdd8f34577598ecaedaa0d7
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed,  3 Jul 2013 14:03:55 +0200

Remove context parameter from lookup

We will allways look symbols based in the name and maybe in the
namespace, we don't need the context in the lookup function.
The unique case where we add a symbol in a different context of the
actual, is in the label case (labels are function scope symbols), so we
need a insert function which allow us modify the context of a symbol.

Diffstat:
Mdecl.c | 9++++-----
Mflow.c | 34+++++++++++++++++++++++++---------
Mkeyword.c | 2+-
Mlex.c | 4++--
Msymbol.c | 46++++++++++++++++++++++++++++++++++++----------
Msymbol.h | 6++++--
6 files changed, 72 insertions(+), 29 deletions(-)

diff --git a/decl.c b/decl.c @@ -11,23 +11,22 @@ char parser_out_home; struct ctype *curfun; +static struct symbol *cursym; static void declarator(void); static void newiden(void) { switch (yyval.sym->ns) { - case NS_ANY: /* First aparrence of the symbol */ + case NS_ANY: /* First aparrence of the symbol */ yyval.sym->ns = NS_IDEN; - yyval.sym->ctx = curctx; + cursym = yyval.sym; 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); + cursym = lookup(yytext, NS_IDEN); } } diff --git a/flow.c b/flow.c @@ -28,16 +28,36 @@ pop(void) --blockp; } +static struct symbol* +newlabel(struct symbol *sym, char *s) +{ + switch (sym->ns) { + case NS_LABEL: + error("label '%s' already defined", yytext); + case NS_ANY: + sym->ns = NS_LABEL; + break; + default: + lookup(s, NS_LABEL); + } + + insert(sym, CTX_FUNC); + return sym; +} + static struct node * _goto(void) { register struct node *np; + register struct symbol *sym; + expect(GOTO); expect(IDEN); - if (yyval.sym->ns != NS_LABEL) - yyval.sym = lookup(yytext, NS_LABEL, CTX_ANY); - np = node1(OGOTO, nodesym(yyval.sym)); + sym = yyval.sym; + if (sym->ns != NS_LABEL) + sym = newlabel(sym, yytext); + np = node1(OGOTO, nodesym(sym)); expect(';'); return np; @@ -131,7 +151,7 @@ _switch(void) static struct node * label(void) { - register struct symbol *sym; + register struct symbol *sym = yyval.sym; if (!ahead(':')) { register struct node *np = expr(); /* it is an identifier */ @@ -139,11 +159,7 @@ label(void) return np; } - sym = lookup(yytext, NS_LABEL, CTX_ANY); - if (sym->ctx != CTX_ANY) - error("label '%s' already defined", yytext); - - sym->ctx = curctx; + sym = newlabel(sym, yytext); next(), next(); /* skip IDEN and ':' */ return node2(OLABEL, nodesym(sym), stmt()); } diff --git a/keyword.c b/keyword.c @@ -51,7 +51,7 @@ init_keywords(void) register struct symbol *sym; for (bp = keywords; bp->str; bp++) { - sym = lookup(bp->str, NS_KEYWORD, CTX_ANY); + sym = lookup(bp->str, NS_KEYWORD); sym->tok = bp->tok; } new_ctx(); diff --git a/lex.c b/lex.c @@ -32,7 +32,7 @@ number(void) error("identifier too long %s", yytext); *bp = '\0'; ungetc(ch, yyin); - yyval.sym = lookup(yytext, NS_ANY, CTX_ANY); + yyval.sym = lookup(yytext, NS_ANY); yyval.sym->val = atoi(yytext); return CONSTANT; @@ -52,7 +52,7 @@ iden(void) error("identifier too long %s", yytext); *bp = '\0'; ungetc(ch, yyin); - yyval.sym = lookup(yytext, NS_ANY, CTX_ANY); + yyval.sym = lookup(yytext, NS_ANY); return (yyval.sym->ns == NS_KEYWORD) ? yyval.sym->tok : IDEN; } diff --git a/symbol.c b/symbol.c @@ -1,4 +1,5 @@ +#include <assert.h> #include <stdlib.h> #include <string.h> @@ -62,28 +63,53 @@ freesyms(void) } struct symbol * -lookup(register const char *s, unsigned char ns, unsigned char ctx) +lookup(register const char *s, char ns) { register struct symbol *sym; - static unsigned char l, key; + register unsigned char l; + static unsigned char 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)) { + key = hash(s); + for (sym = htab[key]; sym; sym = sym->hash) { + if (ns != NS_ANY && ns != sym->ns) + continue; + if (!memcmp(sym->name, s, l)) return sym; - } } sym = xmalloc(sizeof(*sym)); sym->name = xstrdup(s); - sym->ns = ns; - sym->ctx = CTX_ANY; sym->next = head; + sym->ctx = curctx; + sym->ns = ns; head = sym; - key = hash(s); sym->hash = htab[key]; htab[key] = sym; return sym; } + +void +insert(struct symbol *sym, unsigned char ctx) +{ + register struct symbol *p, *q; + + for (q = p = head; p; q = p, p = p->next) { + if (p == sym) + break; + } + assert(p); /* sym must be in the list */ + q->next = p->next; /* remove from the list */ + + for (q = p = head; p; q = p, p = p->next) { + if (p->ctx <= ctx) + break; + } + if (q == NULL) { + head = sym; + sym->next = NULL; + } else { + q->next = sym; + sym->next = p; + } +} diff --git a/symbol.h b/symbol.h @@ -8,7 +8,9 @@ #endif #define CTX_OUTER 1 +#define CTX_FUNC 2 #define CTX_ANY 0 + enum namespace { NS_IDEN, NS_KEYWORD, @@ -59,8 +61,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 *lookup(register const char *s, - unsigned char ns, unsigned char ctx); +extern struct symbol *lookup(register const char *s, char ns); +extern void insert(struct symbol *sym, unsigned char ctx); extern void ctype(struct ctype *cp, unsigned char mod); extern struct ctype *newctype(void); extern void delctype(register struct ctype *tp);