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

📄 symtab.c

📁 C编译器,在VC6.0环境下开发
💻 C
📖 第 1 页 / 共 2 页
字号:
	}
	// no function decl
	// so only add def to function definition
	add_symbol_to_symtab(sg_function_symtab, func);
	return	func;
}

// only declaration
// add or only check parameter type
// not overwrite parameter's type
void	add_function_decl_to_functab(symbol *decl)
{
	symbol	*func;

	if ( !IS_FUNCTION(decl) )
	{
		yyerror("not function in add_function_decl_to_functab()");
		user_exit(1);
	}
	if ( func = search_symbol_in_symtab(sg_function_symtab, decl->name) )
	{
		// first check type....
		if ( check_func_args_type(func, decl) )
		{
			// mismatch
			yyerror("function definition or declaration mismatch");
			user_exit(1);
		}
		// match
		// however is definition or declaration
		// the decl need not be added
		// so return
		return;
	}
	// no pre decl or definition
	// so add it
	add_symbol_to_symtab(sg_function_symtab, decl);
}

// check function return value
// array can't be return value
void	check_function_retval(symbol *func)
{
	assert( IS_FUNCTION(func) );

	if ( IS_ARRAY(func) )
	{
		yyerror("function returns array");
		user_exit(1);
	}

	if ( func->NOUN == SPEC_LABEL )
	{
		yyerror("function returns label");
		user_exit(1);
	}
}

// get symbol 's size
int		get_symbol_size(symbol *p)
{
	// ingore the is_long
	// in bytes
	int		sym_size;

	assert( p );
	
	switch(p->NOUN)
	{
	case	SPEC_CHAR:
		sym_size = 1;
		break;
	case	SPEC_FLOAT:	// just as int
	case	SPEC_DOUBLE:// just as int
	case	SPEC_INT:
		sym_size = 2;
		break;
	default:
		yyerror("can't get symbol's size");
		user_exit(1);
	}

	if ( IS_ARRAY(p) )
		sym_size *= p->num_ele;

	return	sym_size;
}

// set local value or args rname
void	set_local_or_args_rname(symbol *p)
{
	assert(p);

	sprintf(p->rname, get_asm_attri(p), abs(p->offset));
}

// get local value or args asm attrib "word ptr [bp-%d]" or "byte ptr [bp-%d]"
// or "word ptr [bp+%d]" or "byte ptr [bp+%d]"
char	*get_asm_attri(symbol *p)
{
	static	char	buf[NAME_LEN];

	// ingore the is_long
	// in bytes
	assert( p );
//	can used in gen code in array[],so...
//	assert( !IS_ARRAY(p) );

	switch(p->NOUN)
	{
	case	SPEC_CHAR:
		strcpy(buf, "byte ptr [bp");
		break;
	case	SPEC_FLOAT:	// just as int
	case	SPEC_DOUBLE:// just as int
	case	SPEC_INT:
		strcpy(buf, "word ptr [bp");
		break;
	default:
		yyerror("can't get asm attrib");
		user_exit(1);
	}
	
	if (p->offset < 0)
	// local value
		strcat(buf, "-%d]");
	else if (p->offset > 0)
		strcat(buf, "+%d]");
	else
	{
		yyerror("symbol->offset is 0, not local value or args, error!");
		user_exit(1);
	}
	return	buf;
}

// assign parameters rname
void	assign_parameters_rname(symbol *args_list)
{
/*	symbol	*tmp;
	// for ip,bp[old] in stack, so offset start value 4
	// right args pus to stack first
	int		offset = 4;

	assert( args_list );

	// calculate the total offset
	tmp = args_list;
	while (tmp)
	{
		// must conside string , string can't be args
		assert( IS_ARGUMENT(tmp) );

		tmp->offset = offset;

		if ( !IS_ARRAY(tmp) )
		{
			offset += get_symbol_size(tmp);
			set_local_or_args_rname(tmp);
		}
		else
		{
			//	note : array push address of the array, so...
			// offset += 2, and it argument rname is word ptr [bp+...]
			offset += 2;
			sprintf(tmp->rname, "word ptr [bp+%d]", tmp->offset);
		}

		ALIGN_OFFSET(offset)

		tmp = tmp->next;
	}
*/
	// left args push to stack first
	symbol	*tmp;
	int		offset = 0;

	assert( args_list );

	// calculate the total offset
	tmp = args_list;
	while (tmp)
	{
		// must conside string , string can't be args
		assert( IS_ARGUMENT(tmp) );

		if ( !IS_ARRAY(tmp) )
			offset += get_symbol_size(tmp);
		else
		{
			//	note : array push address of the array, so...
			// offset += 2, and it argument rname is word ptr [bp+...]
			offset += 2;
		}
		ALIGN_OFFSET(offset)

		tmp->offset = offset;

		tmp = tmp->next;
	}

	offset += 4;

	tmp = args_list;
	while (tmp)
	{
		// must consider string , string can't be args
		assert( IS_ARGUMENT(tmp) );

		tmp->offset = offset - tmp->offset;     


		if ( !IS_ARRAY(tmp) )
			set_local_or_args_rname(tmp);			
		else
			sprintf(tmp->rname, "word ptr [bp+%d]", tmp->offset);

		tmp = tmp->next;
	}
}

// assign symbol a unused name
void	assign_symbol_unusedname(symbol *p)
{
	static	int	unuse_count = 0;

	assert(p);

	sprintf(p->name, _UNUSED_SYM_NAME, unuse_count++);
}

// set function 's offset to sub sp, offset
void	set_func_offset(symbol *func)
{
	assert( func );
	if ( !IS_FUNCTION(func) )
	{
		yyerror("not function in set_func_offset()");
		user_exit(1);
	}
	func->offset = sg_local_offset_top;
	// reset sg_local_offset_top
	sg_local_offset_top = 0;
}

// change cl value if necessary
void	cast_cl_type(symbol *c1, symbol *c2)
{
	symbol	*d, *s;

	assert(c1);
	assert(c2);
	assert( IS_CL(c1) && IS_CL(c2) );

	if ( c1->NOUN == c2->NOUN )
		return;

	if ( c1->NOUN > c2->NOUN )
	{
		s = c1;
		d = c2;
	}
	else
	{
		s = c2;
		d = c1;
	}

	switch(s->NOUN)
	{
	// can't be char
	case	SPEC_INT:
		d->V_I = (int)d->V_C;
		break;
	case	SPEC_FLOAT:
		switch(d->NOUN)
		{
		case	SPEC_CHAR:
			d->V_F = (float)d->V_C;
			break;
		case	SPEC_INT:
			d->V_F = (float)d->V_I;
			break;
		}
		break;
	case	SPEC_DOUBLE:
		switch(d->NOUN)
		{
		case	SPEC_CHAR:
			d->V_LF = (double)d->V_C;
			break;
		case	SPEC_INT:
			d->V_LF = (double)d->V_I;
			break;
		case	SPEC_FLOAT:
			d->V_LF = (double)d->V_F;
			break;
		}
		break;
	default:
		yyerror("can not do cast cl type");
		user_exit(1);
	}
	d->NOUN = s->NOUN;
}

// get symbol value as int
int		get_sym_value(symbol *c)
{
	int		value;

	assert(c);


	// ingore double && float to int
	switch( c->NOUN )
	{
	case	SPEC_CHAR:
		value = c->V_C;
		break;
	case	SPEC_INT:
		value = c->V_I;
		break;
	case	SPEC_FLOAT:
		value = (int)c->V_F;
		break;
	case	SPEC_DOUBLE:
		value = (int)c->V_LF;
		break;
	default:
		yyerror("can't get value in get_sym_value()");
		user_exit(1);
	}
	return	value;
}

// clone a symbol with symbol
symbol	*clone_symbol(symbol *p)
{
	symbol	*tmp;

	assert(p);
	tmp = new_symbol();
	memcpy(tmp, p, sizeof(symbol));

	// keep ->args for function
	tmp->next = NULL;
	tmp->lchild = NULL;
	tmp->rchild = NULL;

	return	tmp;
}

// calcu function argument size
int		get_function_args_size(symbol *func)
{
	symbol *tmp;
	int		f_size = 0;

	assert( func );
	assert( IS_FUNCTION(func) );

	tmp = func->args;

	while ( tmp )
	{
		if ( !IS_ARRAY(tmp) ) 
			f_size += get_symbol_size(tmp);
		else
			// for array send it address
			f_size += 2;

		tmp = tmp->next;
	}
	return	f_size;
}

// create goto label symtab 
void	create_goto_label_symtab()
{
	assert( !sg_goto_label_symtab );

	sg_goto_label_symtab = create_symtab(_GOTO_LABEL_SYMTAB_NAME);
}

static	void	check_label_define(symbol *lb)
{
	if ( !lb )
		return;

	assert( lb->NOUN == SPEC_LABEL );

	if ( IS_LAB_DECL(lb) )
	{
		parse_error(lb->name, " label was undefined");
		user_exit(1);
	}

	if ( lb->lchild )
		check_label_define(lb->lchild);

	if ( lb->rchild )
		check_label_define(lb->rchild);
}

// destory goto label symtab
void	destory_goto_label_symtab()
{
	assert( sg_goto_label_symtab );

	// check the label that not define
	check_label_define(sg_goto_label_symtab->lchild);
	check_label_define(sg_goto_label_symtab->rchild);

	remove_symtab(sg_goto_label_symtab);
	sg_goto_label_symtab = NULL;
}

// found the goto label in goto label symtab
symbol	*search_goto_label(char *name)
{
	assert( sg_goto_label_symtab );

	return search_symbol_in_symtab(sg_goto_label_symtab, name);
}

// add goto label to goto label symtab
void	add_goto_label(symbol *lb)
{
	assert( sg_goto_label_symtab );

	add_symbol_to_symtab(sg_goto_label_symtab, lb);
}


// operation for init_compound_stack
// create golbe symtab
static	void	init_compound_stack()
{
	sg_compound_stack_sp = -1;

	// new globe symtab
	new_compound_symtab();
}

// destory golbe symbol
static	void	destory_compound_stack()
{
	if ( sg_compound_stack_sp )
	{
		yyerror("compound statement exist except globe values, in destory_compound_stack()");
		user_exit(1);
	}
	// delete globe symtab
	del_compound_symtab();
}

static	void	create_function_symtab()
{
	sg_function_symtab = create_symtab(_FUNCTION_SYMTAB_NAME);
}

static	void	destory_function_symtab()
{
	remove_function_symtab_include_args(sg_function_symtab->lchild);
	remove_function_symtab_include_args(sg_function_symtab->rchild);
	del_symbol(sg_function_symtab);
	sg_function_symtab = NULL;
}

void	InitSymTab()
{
	sg_local_offset = 0;
	sg_local_offset_top = 0;
	sg_goto_label_symtab = NULL;

	// create globe symtab
	init_compound_stack();

	// init function symtab
	create_function_symtab();
}

void	DestorySymTab()
{
	//Testing
	dump_current_symtab();
	dump_function_symtab();

	// destory function symtab
	destory_function_symtab();
	
	// destory compound stack
	destory_compound_stack();
}

//  dump symbol for debug
static char	*noun_info(unsigned noun)
{
	switch( noun )
	{
	case	SPEC_UNKNOW:
		return	"SPEC_UNKNOW";

	case	SPEC_VOID:
		return	"SPEC_VOID";

	case	SPEC_CHAR:
		return	"SPEC_CHAR";

	case	SPEC_INT:
		return	"SPEC_INT";

	case	SPEC_FLOAT:
		return	"SPEC_FLOAT";

	case	SPEC_DOUBLE:
		return	"SPEC_DOUBLE";

	case	SPEC_LABEL:
		return	"SPEC_LABEL";
	}

	return	"not define noun";
}

static char	*sclass_info(unsigned sclass)
{
	switch( sclass )
	{
	case	SPEC_UNKNOW:
		return	"SPEC_UNKNOW";

	case	SPEC_AUTO:
		return	"SPEC_AUTO";

	case	SPEC_REGISTER:
		return	"SPEC_REGISTER";

	case	SPEC_CONSTANT:
		return	"SPEC_CONSTANT";

	case	SPEC_TYPEDEF:
		return	"SPEC_TYPEDEF";
	}

	return	"not define sclass";
}

void	dump_symbol(symbol *p)
{
	char	buf[20];

	if ( !p )
		return;

	StrToDebug( p->name, "\n=== DUMP SYMBOL :", " START....");
	StrToDebug( p->rname, "\n ->rname :", NULL);
	StrToDebug( itoa(p->is_symtab, buf, 10), "\n ->is_symtab :", NULL);
	StrToDebug( itoa(p->is_function, buf, 10), "\n ->is_function :", NULL);
	StrToDebug( itoa(p->is_declaration, buf, 10), "\n ->is_declaration :", NULL);
	StrToDebug( itoa(p->is_array, buf, 10), "\n ->is_array :", NULL);
	StrToDebug( itoa(p->is_argument, buf, 10), "\n ->is_argument :", NULL);
	StrToDebug( itoa(p->is_assign, buf, 10), "\n ->is_assign :", NULL);
	StrToDebug( itoa(p->is_cl, buf, 10), "\n ->is_cl :", NULL);
	StrToDebug( itoa(p->is_rvalue, buf, 10), "\n ->is_rvalue :", NULL);
	StrToDebug( itoa(p->is_pushed, buf, 10), "\n ->is_pushed :", NULL);
	StrToDebug( itoa(p->num_ele, buf, 10), "\n ->num_ele :", NULL);
	StrToDebug( itoa(p->offset, buf, 10), "\n ->offset :", NULL);

	StrToDebug( noun_info(p->NOUN), "\n ->NOUN :", NULL );
	StrToDebug( sclass_info(p->SCLASS), "\n ->SCLASS :", NULL );

	StrToDebug( itoa(p->IS_LONG, buf, 10), "\n ->IS_LONG :", NULL);
	StrToDebug( itoa(p->IS_UNSIGNED, buf, 10), "\n ->IS_UNSIGNED :", NULL);
	StrToDebug( itoa(p->IS_STATIC, buf, 10), "\n ->IS_STATIC :", NULL);
	StrToDebug( itoa(p->IS_EXTERN, buf, 10), "\n ->IS_EXTERN :", NULL);

// show const in later
//	V_C	
//	V_UC
//	V_I	
//	V_UI
//	V_F	
//	V_LF
//	V_STR
}

void	dump_function(symbol *func)
{
	symbol *tmp;

	assert( IS_FUNCTION(func) );

	StrToDebug( "\n FUNCTION : -> ", NULL, NULL);
	dump_symbol(func);

	StrToDebug( "\n arguments : -----", NULL, NULL);
	tmp = func->args;
	while ( tmp )
	{
		dump_symbol(tmp);
		tmp = tmp->next;
	}
	StrToDebug( "\n ----- arguments end", NULL, NULL);
	StrToDebug( "\n FUNCTION end <-", NULL, NULL);
}

static void	dump_symtab( symbol *head, void (*p_dump_func)(symbol *) )
{
	if ( !head )	//eg . dump_symtab(NULL)
		return;

	if ( head->lchild )
		dump_symtab(head->lchild, p_dump_func);

	(*p_dump_func)(head);

	if ( head->rchild )
		dump_symtab(head->rchild, p_dump_func);
}
	
void	dump_current_symtab()
{
	dump_symtab(sg_compound_stack[sg_compound_stack_sp].p_symtab, dump_symbol);
}

void	dump_function_symtab()
{
	dump_symtab(sg_function_symtab->lchild, dump_function);
	dump_symtab(sg_function_symtab->rchild, dump_function);
}


⌨️ 快捷键说明

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