mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 09:51:41 +00:00
New symbol table code.
This commit is contained in:
parent
d764ef80d0
commit
782a4c9a8d
4 changed files with 357 additions and 2 deletions
|
@ -3,4 +3,4 @@ AUTOMAKE_OPTIONS= foreign
|
|||
EXTRA_DIST= class.h cpp.h debug.h def.h emit.h expr.h function.h \
|
||||
idstuff.h immediate.h linker.h method.h obj_file.h opcodes.h \
|
||||
options.h qfcc.h qfprogs.h reloc.h strpool.h struct.h switch.h \
|
||||
type.h
|
||||
symtab.h type.h
|
||||
|
|
199
tools/qfcc/include/symtab.h
Normal file
199
tools/qfcc/include/symtab.h
Normal file
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
symtab.h
|
||||
|
||||
Symbol table management
|
||||
|
||||
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2011/01/04
|
||||
|
||||
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:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifndef __symtab_h
|
||||
#define __symtab_h
|
||||
|
||||
/** \defgroup qfcc_symtab Symbol Table Management
|
||||
\ingroup qfcc
|
||||
*/
|
||||
//@{
|
||||
//
|
||||
typedef enum {
|
||||
sym_type,
|
||||
sym_def,
|
||||
sym_enum,
|
||||
sym_class,
|
||||
} sym_type_e;
|
||||
|
||||
typedef struct symbol_s {
|
||||
struct symbol_s *next; ///< chain of symbols in symbol table
|
||||
const char *name; ///< symbol name
|
||||
sym_type_e type; ///< symbol type (typedef, var, struct...)
|
||||
union {
|
||||
struct type_s *type;
|
||||
struct def_s *def;
|
||||
struct enumval_s *enm;
|
||||
struct class_s *class;
|
||||
} s;
|
||||
} symbol_t;
|
||||
|
||||
typedef enum {
|
||||
stab_global, ///< global (many symbols)
|
||||
stab_local, ///< local (few symbols: func, struct)
|
||||
stab_union, ///< offset always 0
|
||||
} stab_type_e;
|
||||
|
||||
typedef struct symtab_s {
|
||||
struct symtab_s *parent; ///< points to parent table
|
||||
struct symtab_s *next; ///< next in global collection of symtabs
|
||||
stab_type_e type; ///< type of symbol table
|
||||
struct hashtab_s *tab; ///< symbols defined in this table
|
||||
symbol_t *symbols; ///< chain of symbols in this table
|
||||
symbol_t **symtail; ///< keep chain in declaration order
|
||||
} symtab_t;
|
||||
|
||||
/** Create a new, empty symbol table.
|
||||
|
||||
The symbol tables support scoping via their \c parent pointer. This
|
||||
supports both code block scoping and ivar inheritance.
|
||||
|
||||
\param parent Pointer to parent scope symbol table.
|
||||
\param type The type of symbol table. Currently governs expected size.
|
||||
\return The new, empty symbol table.
|
||||
*/
|
||||
symtab_t *new_symtab (symtab_t *parent, stab_type_e type);
|
||||
|
||||
/** Lookup a name in the symbol table.
|
||||
|
||||
The entire symbol table chain (symtab_t::parent) starting at symtab
|
||||
will be checked for \a name.
|
||||
|
||||
\param symtab The symbol table to search for \a name. If \a name is
|
||||
not in the symbol table, the tables's parent, if it
|
||||
exists, will be checked, and then its parent, until the
|
||||
end of the chain.
|
||||
\param name The name to look up in the symbol table chain.
|
||||
*/
|
||||
symbol_t *symtab_lookup (symtab_t *symtab, const char *name);
|
||||
|
||||
/** Add a named type (\c typedef) to the symbol table.
|
||||
|
||||
Duplicate names will not be inserted (an error), but only the given
|
||||
symbol table is checked for duplicate names, not the ancestor chain.
|
||||
|
||||
\param symtab The symbol table to which the named type will be added.
|
||||
\param name The name of the type to be added to the symbol table.
|
||||
\param type The type to be added to the symbol table.
|
||||
\return The new symbol representing the named type or null if
|
||||
an error occurred.
|
||||
*/
|
||||
symbol_t *symtab_add_type (symtab_t *symtab, const char *name,
|
||||
struct type_s *type);
|
||||
|
||||
/** Add a def to the symbol table.
|
||||
|
||||
Duplicate names will not be inserted (an error), but only the given
|
||||
symbol table is checked for duplicate names, not the ancestor chain.
|
||||
|
||||
\param symtab The symbol table to which the def will be added.
|
||||
\param name The name of the def to be added to the symbol table.
|
||||
\param def The def to be added to the symbol table.
|
||||
\return The new symbol representing the def or null if an
|
||||
error occurred.
|
||||
*/
|
||||
symbol_t *symtab_add_def (symtab_t *symtab, const char *name,
|
||||
struct def_s *def);
|
||||
|
||||
/** Add an enum to the symbol table.
|
||||
|
||||
Duplicate names will not be inserted (an error), but only the given
|
||||
symbol table is checked for duplicate names, not the ancestor chain.
|
||||
|
||||
\param symtab The symbol table to which the enum will be added.
|
||||
\param name The name of the enum to be added to the symbol table.
|
||||
\param enm The enum to be added to the symbol table.
|
||||
\return The new symbol representing the enum or null if an
|
||||
error occurred.
|
||||
*/
|
||||
symbol_t *symtab_add_enum (symtab_t *symtab, const char *name,
|
||||
struct enumval_s *enm);
|
||||
|
||||
/** Add a class to the symbol table.
|
||||
|
||||
Duplicate names will not be inserted (an error), but only the given
|
||||
symbol table is checked for duplicate names, not the ancestor chain.
|
||||
|
||||
\param symtab The symbol table to which the class will be added.
|
||||
\param name The name of the class to be added to the symbol table.
|
||||
\param class The class to be added to the symbol table.
|
||||
\return The new symbol representing the class or null if an
|
||||
error occurred.
|
||||
*/
|
||||
symbol_t *symtab_add_class (symtab_t *symtab, const char *name,
|
||||
struct class_s *class);
|
||||
|
||||
/** Create a new single symbol table from the given symbol table chain.
|
||||
|
||||
Create a new symbol table and add all of the symbols from the given
|
||||
symbol table chain to the new symbol table. However, in order to
|
||||
preserve scoping rules, duplicate names in ancestor tables will not be
|
||||
added to the new table.
|
||||
|
||||
The new symbol table will be "local".
|
||||
|
||||
The intended use is for creating the ivar scope for methods.
|
||||
|
||||
\param symtab The symbol table chain to be copied.
|
||||
\param parent The parent symbol table of the new symbol table, or
|
||||
null.
|
||||
\return The new symbol table.
|
||||
|
||||
\dot
|
||||
digraph symtab_flat_copy {
|
||||
layout=fdp;
|
||||
parent;
|
||||
subgraph clusterI {
|
||||
node [shape=record];
|
||||
root [label="{<p>parent|integer\ x;|integer\ y;|float\ z;}"];
|
||||
base [label="{<p>parent|float\ w;|float\ x;}"];
|
||||
cur [label="{<p>parent|float\ y;}"];
|
||||
cur:p -> base;
|
||||
base:p -> root;
|
||||
}
|
||||
subgraph clusterO {
|
||||
node [shape=record];
|
||||
out [label="{<p>parent|float\ z;|float\ w;|float\ x;|float\ y;}"];
|
||||
}
|
||||
symtab;
|
||||
return;
|
||||
symtab -> cur;
|
||||
clusterI -> clusterO [len=1];
|
||||
out:p -> parent;
|
||||
return -> out;
|
||||
}
|
||||
\enddot
|
||||
*/
|
||||
symtab_t *symtab_flat_copy (symtab_t *symtab, symtab_t *parent);
|
||||
|
||||
//@}
|
||||
|
||||
#endif//__symtab_h
|
|
@ -52,7 +52,8 @@ EXTRA_PROGRAMS= qfcc qfprogs
|
|||
qfcc_SOURCES= \
|
||||
class.c constfold.c cpp.c debug.c def.c emit.c expr.c function.c \
|
||||
idstuff.c immediate.c linker.c method.c obj_file.c opcodes.c options.c \
|
||||
qc-lex.l qc-parse.y qfcc.c reloc.c strpool.c struct.c switch.c type.c
|
||||
qc-lex.l qc-parse.y qfcc.c reloc.c strpool.c struct.c switch.c symtab.c \
|
||||
type.c
|
||||
|
||||
qfcc_LDADD= $(QFCC_LIBS)
|
||||
qfcc_DEPENDENCIES= $(QFCC_DEPS)
|
||||
|
|
155
tools/qfcc/source/symtab.c
Normal file
155
tools/qfcc/source/symtab.c
Normal file
|
@ -0,0 +1,155 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "QF/hash.h"
|
||||
|
||||
#include "class.h"
|
||||
#include "def.h"
|
||||
#include "qfcc.h"
|
||||
#include "symtab.h"
|
||||
#include "type.h"
|
||||
|
||||
static symtab_t *free_symtabs;
|
||||
static symbol_t *free_symbols;
|
||||
|
||||
static const char *
|
||||
sym_getkey (void *k, void *unused)
|
||||
{
|
||||
return ((symbol_t *) k)->name;
|
||||
}
|
||||
|
||||
symtab_t *
|
||||
new_symtab (symtab_t *parent, stab_type_e type)
|
||||
{
|
||||
symtab_t *symtab;
|
||||
int tabsize = 63;
|
||||
|
||||
ALLOC (16, symtab_t, symtabs, symtab);
|
||||
|
||||
symtab->parent = parent;
|
||||
symtab->type = type;
|
||||
if (symtab->type == stab_global)
|
||||
tabsize = 1023;
|
||||
symtab->tab = Hash_NewTable (tabsize, sym_getkey, 0, 0);
|
||||
symtab->symtail = &symtab->symbols;
|
||||
return symtab;
|
||||
}
|
||||
|
||||
symbol_t *
|
||||
symtab_lookup (symtab_t *symtab, const char *name)
|
||||
{
|
||||
symbol_t *symbol;
|
||||
while (symtab) {
|
||||
if ((symbol = Hash_Find (symtab->tab, name)))
|
||||
return symbol;
|
||||
symtab = symtab->parent;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static symbol_t *
|
||||
new_symbol (void)
|
||||
{
|
||||
symbol_t *symbol;
|
||||
ALLOC (256, symbol_t, symbols, symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
static void
|
||||
add_symbol (symtab_t *symtab, symbol_t *symbol)
|
||||
{
|
||||
Hash_Add (symtab->tab, symbol);
|
||||
symbol->next = *symtab->symtail;
|
||||
*symtab->symtail = symbol;
|
||||
symtab->symtail = &symbol->next;
|
||||
}
|
||||
|
||||
symbol_t *
|
||||
symtab_add_type (symtab_t *symtab, const char *name, type_t *type)
|
||||
{
|
||||
symbol_t *symbol;
|
||||
if ((symbol = Hash_Find (symtab->tab, name))) {
|
||||
// duplicate symbol
|
||||
}
|
||||
symbol = new_symbol ();
|
||||
symbol->name = name;
|
||||
symbol->type = sym_type;
|
||||
symbol->s.type = type;
|
||||
add_symbol (symtab, symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
symbol_t *
|
||||
symtab_add_def (symtab_t *symtab, const char *name, def_t *def)
|
||||
{
|
||||
symbol_t *symbol;
|
||||
if ((symbol = Hash_Find (symtab->tab, name))) {
|
||||
// duplicate symbol
|
||||
}
|
||||
symbol = new_symbol ();
|
||||
symbol->name = name;
|
||||
symbol->type = sym_def;
|
||||
symbol->s.def = def;
|
||||
add_symbol (symtab, symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
symbol_t *
|
||||
symtab_add_enum (symtab_t *symtab, const char *name, struct enumval_s *enm)
|
||||
{
|
||||
symbol_t *symbol;
|
||||
if ((symbol = Hash_Find (symtab->tab, name))) {
|
||||
// duplicate symbol
|
||||
}
|
||||
symbol = new_symbol ();
|
||||
symbol->name = name;
|
||||
symbol->type = sym_enum;
|
||||
symbol->s.enm = enm;
|
||||
add_symbol (symtab, symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
symbol_t *
|
||||
symtab_add_class (symtab_t *symtab, const char *name, class_t *class)
|
||||
{
|
||||
symbol_t *symbol;
|
||||
if ((symbol = Hash_Find (symtab->tab, name))) {
|
||||
// duplicate symbol
|
||||
}
|
||||
symbol = new_symbol ();
|
||||
symbol->name = name;
|
||||
symbol->type = sym_class;
|
||||
symbol->s.class = class;
|
||||
add_symbol (symtab, symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
symtab_t *
|
||||
symtab_flat_copy (symtab_t *symtab, symtab_t *parent)
|
||||
{
|
||||
symtab_t *newtab;
|
||||
symbol_t *newsym;
|
||||
symbol_t *symbol;
|
||||
|
||||
newtab = new_symtab (parent, stab_local);
|
||||
while (symtab) {
|
||||
for (symbol = symtab->symbols; symbol; symbol = symbol->next) {
|
||||
if (Hash_Find (newtab->tab, symbol->name))
|
||||
continue;
|
||||
newsym = new_symbol ();
|
||||
*newsym = *symbol;
|
||||
add_symbol (newtab, newsym);
|
||||
}
|
||||
symtab = symtab->parent;
|
||||
// Set the tail pointer so symbols in ancestor tables come before
|
||||
// those in decendent tables.
|
||||
newtab->symtail = &newtab->symbols;
|
||||
}
|
||||
// Reset the tail pointer so any symbols added to newtab come after
|
||||
// those copied from the input symbol table chain.
|
||||
for (symbol = newtab->symbols; symbol && symbol->next;
|
||||
symbol = symbol->next)
|
||||
;
|
||||
newtab->symtail = symbol ? &symbol->next : &newtab->symbols;
|
||||
return newtab;
|
||||
}
|
Loading…
Reference in a new issue