diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/symbol.c	Sat Jan 03 04:20:49 2009 +0000
@@ -0,0 +1,120 @@
+/*
+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;
+}