mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
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.
This commit is contained in:
parent
581d6bc721
commit
ec16ffaa65
5 changed files with 161 additions and 108 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
151
tools/qfcc/source/pr_def.c
Normal file
151
tools/qfcc/source/pr_def.c
Normal file
|
@ -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 <QF/hash.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
|
@ -30,8 +30,8 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include "QF/crc.h"
|
||||
#include "QF/qendian.h"
|
||||
#include <QF/crc.h>
|
||||
#include <QF/qendian.h>
|
||||
|
||||
#include "qfcc.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue