/* symbol.c */

#include "symbol.h"

static SYMBOL *symbolroot;
extern int yyerror();

/* initialise the symbol table */

void initsymbol()
{
	symbolroot = NULL;
}

/* return pointer to symbol OR NULL if doesn't exist */

SYMBOL *lookupsymbol(char *name)
{
	SYMBOL *ptr;

	ptr = symbolroot;

	while(ptr != NULL)
	{
		if(strcmp(name, ptr->name) == 0)
			break;
		ptr = ptr->next;
	}

	return ptr;
}

/* create a symbol */

SYMBOL *createsymbol(char *name, int value, int defined, int type, int scope)
{
	SYMBOL *ptr;

	ptr = (SYMBOL *)malloc(sizeof(SYMBOL));

	if (ptr == NULL)
	{
		yyerror("Out of Memory");
		exit(1);
	}

	ptr->name = strdup(name);

	if (ptr->name == NULL)
	{
		yyerror("Out of Memory");
		exit(1);
	}

	ptr->type    = type;
	ptr->value   = value;
	ptr->defined = defined;
	ptr->scope   = scope;
	ptr->next    = NULL;

	return ptr;
}

/* delete a symbol (doesn't follow tree!) */
/* returns the value of sym->next         */

SYMBOL *deletesymbol(SYMBOL *sym)
{
	SYMBOL *ptr;

	ptr = sym->next;

	free(sym->name);	/* delete the name string */
	free(sym);		/* free the structure     */

	return ptr;
}

/* add a symbol to the symbol table */

void addsymbol(char *name, int value, int defined, int type, int scope)
{
	SYMBOL *ptr;

	ptr = createsymbol(name, value, defined, type, scope);

	ptr->next = symbolroot;

	symbolroot = ptr;
}

/* debugging function, list the symbols */

void symbollist()
{
	SYMBOL *ptr;

	ptr = symbolroot;

	while(ptr != NULL)
	{
		printf("%20s  ",ptr->name);
		printf("(scope %d) ",ptr->scope);

		switch(ptr->type)
		{
			case UNKNOWNDEF:printf("???   ");
					break;
			case VARDEF:	printf("Var   ");
					break;
			case LABDEF:	printf("Label ");
					break;
			default:	printf("Error unknown symbol type\n");
					exit(1);
		}

		if(ptr->defined)
		{
			printf("= %5d (0x%04x)\n", ptr->value, ptr->value);
		}
		else
		{
			printf("undefined\n");
		}

		ptr = ptr->next;
	}
}

void removelocalsyms(int scope)
{
	SYMBOL *ptr;

	ptr = symbolroot;

	while((ptr != NULL) && (ptr->scope == scope))
	{
		ptr = deletesymbol(ptr);
	}

	symbolroot = ptr;
}

/* ... The End ... */

