ref: 711bace8774f91a3254ae7ef98166a2b2906f353
parent: 12d82a8fefc00b701aa55f957a2a8da22e72885a
author: Roberto E. Vargas Caballero <[email protected]>
date: Sun Jul 29 04:44:48 EDT 2012
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.
--- a/decl.c
+++ b/decl.c
@@ -19,7 +19,7 @@
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 @@
tp = newctype();
if (!spec(tp)) {
- if (nested_level != 0)
+ if (curctx != OUTER_CTX)
return 0;
warning("data definition has no type or storage class");
}
--- a/flow.c
+++ b/flow.c
@@ -114,9 +114,7 @@
void compound(void)
{
if (accept('{')) {
- struct symctx ctx;
-
- new_ctx(&ctx);
+ new_ctx();
while (decl())
/* nothing */;
while (!accept('}'))
--- a/keyword.c
+++ b/keyword.c
@@ -48,12 +48,11 @@
{
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();
}
--- 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;
--- 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;
+ register unsigned char h, ch;
- 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);
- }
+ for (h = 0; ch = *s++; h += ch)
+ /* nothing */;
+ return h & NR_SYM_HASH - 1;
}
-void new_ctx(struct symctx *ctx)
+void new_ctx(void)
{
- ++nested_level;
- ctx->next = ctx_head;
- ctx_head = ctx;
- ctx->iden = iden_hash.top;
+ ++curctx;
}
void del_ctx(void)
{
- --nested_level;
- del_hash_ctx(&iden_hash, ctx_head->next->iden);
-}
+ register struct symbol *sym, *aux;
+ static char *s;
-static inline unsigned char hashfun(register const char *s)
-{
- register unsigned char h, ch;
-
- for (h = 0; ch = *s++; h += ch)
- /* nothing */;
- return h & NR_SYM_HASH - 1;
+ --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;
}
--- 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,26 +33,19 @@
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 symbol *hash;
};
-struct symctx {
- struct symbol *iden;
- struct symctx *next;
-};
-
extern struct type tchar, tshort, tint, tulong, tllong, tvoid, tkeyword;
extern struct type tfloat, tdouble, tldouble, tlong;
@@ -59,10 +53,10 @@
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);
--- 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,
--- a/types.c
+++ b/types.c
@@ -126,7 +126,7 @@
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 @@
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 @@
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;