⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decl.c

📁 一个c语言写做的编译器的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	    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 + -