New symbol table code.

This commit is contained in:
Bill Currie 2011-01-05 19:09:49 +09:00
parent d764ef80d0
commit 782a4c9a8d
4 changed files with 357 additions and 2 deletions

View file

@ -3,4 +3,4 @@ AUTOMAKE_OPTIONS= foreign
EXTRA_DIST= class.h cpp.h debug.h def.h emit.h expr.h function.h \ 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 \ 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 \ 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
View 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

View file

@ -52,7 +52,8 @@ EXTRA_PROGRAMS= qfcc qfprogs
qfcc_SOURCES= \ qfcc_SOURCES= \
class.c constfold.c cpp.c debug.c def.c emit.c expr.c function.c \ 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 \ 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_LDADD= $(QFCC_LIBS)
qfcc_DEPENDENCIES= $(QFCC_DEPS) qfcc_DEPENDENCIES= $(QFCC_DEPS)

155
tools/qfcc/source/symtab.c Normal file
View 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;
}