shithub: scc

Download patch

ref: 8fa3bec21d142b3e8e14b6ae27574081ad0c967f
parent: 893e56b36a5d1da429dd01ca703adbedff2898e5
author: Roberto E. Vargas Caballero <[email protected]>
date: Fri Oct 25 10:33:21 EDT 2013

Use a different hash for keywords

With the previous implementation it was necessary look in the
symbol table in order to know if a identifier was a keyword
or not. This search generated the problem of not know yet
the correct namespace, and due to this problem it was necessary
the ugly code of namespace.
This patch is the first step to remove this shit, and uses
a new hash only for the keywords, so the problem of the
namespaces will be fixed because we push the search to other
moment when we already have the needed information.

--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 
-OBJS = types.o decl.o lex.o error.o symbol.o flow.o main.o expr.o keyword.o \
+OBJS = types.o decl.o lex.o error.o symbol.o flow.o main.o expr.o \
 	wrapper.o tree.o
 LIBS =
 
--- a/keyword.c
+++ /dev/null
@@ -1,60 +1,0 @@
-#include <stddef.h>
-
-#include "tokens.h"
-#include "symbol.h"
-
-
-static struct keyword {
-	char *str;
-	unsigned char tok;
-} keywords [] = {"auto", AUTO,
-		 "break", BREAK,
-		 "_Bool", CHAR,
-		 "_Complex", COMPLEX,
-		 "case", CASE,
-		 "char", CHAR,
-		 "const", CONST,
-		 "continue", CONTINUE,
-		 "default", DEFAULT,
-		 "do", DO,
-		 "double", DOUBLE,
-		 "else", ELSE,
-		 "enum", ENUM,
-		 "extern", EXTERN,
-		 "float", FLOAT,
-		 "for", FOR,
-		 "goto", GOTO,
-		 "if", IF,
-		 "int", INT,
-		 "_Imaginary", IMAGINARY,
-		 "long", LONG,
-		 "register", REGISTER,
-		 "restricted", RESTRICT,
-		 "return", RETURN,
-		 "short", SHORT,
-		 "signed", SIGNED,
-		 "sizeof", SIZEOF,
-		 "static", STATIC,
-		 "struct", STRUCT,
-		 "switch", SWITCH,
-		 "typedef", TYPEDEF,
-		 "union", UNION,
-		 "unsigned", UNSIGNED,
-		 "void", VOID,
-		 "volatile", VOLATILE,
-		 "while", WHILE,
-		 NULL, 0,
-};
-
-void
-init_keywords(void)
-{
-	register struct keyword *bp;
-	register struct symbol *sym;
-
-	for (bp = keywords; bp->str; bp++) {
-		sym = lookup(bp->str, NS_KEYWORD);
-		sym->tok = bp->tok;
-	}
-	new_ctx();
-}
--- a/lex.c
+++ b/lex.c
@@ -9,6 +9,8 @@
 #include "symbol.h"
 #include "sizes.h"
 
+#define NR_KEYW_HASH 16
+
 union yyval yyval;
 unsigned char yytoken;
 char yytext[IDENTSIZ + 1];
@@ -16,8 +18,16 @@
 unsigned columnum;
 const char *filename;
 
+struct keyword {
+	char *str;
+	unsigned char tok;
+	struct keyword *next;
+};
+
 static FILE *yyin;
+static struct keyword *ktab[NR_KEYW_HASH];
 
+
 static char
 number(void)
 {
@@ -64,11 +74,75 @@
 	return CONSTANT;
 }
 
+void
+init_keywords(void)
+{
+	static struct keyword buff[] = {
+		{"auto", AUTO, NULL},
+		{"break", BREAK, NULL},
+		{"_Bool", CHAR, NULL},
+		{"_Complex", COMPLEX, NULL},
+		{"case", CASE, NULL},
+		{"char", CHAR, NULL},
+		{"const", CONST, NULL},
+		{"continue", CONTINUE, NULL},
+		{"default", DEFAULT, NULL},
+		{"do", DO, NULL},
+		{"double", DOUBLE, NULL},
+		{"else", ELSE, NULL},
+		{"enum", ENUM, NULL},
+		{"extern", EXTERN, NULL},
+		{"float", FLOAT, NULL},
+		{"for", FOR, NULL},
+		{"goto", GOTO, NULL},
+		{"if", IF, NULL},
+		{"int", INT, NULL},
+		{"_Imaginary", IMAGINARY, NULL},
+		{"long", LONG, NULL},
+		{"register", REGISTER, NULL},
+		{"restricted", RESTRICT, NULL},
+		{"return", RETURN, NULL},
+		{"short", SHORT, NULL},
+		{"signed", SIGNED, NULL},
+		{"sizeof", SIZEOF, NULL},
+		{"static", STATIC, NULL},
+		{"struct", STRUCT, NULL},
+		{"switch", SWITCH, NULL},
+		{"typedef", TYPEDEF, NULL},
+		{"union", UNION, NULL},
+		{"unsigned", UNSIGNED, NULL},
+		{"void", VOID, NULL},
+		{"volatile", VOLATILE, NULL},
+		{"while", WHILE, NULL},
+		{NULL, 0, NULL},
+	};
+	register struct keyword *bp;
+
+	for (bp = buff;  bp->str; ++bp) {
+		register unsigned char h = hash(bp->str) & NR_KEYW_HASH-1;
+		bp->next = ktab[h];
+		ktab[h] = bp;
+	}
+}
+
 static unsigned char
+keyword(char *s)
+{
+	register struct keyword *bp;
+
+	for (bp = ktab[hash(s) & NR_KEYW_HASH-1]; bp; bp = bp->next) {
+		if (!strcmp(bp->str, s))
+			return bp->tok;
+	}
+	return 0;
+}
+
+static unsigned char
 iden(void)
 {
 	register char ch, *bp;
 	register struct symbol *sym;
+	static unsigned char tok;
 
 	for (bp = yytext; bp < yytext + IDENTSIZ; *bp++ = ch) {
 		if (!isalnum(ch = getc(yyin)) && ch != '_')
@@ -78,9 +152,12 @@
 		error("identifier too long %s", yytext);
 	*bp = '\0';
 	ungetc(ch, yyin);
-	yyval.sym = lookup(yytext, NS_ANY);
 
-	return (yyval.sym->ns == NS_KEYWORD) ? yyval.sym->tok : IDEN;
+	if (tok = keyword(yytext))
+		return tok;
+
+	yyval.sym = lookup(yytext, NS_ANY);
+	return IDEN;
 }
 
 static unsigned char
--- a/symbol.c
+++ b/symbol.c
@@ -14,7 +14,7 @@
 static struct symbol *head, *headfun;
 
 
-static inline unsigned char
+unsigned char
 hash(register const char *s)
 {
 	register unsigned char h, ch;
@@ -21,7 +21,7 @@
 
 	for (h = 0; ch = *s++; h += ch)
 		/* nothing */;
-	return h & NR_SYM_HASH - 1;
+	return h;
 }
 
 void
@@ -40,7 +40,7 @@
 		if (sym->ctx <= curctx)
 			break;
 		if ((s = sym->name) != NULL)
-			htab[hash(s)] = sym->hash;
+			htab[hash(s) & NR_SYM_HASH - 1] = sym->hash;
 		next = sym->next;
 		sym->next = headfun;
 		headfun = sym;
@@ -76,7 +76,7 @@
 	}
 
 	l = strlen(s);
-	key = hash(s);
+	key = hash(s) & NR_SYM_HASH - 1;
 	if (!(ins = ns >= 0))
 		ns = -ns;
 
--- a/symbol.h
+++ b/symbol.h
@@ -7,9 +7,8 @@
 # include <stdbool.h>
 #endif
 
-#define CTX_OUTER 1
-#define CTX_FUNC  2
-#define CTX_ANY   0
+#define CTX_OUTER 0
+#define CTX_FUNC  1
 
 #define NOINSERT(x) (-x)
 
@@ -52,7 +51,6 @@
 	char *name;
 	struct {
 		union {
-			unsigned char tok;  /* used in keywords */
 			short val;	/* used in integer constant */
 		};
 	};
@@ -76,6 +74,7 @@
 extern struct ctype *storage(struct ctype *tp, unsigned char mod);
 extern struct ctype *newctype(void);
 extern void delctype(struct ctype *tp);
+extern unsigned char hash(register const char *s);
 
 #ifndef NDEBUG
 extern void ptype(register struct ctype *t);