home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
icon
/
dos
/
src
/
rtt
/
rttsym.c
< prev
Wrap
C/C++ Source or Header
|
1992-02-10
|
22KB
|
765 lines
/*
* rttsym.c contains symbol table routines.
*/
#include "rtt.h"
#define HashSize 149
/*
* Prototype for static function.
*/
hidden novalue add_def Params((struct node *dcltor));
hidden novalue add_s_prm Params((struct token *ident, int param_num,
int flags));
hidden novalue dcl_typ Params((struct node *dcl));
hidden novalue dcltor_typ Params((struct node *dcltor, struct node *tqual));
word lbl_num = 0; /* next unused label number */
struct lvl_entry *dcl_stk; /* stack of declaration contexts */
char *str_rslt; /* string "result" in string table */
struct init_tend *tend_lst = NULL; /* list of tended descriptors */
struct sym_entry *decl_lst = NULL; /* declarations from "declare {...}" */
struct sym_entry *v_len = NULL; /* entry for length of varargs */
int il_indx = 0; /* data base symbol table index */
/*
* Free lists for various structures.
*/
static struct sym_entry *sym_free = NULL;
static struct lvl_entry *lvl_entry_free = NULL;
static struct init_tend *init_tend_free = NULL;
static struct sym_entry *sym_tbl[HashSize]; /* symbol table */
/*
* The following strings are put in the string table and used for
* reconginizing valid tended declarations.
*/
static char *block = "block";
static char *descrip = "descrip";
static char *blk_lst[] = {"b_real", "b_cset", "b_file", "b_proc",
"b_list", "b_lelem", "b_table", "b_telem", "b_set", "b_selem",
"b_record", "b_tvkywd", "b_tvsubs", "b_tvtbl", "b_coexpr", "b_refresh",
"b_slots", NULL};
/*
* init_sym - initialize symbol table.
*/
novalue init_sym()
{
static int first_time = 1;
int hash_val;
register struct sym_entry *sym;
int i;
char **s;
/*
* Initialize the symbol table and declaration stack. When called for
* the first time, put strings in string table.
*/
if (first_time) {
first_time = 0;
for (i = 0; i < HashSize; ++i)
sym_tbl[i] = NULL;
dcl_stk = NewStruct(lvl_entry);
dcl_stk->nest_lvl = 1;
dcl_stk->next = NULL;
block = spec_str(block);
descrip = spec_str(descrip);
for (s = blk_lst; *s != NULL; ++s)
*s = spec_str(*s);
}
else {
for (hash_val = 0; hash_val < HashSize; ++ hash_val) {
for (sym = sym_tbl[hash_val]; sym != NULL &&
sym->nest_lvl > 0; sym = sym_tbl[hash_val]) {
sym_tbl[hash_val] = sym->next;
sym->next = sym_free;
sym_free = sym;
}
}
}
dcl_stk->kind_dcl = OtherDcl;
dcl_stk->parms_done = 0;
}
/*
* sym_lkup - look up a string in the symbol table. Return NULL If it is not
* there.
*/
struct sym_entry *sym_lkup(image)
char *image;
{
register struct sym_entry *sym;
for (sym = sym_tbl[(unsigned int)image % HashSize]; sym != NULL;
sym = sym->next)
if (sym->image == image)
return sym;
return NULL;
}
/*
* sym_add - add a symbol to the symbol table. For some types of entries
* it is illegal to redefine them. In that case, NULL is returned otherwise
* the entry is returned.
*/
struct sym_entry *sym_add(tok_id, image, id_type, nest_lvl)
int tok_id;
char *image;
int id_type;
int nest_lvl;
{
register struct sym_entry **symp;
register struct sym_entry *sym;
symp = &sym_tbl[(unsigned int)image % HashSize];
while (*symp != NULL && (*symp)->nest_lvl > nest_lvl)
symp = &((*symp)->next);
while (*symp != NULL && (*symp)->nest_lvl == nest_lvl) {
if ((*symp)->image == image) {
/*
* Redeclaration:
*
* An explicit typedef may be given for a built-in typedef
* name. A label appears in multiply gotos and as a label
* on a statement. Assume a global redeclaration is for an
* extern. Return the entry for these situations but don't
* try too hard to detect errors. If actual errors are not
* caught here, the C compiler will find them.
*/
if (tok_id == TypeDefName && ((*symp)->tok_id == C_Integer ||
(*symp)->tok_id == TypeDefName))
return *symp;
if (id_type == Label && (*symp)->id_type == Label)
return *symp;
if ((*symp)->nest_lvl == 1)
return *symp;
return NULL; /* illegal redeclarations */
}
symp = &((*symp)->next);
}
/*
* No entry exists for the symbol, create one, fill in its fields, and add
* it to the table.
*/
if ((sym = sym_free) == NULL)
sym = NewStruct(sym_entry);
else
sym_free = sym_free->next;
sym->tok_id = tok_id;
sym->image = image;
sym->id_type = id_type;
sym->nest_lvl = nest_lvl;
sym->ref_cnt = 1;
sym->il_indx = -1;
sym->may_mod = 0;
if (id_type == Label)
sym->u.lbl_num = lbl_num++;
sym->next = *symp;
*symp = sym;
return sym; /* success */
}
/*
* lbl - make sure the label is in the symbol table and return a node
* referencing the symbol table entry.
*/
struct node *lbl(t)
struct token *t;
{
struct sym_entry *sym;
struct node *n;
sym = sym_add(Identifier, t->image, Label, 2);
if (sym == NULL)
errt2(t, "conflicting definitions for ", t->image);
n = var_node(t);
if (n->u[0].sym != sym)
errt2(t, "conflicting definitions for ", t->image);
return n;
}
/*
* push_cntxt - push a level of declaration context (this may or may not
* be level of declaration nesting).
*/
novalue push_cntxt(lvl_incr)
int lvl_incr;
{
struct lvl_entry *entry;
if ((entry = lvl_entry_free) == NULL)
entry = NewStruct(lvl_entry);
else
lvl_entry_free = lvl_entry_free->next;
entry->nest_lvl = dcl_stk->nest_lvl + lvl_incr;
entry->kind_dcl = OtherDcl;
entry->parms_done = 0;
entry->tended = NULL;
entry->next = dcl_stk;
dcl_stk = entry;
}
/*
* pop_cntxt - end a level of declaration context
*/
novalue pop_cntxt()
{
int hash_val;
int old_lvl;
int new_lvl;
register struct sym_entry *sym;
struct lvl_entry *entry;
/*
* Move the top entry of the stack to the free list.
*/
old_lvl = dcl_stk->nest_lvl;
entry = dcl_stk;
dcl_stk = dcl_stk->next;
entry->next = lvl_entry_free;
lvl_entry_free = entry;
/*
* If this pop reduced the declaration nesting level, remove obsolete
* entries from the symbol table.
*/
new_lvl = dcl_stk->nest_lvl;
if (old_lvl > new_lvl) {
for (hash_val = 0; hash_val < HashSize; ++ hash_val) {
for (sym = sym_tbl[hash_val]; sym != NULL &&
sym->nest_lvl > new_lvl; sym = sym_tbl[hash_val]) {
sym_tbl[hash_val] = sym->next;
free_sym(sym);
}
}
unuse(tend_lst, old_lvl);
}
}
/*
* unuse - mark tended slots in at the given level of declarations nesting
* as being no longer in use, and leave the slots available for reuse
* for declarations that occur in pararallel compound statements.
*/
novalue unuse(t_lst, lvl)
struct init_tend *t_lst;
int lvl;
{
while (t_lst != NULL) {
if (t_lst->nest_lvl >= lvl)
t_lst->in_use = 0;
t_lst = t_lst->next;
}
}
/*
* free_sym - remove a reference to a symbol table entry and free storage
* related to it if no references remain.
*/
novalue free_sym(sym)
struct sym_entry *sym;
{
if (--sym->ref_cnt <= 0) {
switch (sym->id_type) {
case TndDesc:
case TndStr:
case TndBlk:
free_tree(sym->u.tnd_var.init); /* initializer expression */
}
sym->next = sym_free;
sym_free = sym;
}
}
/*
* alloc_tnd - allocated a slot in a tended array for a variable and return
* its index.
*/
int alloc_tnd(typ, init, lvl)
int typ;
struct node *init;
int lvl;
{
register struct init_tend *tnd;
if (lvl > 2) {
/*
* This declaration occurs in an inner compound statement. There
* may be slots created for parallel compound statement, but were
* freed and can be reused here.
*/
tnd = tend_lst;
while (tnd != NULL && (tnd->in_use || tnd->init_typ != typ))
tnd = tnd->next;
if (tnd != NULL) {
tnd->in_use = 1;
tnd->nest_lvl = lvl;
return tnd->t_indx;
}
}
/*
* Allocate a new tended slot, compute its index in the array, and
* set initialization and other information.
*/
if ((tnd = init_tend_free) == NULL)
tnd = NewStruct(init_tend);
else
init_tend_free = init_tend_free->next;
if (tend_lst == NULL)
tnd->t_indx = 0;
else
tnd->t_indx = tend_lst->t_indx + 1;
tnd->init_typ = typ;
/*
* The initalization from the declaration will only be used to
* set up the tended location if the declaration is in the outermost
* "block". Otherwise a generic initialization will be done during
* the set up and the one from the declaration will be put off until
* the block is entered.
*/
if (lvl == 2)
tnd->init = init;
else
tnd->init = NULL;
tnd->in_use = 1;
tnd->nest_lvl = lvl;
tnd->next = tend_lst;
tend_lst = tnd;
return tnd->t_indx;
}
/*
* free_tend - put the list of tended descriptors on the free list.
*/
novalue free_tend()
{
register struct init_tend *tnd;
if (tend_lst == NULL)
return;
for (tnd = tend_lst; ; tnd = tnd->next) {
if (tnd->next == NULL) {
tnd->next = init_tend_free;
init_tend_free = tend_lst;
tend_lst = NULL;
return;
}
}
}
/*
* dst_alloc - the conversion of a parameter is encountered during
* parsing; make sure a place is allocated to act as the destination.
*/
novalue dst_alloc(cnv_typ, var)
struct node *cnv_typ;
struct node *var;
{
struct sym_entry *sym;
if (var->nd_id == SymNd) {
sym = var->u[0].sym;
if (sym->id_type & DrfPrm) {
switch (cnv_typ->tok->tok_id) {
case C_Integer:
sym->u.param_info.non_tend |= PrmInt;
break;
case C_Double:
sym->u.param_info.non_tend |= PrmDbl;
break;
}
}
}
}
/*
* strt_def - the start of an operation definition is encountered during
* parsing; establish an new declaration context and make "result"
* a special identifier.
*/
novalue strt_def()
{
struct sym_entry *sym;
push_cntxt(1);
sym = sym_add(Identifier, str_rslt, RsltLoc, dcl_stk->nest_lvl);
sym->u.referenced = 0;
}
/*
* add_def - update the symbol table for the given declarator.
*/
static novalue add_def(dcltor)
struct node *dcltor;
{
struct sym_entry *sym;
struct token *t;
int tok_id;
/*
* find the identifier within the declarator.
*/
for (;;) {
switch (dcltor->nd_id) {
case BinryNd:
/* ')' or '[' */
dcltor = dcltor->u[0].child;
break;
case ConCatNd:
/* pointer direct-declarator */
dcltor = dcltor->u[1].child;
break;
case PrefxNd:
/* ( ... ) */
dcltor = dcltor->u[0].child;
break;
case PrimryNd:
t = dcltor->tok;
if (t->tok_id == Identifier || t->tok_id == TypeDefName) {
/*
* We have found the identifier, add an entry to the
* symbol table based on information in the declaration
* context.
*/
if (dcl_stk->kind_dcl == IsTypedef)
tok_id = TypeDefName;
else
tok_id = Identifier;
sym = sym_add(tok_id, t->image, OtherDcl, dcl_stk->nest_lvl);
if (sym == NULL)
errt2(t, "redefinition of ", t->image);
}
return;
default:
return;
}
}
}
/*
* id_def - a declarator has been parsed. Determine what to do with it
* based on information put in the declaration context while parsing
* the "storage class type qualifier list".
*/
novalue id_def(dcltor, init)
struct node *dcltor;
struct node *init;
{
struct node *chld0, *chld1;
struct sym_entry *sym;
if (dcl_stk->parms_done)
pop_cntxt();
/*
* Look in the declaration context (the top of the declaration stack)
* to see if this is a tended declaration.
*/
switch (dcl_stk->kind_dcl) {
case TndDesc:
case TndStr:
case TndBlk:
/*
* Tended variables are either simple identifers or pointers to
* simple identifers.
*/
chld0 = dcltor->u[0].child;
chld1 = dcltor->u[1].child;
if (chld1->nd_id != PrimryNd || (chld1->tok->tok_id != Identifier &&
chld1->tok->tok_id != TypeDefName))
errt1(chld1->tok, "unsupported tended declaration");
if (dcl_stk->kind_dcl == TndDesc) {
/*
* Declared as full tended descriptor - must not be a pointer.
*/
if (chld0 != NULL)
errt1(chld1->tok, "unsupported tended declaration");
}
else {
/*
* Must be a tended pointer.
*/
if (chld0 == NULL || chld0->nd_id != PrimryNd)
errt1(chld1->tok, "unsupported tended declaration");
}
/*
* This is a legal tended declaration, make a symbol table entry
* for it and allocated a tended slot. Add the symbol table
* entry to the list of tended variables in this context.
*/
sym = sym_add(Identifier, chld1->tok->image, dcl_stk->kind_dcl,
dcl_stk->nest_lvl);
if (sym == NULL)
errt2(chld1->tok, "redefinition of ", chld1->tok->image);
sym->u.tnd_var.blk_name = dcl_stk->blk_name;
sym->u.tnd_var.init = init;
sym->t_indx = alloc_tnd(dcl_stk->kind_dcl, init, dcl_stk->nest_lvl);
sym->u.tnd_var.next = dcl_stk->tended;
dcl_stk->tended = sym;
++sym->ref_cnt;
return;
default:
add_def(dcltor); /* ordinary declaration */
}
}
/*
* func_def - a function header has been parsed. Add the identifer for
* the function to the symbol table.
*/
novalue func_def(head)
struct node *head;
{
/*
* If this is really a function header, the current declaration
* context indicates that a parameter list has been completed.
* Parameter lists at other than at nesting level 2 are part of
* nested declaration information and do not show up here. The
* function parameters must remain in the symbol table, so the
* context is just updated, not popped.
*/
if (!dcl_stk->parms_done)
yyerror("invalid declaration");
dcl_stk->parms_done = 0;
if (dcl_stk->next->kind_dcl == IsTypedef)
yyerror("a typedef may not be a function definition");
add_def(head->u[1].child);
}
/*
* s_prm_def - add symbol table entries for a parameter to an operation.
* Undereferenced and/or dereferenced versions of the parameter may be
* specified.
*/
novalue s_prm_def(u_ident, d_ident)
struct token *u_ident;
struct token *d_ident;
{
int param_num;
if (params == NULL)
param_num = 0;
else
param_num = params->u.param_info.param_num + 1;
if (u_ident != NULL)
add_s_prm(u_ident, param_num, RtParm);
if (d_ident != NULL)
add_s_prm(d_ident, param_num, DrfPrm);
}
/*
* add_s_prm - add a symbol table entry for either a dereferenced or
* undereferenced version of a parameter. Put it on the current
* list of parameters.
*/
static novalue add_s_prm(ident, param_num, flags)
struct token *ident;
int param_num;
int flags;
{
struct sym_entry *sym;
sym = sym_add(Identifier, ident->image, flags, dcl_stk->nest_lvl);
if (sym == NULL)
errt2(ident, "redefinition of ", ident->image);
sym->u.param_info.param_num = param_num;
sym->u.param_info.non_tend = 0;
sym->u.param_info.cur_loc = PrmTend;
sym->u.param_info.next = params;
sym->il_indx = il_indx++;
params = sym;
++sym->ref_cnt;
}
/*
* var_args - a variable length parameter list for an operation is parsed.
*/
novalue var_args(ident)
struct token *ident;
{
struct sym_entry *sym;
/*
* The last parameter processed represents the variable part of the list;
* update the symbol table entry. It may be dereferenced or undereferenced
* but not both.
*/
sym = params->u.param_info.next;
if (sym != NULL && sym->u.param_info.param_num ==
params->u.param_info.param_num)
errt1(ident, "only one version of variable parameter list allowed");
params->id_type |= VarPrm;
/*
* Add the identifier for the length of the variable part of the list
* to the symbol table.
*/
sym = sym_add(Identifier, ident->image, VArgLen, dcl_stk->nest_lvl);
if (sym == NULL)
errt2(ident, "redefinition of ", ident->image);
sym->il_indx = il_indx++;
v_len = sym;
++v_len->ref_cnt;
}
/*
* d_lst_typ - the end of a "declare {...}" is encountered. Go through a
* declaration list adding storage class, type qualifier, declarator
* and initializer information to the symbol table entry for each
* identifer. Add the entry onto the list associated with the "declare"
*/
novalue d_lst_typ(dcls)
struct node *dcls;
{
if (dcls == NULL)
return;
for ( ; dcls != NULL && dcls->nd_id == LstNd; dcls = dcls->u[0].child)
dcl_typ(dcls->u[1].child);
dcl_typ(dcls);
}
/*
* dcl_typ - go through the declarators of a declaration adding the storage
* class, type qualifier, declarator, and initializer information to the
* symbol table entry of each identifier. Add the entry onto the list
* associated with the current "declare {...}".
*/
static novalue dcl_typ(dcl)
struct node *dcl;
{
struct node *tqual;
struct node *dcltors;
if (dcl == NULL)
return;
tqual = dcl->u[0].child;
for (dcltors = dcl->u[1].child; dcltors->nd_id == CommaNd;
dcltors = dcltors->u[0].child)
dcltor_typ(dcltors->u[1].child, tqual);
dcltor_typ(dcltors, tqual);
}
/*
* dcltor_typ- find the identifier in the [initialized] declarator and add
* the storage class, type qualifer, declarator, and initialization
* information to its symbol table entry. Add the entry onto the list
* associated with the current "declare {...}".
*/
static novalue dcltor_typ(dcltor, tqual)
struct node *dcltor;
struct node *tqual;
{
struct sym_entry *sym;
struct node *part_dcltor;
struct node *init = NULL;
struct token *t;
if (dcltor->nd_id == BinryNd && dcltor->tok->tok_id == '=') {
init = dcltor->u[1].child;
dcltor = dcltor->u[0].child;
}
part_dcltor = dcltor;
for (;;) {
switch (part_dcltor->nd_id) {
case BinryNd:
/* ')' or '[' */
part_dcltor = part_dcltor->u[0].child;
break;
case ConCatNd:
/* pointer direct-declarator */
part_dcltor = part_dcltor->u[1].child;
break;
case PrefxNd:
/* ( ... ) */
part_dcltor = part_dcltor->u[0].child;
break;
case PrimryNd:
t = part_dcltor->tok;
if (t->tok_id == Identifier || t->tok_id == TypeDefName) {
/*
* The identifier has been found, update its symbol table
* entry.
*/
sym = sym_lkup(t->image);
sym->u.declare_var.tqual = tqual;
sym->u.declare_var.dcltor = dcltor;
sym->u.declare_var.init = init;
++sym->ref_cnt;
sym->u.declare_var.next = decl_lst;
decl_lst = sym;
}
return;
default:
return;
}
}
}
/*
* tnd_char - indicate in the current declaration context that a tended
* character (pointer?) declaration has been found.
*/
novalue tnd_char()
{
dcl_stk->kind_dcl = TndStr;
dcl_stk->blk_name = NULL;
}
/*
* tnd_strct - indicate in the current declaration context that a tended
* struct declaration has been found and indicate the struct type.
*/
novalue tnd_strct(t)
struct token *t;
{
char *strct_nm;
char **s;
strct_nm = t->image;
free_t(t);
/*
* Make sure it is a struct type that may be tended.
*/
if (strct_nm == descrip) {
dcl_stk->kind_dcl = TndDesc;
dcl_stk->blk_name = NULL;
return;
}
for (s = blk_lst; *s != NULL; ++s) {
if (*s == strct_nm) {
dcl_stk->kind_dcl = TndBlk;
dcl_stk->blk_name = strct_nm;
return;
}
}
yyerror("unsupported tended type");
}
/*
* tnd_strct - indicate in the current declaration context that a tended
* union (pointer?) declaration has been found.
*/
novalue tnd_union(t)
struct token *t;
{
/*
* Only union block pointers may be tended.
*/
if (t->image != block)
yyerror("unsupported tended type");
free_t(t);
dcl_stk->kind_dcl = TndBlk;
dcl_stk->blk_name = NULL;
}