📄 decl.c
字号:
discard_symbol( sym );
sym = first;
}
else /* Node is in middle of the list. */
{
prev->next = sym->next;
discard_symbol( sym );
sym = prev->next;
}
}
return first;
}
void print_bss_dcl( sym ) /* Print a declaration to the bss segment. */
symbol *sym;
{
if( sym->etype->SCLASS != FIXED )
yyerror( "Illegal storage class for %s", sym->name );
else
{
if( sym->etype->STATIC && sym->etype->EXTERN )
yyerror("%s: Bad storage class\n", sym->name );
var_dcl( yybss, sym->etype->OCLASS, sym, ";\n" );
}
}
/*----------------------------------------------------------------------*/
PUBLIC void var_dcl( ofunct, c_code_sclass, sym, terminator )
void (* ofunct) P((char *,...)); /* output function (yybss or yydata). */
int c_code_sclass; /* C-code storage class of symbol. */
symbol *sym; /* Symbol itself. */
char *terminator; /* Print this string at end of the declaration. */
{
/* Kick out a variable declaration for the current symbol. */
char suffix[32];
char *type = "" ;
int size = 1 ;
link *p = sym->type;
char *storage_class = (c_code_sclass == PUB) ? "public" :
(c_code_sclass == PRI) ? "private" :
(c_code_sclass == EXT) ? "external" : "common" ;
*suffix = '\0';
if( IS_FUNCT(p) )
{
yyerror("INTERNAL, var_dcl: object not a variable\n");
exit( 1 );
}
if( IS_ARRAY(p) )
{
for(; IS_ARRAY(p) ; p = p->next )
size *= p->NUM_ELE ;
sprintf( suffix, "[%d]", size );
}
if( IS_STRUCT(p) )
{
( *ofunct )( "\nALIGN(lword)\n" );
sprintf( suffix, "[%d]", size * p->V_STRUCT->size );
}
if( IS_POINTER(p) )
type = PTYPE;
else /* Must be a specifier. */
switch( p->NOUN )
{
case CHAR: type = CTYPE; break;
case INT: type = p->LONG ? LTYPE : ITYPE; break;
case STRUCTURE: type = STYPE; break;
}
( *ofunct )( "%s\t%s\t%s%s%s", storage_class, type,
sym->rname, suffix, terminator );
}
int illegal_struct_def( cur_struct, fields )
structdef *cur_struct;
symbol *fields;
{
/* Return true if any of the fields are defined recursively or if a function
* definition (as compared to a function pointer) is found as a field.
*/
for(; fields; fields = fields->next )
{
if( IS_FUNCT(fields->type) )
{
yyerror("struct/union member may not be a function");
return 1;
}
if( IS_STRUCT(fields->type) &&
!strcmp( fields->type->V_STRUCT->tag, cur_struct->tag))
{
yyerror("Recursive struct/union definition\n");
return 1;
}
}
return 0;
}
/*----------------------------------------------------------------------*/
int figure_struct_offsets( p, is_struct )
symbol *p; /* Chain of symbols for fields. */
int is_struct; /* 0 if a union. */
{
/* Figure the field offsets and return the total structure size. Assume
* that the first element of the structure is aligned on a worst-case
* boundary. The returned size is always an even multiple of the worst-case
* alignment. The offset to each field is put into the "level" field of the
* associated symbol.
*/
int align_size, obj_size;
int offset = 0;
for( ; p ; p = p->next )
{
if( !is_struct ) /* It's a union. */
{
offset = max( offset, get_sizeof( p->type ) );
p->level = 0;
}
else
{
obj_size = get_sizeof ( p->type );
align_size = get_alignment ( p->type );
while( offset % align_size )
++offset;
p->level = offset;
offset += obj_size ;
}
}
/* Return the structure size: the current offset rounded up to the */
/* worst-case alignment boundary. You need to waste space here in case */
/* this is an array of structures. */
while( offset % ALIGN_WORST )
++offset ;
return offset;
}
/*----------------------------------------------------------------------*/
int get_alignment( p )
link *p;
{
/* Returns the alignment--the number by which the base address of the object
* must be an even multiple. This number is the same one that is returned by
* get_sizeof(), except for structures which are worst-case aligned, and
* arrays, which are aligned according to the type of the first element.
*/
int size;
if( !p )
{
yyerror("INTERNAL, get_alignment: NULL pointer\n");
exit( 1 );
}
if( IS_ARRAY( p ) ) return get_alignment( p->next );
if( IS_STRUCT( p ) ) return ALIGN_WORST;
if( size = get_sizeof( p ) ) return size;
yyerror("INTERNAL, get_alignment: Object aligned on zero boundary\n");
exit( 1 );
BCC( return 0; ) /* Keep the compiler happy */
}
PUBLIC void do_enum( sym, val )
symbol *sym;
int val;
{
if( conv_sym_to_int_const( sym, val ) )
addsym( Symbol_tab, sym );
else
{
yyerror( "%s: redefinition", sym->name );
discard_symbol( sym );
}
}
/*---------------------------------------------------------------------*/
PUBLIC int conv_sym_to_int_const( sym, val )
symbol *sym;
int val;
{
/* Turn an empty symbol into an integer constant by adding a type chain
* and initializing the v_int field to val. Any existing type chain is
* destroyed. If a type chain is already in place, return 0 and do
* nothing, otherwise return 1. This function processes enum's.
*/
link *lp;
if( sym->type )
return 0;
lp = new_link();
lp->class = SPECIFIER;
lp->NOUN = INT;
lp->SCLASS = CONSTANT;
lp->V_INT = val ;
sym->type = lp;
*sym->rname = '\0';
return 1;
}
void fix_types_and_discard_syms( sym )
symbol *sym;
{
/* Patch up subroutine arguments to match formal declarations.
*
* Look up each symbol in the list. If it's in the table at the correct
* level, replace the type field with the type for the symbol in the list,
* then discard the redundant symbol structure. All symbols in the input
* list are discarded after they're processed.
*
* Type checking and automatic promotions are done here, too, as follows:
* chars are converted to int.
* arrays are converted to pointers.
* structures are not permitted.
*
* All new objects are converted to autos.
*/
symbol *existing, *s;
while( sym )
{
if( !( existing = (symbol *)findsym( Symbol_tab,sym->name) )
|| sym->level != existing->level )
{
yyerror("%s not in argument list\n", sym->name );
exit(1);
}
else if( !sym->type || !sym->etype )
{
yyerror("INTERNAL, fix_types: Missing type specification\n");
exit(1);
}
else if( IS_STRUCT(sym->type) )
{
yyerror("Structure passing not supported, use a pointer\n");
exit(1);
}
else if( !IS_CHAR(sym->type) )
{
/* The existing symbol is of the default int type, don't redefine
* chars because all chars are promoted to int as part of the call,
* so can be represented as an int inside the subroutine itself.
*/
if( IS_ARRAY(sym->type) ) /* Make it a pointer to the */
sym->type->DCL_TYPE = POINTER; /* first element. */
sym->etype->SCLASS = AUTO; /* Make it an automatic var. */
discard_link_chain(existing->type); /* Replace existing type */
existing->type = sym->type; /* chain with the current one.*/
existing->etype = sym->etype;
sym->type = sym->etype = NULL; /* Must be NULL for discard_- */
} /* symbol() call, below. */
s = sym->next;
discard_symbol( sym );
sym = s;
}
}
/*----------------------------------------------------------------------*/
int figure_param_offsets( sym )
symbol *sym;
{
/* Traverse the chain of parameters, figuring the offsets and initializing
* the real name (in sym->rname) accordingly. Note that the name chain is
* assembled in reverse order, which is what you want here because the
* first argument will have been pushed first, and so will have the largest
* offset. The stack is 32 bits wide, so every legal type of object will
* require only one stack element. This would not be the case were floats
* or structure-passing supported. This also takes care of any alignment
* difficulties.
*
* Return the number of 32-bit stack words required for the parameters.
*/
int offset = 8; /* First parameter is always at BP(fp+8): */
/* 4 for old fp, 4 for return address. */
for(; sym ; sym = sym->next )
{
if( IS_STRUCT(sym->type) )
{
yyerror("Structure passing not supported\n");
continue;
}
sprintf( sym->rname, "fp+%d", offset );
offset += SWIDTH ;
}
/* Return the offset in stack elements, rounded up if necessary. */
return( (offset / SWIDTH) + (offset % SWIDTH != 0) );
}
/*----------------------------------------------------------------------*/
void print_offset_comment( sym, label )
symbol *sym;
char *label;
{
/* Print a comment listing all the local variables. */
for(; sym ; sym = sym->next )
yycode( "\t/* %16s = %-16s [%s] */\n", sym->rname, sym->name, label );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -