view src/symbol.c @ 37:538e15927776

Added symbol handling to expression subsystem; adpated instruction handlers to the new scheme; misc fixes
author lost
date Sat, 03 Jan 2009 04:20:49 +0000
parents
children d2cee0c335e7
line wrap: on
line source

/*
symbol.c
Copyright © 2009 William Astle

This file is part of LWASM.

LWASM is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.

You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*
for handling the symbol table
*/

#define __symbol_c_seen__

#include <string.h>

#include "lwasm.h"
#include "util.h"

int lwasm_register_symbol(asmstate_t *as, lwasm_line_t *l, char *sym, int val)
{
	lwasm_symbol_ent_t *se, *se2;
	char *p;
	
	int scontext = -1;
	
	// first check if the symbol is valid
	// the following characters are allowed in a symbol:
	// [a-zA-Z0-9._$?@] and any byte value larger than 0x7F
	// although symbols should be restricted to the 7 bit range
	// symbols must start with [a-zA-Z._]
	if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._@?", *sym))
	{
		register_error(as, l, 1, "Bad symbol: %s", sym);
		return -1;
	}
	
	for (p = sym; *p; p++)
	{
		if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._$?@0123456789", *sym) && (unsigned char)*sym < 0x80)
		{
			register_error(as, l, 1, "Bad symbol: %s", sym);
			return -1;
		}
		// flag local symbols while we're at it...
		if (*p == '?' || *p == '@')
			scontext = as -> context;
	}
	
	// now look it for to see if it is a duplicate
	se = lwasm_find_symbol(as, sym, scontext);
	if (se)
	{
		register_error(as, l, 1, "Mulitply defined symbol: %s", sym);
		return -1;
	}
		
	// if not a duplicate, register it with the value
	se = lwasm_alloc(sizeof(lwasm_symbol_ent_t));
	if (as -> symhead)
	{
		se -> prev = NULL;
		se -> next = as -> symhead;
		as -> symhead -> prev = se;
		as -> symhead = se;
	}
	else
	{
		se -> next = NULL;
		se -> prev = NULL;
		as -> symhead = se;
		as -> symtail = se;
	}
	se -> value = val;
	se -> sym = lwasm_strdup(sym);
	se -> context = scontext;

	return 0;
}

lwasm_symbol_ent_t *lwasm_find_symbol(asmstate_t *as, char *sym, int scontext)
{
	lwasm_symbol_ent_t *se;
	
	for (se = as -> symhead; se; se = se -> next)
	{
		if (scontext == se -> context && !strcmp(sym, se -> sym))
		{
			return se;
		}
	}
	return NULL;
}

// reset the value of a symbol - should not be used normally
// it is intended for use by such operations as EQU
// returns -1 if the symbol is not registered
int lwasm_set_symbol(asmstate_t *as, char *sym, int scontext, int val)
{
	lwasm_symbol_ent_t *se;
	
	se = lwasm_find_symbol(as, sym, scontext);
	if (!se)
		return -1;
	
	se -> value = val;
	return 0;
}