changeset 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 99e3b3310bac
children 9bd584bb6296
files src/Makefile.am src/expr.c src/expr.h src/insn_bitbit.c src/insn_gen.c src/insn_indexed.c src/insn_logicmem.c src/insn_rel.c src/lwasm.c src/lwasm.h src/parse.c src/pass1.c src/symbol.c src/symtab.c
diffstat 14 files changed, 285 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile.am	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/Makefile.am	Sat Jan 03 04:20:49 2009 +0000
@@ -1,3 +1,3 @@
 bin_PROGRAMS = lwasm
-lwasm_SOURCES = main.c expr.c pass1.c pass2.c util.c instab.c parse.c lwasm.c insn_inh.c insn_rtor.c insn_rlist.c insn_rel.c insn_tfm.c insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c list.c
+lwasm_SOURCES = main.c expr.c pass1.c pass2.c util.c instab.c parse.c lwasm.c insn_inh.c insn_rtor.c insn_rlist.c insn_rel.c insn_tfm.c insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c list.c symbol.c
 EXTRA_DIST = instab.h lwasm.h expr.h util.h
--- a/src/expr.c	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/expr.c	Sat Jan 03 04:20:49 2009 +0000
@@ -67,6 +67,8 @@
 lwasm_expr_term_t *lwasm_expr_term_create_oper(int oper)
 {
 	lwasm_expr_term_t *t;
+
+fprintf(stderr, "Creating operator term: %d\n", oper);
 	
 	t = lwasm_alloc(sizeof(lwasm_expr_term_t));
 	t -> term_type = LWASM_TERM_OPER;
@@ -77,6 +79,7 @@
 lwasm_expr_term_t *lwasm_expr_term_create_int(int val)
 {
 	lwasm_expr_term_t *t;
+fprintf(stderr, "Creating integer term: %d\n", val);
 	
 	t = lwasm_alloc(sizeof(lwasm_expr_term_t));
 	t -> term_type = LWASM_TERM_INT;
@@ -88,6 +91,7 @@
 {
 	lwasm_expr_term_t *t;
 	
+fprintf(stderr, "Creating symbol term: %s\n", sym);
 	t = lwasm_alloc(sizeof(lwasm_expr_term_t));
 	t -> term_type = LWASM_TERM_SYM;
 	t -> symbol = lwasm_strdup(sym);
@@ -177,10 +181,11 @@
 int lwasm_expr_parse_term(lwasm_expr_stack_t *s, const char **p)
 {
 	lwasm_expr_term_t *t;
-
+fprintf(stderr, "Expression string %s\n", *p);
 eval_next:
 	if (**p == '(')
 	{
+	fprintf(stderr, "Starting paren\n");
 		(*p)++;
 		lwasm_expr_parse_expr(s, p, 0);
 		if (**p != ')')
@@ -191,6 +196,7 @@
 	
 	if (**p == '+')
 	{
+	fprintf(stderr, "Unary +\n");
 		(*p)++;
 		goto eval_next;
 	}
@@ -424,6 +430,7 @@
 				{
 					// otherwise we must be decimal (if we're still allowed one)
 					val = decval;
+					fprintf(stderr, "End of decimal value\n");
 					break;
 				}
 				else
@@ -492,7 +499,14 @@
 				dval -= '0';
 				if (dval > 9)
 					dval -= 7;
-				
+				fprintf(stderr, "Got digit: %d\n", dval);
+//				if (dval > 1)
+//					valtype &= 14;
+//				if (dval > 7)
+//					valtype &= 12;
+//				if (dval > 9)
+//					valtype &= 8;
+
 				if (valtype & 8)
 				{
 					hexval = hexval * 16 + dval;
@@ -520,11 +534,12 @@
 				}
 			}
 			// break out if we have a return value
-			if (valtype = -1)
+			if (valtype == -1)
 				break;
 			// return if no more valid possibilities!
 			if (valtype == 0)
 				return -1;
+			val = decval;	// in case we fall through
 		}
 		
 		// we get here when we have a value to return
@@ -560,12 +575,15 @@
 	lwasm_expr_term_t *operterm;
 	
 	// return if we are at the end of the expression or a subexpression
-	if (!**p || isspace(**p) || **p == ')')
+	if (!**p || isspace(**p) || **p == ')' || **p == ',')
 		return 0;
 	
-eval_next:
 	if (lwasm_expr_parse_term(s, p) < 0)
 		return -1;
+
+eval_next:
+	if (!**p || isspace(**p) || **p == ')' || **p == ',')
+		return 0;
 	
 	// expecting an operator here
 	for (opern = 0; operators[opern].opernum != LWASM_OPER_NONE; opern++)
@@ -625,15 +643,18 @@
 contain the pointer to the next character after the expression if and only
 if there is no error. In the case of an error, *outp is undefined.
 */
-lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp)
+lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp, int (*sfunc)(char *sym, void *state, int *val), void *state)
 {
 	lwasm_expr_stack_t *s;
 	const char *p;
-	
+	int rval;
+		
 	// actually parse the expression
 	p = inp;
 	s = lwasm_expr_stack_create();
-	if (lwasm_expr_parse_expr(s, &p, 0) < 0)
+	
+	rval = lwasm_expr_parse_expr(s, &p, 0);
+	if (rval < 0)
 		goto cleanup_error;
 	
 	// save end of expression
@@ -641,8 +662,11 @@
 		(*outp) = p;
 	
 	// return potentially partial expression
-	if (lwasm_expr_reval(s) < 0)
+	if (lwasm_expr_reval(s, sfunc, state) < 0)
 		goto cleanup_error;
+
+	if (lwasm_expr_is_constant(s))
+		fprintf(stderr, "Constant expression evaluates to: %d\n", lwasm_expr_get_value(s));
 	
 	return s;
 
@@ -668,9 +692,26 @@
 further operators or only a single term remains
 
 */
-int lwasm_expr_reval(lwasm_expr_stack_t *s)
+int lwasm_expr_reval(lwasm_expr_stack_t *s, int (*sfunc)(char *sym, void *state, int *val), void *state)
 {
 	lwasm_expr_stack_node_t *n;
+	int sval;
+	
+	// resolve symbols
+	// symbols that do not resolve to a constant are left alone
+	for (n = s -> head; n; n = n -> next)
+	{
+		if (n -> term -> term_type == LWASM_TERM_SYM)
+		{
+			if (sfunc(n -> term -> symbol, state, &sval) == 0)
+			{
+				n -> term -> term_type = LWASM_TERM_INT;
+				n -> term -> value = sval;
+				lwasm_free(n -> term -> symbol);
+				n -> term -> symbol = NULL;
+			}
+		}
+	}
 
 next_iter:	
 	// a single term
--- a/src/expr.h	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/expr.h	Sat Jan 03 04:20:49 2009 +0000
@@ -97,10 +97,10 @@
 You must call lwasm_expr_stack_free() on the result when you are finished
 with it.
 */
-__expr_E__ lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp);
+__expr_E__ lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp, int (*sfunc)(char *sym, void *state, int *val), void *state);
 
 // simplify expression
-__expr_E__ int lwasm_expr_reval(lwasm_expr_stack_t *s);
+__expr_E__ int lwasm_expr_reval(lwasm_expr_stack_t *s, int (*sfunc)(char *sym, void *state, int *val), void *state);
 
 // useful macros
 // is the expression "simple" (one term)?
--- a/src/insn_bitbit.c	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_bitbit.c	Sat Jan 03 04:20:49 2009 +0000
@@ -59,7 +59,7 @@
 		register_error(as, l, 1, "Bad operand");
 		return;
 	}
-	s = lwasm_expr_eval(*p, NULL);
+	s = lwasm_evaluate_expr(as, l, *p, NULL);
 	if (!s)
 	{
 		register_error(as, l, 1, "Bad operand");
@@ -83,7 +83,7 @@
 	}
 	r = (r << 6) | (v1 << 3);
 
-	s = lwasm_expr_eval(*p, NULL);
+	s = lwasm_evaluate_expr(as, l, *p, NULL);
 	if (!s)
 	{
 		register_error(as, l, 1, "Bad operand");
@@ -113,7 +113,7 @@
 	if (**p == '<')
 		(*p)++;
 			
-	s = lwasm_expr_eval(*p, NULL);
+	s = lwasm_evaluate_expr(as, l, *p, NULL);
 	if (!s)
 	{
 		register_error(as, l, 1, "Bad operand");
--- a/src/insn_gen.c	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_gen.c	Sat Jan 03 04:20:49 2009 +0000
@@ -61,7 +61,7 @@
 			(*optr)++;
 			f16 = 1;
 		}
-		s = lwasm_expr_eval(*optr, NULL);
+		s = lwasm_evaluate_expr(as, l, *optr, NULL);
 		if (!s)
 		{
 			register_error(as, l, 1, "Bad expression");
@@ -138,7 +138,7 @@
 	{
 		lwasm_emitop(as, l, instab[opnum].ops[3]);
 		(*p)++;
-		s = lwasm_expr_eval(*p, NULL);
+		s = lwasm_evaluate_expr(as, l, *p, NULL);
 		if (!s)
 		{
 			register_error(as, l, 1, "Bad expression");
@@ -169,7 +169,7 @@
 	{
 		lwasm_emitop(as, l, instab[opnum].ops[3]);
 		(*p)++;
-		s = lwasm_expr_eval(*p, NULL);
+		s = lwasm_evaluate_expr(as, l, *p, NULL);
 		if (!s)
 		{
 			register_error(as, l, 1, "Bad expression");
@@ -199,7 +199,7 @@
 	{
 		lwasm_emitop(as, l, instab[opnum].ops[3]);
 		(*p)++;
-		s = lwasm_expr_eval(*p, NULL);
+		s = lwasm_evaluate_expr(as, l, *p, NULL);
 		if (!s)
 		{
 			register_error(as, l, 1, "Bad expression");
@@ -231,7 +231,7 @@
 	{
 		lwasm_emitop(as, l, instab[opnum].ops[0]);
 		(*p)++;
-		s = lwasm_expr_eval(*p, NULL);
+		s = lwasm_evaluate_expr(as, l, *p, NULL);
 		if (!s)
 		{
 			register_error(as, l, 1, "Bad expression");
--- a/src/insn_indexed.c	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_indexed.c	Sat Jan 03 04:20:49 2009 +0000
@@ -129,7 +129,7 @@
 		*b1 = 0x9f;
 		*b2 = 0;
 		*b3 = 0;
-		s = lwasm_expr_eval(*p, &p2);
+		s = lwasm_evaluate_expr(as, l, *p, &p2);
 		if (!s)
 		{
 			register_error(as, l, 1, "Bad expression");
@@ -170,7 +170,7 @@
 	}
 	
 	// now we have to evaluate the expression
-	s = lwasm_expr_eval(*p, &p2);
+	s = lwasm_evaluate_expr(as, l, *p, &p2);
 	*p = p2;
 	if (!s)
 	{
--- a/src/insn_logicmem.c	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_logicmem.c	Sat Jan 03 04:20:49 2009 +0000
@@ -40,7 +40,7 @@
 	if (**p == '#')
 		(*p)++;
 	
-	s = lwasm_expr_eval(*p, &p2);
+	s = lwasm_evaluate_expr(as, l, *p, &p2);
 	*p = (char *)p2;
 
 	if (!s)
--- a/src/insn_rel.c	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_rel.c	Sat Jan 03 04:20:49 2009 +0000
@@ -37,7 +37,7 @@
 	
 	lwasm_emitop(as, l, instab[opnum].ops[0]);
 	
-	s = lwasm_expr_eval(*p, NULL);
+	s = lwasm_evaluate_expr(as, l, *p, NULL);
 	if (!s)
 	{
 		register_error(as, l, 1, "Bad operand");
@@ -62,7 +62,7 @@
 	
 	lwasm_emitop(as, l, instab[opnum].ops[0]);
 	
-	s = lwasm_expr_eval(*p, NULL);
+	s = lwasm_evaluate_expr(as, l, *p, NULL);
 	if (!s)
 	{
 		register_error(as, l, 1, "Bad operand");
--- a/src/lwasm.c	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/lwasm.c	Sat Jan 03 04:20:49 2009 +0000
@@ -29,6 +29,7 @@
 
 #include "lwasm.h"
 #include "util.h"
+#include "expr.h"
 
 int register_error(asmstate_t *as, lwasm_line_t *l, int pass, const char *fmt, ...)
 {
@@ -147,3 +148,36 @@
 		(*str)+=3;
 	return rval;
 }
+
+struct symstateinfo
+{
+	asmstate_t *as;
+	lwasm_line_t *l;
+};	
+
+int lwasm_expr_lookup_symbol(char *sym, void *state, int *val)
+{
+	lwasm_symbol_ent_t *se;
+	struct symstateinfo *st;
+	
+	st = state;
+	
+	// look for local symbol first then global symbol
+	se = lwasm_find_symbol(st -> as, sym, st -> as -> context);
+	if (!se)
+		se = lwasm_find_symbol(st -> as, sym, -1);
+	if (!se)
+		return -1;
+	*val = se -> value;
+	return 0;
+}
+
+lwasm_expr_stack_t *lwasm_evaluate_expr(asmstate_t *as, lwasm_line_t *l, const char *inp, const char **outp)
+{
+	struct symstateinfo st;
+	
+	st.as = as;
+	st.l = l;
+	
+	return(lwasm_expr_eval(inp, outp, lwasm_expr_lookup_symbol, &st));
+}
--- a/src/lwasm.h	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/lwasm.h	Sat Jan 03 04:20:49 2009 +0000
@@ -24,10 +24,13 @@
 #ifndef __lwasm_h_seen__
 #define __lwasm_h_seen__
 
+#include "expr.h"
+
 #define OUTPUT_DECB		0	// DECB multirecord format
 #define OUTPUT_RAW		1	// raw sequence of bytes
 #define OUTPUT_OBJ		2	// proprietary object file format
 
+
 // structure for tracking errors
 typedef struct lwasm_error_s lwasm_error_t;
 struct lwasm_error_s
@@ -46,12 +49,25 @@
 	lwasm_line_t *prev;	// previous line
 	lwasm_error_t *err;	// error messages
 	int fsize;			// forced size (0 = no forced size)
+	char *sym;			// scratch area to record the presence of a symbol
+};
+
+// for keeping track of symbols
+typedef struct lwasm_symbol_ent_s lwasm_symbol_ent_t;
+struct lwasm_symbol_ent_s
+{
+	char *sym;			// the symbol
+	int context;		// the context number of the symbol (-1 for global)
+	int value;			// the value of the symbol
+	lwasm_symbol_ent_t *next;	// next symbol in the table
+	lwasm_symbol_ent_t *prev;	// previous symbol in the table
 };
 
 // keep track of current assembler state
 typedef struct {
 	int dpval;					// current dp value (setdp)
 	int addr;					// current address
+	int context;				// context counter (for local symbols)
 	int errorcount;				// error count
 	int passnum;				// which pass are we on?
 	int execaddr;				// execution address for the program (END ....)
@@ -59,6 +75,9 @@
 
 	lwasm_line_t *lineshead;	// first line of source code
 	lwasm_line_t *linestail;	// last line of source code
+	
+	lwasm_symbol_ent_t *symhead;	// first entry in symbol table
+	lwasm_symbol_ent_t *symtail;	// last entry in symbol table
 
 	const char *infile;			// input file
 	const char *outfile;		// output file
@@ -84,14 +103,23 @@
 __lwasm_E__ int lwasm_lookupreg2(const char *reglist, char **str);
 __lwasm_E__ int lwasm_lookupreg3(const char *rlist, const char **str);
 
+__lwasm_E__ lwasm_expr_stack_t *lwasm_evaluate_expr(asmstate_t *as, lwasm_line_t *l, const char *inp, const char **outp);
+
 #undef __lwasm_E__
 
 
-#ifndef __symtab_c_seen__
-//extern void register_symbol(asmstate_t *as, sourceline_t *cl, char *symstr, int val, int flags);
-//extern int lookup_symbol(asmstate_t *as, char *symstr);
-//extern void list_symbols(asmstate_t *as, FILE *f);
+#ifndef __symbol_c_seen__
+#define __lwasm_E__ extern
+#else
+#define __lwasm_E__
 #endif
 
+__lwasm_E__ int lwasm_register_symbol(asmstate_t *as, lwasm_line_t *l, char *sym, int val);
+__lwasm_E__ lwasm_symbol_ent_t *lwasm_find_symbol(asmstate_t *as, char *sym, int scontext);
+__lwasm_E__ int lwasm_set_symbol(asmstate_t *as, char *sym, int scontext, int val);
+
+#undef __lwasm_E__
+
+
 
 #endif //__lwasm_h_seen__
--- a/src/parse.c	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/parse.c	Sat Jan 03 04:20:49 2009 +0000
@@ -37,17 +37,43 @@
 	char *p, *p2;
 	char *opc;
 	int opnum;
+	char *sym;
 	
 	p = l -> text;
 	
 	if (!*p)
+	{
+		as -> context += 1;
 		return 0;
+	}
 	
 	if (!isspace(*p) && *p != '*' && *p != ';')
 	{
 		// we have a symbol specified here
 		// parse it and define
 		// need to handle local symbols here...
+		for (p2 = p; *p2 && !isspace(*p2); p2++)
+			/* do nothing */ ;
+		
+		sym = lwasm_alloc((p2 - p) + 1);
+		sym[p2 - p] = '\0';
+		memcpy(sym, p, p2 - p);
+		
+		l -> sym = sym;
+		// have a symbol; now determine if it is valid and register it
+		// at the current address of the line
+		if (lwasm_register_symbol(as, l, sym, as -> addr) < 0)
+			l -> sym = NULL;
+	}
+	else
+	{
+		while (*p && isspace(*p))
+			(*p)++;
+		if (!*p)
+		{
+			as -> context += 1;
+			return 0;
+		}
 	}
 
 	// skip white space
@@ -56,7 +82,10 @@
 	
 	// if comment or end of line, return
 	if (!*p || *p == '*' || *p == ';')
+	{
+		lwasm_free(l -> sym);
 		return 0;
+	}
 	
 	// parse the opcode
 	for (p2 = p; *p2 && !isspace(*p2); p2++)
@@ -83,6 +112,7 @@
 	{
 		// invalid operation code, throw error
 		register_error(as, l, 1, "Invalid operation code '%s'", opc);
+		lwasm_free(l -> sym);
 		lwasm_free(opc);
 		return -1;
 	}
@@ -91,4 +121,5 @@
 	(instab[opnum].fn)(as, l, &p2, opnum);
 	
 	lwasm_free(opc);
+	lwasm_free(sym);
 }
--- a/src/pass1.c	Fri Jan 02 06:07:40 2009 +0000
+++ b/src/pass1.c	Sat Jan 03 04:20:49 2009 +0000
@@ -135,6 +135,7 @@
 			nl -> prev = as -> linestail;
 			nl -> err = NULL;
 			nl -> fsize = 0;
+			nl -> sym = NULL;
 			if (as -> linestail)
 				as -> linestail -> next = nl;
 			else
--- /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;
+}
--- a/src/symtab.c	Fri Jan 02 06:07:40 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
-symtab.c
-Copyright © 2008 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/>.
-
-Implements code for handling the symbol table.
-*/
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#define __symtab_c_seen__
-#include "lwasm.h"
-
-void register_symbol(asmstate_t *as, sourceline_t *cl, char *symstr, int val, int flags)
-{
-	symtab_t *st;
-	symtab_t *prev;
-	int cv = -2;
-	
-	for (prev = NULL, st = as -> symbol_table; st; st = st -> next)
-	{
-		cv = strcasecmp(st -> symbol, symstr);
-		if (cv == 0)
-		{
-			cv = strcmp(st -> symbol, symstr);
-		}
-		if (cv >= 0)
-			break;
-		prev = st;
-	}
-	// cv is 0 if we found the symbol, > 0 if we didn't and found one
-	// later in order, or -2 if we never did a comparison
-	// if st is NULL, the value of cv is irrelevant as it means
-	// we fell off the end of the list
-	// if st is NULL and prev is not, then prev is the tail of the list
-	// if both are NULL, the list is empty
-	
-	// handle adding the symbol if needed
-	if (!st || cv != 0)
-	{
-		symtab_t *st2;
-		// register the symbol
-		st2 = malloc(sizeof(symtab_t));
-		st2 -> symbol = strdup(symstr);
-		st2 -> addr = val;
-		st2 -> flags = 0;
-		if (flags & SYMFLAG_SET)
-			st2 -> flags |= SYMFLAG_SET;
-
-		if (prev)
-			prev -> next = st2;
-		else
-			as -> symbol_table = st2;
-		
-		st2 -> next = st;
-		return;
-	}
-	
-	// st is NOT NULL here and cv IS 0
-	if ((flags & SYMFLAG_SET) && ((st -> flags) & SYMFLAG_SET))
-	{
-		// symbol already exists but it is a "SET" symbol so reset the value
-		st -> addr = val;
-		return;
-	}
-	if (st && as -> passnum == 1)
-	{
-		// duplicate symbol, flag error
-		errorp1(ERR_DUPSYM);
-	}
-	if (st -> addr != val)
-		errorp2(ERR_PHASE);
-}
-
-int lookup_symbol(asmstate_t *as, char *symstr)
-{
-	symtab_t *st;
-
-	for (st = as -> symbol_table; st; st = st -> next)
-	{
-		if (!strcmp(symstr, st -> symbol))
-			break;
-	}
-	if (st)
-		return st -> addr;
-	return -1;
-}
-
-void list_symbols(asmstate_t *as, FILE *f)
-{
-	symtab_t *st;
-	for (st = as -> symbol_table; st; st = st -> next)
-	{
-		fprintf(f, "%04X %s%s\n", st -> addr, st -> symbol, (st -> flags & SYMFLAG_SET) ? "(S)" : "");
-	}
-}