From: Peter Johnson Date: Mon, 24 Sep 2001 06:40:27 +0000 (-0000) Subject: Used ternary search tree instead of linked list to store symbol table. X-Git-Tag: v0.1.0~301 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f9209d52006975d48015bb9c81024605ba4ec31b;p=yasm Used ternary search tree instead of linked list to store symbol table. Cleaned up function naming too. Removed locallabel_base from global.h, moving it into the parser-specific code. Made sym_table private to symrec.c. svn path=/trunk/yasm/; revision=220 --- diff --git a/libyasm/linemgr.h b/libyasm/linemgr.h index a836dfd9..1d6716e0 100644 --- a/libyasm/linemgr.h +++ b/libyasm/linemgr.h @@ -25,6 +25,5 @@ extern char *filename; extern unsigned int line_number; extern unsigned char mode_bits; -extern struct symrec_s *locallabel_base; #endif diff --git a/libyasm/symrec.c b/libyasm/symrec.c index 8de9f81e..779e03a1 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -40,105 +40,65 @@ RCSID("$IdPath$"); /* private functions */ -static symtab *symtab_get(char *); -static symtab *symtab_new(char *, SymType); -static symtab *symtab_get_or_new(char *, SymType); -static void symtab_insert(symtab *); +static symrec *symrec_get_or_new(char *, SymType); -/* The symbol table: a chain of `symtab'. */ -symtab *sym_table = (symtab *)NULL; +/* The symbol table: a ternary tree. */ +static ternary_tree sym_table = (ternary_tree)NULL; -/* insert a symtab into the global sym_table */ -void -symtab_insert(symtab *tab) -{ - tab->next = (symtab *)sym_table; - sym_table = tab; -} - -/* find a symtab in the global sym_table */ -symtab * -symtab_get(char *name) +/* create a new symrec */ +static symrec * +symrec_get_or_new(char *name, SymType type) { - symtab *tab; + symrec *rec, *rec2; - for (tab = sym_table; tab != NULL; tab = tab->next) { - if (strcmp(tab->rec.name, name) == 0) { - return tab; - } - } - return NULL; -} + rec = malloc(sizeof(symrec)); + if (!rec) + Fatal(FATAL_NOMEM); -/* call a function with each symrec. stop early if 0 returned */ -void -sym_foreach(int (*mapfunc) (symrec *)) -{ - symtab *tab; + rec2 = ternary_insert(&sym_table, name, rec, 0); - for (tab = sym_table; tab != NULL; tab = tab->next) { - if (mapfunc(&(tab->rec)) == 0) { - return; - } + if (rec2 != rec) { + free(rec); + return rec2; } -} -/* create a new symtab */ -symtab * -symtab_new(char *name, SymType type) -{ - symtab *tab; - tab = malloc(sizeof(symtab)); - if (tab == NULL) - return NULL; - tab->rec.name = malloc(strlen(name) + 1); - if (tab->rec.name == NULL) { - free(tab); - return NULL; - } - strcpy(tab->rec.name, name); - tab->rec.type = type; - tab->rec.value = 0; - tab->rec.line = line_number; - tab->rec.status = SYM_NOSTATUS; - symtab_insert(tab); - return tab; + rec->name = strdup(name); + if (!rec->name) + Fatal(FATAL_NOMEM); + rec->type = type; + rec->value = 0; + rec->line = line_number; + rec->status = SYM_NOSTATUS; + + return rec; } -symtab * -symtab_get_or_new(char *name, SymType type) +/* call a function with each symrec. stop early if 0 returned */ +void +symrec_foreach(int (*func) (char *name, symrec *rec)) { - symtab *tab; - - tab = symtab_get(name); - if (tab == NULL) { - tab = symtab_new(name, type); - if (tab == NULL) { - Fatal(FATAL_NOMEM); - } - } - return tab; } symrec * -sym_use_get(char *name, SymType type) +symrec_use(char *name, SymType type) { - symtab *tab; + symrec *rec; - tab = symtab_get_or_new(name, type); - tab->rec.status |= SYM_USED; - return &(tab->rec); + rec = symrec_get_or_new(name, type); + rec->status |= SYM_USED; + return rec; } symrec * -sym_def_get(char *name, SymType type) +symrec_define(char *name, SymType type) { - symtab *tab; + symrec *rec; - tab = symtab_get_or_new(name, type); - if (tab->rec.status & SYM_DECLARED) + rec = symrec_get_or_new(name, type); + if (rec->status & SYM_DECLARED) Error(_("duplicate definition of `%s'; previously defined on line %d"), - tab->rec.name, tab->rec.line); - tab->rec.status |= SYM_DECLARED; - return &(tab->rec); + name, rec->line); + rec->line = line_number; /* set line number of definition */ + rec->status |= SYM_DECLARED; + return rec; } diff --git a/libyasm/symrec.h b/libyasm/symrec.h index a31fe7e2..936c6728 100644 --- a/libyasm/symrec.h +++ b/libyasm/symrec.h @@ -38,19 +38,12 @@ typedef struct symrec_s { char *name; SymType type; SymStatus status; - int line; + int line; /* line symbol was first declared or used on */ double value; } symrec; -typedef struct symtab_s { - symrec rec; - struct symtab_s *next; -} symtab; - -extern symtab *sym_table; - -symrec *sym_use_get(char *, SymType); -symrec *sym_def_get(char *, SymType); -void sym_foreach(int (*)(symrec *)); +symrec *symrec_use(char *name, SymType type); +symrec *symrec_define(char *name, SymType type); +void symrec_foreach(int (*func) (char *name, symrec *rec)); #endif diff --git a/modules/parsers/nasm/bison.y.in b/modules/parsers/nasm/bison.y.in index d3eee5ac..25cd0dee 100644 --- a/modules/parsers/nasm/bison.y.in +++ b/modules/parsers/nasm/bison.y.in @@ -56,6 +56,7 @@ void nasm_parser_error(char *); extern objfmt *nasm_parser_objfmt; extern sectionhead nasm_parser_sections; extern section *nasm_parser_cur_section; +extern char *nasm_parser_locallabel_base; %} @@ -176,9 +177,12 @@ label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */ | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */ ; -label_id: ID { $$ = locallabel_base = sym_def_get($1.name, SYM_LABEL); } - | SPECIAL_ID { $$ = sym_def_get($1.name, SYM_LABEL); } - | LOCAL_ID { $$ = sym_def_get($1.name, SYM_LABEL); } +label_id: ID { + $$ = symrec_define($1.name, SYM_LABEL); + nasm_parser_locallabel_base = strdup($1.name); + } + | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } + | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } ; /* directives */ @@ -375,8 +379,7 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } /* expression trees */ expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } | explabel { - $$ = expr_new_ident(EXPR_SYM, - ExprSym(sym_use_get($1.name, SYM_LABEL))); + $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL))); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } diff --git a/modules/parsers/nasm/nasm-bison.y b/modules/parsers/nasm/nasm-bison.y index d3eee5ac..25cd0dee 100644 --- a/modules/parsers/nasm/nasm-bison.y +++ b/modules/parsers/nasm/nasm-bison.y @@ -56,6 +56,7 @@ void nasm_parser_error(char *); extern objfmt *nasm_parser_objfmt; extern sectionhead nasm_parser_sections; extern section *nasm_parser_cur_section; +extern char *nasm_parser_locallabel_base; %} @@ -176,9 +177,12 @@ label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */ | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */ ; -label_id: ID { $$ = locallabel_base = sym_def_get($1.name, SYM_LABEL); } - | SPECIAL_ID { $$ = sym_def_get($1.name, SYM_LABEL); } - | LOCAL_ID { $$ = sym_def_get($1.name, SYM_LABEL); } +label_id: ID { + $$ = symrec_define($1.name, SYM_LABEL); + nasm_parser_locallabel_base = strdup($1.name); + } + | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } + | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } ; /* directives */ @@ -375,8 +379,7 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } /* expression trees */ expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } | explabel { - $$ = expr_new_ident(EXPR_SYM, - ExprSym(sym_use_get($1.name, SYM_LABEL))); + $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL))); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } diff --git a/modules/parsers/nasm/token.l.in b/modules/parsers/nasm/token.l.in index ab87ebf9..47a6fdb7 100644 --- a/modules/parsers/nasm/token.l.in +++ b/modules/parsers/nasm/token.l.in @@ -62,7 +62,7 @@ static char *strbuf = (char *)NULL; static size_t strbuf_size = 0; /* last "base" label for local (.) labels */ -symrec *locallabel_base = (symrec *)NULL; +char *nasm_parser_locallabel_base = (char *)NULL; /* current line number */ int line_number; @@ -305,17 +305,17 @@ $$|$|\.\.[a-z0-9_$#@~.?]+ { /* local label (.label) */ \.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* { - if (!locallabel_base) { + if (!nasm_parser_locallabel_base) { Warning(_("no non-local label before `%s'"), yytext); yylval.syminfo.name = strdup(yytext); if (!yylval.syminfo.name) Fatal(FATAL_NOMEM); } else { yylval.syminfo.name = malloc(strlen(yytext) + - strlen(locallabel_base->name) + 1); + strlen(nasm_parser_locallabel_base) + 1); if (!yylval.syminfo.name) Fatal(FATAL_NOMEM); - strcpy(yylval.syminfo.name, locallabel_base->name); + strcpy(yylval.syminfo.name, nasm_parser_locallabel_base); strcat(yylval.syminfo.name, yytext); } yylval.syminfo.line = line_number; diff --git a/src/globals.h b/src/globals.h index a836dfd9..1d6716e0 100644 --- a/src/globals.h +++ b/src/globals.h @@ -25,6 +25,5 @@ extern char *filename; extern unsigned int line_number; extern unsigned char mode_bits; -extern struct symrec_s *locallabel_base; #endif diff --git a/src/linemgr.h b/src/linemgr.h index a836dfd9..1d6716e0 100644 --- a/src/linemgr.h +++ b/src/linemgr.h @@ -25,6 +25,5 @@ extern char *filename; extern unsigned int line_number; extern unsigned char mode_bits; -extern struct symrec_s *locallabel_base; #endif diff --git a/src/parsers/nasm/bison.y.in b/src/parsers/nasm/bison.y.in index d3eee5ac..25cd0dee 100644 --- a/src/parsers/nasm/bison.y.in +++ b/src/parsers/nasm/bison.y.in @@ -56,6 +56,7 @@ void nasm_parser_error(char *); extern objfmt *nasm_parser_objfmt; extern sectionhead nasm_parser_sections; extern section *nasm_parser_cur_section; +extern char *nasm_parser_locallabel_base; %} @@ -176,9 +177,12 @@ label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */ | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */ ; -label_id: ID { $$ = locallabel_base = sym_def_get($1.name, SYM_LABEL); } - | SPECIAL_ID { $$ = sym_def_get($1.name, SYM_LABEL); } - | LOCAL_ID { $$ = sym_def_get($1.name, SYM_LABEL); } +label_id: ID { + $$ = symrec_define($1.name, SYM_LABEL); + nasm_parser_locallabel_base = strdup($1.name); + } + | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } + | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } ; /* directives */ @@ -375,8 +379,7 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } /* expression trees */ expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } | explabel { - $$ = expr_new_ident(EXPR_SYM, - ExprSym(sym_use_get($1.name, SYM_LABEL))); + $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL))); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } diff --git a/src/parsers/nasm/nasm-bison.y b/src/parsers/nasm/nasm-bison.y index d3eee5ac..25cd0dee 100644 --- a/src/parsers/nasm/nasm-bison.y +++ b/src/parsers/nasm/nasm-bison.y @@ -56,6 +56,7 @@ void nasm_parser_error(char *); extern objfmt *nasm_parser_objfmt; extern sectionhead nasm_parser_sections; extern section *nasm_parser_cur_section; +extern char *nasm_parser_locallabel_base; %} @@ -176,9 +177,12 @@ label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */ | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */ ; -label_id: ID { $$ = locallabel_base = sym_def_get($1.name, SYM_LABEL); } - | SPECIAL_ID { $$ = sym_def_get($1.name, SYM_LABEL); } - | LOCAL_ID { $$ = sym_def_get($1.name, SYM_LABEL); } +label_id: ID { + $$ = symrec_define($1.name, SYM_LABEL); + nasm_parser_locallabel_base = strdup($1.name); + } + | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } + | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } ; /* directives */ @@ -375,8 +379,7 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } /* expression trees */ expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } | explabel { - $$ = expr_new_ident(EXPR_SYM, - ExprSym(sym_use_get($1.name, SYM_LABEL))); + $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL))); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } diff --git a/src/parsers/nasm/token.l.in b/src/parsers/nasm/token.l.in index ab87ebf9..47a6fdb7 100644 --- a/src/parsers/nasm/token.l.in +++ b/src/parsers/nasm/token.l.in @@ -62,7 +62,7 @@ static char *strbuf = (char *)NULL; static size_t strbuf_size = 0; /* last "base" label for local (.) labels */ -symrec *locallabel_base = (symrec *)NULL; +char *nasm_parser_locallabel_base = (char *)NULL; /* current line number */ int line_number; @@ -305,17 +305,17 @@ $$|$|\.\.[a-z0-9_$#@~.?]+ { /* local label (.label) */ \.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* { - if (!locallabel_base) { + if (!nasm_parser_locallabel_base) { Warning(_("no non-local label before `%s'"), yytext); yylval.syminfo.name = strdup(yytext); if (!yylval.syminfo.name) Fatal(FATAL_NOMEM); } else { yylval.syminfo.name = malloc(strlen(yytext) + - strlen(locallabel_base->name) + 1); + strlen(nasm_parser_locallabel_base) + 1); if (!yylval.syminfo.name) Fatal(FATAL_NOMEM); - strcpy(yylval.syminfo.name, locallabel_base->name); + strcpy(yylval.syminfo.name, nasm_parser_locallabel_base); strcat(yylval.syminfo.name, yytext); } yylval.syminfo.line = line_number; diff --git a/src/symrec.c b/src/symrec.c index 8de9f81e..779e03a1 100644 --- a/src/symrec.c +++ b/src/symrec.c @@ -40,105 +40,65 @@ RCSID("$IdPath$"); /* private functions */ -static symtab *symtab_get(char *); -static symtab *symtab_new(char *, SymType); -static symtab *symtab_get_or_new(char *, SymType); -static void symtab_insert(symtab *); +static symrec *symrec_get_or_new(char *, SymType); -/* The symbol table: a chain of `symtab'. */ -symtab *sym_table = (symtab *)NULL; +/* The symbol table: a ternary tree. */ +static ternary_tree sym_table = (ternary_tree)NULL; -/* insert a symtab into the global sym_table */ -void -symtab_insert(symtab *tab) -{ - tab->next = (symtab *)sym_table; - sym_table = tab; -} - -/* find a symtab in the global sym_table */ -symtab * -symtab_get(char *name) +/* create a new symrec */ +static symrec * +symrec_get_or_new(char *name, SymType type) { - symtab *tab; + symrec *rec, *rec2; - for (tab = sym_table; tab != NULL; tab = tab->next) { - if (strcmp(tab->rec.name, name) == 0) { - return tab; - } - } - return NULL; -} + rec = malloc(sizeof(symrec)); + if (!rec) + Fatal(FATAL_NOMEM); -/* call a function with each symrec. stop early if 0 returned */ -void -sym_foreach(int (*mapfunc) (symrec *)) -{ - symtab *tab; + rec2 = ternary_insert(&sym_table, name, rec, 0); - for (tab = sym_table; tab != NULL; tab = tab->next) { - if (mapfunc(&(tab->rec)) == 0) { - return; - } + if (rec2 != rec) { + free(rec); + return rec2; } -} -/* create a new symtab */ -symtab * -symtab_new(char *name, SymType type) -{ - symtab *tab; - tab = malloc(sizeof(symtab)); - if (tab == NULL) - return NULL; - tab->rec.name = malloc(strlen(name) + 1); - if (tab->rec.name == NULL) { - free(tab); - return NULL; - } - strcpy(tab->rec.name, name); - tab->rec.type = type; - tab->rec.value = 0; - tab->rec.line = line_number; - tab->rec.status = SYM_NOSTATUS; - symtab_insert(tab); - return tab; + rec->name = strdup(name); + if (!rec->name) + Fatal(FATAL_NOMEM); + rec->type = type; + rec->value = 0; + rec->line = line_number; + rec->status = SYM_NOSTATUS; + + return rec; } -symtab * -symtab_get_or_new(char *name, SymType type) +/* call a function with each symrec. stop early if 0 returned */ +void +symrec_foreach(int (*func) (char *name, symrec *rec)) { - symtab *tab; - - tab = symtab_get(name); - if (tab == NULL) { - tab = symtab_new(name, type); - if (tab == NULL) { - Fatal(FATAL_NOMEM); - } - } - return tab; } symrec * -sym_use_get(char *name, SymType type) +symrec_use(char *name, SymType type) { - symtab *tab; + symrec *rec; - tab = symtab_get_or_new(name, type); - tab->rec.status |= SYM_USED; - return &(tab->rec); + rec = symrec_get_or_new(name, type); + rec->status |= SYM_USED; + return rec; } symrec * -sym_def_get(char *name, SymType type) +symrec_define(char *name, SymType type) { - symtab *tab; + symrec *rec; - tab = symtab_get_or_new(name, type); - if (tab->rec.status & SYM_DECLARED) + rec = symrec_get_or_new(name, type); + if (rec->status & SYM_DECLARED) Error(_("duplicate definition of `%s'; previously defined on line %d"), - tab->rec.name, tab->rec.line); - tab->rec.status |= SYM_DECLARED; - return &(tab->rec); + name, rec->line); + rec->line = line_number; /* set line number of definition */ + rec->status |= SYM_DECLARED; + return rec; } diff --git a/src/symrec.h b/src/symrec.h index a31fe7e2..936c6728 100644 --- a/src/symrec.h +++ b/src/symrec.h @@ -38,19 +38,12 @@ typedef struct symrec_s { char *name; SymType type; SymStatus status; - int line; + int line; /* line symbol was first declared or used on */ double value; } symrec; -typedef struct symtab_s { - symrec rec; - struct symtab_s *next; -} symtab; - -extern symtab *sym_table; - -symrec *sym_use_get(char *, SymType); -symrec *sym_def_get(char *, SymType); -void sym_foreach(int (*)(symrec *)); +symrec *symrec_use(char *name, SymType type); +symrec *symrec_define(char *name, SymType type); +void symrec_foreach(int (*func) (char *name, symrec *rec)); #endif