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

📄 symbol.c

📁 用C++编写的一个编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <string.h>
#include <stdio.h>
#include "symbol.h"
#include "utility.h"
#include "genasm.h"

struct _node *symtab[SYMTABSIZE];
struct _node *typetab[TYPETABSIZE];
struct _sym *current_func = NULL;

typedef struct _defines{
	List add;
	List dup;
}LocalDefines;

static LocalDefines *current_block;

static List block_list;
List const_list; //const string, or like that
List data_list;//data 
List bss_list;//data?
List extern_list; //extern var and all function decl
static List label_list;

struct _datatype *newType(
	char 		*name, 
	int		 	bt,
	struct _expnode	*array_vol
)
{
	Type *type;

	type = dmalloc(sizeof(Type), true);
	type->tname = name;
	type->basic_type= bt;
	if(array_vol)
	{
		type->array_vol= UNKNOWN;//set the default value for easy analysis
		if(array_vol->exptype == exp_const)
		{
			bt = array_vol->datatype->basic_type;
			if(bt == bt_pointer)
				generror(ERR_TYPE_CONFLICT, "in dimension size");
			else if(bt == bt_double)
				type->array_vol = (unsigned)array_vol->val.f;
			else 
			{//ignore the sign bit
				if(array_vol->val.i<=0)
					generror(ERR_EXPECT_POSITIVE, "in dimension size");
				else 
					type->array_vol=array_vol->val.i;
			}
		}
		else if(array_vol->exptype != exp_void)//only void are temp allowed ?????
			generror(ERR_EXPECT_CONST, "in dimension size");
	}
	else type->array_vol=0;
	type->memlist = NULL;
	type->arglist = NULL;
	switch(bt)
	{
	case bt_void:
	case bt_ellipsis:
		type->size = 0;
		break;
	case bt_char:
	case bt_unsignedchar:
		type->size =1;
		break;
	case bt_short:
	case bt_unsignedshort:
		type->size = 2;
		break;
	case bt_int:
	case bt_unsignedint:
	case bt_long:
	case bt_unsignedlong:
	case bt_float:
	case bt_enum:
	case bt_func://need to convert to bt_funcptr later
	case bt_funcptr:
		type->size = 4;
		break;
	case bt_double:
		type->size = 8;
		break;
	case bt_struct:
	case bt_union:
	case bt_typedef:	
		type->size = UNKNOWN;
		break;
	case bt_pointer:
		type->size = array_vol?UNKNOWN:4;
		break;
	}
	type->subtype = NULL;
	return type;
}

int check_basictype(
	int prefix,
	int origin 
)//lots of bug, just for simple use 
{
	if(prefix == bt_long)
	{
		if(origin == bt_int)
			return bt_long;
		else if(origin == bt_unsignedint)
			return bt_unsignedlong;
		else if(origin == bt_double)
			return bt_double;
	}
	else if(prefix == bt_short)
	{
		if(origin == bt_int)
			return bt_short;
		else if(origin == bt_unsignedint)
			return bt_unsignedshort;
	}
	else if(prefix == bt_unsignedint)
	{
		if(origin == bt_long)
			return bt_unsignedlong;
		else if(origin == bt_short)
			return bt_unsignedshort;
		else if(origin == bt_char)
			return bt_unsignedchar;
		else if(origin == bt_int)
			return bt_unsignedint;
	}
	else if(prefix == bt_int)//signed
	{
		if(origin != bt_unsignedchar ||origin !=bt_unsignedint 
			||origin != bt_unsignedshort ||origin!=bt_unsignedlong)
			return origin;
	}
	generror(ERR_WRONG_BASIC_TYPE, NULL);
	return origin;
}
//when and only when in function argument list declaration, the name can be null
struct _sym *newSymbol(
	char		*name, 
	int			sc,
	Type		*datatype
)
{
	Symbol *sym = dmalloc(sizeof(Symbol), true);
	//to ensure every symbol have a name
	sym->name = name?name:"parameter";
	sym->storage_class =sc;
	sym->datatype = datatype;
	sym->init = NULL;
	sym->next = NULL;
	sym->refcount = 0;
	//all member in value have the same size
	sym->value.linkname = NULL;
	return sym;
}
struct _sym *newEnumerator(
	char		*name,
	struct _expnode * val)
{
	Symbol *sym = newSymbol(name, sc_member, newType(NULL, bt_long, NULL));
	HashNode *hashnode;
	sym->const_flag =1;
	if(val == NULL)
		sym->value.i = UNKNOWN;
	else if(val->exptype == exp_const)
	{
		sym->value.i = val->val.i;
	}
	else 
	{
		sym->value.i = UNKNOWN;
		generror(ERR_EXPECT_CONST, name);
	}
	//add to symbol table;
	hashnode =add_node(symtab, SYMTABSIZE, name, sym);
	if(hashnode)
	{
		generror(ERR_REDEF_VAR, name);
	}
	return sym;
}
struct _supertype *newSuperType(
	int sc,
	struct _datatype *type
)
{
	struct _supertype *one = dmalloc(sizeof(SuperType), true);
	one->sc = sc;
	one->datatype = type;
	return one;
}
struct _node **member_declare(
	int bt,
	struct _stmtnode *declaration_list,
	int *size	//out
)
{
	SuperType *spec; 
	Symbol  *dec; //dec means declarator

	HashNode **memlist=dmalloc(sizeof(HashNode*)*MEMTABSIZE, false);
	
	*size=0;

	memset(memlist, 0, sizeof(HashNode*)*MEMTABSIZE);

	for(;declaration_list;declaration_list=declaration_list->next)
	{
		spec = declaration_list->spec;
		dec = declaration_list->declist;

		for(;dec;dec=dec->next)
		{
			dec->storage_class = sc_member;
			dec->datatype = compoundType(dec->datatype, spec->datatype);
			checkTypeSize(dec->datatype);
			if(add_node(memlist, MEMTABSIZE, dec->name, dec))
			{
				generror(ERR_REDEF_MEMBER, dec->name);
			}
			if(bt == bt_struct)
			{
				*size = align_add(*size, dec->datatype->size);
				dec->value.offset=*size-dec->datatype->size;
			}
			else 
			{
				*size = MAX(*size, dec->datatype->size);
				dec->value.offset =0;
			}
		}
	}
	if(*size&3)
		*size = (*size&~3)+4;
	return memlist;
}
struct _datatype *new_sameType(
	struct _datatype *type,
	bool	auto_flag
)
{
	Type *same = NULL, *p, *q;
	for(;type;type=type->subtype)
	{
		q=dmalloc(sizeof(Type), auto_flag);
		memcpy(q, type, sizeof(Type));
		if(!same)same = p =q;
		else p =p->subtype = q;
	}	
	return same;
}


struct _datatype *compoundType(
	struct _datatype *origin,
	struct _datatype *extra
)
{
	Type *p=origin;
	if(!origin)
		return extra;
	for(p=origin;p->subtype;p=p->subtype);
	//for function pointer convert
	if(extra->basic_type == bt_func)
	{
		if(p->basic_type == bt_pointer)
		{
			if(p->array_vol)
				generror(ERR_ARRAY_FUNC, NULL);
			else 
			{
				memcpy(p, extra, sizeof(Type));
				p->basic_type = bt_funcptr;
			}
		}
		else
			debug("compoumdType error\n");
	}
	else if(p->basic_type == bt_pointer
		||p->basic_type == bt_func
		||p->basic_type == bt_funcptr
		||p->basic_type == bt_typedef)
		p->subtype = extra;
	else debug("compoumdType error\n");
	return origin;
}
//check and return the size of this type
int checkTypeSize(
	struct _datatype* type
)//all member in type should be ready
{
	if(!type)
		debug("[checkTypeSize] fatal error, null pointer input\n");
	//if(type->size != UNKNOWN)
	//	return type->size;

	switch(type->basic_type)
	{
	case bt_struct:
	case bt_union:
	//in C struct/union is just a label
//		if(!type->memlist)
//			generror(ERR_STRUCT_VACANT, type->tname);
		break;

	case bt_typedef:
	case bt_pointer:
		checkTypeSize(type->subtype); 
		if(type->basic_type == bt_typedef)
			type->size = type->subtype->size;
		else if(type->array_vol != 0)
			type->size = type->array_vol * type->subtype->size;
		break;
	default:
		break;
	}

	if(!type->size)
		generror(ERR_ZERO_SIZE, type->tname);
	else if(type->size == UNKNOWN)
		generror(ERR_UNKNOWN_SIZE, type->tname);

	return type->size;
}
//sometimes it will do some modify
//return status 0 is ok, 1 is almost ok, 2 is not ok
int checkTypeSame(
	struct _datatype	*t1,
	struct _datatype 	*t2
)
{
	Symbol *sym1,*sym2;
	//t1, t2 are all valid
	if(!t1||!t2)
	{
		debug("[checkType] null pointer input\n");
		return 2;
	}

	if(t1 == t2
		||t1->basic_type == bt_ellipsis
		||t2->basic_type == bt_ellipsis)
		return 0;

	if(t1->memlist && t2->memlist && t1->memlist != t2->memlist)
			return 2;

	if(t1->basic_type!=t2->basic_type)
	{
		if(is_real(t1->basic_type)&&is_real(t2->basic_type))
			return 1;
		else 
			return 2;
	}

	switch(t1->basic_type)
	{
	case bt_struct:
	case bt_union:
		if(t1->tname&&t2->tname
			&&strcmp(t1->tname,t2->tname))
			return 2;

		if(t1->memlist)
		{
			t2->memlist = t1->memlist;
			t2->size = t1->size;
		}
		else 
		{
			t1->memlist = t2->memlist;
			t1->size = t2->size;
		}
		break;
	case bt_funcptr:
		if(t1->arglist == t2->arglist)
			break;

		sym1= t1->arglist;
		sym2= t2->arglist;
		while(sym2&&sym1)
		{
			if(checkTypeSame(sym1->datatype, sym2->datatype)>1)break;
			sym1->name = sym2->name;//....

⌨️ 快捷键说明

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