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

📄 declaration.c

📁 一个编译器修改的例子
💻 C
字号:
#include "declaration.h"#include "error.h"#include "io.h"#include "salloc.h"#include "printlist.h"#include "statement.h"#include <string.h>List *global_declarations;int expr_offset = 0;Declaration *global_decl;Type *type;Scope *temp, *expr_temp;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));#ifdef DEBUG	printf("Token name = %s\n",token->name);	printf("Token line = %d\n",token->line_number);#endif    decl->subtype			= var_decl;    decl->token				= token;    VAR_DECL(decl).type			= 0;    return decl;}Declaration *new_record_declaration(Token *token, List *list)     /*create a new record declaration */{    Declaration *decl			= safe_malloc(sizeof(Declaration));#ifdef DEBUG	printf("Token name = %s\n",token->name);	printf("Token line = %d\n",token->line_number);#endif	decl->subtype			= record_decl;        decl->token			= token;	RECORD_DECL(decl).member_scope  = current_scope;	RECORD_DECL(decl).var_list	= list;	RECORD_DECL(decl).type = new_record_type(decl);	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:		delete_scope(RECORD_DECL(decl).member_scope);		delete_declaration_list(RECORD_DECL(decl).var_list);		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->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->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);}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;	case record_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));    }}static void generate_record_declaration(FILE *file, Declaration *decl, Bool initialize){	int i;	Declaration *declTemp;	fprintf(file,"typedef struct\n{\n");#ifdef DEBUG	printf("typedef struct\n{\n");#endif	for (i=0;i<list_size(RECORD_DECL(decl).var_list);i++) {		declTemp = ((Declaration *)list_index(RECORD_DECL(decl).var_list,i));		generate_type(file,(VAR_DECL(declTemp)).type);		fprintf(file," field_%s;\n",((Declaration *)list_index(RECORD_DECL(decl).var_list,i))->token->name);		#ifdef DEBUG		printf(" field_%s;\n",((Declaration *)list_index(RECORD_DECL(decl).var_list,i))->token->name);		#endif			}	fprintf(file,"}\nrecord_%s;\n",decl->token->name);#ifdef DEBUG	printf("}\nrecord_%s;\n",decl->token->name);#endif}static void generate_init_record(FILE *file,Declaration *decl){	int i;	Declaration *declTemp,*temp;	declTemp = decl;	for (i=0;i<list_size(RECORD_DECL(declTemp).var_list);i++)	{		temp = list_index(RECORD_DECL(declTemp).var_list,i);		if (i==0) {			fprintf(file, "{");			#ifdef DEBUG			printf("{");			#endif		}		else 		{			fprintf(file,",");			#ifdef DEBUG			printf(",");			#endif		}				if (VAR_DECL(temp).type->subtype == record_type)		{			generate_init_record(file, RECORD_TYPE(VAR_DECL(temp).type).decl);		} else {			fprintf(file, "0");			#ifdef DEBUG			printf("0");			#endif		}	}	if (i==0) {		fprintf(file, "{}");		#ifdef DEBUG		printf("{}");		#endif	}	else 	{		fprintf(file,"}");		#ifdef DEBUG		printf("}");		#endif	}}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 ");		#ifdef DEBUG		printf("extern ");		#endif				generate_type(h_out, VAR_DECL(decl).type);						fprintf(h_out, " cb_%s;\n", decl->token->name);		#ifdef DEBUG		printf(" cb_%s;\n", decl->token->name);		#endif    }		if(decl->subtype == var_decl)	{		generate_type(file, VAR_DECL(decl).type);		fprintf(file, " cb_%s", decl->token->name);		#ifdef DEBUG		printf(" cb_%s", decl->token->name);		#endif				if (initialize) 		{			if ( VAR_DECL(decl).type->subtype==record_type)			{				fprintf(file,"=");				#ifdef DEBUG				printf("=");				#endif				generate_init_record(file,RECORD_TYPE(VAR_DECL(decl).type).decl);				fprintf(file,";\n");				#ifdef DEBUG				printf(";\n"); 				#endif							}			else			{				fprintf(file, "=0;\n");				#ifdef DEBUG				printf("=0;\n");				#endif			}		}	}}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);	#ifdef DEBUG	printf(" cb_%s", decl->token->name);	#endif    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);	#ifdef DEBUG	printf("%c",i == 0 ? '(' : ',');	#endif	generate_var_declaration(file, arg, false);    }    fprintf(file, i == 0 ? "()" : ")");	#ifdef DEBUG	printf(i == 0 ? "()" : ")");	#endif}static void generate_subprog_declaration(Declaration *decl){    generate_prototype(h_out, decl);    fprintf(h_out, ";\n");	#ifdef DEBUG	printf(";\n");	#endif    if (SUBPROG_DECL(decl).body != 0)    {	generate_prototype(c_out, decl);	fprintf(c_out, "{\n");	#ifdef DEBUG	printf("{\n");	#endif	generate_statement(SUBPROG_DECL(decl).body);	if (SUBPROG_DECL(decl).return_type->subtype != void_type)	{			fprintf(c_out, "runtime_error(\"%s returns no value\");\n", decl->token->name);		#ifdef DEBUG		printf("runtime_error(\"%s returns no value\");\n", decl->token->name);		#endif	}	fprintf(c_out, "}\n");	#ifdef DEBUG	printf("}\n");	#endif    }}void generate_declaration(Declaration *decl){    switch (decl->subtype)    {	case subprog_decl:	    generate_subprog_declaration(decl);	    break;	case var_decl:	    generate_var_declaration(c_out, decl, true);	    break;				case record_decl:		generate_record_declaration(h_out,decl,true);		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 + -