📄 symtab.c
字号:
/*@A (C) 1992 Allen I. Holub */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tools/debug.h>
#include <tools/hash.h>
#include <tools/l.h>
#include <tools/compiler.h>
#include <tools/c-code.h>
#include "symtab.h" /* Symbol-table definitions. */
#include "value.h" /* Value definitions. */
#include "proto.h" /* Prototypes for all functions in this directory. */
#include "label.h" /* Labels to use for compiler-generated symbols. */
#if ( (0 ANSI(+1)) == 0 ) /* If not an ANSI compilers */
#define sprintf _sprintf /* Use ANSI-compatible version out of comp.lib */
#endif
/*----------------------------------------------------------------------*/
PRIVATE symbol *Symbol_free = NULL; /* Free-list of recycled symbols. */
PRIVATE link *Link_free = NULL; /* Free-list of recycled links. */
PRIVATE structdef *Struct_free = NULL; /* Free-list of recycled structdefs. */
#define LCHUNK 10 /* new_link() gets this many nodes at one shot.*/
static void psym P((symbol *sym_p, FILE *fp ));
static void pstruct P((structdef *sdef_p, FILE *fp ));
/*----------------------------------------------------------------------*/
PUBLIC symbol *new_symbol( name, scope )
char *name;
int scope;
{
symbol *sym_p;
if( !Symbol_free ) /* Free list is empty.*/
sym_p = (symbol *) newsym( sizeof(symbol) );
else /* Unlink node from */
{ /* the free list. */
sym_p = Symbol_free;
Symbol_free = Symbol_free->next ;
memset( sym_p, 0, sizeof(symbol) );
}
strncpy( sym_p->name, name, sizeof(sym_p->name) );
sym_p->level = scope;
return sym_p;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
PUBLIC void discard_symbol( sym )
symbol *sym;
{
/* Discard a single symbol structure and any attached links and args. Note
* that the args field is recycled for initializers, the process is
* described later on in the text (see value.c in the code), but you have to
* test for a different type here. Sorry about the forward reference.
*/
if( sym )
{
if( IS_FUNCT( sym->type ) )
discard_symbol_chain( sym->args ); /* Function arguments. */
else
discard_value( (value *)sym->args ); /* If an initializer. */
discard_link_chain( sym->type ); /* Discard type chain. */
sym->next = Symbol_free ; /* Put current symbol */
Symbol_free = sym; /* in the free list. */
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
PUBLIC void discard_symbol_chain(sym) /* Discard an entire cross-linked */
symbol *sym; /* chain of symbols. */
{
symbol *p = sym;
while( sym )
{
p = sym->next;
discard_symbol( sym );
sym = p;
}
}
/*----------------------------------------------------------------------*/
PUBLIC link *new_link( )
{
/* Return a new link. It's initialized to zeros, so it's a declarator.
* LCHUNK nodes are allocated from malloc() at one time.
*/
link *p;
int i;
if( !Link_free )
{
if( !(Link_free = (link *) malloc( sizeof(link) * LCHUNK )) )
{
yyerror("INTERNAL, new_link: Out of memory\n");
exit( 1 );
}
for( p = Link_free, i = LCHUNK; --i > 0; ++p ) /* Executes LCHUNK-1 */
p->next = p + 1; /* times. */
p->next = NULL ;
}
p = Link_free;
Link_free = Link_free->next;
memset( p, 0, sizeof(link) );
return p;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
PUBLIC void discard_link_chain( p )
link *p;
{
/* Discard all links in the chain. Nothing is removed from the structure
* table, however. There's no point in discarding the nodes one at a time
* since they're already linked together, so find the first and last nodes
* in the input chain and link the whole list directly.
*/
link *start ;
if( start = p )
{
while( p->next ) /* find last node */
p = p->next;
p->next = Link_free;
Link_free = start;
}
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PUBLIC void discard_link( p ) /* Discard a single link. */
link *p;
{
p->next = Link_free;
Link_free = p;
}
/*----------------------------------------------------------------------*/
PUBLIC structdef *new_structdef( tag ) /* Allocate a new structdef. */
char *tag;
{
structdef *sdef_p;
if( !Struct_free )
sdef_p = (structdef *) newsym( sizeof(structdef) );
else
{
sdef_p = Struct_free;
Struct_free = (structdef *)(Struct_free->fields);
memset( sdef_p, 0, sizeof(structdef) );
}
strncpy( sdef_p->tag, tag, sizeof(sdef_p->tag) );
return sdef_p;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
#ifdef STRUCTS_ARE_DISCARDED /* they aren't in the present compiler */
PUBLIC void discard_structdef( sdef_p )
structdef *sdef_p;
{
/* Discard a structdef and any attached fields, but don't discard linked
* structure definitions.
*/
if( sdef_p )
{
discard_symbol_chain( sdef_p->fields );
sdef_p->fields = (symbol *)Struct_free ;
Struct_free = sdef_p;
}
}
#endif
PUBLIC void add_declarator( sym, type )
symbol *sym;
int type;
{
/* Add a declarator link to the end of the chain, the head of which is
* pointed to by sym->type and the tail of which is pointed to by
* sym->etype. *head must be NULL when the chain is empty. Both pointers
* are modified as necessary.
*/
link *link_p;
if( type == FUNCTION && IS_ARRAY(sym->etype) )
{
yyerror("Array of functions is illegal, assuming function pointer\n");
add_declarator( sym, POINTER );
}
link_p = new_link(); /* The default class is DECLARATOR. */
link_p->DCL_TYPE = type;
if( !sym->type )
sym->type = sym->etype = link_p;
else
{
sym->etype->next = link_p;
sym->etype = link_p;
}
}
PUBLIC void spec_cpy( dst, src ) /* Copy all initialized fields in src to dst.*/
link *dst, *src;
{
if( src->NOUN ) dst->NOUN = src->NOUN ;
if( src->SCLASS ) dst->SCLASS = src->SCLASS ;
if( src->LONG ) dst->LONG = src->LONG ;
if( src->UNSIGNED ) dst->UNSIGNED = src->UNSIGNED ;
if( src->STATIC ) dst->STATIC = src->STATIC ;
if( src->EXTERN ) dst->EXTERN = src->EXTERN ;
if( src->tdef ) dst->tdef = src->tdef ;
if( src->SCLASS == CONSTANT || src->NOUN == STRUCTURE)
memcpy( &dst->VALUE, &src->VALUE, sizeof(src->VALUE) );
}
PUBLIC link *clone_type( tchain, endp )
link *tchain; /* input: Type chain to duplicate. */
link **endp; /* output: Pointer to last node in cloned chain. */
{
/* Manufacture a clone of the type chain in the input symbol. Return a
* pointer to the cloned chain, NULL if there were no declarators to clone.
* The tdef bit in the copy is always cleared.
*/
link *last, *head = NULL;
for(; tchain ; tchain = tchain->next )
{
if( !head ) /* 1st node in chain. */
head = last = new_link();
else /* Subsequent node. */
{
last->next = new_link();
last = last->next;
}
memcpy( last, tchain, sizeof(*last) );
last->next = NULL;
last->tdef = 0;
}
*endp = last;
return head;
}
/*----------------------------------------------------------------------*/
PUBLIC int the_same_type( p1, p2, relax )
link *p1, *p2;
int relax;
{
/* Return 1 if the types match, 0 if they don't. Ignore the storage class.
* If "relax" is true and the array declarator is the first link in the
* chain, then a pointer is considered equivalent to an array.
*/
if( relax && IS_PTR_TYPE(p1) && IS_PTR_TYPE(p2) )
{
p1 = p1->next;
p2 = p2->next;
}
for(; p1 && p2 ; p1 = p1->next, p2 = p2->next)
{
if( p1->class != p2->class )
return 0;
if( p1->class == DECLARATOR )
{
if( (p1->DCL_TYPE != p2->DCL_TYPE) ||
(p1->DCL_TYPE==ARRAY && (p1->NUM_ELE != p2->NUM_ELE)) )
return 0;
}
else /* this is done last */
{
if( (p1->NOUN == p2->NOUN ) && (p1->LONG == p2->LONG ) &&
(p1->UNSIGNED == p2->UNSIGNED ) )
{
return ( p1->NOUN==STRUCTURE ) ? p1->V_STRUCT == p2->V_STRUCT
: 1 ;
}
return 0;
}
}
yyerror("INTERNAL the_same_type: Unknown link class\n");
return 0;
}
/*----------------------------------------------------------------------*/
PUBLIC int get_sizeof( p )
link *p;
{
/* Return the size in bytes of an object of the the type pointed to by p.
* Functions are considered to be pointer sized because that's how they're
* represented internally.
*/
int size;
if( p->class == DECLARATOR )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -