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

📄 declaration.c

📁 一个编译器修改的例子
💻 C
字号:
#include "declaration.h"#include "error.h"#include "io.h"#include "salloc.h"#include <string.h>/* Variable to temporarily hold a Declaration pointer for subtype check. Used * in the ASSERT_DECL_SUBTYPE macro. */Declaration *__decl;List *global_declarations;Declaration *new_subprogram_declaration(Token *token){    Declaration *decl			 = safe_malloc(sizeof(Declaration));    decl->subtype			 = subprog_decl;    decl->token				 = token;    SUBPROG_DECL(decl).body		 = 0;    SUBPROG_DECL(decl).formal_args_scope = 0;    SUBPROG_DECL(decl).formal_args	 = 0;    SUBPROG_DECL(decl).type		 = 0;    SUBPROG_DECL(decl).return_type	 = 0;    SUBPROG_DECL(decl).redeclaration	 = 0;    SUBPROG_DECL(decl).has_been_defined	 = false;    return decl;}Declaration *new_var_declaration(Token *token){    Declaration *decl			= safe_malloc(sizeof(Declaration));    decl->subtype			= var_decl;    decl->token				= token;    VAR_DECL(decl).type			= 0;    return decl;}/*add : create a new record declaration */Declaration *new_record_declaration(Token *token){    Declaration *decl			= safe_malloc(sizeof(Declaration));    decl->subtype			= record_decl;    decl->token				= token;    return decl;}void delete_declaration(Declaration *decl){    if (decl != 0)    {	switch (decl->subtype)	{	    case subprog_decl:		delete_statement(SUBPROG_DECL(decl).body);		delete_scope(SUBPROG_DECL(decl).formal_args_scope);		delete_declaration_list(SUBPROG_DECL(decl).formal_args);		delete_type(SUBPROG_DECL(decl).type);		delete_type(SUBPROG_DECL(decl).return_type);		break;	    case var_decl:		delete_type(VAR_DECL(decl).type);		break;	    case record_decl:  /*add*/		delete_scope(RECORD_DECL(decl).formal_var_scope);                delete_declaration_list(RECORD_DECL(decl).formal_var);		break;	}	delete_token(decl->token);	free(decl);    }}void delete_declaration_list(List *declarations){    if (declarations != 0)    {	unsigned i;	for (i = 0; i < list_size(declarations); i ++)	    delete_declaration(list_index(declarations, i));	delete_list(declarations);    }}/* Redeclaring is only allowed for subprograms, and only if the types * are identical. This function checks whether that is the case for * two declarations. */static void match_subprogram_prototypes(Declaration *d1, Declaration *d2){    unsigned i;    List     *formals1, *formals2;    Type     *t1, *t2;    if (d1->subtype != subprog_decl)    {	error(d2->token, "%s redeclares non-subprogram", d2->token->name);	return;    }    formals1 = SUBPROG_DECL(d1).formal_args;    formals2 = SUBPROG_DECL(d2).formal_args;    if (formals1 != 0 && formals2 != 0)    {	if (list_size(formals1) != list_size(formals2))	    error(d2->token, "%s redeclared with different number of arguments",		  d2->token->name);	else	    for (i = 0; i < list_size(formals1); i ++)	    {		Declaration *var1 = list_index(formals1, i);		Declaration *var2 = list_index(formals2, i);		t1 = VAR_DECL(var1).type;		t2 = VAR_DECL(var2).type;		if (!types_compatible(t1, t2)			|| t1->call_by_ref != t2->call_by_ref)		    error(var2->token,		    	"argument %u redeclared with different type", i + 1);	    }    }    t1 = SUBPROG_DECL(d1).return_type;    t2 = SUBPROG_DECL(d2).return_type;    if (!types_compatible(t1, t2))	error(d2->token, "different return type for redeclared subprogram %s",	      d2->token->name);}static void type_check_main_function(Declaration *decl){    List	*formals;    Declaration *arg;    Type	*type;    if (strcmp(decl->token->name, "main") == 0 &&	(formals = SUBPROG_DECL(decl).formal_args) != 0 &&	(list_size(formals) != 1 ||	((arg = list_index(formals, 0)) != 0 &&	(type = VAR_DECL(arg).type) != 0 &&	(type->call_by_ref ||	type->subtype != array_type ||	((type = ARRAY_TYPE(type).base_type) != 0 &&	(type->subtype != array_type ||	((type = ARRAY_TYPE(type).base_type) != 0 &&	type->subtype != char_type))))) ||	SUBPROG_DECL(decl).return_type == 0 ||	SUBPROG_DECL(decl).return_type->subtype != int_type))	error(decl->token, "prototype of global function main should be: "	      "\"function main(argv : array of string) : int;\"");}static void type_check_subprogram_declaration(Declaration *decl){    Declaration *redecl = SUBPROG_DECL(decl).redeclaration;    if (redecl != 0)    {	match_subprogram_prototypes(redecl, decl);	if (redecl->subtype == subprog_decl && SUBPROG_DECL(decl).body != 0)	{	    if (SUBPROG_DECL(redecl).has_been_defined)		error(decl->token, "multiple definition of %s",		      decl->token->name);	    else		SUBPROG_DECL(redecl).has_been_defined = true;	}    }    type_check_statement(SUBPROG_DECL(decl).body, decl);    type_check_main_function(decl);}/*add : check if there is a recursive definition in record declaration */void type_check_record_declaration(Declaration *decl){ unsigned i; Declaration *var; for(i=0;i<list_size(RECORD_DECL(decl).formal_var);i++)  {   var=list_index(RECORD_DECL(decl).formal_var,i);   if(VAR_DECL(var).type->subtype==record_type)     {       if(decl->token->name==RECORD_TYPE(VAR_DECL(var).type).decl->token->name)         {           error(decl->token,"%s struct has a recursive definition",decl->token->name);           break;         }     }  }}void type_check_declaration(Declaration *decl){    if (decl == 0)	return;    switch (decl->subtype)    {	case subprog_decl:	    type_check_subprogram_declaration(decl);	    break;	case var_decl:	    break;      /*add : check recursion in record declaration */	case record_decl:            type_check_record_declaration(decl);	    break;    }}void type_check_declaration_list(List *declarations){    if (declarations != 0)    {	unsigned i;	for (i = 0; i < list_size(declarations); i ++)	    type_check_declaration(list_index(declarations, i));    }}/*add : initialize a new record declaration and create C code */void initialize_record_decl(FILE *file, Declaration *decl){   Declaration *var;   unsigned i;   fprintf(file,"{");   for(i=0;i<list_size(RECORD_DECL(decl).formal_var);i++)      {       var=list_index(RECORD_DECL(decl).formal_var,i);       switch (VAR_DECL(var).type->subtype)         {           case bool_type:                fprintf(file,"false");                if(i!=list_size(RECORD_DECL(decl).formal_var)-1) fprintf(file,",");                break;           case char_type:                fprintf(file,"0");                if(i!=list_size(RECORD_DECL(decl).formal_var)-1) fprintf(file,",");                break;           case int_type:                fprintf(file,"0");                if(i!=list_size(RECORD_DECL(decl).formal_var)-1) fprintf(file,",");                break;           case real_type:                fprintf(file,"0.0");                if(i!=list_size(RECORD_DECL(decl).formal_var)-1) fprintf(file,",");                break;           case array_type:                fprintf(file,"NULL");                if(i!=list_size(RECORD_DECL(decl).formal_var)-1) fprintf(file,",");                break;           case record_type:                                initialize_record_decl(file,RECORD_TYPE(VAR_DECL(var).type).decl);                if(i!=list_size(RECORD_DECL(decl).formal_var)-1) fprintf(file,",");                break;           default:                error(decl->token,"this declaration %s is unknown", decl->token->name);                break;         }      }   fprintf(file,"}");}/* add : adding initialision of record declaration*/static void generate_var_declaration(FILE *file, Declaration *decl,				     Bool initialize){    /* RAFB: bug fix.  We must generate an extern declaration for	 * each global variable in case it is used before it is	 * declared.	 */    if (lookup_in_this_scope(global_scope, decl->token->name) == decl)    {        fprintf(h_out,  "extern ");        generate_type(h_out, VAR_DECL(decl).type);        fprintf(h_out, " cb_%s;\n", decl->token->name);    }        generate_type(file, VAR_DECL(decl).type);        fprintf(file, " cb_%s", decl->token->name);        if(initialize)           {             switch (VAR_DECL(decl).type->subtype)                {                   case bool_type:                       fprintf(file,"=false");                       break;                   case char_type:                       fprintf(file,"=0");                       break;                   case int_type:                       fprintf(file,"=0");                       break;                   case real_type:                       fprintf(file,"=0.0");                       break;                   case array_type:                       fprintf(file,"=NULL");                       break;                   case record_type:                                       fprintf(file,"=");                       initialize_record_decl(file,RECORD_TYPE(VAR_DECL(decl).type).decl);                       break;                   default:                       error(decl->token,"this declaration %s is unknown", decl->token->name);                       break;               }          }}static void generate_prototype(FILE *file, Declaration *decl){    unsigned i;    generate_type(file, SUBPROG_DECL(decl).return_type);    fprintf(file, " cb_%s", decl->token->name);    for (i = 0; i < list_size(SUBPROG_DECL(decl).formal_args); i ++)    {	Declaration *arg = list_index(SUBPROG_DECL(decl).formal_args, i);	putc(i == 0 ? '(' : ',', file);	generate_var_declaration(file, arg, false);    }    fprintf(file, i == 0 ? "(void)" : ")");}/*add : create C code in h_out file for a record declaration */static void generate_record_declaration(FILE *file, Declaration *decl,Bool initialize){ unsigned i; Declaration *var; fprintf(file,"typedef struct"); fprintf(file," {\n"); for(i=0;i<list_size(RECORD_DECL(decl).formal_var);i++)  {   var=list_index(RECORD_DECL(decl).formal_var,i);   generate_var_declaration(file, var, initialize);   fprintf(file,";\n");  } fprintf(file,"}\n"); fprintf(file,"record_%s;\n",decl->token->name);}static void generate_subprog_declaration(Declaration *decl){    generate_prototype(h_out, decl);    fprintf(h_out, ";\n");    if (SUBPROG_DECL(decl).body != 0)    {	generate_prototype(c_out, decl);	fprintf(c_out, "{\n");	generate_statement(SUBPROG_DECL(decl).body);	if (SUBPROG_DECL(decl).return_type->subtype != void_type)	    fprintf(c_out, "runtime_error(\"%s returns no value\");", decl->token->name);	fprintf(c_out, "}\n");    }}void generate_declaration(Declaration *decl){    switch (decl->subtype)    {	case subprog_decl:	    generate_subprog_declaration(decl);	    break;	case var_decl:          if(VAR_DECL(decl).type->subtype!=record_type)      	    generate_var_declaration(c_out, decl, true);          else             generate_var_declaration(c_out, decl, true);	  fprintf(c_out, ";\n");	  break;      case record_decl:          generate_record_declaration(h_out,decl,false);          break;    }}void generate_declaration_list(List *declarations){    unsigned i;    for (i = 0; i < list_size(declarations); i ++)	generate_declaration(list_index(declarations, i));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -