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

📄 symtab.c

📁 C编译器,在VC6.0环境下开发
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"SymTab.h"
#include	"GenCode.h"
#include	"Error.h"
#include	"Debug.h"
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<malloc.h>
#include	<memory.h>
#include	<assert.h>
#include	<math.h>

#define		COMPOUND_STACK_SIZE	64

const	char	_COMPOUND_SYMTAB_NAME[] = "%d_703027";
const	char	_FUNCTION_SYMTAB_NAME[] = "51911080";
const	char	_UNUSED_SYM_NAME[] = "5yong_%d";
const	char	_GOTO_LABEL_SYMTAB_NAME[] = "041249";

// for compound stack
typedef	struct	_comp_element_
{
	// symtab pointer
	symbol *p_symtab;
	// this layer's start offset
	// in bytes
	int		offset;
} comp_element;

static	comp_element sg_compound_stack[COMPOUND_STACK_SIZE];
static	int		sg_compound_stack_sp = -1;

// used for alloc space in stack for local value
static	int		sg_local_offset = 0;
static	int		sg_local_offset_top = 0;

#define		CHECK_COMPOUND_STACK_OVERFLOW	assert(sg_compound_stack_sp < COMPOUND_STACK_SIZE);
#define		CHECK_COMPOUND_STACK_BOTTOM		\
				if ( sg_compound_stack_sp <= -1 )	\
				{									\
					yyerror("compound statement not match");\
					user_exit(1);							\
				}


#define		ALIGN_OFFSET(x)		if ((x) % 2)	\
									x++;
#define		JUST_OFFSET_TOP		if ( sg_local_offset_top	\
									< sg_local_offset )		\
									sg_local_offset_top	=	\
										sg_local_offset;

// record the globe vlaue
// only globe value no function, no ...
symbol	*sg_function_symtab = NULL;

// goto label symtab
symbol	*sg_goto_label_symtab = NULL;

static char	*get_compound_symtab_name()
{
	static char buf[NAME_LEN];

	sprintf(buf, _COMPOUND_SYMTAB_NAME, sg_compound_stack_sp);
	return	buf;
}

symbol	*new_symbol()
{
	symbol *tmp;
	
	tmp = (symbol *)malloc( sizeof(symbol) );
	if ( !tmp )
	{
		yyerror("Out of memory in new_symbol()");
		user_exit(1);
	}
	
	// init the symbol, set to zero
	// can think init is zero include point & other
	memset( tmp, 0, sizeof( symbol ));

	return	tmp;
}

void	del_symbol(symbol *p)
{
	assert( p );

	free( p );
}

// delete a symtab all
void	remove_symtab(symbol *head)
{
	// use ->lchild & ->rchild to remove child ,
	// becuse ->next only used for search

	if ( !head )	//eg . remove_symtab(NULL)
		return;

	if ( head->lchild )
		remove_symtab(head->lchild);

	if ( head->rchild )
		remove_symtab(head->rchild);
	
	del_symbol(head);
}

// delete a symtab except function args
void	remove_symtab_except_args(symbol *head)
{
	// use ->lchild & ->rchild to remove child ,
	// becuse ->next only used for search

	if ( !head )
		return;

	if ( head->lchild )
		remove_symtab_except_args(head->lchild);

	if ( head->rchild )
		remove_symtab_except_args(head->rchild);
	
	if ( !IS_ARGUMENT(head) )
		del_symbol(head);
	else
		// is args
		head->rchild = head->lchild = NULL;
}

// delete a function symtab include function args
void	remove_function_symtab_include_args(symbol *func)
{
	// use ->lchild & ->rchild to remove child ,
	// and remove ->args
	symbol *tmp;

	if ( !func )
		return;

	if ( !IS_FUNCTION(func) )
	{
		yyerror("not function in remove_function_symtab_include_args()");
		user_exit(1);
	}

	if ( IS_FUNC_DECL(func) && func->IS_EXTERN )
		gen_extern_func(func);

	if ( func->lchild )
		remove_function_symtab_include_args(func->lchild);

	if ( func->rchild )
		remove_function_symtab_include_args(func->rchild);
	
	// delete the args
	tmp = func->args;

	while ( tmp )
	{
		symbol *p;
		
		if ( !IS_ARGUMENT(tmp) )
		{
			yyerror("not args in remove_function_symtab_include_args()");
			user_exit(1);
		}
		p = tmp;
		tmp = tmp->next;
		del_symbol(p);
	}
	
	// delete function symbol
	del_symbol(func);
}

// remove the linked symbol use ->next
// eg. not use declaration list
void	remove_symbol_list(symbol *p)
{
	while ( p )
	{
		symbol *tmp = p;

		p = p->next;
		del_symbol(tmp);
	}
}

symbol	*create_symtab(const char *name)
{
	symbol	*tmp;

	tmp = new_symbol();
	tmp->is_symtab = 1;
	strncpy( tmp->name, name, NAME_LEN );
	
	return	tmp;
}

// return NULL means not found
symbol	*search_symbol_in_symtab(symbol *tab, char *name)
{
	if ( !IS_SYMTAB(tab) )
	{
		yyerror("not symtab in search_symbol_in_symtab()");
		user_exit(1);
	}

	while( tab )
	{
		int	i;

		i = strcmp(name, tab->name);
		if ( i < 0 )
		// name < tab->name
			tab = tab->lchild;
		else if ( i > 0 )
		// name > tab->name
			tab = tab->rchild;
		else
		// found
			break;
	}

	// because tab is NULL
	// so only return tab means return NULL;
	return	tab;
}

// return NULL means not found
symbol	*search_symbol_to_top(char *name)
{
	symbol	*tmp;
	int		level = sg_compound_stack_sp;

	for ( ; level >= 0; level-- )
	{
		tmp = sg_compound_stack[level].p_symtab;
		
		if (tmp = search_symbol_in_symtab(tmp, name))
		// found
			goto lab_found;
	}

	// search in function symtab
	tmp = search_symbol_in_symtab(sg_function_symtab, name);

lab_found:
	return	tmp;
}

int		add_symbol_to_symtab(symbol *tab, symbol *p)
{
	if (!tab || !p)
		return	1;

	if ( !IS_SYMTAB(tab) )
	{
		yyerror("not a symtab in add_symbol_to_symtab()");
		user_exit(1);
	}

	while(1)
	{
		int	i;

		i = strcmp(p->name, tab->name);
		if ( i < 0 )
		// p->name < tab->name
		{
			if ( tab->lchild )
				tab = tab->lchild;
			else
			{
				tab->lchild = p;
				break;
			}
		}
		else if ( i > 0 )
		// p->name > tab->name
		{
			if ( tab->rchild )
				tab = tab->rchild;
			else
			{
				tab->rchild = p;
				break;
			}
		}
		else
		// equal
		{
			parse_error("Duplicate identifier.", p->name);
			user_exit(1);
		}
	}
	return	0;
}

int		add_symbol_to_current_symtab(symbol *p)
{
	// if p is function symbol, then don't add to current symtab
	// because in C language every function is globe function
	// it must be add to function symtab
	if ( IS_FUNCTION(p) )
	// just return successful flag
		return	0;

	// we must record the added symbol size ,
	// and add to sg_local_offset, so access the word ptr [bp - offset]
	// except some symbol like typedef or function definition
	// so, call a method
	if  ( IS_LOCAL_VAR(p) )
	{
		if ( sg_compound_stack_sp )
		// means symbol p is a var and current layer is not globe
		{
			sg_local_offset += get_symbol_size(p);
			// the offset was bp -... so is '-'
			p->offset = - sg_local_offset;

			set_local_or_args_rname(p);

			ALIGN_OFFSET(sg_local_offset)

			JUST_OFFSET_TOP
		}
		else
		// globe val, assign ->rname only
		{
			sprintf(p->rname, _GLOBE_VAL_NAME, p->name);
		}
	}
			
	return	add_symbol_to_symtab(sg_compound_stack[sg_compound_stack_sp].p_symtab, p);
}

int		add_symbol_list_to_current_symtab(symbol *p)
{
	while ( p )
	{
		if ( add_symbol_to_current_symtab(p) )
			return	1;
		p = p->next;
	}
	return	0;
}

// link two symbol list to one list
// link p2 at ->next of p1's last symbol
symbol	*link_symbol_list(symbol *p1, symbol *p2)
{
	symbol	*tmp = p1;

	if (!p1 || !p2)
		return	p1;

	while ( tmp->next )
		tmp = tmp->next;

	tmp->next = p2;
	return	p1;
}

// change p1
void	union_specifier_symbol(symbol *p1, symbol *p2)
{
	if ( !p1 || !p2 )
		return;

	if ( p1->NOUN == SPEC_UNKNOW )
		p1->NOUN = p2->NOUN;

	if ( p1->SCLASS == SPEC_UNKNOW )
		p1->SCLASS = p2->SCLASS;

	if ( !p1->IS_LONG )
		p1->IS_LONG = p2->IS_LONG;

	if ( !p1->IS_UNSIGNED )
		p1->IS_UNSIGNED = p2->IS_UNSIGNED;

	if ( !p1->IS_STATIC )
		p1->IS_STATIC = p2->IS_STATIC;

	if ( !p1->IS_EXTERN )
		p1->IS_EXTERN = p2->IS_EXTERN;
}	

// check var declarator
void	check_var_declarator(symbol *decl)
{
	assert(decl);

	if (decl->NOUN == SPEC_VOID )
	{
		yyerror("illegal use of type 'void'");
		user_exit(1);
	}
}

// union the specifier to declarator
// at same time check declarator , not be void
void	unoin_specifier_to_declarator(symbol *spec, symbol *decl)
{
	if ( !spec || !decl )
		return;

	decl->NOUN = spec->NOUN;
	decl->SCLASS = spec->SCLASS;
	decl->IS_LONG = spec->IS_LONG;
	decl->IS_UNSIGNED = spec->IS_UNSIGNED;
	decl->IS_STATIC = spec->IS_STATIC;
	decl->IS_EXTERN = spec->IS_EXTERN;
}

// union the specifier to declarator list
void	unoin_specifier_to_declarator_list(symbol *spec, symbol *decl_list)
{
	if ( !spec )
		return;

	while ( decl_list )
	{
		unoin_specifier_to_declarator(spec, decl_list);
		decl_list = decl_list->next;
	}
}

// new symbol from a typedef symbol
symbol	*new_symbol_from_typedef(symbol *def_sym)
{
	symbol *tmp;

	if ( !def_sym || !IS_TYPEDEF(def_sym) )
		return	NULL;
	
	tmp = new_symbol();

	tmp->NOUN = def_sym->NOUN;
	tmp->SCLASS = SPEC_UNKNOW;
	tmp->IS_LONG = def_sym->IS_LONG;
	tmp->IS_UNSIGNED = def_sym->IS_UNSIGNED;
	tmp->IS_STATIC = def_sym->IS_STATIC;
	tmp->IS_EXTERN = def_sym->IS_EXTERN;

	// for array typedef
	tmp->is_array = def_sym->is_array;
	tmp->num_ele = def_sym->num_ele;

	return	tmp;
}

symbol	*find_symtab_typedef(char *name)
{
	symbol	*tmp;

	tmp = search_symbol_to_top(name);
	if ( tmp && IS_TYPEDEF(tmp) )
		return	tmp;

	return	NULL;
}

// create compound symtab , and push it
symbol	*new_compound_symtab()
{
	sg_compound_stack_sp++;

	CHECK_COMPOUND_STACK_OVERFLOW

	sg_compound_stack[sg_compound_stack_sp].p_symtab =
			create_symtab(get_compound_symtab_name());

	sg_compound_stack[sg_compound_stack_sp].offset = 
			sg_local_offset;

	return	sg_compound_stack[sg_compound_stack_sp].p_symtab;
}

// pop a compound symtab, and destory it
void	del_compound_symtab()
{
	sg_local_offset = sg_compound_stack[sg_compound_stack_sp].offset;

	// conside the function declaration use this method
	// so only delete the symbol not args,
	// to common compound statement, it not different between
	// this method and remove_symtab, but it important to 
	// function compound statement
	CHECK_COMPOUND_STACK_BOTTOM

	remove_symtab_except_args(sg_compound_stack[sg_compound_stack_sp--].p_symtab);
}

// check args type in function call in term of number of args
int		check_args_type_in_function_call(symbol *p1,symbol *p2)
{
	// for check for function call
	assert(p1);
	assert(p2);

	while ( p1 && p2 )
	{
/*		if ( p1->NOUN != p2->NOUN )
			return	1;
		if ( p1->SCLASS != p2->SCLASS )
			return	1;
		if ( p1->IS_LONG != p2->IS_LONG )
			return	1;
		if ( p1->IS_UNSIGNED != p2->IS_UNSIGNED )
			return	1;
*/ // for call type can be cast in sometimes
/*		if ( IS_ARRAY( p1 ) )
		{
			if ( !IS_ARRAY(p2) || IS_ARRAY_HAS_INDEX(p2) )
				return	1;
		}
		// p1 is not a array
		else if ( IS_ARRAY(p2) && !IS_ARRAY_HAS_INDEX(p2) )
			return	1;
*/
		// can tell the array is or not has index , because the index flags has been 
		// clear , so.... check it by programer
		p1 = p1->next;
		p2 = p2->next;
	}

	if (  p1 != p2 )
		return	1;

	return	0;
}

// check args type
int		check_args_type(symbol *p1,symbol *p2)
{
	while ( p1 && p2 )
	{
		assert( IS_ARGUMENT(p1) );
		assert( IS_ARGUMENT(p2) );

		if ( p1->NOUN != p2->NOUN )
			return	1;
		if ( p1->SCLASS != p2->SCLASS )
			return	1;
		if ( p1->IS_LONG != p2->IS_LONG )
			return	1;
		if ( p1->IS_UNSIGNED != p2->IS_UNSIGNED )
			return	1;
		if ( p1->is_array != p2->is_array )
			return	1;
		// for function , array argument only a pointer, so dont check the num_ele
//		if ( IS_ARRAY(p1) && (p1->num_ele != p2->num_ele) )
//			return	1;

		p1 = p1->next;
		p2 = p2->next;
	}

	if (  p1 != p2 )
		return	1;

	return	0;
}

// check the function parameter and return type
int		check_func_args_type(symbol *func,symbol *decl)
{
	// check function itself attribute
	if ( !IS_FUNCTION(func) || !IS_FUNCTION(decl) )
		return	1;
	if ( func->NOUN != decl->NOUN )
		return	1;
	if ( func->SCLASS != decl->SCLASS )
		return	1;
	if ( func->IS_LONG != decl->IS_LONG )
		return	1;
	if ( func->IS_UNSIGNED != decl->IS_UNSIGNED )
		return	1;
	
	return	check_args_type(func->args,	decl->args);
}

// add function definition to function tab
// if declaration if exist, check parameter type, 
// and overwrite parameter's name
// actual delete the declaration list
// and add itself to function symtab
// the function could be changed
// so return new symbol pointer
symbol	*add_function_def_to_functab(symbol *func)
{
	symbol	*decl;

	if ( !IS_FUNCTION(func) )
	{
		yyerror("not function in add_function_def_to_functab()");
		user_exit(1);
	}
	if ( decl = search_symbol_in_symtab(sg_function_symtab, func->name) )
	{
		// found the same name function
		// see if the pre declaration
		if ( !IS_FUNC_DECL(decl) )
		{
			// another function has define as the same name
			// so, error........
			parse_error(func->name," already has a body");
			user_exit(1);
		}
		// only declaration
		// chech parameter type
		if ( check_func_args_type(func, decl) )
		{
			// type mismatch
			yyerror("function declaration has the different parameter type or return value type with definition");
			user_exit(1);
		}
		// ok, 	change decl to definition
		// delete decl 's parameter list
		remove_symbol_list(decl->args);
		// link func->args to decl->args
		// later see it enough???
		decl->args = func->args;
		decl->IS_STATIC = func->IS_STATIC;
		decl->IS_EXTERN = func->IS_EXTERN;
		// delete fun symbol
		del_symbol(func);
		// clear decl flags, it ture definition, heihei....
		decl->is_declaration = 0;

		return	decl;

⌨️ 快捷键说明

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