From ec16ffaa651e59d0233b2a87ace45ca57449b387 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Apr 2001 02:12:57 +0000 Subject: [PATCH] move to using hash tables for variable lookups. WARNING: this fixes a scope bug in qcc and thus you WILL get different (but now correct) code for the following: float foo; void () bar = { local float foo; foo = 0; } ie, the local foo will, as is correct, now be a separate var to the global foo. --- tools/qfcc/include/qfcc.h | 4 +- tools/qfcc/source/Makefile.am | 2 +- tools/qfcc/source/pr_comp.c | 108 +----------------------- tools/qfcc/source/pr_def.c | 151 ++++++++++++++++++++++++++++++++++ tools/qfcc/source/qfcc.c | 4 +- 5 files changed, 161 insertions(+), 108 deletions(-) create mode 100644 tools/qfcc/source/pr_def.c diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 8f4e53680..bc76df920 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -254,7 +254,7 @@ typedef struct def_s type_t *type; char *name; struct def_s *next; - struct def_s *search_next; // for finding faster + struct def_s *scope_next; // to facilitate hash table removal gofs_t ofs; struct def_s *scope; // function the var was defined in, or NULL int initialized; // 1 when a declaration included "= immediate" @@ -384,6 +384,8 @@ extern int pr_error_count; void PR_NewLine (void); def_t *PR_GetDef (type_t *type, char *name, def_t *scope, qboolean allocate); +def_t *PR_NewDef (type_t *type, const char *name, def_t *scope); +void PR_FlushScope (def_t *scope); void PR_PrintDefs (void); diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index e788e00eb..4581588ce 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -32,5 +32,5 @@ INCLUDES= -I$(top_srcdir)/include bin_PROGRAMS= qfcc -qfcc_SOURCES= cmdlib.c pr_comp.c pr_lex.c qfcc.c +qfcc_SOURCES= cmdlib.c pr_comp.c pr_def.c pr_lex.c qfcc.c qfcc_LDADD= -lQFutil diff --git a/tools/qfcc/source/pr_comp.c b/tools/qfcc/source/pr_comp.c index e0c49a4e3..c0763b687 100644 --- a/tools/qfcc/source/pr_comp.c +++ b/tools/qfcc/source/pr_comp.c @@ -221,18 +221,10 @@ PR_ParseImmediate (void) } // allocate a new one - cn = malloc (sizeof (def_t)); - cn->next = NULL; - pr.def_tail->next = cn; - pr.def_tail = cn; - - cn->search_next = pr.search; - pr.search = cn; - - cn->type = pr_immediate_type; - cn->name = "IMMEDIATE"; + // always share immediates + cn = PR_NewDef (pr_immediate_type, "IMMEDIATE", 0); cn->initialized = 1; - cn->scope = NULL; // always share immediates + cn->scope = NULL; // copy the immediate to the global area cn->ofs = numpr_globals; @@ -728,99 +720,6 @@ PR_ParseImmediateStatements (type_t *type) return f; } -/* - PR_GetDef - - If type is NULL, it will match any type - If allocate is true, a new def will be allocated if it can't be found -*/ -def_t * -PR_GetDef (type_t *type, char *name, def_t *scope, qboolean allocate) -{ - def_t *def, **old; - char element[MAX_NAME]; - - // see if the name is already in use - old = &pr.search; - for (def = *old; def; old = &def->search_next, def = *old) - if (!strcmp (def->name, name)) { - if (def->scope && def->scope != scope) // in a different function - continue; - - if (type && def->type != type) - PR_ParseError ("Type mismatch on redeclaration of %s", name); - - // move to head of list to find fast next time - *old = def->search_next; - def->search_next = pr.search; - pr.search = def; - - return def; - } - - if (!allocate) - return NULL; - - // allocate a new def - def = malloc (sizeof (def_t)); - memset (def, 0, sizeof (*def)); - def->next = NULL; - pr.def_tail->next = def; - pr.def_tail = def; - - - def->search_next = pr.search; - pr.search = def; - - def->name = malloc (strlen (name) + 1); - strcpy (def->name, name); - def->type = type; - - def->scope = scope; - - def->ofs = numpr_globals; - pr_global_defs[numpr_globals] = def; - - /* - make automatic defs for the vectors elements - .origin can be accessed as .origin_x, .origin_y, and .origin_z - */ - if (type->type == ev_vector) { - sprintf (element, "%s_x", name); - PR_GetDef (&type_float, element, scope, true); - - sprintf (element, "%s_y", name); - PR_GetDef (&type_float, element, scope, true); - - sprintf (element, "%s_z", name); - PR_GetDef (&type_float, element, scope, true); - } else { - numpr_globals += type_size[type->type]; - } - - if (type->type == ev_field) { - *(int *) &pr_globals[def->ofs] = pr.size_fields; - - if (type->aux_type->type == ev_vector) { - sprintf (element, "%s_x", name); - PR_GetDef (&type_floatfield, element, scope, true); - - sprintf (element, "%s_y", name); - PR_GetDef (&type_floatfield, element, scope, true); - - sprintf (element, "%s_z", name); - PR_GetDef (&type_floatfield, element, scope, true); - } else { - pr.size_fields += type_size[type->aux_type->type]; - } - } - -// if (pr_dumpasm) -// PR_PrintOfs (def->ofs); - - return def; -} - /* PR_ParseDefs @@ -856,6 +755,7 @@ PR_ParseDefs (void) locals_start = locals_end = numpr_globals; pr_scope = def; f = PR_ParseImmediateStatements (type); + PR_FlushScope (pr_scope); pr_scope = NULL; def->initialized = 1; G_FUNCTION (def->ofs) = numfunctions; diff --git a/tools/qfcc/source/pr_def.c b/tools/qfcc/source/pr_def.c new file mode 100644 index 000000000..a0c50eb56 --- /dev/null +++ b/tools/qfcc/source/pr_def.c @@ -0,0 +1,151 @@ +/* Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + See file, 'COPYING', for details. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "qfcc.h" + + +def_t *pr_global_defs[MAX_REGS]; // to find def for a global variable +int pr_edict_size; + +hashtab_t *defs_by_name; + +static char * +defs_get_key (void *_def, void *_tab) +{ + def_t *def = (def_t*)_def; + hashtab_t **tab = (hashtab_t**) _tab; + + if (tab == &defs_by_name) { + return def->name; + } + return ""; +} + +/* + PR_GetDef + + If type is NULL, it will match any type + If allocate is true, a new def will be allocated if it can't be found +*/ +def_t * +PR_GetDef (type_t *type, char *name, def_t *scope, qboolean allocate) +{ + def_t *def; + char element[MAX_NAME]; + + if (!defs_by_name) { + defs_by_name = Hash_NewTable (1021, defs_get_key, 0, &defs_by_name); + } + + // see if the name is already in use + def = (def_t*) Hash_Find (defs_by_name, name); + if (def) { + if (allocate && scope == def->scope) + if (type && def->type != type) + PR_ParseError ("Type mismatch on redeclaration of %s", name); + if (!allocate || def->scope == scope) + return def; + } + + if (!allocate) + return NULL; + + // allocate a new def + def = PR_NewDef (type, name, scope); + Hash_Add (defs_by_name, def); + + def->ofs = numpr_globals; + pr_global_defs[numpr_globals] = def; + + /* + make automatic defs for the vectors elements + .origin can be accessed as .origin_x, .origin_y, and .origin_z + */ + if (type->type == ev_vector) { + sprintf (element, "%s_x", name); + PR_GetDef (&type_float, element, scope, true); + + sprintf (element, "%s_y", name); + PR_GetDef (&type_float, element, scope, true); + + sprintf (element, "%s_z", name); + PR_GetDef (&type_float, element, scope, true); + } else { + numpr_globals += type_size[type->type]; + } + + if (type->type == ev_field) { + *(int *) &pr_globals[def->ofs] = pr.size_fields; + + if (type->aux_type->type == ev_vector) { + sprintf (element, "%s_x", name); + PR_GetDef (&type_floatfield, element, scope, true); + + sprintf (element, "%s_y", name); + PR_GetDef (&type_floatfield, element, scope, true); + + sprintf (element, "%s_z", name); + PR_GetDef (&type_floatfield, element, scope, true); + } else { + pr.size_fields += type_size[type->aux_type->type]; + } + } + +// if (pr_dumpasm) +// PR_PrintOfs (def->ofs); + + return def; +} + +def_t * +PR_NewDef (type_t *type, const char *name, def_t *scope) +{ + def_t *def; + + def = calloc (1, sizeof (def_t)); + pr.def_tail->next = def; + pr.def_tail = def; + + if (scope) { + def->scope_next = scope->scope_next; + scope->scope_next = def; + } + + def->name = strdup (name); + def->type = type; + + def->scope = scope; + + return def; +} + +void +PR_FlushScope (def_t *scope) +{ + def_t *def; + + for (def = scope->scope_next; def; def = def->scope_next) { + Hash_Del (defs_by_name, def->name); + } +} diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 695d238df..c13d2071b 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -30,8 +30,8 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif -#include "QF/crc.h" -#include "QF/qendian.h" +#include +#include #include "qfcc.h"