changeset 151:427e268e876b

renamed src to lwasm to better reflect its purpose
author lost
date Fri, 30 Jan 2009 04:01:55 +0000
parents f0881c115010
children 6bd4755d224f
files Makefile.am configure.ac doc/Makefile.am doc/README lwasm/Makefile.am lwasm/expr.c lwasm/expr.h lwasm/insn_bitbit.c lwasm/insn_gen.c lwasm/insn_indexed.c lwasm/insn_inh.c lwasm/insn_logicmem.c lwasm/insn_rel.c lwasm/insn_rlist.c lwasm/insn_rtor.c lwasm/insn_tfm.c lwasm/instab.c lwasm/instab.h lwasm/list.c lwasm/lwasm.c lwasm/lwasm.h lwasm/lwval.c lwasm/lwval.h lwasm/macro.c lwasm/main.c lwasm/output.c lwasm/parse.c lwasm/pass1.c lwasm/pass2.c lwasm/pragma.c lwasm/pseudo.c lwasm/symbol.c lwasm/util.c lwasm/util.h src/Makefile.am src/insn_gen.c src/instab.c src/instab.h src/list.c src/lwasm.c src/lwasm.h src/macro.c src/main.c src/output.c src/pragma.c src/pseudo.c
diffstat 46 files changed, 6694 insertions(+), 3519 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Fri Jan 30 02:55:30 2009 +0000
+++ b/Makefile.am	Fri Jan 30 04:01:55 2009 +0000
@@ -1,2 +1,2 @@
-SUBDIRS = src lwlink
-DIST_SUBDIRS = doc src lwlink
+SUBDIRS = lwasm lwlink
+DIST_SUBDIRS = doc lwasm lwlink
--- a/configure.ac	Fri Jan 30 02:55:30 2009 +0000
+++ b/configure.ac	Fri Jan 30 04:01:55 2009 +0000
@@ -4,7 +4,7 @@
 AC_CONFIG_HEADERS([src/config.h])
 AC_CONFIG_FILES([
 	Makefile
-	src/Makefile
+	lwasm/Makefile
 	doc/Makefile
 	lwlink/Makefile
 ])
--- a/doc/Makefile.am	Fri Jan 30 02:55:30 2009 +0000
+++ b/doc/Makefile.am	Fri Jan 30 04:01:55 2009 +0000
@@ -1,3 +1,3 @@
-EXTRA_DIST = lwasm.txt internals.txt pseudoops.txt objectfiles.txt scripts.txt lwlink.txt
+EXTRA_DIST = lwasm.txt internals.txt manual.docbook.sgml manual.html manual
 
 
--- a/doc/README	Fri Jan 30 02:55:30 2009 +0000
+++ b/doc/README	Fri Jan 30 04:01:55 2009 +0000
@@ -9,5 +9,5 @@
 
 or
 
-docbook2html -u manual.docbook.sgml && mv manual.docbook.html manual.html
+docbook2html -u manual.docbook.sgml && mv manual.docbook.html manual/manual.html
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/Makefile.am	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +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 symbol.c output.c pseudo.c macro.c pragma.c
+EXTRA_DIST = instab.h lwasm.h expr.h util.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/expr.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,893 @@
+/*
+expr.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/>.
+*/
+
+/*
+This file contains the actual expression evaluator
+*/
+
+#define __expr_c_seen__
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "expr.h"
+#include "util.h"
+#include "lwasm.h"
+
+lwasm_expr_stack_t *lwasm_expr_stack_create(void)
+{
+	lwasm_expr_stack_t *s;
+	
+	s = lwasm_alloc(sizeof(lwasm_expr_stack_t));
+	s -> head = NULL;
+	s -> tail = NULL;
+	return s;
+}
+
+void lwasm_expr_stack_free(lwasm_expr_stack_t *s)
+{
+	while (s -> head)
+	{
+		s -> tail = s -> head;
+		s -> head = s -> head -> next;
+		lwasm_expr_term_free(s -> tail -> term);
+		lwasm_free(s -> tail);
+	}
+	lwasm_free(s);
+}
+
+void lwasm_expr_term_free(lwasm_expr_term_t *t)
+{
+	if (t)
+	{
+		if (t -> term_type == LWASM_TERM_SYM)
+			lwasm_free(t -> symbol);
+		lwasm_free(t);
+	}
+}
+
+lwasm_expr_term_t *lwasm_expr_term_create_oper(int oper)
+{
+	lwasm_expr_term_t *t;
+
+	debug_message(10, "Creating operator term: %d", oper);
+	
+	t = lwasm_alloc(sizeof(lwasm_expr_term_t));
+	t -> term_type = LWASM_TERM_OPER;
+	t -> value = oper;
+	return t;
+}
+
+lwasm_expr_term_t *lwasm_expr_term_create_int(int val)
+{
+	lwasm_expr_term_t *t;
+	debug_message(10, "Creating integer term: %d", val);
+	
+	t = lwasm_alloc(sizeof(lwasm_expr_term_t));
+	t -> term_type = LWASM_TERM_INT;
+	t -> value = val;
+	return t;
+}
+
+lwasm_expr_term_t *lwasm_expr_term_create_secbase(void)
+{
+	lwasm_expr_term_t *t;
+	debug_message(10, "Creating section base term");
+	
+	t = lwasm_alloc(sizeof(lwasm_expr_term_t));
+	t -> term_type = LWASM_TERM_SECBASE;
+	return t;
+}
+
+lwasm_expr_term_t *lwasm_expr_term_create_sym(char *sym)
+{
+	lwasm_expr_term_t *t;
+	
+	debug_message(10, "Creating symbol term: %s", sym);
+	
+	t = lwasm_alloc(sizeof(lwasm_expr_term_t));
+	t -> term_type = LWASM_TERM_SYM;
+	t -> symbol = lwasm_strdup(sym);
+	return t;
+}
+
+lwasm_expr_term_t *lwasm_expr_term_dup(lwasm_expr_term_t *t)
+{
+	switch (t -> term_type)
+	{
+	case LWASM_TERM_INT:
+		return lwasm_expr_term_create_int(t -> value);
+		
+	case LWASM_TERM_OPER:
+		return lwasm_expr_term_create_oper(t -> value);
+		
+	case LWASM_TERM_SYM:
+		return lwasm_expr_term_create_sym(t -> symbol);
+	
+	case LWASM_TERM_SECBASE:
+		return lwasm_expr_term_create_secbase();
+		
+	default:
+		debug_message(0, "lwasm_expr_term_dup(): invalid term type %d", t -> term_type);
+		exit(1);
+	}
+// can't get here
+}
+
+void lwasm_expr_stack_push(lwasm_expr_stack_t *s, lwasm_expr_term_t *t)
+{
+	lwasm_expr_stack_node_t *n;
+
+	if (!s)
+	{
+		debug_message(0, "lwasm_expr_stack_push(): invalid stack pointer");
+		exit(1);
+	}
+	
+	n = lwasm_alloc(sizeof(lwasm_expr_stack_node_t));
+	n -> next = NULL;
+	n -> prev = s -> tail;
+	n -> term = lwasm_expr_term_dup(t);
+	
+	if (s -> head)
+	{
+		s -> tail -> next = n;
+		s -> tail = n;
+	}
+	else
+	{
+		s -> head = n;
+		s -> tail = n;
+	}
+}
+
+lwasm_expr_term_t *lwasm_expr_stack_pop(lwasm_expr_stack_t *s)
+{
+	lwasm_expr_term_t *t;
+	lwasm_expr_stack_node_t *n;
+	
+	if (!(s -> tail))
+		return NULL;
+	
+	n = s -> tail;
+	s -> tail = n -> prev;
+	if (!(n -> prev))
+	{
+		s -> head = NULL;
+	}
+	
+	t = n -> term;
+	n -> term = NULL;
+	
+	lwasm_free(n);
+	
+	return t;
+}
+
+// the following two functions are co-routines which actually parse
+// an infix expression onto the expression stack, each returns -1
+// if an error is encountered
+
+/*
+parse a term and push it onto the stack
+
+this function handles unary prefix operators (-, +, .not., .com.)
+as well as ()
+*/
+int lwasm_expr_parse_term(lwasm_expr_stack_t *s, const char **p)
+{
+	lwasm_expr_term_t *t;
+	debug_message(2, "Expression string %s", *p);
+
+eval_next:
+	if (!**p || isspace(**p) || **p == ')' || **p == ']')
+		return -1;
+	if (**p == '(')
+	{
+		debug_message(3, "Starting paren");
+		(*p)++;
+		lwasm_expr_parse_expr(s, p, 0);
+		if (**p != ')')
+			return -1;
+		(*p)++;
+		return 0;
+	}
+	
+	if (**p == '+')
+	{
+		debug_message(3, "Unary +");
+		(*p)++;
+		goto eval_next;
+	}
+	
+	if (**p == '-')
+	{
+		// parse expression following "-"
+		(*p)++;
+		if (lwasm_expr_parse_expr(s, p, 200) < 0)
+			return -1;
+		t = lwasm_expr_term_create_oper(LWASM_OPER_NEG);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		return 0;
+	}
+	
+	if (**p == '^')
+	{
+		// parse expression following "^"
+		(*p)++;
+		if (lwasm_expr_parse_expr(s, p, 200) < 0)
+			return -1;
+		t = lwasm_expr_term_create_oper(LWASM_OPER_COM);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		return 0;
+	}
+	
+	/*
+		we have an actual term here so evaluate it
+		
+		it could be one of the following:
+		
+		1. a decimal constant
+		2. a hexadecimal constant
+		3. an octal constant
+		4. a binary constant
+		5. a symbol reference
+		6. the "current" instruction address (*)
+		7. the "current" data address (.)
+		8. a "back reference" (<)
+		9. a "forward reference" (>)
+		
+		items 6 through 9 are stored as symbol references
+		
+		(a . followed by a . or a alpha char or number is a symbol)
+	*/
+	if (**p == '*'
+		|| (
+			**p == '.' 
+			&& (*p)[1] != '.' 
+			&& !((*p)[1] >= 'A' && (*p)[1] <= 'Z') 
+			&& !((*p)[1] >= 'a' && (*p)[1] <= 'z') 
+			&& !((*p)[1] >= '0' && (*p)[1] <= '9')
+			)
+		|| **p == '<'
+		|| **p == '>')
+	{
+		char tstr[2];
+		tstr[0] = **p;
+		tstr[1] = '\0';
+		t = lwasm_expr_term_create_sym(tstr);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		(*p)++;
+		return 0;
+	}
+	
+	/*
+		- a symbol will be a string of characters introduced by a letter, ".",
+		  "_" but NOT a number
+		- a decimal constant will consist of only digits, optionally prefixed
+		  with "&"
+		- a binary constant will consist of only 0s and 1s either prefixed with %
+		  or suffixed with "B"
+		- a hex constant will consist of 0-9A-F either prefixed with $ or
+		  suffixed with "H"; a hex number starting with A-F must be prefixed
+		  with $ or start with 0 and end with H
+		- an octal constant will consist of 0-7 either prefixed with @ or
+		  suffixed with "O" or "Q"
+		- an ascii constant will be a single character prefixed with a '
+		- a double ascii constant will be two characters prefixed with a "
+		
+	*/
+	if (**p == '"')
+	{
+		// double ascii constant
+		int val;
+		(*p)++;
+		if (!**p)
+			return -1;
+		if (!*((*p)+1))
+			return -1;
+		val = **p << 8 | *((*p) + 1);
+		(*p) += 2;
+		t = lwasm_expr_term_create_int(val);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		return 0;
+	}
+	else if (**p == '\'')
+	{
+		// single ascii constant
+		int val;
+		(*p)++;
+		debug_message(3, "Single ascii character constant '%c'", **p);
+		if (!**p)
+			return -1;
+		val = **p;
+		(*p)++;
+		t = lwasm_expr_term_create_int(val);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		return 0;
+	}
+	else if (**p == '&')
+	{
+		// decimal constant
+		int val = 0;
+		
+		(*p)++;
+		while (**p && strchr("0123456789", **p))
+		{
+			val = val * 10 + (**p - '0');
+			(*p)++;
+		}
+		t = lwasm_expr_term_create_int(val);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		return 0;
+	}
+	else if (**p == '%')
+	{
+		// binary constant
+		int val = 0;
+		
+		(*p)++;
+		while (**p == '0' || **p == '1')
+		{
+			val = val * 2 + (**p - '0');
+			(*p)++;
+		}
+		t = lwasm_expr_term_create_int(val);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		return 0;
+	}
+	else if (**p == '$')
+	{
+		// hexadecimal constant
+		int val = 0, val2;
+		
+		(*p)++;
+		debug_message(3, "Found prefix hex constant: %s", *p);
+		while (**p && strchr("0123456789ABCDEFabcdef", **p))
+		{
+			val2 = toupper(**p) - '0';
+			if (val2 > 9)
+				val2 -= 7;
+			debug_message(3, "Got char: %c (%d)", **p, val2);
+			val = val * 16 + val2;
+			(*p)++;
+		}
+		t = lwasm_expr_term_create_int(val);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		return 0;
+	}
+	// an @ followed by a digit is an octal number
+	// but if it's followed by anything else, it is a symbol
+	else if (**p == '@' && isdigit(*(*p + 1)))
+	{
+		// octal constant
+		int val = 0;
+		
+		(*p)++;
+		while (**p && strchr("01234567", **p))
+		{
+			val = val * 8 + (**p - '0');
+			(*p)++;
+		}
+		t = lwasm_expr_term_create_int(val);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		return 0;
+	}
+	
+	// symbol or bare decimal or suffix identified constant here
+	// all numbers will start with a digit at this point
+	if (**p < '0' || **p > '9')
+	{
+		int l = 0;
+		char *sb;
+		
+		// evaluate a symbol here
+		static const char *symchars = "_.$@?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+		while ((*p)[l] && strchr(symchars, (*p)[l]))
+			l++;
+
+		if (l == 0)
+			return -1;
+
+		sb = lwasm_alloc(l + 1);
+		sb[l] = '\0';
+		memcpy(sb, *p, l);
+		t = lwasm_expr_term_create_sym(sb);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		(*p) += l;
+		debug_message(3, "Symbol: '%s'; (%s)", sb, *p);
+		lwasm_free(sb);
+		return 0;
+	}
+	
+	if (!**p)
+		return -1;
+	
+	// evaluate a suffix based constant
+	{
+		int decval = 0, binval = 0, hexval = 0, octval = 0;
+		int valtype = 15;	// 1 = bin, 2 = oct, 4 = dec, 8 = hex
+		int bindone = 0;
+		int val;
+		int dval;
+		
+		while (1)
+		{
+			if (!**p || !strchr("0123456789ABCDEFabcdefqhoQHO", **p))
+			{
+				// we can legally have bin or decimal here
+				if (bindone)
+				{
+					// we just finished a binary value
+					val = binval;
+					break;
+				}
+				else if (valtype & 4)
+				{
+					// otherwise we must be decimal (if we're still allowed one)
+					val = decval;
+					debug_message(3, "End of decimal value");
+					break;
+				}
+				else
+				{
+					// bad value
+					return -1;
+				}
+			}
+			
+			dval = toupper(**p);
+			(*p)++;
+			
+			if (bindone)
+			{
+				// any characters past "B" means it is not binary
+				bindone = 0;
+				valtype &= 14;
+			}
+			
+			switch (dval)
+			{
+			case 'Q':
+			case 'O':
+				if (valtype & 2)
+				{
+					val = octval;
+					valtype = -1;
+					break;
+				}
+				else
+				{
+					// not a valid octal value
+					return -1;
+				}
+				/* can't get here */
+
+			case 'H':
+				if (valtype & 8)
+				{
+					val = hexval;
+					valtype = -1;
+					break;
+				}
+				else
+				{
+					// not a valid hex number
+					return -1;
+				}
+				/* can't get here */
+
+			case 'B':
+				// this is a bit of a sticky one since B is a legit hex
+				// digit so this may or may not be the end of the number
+				// so we fall through to the digit case
+
+				if (valtype & 1)
+				{
+					// could still be binary
+					bindone = 1;
+					valtype = 9;	// hex and binary
+				}
+				/* fall through intentional */
+				
+			default:
+				// digit
+				dval -= '0';
+				if (dval > 9)
+					dval -= 7;
+				debug_message(3, "Got digit: %d", dval);
+//				if (dval > 1)
+//					valtype &= 14;
+//				if (dval > 7)
+//					valtype &= 12;
+//				if (dval > 9)
+//					valtype &= 8;
+
+				if (valtype & 8)
+				{
+					hexval = hexval * 16 + dval;
+				}
+				if (valtype & 4)
+				{
+					if (dval > 9)
+						valtype &= 11;
+					else
+						decval = decval * 10 + dval;
+				}
+				if (valtype & 2)
+				{
+					if (dval > 7)
+						valtype &= 13;
+					else
+						octval = octval * 8 + dval;
+				}
+				if (valtype & 1)
+				{
+					if (dval > 1)
+						valtype &= 14;
+					else
+						binval = binval * 2 + dval;
+				}
+			}
+			// break out if we have a return value
+			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
+		t = lwasm_expr_term_create_int(val);
+		lwasm_expr_stack_push(s, t);
+		lwasm_expr_term_free(t);
+		return 0;
+	}
+	/* can't get here */
+}
+
+// parse an expression and push the result onto the stack
+// if an operator of lower precedence than the value of "prec" is found,
+int lwasm_expr_parse_expr(lwasm_expr_stack_t *s, const char **p, int prec)
+{
+	static const struct operinfo
+	{
+		int opernum;
+		char *operstr;
+		int operprec;
+	} operators[] =
+	{
+		{ LWASM_OPER_PLUS, "+", 100 },
+		{ LWASM_OPER_MINUS, "-", 100 },
+		{ LWASM_OPER_TIMES, "*", 150 },
+		{ LWASM_OPER_DIVIDE, "/", 150 },
+		{ LWASM_OPER_MOD, "%", 150 },
+		{ LWASM_OPER_INTDIV, "\\", 150 },
+		
+		{ LWASM_OPER_NONE, "", 0 }
+	};	
+	int opern, i;
+	lwasm_expr_term_t *operterm;
+	
+	// return if we are at the end of the expression or a subexpression
+	if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']')
+		return 0;
+	
+	if (lwasm_expr_parse_term(s, p) < 0)
+		return -1;
+
+eval_next:
+	if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']')
+		return 0;
+	
+	// expecting an operator here
+	for (opern = 0; operators[opern].opernum != LWASM_OPER_NONE; opern++)
+	{
+		for (i = 0; (*p)[i] && operators[opern].operstr[i] && (*p[i] == operators[opern].operstr[i]); i++)
+			/* do nothing */ ;
+		if (operators[opern].operstr[i] == '\0')
+			break;
+	}
+	if (operators[opern].opernum == LWASM_OPER_NONE)
+	{
+		// unrecognized operator
+		return -1;
+	}
+	
+	// the operator number in question is in opern; i is the length of the
+	// operator string
+	
+	// logic:
+	// if the precedence of this operation is <= to the "prec" flag,
+	// we simply return without advancing the input pointer; the operator
+	// will be evaluated again in the enclosing function call
+	if (operators[opern].operprec <= prec)
+		return 0;
+	
+	// logic:
+	// we have a higher precedence operator here so we will advance the
+	// input pointer to the next term and let the expression evaluator
+	// loose on it after which time we will push our operator onto the
+	// stack and then go on with the expression evaluation
+	(*p) += i;	// advance input pointer
+	
+	// evaluate next expression(s) of higher precedence
+	if (lwasm_expr_parse_expr(s, p, operators[opern].operprec) < 0)
+		return -1;
+	
+	operterm = lwasm_expr_term_create_oper(operators[opern].opernum);
+	lwasm_expr_stack_push(s, operterm);
+	lwasm_expr_term_free(operterm);
+	
+	// return if we are at the end of the expression or a subexpression
+	if (!**p || isspace(**p) || **p == ')')
+		return 0;
+
+	// continue evaluating
+	goto eval_next;	 	
+}
+
+/*
+actually evaluate an expression
+
+This happens in two stages. The first stage merely parses the expression into
+a lwasm_expr_stack_t * which is then evaluated as much as possible before the
+result is returned.
+
+Returns NULL on a parse error or otherwise invalid expression. *outp will
+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 *(*sfunc)(char *sym, void *state), void *state)
+{
+	lwasm_expr_stack_t *s;
+	const char *p;
+	int rval;
+		
+	// actually parse the expression
+	p = inp;
+	s = lwasm_expr_stack_create();
+	
+	rval = lwasm_expr_parse_expr(s, &p, 0);
+	if (rval < 0)
+		goto cleanup_error;
+	
+	// save end of expression
+	if (outp)
+		(*outp) = p;
+	
+	// return potentially partial expression
+	if (lwasm_expr_reval(s, sfunc, state) < 0)
+		goto cleanup_error;
+
+	if (lwasm_expr_is_constant(s))
+		debug_message(3, "Constant expression evaluates to: %d", lwasm_expr_get_value(s));
+	
+	return s;
+
+cleanup_error:
+	lwasm_expr_stack_free(s);
+	return NULL;
+}
+
+/*
+take an expression stack s and scan for operations that can be completed
+
+return -1 on error, 0 on no error
+
+possible errors are: division by zero or unknown operator
+
+theory of operation:
+
+scan the stack for an operator which has two constants preceding it (binary)
+or 1 constant preceding it (unary) and if found, perform the calculation
+and replace the operator and its operands with the result
+
+repeat the scan until no futher simplications are found or if there are no
+further operators or only a single term remains
+
+*/
+int lwasm_expr_reval(lwasm_expr_stack_t *s, lwasm_expr_stack_t *(*sfunc)(char *sym, void *state), void *state)
+{
+	lwasm_expr_stack_node_t *n, *n2;
+	lwasm_expr_stack_t *ss;
+	int c;
+	
+next_iter_sym:
+	// resolve symbols
+	// symbols that do not resolve to an expression are left alone
+	for (c = 0, n = s -> head; n; n = n -> next)
+	{
+		if (n -> term -> term_type == LWASM_TERM_SYM)
+		{
+			ss = sfunc(n -> term -> symbol, state);
+			if (ss)
+			{
+				c++;
+				// splice in the result stack
+				if (n -> prev)
+				{
+					n -> prev -> next = ss -> head;
+				}
+				else
+				{
+					s -> head = ss -> head;
+				}
+				ss -> head -> prev = n -> prev;
+				ss -> tail -> next = n -> next;
+				if (n -> next)
+				{
+					n -> next -> prev = ss -> tail;
+				}
+				else
+				{
+					s -> tail = ss -> tail;
+				}
+				lwasm_expr_term_free(n -> term);
+				lwasm_free(n);
+				n = ss -> tail;
+				
+				ss -> head = NULL;
+				ss -> tail = NULL;
+				lwasm_expr_stack_free(ss);
+			}
+		}
+	}
+	if (c)
+		goto next_iter_sym;
+
+next_iter:	
+	// a single term
+	if (s -> head == s -> tail)
+		return 0;
+	
+	// search for an operator
+	for (n = s -> head; n; n = n -> next)
+	{
+		if (n -> term -> term_type == LWASM_TERM_OPER)
+		{
+			if (n -> term -> value == LWASM_OPER_NEG
+				|| n -> term -> value == LWASM_OPER_COM
+				)
+			{
+				// unary operator
+				if (n -> prev && n -> prev -> term -> term_type == LWASM_TERM_INT)
+				{
+					// a unary operator we can resolve
+					// we do the op then remove the term "n" is pointing at
+					if (n -> term -> value == LWASM_OPER_NEG)
+					{
+						n -> prev -> term -> value = -(n -> prev -> term -> value);
+					}
+					else if (n -> term -> value == LWASM_OPER_COM)
+					{
+						n -> prev -> term -> value = ~(n -> prev -> term -> value);
+					}
+					n -> prev -> next = n -> next;
+					if (n -> next)
+						n -> next -> prev = n -> prev;
+					else
+						s -> tail = n -> prev;	
+					
+					lwasm_expr_term_free(n -> term);
+					lwasm_free(n);
+					break;
+				}
+			}
+			else
+			{
+				// binary operator
+				if (n -> prev && n -> prev -> prev && n -> prev -> term -> term_type == LWASM_TERM_INT && n -> prev -> prev -> term -> term_type == LWASM_TERM_INT)
+				{
+					// a binary operator we can resolve
+					switch (n -> term -> value)
+					{
+					case LWASM_OPER_PLUS:
+						n -> prev -> prev -> term -> value += n -> prev -> term -> value;
+						break;
+
+					case LWASM_OPER_MINUS:
+						n -> prev -> prev -> term -> value -= n -> prev -> term -> value;
+						break;
+
+					case LWASM_OPER_TIMES:
+						n -> prev -> prev -> term -> value *= n -> prev -> term -> value;
+						break;
+
+					case LWASM_OPER_DIVIDE:
+						if (n -> prev -> term -> value == 0)
+							return -1;
+						n -> prev -> prev -> term -> value /= n -> prev -> term -> value;
+						break;
+
+					case LWASM_OPER_MOD:
+						if (n -> prev -> term -> value == 0)
+							return -1;
+						n -> prev -> prev -> term -> value %= n -> prev -> term -> value;
+						break;
+
+					case LWASM_OPER_INTDIV:
+						if (n -> prev -> term -> value == 0)
+							return -1;
+						n -> prev -> prev -> term -> value /= n -> prev -> term -> value;
+						break;
+
+					case LWASM_OPER_BWAND:
+						n -> prev -> prev -> term -> value &= n -> prev -> term -> value;
+						break;
+
+					case LWASM_OPER_BWOR:
+						n -> prev -> prev -> term -> value |= n -> prev -> term -> value;
+						break;
+
+					case LWASM_OPER_BWXOR:
+						n -> prev -> prev -> term -> value ^= n -> prev -> term -> value;
+						break;
+
+					case LWASM_OPER_AND:
+						n -> prev -> prev -> term -> value = (n -> prev -> term -> value && n -> prev -> prev -> term -> value) ? 1 : 0;
+						break;
+
+					case LWASM_OPER_OR:
+						n -> prev -> prev -> term -> value = (n -> prev -> term -> value || n -> prev -> prev -> term -> value) ? 1 : 0;
+						break;
+
+					default:
+						// return error if unknown operator!
+						return -1;
+					}
+
+					// now remove the two unneeded entries from the stack
+					n -> prev -> prev -> next = n -> next;
+					if (n -> next)
+						n -> next -> prev = n -> prev -> prev;
+					else
+						s -> tail = n -> prev -> prev;	
+					
+					lwasm_expr_term_free(n -> term);
+					lwasm_expr_term_free(n -> prev -> term);
+					lwasm_free(n -> prev);
+					lwasm_free(n);
+					break;
+				}
+			}
+		}
+	}
+	// note for the terminally confused about dynamic memory and pointers:
+	// n will not be NULL even after the lwasm_free calls above so
+	// this test will still work (n will be a dangling pointer)
+	// (n will only be NULL if we didn't find any operators to simplify)
+	if (n)
+		goto next_iter;
+	
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/expr.h	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,119 @@
+/*
+expr.h
+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/>.
+*/
+
+/*
+Definitions for expression evaluator
+*/
+
+#ifndef __expr_h_seen__
+#define __expr_h_seen__
+
+#ifndef __expr_c_seen__
+#define __expr_E__ extern
+#else
+#define __expr_E__
+#endif
+
+// term types
+#define LWASM_TERM_NONE		0
+#define LWASM_TERM_OPER		1	// an operator
+#define LWASM_TERM_INT		2	// 32 bit signed integer
+#define LWASM_TERM_SYM		3	// symbol reference
+#define LWASM_TERM_SECBASE	4	// section base reference
+
+// operator types
+#define LWASM_OPER_NONE		0
+#define LWASM_OPER_PLUS		1	// +
+#define LWASM_OPER_MINUS	2	// -
+#define LWASM_OPER_TIMES	3	// *
+#define LWASM_OPER_DIVIDE	4	// /
+#define LWASM_OPER_MOD		5	// %
+#define LWASM_OPER_INTDIV	6	// \ (don't end line with \)
+#define LWASM_OPER_BWAND	7	// bitwise AND
+#define LWASM_OPER_BWOR		8	// bitwise OR
+#define LWASM_OPER_BWXOR	9	// bitwise XOR
+#define LWASM_OPER_AND		10	// boolean AND
+#define LWASM_OPER_OR		11	// boolean OR
+#define LWASM_OPER_NEG		12	// - unary negation (2's complement)
+#define LWASM_OPER_COM		13	// ^ unary 1's complement
+
+
+// term structure
+typedef struct lwasm_expr_term_s
+{
+	int term_type;		// type of term (see above)
+	char *symbol;		// name of a symbol
+	int value;			// value of the term (int) or operator number (OPER)
+} lwasm_expr_term_t;
+
+// type for an expression evaluation stack
+typedef struct lwasm_expr_stack_node_s lwasm_expr_stack_node_t;
+struct lwasm_expr_stack_node_s
+{
+	lwasm_expr_term_t		*term;
+	lwasm_expr_stack_node_t	*prev;
+	lwasm_expr_stack_node_t	*next;	
+};
+
+typedef struct lwasm_expr_stack_s
+{
+	lwasm_expr_stack_node_t *head;
+	lwasm_expr_stack_node_t *tail;
+} lwasm_expr_stack_t;
+
+__expr_E__ void lwasm_expr_term_free(lwasm_expr_term_t *t);
+__expr_E__ lwasm_expr_term_t *lwasm_expr_term_create_oper(int oper);
+__expr_E__ lwasm_expr_term_t *lwasm_expr_term_create_sym(char *sym);
+__expr_E__ lwasm_expr_term_t *lwasm_expr_term_create_int(int val);
+__expr_E__ lwasm_expr_term_t *lwasm_expr_term_create_secbase(void);
+__expr_E__ lwasm_expr_term_t *lwasm_expr_term_dup(lwasm_expr_term_t *t);
+
+__expr_E__ void lwasm_expr_stack_free(lwasm_expr_stack_t *s);
+__expr_E__ lwasm_expr_stack_t *lwasm_expr_stack_create(void);
+
+__expr_E__ void lwasm_expr_stack_push(lwasm_expr_stack_t *s, lwasm_expr_term_t *t);
+__expr_E__ lwasm_expr_term_t *lwasm_expr_stack_pop(lwasm_expr_stack_t *s);
+
+/*
+Evaluate an expression. The result is an lwasm_expr_stack_t pointer. If the
+expression evaluates to a constant result, the stack will contain exactly one
+value which will be a constant. Otherwise, the stack will contain the
+expression with all operations that can be evaluated completely evaluated.
+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, lwasm_expr_stack_t *(*sfunc)(char *sym, void *state), void *state);
+
+// simplify expression
+__expr_E__ int lwasm_expr_reval(lwasm_expr_stack_t *s, lwasm_expr_stack_t *(*sfunc)(char *sym, void *state), void *state);
+
+// useful macros
+// is the expression "simple" (one term)?
+#define lwasm_expr_is_simple(s) ((s) -> head == (s) -> tail)
+
+// is the expression constant?
+#define lwasm_expr_is_constant(s) (lwasm_expr_is_simple(s) && (!((s) -> head) || (s) -> head -> term -> term_type == LWASM_TERM_INT))
+
+// get the constant value of an expression or 0 if not constant
+#define lwasm_expr_get_value(s) (lwasm_expr_is_constant(s) ? ((s) -> head ? (s) -> head -> term -> value : 0) : 0)
+
+#undef __expr_E__
+
+#endif // __expr_h_seen__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_bitbit.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,137 @@
+/*
+insn_bitbit.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 inherent mode instructions
+*/
+
+#define __insn_bitbit_c_seen__
+
+#include <stdlib.h>
+
+#include "lwasm.h"
+#include "instab.h"
+#include "expr.h"
+
+// these instructions cannot tolerate external references
+OPFUNC(insn_bitbit)
+{
+	int r;
+	lwasm_expr_stack_t *s;
+	int v1;
+	int tv;
+
+	lwasm_emitop(as, l, instab[opnum].ops[0]);
+	
+	r = toupper(*(*p)++);
+	if (r == 'A')
+		r = 1;
+	else if (r == 'B')
+		r = 2;
+	else if (r == 'C' && toupper(**p) == 'C')
+	{
+		r = 0;
+		(*p)++;
+	}
+	else
+	{
+		register_error(as, l, 1, "Bad register");
+		return;
+	}
+	if (*(*p)++ != ',')
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	s = lwasm_evaluate_expr(as, l, *p, NULL, 0);
+	if (!s)
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	if (!lwasm_expr_is_constant(s))
+	{
+		register_error(as, l, 2, "Incomplete reference");
+	}
+	v1 = lwasm_expr_get_value(s);
+	lwasm_expr_stack_free(s);
+	if (v1 < 0 || v1 > 7)
+	{
+		register_error(as, l, 2, "Invalid bit number");
+		v1 = 0;
+	}
+	if (*(*p)++ != ',')
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	r = (r << 6) | (v1 << 3);
+
+	s = lwasm_evaluate_expr(as, l, *p, NULL, 0);
+	if (!s)
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	if (!lwasm_expr_is_constant(s))
+	{
+		register_error(as, l, 1, "Incomplete reference");
+	}
+	v1 = lwasm_expr_get_value(s);
+	lwasm_expr_stack_free(s);
+	if (v1 < 0 || v1 > 7)
+	{
+		register_error(as, l, 2, "Invalid bit number");
+		v1 = 0;
+	}
+	if (*(*p)++ != ',')
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	r |= v1;
+	
+	lwasm_emit(as, l, r);
+			
+	// ignore base page address modifier
+	if (**p == '<')
+		(*p)++;
+			
+	s = lwasm_evaluate_expr(as, l, *p, NULL, 0);
+	if (!s)
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	if (!lwasm_expr_is_constant(s))
+	{
+		register_error(as, l, 1, "Incomplete reference");
+	}
+	v1 = lwasm_expr_get_value(s);
+	lwasm_expr_stack_free(s);
+	v1 &= 0xFFFF;
+
+	tv = v1 - ((as -> dpval) << 8);
+	if (tv > 0xFF || tv < 0)
+	{
+		register_error(as, l, 2, "Byte overflow");
+	}
+	lwasm_emit(as, l, tv & 0xff);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_gen.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,228 @@
+/*
+insn_gen.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/>.
+
+Contains code for parsing general addressing modes (IMM+DIR+EXT+IND)
+*/
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "lwasm.h"
+#include "instab.h"
+#include "expr.h"
+
+extern void insn_indexed_aux(asmstate_t *as, lwasm_line_t *l, const char **p, int *b1, int *b2, int *b3);
+
+// "extra" is required due to the way OIM, EIM, TIM, and AIM work
+void insn_gen_aux(asmstate_t *as, lwasm_line_t *l, char **optr, int opnum, int extra)
+{
+	int b1 = -1, b2 = -1, b3 = -1;
+
+	const char *optr2;
+	int v1, tv, rval;
+	lwasm_expr_stack_t *s;
+	int f8 = 0;
+	int f16 = 0;
+	int isdp = 0;
+
+	optr2 = *optr;
+	while (*optr2 && !isspace(*optr2) && *optr2 != ',') optr2++
+		/* do nothing */ ;
+
+	if (*optr2 != ',' && **optr != '[')
+	{
+		// not indexed
+		if (l -> fsize == 1)
+			f8 = 1;
+		else if (l -> fsize == 2)
+			f16 = 1;
+
+		if (**optr == '<')
+		{
+			(*optr)++;
+			f8 = 1;
+		}
+		else if (**optr == '>')
+		{
+			(*optr)++;
+			f16 = 1;
+		}
+		rval = lwasm_expr_result2(as, l, optr, 0, &v1, 0);
+		if (rval != 0)
+		{
+			f16 = 1;
+			v1 = 0;
+			l -> fsize = 2;
+		}
+
+		if (((v1 >> 8) & 0xff) == (as -> dpval & 0xff))
+			isdp = 1;
+		
+		// disallow non-explicit DP in obj target
+		if (as -> outformat == OUTPUT_OBJ && !f8)
+			f16 = 1;
+	
+		if (f8 || (!f16 && isdp))
+		{
+			v1 = v1 & 0xffff;
+			tv = v1 - ((as -> dpval) << 8);
+			if (tv < 0 || tv > 0xff)
+			{
+				register_error(as, l, 2, "Byte overflow");
+			}
+			v1 = v1 & 0xff;
+			lwasm_emitop(as, l, instab[opnum].ops[0]);
+			if (extra != -1)
+				lwasm_emit(as, l, extra);
+			lwasm_emit(as, l, v1 & 0xff);
+			return;
+		}
+		else
+		{
+			// everything else is 16 bit....
+			lwasm_emitop(as, l, instab[opnum].ops[2]);
+			if (extra != -1)
+				lwasm_emit(as, l, extra);
+			l -> relocoff = as -> addr - l -> codeaddr;
+			lwasm_emit(as, l, v1 >> 8);
+			lwasm_emit(as, l, v1 & 0xff);
+			return;
+		}
+	}	
+
+	lwasm_emitop(as, l, instab[opnum].ops[1]);
+	if (extra != -1)
+		lwasm_emit(as, l, extra);
+	insn_indexed_aux(as, l, (const char **)optr, &b1, &b2, &b3);
+	if (b1 != -1)
+		lwasm_emit(as, l, b1);
+	if (b2 != -1)
+		lwasm_emit(as, l, b2);
+	if (b3 != -1)
+		lwasm_emit(as, l, b3);
+	return;
+}
+
+// the various insn_gen? functions have an immediate mode of ? bits
+OPFUNC(insn_gen0)
+{
+	if (**p == '#')
+	{
+		register_error(as, l, 1, "Immediate mode not allowed");
+		return;
+	}
+	
+	// handle non-immediate
+	insn_gen_aux(as, l, p, opnum, -1);
+}
+
+OPFUNC(insn_gen8)
+{
+	int rval;
+	int r;
+	
+	if (**p == '#')
+	{
+		lwasm_emitop(as, l, instab[opnum].ops[3]);
+		(*p)++;
+		r = lwasm_expr_result2(as, l, p, 0, &rval, 0);
+		if (r != 0)
+			rval = 0;
+		if (r == 1 && as -> passnum == 2)
+			register_error(as, l, 2, "Illegal external or intersegment reference");
+		lwasm_emit(as, l, rval & 0xff);
+		return;
+	}
+	
+	insn_gen_aux(as, l, p, opnum, -1);
+}
+
+OPFUNC(insn_gen16)
+{
+	int rval, r;
+	
+	if (**p == '#')
+	{
+		lwasm_emitop(as, l, instab[opnum].ops[3]);
+		(*p)++;
+
+		r = lwasm_expr_result2(as, l, p, 0, &rval, 0);
+		if (r != 0)
+			rval = 0;
+		if (r == 1 && as -> passnum == 2)
+		{
+			l -> relocoff = as -> addr - l -> codeaddr;
+		}
+		lwasm_emit(as, l, (rval >> 8) & 0xff);
+		lwasm_emit(as, l, rval & 0xff);
+		return;
+	}
+	
+	insn_gen_aux(as, l, p, opnum, -1);
+}
+
+OPFUNC(insn_gen32)
+{
+	int r, rval;
+	
+	if (**p == '#')
+	{
+		lwasm_emitop(as, l, instab[opnum].ops[3]);
+		(*p)++;
+
+		r = lwasm_expr_result2(as, l, p, 0, &rval, 0);
+		if (r != 0)
+			rval = 0;
+		if (r == 1 && as -> passnum == 2)
+		{
+			register_error(as, l, 2, "Illegal external or intersegment reference");
+		}
+
+		lwasm_emit(as, l, (rval >> 24) & 0xff);
+		lwasm_emit(as, l, (rval >> 16) & 0xff);
+		lwasm_emit(as, l, (rval >> 8) & 0xff);
+		lwasm_emit(as, l, rval & 0xff);
+		return;
+	}
+	
+	insn_gen_aux(as, l, p, opnum, -1);
+}
+
+OPFUNC(insn_imm8)
+{
+	int r, rval;
+	
+	if (**p == '#')
+	{
+		lwasm_emitop(as, l, instab[opnum].ops[0]);
+		(*p)++;
+
+		r = lwasm_expr_result2(as, l, p, 0, &rval, 0);
+		if (r != 0)
+			rval = 0;
+		if (r == 1 && as -> passnum == 2)
+			register_error(as, l, 2, "Illegal external or intersegment reference");
+
+		if (rval < -128 || rval > 255)
+			register_error(as, l, 2, "Byte overflow");
+		lwasm_emit(as, l, rval & 0xff);
+		return;
+	}
+
+	register_error(as, l, 1, "Bad operand");	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_indexed.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,443 @@
+/*
+insn_indexed.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 indexed mode instructions
+*/
+
+#define __insn_indexed_c_seen__
+
+#include <ctype.h>
+#include <string.h>
+
+#include "lwasm.h"
+#include "instab.h"
+#include "expr.h"
+
+void insn_indexed_aux(asmstate_t *as, lwasm_line_t *l, const char **p, int *b1, int *b2, int *b3)
+{
+	static const char *regs = "X  Y  U  S  W  PCRPC ";
+	static const struct { char *opstr; int pb; } simpleindex[] =
+	{
+		{",x", 0x84},		{",y", 0xa4},		{",u", 0xc4},		{",s", 0xe4},
+		{",x+", 0x80},		{",y+", 0xa0},		{",u+", 0xc0},		{",s+", 0xe0},
+		{",x++", 0x81},		{",y++", 0xa1},		{",u++", 0xc1},		{",s++", 0xe1},
+		{",-x", 0x82},		{",-y", 0xa2},		{",-u", 0xc2},		{",-s", 0xe2},
+		{",--x", 0x83},		{",--y", 0xa3},		{",--u", 0xc3},		{",--s", 0xe3},
+		{"a,x", 0x86},		{"a,y", 0xa6},		{"a,u", 0xc6},		{"a,s", 0xe6},
+		{"b,x", 0x85},		{"b,y", 0xa5},		{"b,u", 0xc5},		{"b,s", 0xe5},
+		{"e,x", 0x87},		{"e,y", 0xa7},		{"e,u", 0xc7},		{"e,s", 0xe7},
+		{"f,x",	0x8a},		{"f,y",	0xaa},		{"f,u", 0xca},		{"f,s", 0xea},
+		{"d,x", 0x8b},		{"d,y", 0xab},		{"d,u", 0xcb},		{"d,s", 0xed},
+		{"w,x", 0x8e},		{"w,y", 0xae},		{"w,u", 0xce},		{"w,s", 0xee},
+		{",w", 0x8f},							{",w++", 0xcf},		{",--w", 0xef},
+		
+		{"[,x]", 0x94},		{"[,y]", 0xb4},		{"[,u", 0xd4},		{"[,s]", 0xf4},
+		{"[,x++]", 0x91},	{"[,y++]", 0xb1},	{"[,u++]", 0xd1},	{"[,s++]", 0xf1},
+		{"[,--x]", 0x93},	{"[,--y]", 0xb3},	{"[,--u]", 0xd3},	{"[,--s]", 0xf3},
+		{"[a,x]", 0x96},	{"[a,y]", 0xb6},	{"[a,u]", 0xd6},	{"[a,s]", 0xf6},
+		{"[b,x]", 0x95},	{"[b,y]", 0xb5},	{"[b,u]", 0xd5},	{"[b,s]", 0xf5},
+		{"[e,x]", 0x97},	{"[e,y]", 0xb7},	{"[e,u]", 0xd7},	{"[e,s]", 0xf7},
+		{"[f,x]", 0x9a},	{"[f,y]", 0xba},	{"[f,u]", 0xda},	{"[f,s]", 0xfa},
+		{"[d,x]", 0x9b},	{"[d,y]", 0xbb},	{"[d,u]", 0xdb},	{"[d,s]", 0xfd},
+		{"[w,x]", 0x9e},	{"[w,y]", 0xbe},	{"[w,u]", 0xde},	{"[w,s]", 0xfe},
+		{"[,w]", 0x90},							{"[,w++]", 0xd0},	{"[,--w]", 0xf0},
+		
+		{ "", -1 }
+	};
+	char stbuf[25];
+	int i, j, rn;
+	int f8 = 0, f16 = 0, f0 = 0;
+	int r, v;
+	int indir = 0;
+	int fs8 = 0, fs16 = 0;
+	
+	// initialize output bytes
+	*b1 = *b2 = *b3 = -1;
+	
+	// fetch out operand for lookup
+	for (i = 0; i < 24; i++)
+	{
+		if (*((*p) + i) && !isspace(*((*p) + i)))
+			stbuf[i] = *((*p) + i);
+		else
+			break;
+	}
+	stbuf[i] = '\0';
+	
+	// now look up operand in "simple" table
+	if (!*((*p) + i) || isspace(*((*p) + i)))
+	{
+		// do simple lookup
+		for (j = 0; simpleindex[j].opstr[0]; j++)
+		{
+			if (!strcasecmp(stbuf, simpleindex[j].opstr))
+				break;
+		}
+		if (simpleindex[j].opstr[0])
+		{
+			*b1 = simpleindex[j].pb;
+			(*p) += i;
+			return;
+		}
+	}
+
+	// now do the "hard" ones
+
+	// is it indirect?
+	if (**p == '[')
+	{
+		indir = 1;
+		(*p)++;
+	}
+	
+	// look for a "," - all indexed modes have a "," except extended indir
+	rn = 0;
+	for (i = 0; (*p)[i] && !isspace((*p)[i]); i++)
+	{
+		if ((*p)[i] == ',')
+		{
+			rn = 1;
+			break;
+		}
+	}
+
+	// if no "," and indirect, do extended indir
+	if (!rn && indir)
+	{
+		// extended indir
+		*b1 = 0x9f;
+		*b2 = 0;
+		*b3 = 0;
+		r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0);
+		if (r < 0)
+		{
+			return;
+		}
+		if (**p != ']')
+		{
+			register_error(as, l, 1, "Bad operand");
+			return;
+		}
+		
+		(*p)++;
+		
+		if (r == 1 && as -> passnum == 2)
+		{
+			l -> relocoff = as -> addr - l -> codeaddr + 1;
+		}
+		
+		*b2 = (v >> 8) & 0xff;
+		*b3 = v & 0xff;
+		return;
+	}
+
+	// if we've previously forced the offset size, make a note of it
+	if (l -> fsize == 1)
+		f8 = 1;
+	else if (l -> fsize == 2)
+		f16 = 1;
+
+	if (**p == '<')
+	{
+		fs8 = 1;
+		(*p)++;
+	}
+	else if (**p == '>')
+	{
+		fs16 = 1;
+		(*p)++;
+	}
+
+	if (**p == '0' && *(*p+1) == ',')
+	{
+		f0 = 1;
+	}
+	
+	// now we have to evaluate the expression
+	r = lwasm_expr_result2(as, l, (char **)p, 0, &v, 0);
+	if (r < 0)
+	{
+		return;
+	}
+	// now look for a comma; if not present, explode
+	if (*(*p)++ != ',')
+	{
+		// syntax error; force 0 bit
+		*b1 = 00;
+		l -> fsize = 0;
+		return;
+	}
+	
+	// now get the register
+	rn = lwasm_lookupreg3(regs, p);
+	if (rn < 0)
+	{
+		*b1 = 0;
+		l -> fsize = 0;
+		register_error(as, l, 1, "Bad register");
+		return;
+	}
+	
+	if (indir)
+	{
+		if (**p != ']')
+		{
+			register_error(as, l, 1, "Bad operand");
+			l -> fsize = 0;
+			*b1 = 0;
+			return;
+		}
+		else
+			(*p)++;
+	}
+	
+	// incomplete reference on pass 1 forces 16 bit
+	if (r == 1 && as -> passnum == 1)
+	{
+		f16 = 1;
+		l -> fsize = 2;
+	}
+	
+	// incomplete reference on pass 2 needs relocoff set
+	if (r == 1 && as -> passnum == 2)
+	{
+		l -> relocoff = as -> addr - l -> codeaddr + 1;
+	}
+
+	// nnnn,W is only 16 bit (or 0 bit)
+	if (rn == 4)
+	{
+		if (f8)
+		{
+			register_error(as, l, 1, "n,W cannot be 8 bit");
+			l -> fsize = 0;
+			*b1 = 0;
+			return;
+		}
+		// note: set f16 above for incomplete references
+		// also set reloc offset
+		if (!f16 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE) && v == 0)
+		{
+			if (indir)
+				*b1 = 0x90;
+			else
+				*b1 = 0x8f;
+			return;
+		}
+		
+		if (indir)
+			*b1 = 0xb0;
+		else
+			*b1 = 0xcf;
+		*b2 = (v >> 8) & 0xff;
+		*b3 = v & 0xff;
+		return;
+	}
+	
+	// set indir to correct bit value
+	if (indir) indir = 0x10;
+	
+	// PCR? then we have PC relative addressing (like B??, LB??)
+	if (rn == 5)
+	{
+		lwasm_expr_term_t *t;
+		// external references are handled exactly the same as for
+		// relative addressing modes
+		// on pass 1, adjust the expression for a subtraction of the
+		// current address
+		
+		// need to re-evaluate the expression with "SECTCONST"...
+		r = lwasm_expr_result2(as, l, (char **)p, EXPR_SECTCONST | EXPR_REEVAL, &v, 0);
+		if (r != 0)
+			v = 0;
+		if (as -> passnum == 1)
+		{
+			l -> fsize = 0;
+		}
+		f8 = f16 = 0;
+		if (r == 1 && as -> passnum == 1 && !fs8)
+		{
+			l -> fsize = 2;	
+			f16 = 1;
+		}
+		if (fs8)
+			f8 = 1;
+		if (fs16)
+			f16 = 1;
+		if (l -> fsize == 2)
+			f16 = 1;
+		else if (l -> fsize == 1)
+			f8 = 1;
+		if (as -> passnum == 1)
+			v -= as -> addr;
+		
+		// we have a slight problem here
+		// PCR based on current insn loc is really
+		// -125 <= offset <= +130 (8 bit offset)
+		// NOTE: when we are called, we already have the opcode emitted
+		// so we only need to worry about the size of the operand
+		// hence the 2 and 3 magic numbers below instead of 3 and 4
+		// (and that also avoids errors with two byte opcodes, etc)
+		if (f8 || (!f16 && v >= -125 && v <= 130))
+		{
+			f8 = 1;
+			l -> fsize = 1;
+			*b1 = indir | 0x8C;
+			if (as -> passnum == 1)
+				v -= 2;
+			if (v < -128 || v > 127)
+				register_error(as, l, 2, "Byte overflow");
+			*b2 = v & 0xff;
+			if (r != 0 && as -> passnum == 2)
+			{
+				register_error(as, l, 2, "Illegal incomplete reference");
+			}
+			goto finpcr;
+		}
+		
+		// anything else is 16 bit offset
+		// need 16 bit
+		
+		l -> fsize = 2;
+		*b1 = indir | 0x8D;
+		if (as -> passnum == 1)
+			v -= 3;
+		*b2 = (v >> 8) & 0xff;
+		*b3 = v & 0xff;
+		if (as -> passnum == 2 && r == 1)
+		{
+			t = lwasm_expr_term_create_secbase();
+			lwasm_expr_stack_push(l -> exprs[0], t);
+			lwasm_expr_term_free(t);
+			t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS);
+			lwasm_expr_stack_push(l -> exprs[0], t);
+			lwasm_expr_term_free(t);
+		}
+
+	finpcr:
+		if (as -> passnum == 1)
+		{
+			// need to adjust the expression
+			if (l -> exprs[0])
+			{
+				t = lwasm_expr_term_create_int(as -> addr + (f8 ? 2 : 3));
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+				t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS);
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+			}
+			else
+			{
+				l -> exprvals[0] -= as -> addr + (f8 ? 2 : 3);
+			}
+		}
+		return;
+	}
+	if (fs16)
+		f16 = 1;
+	if (fs8)
+		f8 = 1;
+
+	if (f8 && r != 0)
+	{
+		register_error(as, l, 2, "Illegal external or inter-section reference");
+		r = 0;
+		v = 0;
+	}
+
+	// constant offset from PC (using PC as regular register :) )
+	// FIXME: handle external references intelligently
+	if (rn == 6)
+	{
+		if (f8 || (!f16 && v >= -128 && v <= 127))
+		{
+			*b1 = indir | 0x8C;
+			if (v < -128 || v > 127)
+				register_error(as, l, 2, "Byte overflow");
+			*b2 = v & 0xff;
+			return;
+		}
+		
+		// everything else must be 16 bit
+		// need 16 bit
+		*b1 = indir | 0x8D;
+		*b2 = (v >> 8) & 0xff;
+		*b3 = v & 0xff;
+		return;
+	}
+
+	// we only have to deal with x,y,u,s here
+	if (!f8 && !f16 && v >= -16 && v <= 15)
+	{
+		// zero offset going to ,R?
+		if (v == 0 && !f0 && !(as -> pragmas & PRAGMA_NOINDEX0TONONE))
+		{
+			*b1 = rn << 5 | indir | 0x80 | 0x04;
+			return;
+		}
+		
+		// no 5 bit on indirect
+		if (indir)
+		{
+			f8 = 1;
+			l -> fsize = 1;
+			goto no5bit;
+		}
+		
+		// 5 bit addressing
+		*b1 = rn << 5 | (v & 0x1F);
+		return;
+	}
+
+no5bit:
+	if (f16 || (!f8 && (v < -128 || v > 127)))
+	{
+		// must be a 16 bit offset here
+		*b1 = rn << 5 | indir | 0x80 | 0x09;
+		*b2 = (v >> 8) & 0xff;
+		*b3 = v & 0xff;
+		return;
+	}
+	
+	// if we're here, we have an 8 bit offset
+	// note: cannot get here if incomplete reference detected above
+	*b1 = rn << 5 | indir | 0x80 | 0x08;
+	if (v < -128 || v > 127)
+		register_error(as, l, 2, "Byte overflow");
+	*b2 = v & 0xff;
+	return;
+}
+
+OPFUNC(insn_indexed)
+{
+	int b1, b2, b3;
+	
+	lwasm_emitop(as, l, instab[opnum].ops[0]);
+
+	insn_indexed_aux(as, l, (const char **)p, &b1, &b2, &b3);
+	if (b1 != -1)
+		lwasm_emit(as, l, b1);
+	if (b2 != -1)
+		lwasm_emit(as, l, b2);
+	if (b3 != -1)
+		lwasm_emit(as, l, b3);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_inh.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,33 @@
+/*
+insn_inh.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 inherent mode instructions
+*/
+
+#define __insn_inh_c_seen__
+
+#include "lwasm.h"
+#include "instab.h"
+
+OPFUNC(insn_inh)
+{
+	lwasm_emitop(as, l, instab[opnum].ops[0]);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_logicmem.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,63 @@
+/*
+insn_logicmem.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/>.
+
+Contains code for handling logic/mem instructions
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "lwasm.h"
+#include "instab.h"
+#include "expr.h"
+
+extern void insn_gen_aux(asmstate_t *as, lwasm_line_t *l, char **optr, int opnum, int extra);
+
+// for aim, oim, eim, tim
+// the immediate operand must be constant on pass 2
+OPFUNC(insn_logicmem)
+{
+	int rval, v1;
+	const char *p2;
+	lwasm_expr_stack_t *s;
+	
+	if (**p == '#')
+		(*p)++;
+	
+	rval = lwasm_expr_result2(as, l, p, 0, &v1, 1);
+	if (rval != 0)
+		v1 = 0;
+	if (rval == 1 && as -> passnum == 2)
+		register_error(as, l, 2, "Illegal external or intersegment reference");
+
+	if (v1 < -128 || v1 > 255)
+		register_error(as, l, 2, "Byte overflow");
+	
+	if (**p != ',' && **p != ';')
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	
+	(*p)++;
+
+	// now we have a general addressing mode - call for it
+	insn_gen_aux(as, l, p, opnum, v1 & 0xff);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_rel.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,123 @@
+/*
+insn_rel.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 relative mode instructions
+*/
+
+#define __insn_rel_c_seen__
+
+#include <stdlib.h>
+
+#include "expr.h"
+#include "lwasm.h"
+#include "instab.h"
+
+OPFUNC(insn_rel8)
+{
+	int v;
+	lwasm_expr_term_t *t;
+	int r;
+	
+	lwasm_emitop(as, l, instab[opnum].ops[0]);
+
+	if ((r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST, &v, 0)) < 0)
+		v = 0;
+	else
+	{
+		if (as -> passnum == 1)
+		{
+			// need to adjust the expression
+			if (l -> exprs[0])
+			{
+				t = lwasm_expr_term_create_int(as -> addr + 1);
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+				t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS);
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+			}
+			else
+			{
+				l -> exprvals[0] -= as -> addr + 1;
+			}
+		}
+	}
+	if (r == 1 && as -> passnum == 2)
+	{
+		register_error(as, l, 2, "Illegal external or intersegment reference");
+	}
+	if (v < -128 || v > 127)
+		register_error(as, l, 2, "Byte overflow");
+	lwasm_emit(as, l, v & 0xff);
+}
+
+/*
+External and intersegment references are adjusted for the relative addressing mode
+by adjusting the expression on pass 1 and then treated as absolute references later
+*/
+OPFUNC(insn_rel16)
+{
+	int v;
+	int r;
+	lwasm_expr_term_t *t;
+	
+	lwasm_emitop(as, l, instab[opnum].ops[0]);
+	
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST, &v, 0);
+	if (r < 0)
+		v = 0;
+	else
+	{
+		if (as -> passnum == 1)
+		{
+			// need to adjust the expression
+			if (l -> exprs[0])
+			{
+				t = lwasm_expr_term_create_int(as -> addr + 2);
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+				t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS);
+				lwasm_expr_stack_push(l -> exprs[0], t);
+				lwasm_expr_term_free(t);
+			}
+			else
+			{
+				l -> exprvals[0] -= as -> addr + 2;
+			}
+		}
+	}
+	if (as -> passnum == 2 && r == 1)
+	{
+		// since we have a reference outside this section, add
+		// a subtract of the section base to get the right value
+		// upon linking
+		t = lwasm_expr_term_create_secbase();
+		lwasm_expr_stack_push(l -> exprs[0], t);
+		lwasm_expr_term_free(t);
+		t = lwasm_expr_term_create_oper(LWASM_OPER_MINUS);
+		lwasm_expr_stack_push(l -> exprs[0], t);
+		lwasm_expr_term_free(t);
+
+		l -> relocoff = as -> addr - l -> codeaddr;
+	}
+	lwasm_emit(as, l, (v >> 8) & 0xff);
+	lwasm_emit(as, l, v & 0xff);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_rlist.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,62 @@
+/*
+insn_rlist.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 inherent mode instructions
+*/
+
+#define __insn_rlist_c_seen__
+
+#include "lwasm.h"
+#include "instab.h"
+
+OPFUNC(insn_rlist)
+{
+	int rb = 0;
+	int rn;
+	static const char *regs = "CCA B DPX Y U PCD S ";
+
+	lwasm_emitop(as, l, instab[opnum].ops[0]);
+	while (**p && !isspace(**p))
+	{
+		rn = lwasm_lookupreg2(regs, p);
+		if (rn < 0)
+		{
+			register_error(as, l, 1, "Bad register '%s'", *p);
+			lwasm_emit(as, l, 0);
+			return;
+		}
+		if (**p && **p != ',' && !isspace(**p))
+		{
+			register_error(as, l, 1, "Bad operand");
+			lwasm_emit(as, l, 0);
+		}
+		if (**p == ',')
+			(*p)++;
+		if (rn == 8)
+			rn = 6;
+		else if (rn == 9)
+			rn = 0x40;
+		else
+			rn = 1 << rn;
+		rb |= rn;
+	}
+	lwasm_emit(as, l, rb);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_rtor.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,56 @@
+/*
+insn_rtor.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 register to register mode instructions
+*/
+
+#define __insn_rtor_c_seen__
+
+#include "lwasm.h"
+#include "instab.h"
+
+OPFUNC(insn_rtor)
+{
+	int r0, r1;
+	static const char *regs = "D X Y U S PCW V A B CCDP0 0 E F ";
+	
+	lwasm_emitop(as, l, instab[opnum].ops[0]);
+	// register to register (r0,r1)
+	// registers are in order:
+	// D,X,Y,U,S,PC,W,V
+	// A,B,CC,DP,0,0,E,F
+	r0 = lwasm_lookupreg2(regs, p);
+	if (r0 < 0 || *(*p)++ != ',')
+	{
+		register_error(as, l, 1, "Bad operand");
+		r0 = r1 = 0;
+	}
+	else
+	{
+		r1 = lwasm_lookupreg2(regs, p);
+		if (r1 < 0)
+		{
+			register_error(as, l, 1, "Bad operand");
+			r0 = r1 = 0;
+		}
+	}
+	lwasm_emit(as, l, (r0 << 4) | r1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/insn_tfm.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,111 @@
+/*
+insn_tfm.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 inherent mode instructions
+*/
+
+#define __insn_tfm_c_seen__
+
+#include <ctype.h>
+#include <string.h>
+
+#include "lwasm.h"
+#include "instab.h"
+
+OPFUNC(insn_tfm)
+{
+	static const char *reglist = "DXYUS   AB  00EF";
+	int r0, r1;
+	char *c;
+	int tfm = 0;
+			
+	c = strchr(reglist, toupper(*(*p)++));
+	if (!c)
+	{
+		register_error(as, l, 1, "Unknown operation");
+		return;
+	}
+	r0 = c - reglist;
+	if (**p == '+')
+	{
+		(*p)++;
+		tfm = 1;
+	}
+	else if (**p == '-')
+	{
+		(*p)++;
+		tfm = 2;
+	}
+	if (*(*p)++ != ',')
+	{
+		register_error(as, l, 1, "Unknown operation");
+		return;
+	}
+	c = strchr(reglist, toupper(*(*p)++));
+	if (!c)
+	{
+		register_error(as, l, 1, "Unknown operation");
+		return;
+	}
+	r1 = c - reglist;
+
+	if (**p == '+')
+	{
+		(*p)++;
+		tfm |= 4;
+	}
+	else if (**p == '-')
+	{
+		(*p)++;
+		tfm |= 8;
+	}
+	
+	if (**p && !isspace(**p))
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+			
+	// valid values of tfm here are:
+	// 1: r0+,r1 (2)
+	// 4: r0,r1+ (3)
+	// 5: r0+,r1+ (0)
+	// 10: r0-,r1- (1)
+	switch (tfm)
+	{
+	case 5: //r0+,r1+
+		lwasm_emitop(as, l, instab[opnum].ops[0]);
+		break;
+	case 10: //r0-,r1-
+		lwasm_emitop(as, l, instab[opnum].ops[1]);
+		break;
+	case 1: // r0+,r1
+		lwasm_emitop(as, l, instab[opnum].ops[2]);
+		break;
+	case 4: // r0,r1+
+		lwasm_emitop(as, l, instab[opnum].ops[3]);
+		break;
+	default:
+		register_error(as, l, 1, "Unknown operation");
+		return;
+	}
+	lwasm_emit(as, l, (r0 << 4) | r1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/instab.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,389 @@
+/*
+instab.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/>.
+
+
+Contains the instruction table for assembling code
+*/
+
+#include <stdlib.h>
+
+#define __instab_c_seen__
+#include "instab.h"
+
+extern OPFUNC(insn_inh);
+extern OPFUNC(insn_gen8);
+extern OPFUNC(insn_gen16);
+extern OPFUNC(insn_gen32);
+extern OPFUNC(insn_gen0);
+extern OPFUNC(insn_rtor);
+extern OPFUNC(insn_imm8);
+extern OPFUNC(insn_rel8);
+extern OPFUNC(insn_rel16);
+extern OPFUNC(insn_rlist);
+extern OPFUNC(insn_bitbit);
+extern OPFUNC(insn_logicmem);
+extern OPFUNC(insn_tfm);
+extern OPFUNC(insn_indexed);
+
+extern OPFUNC(pseudo_org);
+extern OPFUNC(pseudo_equ);
+extern OPFUNC(pseudo_rmb);
+extern OPFUNC(pseudo_rmd);
+extern OPFUNC(pseudo_rmq);
+extern OPFUNC(pseudo_zmb);
+extern OPFUNC(pseudo_zmd);
+extern OPFUNC(pseudo_zmq);
+extern OPFUNC(pseudo_include);
+extern OPFUNC(pseudo_end);
+extern OPFUNC(pseudo_align);
+extern OPFUNC(pseudo_error);
+extern OPFUNC(pseudo_fcc);
+extern OPFUNC(pseudo_fcs);
+extern OPFUNC(pseudo_fcn);
+extern OPFUNC(pseudo_fcb);
+extern OPFUNC(pseudo_fdb);
+extern OPFUNC(pseudo_fqb);
+extern OPFUNC(pseudo_ifne);
+extern OPFUNC(pseudo_ifeq);
+extern OPFUNC(pseudo_ifgt);
+extern OPFUNC(pseudo_ifge);
+extern OPFUNC(pseudo_iflt);
+extern OPFUNC(pseudo_ifle);
+extern OPFUNC(pseudo_else);
+extern OPFUNC(pseudo_endc);
+extern OPFUNC(pseudo_macro);
+extern OPFUNC(pseudo_endm);
+extern OPFUNC(pseudo_setdp);
+extern OPFUNC(pseudo_set);
+extern OPFUNC(pseudo_section);
+extern OPFUNC(pseudo_endsection);
+extern OPFUNC(pseudo_pragma);
+extern OPFUNC(pseudo_starpragma);
+extern OPFUNC(pseudo_extern);
+extern OPFUNC(pseudo_export);
+extern OPFUNC(pseudo_ifdef);
+extern OPFUNC(pseudo_ifndef);
+
+instab_t instab[] =
+{
+	{ "abx",	{	0x3a,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "adca",	{	0x99,	0xa9,	0xb9,	0x89	},	insn_gen8 },
+	{ "adcb",	{	0xd9,	0xe9,	0xf9,	0xc9	},	insn_gen8 },
+	{ "adcd",	{	0x1099,	0x10a9,	0x10b9,	0x1089	},	insn_gen16 },
+	{ "adcr",	{	0x1031,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	{ "adda",	{	0x9b,	0xab,	0xbb,	0x8b	},	insn_gen8 },
+	{ "addb",	{	0xdb,	0xeb,	0xfb,	0xcb	},	insn_gen8 },
+	{ "addd",	{	0xd3,	0xe3,	0xf3,	0xc3	},	insn_gen16 },
+	{ "adde",	{	0x119b,	0x11ab,	0x11bb,	0x118b	},	insn_gen8 },
+	{ "addf",	{	0x11db,	0x11eb,	0x11fb,	0x11cb	},	insn_gen8 },
+	{ "addr",	{	0x1030,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	{ "addw",	{	0x109b,	0x10ab,	0x10bb,	0x108b	},	insn_gen16 },
+	{ "aim",	{	0x02,	0x62,	0x72,	-0x1	},	insn_logicmem },
+	{ "anda",	{	0x94,	0xa4,	0xb4,	0x84	},	insn_gen8 },
+	{ "andb",	{	0xd4,	0xe4,	0xf4,	0xc4	},	insn_gen8 },
+	{ "andcc",	{	0x1c,	-0x1,	-0x1,	0x1c	},	insn_imm8 },
+	{ "andd",	{	0x1094,	0x10a4,	0x10b4,	0x1084	},	insn_gen16 },
+	{ "andr",	{	0x1034,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	{ "asl",	{	0x08,	0x68,	0x78,	-0x1	},	insn_gen0 },
+	{ "asla",	{	0x48,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "aslb",	{	0x58,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "asld",	{	0x1048,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "asr",	{	0x07,	0x67,	0x77,	-0x1	},	insn_gen0 },
+	{ "asra",	{	0x47,	-0x1,	-0x1,	-0x1	}, 	insn_inh },
+	{ "asrb",	{	0x57,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "asrd",	{	0x1047,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	
+	{ "band",	{	0x1130,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
+	{ "bcc",	{	0x24,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bcs",	{	0x25,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "beor",	{	0x1134,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
+	{ "beq",	{	0x27,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bge",	{	0x2c,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bgt",	{	0x2e,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bhi",	{	0x22,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bhs",	{	0x24,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "biand",	{	0x1131,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
+	{ "bieor",	{	0x1135,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
+	{ "bior",	{	0x1133, -0x1,	-0x1,	-0x1	},	insn_bitbit },
+	{ "bita",	{	0x95,	0xa5,	0xb5,	0x85	},	insn_gen8 },
+	{ "bitb",	{	0xd5,	0xe5,	0xf5,	0xc5	},	insn_gen8 },
+	{ "bitd",	{	0x1095,	0x10a5,	0x10b5,	0x1085	},	insn_gen16 },
+	{ "bitmd",	{	0x113c, -0x1,	-0x1,	0x113c	},	insn_imm8 },
+	{ "ble",	{	0x2f,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "blo",	{	0x25,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bls",	{	0x23,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "blt",	{	0x2d,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bmi",	{	0x2b,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bne",	{	0x26, 	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bor",	{	0x1132,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
+	{ "bpl",	{	0x2a,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bra",	{	0x20,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "brn",	{	0x21,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bsr",	{	0x8d,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bvc",	{	0x28,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	{ "bvs",	{	0x29,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
+	
+	{ "clr",	{	0x0f,	0x6f,	0x7f,	-0x1	},	insn_gen0 },
+	{ "clra",	{	0x4f,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "clrb",	{	0x5f,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "clrd",	{	0x104f,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "clre",	{	0x114f,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "clrf",	{	0x115f,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "clrw",	{	0x105f,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "cmpa",	{	0x91,	0xa1,	0xb1,	0x81	},	insn_gen8 },
+	{ "cmpb",	{	0xd1,	0xe1,	0xf1,	0xc1	},	insn_gen8 },
+	{ "cmpd",	{	0x1093,	0x10a3,	0x10b3,	0x1083	},	insn_gen16 },
+	{ "cmpe",	{	0x1191,	0x11a1,	0x11b1,	0x1181	},	insn_gen8 },
+	{ "cmpf",	{	0x11d1,	0x11e1,	0x11f1,	0x11c1	},	insn_gen8 },
+	{ "cmpr",	{	0x1037,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	{ "cmps",	{	0x119c,	0x11ac,	0x11bc,	0x118c	},	insn_gen16 },
+	{ "cmpu",	{	0x1193,	0x11a3,	0x11b3,	0x1183	},	insn_gen16 },
+	{ "cmpw",	{	0x1091,	0x10a1,	0x10b1,	0x1081	},	insn_gen16 },
+	{ "cmpx",	{	0x9c,	0xac,	0xbc,	0x8c	}, 	insn_gen16 },
+	{ "cmpy",	{	0x109c,	0x10ac,	0x10bc,	0x108c	},	insn_gen16 },
+	{ "com",	{	0x03,	0x63,	0x73,	-0x1	},	insn_gen0 },
+	{ "coma",	{	0x43,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "comb",	{	0x53,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "comd",	{	0x1043,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "come",	{	0x1143,	-0x1, 	-0x1,	-0x1	},	insn_inh },
+	{ "comf", 	{	0x1153, -0x1,	-0x1,	-0x1	}, 	insn_inh },
+	{ "comw",	{	0x1053,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "cwai",	{	0x3c, 	-0x1,	-0x1,	-0x1	},	insn_imm8 },
+	
+	{ "daa",	{	0x19,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "dec",	{	0x0a,	0x6a,	0x7a,	-0x1	},	insn_gen0 },
+	{ "deca",	{	0x4a,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "decb",	{	0x5a,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "decd",	{	0x104a,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "dece",	{	0x114a,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "decf",	{	0x115a,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "decw",	{	0x105a,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "divd",	{	0x118d,	0x119d,	0x11ad,	0x11bd	},	insn_gen8 },
+	{ "divq",	{	0x118e,	0x119e,	0x11ae,	0x11be	},	insn_gen16 },
+
+	{ "eim",	{	0x05,	0x65,	0x75,	-0x1	},	insn_logicmem },
+	{ "eora",	{	0x98,	0xa8,	0xb8,	0x88	},	insn_gen8 },
+	{ "eorb",	{	0xd8,	0xe9,	0xf9,	0xc8	},	insn_gen8 },
+	{ "eord",	{	0x1098,	0x10a8,	0x10b8,	0x1088	},	insn_gen16 },
+	{ "eorr",	{	0x1036,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	{ "exg",	{	0x1e,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	
+	{ "inc",	{	0x0c,	0x6c,	0x7c,	-0x1	},	insn_gen0 },
+	{ "inca",	{	0x4c,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "incb",	{	0x5c,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "incd",	{	0x104c,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "ince",	{	0x114c,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "incf",	{	0x115c,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "incw",	{	0x105c,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	
+	{ "jmp",	{	0x0e,	0x6e,	0x7e,	-0x1	},	insn_gen0 },
+	{ "jsr",	{	0x9d,	0xad,	0xbd,	-0x1	}, 	insn_gen0 },
+	
+	{ "lbcc",	{	0x1024,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbcs",	{	0x1025,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbeq",	{	0x1027,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbge",	{	0x102c,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbgt",	{	0x102e,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbhi",	{	0x1022,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbhs",	{	0x1024,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lble",	{	0x102f,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lblo",	{	0x1025,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbls",	{	0x1023,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lblt",	{	0x102d, -0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbmi",	{	0x102b,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbne",	{	0x1026,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbpl",	{	0x102a,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbra",	{	0x16,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbrn",	{	0x1021,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbsr",	{	0x17,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbvc",	{	0x1028,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lbvs",	{	0x1029,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
+	{ "lda",	{	0x96,	0xa6,	0xb6,	0x86	},	insn_gen8 },
+	{ "ldb",	{	0xd6,	0xe6,	0xf6,	0xc6	},	insn_gen8 },
+	{ "ldbt",	{	0x1136,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
+	{ "ldd",	{	0xdc,	0xec,	0xfc,	0xcc	},	insn_gen16 },
+	{ "lde",	{	0x1196,	0x11a6,	0x11b6,	0x1186	},	insn_gen8 },
+	{ "ldf",	{	0x11d6,	0x11e6,	0x11f6,	0x11c6	},	insn_gen8 },
+	{ "ldq",	{	0x10dc,	0x10ec,	0x10fc,	0xcd	},	insn_gen32 },
+	{ "lds",	{	0x10de,	0x10ee,	0x10fe,	0x10ce	},	insn_gen16 },
+	{ "ldu",	{ 	0xde,	0xee,	0xfe,	0xce	},	insn_gen16 },
+	{ "ldw",	{	0x1096,	0x10a6,	0x10b6,	0x1086	},	insn_gen16 },
+	{ "ldx",	{	0x9e,	0xae,	0xbe,	0x8e	},	insn_gen16 },
+	{ "ldy",	{	0x109e,	0x10ae,	0x10be,	0x108e	},	insn_gen16 },
+	{ "ldmd",	{	0x113d, -0x1,	-0x1,	0x113d	},	insn_imm8 },
+	{ "leas",	{	0x32,	-0x1,	-0x1,	-0x1	},	insn_indexed },
+	{ "leau",	{	0x33,	-0x1,	-0x1,	-0x1	},	insn_indexed },
+	{ "leax",	{	0x30,	-0x1,	-0x1,	-0x1	},	insn_indexed },
+	{ "leay",	{	0x31,	-0x1,	-0x1,	-0x1	},	insn_indexed },
+	{ "lsl",	{	0x08,	0x68,	0x78,	-0x1	},	insn_gen0 },
+	{ "lsla",	{	0x48,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "lslb",	{	0x58,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "lsld",	{	0x1048,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "lsr",	{	0x04,	0x64,	0x74,	-0x1	},	insn_gen0 },
+	{ "lsra",	{	0x44,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "lsrb",	{	0x54,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "lsrd",	{	0x1044,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "lsrw",	{	0x1054,	-0x1,	-0x1,	-0x1	},	insn_inh },
+
+	{ "mul",	{	0x3d,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "muld",	{	0x118f,	0x119f,	0x11af,	0x11bf	},	insn_gen16 },
+	
+	{ "neg",	{	0x00,	0x60,	0x70,	-0x1	},	insn_gen0 },
+	{ "nega",	{	0x40,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "negb",	{	0x50,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "negd",	{	0x1040,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "nop",	{	0x12,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	
+	{ "oim",	{	0x01,	0x61,	0x71,	-0x1	},	insn_logicmem },
+	{ "ora",	{	0x9a,	0xaa,	0xba,	0x8a	},	insn_gen8 },
+	{ "orb",	{	0xda,	0xea,	0xfa,	0xca	},	insn_gen8 },
+	{ "orcc",	{	0x1a,	-0x1,	-0x1,	0x1a	},	insn_imm8 },
+	{ "ord",	{	0x109a,	0x10aa,	0x10ba,	0x108a	},	insn_gen16 },
+	{ "orr",	{	0x1035,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	
+	{ "pshs",	{	0x34,	-0x1,	-0x1,	-0x1	},	insn_rlist },
+	{ "pshsw",	{	0x1038,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "pshu",	{	0x36,	-0x1,	-0x1,	-0x1	},	insn_rlist },
+	{ "pshuw",	{	0x103a,	-0x1,	-0x1,	-0x1	},	insn_inh	},
+	{ "puls",	{	0x35,	-0x1,	-0x1,	-0x1	},	insn_rlist },
+	{ "pulsw",	{	0x1039,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "pulu",	{	0x37,	-0x1,	-0x1,	-0x1	},	insn_rlist },
+	{ "puluw",	{	0x103b,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	
+	{ "rol",	{	0x09,	0x69,	0x79,	-0x1	},	insn_gen0 },
+	{ "rola",	{	0x49,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "rolb",	{	0x59,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "rold",	{	0x1049,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "rolw",	{	0x1059,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "ror",	{	0x06,	0x66,	0x76,	-0x1	},	insn_gen0 },
+	{ "rora",	{	0x46,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "rorb",	{	0x56,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "rord",	{	0x1046,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "rorw",	{	0x1056,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "rti",	{	0x3b,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "rts",	{	0x39,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	
+	{ "sbca",	{	0x92,	0xa2,	0xb2,	0x82	},	insn_gen8 },
+	{ "sbcb",	{	0xd2,	0xe2,	0xf2,	0xc2	},	insn_gen8 },
+	{ "sbcd",	{	0x1092,	0x10a2,	0x10b2,	0x1082	},	insn_gen16 },
+	{ "sbcr",	{	0x1033,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	{ "sex",	{	0x1d,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "sexw",	{	0x14,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "sta",	{	0x97,	0xa7,	0xb7,	-0x1	},	insn_gen0 },
+	{ "stb",	{	0xd7,	0xe7,	0xf7,	-0x1	},	insn_gen0 },
+	{ "stbt",	{	0x1137,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
+	{ "std",	{	0xdd,	0xed,	0xfd,	-0x1	},	insn_gen0 },
+	{ "ste",	{	0x1197,	0x11a7,	0x11b7,	-0x1	},	insn_gen0 },
+	{ "stf",	{	0x11d7,	0x11e7,	0x11f7,	-0x1	},	insn_gen0 },
+	{ "stq",	{	0x10dd,	0x10ed,	0x10fd,	-0x1	},	insn_gen0 },
+	{ "sts",	{	0x10df,	0x10ef,	0x10ff,	-0x1	},	insn_gen0 },
+	{ "stu",	{	0xdf,	0xef,	0xff,	-0x1	},	insn_gen0 },
+	{ "stw",	{	0x1097,	0x10a7,	0x10b7,	-0x1	},	insn_gen0 },
+	{ "stx",	{	0x9f,	0xaf,	0xbf,	-0x1	},	insn_gen0 },
+	{ "sty",	{	0x109f,	0x10af,	0x10bf,	-0x1	},	insn_gen0 },
+	{ "suba",	{	0x90,	0xa0,	0xb0,	0x80	},	insn_gen8 },
+	{ "subb",	{	0xd0,	0xe0,	0xf0,	0xc0	},	insn_gen8 },
+	{ "subd",	{	0x93,	0xa3,	0xb3,	0x83	},	insn_gen16 },
+	{ "sube",	{	0x1190,	0x11a0,	0x11b0,	0x1180	},	insn_gen8 },
+	{ "subf",	{	0x11d0,	0x11e0,	0x11f0,	0x11c0	},	insn_gen8 },
+	{ "subr",	{	0x1032,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	{ "subw",	{	0x1090,	0x10a0,	0x1090,	0x1080	},	insn_gen8 },
+	{ "swi",	{	0x3f,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "swi2",	{	0x103f,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "swi3",	{	0x113f,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "sync",	{	0x13,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	
+	// note: 		r+,r+	r-,r-	r+,r	r,r+
+	{ "tfm",	{	0x1138,	0x1139,	0x113a,	0x113b	},	insn_tfm },
+
+	{ "tfr",	{	0x1f,	-0x1,	-0x1,	-0x1	},	insn_rtor },
+	{ "tim",	{	0x0b,	0x6b,	0x7b,	-0x1	},	insn_logicmem },
+	{ "tst",	{	0x0d,	0x6d,	0x7d,	-0x1	},	insn_gen0 },
+	{ "tsta",	{	0x4d,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "tstb",	{	0x5d,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "tstd",	{	0x104d,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "tste",	{	0x114d,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "tstf",	{	0x115d,	-0x1,	-0x1,	-0x1	},	insn_inh },
+	{ "tstw",	{	0x105d,	-0x1,	-0x1,	-0x1	},	insn_inh },
+
+	{ "org",	{ -1, -1, -1, -1 },	pseudo_org },
+
+	{ "equ",	{ -1, -1, -1, -1 },	pseudo_equ,	0,	0,	1 },
+	{ "=",		{ -1, -1, -1, -1 },	pseudo_equ,	0,	0,	1 },
+	{ "extern",	{ -1, -1, -1, -1 },	pseudo_extern,	0,	0,	1 },
+	{ "external",	{ -1, -1, -1, -1 },	pseudo_extern,	0,	0,	1 },
+	{ "import",	{ -1, -1, -1, -1 },	pseudo_extern,	0,	0,	1 },
+	{ "export",	{ -1, -1, -1, -1 },	pseudo_export,	0,	0,	1 },
+
+
+	{ "rmb", 	{ -1, -1, -1, -1 }, pseudo_rmb },
+	{ "rmd", 	{ -1, -1, -1, -1 }, pseudo_rmd },
+	{ "rmq", 	{ -1, -1, -1, -1 }, pseudo_rmq },
+
+	{ "zmb", 	{ -1, -1, -1, -1 }, pseudo_zmb },
+	{ "zmd", 	{ -1, -1, -1, -1 }, pseudo_zmd },
+	{ "zmq", 	{ -1, -1, -1, -1 }, pseudo_zmq },
+
+	{ "fcc",	{ -1, -1, -1, -1 },	pseudo_fcc },
+	{ "fcn",	{ -1, -1, -1, -1 },	pseudo_fcn },
+	{ "fcs",	{ -1, -1, -1, -1 },	pseudo_fcs },
+
+	{ "fcb",	{ -1, -1, -1, -1 },	pseudo_fcb },
+	{ "fdb",	{ -1, -1, -1, -1 },	pseudo_fdb },
+	{ "fqb",	{ -1, -1, -1, -1 },	pseudo_fqb },
+
+	{ "end", 	{ -1, -1, -1, -1 }, pseudo_end },
+
+	{ "include", { -1, -1, -1, -1 }, pseudo_include },
+	
+	{ "align", { -1, -1, -1, -1 },	pseudo_align },
+
+	{ "error",	{ -1, -1, -1, -1},	pseudo_error },
+
+	{ "ifeq",	{ -1, -1, -1, -1}, 	pseudo_ifeq, 1 },
+	{ "ifne",	{ -1, -1, -1, -1}, 	pseudo_ifne, 1 },
+	{ "if",		{ -1, -1, -1, -1}, 	pseudo_ifne, 1 },
+	{ "ifgt",	{ -1, -1, -1, -1}, 	pseudo_ifgt, 1 },
+	{ "ifge",	{ -1, -1, -1, -1}, 	pseudo_ifge, 1 },
+	{ "iflt",	{ -1, -1, -1, -1}, 	pseudo_iflt, 1 },
+	{ "ifle",	{ -1, -1, -1, -1}, 	pseudo_ifle, 1 },
+	{ "endc",	{ -1, -1, -1, -1}, 	pseudo_endc, 1 },
+	{ "else",	{ -1, -1, -1, -1}, 	pseudo_else, 1 },
+	{ "ifdef",	{ -1, -1, -1, -1},	pseudo_ifdef, 1},
+	{ "ifndef",	{ -1, -1, -1, -1},	pseudo_ifndef, 1},
+
+	{ "macro",	{ -1, -1, -1, -1}, 	pseudo_macro,	1,	0,	1 },
+	{ "endm",	{ -1, -1, -1, -1},	pseudo_endm,	1,	1,	1 },
+
+	{ "setdp", 	{ -1, -1, -1, -1},	pseudo_setdp },
+	{ "set",	{ -1, -1, -1, -1},	pseudo_set,	0,	0,	1 },
+
+	{ "section",	{ -1, -1, -1, -1},	pseudo_section },
+	{ "sect",	{ -1, -1, -1, -1},	pseudo_section },
+	{ "ends",	{ -1, -1, -1, -1},	pseudo_endsection },
+	{ "endsect",	{ -1, -1, -1, -1},	pseudo_endsection },
+	{ "endsection",	{ -1, -1, -1, -1},	pseudo_endsection },
+	
+	{ "pragma",	{ -1, -1, -1, -1},	pseudo_pragma },
+	{ "*pragma",	{ -1, -1, -1, -1},	pseudo_starpragma },
+	
+
+	/* flag end of table */	
+	{ NULL,		{ -0x1, -0x1, -0x1, -0x1 }, insn_inh }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/instab.h	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,45 @@
+/*
+instab.h
+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/>.
+
+
+Contains definitions for the instruction table
+*/
+
+#ifndef __instab_h_seen__
+#define __instab_h_seen__
+
+#include "lwasm.h"
+
+typedef struct
+{
+	char *opcode;				/* the mneumonic */
+	int ops[4];					/* opcode values for up to four addr modes */
+	void (*fn)(asmstate_t *as, lwasm_line_t *l, char **optr, int opnum);
+	int iscond;					/* set if this should be dispatched even if skipping a condition/macro */
+	int endm;					/* end of macro? */
+	int setsym;					/* does this set a symbol address? EQU, SET */
+} instab_t;
+
+#define OPFUNC(fn)	void (fn)(asmstate_t *as, lwasm_line_t *l, char **p, int opnum)
+
+#ifndef __instab_c_seen__
+extern instab_t instab[];
+#endif //__instab_c_seen__
+
+#endif //__instab_h_seen__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/list.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,139 @@
+/*
+list.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/>.
+
+Contains code for displaying a program listings, etc.
+*/
+
+#define __list_c_seen__
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lwasm.h"
+
+void lwasm_show_errors(asmstate_t *as)
+{
+	lwasm_line_t *l;
+	lwasm_error_t *e;
+	
+	for (l = as -> lineshead; l; l = l -> next)
+	{
+		if (l -> err)
+		{
+			for (e = l -> err; e; e = e -> next)
+			{
+				fprintf(stderr, "ERROR: %s\n", e -> mess);
+			}
+			fprintf(stderr, "%s:%d: %s\n", l -> filename, l -> lineno, l -> text);
+		}
+	}
+}
+
+void lwasm_list(asmstate_t *as)
+{
+	FILE *lf;
+	lwasm_line_t *l;
+	int c, c3;
+	char *p;
+	
+	if (!as -> listfile)
+		return;
+	if (as -> listfile[0] == '-' && as -> listfile[1] == '\0')
+		lf = stdout;
+	else
+	{
+		lf = fopen(as -> listfile, "w");
+		if (!lf)
+		{
+			fprintf(stderr, "Unable to open list file '%s'. No listing will be generated: ", as -> listfile);
+			perror("");
+			goto showerr;
+		}
+	}
+
+	for (l = as -> lineshead; l; l = l -> next)
+	{
+		if (l -> addrset == 1 || l -> codelen > 0 || l -> nocodelen > 0)
+		{
+			fprintf(lf, "%04X ", l -> codeaddr);
+		}
+		else
+		{
+			fprintf(lf, "     ");
+		}
+		
+		if (l -> addrset == 2)
+		{
+			fprintf(lf, "%04X      ", l -> symaddr);
+		}
+		else
+		{
+			for (c = 0; c < l -> codelen && c < 5; c++)
+			{
+				fprintf(lf, "%02X", l -> bytes[c]);
+			}
+			while (c < 5)
+			{
+				fprintf(lf, "  ");
+				c++;
+			}
+		}
+		fprintf(lf, " %20.20s:%05d ", l -> filename, l -> lineno);
+		
+		// print line here
+		for (c3 = 0, c = 0, p = l -> text; *p; c++, p++)
+		{
+			if (*p == '\t')
+			{
+				int c2;
+				c2 = 8 - (c3 % 8);
+				c3 += c2;
+				while (c2--) fputc(' ', lf);
+			}
+			else
+			{
+				c3++;
+				fputc(*p, lf);
+			}
+		}
+		fputc('\n', lf);
+		
+		if (l -> codelen > 5)
+		{
+			fprintf(lf, "%04X ", (l -> codeaddr + 5) & 0xFFFF);
+			for (c = 5; c < l -> codelen; c++)
+			{
+				if (!(c % 5) && c != 5)
+				{
+					fprintf(lf, "\n%04X ", (l -> codeaddr + c) & 0xFFFF);
+				}
+				fprintf(lf, "%02X", l -> bytes[c]);
+			}
+			fputc('\n', lf);
+		}
+	}
+	
+	lwasm_list_symbols(as, lf);
+	
+	if (lf != stdout)
+		fclose(lf);
+
+showerr:
+	lwasm_show_errors(as);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/lwasm.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,428 @@
+/*
+lwasm.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/>.
+
+
+Contains random functions used by the assembler
+*/
+
+#define __lwasm_c_seen__
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "lwasm.h"
+#include "util.h"
+#include "expr.h"
+
+int debug_level = 0;
+
+int register_error(asmstate_t *as, lwasm_line_t *l, int pass, const char *fmt, ...)
+{
+	lwasm_error_t *e;
+	va_list args;
+	char errbuff[1024];
+	int r;
+	
+	if (!l)
+		return;
+
+	if (as -> passnum != pass)
+		return;
+	
+	va_start(args, fmt);
+	
+	e = lwasm_alloc(sizeof(lwasm_error_t));
+	
+	e -> next = l -> err;
+	l -> err = e;
+	
+	as -> errorcount++;
+	
+	r = vsnprintf(errbuff, 1024, fmt, args);
+	e -> mess = lwasm_strdup(errbuff);
+	
+	va_end(args);
+	
+	return r;
+}
+
+void lwasm_emit(asmstate_t *as, lwasm_line_t *l, int b)
+{
+	as -> addr += 1;
+	as -> addr &= 0xffff;
+	
+	if (as -> outformat == OUTPUT_OBJ && !(as -> csect))
+	{
+		register_error(as, l, 1, "Output not allowed outside sections with obj target");
+		return;
+	}
+	if (as -> outformat == OUTPUT_OBJ && as -> csect -> flags & SECTION_BSS)
+	{
+		register_error(as, l, 1, "Output not allowed inside BSS sections");
+		return;
+	}
+	if (as -> passnum == 1)
+		return;
+
+
+	if (l -> codelen >= l -> codesize)
+	{
+		l -> bytes = realloc(l -> bytes, l -> codesize + 16);
+		l -> codesize += 16;
+	}
+	l -> bytes[l -> codelen] = b & 0xff;
+	l -> codelen += 1;
+}
+
+void lwasm_emitop(asmstate_t *as, lwasm_line_t *l, int o)
+{
+	if (o >= 0x100)
+		lwasm_emit(as, l, o >> 8);
+	lwasm_emit(as, l, o & 0xff);
+}
+
+int lwasm_lookupreg2(const char *reglist, char **str)
+{
+	int rval = 0;
+
+	while (*reglist)
+	{
+		if (toupper(**str) == *reglist)
+		{
+			// first char matches
+			if (reglist[1] == ' ' && !isalpha(*(*str + 1)))
+				break;
+			if (toupper(*(*str + 1)) == reglist[1])
+				break;
+		}
+		reglist += 2;
+		rval++;
+	}
+	if (!*reglist)
+		return -1;
+	if (reglist[1] == ' ')
+		(*str)++;
+	else
+		(*str) += 2;
+	return rval;
+}
+
+int lwasm_lookupreg3(const char *rlist, const char **str)
+{
+	int rval = 0;
+	int f = 0;
+	const char *reglist = rlist;
+		
+	while (*reglist)
+	{
+		if (toupper(**str) == *reglist)
+		{
+			// first char matches
+			if (reglist[1] == ' ')
+			{
+				f = 1;
+				break;
+			}
+			if (toupper(*(*str + 1)) == reglist[1])
+			{
+				// second char matches
+				if (reglist[2] == ' ')
+				{
+					f = 1;
+					break;
+				}
+				if (toupper(*(*str + 2)) == reglist[2])
+				{
+					f = 1;
+					break;
+				}
+			}
+		}
+		reglist += 3;
+		rval++;
+	}
+	if (f == 0)
+		return -1;
+	
+	
+	reglist = rval * 3 + rlist;
+	if (reglist[1] == ' ')
+		(*str) += 1;
+	else if (reglist[2] == ' ')
+		(*str) += 2;
+	else
+		(*str)+=3;
+	return rval;
+}
+
+struct symstateinfo
+{
+	asmstate_t *as;
+	lwasm_line_t *l;
+	int flags;
+};	
+
+lwasm_expr_stack_t *lwasm_expr_lookup_symbol(char *sym, void *state)
+{
+	lwasm_symbol_ent_t *se;
+	struct symstateinfo *st;
+	lwasm_expr_stack_t *rs;
+	lwasm_expr_term_t *t;
+	lwasm_expr_stack_node_t *n;
+	
+	int val;
+	
+	st = state;
+	debug_message(3, "lwasm_expr_lookup_symbol(): find '%s' (context=%d)", sym, st -> as -> context);	
+
+	// check for special symbols first...
+	if (sym[1] == '\0')
+	{
+		switch (sym[0])
+		{
+		// current line address
+		case '*':
+		case '.':
+			val = st -> l -> codeaddr;
+			goto retconst;
+		
+		case '<':
+			// previous branch point
+			// not implemented
+			break;
+		case '>':
+			// next branch point
+			// not implemented
+			break;
+		}
+	}
+
+	// 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);
+	debug_message(3, "lwasm_expr_lookup_symbol(): got '%p'", se);
+	if (!se)
+	{
+		register_error(st -> as, st -> l, 2, "Undefined symbol '%s'", sym);
+		return NULL;
+	}
+	// external reference - can not resolve it
+	if (se -> flags & SYMBOL_EXTERN)
+	{
+		return NULL;
+	}
+	if (st -> flags & EXPR_SECTCONST)
+	{
+		if (se -> sect == st -> l -> sect)
+		{
+			if (se -> expr)
+				goto retsym;
+			val = se -> value;
+			goto retconst;
+		}
+	}
+	if (st -> as -> outformat == OUTPUT_OBJ && se -> sect != NULL)
+	{
+		return NULL;
+	}
+	if (st -> as -> outformat != OUTPUT_OBJ || se -> sect == NULL)
+	{
+		// global symbol, intrasegment reference, or not an object target
+		val = se -> value;
+		goto retconst;
+	}
+	
+	// an intersegment reference will return as NULL (to be resolved at output/link time)
+	// if se -> expr is NULL, it has to be an intersegment reference here
+	if (se -> expr == NULL)
+	{
+		return NULL;
+	}
+	
+retsym:
+	// duplicate the expression for return
+	rs = lwasm_expr_stack_create();
+	for (n = se -> expr -> head; n; n = n -> next)
+	{
+		lwasm_expr_stack_push(rs, n -> term);
+	}
+	return rs;
+
+retconst:
+	rs = lwasm_expr_stack_create();
+	t = lwasm_expr_term_create_int(val);
+	lwasm_expr_stack_push(rs, t);
+	lwasm_expr_term_free(t);
+	return rs;
+}
+
+lwasm_expr_stack_t *lwasm_evaluate_expr(asmstate_t *as, lwasm_line_t *l, const char *inp, const char **outp, int flags)
+{
+	struct symstateinfo st;
+	
+	st.as = as;
+	st.l = l;
+	st.flags = flags;
+	
+	debug_message(2, "Evaluate expression: %s", inp);
+	
+	return(lwasm_expr_eval(inp, outp, lwasm_expr_lookup_symbol, &st));
+}
+
+
+int lwasm_reevaluate_expr(asmstate_t *as, lwasm_line_t *l, lwasm_expr_stack_t *s, int flags)
+{
+	struct symstateinfo st;
+	
+	st.as = as;
+	st.l = l;
+	st.flags = flags;
+	return(lwasm_expr_reval(s, lwasm_expr_lookup_symbol, &st));
+}
+
+// return 1 if no undefined symbols (externals and incompletes are okay)
+// return 0 if there are undefined symbols
+int lwasm_expr_result_ckconst(asmstate_t *as, lwasm_expr_stack_t *s)
+{
+	lwasm_expr_stack_node_t *n;
+	lwasm_symbol_ent_t *se;
+	
+	if (as -> outformat != OUTPUT_OBJ)
+	{
+		if (lwasm_expr_is_constant(s))
+			return 1;
+		else
+			return 0;
+	}
+	
+	for (n = s -> head; n; n = n -> next)
+	{
+		if (n -> term -> term_type == LWASM_TERM_SYM)
+		{
+			se = lwasm_find_symbol(as, n -> term -> symbol, as -> context);
+			if (!se)
+				se = lwasm_find_symbol(as, n -> term -> symbol, -1);
+			if (!se)
+				return 0;
+		}
+	}
+	return 1;
+}
+
+/*
+Evaluate an expression according to the flag value. Return 0 if a constant result was
+obtained, 1 if an incomplete result was obtained, and -1 if an error was flagged.
+
+*/
+int lwasm_expr_result2(asmstate_t *as, lwasm_line_t *l, char **inp, int flag, int *val, int slot)
+{
+	lwasm_expr_stack_t *s = NULL;
+	const char *ep;
+	int rval;
+
+	if ((as -> passnum == 1 && !(flag & EXPR_REEVAL)) || slot < 0)
+	{		
+		s = lwasm_evaluate_expr(as, l, *inp, &ep, flag);
+		if (slot >= 0)
+			l -> exprs[slot] = s;
+		if (!s)
+		{
+			register_error(as, l, 1, "Bad expression");
+			*val = 0;
+			return -1;
+		}
+		*inp = (char *)ep;
+		if (slot >= 0)
+		{
+			l -> exprends[slot] = (char *)ep;
+			l -> exprvals[slot] = lwasm_expr_get_value(s);
+		}
+	}
+	else if (l -> exprs[slot])
+	{
+		s = l -> exprs[slot];
+		lwasm_reevaluate_expr(as, l, s, flag);
+		l -> exprvals[slot] = lwasm_expr_get_value(s);
+	}
+	if (as -> passnum == 2 && slot >= 0)
+		*inp = l -> exprends[slot];
+
+	if (s && lwasm_expr_is_constant(s))
+	{
+		*val = lwasm_expr_get_value(s);
+		lwasm_expr_stack_free(s);
+		l -> exprs[slot] = NULL;
+		s = NULL;
+		return 0;
+	}
+
+	if (!s && slot >= 0)
+	{
+		*val = l -> exprvals[slot];
+		return 0;
+	}
+	else if (!s)
+	{
+		*val = 0;
+		return 0;
+	}
+
+	// was a constant result on pass 1 requested?
+	// that means we must have a constant on either pass
+	if (flag & EXPR_PASS1CONST)
+	{
+		*val = 0;
+		if (slot >= 0)
+			l -> exprvals[slot] = 0;
+		register_error(as, l, 1, "Illegal forward, external, or inter-section reference");
+		lwasm_expr_stack_free(s);
+		if (slot >= 0)
+			l -> exprs[slot] = NULL;
+		return -1;
+	}
+	
+	return 1;
+}
+
+void debug_message(int level, const char *fmt, ...)
+{
+	va_list args;
+	
+	va_start(args, fmt);
+	if (debug_level >= level)
+	{
+		if (level > 0)
+			fprintf(stderr, "DEBUG %d: ", level);
+		vfprintf(stderr, fmt, args);
+		fputc('\n', stderr);
+	}
+	va_end(args);
+}
+
+int lwasm_next_context(asmstate_t *as)
+{
+	int r;
+	r = as -> nextcontext;
+	as -> nextcontext += 1;
+	debug_message(3, "lwasm_next_context(): %d (%d) pass %d", r, as -> nextcontext, as -> passnum);
+	return r;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/lwasm.h	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,234 @@
+/*
+lwasm.h
+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/>.
+
+Contains the main defs used by the assembler
+*/
+
+
+#ifndef __lwasm_h_seen__
+#define __lwasm_h_seen__
+
+#include <stdio.h>
+#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
+#define OUTPUT_RAWREL	3	// raw bytes where ORG causes a SEEK in the file
+
+// structure for tracking sections
+typedef struct section_reloc_list_s section_reloc_list_t;
+struct section_reloc_list_s
+{
+	int offset;						// offset into section
+	lwasm_expr_stack_t *expr;		// value definition
+	int context;					// symbol context (for local syms)
+	section_reloc_list_t *next;		// next relocation
+};
+
+typedef struct export_list_s export_list_t;
+struct export_list_s
+{
+	int offset;						// offset of symbol
+	char *sym;						// name of symbol
+	export_list_t *next;			// next export	
+};
+
+#define SECTION_BSS		1	// the section contains no actual code - just uninit vars
+typedef struct sectiontab_s sectiontab_t;
+struct sectiontab_s
+{
+	char *name;				// name of the section
+	int offset;				// current offset in the section
+	int flags;				// section flags
+	sectiontab_t *next;		// next section
+	// the following are used during code output
+	unsigned char *obytes;	// output bytes
+	int oblen;				// how many bytes output so far?
+	int obsize;				// how big is output buffer so far?
+	section_reloc_list_t *rl;	// relocation list
+	export_list_t *exports;	// export list for the section
+};
+
+// structure for tracking macros
+typedef struct macrotab_s macrotab_t;
+struct macrotab_s
+{
+	char *name;
+	char **lines;
+	int numlines;
+	macrotab_t *next;
+};
+
+// structure for tracking errors
+typedef struct lwasm_error_s lwasm_error_t;
+struct lwasm_error_s
+{
+	char *mess;				// the actual error message
+	lwasm_error_t *next;	// ptr to next error
+};
+
+// structure for keeping track of lines
+// it also as space for 4 expressions which is enough for all known
+// instructions and addressing modes
+// on pass 1, the expressions are parsed, on pass 2 they are re-evaluated
+// to determine constancy
+typedef struct lwasm_line_s lwasm_line_t;
+struct lwasm_line_s {
+	char *text;			// the actual text of the line
+	int lineno;			// line number within the file
+	char *filename;		// file name reference
+	lwasm_line_t *next;	// next line
+	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
+	unsigned char *bytes;	// actual bytes emitted
+	int codelen;		// number of bytes emitted
+	int codesize;		// the size of the code buffer
+	int codeaddr;		// address the code goes at
+	int nocodelen;		// for "RMB" type instructions
+	int addrset;		// set if this instruction sets the assembly address
+	int symaddr;		// set if this instruction sets a symbol addr with EQU or the like
+	int badop;			// bad operation - ignore it
+	int context;		// the symbol context for this line
+	
+	// the following are used for obj format - for external references, inter-section
+	// references, and intrasection relocations
+	int relocoff;		// offset into insn where relocation value goes
+	lwasm_expr_stack_t *exprs[4];	// non-constant expression values
+	int exprvals[4];	// constant expression values
+	char *exprends[4];	// pointer to character after end of expression
+	
+	sectiontab_t *sect;	// which section is the line in?
+};
+
+// for keeping track of symbols
+#define	SYMBOL_SET		1	// the symbol was used for "SET"
+#define SYMBOL_COMPLEX	2	// register symbol as a complex symbol (from l -> expr)
+#define SYMBOL_FORCE	4	// force resetting the symbol value if it already exists on pass 2
+#define SYMBOL_NORM		0	// no flags
+#define SYMBOL_EXTERN	8	// the symbol is an external reference
+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
+	int flags;					// flags for the symbol
+	char *externalname;			// for external references that are aliased locally
+	sectiontab_t *sect;			// the section the symbol exists in; NULL for none
+	lwasm_expr_stack_t *expr;	// expression for a symbol that is not constant NULL for const
+	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 ....)
+	int pragmas;				// what pragmas are in effect?
+
+	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
+	
+	macrotab_t *macros;			// macro table
+
+	const char *infile;			// input file
+	const char *outfile;		// output file
+	const char *listfile;		// output listing file
+	int outformat;				// output format type
+	char **filelist;			// files that have been read
+	int filelistlen;			// number of files in the list
+	
+	int endseen;				// set to true if "end" has been seen
+	int skipcond;				// skipping a condition?
+	int skipcount;				// how many?
+	int skipmacro;				// skipping a macro?
+	int inmacro;				// are we currently in a macro?
+	int macroex;				// current depth of macro expansion
+	int nextcontext;			// next context number
+	int skiplines;				// number of lines to skip
+	
+	// items used only for the "object" target
+	sectiontab_t *sections;		// pointer to section table
+	sectiontab_t *csect;		// current section - NULL if not in one
+} asmstate_t;
+
+// do not rewrite XXX,r to ,r if XXX evaluates to 0
+#define PRAGMA_NOINDEX0TONONE	1
+// any undefined symbols are considered external
+#define PRAGMA_UNDEFEXTERN	2
+
+#ifndef __lwasm_c_seen__
+#define __lwasm_E__ extern
+#else
+#define __lwasm_E__
+#endif
+
+__lwasm_E__ int debug_level;
+
+__lwasm_E__ int register_error(asmstate_t *as, lwasm_line_t *l, int pass, const char *fmt, ...);
+__lwasm_E__ void debug_message(int level, const char *fmt, ...);
+
+__lwasm_E__ void lwasm_emit(asmstate_t *as, lwasm_line_t *l, int b);
+__lwasm_E__ void lwasm_emitop(asmstate_t *as, lwasm_line_t *l, int o);
+__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, int flags);
+
+
+// return next context number and update it
+__lwasm_E__ int lwasm_next_context(asmstate_t *as);
+
+// also throw an error on expression eval failure
+// return 0 on ok, -1 on error, 1 if a complex expression was returned
+#define EXPR_NOFLAG			0
+#define EXPR_PASS1CONST		1	// no forward references on pass 1
+#define EXPR_SECTCONST		2	// resolve symbols local to section
+#define EXPR_REEVAL			4	// re-evaluate the expression
+__lwasm_E__ int lwasm_expr_result(asmstate_t *as, lwasm_line_t *l, char **inp, int flag, int *val);
+__lwasm_E__ int lwasm_expr_result2(asmstate_t *as, lwasm_line_t *l, char **inp, int flag, int *val, int slot);
+
+#undef __lwasm_E__
+
+
+#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, int flags);
+__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);
+__lwasm_E__ void lwasm_list_symbols(asmstate_t *as, FILE *f);
+#undef __lwasm_E__
+
+
+
+#endif //__lwasm_h_seen__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/lwval.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,210 @@
+/*
+lwval.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/>.
+*/
+
+/*
+This file contains implementations associated with the expression evaluator
+used by LWASM.
+
+*/
+
+#include <malloc.h>
+
+#define __lwval_c_seen__
+#include "lwval.h"
+
+LWVAL *lwval_construct_int(int value)
+{
+	LWVAL *v;
+	
+	v = malloc(sizeof(LWVAL));
+	if (!v)
+		return NULL;
+	
+	v -> lwval_type = LWVAL_TYPE_INT;
+	v -> dt.lwval_int = value;
+	
+	return v;
+}
+
+LWVAL *lwval_construct_err(int errno)
+{
+	LWVAL *v;
+	
+	v = malloc(sizeof(LWVAL));
+	if (!v)
+		return NULL;
+	
+	v -> lwval_type = LWVAL_TYPE_ERR;
+	v -> dt.lwval_int = errno;
+	
+	return v;
+}
+
+LWVAL *lwval_construct_nan(void)
+{
+	LWVAL *v;
+	
+	v = malloc(sizeof(LWVAL));
+	if (!v)
+		return NULL;
+	
+	v -> lwval_type = LWVAL_TYPE_NAN;
+	
+	return v;
+}
+
+LWVAL *lwval_construct_undef(void)
+{
+	LWVAL *v;
+	
+	v = malloc(sizeof(LWVAL));
+	if (!v)
+		return NULL;
+	
+	v -> lwval_type = LWVAL_TYPE_UNDEF;
+	
+	return v;
+}
+
+LWVAL *lwval_construct_expr(LWVAL *v1, LWVAL *v2, int op)
+{
+	LWVAL *v;
+	v = malloc(sizeof(LWVAL));
+	if (!v)
+		return NULL;
+	
+	v -> lwval_type = LWVAL_TYPE_EXPR;
+	v -> dt.expr.v1 = v1;
+	v -> dt.expr.v2 = v2;
+	v -> dt.expr.op = op;
+	return v;
+}
+
+void lwval_destroy(LWVAL *value)
+{
+	if (value)
+	{
+		lwval_clear(value);
+		free(value);
+	}
+}
+
+// performs a deep copy of an LWVAL, including ALL referenced values
+void lwval_dup(LWVAL *v1, LWVAL *v2)
+{
+	lwval_clear(v2);
+	
+	switch (v1 -> lwval_type)
+	{
+	case LWVAL_TYPE_INT:
+	case LWVAL_TYPE_ERR:
+		v2 -> dt.lwval_int = v1 -> dt.lwval_int;
+		break;
+	
+	case LWVAL_TYPE_EXPR:
+		v2 -> dt.expr.op = v1 -> dt.expr.op;
+		if (v1 -> dt.expr.v1)
+		{
+			v2 -> dt.expr.v1 = lwval_construct_undef();
+			lwval_dup(v1 -> dt.expr.v1, v2 -> dt.expr.v1);
+		}
+		else
+			v2 -> dt.expr.v1 = NULL;
+		if (v1 -> dt.expr.v2)
+		{
+			v2 -> dt.expr.v2 = lwval_construct_undef();
+			lwval_dup(v1 -> dt.expr.v2, v2 -> dt.expr.v2);
+		}
+		else
+			v2 -> dt.expr.v2 = NULL;
+		break;
+	}
+	
+	v2 -> lwval_type = v1 -> lwval_type;
+}
+
+void lwval_clear(LWVAL *value)
+{
+	switch (value -> lwval_type)
+	{
+	case LWVAL_TYPE_EXPR:
+		lwval_destroy(value -> dt.expr.v1);
+		lwval_destroy(value -> dt.expr.v2);
+		break;
+	}
+	value -> lwval_type = LWVAL_TYPE_UNDEF;
+}
+
+// for integer, simply negate value
+// for expr, change to "-1 * (expr)"
+// everything else: error
+LWVAL *lwval_neg(LWVAL *v1)
+{
+	switch (v1 -> lwval_type)
+	{
+	case LWVAL_TYPE_INT:
+		v1 -> dt.lwval_int = -(v1 -> dt.lwval_int);
+		break;
+	
+	case LWVAL_TYPE_EXPR:
+		{
+			LWVAL *v, *v2;
+			v = lwval_construct_undef();
+			lwval_dup(v1, v);
+			lwval_clear(v1);
+			v2 = lwval_construct_expr(lwval_construct_int(-1), v, '*');
+			lwval_dup(v2, v1);
+			lwval_destroy(v2);
+		}
+		break;
+	
+	default:
+		lwval_clear(v1);
+		v1 -> lwval_type = LWVAL_TYPE_ERR;
+		v1 -> dt.lwval_int = 1;
+	}
+	
+	return v1;
+}
+
+// v1 + v2 -> v1
+LWVAL *lwval_add(LWVAL *v1, LWVAL *v2)
+{
+}
+
+// v1 - v2 -> v1
+LWVAL *lwval_sub(LWVAL *v1, LWVAL *v2)
+{
+}
+
+// v1 * v2 -> v1
+LWVAL *lwval_mul(LWVAL *v1, LWVAL *v2)
+{
+}
+
+// v1 / v2 -> v1
+LWVAL *lwval_div(LWVAL *v1, LWVAL *v2)
+{
+}
+
+// v1 % v2 -> v1
+LWVAL *lwval_mod(LWVAL *v1, LWVAL *v2)
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/lwval.h	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,113 @@
+/*
+lwval.h
+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/>.
+*/
+
+/*
+This file contains definitions associated with the expression evaluator used
+by LWASM.
+
+The core of the entire expression handler is the opaque type LWVAL, pointers
+to which are passed around to keep track of values. A value may be a simple
+integer or it could be a more complex expression linked by operators or it
+could be a polynomial expression. Simple integers are merely a degenerate
+case of polynomials.
+
+The package understands the following operations:
+
+addition
+subtraction
+multiplication
+division
+modulus
+parentheses
+unary negation
+unary "positive"
+bitwise and
+bitwise or
+bitwise not (1's complement)
+bitwise exclusive or
+
+Infix operators can be expressed as LWVAL <op> LWVAL. Thus, the order of
+operations is only relevant when initially parsing the expression. The order
+of evaluation is determined by what appears on either side of the <op> as
+an LWVAL may be an expression.
+*/
+
+#ifndef __lwval_h_seen__
+#define __lwval_h_seen__
+
+typedef struct lwval LWVAL;
+
+struct lwval_dt_expr
+{
+	LWVAL *v1;						// first value
+	LWVAL *v2;						// second value
+	int op;							// operator
+};
+
+union lwval_dt
+{
+	int lwval_int;					// integer type data
+	char *lwval_var;				// pointer to variable name
+	struct lwval_dt_expr expr;		// expression
+};
+
+enum
+{
+	LWVAL_TYPE_UNDEF,				// undefined
+	LWVAL_TYPE_NAN,					// not a number
+	LWVAL_TYPE_INT,					// integer
+	LWVAL_TYPE_VAR,					// variable (symbol)
+	LWVAL_TYPE_EXPR,				// expression
+	LWVAL_TYPE_ERR					// error
+};
+
+struct lwval
+{
+	int lwval_type;					// data type
+	union lwval_dt dt;				// type specific stuff
+};
+
+#ifndef __lwval_c_seen__
+#define __lwval_extern__ extern
+#else
+#define __lwval_extern__
+#endif
+
+__lwval_extern__ LWVAL *lwval_construct_int(int value);
+__lwval_extern__ LWVAL *lwval_construct_err(int errno);
+__lwval_extern__ LWVAL *lwval_construct_nan(void);
+__lwval_extern__ LWVAL *lwval_construct_expr(LWVAL *v1, LWVAL *v2, int op);
+__lwval_extern__ LWVAL *lwval_construct_undef(void);
+__lwval_extern__ void lwval_clear(LWVAL *value);
+__lwval_extern__ void lwval_destroy(LWVAL *value);
+__lwval_extern__ void lwval_dup(LWVAL *v1, LWVAL *v2);
+
+// operators - operate on v1 and v2 in order, result goes into
+// v1; return v1
+__lwval_extern__ LWVAL *lwval_add(LWVAL *v1, LWVAL *v2);
+__lwval_extern__ LWVAL *lwval_sub(LWVAL *v1, LWVAL *v2);
+__lwval_extern__ LWVAL *lwval_mul(LWVAL *v1, LWVAL *v2);
+__lwval_extern__ LWVAL *lwval_div(LWVAL *v1, LWVAL *v2);
+__lwval_extern__ LWVAL *lwval_mod(LWVAL *v1, LWVAL *v2);
+__lwval_extern__ LWVAL *lwval_neg(LWVAL *v1);
+
+#undef __lwval_extern__
+
+#endif //__lwval_h_seen__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/macro.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,340 @@
+/*
+macro.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/>.
+
+Contains stuff associated with macro processing
+*/
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lwasm.h"
+#include "instab.h"
+#include "util.h"
+
+OPFUNC(pseudo_macro)
+{
+	macrotab_t *m;
+
+	// if skipping a condition, flag in a macro
+	if (as -> skipcond)
+	{
+		as -> skipmacro = 1;
+		return;
+	}
+
+	// actually define a macro
+	if (as -> inmacro)
+	{
+		register_error(as, l, 1, "Attempt to define a macro inside a macro");
+		return;
+	}
+
+	as -> inmacro = 1;
+
+	// don't actually do anything if not pass 1
+	if (as -> passnum != 1)
+		return;
+
+
+	if (!l -> sym)
+	{
+		register_error(as, l, 1, "Macro definition with no effect - no symbol");
+		return;
+	}
+	
+	// search for macro by same name...
+	for (m = as -> macros; m; m = m -> next)
+	{
+		if (!strcmp(m -> name, l -> sym))
+			break;
+	}
+	if (m)
+	{
+		register_error(as, l, 1, "Duplicate macro definition");
+		return;
+	}
+	
+	m = lwasm_alloc(sizeof(macrotab_t));
+	m -> name = lwasm_strdup(l -> sym);
+	m -> next = as -> macros;
+	m -> lines = NULL;
+	m -> numlines = 0;
+	as -> macros = m;
+
+	while (**p && !isspace(**p))
+		(*p)++;
+}
+
+OPFUNC(pseudo_endm)
+{
+	if (as -> skipcond)
+	{
+		as -> skipmacro = 0;
+		return;
+	}
+	
+	if (!as -> inmacro)
+	{
+		register_error(as, l, 1, "ENDM without MACRO");
+		return;
+	}
+	
+	as -> inmacro = 0;
+	
+	// a macro definition counts as a context break for local symbols
+	as -> context = lwasm_next_context(as);
+}
+
+// the current macro will ALWAYS be the first one in the table
+int add_macro_line(asmstate_t *as, char *optr)
+{
+	if (!as -> inmacro)
+		return 0;
+	
+	if (as -> passnum == 2)
+		return 1;
+
+	as -> macros -> lines = lwasm_realloc(as -> macros -> lines, sizeof(char *) * (as -> macros -> numlines + 1));
+	as -> macros -> lines[as -> macros -> numlines] = lwasm_strdup(optr);
+	as -> macros -> numlines += 1;
+	return 1;
+}
+
+void macro_add_to_buff(char **buff, int *loc, int *len, char c)
+{
+	if (*loc == *len)
+	{
+		*buff = lwasm_realloc(*buff, *len + 32);
+		*len += 32;
+	}
+	(*buff)[(*loc)++] = c;
+}
+
+// this is just like a regular operation function
+/*
+macro args are referenced by "\n" where 1 <= n <= 9
+or by "\{n}"; a \ can be included by writing \\
+a comma separates argument but one can be included with "\,"
+whitespace ends argument list but can be included with "\ " or the like
+
+In pass 1, actually add the lines to the system, in pass 2, do not
+In pass 2, track the number of lines to skip because they already will be
+processed by this function - this will be in as -> skiplines
+
+*/
+int expand_macro(asmstate_t *as, lwasm_line_t *l, char **p, char *opc)
+{
+	int lc;
+	lwasm_line_t *cl, *nl;
+	int oldcontext;
+	macrotab_t *m;
+
+	char **args = NULL;		// macro arguments
+	int nargs = 0;			// number of arguments
+
+	char *p2, *p3;
+	
+	int bloc, blen;
+	char *linebuff;
+
+	for (m = as -> macros; m; m = m -> next)
+	{
+		if (!strcmp(opc, m -> name))
+			break;
+	}
+	// signal no macro expansion
+	if (!m)
+		return -1;
+	
+
+	// save current symbol context for after macro expansion
+	oldcontext = as -> context;
+
+	cl = l;
+
+	as -> context = lwasm_next_context(as);
+
+	// step 1: parse arguments (pass 1 only)
+	if (as -> passnum == 1)
+	{
+		while (**p && !isspace(**p) && **p != ',')
+		{
+			p2 = *p;
+			while (*p2 && !isspace(*p2) && *p2 != ',')
+			{
+				if (*p2 == '\\')
+				{
+					if (p2[1])
+						p2++;
+				}
+				p2++;
+			}
+			
+			// have arg here
+			args = lwasm_realloc(args, sizeof(char *) * (nargs + 1));
+			args[nargs] = lwasm_alloc(p2 - *p + 1);
+			args[nargs][p2 - *p] = '\0';
+			memcpy(args[nargs], *p, p2 - *p);
+			*p = p2;
+			
+			// now collapse out "\" characters
+			for (p3 = p2 = args[nargs]; *p2; p2++, p3++)
+			{
+				if (*p2 == '\\' && p2[1])
+				{
+					p2++;
+				}
+				*p3 = *p2;
+			}
+			*p3 = '\0';
+			
+			nargs++;
+			if (**p == ',')
+				(*p)++;
+		}
+	}
+	
+	{
+		int i;
+		for (i = 0; i < nargs; i++)
+		{
+			debug_message(10, "Macro (%s) arg %d: %s", m -> name, i + 1, args[i]);
+		}
+	}
+	
+	// step 2: iterate over the lines
+	if (as -> passnum == 2)
+	{
+		// pass 2 only - parse the lines and count them
+		for (lc = 0; lc < m -> numlines; lc++)
+		{
+			cl = cl -> next;
+			as -> skiplines++;
+			lwasm_parse_line(as, cl);
+		}
+	}
+	else
+	{
+		// pass 1 only - construct the lines and parse them
+		for (lc = 0; lc < m -> numlines; lc++)
+		{
+			nl = lwasm_alloc(sizeof(lwasm_line_t));
+			nl -> lineno = lc + 1;
+			nl -> filename = m -> name;
+			nl -> next = NULL;
+			nl -> prev = as -> linestail;
+			nl -> err = NULL;
+			nl -> fsize = 0;
+			nl -> sym = NULL;
+			nl -> bytes = NULL;
+			nl -> codelen = 0;
+			nl -> codesize = 0;
+			nl -> nocodelen = 0;
+			nl -> addrset = 0;
+			nl -> symaddr = -1;
+			nl -> badop = 0;
+			nl -> relocoff = -1;
+			if (as -> linestail)
+				as -> linestail -> next = nl;
+			as -> linestail = nl;
+			if (!(as -> lineshead))
+				as -> lineshead = nl;
+
+			bloc = blen = 0;
+			linebuff = NULL;
+			for (p2 = m -> lines[lc]; *p2; p2++)
+			{
+				if (*p2 == '\\' && isdigit(p2[1]))
+				{
+					int n;
+					
+					p2++;
+					n = *p2 - '0';
+					if (n == 0)
+					{
+						for (p3 = m -> name; *p3; p3++)
+							macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
+						continue;
+					}
+					if (n < 1 || n > nargs)
+						continue;
+					for (p3 = args[n - 1]; *p3; p3++)
+						macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
+					continue;
+				}
+				else if (*p2 == '{')
+				{
+					int n = 0, n2;
+					p2++;
+					while (*p2 && isdigit(*p2))
+					{
+						n2 = *p2 - '0';
+						if (n2 < 0 || n2 > 9)
+							n2 = 0;
+						n = n * 10 + n2;
+						p2++;
+					}
+					if (*p2 == '}')
+						p2++;
+					 
+					if (n == 0)
+					{
+						for (p3 = m -> name; *p3; p3++)
+							macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
+						continue;
+					}
+					if (n < 1 || n > nargs)
+						continue;
+					for (p3 = args[n - 1]; *p3; p3++)
+						macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
+					continue;
+				}
+				else
+				{
+					macro_add_to_buff(&linebuff, &bloc, &blen, *p2);
+				}
+			}
+
+			macro_add_to_buff(&linebuff, &bloc, &blen, 0);
+			
+			nl -> text = linebuff;
+
+			lwasm_parse_line(as, nl);
+			if (as -> endseen)
+				break;
+
+		}
+	}
+	
+	// restore context from before the macro was called
+	as -> context = oldcontext;
+
+	// clean up
+	if (args)
+	{
+		while (nargs)
+		{
+			lwasm_free(args[--nargs]);
+		}
+		lwasm_free(args);
+	}
+
+	// indicate a macro was expanded
+	return 0;	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/main.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,199 @@
+/*
+main.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 the program startup code
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <argp.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lwasm.h"
+
+// external declarations
+extern void lwasm_pass1(asmstate_t *as);
+extern void lwasm_pass2(asmstate_t *as);
+extern void lwasm_list(asmstate_t *as);
+extern void lwasm_output(asmstate_t *as);
+extern void pseudo_pragma_real(asmstate_t *as, lwasm_line_t *cl, char **optr, int error);
+
+// command line option handling
+const char *argp_program_version = "LWASM from " PACKAGE_STRING;
+const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+
+static error_t parse_opts(int key, char *arg, struct argp_state *state)
+{
+	asmstate_t *as = state -> input;
+	char *p;
+	
+	switch (key)
+	{
+	case 'o':
+		// output
+		if (as -> outfile)
+		{
+		}
+		as -> outfile = arg;
+		break;
+	
+	case 'd':
+		// debug
+		debug_level++;
+		break;
+	
+	case 'l':
+		// list
+		if (arg)
+			as -> listfile = arg;
+		else
+			as -> listfile = "-";
+		break;
+	
+	case 'b':
+		// decb output
+		as -> outformat = OUTPUT_DECB;
+		break;
+	
+	case 'r':
+		// raw binary output
+		as -> outformat = OUTPUT_RAW;
+		break;
+	
+	case 0x100:
+		// proprietary object format
+		as -> outformat = OUTPUT_OBJ;
+		break;
+		
+	case 'f':
+		// output format
+		if (!strcasecmp(arg, "decb"))
+			as -> outformat = OUTPUT_DECB;
+		else if (!strcasecmp(arg, "raw"))
+			as -> outformat = OUTPUT_RAW;
+		else if (!strcasecmp(arg, "obj"))
+			as -> outformat = OUTPUT_OBJ;
+		else
+		{
+			fprintf(stderr, "Invalid output format: %s\n", arg);
+			exit(1);
+		}
+		break;
+	
+	case 'p':
+		// pragmas
+		p = arg;
+		pseudo_pragma_real(as, NULL, &p, 2);
+		if (!p)
+		{
+			fprintf(stderr, "Invalid pragma string: %s\n", arg);
+			exit(1);
+		}
+		break;
+
+	case ARGP_KEY_END:
+		// done; sanity check
+		if (!as -> outfile)
+			as -> outfile = "a.out";
+		break;
+	
+	case ARGP_KEY_ARG:
+		// non-option arg
+		if (as -> infile)
+			argp_usage(state);
+		as -> infile = arg;
+		break;
+		
+	default:
+		return ARGP_ERR_UNKNOWN;
+	}
+	return 0;
+}
+
+static struct argp_option options[] =
+{
+	{ "output",		'o',	"FILE",	0,
+				"Output to FILE"},
+	{ "debug",		'd',	0,		0,
+				"Set debug mode"},
+	{ "format",		'f',	"TYPE",	0,
+				"Select output format: decb, raw, obj"},
+	{ "list",		'l',	"FILE",	OPTION_ARG_OPTIONAL,
+				"Generate list [to FILE]"},
+	{ "decb",		'b',	0,		0,
+				"Generate DECB .bin format output, equivalent of --format=decb"},
+	{ "raw",		'r',	0,		0,
+				"Generate raw binary format output, equivalent of --format=raw"},
+	{ "obj",		0x100,		0,		0,
+				"Generate proprietary object file format for later linking, equivalent of --format=obj" },
+	{ "pragma",		'p',	"PRAGMA",	0,
+				"Set an assembler pragma to any value understood by the \"pragma\" pseudo op"},
+	{ 0 }
+};
+
+static struct argp argp =
+{
+	options,
+	parse_opts,
+	"<input file>",
+	"LWASM, a HD6309 and MC6809 cross-assembler"
+};
+
+// main function; parse command line, set up assembler state, and run the
+// assembler on the first file
+int main(int argc, char **argv)
+{
+	// assembler state
+	asmstate_t asmstate = { 0 };
+
+	argp_parse(&argp, argc, argv, 0, 0, &asmstate);
+
+	if (!asmstate.infile)
+	{
+		fprintf(stderr, "No input files specified.\n");
+		exit(1);
+	}	
+
+	/* pass 1 - collect the symbols and assign addresses where possible */
+	/* pass 1 also resolves included files, etc. */
+	/* that means files are read exactly once unless included multiple times */
+	lwasm_pass1(&asmstate);
+	
+	// pass 2: actually generate the code; if any phasing errors appear
+	// at this stage, we have a bug
+	lwasm_pass2(&asmstate);
+
+	// now make a pretty listing
+	lwasm_list(&asmstate);
+
+	// now write the code out to the output file
+	lwasm_output(&asmstate);
+
+	if (asmstate.errorcount > 0)
+		exit(1);
+
+	exit(0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/output.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,419 @@
+/*
+output.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/>.
+
+
+Contains the code for actually outputting the assembled code
+*/
+
+//#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+//#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#define __output_c_seen__
+//#include "instab.h"
+#include "lwasm.h"
+#include "util.h"
+
+void write_code_raw(asmstate_t *as, FILE *of);
+void write_code_decb(asmstate_t *as, FILE *of);
+void write_code_rawrel(asmstate_t *as, FILE *of);
+void write_code_obj(asmstate_t *as, FILE *of);
+
+// this prevents warnings about not using the return value of fwrite()
+#define writebytes(s, l, c, f)	do { int r; r = fwrite((s), (l), (c), (f)); } while (0)
+
+void lwasm_output(asmstate_t *as)
+{
+	FILE *of;
+	
+	if (as -> errorcount > 0)
+	{
+		fprintf(stderr, "Not doing output due to assembly errors.\n");
+		return;
+	}
+	
+	of = fopen(as -> outfile, "wb");
+	if (!of)
+	{
+		fprintf(stderr, "Cannot open '%s' for output", as -> outfile);
+		perror("");
+		return;
+	}
+
+	switch (as -> outformat)
+	{
+	case OUTPUT_RAW:
+		write_code_raw(as, of);
+		break;
+		
+	case OUTPUT_DECB:
+		write_code_decb(as, of);
+		break;
+		
+	case OUTPUT_RAWREL:
+		write_code_rawrel(as, of);
+		break;
+	
+	case OUTPUT_OBJ:
+		write_code_obj(as, of);
+		break;
+
+	default:
+		fprintf(stderr, "BUG: unrecognized output format when generating output file\n");
+		fclose(of);
+		unlink(as -> outfile);
+		return;
+	}
+
+	fclose(of);
+}
+
+/*
+rawrel output treats an ORG directive as an offset from the start of the
+file. Undefined results will occur if an ORG directive moves the output
+pointer backward. This particular implementation uses "fseek" to handle
+ORG requests and to skip over RMBs.
+
+This simple brain damanged method simply does an fseek before outputting
+each instruction.
+*/
+void write_code_rawrel(asmstate_t *as, FILE *of)
+{
+	lwasm_line_t *cl;
+	
+	for (cl = as -> lineshead; cl; cl = cl -> next)
+	{
+		if (cl -> codelen == 0)
+			continue;
+		
+		fseek(of, cl -> codeaddr, SEEK_SET);
+		writebytes(cl -> bytes, cl -> codelen, 1, of);
+	}
+}
+
+/*
+raw merely writes all the bytes directly to the file as is. ORG is just a
+reference for the assembler to handle absolute references. Multiple ORG
+statements will produce mostly useless results
+*/
+void write_code_raw(asmstate_t *as, FILE *of)
+{
+	lwasm_line_t *cl;
+	
+	for (cl = as -> lineshead; cl; cl = cl -> next)
+	{
+		if (cl -> nocodelen)
+		{
+			int i;
+			for (i = 0; i < cl -> nocodelen; i++)
+				writebytes("\0", 1, 1, of);
+			continue;
+		}
+		writebytes(cl -> bytes, cl -> codelen, 1, of);
+	}
+}
+
+void write_code_decb(asmstate_t *as, FILE *of)
+{
+	long preambloc;
+	lwasm_line_t *cl;
+	int blocklen = -1;
+	int nextcalc = -1;
+	unsigned char outbuf[5];
+	
+	for (cl = as -> lineshead; cl; cl = cl -> next)
+	{
+		if (cl -> nocodelen)
+			continue;
+		if (cl -> codeaddr != nextcalc && cl -> codelen > 0)
+		{
+			// need preamble here
+			if (blocklen > 0)
+			{
+				// update previous preamble if needed
+				fseek(of, preambloc, SEEK_SET);
+				outbuf[0] = (blocklen >> 8) & 0xFF;
+				outbuf[1] = blocklen & 0xFF;
+				writebytes(outbuf, 2, 1, of);
+				fseek(of, 0, SEEK_END);
+			}
+			blocklen = 0;
+			nextcalc = cl -> codeaddr;
+			outbuf[0] = 0x00;
+			outbuf[1] = 0x00;
+			outbuf[2] = 0x00;
+			outbuf[3] = (nextcalc >> 8) & 0xFF;
+			outbuf[4] = nextcalc & 0xFF;
+			preambloc = ftell(of) + 1;
+			writebytes(outbuf, 5, 1, of);
+		}
+		nextcalc += cl -> codelen;
+		writebytes(cl -> bytes, cl -> codelen, 1, of);
+		blocklen += cl -> codelen;
+	}
+	if (blocklen > 0)
+	{
+		fseek(of, preambloc, SEEK_SET);
+		outbuf[0] = (blocklen >> 8) & 0xFF;
+		outbuf[1] = blocklen & 0xFF;
+		writebytes(outbuf, 2, 1, of);
+		fseek(of, 0, SEEK_END);
+	}
+	
+	// now write postamble
+	outbuf[0] = 0xFF;
+	outbuf[1] = 0x00;
+	outbuf[2] = 0x00;
+	outbuf[3] = (as -> execaddr >> 8) & 0xFF;
+	outbuf[4] = (as -> execaddr) & 0xFF;
+	writebytes(outbuf, 5, 1, of);
+}
+
+void write_code_obj_sbadd(sectiontab_t *s, unsigned char b)
+{
+	if (s -> oblen >= s -> obsize)
+	{
+		s -> obytes = lwasm_realloc(s -> obytes, s -> obsize + 128);
+		s -> obsize += 128;
+	}
+	s -> obytes[s -> oblen] = b;
+	s -> oblen += 1;
+}
+
+void write_code_obj(asmstate_t *as, FILE *of)
+{
+	lwasm_line_t *l;
+	sectiontab_t *s;
+	lwasm_symbol_ent_t *se;
+	export_list_t *ex;
+	section_reloc_list_t *re;
+	lwasm_expr_stack_node_t *sn;			
+	
+	int i;
+	unsigned char buf[16];
+
+	// output the magic number and file header
+	// the 8 is NOT an error
+	writebytes("LWOBJ16", 8, 1, of);
+	
+	// run through the entire system and build the byte streams for each
+	// section; at the same time, generate a list of "local" symbols to
+	// output for each section
+	// NOTE: for "local" symbols, we will append \x01 and the ascii string
+	// of the context identifier (so sym in context 1 would be "sym\x011"
+	// we can do this because the linker can handle symbols with any
+	// character other than NUL.
+	// also we will generate a list of incomplete references for each
+	// section along with the actual definition that will be output
+	
+	// once all this information is generated, we will output each section
+	// to the file
+	
+	// NOTE: we build everything in memory then output it because the
+	// assembler accepts multiple instances of the same section but the
+	// linker expects only one instance of each section in the object file
+	// so we need to collect all the various pieces of a section together
+	// (also, the assembler treated multiple instances of the same section
+	// as continuations of previous sections so we would need to collect
+	// them together anyway.
+	
+	for (l = as -> lineshead; l; l = l -> next)
+	{
+		if (l -> sect)
+		{
+			// we're in a section - need to output some bytes
+			for (i = 0; i < l -> codelen; i++)
+				write_code_obj_sbadd(l -> sect, l -> bytes[i]);
+			for (i = 0; i < l -> nocodelen; i++)
+				write_code_obj_sbadd(l -> sect, 0);
+			
+			// do we have a "relocation"? If so, add a reference to the
+			// relocation table
+			if (l -> relocoff >= 0)
+			{
+				// build the relocation reference for the linker
+				re = lwasm_alloc(sizeof(section_reloc_list_t));
+				re -> next = l -> sect -> rl;
+				l -> sect -> rl = re;
+				
+				re -> offset = l -> codeaddr + l -> relocoff;
+				re -> expr = l -> exprs[0];
+				re -> context = l -> context;
+			}
+		}
+	}
+	
+	// run through the sections
+	for (s = as -> sections; s; s = s -> next)
+	{
+		// write the name
+		writebytes(s -> name, strlen(s -> name) + 1, 1, of);
+		
+		// write the flags
+		if (s -> flags & SECTION_BSS)
+			writebytes("\x01", 1, 1, of);
+		
+		// indicate end of flags - the "" is NOT an error
+		writebytes("", 1, 1, of);
+		
+		
+		// now the local symbols
+		for (se = as -> symhead; se; se = se -> next)
+		{
+			// ignore symbols not in this section
+			if (se -> sect != s)
+				continue;
+			
+			if (se -> flags & SYMBOL_SET)
+				continue;
+			
+			if (se -> flags & SYMBOL_EXTERN)
+				continue;
+			
+			writebytes(se -> sym, strlen(se -> sym), 1, of);
+			if (se -> context >= 0)
+			{
+				writebytes("\x01", 1, 1, of);
+				sprintf(buf, "%d", se -> context);
+				writebytes(buf, strlen(buf), 1, of);
+			}
+			// the "" is NOT an error
+			writebytes("", 1, 1, of);
+			
+			// write the address
+			buf[0] = (se -> value >> 8) & 0xff;
+			buf[1] = se -> value & 0xff;
+			writebytes(buf, 2, 1, of);
+		}	
+		// flag end of local symbol table - "" is NOT an error
+		writebytes("", 1, 1, of);
+		
+		// now the exports
+		for (ex = s -> exports; ex; ex = ex -> next)
+		{
+			writebytes(ex -> sym, strlen(ex -> sym) + 1, 1, of);
+			buf[0] = (ex -> offset >> 8) & 0xff;
+			buf[1] = ex -> offset & 0xff;
+			writebytes(buf, 2, 1, of);
+		}
+		
+		// flag end of exported symbols - "" is NOT an error
+		writebytes("", 1, 1, of);
+		
+		// now output the "incomplete references"
+		// this being the most complex bit
+		for (re = s -> rl; re; re = re -> next)
+		{
+			if (re -> expr == NULL)
+			{
+				// this is an error but we'll simply ignore it
+				// and not output this expression
+				continue;
+			}
+			
+			// work through each term in the expression and output
+			// the proper equivalent to the object file
+			for (sn = re -> expr -> head; sn; sn = sn -> next)
+			{
+				switch (sn -> term -> term_type)
+				{
+				case LWASM_TERM_OPER:
+					buf[0] =  0x04;
+					buf[1] = sn -> term -> value;
+					writebytes(buf, 2, 1, of);
+					break;
+					
+				case LWASM_TERM_INT:
+					buf[0] = 0x01;
+					buf[1] = (sn -> term -> value >> 8) & 0xff;
+					buf[2] = sn -> term -> value & 0xff;
+					writebytes(buf, 3, 1, of);
+					break;
+				
+				case LWASM_TERM_SECBASE:
+					writebytes("\x05", 1, 1, of);
+					break;
+
+				case LWASM_TERM_SYM:
+					// now for the ugly part - resolve a symbol reference
+					// and determine whether it's internal, external, or
+					// a section base
+					se = lwasm_find_symbol(as, sn -> term -> symbol, re -> context);
+					if (!se)
+						se = lwasm_find_symbol(as, sn -> term -> symbol, -1);
+					if (!se || se -> flags & SYMBOL_EXTERN)
+					{
+						// not found - assume external reference
+						// found but flagged external - handle it
+						writebytes("\x02", 1, 1, of);
+						writebytes(se -> sym, strlen(se -> sym) + 1, 1, of);
+						break;
+					}
+					// a local symbol reference here
+					writebytes("\x03", 1, 1, of);
+					writebytes(se -> sym, strlen(se -> sym), 1, of);
+					if (se -> context >= 0)
+					{
+						writebytes("\x01", 1, 1, of);
+						sprintf(buf, "%d", se -> context);
+						writebytes(buf, strlen(buf), 1, of);
+					}
+					writebytes("", 1, 1, of);
+					break;
+
+				default:
+					// unrecognized term type - replace with integer 0
+					buf[0] = 0x01;
+					buf[1] = 0x00;
+					buf[2] = 0x00;
+					writebytes(buf, 3, 1, of);
+					break;
+				}
+			}
+			
+			// flag end of expressions
+			writebytes("", 1, 1, of);
+			
+			// write the offset
+			buf[0] = (re -> offset >> 8) & 0xff;
+			buf[1] = re -> offset & 0xff;
+			writebytes(buf, 2, 1, of);
+		}
+		// flag end of incomplete references list
+		writebytes("", 1, 1, of);
+		
+		// now blast out the code
+		
+		// length
+		buf[0] = s -> oblen >> 8 & 0xff;
+		buf[1] = s -> oblen & 0xff;
+		writebytes(buf, 2, 1, of);
+		
+		if (!(s -> flags & SECTION_BSS))
+		{
+			writebytes(s -> obytes, s -> oblen, 1, of);
+		}
+	}
+	
+	// flag no more sections
+	// the "" is NOT an error
+	writebytes("", 1, 1, of);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/parse.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,196 @@
+/*
+parse.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/>.
+*/
+
+/*
+Contains the general parser
+*/
+
+#define __parse_c_seen__
+
+#include <ctype.h>
+#include <string.h>
+
+#include "lwasm.h"
+#include "instab.h"
+#include "util.h"
+
+// parse a line and despatch to the appropriate handlers for opcodes
+int lwasm_parse_line(asmstate_t *as, lwasm_line_t *l)
+{
+	char *p, *p2;
+	char *opc;
+	int opnum;
+	char *sym = NULL;
+
+	// if this was a bad op first pass (or otherwise a no-process line)
+	// ignore it
+	if (l -> badop)
+		return;
+	
+	p = l -> text;
+	l -> sect = as -> csect;
+
+	// blank lines are a no brainer
+	if (!*p)
+	{
+		as -> context = lwasm_next_context(as);
+		return 0;
+	}
+	
+	// for output generation later but only on pass 1
+	// also used by some pseudo ops on pass 2
+	if (as -> passnum == 1)
+		l -> codeaddr = as -> addr;
+	
+	// if it's a comment, return (this doesn't cause a context change)
+	if (*p == '*' || *p == ';')
+		return;
+	
+	// if we start with a non-space character, it's a symbol
+	if (!isspace(*p))
+	{
+		// we have a symbol specified here
+		// parse it out and record it for later use
+		for (p2 = p; *p2 && !isspace(*p2); p2++)
+			/* do nothing */ ;
+		
+		sym = lwasm_alloc((p2 - p) + 1);
+		sym[p2 - p] = '\0';
+		memcpy(sym, p, p2 - p);
+		
+		p = p2;
+	}
+	l -> sym = sym;
+
+	// now skip any whitespace to find the opcode
+	while (*p && isspace(*p))
+		p++;
+	
+	// is the line blank?
+	if (!*p && !sym)
+	{
+		// nothing but white space *is* a context break
+		as -> context = lwasm_next_context(as);
+		return;
+	}
+	
+	// parse the opcode
+	for (p2 = p; *p2 && !isspace(*p2); p2++)
+		/* do nothing */ ;
+	
+	opc = lwasm_alloc((p2 - p) + 1);
+	memcpy(opc, p, p2 - p);
+	opc[p2 - p] = '\0';
+
+	debug_message(2, "Found operation code: '%s'", opc);
+
+	// skip intervening whitespace if present
+	while (*p2 && isspace(*p2))
+		p2++;
+
+	// look up instruction in insn table
+	for (opnum = 0; instab[opnum].opcode; opnum++)
+	{
+		if (!strcasecmp(instab[opnum].opcode, opc))
+			break;
+	}
+	
+	// if we found no operation, check if we had a comment
+	// the reason this check is here is to allow for "private"
+	// operation codes like "*pragma" which will be ignored by
+	// other assemblers
+	// also skip empty ops
+	if (!(instab[opnum].opcode))
+	{
+		if (*opc == '*' || *opc == ';' || !*opc)
+			goto done_line;
+	}
+
+	// now we have the opcode and the symbol, we can decide if we're
+	// actually going to do anything with this line
+	
+	// we will NOT call the function if any of the following are true:
+	
+	// - we are skipping a condition and the operation code is not a conditional
+	// - we are defining a macro and the operation code is not ENDM
+
+	// we will call the function in any other circumstance
+	
+	// first condition above
+	if (as -> inmacro && instab[opnum].endm == 0)
+	{
+		add_macro_line(as, l -> text);
+		goto done_line;
+	}
+
+	// second condition above	
+	if (as -> skipcond && instab[opnum].iscond == 0)
+		goto done_line;
+
+	// we've registered the symbol as needed
+	// now we need to check for a macro call IFF we don't collide with
+	// an operation code; otherwise, call the operation function
+	if (instab[opnum].opcode)
+	{
+		if (instab[opnum].fn)
+		{
+			(instab[opnum].fn)(as, l, &p2, opnum);
+		}
+		else
+		{
+			// carp about unimplemented operation
+			register_error(as, l, 1, "Unimplemented operation code: %s", opc);
+		}
+	}
+	else
+	{
+		if (expand_macro(as, l, &p2, opc) == 0)
+			goto done_line;
+
+		// carp about an unknown operation code and note that fact for
+		// pass 2 in case a macro appears later with the same name!
+		register_error(as, l, 1, "Uknown operation code: %s", opc);
+		l -> badop = 1;
+	}
+
+done_line:
+	if (!(as -> skipcond || as -> inmacro))
+	{
+		// register symbol if the operation didn't
+		if (sym && instab[opnum].setsym == 0)
+		{
+			if (as -> passnum == 1)
+			{
+				debug_message(1, "Registering symbol '%s' at %04X", sym, l -> codeaddr);
+				if (lwasm_register_symbol(as, l, sym, l -> codeaddr, SYMBOL_NORM) < 0)
+					l -> sym = NULL;
+				else
+					l -> addrset = 1;
+			}
+		}
+	}
+
+	l -> sect = as -> csect;
+	l -> context = as -> context;
+	
+	lwasm_free(opc);
+	if (sym)
+		lwasm_free(sym);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/pass1.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,178 @@
+/*
+pass1.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/>.
+
+
+Handles first pass of assembly
+
+First pass involves the following:
+
+1. read all lines from the main source file, following all "include"
+   directives as appropriate
+2. each operand is evaluated for syntax and futher for value if there are
+   multiple addressing sizes available; any undefined or not fully resolved
+   value will default to the largest addressing size available (16 bit)
+3. addresses are assigned to every symbol defined in the assembly
+4. macros are defined and expanded at this pass
+
+* note: the lines are re-evaluated on the second pass
+
+All source lines are read into memory with a record of the file name and
+line number within the files.
+
+Lines are one of the following formats:
+
+<symbol> <opcode> <operand> <comment>
+<symbol> <opcode> <comment>
+ <opcode> <operand> <comment>
+ <opcode> <comment>
+
+A "*" or ";" appearing anywhere on the line that is not otherwise interpreted
+as part of an operation code or operand introduces a comment.
+
+Certain lwasm specific operations are prefixed with a "*" to aid in source
+code portability (like *pragma).
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lwasm.h"
+#include "util.h"
+
+
+extern int lwasm_parse_line(asmstate_t *as, lwasm_line_t *l);
+
+// we can't use standard line inputting functions here because we have to
+// handle non-standard line terminations (CR, LF, CRLF, or LFCR)
+int lwasm_read_file(asmstate_t *as, const char *filename)
+{
+	FILE *f;
+	int c, c2;
+	lwasm_line_t *nl;
+	int lineno = 1;
+	char *fnref;
+	
+	// ought to be long enough...we truncate longer lines
+	char linebuff[2049];
+	int lbloc = 0;
+	int eol = 0;
+
+	// add filename to list
+	as -> filelist = lwasm_realloc(as -> filelist, sizeof(char *) * (as -> filelistlen + 1));
+	fnref = as -> filelist[as -> filelistlen] = lwasm_strdup(filename);
+	as -> filelistlen += 1;
+	
+	f = fopen(filename, "rb");
+	if (!f)
+		return -1;
+
+	for (;;)
+	{
+		c = fgetc(f);
+		if (c == EOF)
+		{
+			linebuff[lbloc] = '\0';
+			eol = 1;
+		}
+		else if (c == '\r')
+		{
+			linebuff[lbloc] = '\0';
+			eol = 1;
+			// check for '\n':
+			c2 = fgetc(f);
+			if (c2 == EOF)
+				c = EOF;
+			else if (c2 != '\n')
+				ungetc(c2, f);
+		}
+		else if (c == '\n')
+		{
+			linebuff[lbloc] = '\0';
+			eol = 1;
+			// check for '\r':
+			c2 = fgetc(f);
+			if (c2 == EOF)
+				c = EOF;
+			else if (c2 != '\r')
+				ungetc(c2, f);
+		}
+		else
+		{
+			// silently ignore characters past 2K on a line... FIXME
+			if (lbloc < 2048)
+				linebuff[lbloc++] = c;
+		}
+		if (eol)
+		{
+			eol = 0;
+			lbloc = 0;
+			nl = lwasm_alloc(sizeof(lwasm_line_t));
+			nl -> text = lwasm_strdup(linebuff);
+			nl -> lineno = lineno++;
+			nl -> filename = fnref;
+			nl -> next = NULL;
+			nl -> prev = as -> linestail;
+			nl -> err = NULL;
+			nl -> fsize = 0;
+			nl -> sym = NULL;
+			nl -> bytes = NULL;
+			nl -> codelen = 0;
+			nl -> codesize = 0;
+			nl -> nocodelen = 0;
+			nl -> addrset = 0;
+			nl -> symaddr = -1;
+			nl -> badop = 0;
+			nl -> relocoff = -1;
+			if (as -> linestail)
+				as -> linestail -> next = nl;
+			as -> linestail = nl;
+			if (!(as -> lineshead))
+				as -> lineshead = nl;
+			lwasm_parse_line(as, nl);
+			if (as -> endseen)
+				break;
+		}
+		if (c == EOF)
+			break;
+	}
+	
+	fclose(f);
+	return 0;
+}
+
+void lwasm_pass1(asmstate_t *as)
+{
+	as -> passnum = 1;
+	as -> addr = 0;
+	as -> nextcontext = 1;
+	
+	debug_message(1, "Entering pass 1");
+	if (lwasm_read_file(as, as -> infile) < 0)
+	{
+		fprintf(stderr, "Error reading input file '%s'", as -> infile);
+		perror("");
+		exit(1);
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/pass2.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,61 @@
+/*
+pass2.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/>.
+
+
+Handles second pass of assembly
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "lwasm.h"
+
+void lwasm_pass2(asmstate_t *as)
+{
+	lwasm_line_t *l;
+	sectiontab_t *st;
+	
+	debug_message(1, "Entering pass 2");
+	as -> passnum = 2;
+	as -> addr = 0;
+	as -> context = 0;
+	as -> endseen = 0;
+	as -> skipcond = 0;
+	as -> skipcount = 0;
+	as -> skipmacro = 0;
+	as -> inmacro = 0;
+	as -> nextcontext = 1;
+	as -> skiplines = 0;
+	as -> dpval = 0;
+	
+	for (st = as -> sections; st; st = st -> next)
+		st -> offset = 0;
+	as -> csect = NULL;
+	
+	// iterate over all the lines and re-parse them
+	for (l = as -> lineshead; l && !(as -> endseen); l = l -> next)
+	{
+		if (as -> skiplines)
+			as -> skiplines--;
+		else
+			lwasm_parse_line(as, l);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/pragma.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,123 @@
+/*
+pragma.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/>.
+
+
+This file contains stuff associated with lwasm specific strangeness
+*/
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lwasm.h"
+#include "instab.h"
+
+/*
+A pragma is a means of controlling code generation.
+
+The pseudo op "*pragma" which will be treated as a comment by an assembler
+that doesn't recognize it and thus will not cause assembly errors. This is
+the preferred way of flagging a pragma if it will not cause incorrect
+execution of the program.
+
+The pseudo op "pragma" which will cause an error on an assembler that does
+not understand it.
+
+In the case of "*pragma", unrecognized pragmas MUST be silently ignored. In
+the case of "pragma", unrecognized pragmas should raise an error.
+
+LWASM understands the following pragmas:
+
+index0tonone
+noindex0tonone
+
+When set (index0tonone), an expression that evaluates to 0, other than a
+bare constant, in a <offset>,r operand will cause the code for ",r" to be
+emitted rather than "0,r". If not set (noindex0tonone), the "0,r" output
+will be emitted. The default is to perform the optimization.
+
+This particular optimization will save a cycle for a direct operation. For
+an indirect operation, however, it will save several cycles and a program byte
+which may be very useful.
+*/
+
+void pseudo_pragma_real(asmstate_t *as, lwasm_line_t *cl, char **optr, int error)
+{
+	char pragma[128];
+	int c = 0;
+	
+	while (isspace(**optr))
+		(*optr)++;
+	
+	while (c < 127 && **optr && !isspace(**optr))
+	{
+		pragma[c++] = **optr;
+		(*optr)++;
+	}
+	
+	if (c == 0 || (**optr && !isspace(**optr)))
+	{
+		if (error)
+		{
+			register_error(as, cl, 1, "Unrecognized pragma");
+		}
+		if (error == 2)
+		{
+			*optr = NULL;
+		}
+		return;
+	}
+	pragma[c] = 0;
+	if (!strcasecmp(pragma, "noindex0tonone"))
+	{
+		as -> pragmas |= PRAGMA_NOINDEX0TONONE;
+	}
+	else if (!strcasecmp(pragma, "index0tonone"))
+	{
+		as -> pragmas &= ~PRAGMA_NOINDEX0TONONE;
+	}
+	else if (!strcasecmp(pragma, "undefextern"))
+	{
+		as -> pragmas |= PRAGMA_UNDEFEXTERN;
+	}
+	else if (!strcasecmp(pragma, "noundefextern"))
+	{
+		as -> pragmas &= ~PRAGMA_UNDEFEXTERN;
+	}
+	else
+	{
+		if (error)
+		{
+			register_error(as, cl, 1, "Unrecognized pragma");
+			if (error == 2)
+			{
+				*optr = NULL;
+			}
+		}
+	}
+}
+
+OPFUNC(pseudo_pragma)
+{
+	pseudo_pragma_real(as, l, p, 1);
+}
+
+OPFUNC(pseudo_starpragma)
+{
+	pseudo_pragma_real(as, l, p, 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/pseudo.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,967 @@
+/*
+pseudo.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/>.
+
+
+This file implements the various pseudo operations.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "lwasm.h"
+#include "instab.h"
+#include "expr.h"
+#include "util.h"
+
+extern int lwasm_read_file(asmstate_t *as, const char *filename);
+
+OPFUNC(pseudo_org)
+{
+	int v, r;
+
+	if (as -> csect)
+	{
+		register_error(as, l, 1, "ORG not allowed within sections");
+		return;
+	}
+
+	if (as -> passnum != 1)
+	{
+		// org is not needed to be processed on pass 2
+		// this will prevent phasing errors for forward references that
+		// resolve on the second pass
+		// we saved the org address in l -> codeaddr on pass 1
+		as -> addr = l -> codeaddr;
+		return;
+	}
+	
+	if (l -> sym)
+	{
+		register_error(as, l, 1, "No symbol allowed with ORG");
+	}
+	
+	r = lwasm_expr_result2(as, l, p, EXPR_PASS1CONST, &v, 0);
+	if (r != 0)
+		return;
+	l -> codeaddr = v;
+	l -> addrset = 1;
+	as -> addr = v;
+}
+
+/*
+The operand for include is a string optionally enclosed in "
+*/
+OPFUNC(pseudo_include)
+{
+	int v1;
+	char *fn;
+	
+	// only include files on pass 1
+	// but make sure local include context is right
+	// for the next line...
+	if (as -> passnum != 1)
+	{
+		as -> context = lwasm_next_context(as);
+		return;
+	}
+
+	while (**p && isspace(**p))
+		(*p)++;
+
+	if (!**p)
+	{
+		register_error(as, l, 1, "Bad file name");
+		return;
+	}
+
+	if (**p == '"')
+	{
+		// search for ending "
+		(*p)++;
+		for (v1 = 0; *((*p)+v1) && *((*p)+v1) != '"'; v1++)
+			/* do nothing */ ;
+		if (*((*p)+v1) != '"')
+		{
+			register_error(as, l, 1, "Bad file name");
+			return;
+		}
+	}
+	else
+	{
+		// search for a space type character
+		for (v1 = 0; *((*p)+v1) && !isspace(*((*p)+v1)); v1++)
+			;
+	}
+
+	fn = lwasm_alloc(v1 + 1);
+	memcpy(fn, *p, v1);
+	fn[v1] = '\0';
+
+	// end local label context on include	
+	as -> context = lwasm_next_context(as);
+	if (lwasm_read_file(as, fn) < 0)
+	{
+		register_error(as, l, 1, "File include error (%s)", fn);
+	}
+	lwasm_free(fn);
+}
+
+OPFUNC(pseudo_rmb)
+{
+	int r, v;
+	
+	if (as -> passnum == 2)
+	{
+		as -> addr += l -> nocodelen;
+		return;
+	}
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, -1);
+	if (r != 0)
+		return;
+	l -> nocodelen = v;
+	as -> addr += v;
+}
+
+OPFUNC(pseudo_rmd)
+{
+	int r, v;
+	
+	if (as -> passnum == 2)
+	{
+		as -> addr += l -> nocodelen;
+		return;
+	}
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
+	if (r != 0)
+		return;
+	v *= 2;
+	l -> nocodelen = v;
+	as -> addr += v;
+}
+
+OPFUNC(pseudo_rmq)
+{
+	int r, v;
+	
+	if (as -> passnum == 2)
+	{
+		as -> addr += l -> nocodelen;
+		return;
+	}
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
+	if (r != 0)
+		return;
+	v *= 4;
+	l -> nocodelen = v;
+	as -> addr += v;
+}
+
+OPFUNC(pseudo_zmb)
+{
+	int r, v;
+	
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
+	if (r != 0)
+		return;
+	while (v--)
+		lwasm_emit(as, l, 0);
+}
+
+OPFUNC(pseudo_zmd)
+{
+	int r, v;
+	
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
+	if (r != 0)
+		return;
+	v *= 2;
+	while (v--)
+		lwasm_emit(as, l, 0);
+}
+
+OPFUNC(pseudo_zmq)
+{
+	int r, v;
+	
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
+	if (r != 0)
+		return;
+	v *= 4;
+	while (v--)
+		lwasm_emit(as, l, 0);
+}
+
+OPFUNC(pseudo_end)
+{
+	int r, v;
+	lwasm_expr_stack_t *s;
+	
+
+	as -> endseen = 1;
+	
+	// address only matters for DECB output
+	if (as -> outformat != OUTPUT_DECB)
+		return;
+	
+	r = lwasm_expr_result2(as, l, p, 0, &v, 0);
+	if (r != 0)
+	{
+		register_error(as, l, 2, "Bad operand");
+	}
+
+	v = v & 0xffff;
+	if (as -> passnum == 2)
+	{
+		as -> execaddr = v;
+		l -> symaddr = v;
+		l -> addrset = 2;
+	}
+}
+
+
+OPFUNC(pseudo_align)
+{
+	int cn;
+	int r, v;
+	
+	if (as -> passnum == 2)
+	{
+		while (as -> addr < l -> symaddr)
+			lwasm_emit(as, l, 0);
+		return;
+	}
+	
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
+	if (r != 0)
+	{
+		l -> symaddr = as -> addr;
+		return;
+	}
+
+	if (v < 1)
+	{
+		register_error(as, l, 1, "Illegal alignment %d", v);
+		return;
+	}
+	
+	cn = l -> codeaddr % v;
+	if (cn)
+		cn = v - cn; 
+
+	while (cn--)
+	{
+		lwasm_emit(as, l, 0);
+	}
+	l -> symaddr = as -> addr;
+}
+
+OPFUNC(pseudo_equ)
+{
+	int r, v;
+
+	if (l -> sym == NULL)
+	{
+		register_error(as, l, 1, "No symbol specified");
+		return;
+	}
+
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
+	if (r < 0)
+		v = 0;
+
+	l -> symaddr = v & 0xFFFF;
+	l -> addrset = 2;
+	
+	// note: we need to do this because the symbol might have resolved
+	// to a constant!
+	lwasm_register_symbol(as, l, l -> sym, v, (r > 0 ? SYMBOL_COMPLEX: SYMBOL_NORM) | SYMBOL_FORCE);
+}
+
+OPFUNC(pseudo_set)
+{
+	int r, v;
+
+	// set MUST run on both passes as the symbol value changes!
+
+	if (l -> sym == NULL)
+	{
+		register_error(as, l, 1, "No symbol specified");
+		return;
+	}
+
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
+	if (r < 0)
+		v = 0;
+
+	l -> symaddr = v & 0xFFFF;
+	l -> addrset = 2;
+	
+	lwasm_register_symbol(as, l, l -> sym, v, (r > 0 ? SYMBOL_COMPLEX: SYMBOL_NORM) | SYMBOL_SET);
+}
+
+OPFUNC(pseudo_setdp)
+{
+	int r, v;
+
+	if (as -> outformat == OUTPUT_OBJ)
+	{
+		register_error(as, l, 1, "SETDP not permitted with OBJ target");
+		return;
+	}
+	
+	// setdp is needed on both passes; must resolve to a constant on pass 1
+	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
+	if (r != 0)
+		return;
+
+	if (v < -127 || v > 255)
+	{
+		register_error(as, l, 1, "Byte overflow");
+		return;
+	}
+	
+	l -> symaddr = v & 0xFF;
+	l -> addrset = 2;
+	
+	as -> dpval = v & 0xFF;
+}
+
+OPFUNC(pseudo_fcc)
+{
+	int delim = 0;
+				
+	delim = **p;
+	if (!delim)
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	*p += 1;
+	while (**p && **p != delim)
+	{
+		lwasm_emit(as, l, **p);
+		(*p)++;
+	}
+	if (**p)
+		(*p)++;
+}
+		
+
+OPFUNC(pseudo_fcs)
+{
+	int delim = 0;
+
+	delim = **p;
+	if (!delim)
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	*p += 1;
+	while (**p && **p != delim)
+	{
+		if (!*((*p) + 1) || *((*p) + 1) == delim)
+			lwasm_emit(as, l, **p | 0x80);
+		else
+			lwasm_emit(as, l, **p);
+		(*p)++;
+	}
+	if (**p)
+		(*p)++;
+}
+
+OPFUNC(pseudo_fcn)
+{		
+	int delim = 0;
+				
+	delim = **p;
+	if (!delim)
+	{
+		register_error(as, l, 1, "Bad operand");
+		return;
+	}
+	*p += 1;
+	while (**p && **p != delim)
+	{
+		lwasm_emit(as, l, **p);
+		(*p)++;
+	}
+	if (**p)
+		(*p)++;
+	lwasm_emit(as, l, 0);
+}
+
+// FIXME: handle external, etc., references in a useful manner
+OPFUNC(pseudo_fcb)
+{
+	int r, v;
+	
+fcb_again:
+	r = lwasm_expr_result2(as, l, p, 0, &v, -1);
+	if (r < 0)
+		return;
+
+	if (r > 0)
+	{
+		register_error(as, l, 2, "Illegal external or inter-segment reference");
+		v = 0;
+	}
+
+	if (v < -127 || v > 255)
+	{
+		register_error(as, l, 1, "Byte overflow");
+	}
+	
+	lwasm_emit(as, l, v);
+	if (**p == ',')
+	{
+		(*p)++;
+		goto fcb_again;
+	}
+}
+
+// FIXME: handle external references in an intelligent way
+OPFUNC(pseudo_fdb)
+{			
+	int r, v;
+	int extseen = 0;
+	char *p1;
+	
+fdb_again:
+	p1 = *p;
+	r = lwasm_expr_result2(as, l, p, 0, &v, -1);
+	if (r < 0)
+		return;
+
+	if (r > 0 && extseen == 1)
+	{
+		register_error(as, l, 2, "Illegal external or inter-segment reference (only 1 per FDB line)");
+		v = 0;
+	}
+	else if (r > 0)
+	{
+		l -> relocoff = as -> addr - l -> codeaddr;
+		*p = p1;
+		r = lwasm_expr_result2(as, l, p, 0, &v, 0);
+	}
+
+	lwasm_emit(as, l, v >> 8);
+	lwasm_emit(as, l, v & 0xff);
+	if (**p == ',')
+	{
+		(*p)++;
+		goto fdb_again;
+	}
+}
+
+// FIXME: handle external references in a sensible way
+OPFUNC(pseudo_fqb)
+{	
+	int r, v;
+	
+fqb_again:
+	r = lwasm_expr_result2(as, l, p, 0, &v, -1);
+	if (r < 0)
+		return;
+
+	if (r > 0)
+	{
+		register_error(as, l, 2, "Illegal external or inter-segment reference");
+		v = 0;
+	}
+
+	lwasm_emit(as, l, v >> 24);
+	lwasm_emit(as, l, v >> 16);
+	lwasm_emit(as, l, v >> 8);
+	lwasm_emit(as, l, v & 0xff);
+	if (**p == ',')
+	{
+		(*p)++;
+		goto fqb_again;
+	}
+}
+
+// don't need to do anything if we are executing one of these
+OPFUNC(pseudo_endc)
+{
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount -= 1;
+		if (as -> skipcount <= 0)
+		{
+			as -> skipcond = 0;
+		}
+	}
+	return;
+}
+
+// if "else" executes, we must be going into an "ignore" state
+OPFUNC(pseudo_else)
+{
+	if (as -> skipmacro)
+		return;
+	
+	if (as -> skipcond)
+	{
+		if (as -> skipcount == 1)
+		{
+			as -> skipcount = 0;
+			as -> skipcond = 0;
+		}
+		return;
+	}
+	
+	as -> skipcond = 1;
+	as -> skipcount = 1;
+}
+
+OPFUNC(pseudo_ifne)
+{
+	int v1;
+	int rval;
+
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		return;
+	}
+
+	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
+	if (rval != 0)
+		return;
+	if (!v1)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+OPFUNC(pseudo_ifdef)
+{
+	lwasm_symbol_ent_t *se;
+	char *sym;
+	char *p2;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		return;
+	}
+
+	if (as -> passnum != 1)
+	{
+		if (!(l -> fsize))
+		{
+			as -> skipcond = 1;
+			as -> skipcount = 1;
+		}
+		return;
+	}
+
+	if (!**p)
+	{
+		register_error(as, l, 1, "Need symbol name");
+		return;
+	}
+	
+	for (p2 = *p; *p2 && !isspace(*p2); p2++)
+		/* do nothing */ ;
+	
+	sym = lwasm_alloc(p2 - *p + 1);
+	memcpy(sym, *p, p2 - *p);
+	sym[p2 - *p] = '\0';
+	
+	*p = p2;
+
+	se = lwasm_find_symbol(as, sym, l -> context);
+	if (!se)
+		se = lwasm_find_symbol(as, sym, -1);
+	
+	lwasm_free(sym);
+	
+	if (!se)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+		l -> fsize = 0;
+	}
+	else
+	{
+		l -> fsize = 1;
+	}
+}
+
+OPFUNC(pseudo_ifndef)
+{
+	lwasm_symbol_ent_t *se;
+	char *sym;
+	char *p2;
+	
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		return;
+	}
+
+	if (as -> passnum != 1)
+	{
+		if (l -> fsize)
+		{
+			as -> skipcond = 1;
+			as -> skipcount = 1;
+		}
+		return;
+	}
+
+	if (!**p)
+	{
+		register_error(as, l, 1, "Need symbol name");
+		return;
+	}
+	
+	for (p2 = *p; *p2 && !isspace(*p2); p2++)
+		/* do nothing */ ;
+	
+	sym = lwasm_alloc(p2 - *p + 1);
+	memcpy(sym, *p, p2 - *p);
+	sym[p2 - *p] = '\0';
+	
+	*p = p2;
+
+	se = lwasm_find_symbol(as, sym, l -> context);
+	if (!se)
+		se = lwasm_find_symbol(as, sym, -1);
+	
+	lwasm_free(sym);
+	
+	if (se)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+		l -> fsize = 0;
+	}
+	else
+	{
+		l -> fsize = 1;
+	}
+}
+
+OPFUNC(pseudo_ifeq)
+{
+	int v1;
+	int rval;
+
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		return;
+	}
+
+	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
+	if (rval != 0)
+		return;
+	if (v1)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+OPFUNC(pseudo_iflt)
+{
+	int v1;
+	int rval;
+
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		return;
+	}
+
+	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
+	if (rval != 0)
+		return;
+	if (v1 >= 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+OPFUNC(pseudo_ifle)
+{
+	int v1;
+	int rval;
+
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		return;
+	}
+
+	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
+	if (rval != 0)
+		return;
+	if (v1 > 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+OPFUNC(pseudo_ifgt)
+{
+	int v1;
+	int rval;
+
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		return;
+	}
+
+	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
+	if (rval != 0)
+		return;
+	if (v1 <= 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+OPFUNC(pseudo_ifge)
+{
+	int v1;
+	int rval;
+
+	if (as -> skipcond && !(as -> skipmacro))
+	{
+		as -> skipcount++;
+		return;
+	}
+
+	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
+	if (rval != 0)
+		return;
+	if (v1 < 0)
+	{
+		as -> skipcond = 1;
+		as -> skipcount = 1;
+	}
+}
+
+OPFUNC(pseudo_error)
+{
+	register_error(as, l, 1, "User error: %s", *p);
+}
+
+
+OPFUNC(pseudo_section)
+{
+	sectiontab_t *s;
+	char *p2;
+	char *sn;
+	char *opts;
+	
+
+	if (as -> outformat != OUTPUT_OBJ)
+	{
+		register_error(as, l, 1, "Sections only supported for obj target");
+		return;
+	}
+	
+	if (as -> csect)
+	{
+		as -> csect -> offset = as -> addr;
+		as -> csect = NULL;
+	}
+	
+	if (!**p)
+	{
+		register_error(as, l, 1, "Need section name");
+		return;
+	}
+	
+	for (p2 = *p; *p2 && !isspace(*p2); p2++)
+		/* do nothing */ ;
+	
+	sn = lwasm_alloc(p2 - *p + 1);
+	memcpy(sn, *p, p2 - *p);
+	sn[p2 - *p] = '\0';
+	
+	*p = p2;
+	
+	opts = strchr(sn, ',');
+	if (opts)
+	{
+		*opts++ = '\0';
+	}
+	
+	// have we seen the section name already?
+	for (s = as -> sections; s; s = s -> next)
+	{
+		if (!strcmp(s -> name, sn))
+			break;
+	}
+	
+	if (s && as -> passnum == 1)
+	{
+		lwasm_free(sn);
+		if (opts)
+		{
+			register_error(as, l, 1, "Section options can only be specified the first time");
+			return;
+		}
+	}
+	else if (!s)
+	{
+		s = lwasm_alloc(sizeof(sectiontab_t));
+		s -> name = sn;
+		s -> offset = 0;
+		s -> flags = 0;
+		s -> obytes = NULL;
+		s -> oblen = 0;
+		s -> obsize = 0;
+		s -> rl = NULL;
+		s -> exports = NULL;
+		// parse options; only one "bss"
+		if (opts && as -> passnum == 1)
+		{
+			if (!strcasecmp(opts, "bss"))
+			{
+				s -> flags = SECTION_BSS;
+			}
+			else
+			{
+				register_error(as, l, 1, "Unrecognized section option '%s'", opts);
+				lwasm_free(s -> name);
+				lwasm_free(s);
+				return;
+			}
+		}
+		
+		s -> next = as -> sections;
+		as -> sections = s;
+	}
+	as -> addr = s -> offset;
+	as -> csect = s;
+	as -> context = lwasm_next_context(as);
+}
+
+OPFUNC(pseudo_endsection)
+{
+	if (as -> outformat != OUTPUT_OBJ)
+	{
+		register_error(as, l, 1, "Sections only supported for obj target");
+		return;
+	}
+	
+	if (!(as -> csect))
+	{
+		register_error(as, l, 1, "ENDSECTION when not in a section");
+		return;
+	}
+	
+	as -> csect -> offset = as -> addr;
+	as -> addr = 0;
+	as -> csect = 0;
+	as -> context = lwasm_next_context(as);
+}
+
+OPFUNC(pseudo_extern)
+{
+	if (as -> passnum != 1)
+		return;
+
+	if (as -> outformat != OUTPUT_OBJ)
+	{
+		register_error(as, l, 1, "External references only supported for obj target");
+		return;
+	}
+	
+	if (as -> csect)
+	{
+		register_error(as, l, 1, "Cannot declare external symbols within a section");
+		return;
+	}
+	
+	lwasm_register_symbol(as, l, l -> sym, 0, SYMBOL_EXTERN);
+}
+
+OPFUNC(pseudo_export)
+{
+	lwasm_symbol_ent_t *se;
+	export_list_t *ex;
+	
+	if (as -> outformat != OUTPUT_OBJ)
+	{
+		register_error(as, l, 1, "Symbol exports only supported for obj target");
+		return;
+	}
+	
+	if (as -> passnum == 1)
+		return;
+
+	// the symbol better be defined at this point (pass 2)
+	// local symbols cannot be exported nor can "global" symbols
+	se = lwasm_find_symbol(as, l -> sym, -1);
+	if (!se)
+	{
+		register_error(as, l, 2, "Exported symbols must be fully defined within a section");
+		return;
+	}
+	if (se -> sect == NULL)
+	{
+		register_error(as, l, 2, "Only non-local symbols within a section can be exported");
+		return;
+	}
+
+	if (se -> flags & SYMBOL_SET)
+	{
+		register_error(as, l, 2, "You cannot export symbols defined with SET");
+		return;
+	}
+
+	// if the symbol is not already a simple value, re-evaluate it
+	// and see if it becomes simple
+	
+
+	if (se -> flags & SYMBOL_COMPLEX)
+	{
+		register_error(as, l, 2, "Exported symbols must be fully resolved on pass 2");
+		return;
+	}
+
+	// search for existing export
+	for (ex = se -> sect -> exports; ex; ex = ex -> next)
+		if (!strcmp(l -> sym, ex -> sym))
+			break;
+	if (ex)
+	{
+		register_error(as, l, 2, "Symbol %s already exported", l -> sym);
+		return;
+	}
+
+	// add an external reference
+	ex = lwasm_alloc(sizeof(export_list_t));
+	ex -> next = se -> sect -> exports;
+	se -> sect -> exports = ex;
+	ex -> offset = se -> value;
+	ex -> sym = lwasm_strdup(se -> sym);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/symbol.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,249 @@
+/*
+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"
+#include "expr.h"
+
+/*
+Note that this function may accept symbols that the expression evaluator doesn't
+recognize because the expression evaluator must avoid all ambiguity in order
+to achieve predictable results. The checks here are simply a fuzz check.
+*/
+
+/*
+NOTE: complex symbols always take their value from slot 0 on the expression placeholders
+for a line!
+*/
+int lwasm_register_symbol(asmstate_t *as, lwasm_line_t *l, char *sym, int val, int flags)
+{
+	lwasm_symbol_ent_t *se, *se2;
+	char *p;
+	
+	int scontext = -1;
+	
+	// if the symbol is constant, fall back to simple registration!
+	if (flags & SYMBOL_COMPLEX)
+	{
+		if (l -> exprs[0] == NULL)
+		{
+			val = l -> exprvals[0];
+			flags &= ~SYMBOL_COMPLEX;
+		}
+	}
+	
+	// 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;
+	}
+	
+	if (*sym == '@' && isdigit(sym[1]))
+	{
+		register_error(as, l, 1, "Bad symbol: %s", sym);
+		return -1;
+	}
+	
+	for (p = sym; *p; p++)
+	{
+		if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._$?@0123456789", *sym))
+		{
+			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;
+	}
+	
+	debug_message(3, "lwasm_register_symbol(): registering '%s' (%d) at %04X; flags=%d", sym, scontext, val, flags);
+	
+	// now look it for to see if it is a duplicate
+	se = lwasm_find_symbol(as, sym, scontext);
+	if (se)
+	{
+		if (flags & SYMBOL_FORCE && as -> passnum != 2)
+		{
+			register_error(as, l, 1, "Multiply defined symbol: %s", sym);
+			return -1;
+		}
+		if (!(flags & SYMBOL_SET) || (flags & SYMBOL_SET && !(se -> flags & SYMBOL_SET)))
+		{
+			register_error(as, l, 1, "Mulitply defined symbol: %s", sym);
+			return -1;
+		}
+	}
+	if (se)
+	{
+		se -> value = val;
+		if (flags & SYMBOL_COMPLEX)
+		{
+			se -> expr = l -> exprs[0];
+		}
+		else
+		{
+			se -> expr = NULL;
+		}
+		return;
+	}
+
+	// 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;
+	if (flags & SYMBOL_COMPLEX)
+		se -> expr = l -> exprs[0];
+	se -> sym = lwasm_strdup(sym);
+	se -> context = scontext;
+
+	if (!(flags & SYMBOL_EXTERN))
+		se -> sect = as -> csect;
+	else
+		se -> sect = NULL;
+
+	se -> expr = NULL;
+	se -> flags = flags;
+	se -> externalname = NULL;
+
+	return 0;
+}
+
+lwasm_symbol_ent_t *lwasm_find_symbol(asmstate_t *as, char *sym, int scontext)
+{
+	lwasm_symbol_ent_t *se;
+	static int st = 0;
+	
+	for (se = as -> symhead; se; se = se -> next)
+	{
+		if (scontext == se -> context && !strcmp(sym, se -> sym))
+		{
+			return se;
+		}
+	}
+	if (as -> passnum == 2 && st == 0 && scontext == -1 && as -> outformat == OUTPUT_OBJ && as -> pragmas & PRAGMA_UNDEFEXTERN)
+	{
+		// we want undefined symbols to be considered external
+		// we didn't find it on a lookup so register it as external
+		// but we only do so when looking up in global context
+		st = 1;
+		if (lwasm_register_symbol(as, NULL, sym, 0, SYMBOL_EXTERN))
+		{
+			st = 0;
+			return NULL;
+		}
+		st = 0;
+		
+		// find the newly registered symbol and return it
+		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;
+}
+
+void lwasm_list_symbols(asmstate_t *as, FILE *lf)
+{
+	lwasm_symbol_ent_t *se;
+	
+	for (se = as -> symhead; se; se = se -> next)
+	{
+		if (se -> expr)
+		{
+			fprintf(lf, "<incompl>");
+		}
+		else if (se -> value > 0xffff || se -> value < -0x8000)
+		{
+			fprintf(lf, "%08X ", se -> value);
+		}
+		else
+		{
+			fprintf(lf, "    %04X ", se -> value);
+		}
+		if (se -> context < 0)
+			fputc('G', lf);
+		else
+			fputc('L', lf);
+		
+		if (se -> flags & SYMBOL_SET)
+			fputc('S', lf);
+		else if (se -> flags & SYMBOL_EXTERN)
+			fputc('E', lf);
+		else
+			fputc(' ', lf);
+		
+		fprintf(lf, " %s", se -> sym);
+		
+		if (se -> context >= 0)
+			fprintf(lf, " (%d)", se -> context);
+		
+		if (se -> sect)
+		{
+			fprintf(lf, " [%s]", se -> sect -> name);
+		}
+		
+		fputc('\n', lf);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/util.c	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,84 @@
+/*
+util.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/>.
+*/
+
+/*
+Utility functions
+*/
+
+#define __util_c_seen__
+
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+void *lwasm_alloc(int size)
+{
+	void *ptr;
+	
+	ptr = malloc(size);
+	if (!ptr)
+	{
+		// bail out; memory allocation error
+		fprintf(stderr, "Memory allocation error\n");
+		exit(1);
+	}
+	return ptr;
+}
+
+void *lwasm_realloc(void *optr, int size)
+{
+	void *ptr;
+	
+	if (size == 0)
+	{
+		lwasm_free(optr);
+		return;
+	}
+	
+	ptr = realloc(optr, size);
+	if (!ptr)
+	{
+		fprintf(stderr, "lwasm_realloc(): memory allocation error\n");
+		exit(1);
+	}
+}
+
+void lwasm_free(void *ptr)
+{
+	if (ptr)
+		free(ptr);
+}
+
+char *lwasm_strdup(const char *s)
+{
+	char *d;
+	
+	d = strdup(s);
+	if (!d)
+	{
+		fprintf(stderr, "lwasm_strdup(): memory allocation error\n");
+		exit(1);
+	}
+	
+	return d;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/util.h	Fri Jan 30 04:01:55 2009 +0000
@@ -0,0 +1,44 @@
+/*
+expr.h
+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/>.
+*/
+
+/*
+Utility functions
+*/
+
+#ifndef __util_h_seen__
+#define __util_h_seen__
+
+#ifndef __util_c_seen__
+#define __util_E__ extern
+#else
+#define __util_E__
+#endif
+
+// allocate memory
+__util_E__ void *lwasm_alloc(int size);
+__util_E__ void lwasm_free(void *ptr);
+__util_E__ void *lwasm_realloc(void *optr, int size);
+
+// string stuff
+__util_E__ char *lwasm_strdup(const char *s);
+
+#undef __util_E__
+
+#endif // __util_h_seen__
--- a/src/Makefile.am	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-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 symbol.c output.c pseudo.c macro.c pragma.c
-EXTRA_DIST = instab.h lwasm.h expr.h util.h
--- a/src/insn_gen.c	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,228 +0,0 @@
-/*
-insn_gen.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/>.
-
-Contains code for parsing general addressing modes (IMM+DIR+EXT+IND)
-*/
-
-#include <ctype.h>
-#include <stdlib.h>
-
-#include "lwasm.h"
-#include "instab.h"
-#include "expr.h"
-
-extern void insn_indexed_aux(asmstate_t *as, lwasm_line_t *l, const char **p, int *b1, int *b2, int *b3);
-
-// "extra" is required due to the way OIM, EIM, TIM, and AIM work
-void insn_gen_aux(asmstate_t *as, lwasm_line_t *l, char **optr, int opnum, int extra)
-{
-	int b1 = -1, b2 = -1, b3 = -1;
-
-	const char *optr2;
-	int v1, tv, rval;
-	lwasm_expr_stack_t *s;
-	int f8 = 0;
-	int f16 = 0;
-	int isdp = 0;
-
-	optr2 = *optr;
-	while (*optr2 && !isspace(*optr2) && *optr2 != ',') optr2++
-		/* do nothing */ ;
-
-	if (*optr2 != ',' && **optr != '[')
-	{
-		// not indexed
-		if (l -> fsize == 1)
-			f8 = 1;
-		else if (l -> fsize == 2)
-			f16 = 1;
-
-		if (**optr == '<')
-		{
-			(*optr)++;
-			f8 = 1;
-		}
-		else if (**optr == '>')
-		{
-			(*optr)++;
-			f16 = 1;
-		}
-		rval = lwasm_expr_result2(as, l, optr, 0, &v1, 0);
-		if (rval != 0)
-		{
-			f16 = 1;
-			v1 = 0;
-			l -> fsize = 2;
-		}
-
-		if (((v1 >> 8) & 0xff) == (as -> dpval & 0xff))
-			isdp = 1;
-		
-		// disallow non-explicit DP in obj target
-		if (as -> outformat == OUTPUT_OBJ && !f8)
-			f16 = 1;
-	
-		if (f8 || (!f16 && isdp))
-		{
-			v1 = v1 & 0xffff;
-			tv = v1 - ((as -> dpval) << 8);
-			if (tv < 0 || tv > 0xff)
-			{
-				register_error(as, l, 2, "Byte overflow");
-			}
-			v1 = v1 & 0xff;
-			lwasm_emitop(as, l, instab[opnum].ops[0]);
-			if (extra != -1)
-				lwasm_emit(as, l, extra);
-			lwasm_emit(as, l, v1 & 0xff);
-			return;
-		}
-		else
-		{
-			// everything else is 16 bit....
-			lwasm_emitop(as, l, instab[opnum].ops[2]);
-			if (extra != -1)
-				lwasm_emit(as, l, extra);
-			l -> relocoff = as -> addr - l -> codeaddr;
-			lwasm_emit(as, l, v1 >> 8);
-			lwasm_emit(as, l, v1 & 0xff);
-			return;
-		}
-	}	
-
-	lwasm_emitop(as, l, instab[opnum].ops[1]);
-	if (extra != -1)
-		lwasm_emit(as, l, extra);
-	insn_indexed_aux(as, l, (const char **)optr, &b1, &b2, &b3);
-	if (b1 != -1)
-		lwasm_emit(as, l, b1);
-	if (b2 != -1)
-		lwasm_emit(as, l, b2);
-	if (b3 != -1)
-		lwasm_emit(as, l, b3);
-	return;
-}
-
-// the various insn_gen? functions have an immediate mode of ? bits
-OPFUNC(insn_gen0)
-{
-	if (**p == '#')
-	{
-		register_error(as, l, 1, "Immediate mode not allowed");
-		return;
-	}
-	
-	// handle non-immediate
-	insn_gen_aux(as, l, p, opnum, -1);
-}
-
-OPFUNC(insn_gen8)
-{
-	int rval;
-	int r;
-	
-	if (**p == '#')
-	{
-		lwasm_emitop(as, l, instab[opnum].ops[3]);
-		(*p)++;
-		r = lwasm_expr_result2(as, l, p, 0, &rval, 0);
-		if (r != 0)
-			rval = 0;
-		if (r == 1 && as -> passnum == 2)
-			register_error(as, l, 2, "Illegal external or intersegment reference");
-		lwasm_emit(as, l, rval & 0xff);
-		return;
-	}
-	
-	insn_gen_aux(as, l, p, opnum, -1);
-}
-
-OPFUNC(insn_gen16)
-{
-	int rval, r;
-	
-	if (**p == '#')
-	{
-		lwasm_emitop(as, l, instab[opnum].ops[3]);
-		(*p)++;
-
-		r = lwasm_expr_result2(as, l, p, 0, &rval, 0);
-		if (r != 0)
-			rval = 0;
-		if (r == 1 && as -> passnum == 2)
-		{
-			l -> relocoff = as -> addr - l -> codeaddr;
-		}
-		lwasm_emit(as, l, (rval >> 8) & 0xff);
-		lwasm_emit(as, l, rval & 0xff);
-		return;
-	}
-	
-	insn_gen_aux(as, l, p, opnum, -1);
-}
-
-OPFUNC(insn_gen32)
-{
-	int r, rval;
-	
-	if (**p == '#')
-	{
-		lwasm_emitop(as, l, instab[opnum].ops[3]);
-		(*p)++;
-
-		r = lwasm_expr_result2(as, l, p, 0, &rval, 0);
-		if (r != 0)
-			rval = 0;
-		if (r == 1 && as -> passnum == 2)
-		{
-			register_error(as, l, 2, "Illegal external or intersegment reference");
-		}
-
-		lwasm_emit(as, l, (rval >> 24) & 0xff);
-		lwasm_emit(as, l, (rval >> 16) & 0xff);
-		lwasm_emit(as, l, (rval >> 8) & 0xff);
-		lwasm_emit(as, l, rval & 0xff);
-		return;
-	}
-	
-	insn_gen_aux(as, l, p, opnum, -1);
-}
-
-OPFUNC(insn_imm8)
-{
-	int r, rval;
-	
-	if (**p == '#')
-	{
-		lwasm_emitop(as, l, instab[opnum].ops[0]);
-		(*p)++;
-
-		r = lwasm_expr_result2(as, l, p, 0, &rval, 0);
-		if (r != 0)
-			rval = 0;
-		if (r == 1 && as -> passnum == 2)
-			register_error(as, l, 2, "Illegal external or intersegment reference");
-
-		if (rval < -128 || rval > 255)
-			register_error(as, l, 2, "Byte overflow");
-		lwasm_emit(as, l, rval & 0xff);
-		return;
-	}
-
-	register_error(as, l, 1, "Bad operand");	
-}
--- a/src/instab.c	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,389 +0,0 @@
-/*
-instab.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/>.
-
-
-Contains the instruction table for assembling code
-*/
-
-#include <stdlib.h>
-
-#define __instab_c_seen__
-#include "instab.h"
-
-extern OPFUNC(insn_inh);
-extern OPFUNC(insn_gen8);
-extern OPFUNC(insn_gen16);
-extern OPFUNC(insn_gen32);
-extern OPFUNC(insn_gen0);
-extern OPFUNC(insn_rtor);
-extern OPFUNC(insn_imm8);
-extern OPFUNC(insn_rel8);
-extern OPFUNC(insn_rel16);
-extern OPFUNC(insn_rlist);
-extern OPFUNC(insn_bitbit);
-extern OPFUNC(insn_logicmem);
-extern OPFUNC(insn_tfm);
-extern OPFUNC(insn_indexed);
-
-extern OPFUNC(pseudo_org);
-extern OPFUNC(pseudo_equ);
-extern OPFUNC(pseudo_rmb);
-extern OPFUNC(pseudo_rmd);
-extern OPFUNC(pseudo_rmq);
-extern OPFUNC(pseudo_zmb);
-extern OPFUNC(pseudo_zmd);
-extern OPFUNC(pseudo_zmq);
-extern OPFUNC(pseudo_include);
-extern OPFUNC(pseudo_end);
-extern OPFUNC(pseudo_align);
-extern OPFUNC(pseudo_error);
-extern OPFUNC(pseudo_fcc);
-extern OPFUNC(pseudo_fcs);
-extern OPFUNC(pseudo_fcn);
-extern OPFUNC(pseudo_fcb);
-extern OPFUNC(pseudo_fdb);
-extern OPFUNC(pseudo_fqb);
-extern OPFUNC(pseudo_ifne);
-extern OPFUNC(pseudo_ifeq);
-extern OPFUNC(pseudo_ifgt);
-extern OPFUNC(pseudo_ifge);
-extern OPFUNC(pseudo_iflt);
-extern OPFUNC(pseudo_ifle);
-extern OPFUNC(pseudo_else);
-extern OPFUNC(pseudo_endc);
-extern OPFUNC(pseudo_macro);
-extern OPFUNC(pseudo_endm);
-extern OPFUNC(pseudo_setdp);
-extern OPFUNC(pseudo_set);
-extern OPFUNC(pseudo_section);
-extern OPFUNC(pseudo_endsection);
-extern OPFUNC(pseudo_pragma);
-extern OPFUNC(pseudo_starpragma);
-extern OPFUNC(pseudo_extern);
-extern OPFUNC(pseudo_export);
-extern OPFUNC(pseudo_ifdef);
-extern OPFUNC(pseudo_ifndef);
-
-instab_t instab[] =
-{
-	{ "abx",	{	0x3a,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "adca",	{	0x99,	0xa9,	0xb9,	0x89	},	insn_gen8 },
-	{ "adcb",	{	0xd9,	0xe9,	0xf9,	0xc9	},	insn_gen8 },
-	{ "adcd",	{	0x1099,	0x10a9,	0x10b9,	0x1089	},	insn_gen16 },
-	{ "adcr",	{	0x1031,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	{ "adda",	{	0x9b,	0xab,	0xbb,	0x8b	},	insn_gen8 },
-	{ "addb",	{	0xdb,	0xeb,	0xfb,	0xcb	},	insn_gen8 },
-	{ "addd",	{	0xd3,	0xe3,	0xf3,	0xc3	},	insn_gen16 },
-	{ "adde",	{	0x119b,	0x11ab,	0x11bb,	0x118b	},	insn_gen8 },
-	{ "addf",	{	0x11db,	0x11eb,	0x11fb,	0x11cb	},	insn_gen8 },
-	{ "addr",	{	0x1030,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	{ "addw",	{	0x109b,	0x10ab,	0x10bb,	0x108b	},	insn_gen16 },
-	{ "aim",	{	0x02,	0x62,	0x72,	-0x1	},	insn_logicmem },
-	{ "anda",	{	0x94,	0xa4,	0xb4,	0x84	},	insn_gen8 },
-	{ "andb",	{	0xd4,	0xe4,	0xf4,	0xc4	},	insn_gen8 },
-	{ "andcc",	{	0x1c,	-0x1,	-0x1,	0x1c	},	insn_imm8 },
-	{ "andd",	{	0x1094,	0x10a4,	0x10b4,	0x1084	},	insn_gen16 },
-	{ "andr",	{	0x1034,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	{ "asl",	{	0x08,	0x68,	0x78,	-0x1	},	insn_gen0 },
-	{ "asla",	{	0x48,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "aslb",	{	0x58,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "asld",	{	0x1048,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "asr",	{	0x07,	0x67,	0x77,	-0x1	},	insn_gen0 },
-	{ "asra",	{	0x47,	-0x1,	-0x1,	-0x1	}, 	insn_inh },
-	{ "asrb",	{	0x57,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "asrd",	{	0x1047,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	
-	{ "band",	{	0x1130,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
-	{ "bcc",	{	0x24,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bcs",	{	0x25,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "beor",	{	0x1134,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
-	{ "beq",	{	0x27,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bge",	{	0x2c,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bgt",	{	0x2e,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bhi",	{	0x22,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bhs",	{	0x24,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "biand",	{	0x1131,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
-	{ "bieor",	{	0x1135,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
-	{ "bior",	{	0x1133, -0x1,	-0x1,	-0x1	},	insn_bitbit },
-	{ "bita",	{	0x95,	0xa5,	0xb5,	0x85	},	insn_gen8 },
-	{ "bitb",	{	0xd5,	0xe5,	0xf5,	0xc5	},	insn_gen8 },
-	{ "bitd",	{	0x1095,	0x10a5,	0x10b5,	0x1085	},	insn_gen16 },
-	{ "bitmd",	{	0x113c, -0x1,	-0x1,	0x113c	},	insn_imm8 },
-	{ "ble",	{	0x2f,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "blo",	{	0x25,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bls",	{	0x23,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "blt",	{	0x2d,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bmi",	{	0x2b,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bne",	{	0x26, 	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bor",	{	0x1132,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
-	{ "bpl",	{	0x2a,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bra",	{	0x20,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "brn",	{	0x21,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bsr",	{	0x8d,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bvc",	{	0x28,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	{ "bvs",	{	0x29,	-0x1,	-0x1,	-0x1	},	insn_rel8 },
-	
-	{ "clr",	{	0x0f,	0x6f,	0x7f,	-0x1	},	insn_gen0 },
-	{ "clra",	{	0x4f,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "clrb",	{	0x5f,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "clrd",	{	0x104f,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "clre",	{	0x114f,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "clrf",	{	0x115f,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "clrw",	{	0x105f,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "cmpa",	{	0x91,	0xa1,	0xb1,	0x81	},	insn_gen8 },
-	{ "cmpb",	{	0xd1,	0xe1,	0xf1,	0xc1	},	insn_gen8 },
-	{ "cmpd",	{	0x1093,	0x10a3,	0x10b3,	0x1083	},	insn_gen16 },
-	{ "cmpe",	{	0x1191,	0x11a1,	0x11b1,	0x1181	},	insn_gen8 },
-	{ "cmpf",	{	0x11d1,	0x11e1,	0x11f1,	0x11c1	},	insn_gen8 },
-	{ "cmpr",	{	0x1037,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	{ "cmps",	{	0x119c,	0x11ac,	0x11bc,	0x118c	},	insn_gen16 },
-	{ "cmpu",	{	0x1193,	0x11a3,	0x11b3,	0x1183	},	insn_gen16 },
-	{ "cmpw",	{	0x1091,	0x10a1,	0x10b1,	0x1081	},	insn_gen16 },
-	{ "cmpx",	{	0x9c,	0xac,	0xbc,	0x8c	}, 	insn_gen16 },
-	{ "cmpy",	{	0x109c,	0x10ac,	0x10bc,	0x108c	},	insn_gen16 },
-	{ "com",	{	0x03,	0x63,	0x73,	-0x1	},	insn_gen0 },
-	{ "coma",	{	0x43,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "comb",	{	0x53,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "comd",	{	0x1043,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "come",	{	0x1143,	-0x1, 	-0x1,	-0x1	},	insn_inh },
-	{ "comf", 	{	0x1153, -0x1,	-0x1,	-0x1	}, 	insn_inh },
-	{ "comw",	{	0x1053,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "cwai",	{	0x3c, 	-0x1,	-0x1,	-0x1	},	insn_imm8 },
-	
-	{ "daa",	{	0x19,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "dec",	{	0x0a,	0x6a,	0x7a,	-0x1	},	insn_gen0 },
-	{ "deca",	{	0x4a,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "decb",	{	0x5a,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "decd",	{	0x104a,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "dece",	{	0x114a,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "decf",	{	0x115a,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "decw",	{	0x105a,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "divd",	{	0x118d,	0x119d,	0x11ad,	0x11bd	},	insn_gen8 },
-	{ "divq",	{	0x118e,	0x119e,	0x11ae,	0x11be	},	insn_gen16 },
-
-	{ "eim",	{	0x05,	0x65,	0x75,	-0x1	},	insn_logicmem },
-	{ "eora",	{	0x98,	0xa8,	0xb8,	0x88	},	insn_gen8 },
-	{ "eorb",	{	0xd8,	0xe9,	0xf9,	0xc8	},	insn_gen8 },
-	{ "eord",	{	0x1098,	0x10a8,	0x10b8,	0x1088	},	insn_gen16 },
-	{ "eorr",	{	0x1036,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	{ "exg",	{	0x1e,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	
-	{ "inc",	{	0x0c,	0x6c,	0x7c,	-0x1	},	insn_gen0 },
-	{ "inca",	{	0x4c,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "incb",	{	0x5c,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "incd",	{	0x104c,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "ince",	{	0x114c,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "incf",	{	0x115c,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "incw",	{	0x105c,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	
-	{ "jmp",	{	0x0e,	0x6e,	0x7e,	-0x1	},	insn_gen0 },
-	{ "jsr",	{	0x9d,	0xad,	0xbd,	-0x1	}, 	insn_gen0 },
-	
-	{ "lbcc",	{	0x1024,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbcs",	{	0x1025,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbeq",	{	0x1027,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbge",	{	0x102c,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbgt",	{	0x102e,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbhi",	{	0x1022,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbhs",	{	0x1024,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lble",	{	0x102f,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lblo",	{	0x1025,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbls",	{	0x1023,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lblt",	{	0x102d, -0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbmi",	{	0x102b,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbne",	{	0x1026,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbpl",	{	0x102a,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbra",	{	0x16,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbrn",	{	0x1021,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbsr",	{	0x17,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbvc",	{	0x1028,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lbvs",	{	0x1029,	-0x1,	-0x1,	-0x1	},	insn_rel16 },
-	{ "lda",	{	0x96,	0xa6,	0xb6,	0x86	},	insn_gen8 },
-	{ "ldb",	{	0xd6,	0xe6,	0xf6,	0xc6	},	insn_gen8 },
-	{ "ldbt",	{	0x1136,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
-	{ "ldd",	{	0xdc,	0xec,	0xfc,	0xcc	},	insn_gen16 },
-	{ "lde",	{	0x1196,	0x11a6,	0x11b6,	0x1186	},	insn_gen8 },
-	{ "ldf",	{	0x11d6,	0x11e6,	0x11f6,	0x11c6	},	insn_gen8 },
-	{ "ldq",	{	0x10dc,	0x10ec,	0x10fc,	0xcd	},	insn_gen32 },
-	{ "lds",	{	0x10de,	0x10ee,	0x10fe,	0x10ce	},	insn_gen16 },
-	{ "ldu",	{ 	0xde,	0xee,	0xfe,	0xce	},	insn_gen16 },
-	{ "ldw",	{	0x1096,	0x10a6,	0x10b6,	0x1086	},	insn_gen16 },
-	{ "ldx",	{	0x9e,	0xae,	0xbe,	0x8e	},	insn_gen16 },
-	{ "ldy",	{	0x109e,	0x10ae,	0x10be,	0x108e	},	insn_gen16 },
-	{ "ldmd",	{	0x113d, -0x1,	-0x1,	0x113d	},	insn_imm8 },
-	{ "leas",	{	0x32,	-0x1,	-0x1,	-0x1	},	insn_indexed },
-	{ "leau",	{	0x33,	-0x1,	-0x1,	-0x1	},	insn_indexed },
-	{ "leax",	{	0x30,	-0x1,	-0x1,	-0x1	},	insn_indexed },
-	{ "leay",	{	0x31,	-0x1,	-0x1,	-0x1	},	insn_indexed },
-	{ "lsl",	{	0x08,	0x68,	0x78,	-0x1	},	insn_gen0 },
-	{ "lsla",	{	0x48,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "lslb",	{	0x58,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "lsld",	{	0x1048,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "lsr",	{	0x04,	0x64,	0x74,	-0x1	},	insn_gen0 },
-	{ "lsra",	{	0x44,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "lsrb",	{	0x54,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "lsrd",	{	0x1044,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "lsrw",	{	0x1054,	-0x1,	-0x1,	-0x1	},	insn_inh },
-
-	{ "mul",	{	0x3d,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "muld",	{	0x118f,	0x119f,	0x11af,	0x11bf	},	insn_gen16 },
-	
-	{ "neg",	{	0x00,	0x60,	0x70,	-0x1	},	insn_gen0 },
-	{ "nega",	{	0x40,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "negb",	{	0x50,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "negd",	{	0x1040,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "nop",	{	0x12,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	
-	{ "oim",	{	0x01,	0x61,	0x71,	-0x1	},	insn_logicmem },
-	{ "ora",	{	0x9a,	0xaa,	0xba,	0x8a	},	insn_gen8 },
-	{ "orb",	{	0xda,	0xea,	0xfa,	0xca	},	insn_gen8 },
-	{ "orcc",	{	0x1a,	-0x1,	-0x1,	0x1a	},	insn_imm8 },
-	{ "ord",	{	0x109a,	0x10aa,	0x10ba,	0x108a	},	insn_gen16 },
-	{ "orr",	{	0x1035,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	
-	{ "pshs",	{	0x34,	-0x1,	-0x1,	-0x1	},	insn_rlist },
-	{ "pshsw",	{	0x1038,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "pshu",	{	0x36,	-0x1,	-0x1,	-0x1	},	insn_rlist },
-	{ "pshuw",	{	0x103a,	-0x1,	-0x1,	-0x1	},	insn_inh	},
-	{ "puls",	{	0x35,	-0x1,	-0x1,	-0x1	},	insn_rlist },
-	{ "pulsw",	{	0x1039,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "pulu",	{	0x37,	-0x1,	-0x1,	-0x1	},	insn_rlist },
-	{ "puluw",	{	0x103b,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	
-	{ "rol",	{	0x09,	0x69,	0x79,	-0x1	},	insn_gen0 },
-	{ "rola",	{	0x49,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "rolb",	{	0x59,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "rold",	{	0x1049,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "rolw",	{	0x1059,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "ror",	{	0x06,	0x66,	0x76,	-0x1	},	insn_gen0 },
-	{ "rora",	{	0x46,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "rorb",	{	0x56,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "rord",	{	0x1046,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "rorw",	{	0x1056,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "rti",	{	0x3b,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "rts",	{	0x39,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	
-	{ "sbca",	{	0x92,	0xa2,	0xb2,	0x82	},	insn_gen8 },
-	{ "sbcb",	{	0xd2,	0xe2,	0xf2,	0xc2	},	insn_gen8 },
-	{ "sbcd",	{	0x1092,	0x10a2,	0x10b2,	0x1082	},	insn_gen16 },
-	{ "sbcr",	{	0x1033,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	{ "sex",	{	0x1d,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "sexw",	{	0x14,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "sta",	{	0x97,	0xa7,	0xb7,	-0x1	},	insn_gen0 },
-	{ "stb",	{	0xd7,	0xe7,	0xf7,	-0x1	},	insn_gen0 },
-	{ "stbt",	{	0x1137,	-0x1,	-0x1,	-0x1	},	insn_bitbit },
-	{ "std",	{	0xdd,	0xed,	0xfd,	-0x1	},	insn_gen0 },
-	{ "ste",	{	0x1197,	0x11a7,	0x11b7,	-0x1	},	insn_gen0 },
-	{ "stf",	{	0x11d7,	0x11e7,	0x11f7,	-0x1	},	insn_gen0 },
-	{ "stq",	{	0x10dd,	0x10ed,	0x10fd,	-0x1	},	insn_gen0 },
-	{ "sts",	{	0x10df,	0x10ef,	0x10ff,	-0x1	},	insn_gen0 },
-	{ "stu",	{	0xdf,	0xef,	0xff,	-0x1	},	insn_gen0 },
-	{ "stw",	{	0x1097,	0x10a7,	0x10b7,	-0x1	},	insn_gen0 },
-	{ "stx",	{	0x9f,	0xaf,	0xbf,	-0x1	},	insn_gen0 },
-	{ "sty",	{	0x109f,	0x10af,	0x10bf,	-0x1	},	insn_gen0 },
-	{ "suba",	{	0x90,	0xa0,	0xb0,	0x80	},	insn_gen8 },
-	{ "subb",	{	0xd0,	0xe0,	0xf0,	0xc0	},	insn_gen8 },
-	{ "subd",	{	0x93,	0xa3,	0xb3,	0x83	},	insn_gen16 },
-	{ "sube",	{	0x1190,	0x11a0,	0x11b0,	0x1180	},	insn_gen8 },
-	{ "subf",	{	0x11d0,	0x11e0,	0x11f0,	0x11c0	},	insn_gen8 },
-	{ "subr",	{	0x1032,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	{ "subw",	{	0x1090,	0x10a0,	0x1090,	0x1080	},	insn_gen8 },
-	{ "swi",	{	0x3f,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "swi2",	{	0x103f,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "swi3",	{	0x113f,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "sync",	{	0x13,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	
-	// note: 		r+,r+	r-,r-	r+,r	r,r+
-	{ "tfm",	{	0x1138,	0x1139,	0x113a,	0x113b	},	insn_tfm },
-
-	{ "tfr",	{	0x1f,	-0x1,	-0x1,	-0x1	},	insn_rtor },
-	{ "tim",	{	0x0b,	0x6b,	0x7b,	-0x1	},	insn_logicmem },
-	{ "tst",	{	0x0d,	0x6d,	0x7d,	-0x1	},	insn_gen0 },
-	{ "tsta",	{	0x4d,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "tstb",	{	0x5d,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "tstd",	{	0x104d,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "tste",	{	0x114d,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "tstf",	{	0x115d,	-0x1,	-0x1,	-0x1	},	insn_inh },
-	{ "tstw",	{	0x105d,	-0x1,	-0x1,	-0x1	},	insn_inh },
-
-	{ "org",	{ -1, -1, -1, -1 },	pseudo_org },
-
-	{ "equ",	{ -1, -1, -1, -1 },	pseudo_equ,	0,	0,	1 },
-	{ "=",		{ -1, -1, -1, -1 },	pseudo_equ,	0,	0,	1 },
-	{ "extern",	{ -1, -1, -1, -1 },	pseudo_extern,	0,	0,	1 },
-	{ "external",	{ -1, -1, -1, -1 },	pseudo_extern,	0,	0,	1 },
-	{ "import",	{ -1, -1, -1, -1 },	pseudo_extern,	0,	0,	1 },
-	{ "export",	{ -1, -1, -1, -1 },	pseudo_export,	0,	0,	1 },
-
-
-	{ "rmb", 	{ -1, -1, -1, -1 }, pseudo_rmb },
-	{ "rmd", 	{ -1, -1, -1, -1 }, pseudo_rmd },
-	{ "rmq", 	{ -1, -1, -1, -1 }, pseudo_rmq },
-
-	{ "zmb", 	{ -1, -1, -1, -1 }, pseudo_zmb },
-	{ "zmd", 	{ -1, -1, -1, -1 }, pseudo_zmd },
-	{ "zmq", 	{ -1, -1, -1, -1 }, pseudo_zmq },
-
-	{ "fcc",	{ -1, -1, -1, -1 },	pseudo_fcc },
-	{ "fcn",	{ -1, -1, -1, -1 },	pseudo_fcn },
-	{ "fcs",	{ -1, -1, -1, -1 },	pseudo_fcs },
-
-	{ "fcb",	{ -1, -1, -1, -1 },	pseudo_fcb },
-	{ "fdb",	{ -1, -1, -1, -1 },	pseudo_fdb },
-	{ "fqb",	{ -1, -1, -1, -1 },	pseudo_fqb },
-
-	{ "end", 	{ -1, -1, -1, -1 }, pseudo_end },
-
-	{ "include", { -1, -1, -1, -1 }, pseudo_include },
-	
-	{ "align", { -1, -1, -1, -1 },	pseudo_align },
-
-	{ "error",	{ -1, -1, -1, -1},	pseudo_error },
-
-	{ "ifeq",	{ -1, -1, -1, -1}, 	pseudo_ifeq, 1 },
-	{ "ifne",	{ -1, -1, -1, -1}, 	pseudo_ifne, 1 },
-	{ "if",		{ -1, -1, -1, -1}, 	pseudo_ifne, 1 },
-	{ "ifgt",	{ -1, -1, -1, -1}, 	pseudo_ifgt, 1 },
-	{ "ifge",	{ -1, -1, -1, -1}, 	pseudo_ifge, 1 },
-	{ "iflt",	{ -1, -1, -1, -1}, 	pseudo_iflt, 1 },
-	{ "ifle",	{ -1, -1, -1, -1}, 	pseudo_ifle, 1 },
-	{ "endc",	{ -1, -1, -1, -1}, 	pseudo_endc, 1 },
-	{ "else",	{ -1, -1, -1, -1}, 	pseudo_else, 1 },
-	{ "ifdef",	{ -1, -1, -1, -1},	pseudo_ifdef, 1},
-	{ "ifndef",	{ -1, -1, -1, -1},	pseudo_ifndef, 1},
-
-	{ "macro",	{ -1, -1, -1, -1}, 	pseudo_macro,	1,	0,	1 },
-	{ "endm",	{ -1, -1, -1, -1},	pseudo_endm,	1,	1,	1 },
-
-	{ "setdp", 	{ -1, -1, -1, -1},	pseudo_setdp },
-	{ "set",	{ -1, -1, -1, -1},	pseudo_set,	0,	0,	1 },
-
-	{ "section",	{ -1, -1, -1, -1},	pseudo_section },
-	{ "sect",	{ -1, -1, -1, -1},	pseudo_section },
-	{ "ends",	{ -1, -1, -1, -1},	pseudo_endsection },
-	{ "endsect",	{ -1, -1, -1, -1},	pseudo_endsection },
-	{ "endsection",	{ -1, -1, -1, -1},	pseudo_endsection },
-	
-	{ "pragma",	{ -1, -1, -1, -1},	pseudo_pragma },
-	{ "*pragma",	{ -1, -1, -1, -1},	pseudo_starpragma },
-	
-
-	/* flag end of table */	
-	{ NULL,		{ -0x1, -0x1, -0x1, -0x1 }, insn_inh }
-};
--- a/src/instab.h	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
-instab.h
-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/>.
-
-
-Contains definitions for the instruction table
-*/
-
-#ifndef __instab_h_seen__
-#define __instab_h_seen__
-
-#include "lwasm.h"
-
-typedef struct
-{
-	char *opcode;				/* the mneumonic */
-	int ops[4];					/* opcode values for up to four addr modes */
-	void (*fn)(asmstate_t *as, lwasm_line_t *l, char **optr, int opnum);
-	int iscond;					/* set if this should be dispatched even if skipping a condition/macro */
-	int endm;					/* end of macro? */
-	int setsym;					/* does this set a symbol address? EQU, SET */
-} instab_t;
-
-#define OPFUNC(fn)	void (fn)(asmstate_t *as, lwasm_line_t *l, char **p, int opnum)
-
-#ifndef __instab_c_seen__
-extern instab_t instab[];
-#endif //__instab_c_seen__
-
-#endif //__instab_h_seen__
--- a/src/list.c	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
-list.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/>.
-
-Contains code for displaying a program listings, etc.
-*/
-
-#define __list_c_seen__
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "lwasm.h"
-
-void lwasm_show_errors(asmstate_t *as)
-{
-	lwasm_line_t *l;
-	lwasm_error_t *e;
-	
-	for (l = as -> lineshead; l; l = l -> next)
-	{
-		if (l -> err)
-		{
-			for (e = l -> err; e; e = e -> next)
-			{
-				fprintf(stderr, "ERROR: %s\n", e -> mess);
-			}
-			fprintf(stderr, "%s:%d: %s\n", l -> filename, l -> lineno, l -> text);
-		}
-	}
-}
-
-void lwasm_list(asmstate_t *as)
-{
-	FILE *lf;
-	lwasm_line_t *l;
-	int c, c3;
-	char *p;
-	
-	if (!as -> listfile)
-		return;
-	if (as -> listfile[0] == '-' && as -> listfile[1] == '\0')
-		lf = stdout;
-	else
-	{
-		lf = fopen(as -> listfile, "w");
-		if (!lf)
-		{
-			fprintf(stderr, "Unable to open list file '%s'. No listing will be generated: ", as -> listfile);
-			perror("");
-			goto showerr;
-		}
-	}
-
-	for (l = as -> lineshead; l; l = l -> next)
-	{
-		if (l -> addrset == 1 || l -> codelen > 0 || l -> nocodelen > 0)
-		{
-			fprintf(lf, "%04X ", l -> codeaddr);
-		}
-		else
-		{
-			fprintf(lf, "     ");
-		}
-		
-		if (l -> addrset == 2)
-		{
-			fprintf(lf, "%04X      ", l -> symaddr);
-		}
-		else
-		{
-			for (c = 0; c < l -> codelen && c < 5; c++)
-			{
-				fprintf(lf, "%02X", l -> bytes[c]);
-			}
-			while (c < 5)
-			{
-				fprintf(lf, "  ");
-				c++;
-			}
-		}
-		fprintf(lf, " %20.20s:%05d ", l -> filename, l -> lineno);
-		
-		// print line here
-		for (c3 = 0, c = 0, p = l -> text; *p; c++, p++)
-		{
-			if (*p == '\t')
-			{
-				int c2;
-				c2 = 8 - (c3 % 8);
-				c3 += c2;
-				while (c2--) fputc(' ', lf);
-			}
-			else
-			{
-				c3++;
-				fputc(*p, lf);
-			}
-		}
-		fputc('\n', lf);
-		
-		if (l -> codelen > 5)
-		{
-			fprintf(lf, "%04X ", (l -> codeaddr + 5) & 0xFFFF);
-			for (c = 5; c < l -> codelen; c++)
-			{
-				if (!(c % 5) && c != 5)
-				{
-					fprintf(lf, "\n%04X ", (l -> codeaddr + c) & 0xFFFF);
-				}
-				fprintf(lf, "%02X", l -> bytes[c]);
-			}
-			fputc('\n', lf);
-		}
-	}
-	
-	lwasm_list_symbols(as, lf);
-	
-	if (lf != stdout)
-		fclose(lf);
-
-showerr:
-	lwasm_show_errors(as);
-}
--- a/src/lwasm.c	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,428 +0,0 @@
-/*
-lwasm.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/>.
-
-
-Contains random functions used by the assembler
-*/
-
-#define __lwasm_c_seen__
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "lwasm.h"
-#include "util.h"
-#include "expr.h"
-
-int debug_level = 0;
-
-int register_error(asmstate_t *as, lwasm_line_t *l, int pass, const char *fmt, ...)
-{
-	lwasm_error_t *e;
-	va_list args;
-	char errbuff[1024];
-	int r;
-	
-	if (!l)
-		return;
-
-	if (as -> passnum != pass)
-		return;
-	
-	va_start(args, fmt);
-	
-	e = lwasm_alloc(sizeof(lwasm_error_t));
-	
-	e -> next = l -> err;
-	l -> err = e;
-	
-	as -> errorcount++;
-	
-	r = vsnprintf(errbuff, 1024, fmt, args);
-	e -> mess = lwasm_strdup(errbuff);
-	
-	va_end(args);
-	
-	return r;
-}
-
-void lwasm_emit(asmstate_t *as, lwasm_line_t *l, int b)
-{
-	as -> addr += 1;
-	as -> addr &= 0xffff;
-	
-	if (as -> outformat == OUTPUT_OBJ && !(as -> csect))
-	{
-		register_error(as, l, 1, "Output not allowed outside sections with obj target");
-		return;
-	}
-	if (as -> outformat == OUTPUT_OBJ && as -> csect -> flags & SECTION_BSS)
-	{
-		register_error(as, l, 1, "Output not allowed inside BSS sections");
-		return;
-	}
-	if (as -> passnum == 1)
-		return;
-
-
-	if (l -> codelen >= l -> codesize)
-	{
-		l -> bytes = realloc(l -> bytes, l -> codesize + 16);
-		l -> codesize += 16;
-	}
-	l -> bytes[l -> codelen] = b & 0xff;
-	l -> codelen += 1;
-}
-
-void lwasm_emitop(asmstate_t *as, lwasm_line_t *l, int o)
-{
-	if (o >= 0x100)
-		lwasm_emit(as, l, o >> 8);
-	lwasm_emit(as, l, o & 0xff);
-}
-
-int lwasm_lookupreg2(const char *reglist, char **str)
-{
-	int rval = 0;
-
-	while (*reglist)
-	{
-		if (toupper(**str) == *reglist)
-		{
-			// first char matches
-			if (reglist[1] == ' ' && !isalpha(*(*str + 1)))
-				break;
-			if (toupper(*(*str + 1)) == reglist[1])
-				break;
-		}
-		reglist += 2;
-		rval++;
-	}
-	if (!*reglist)
-		return -1;
-	if (reglist[1] == ' ')
-		(*str)++;
-	else
-		(*str) += 2;
-	return rval;
-}
-
-int lwasm_lookupreg3(const char *rlist, const char **str)
-{
-	int rval = 0;
-	int f = 0;
-	const char *reglist = rlist;
-		
-	while (*reglist)
-	{
-		if (toupper(**str) == *reglist)
-		{
-			// first char matches
-			if (reglist[1] == ' ')
-			{
-				f = 1;
-				break;
-			}
-			if (toupper(*(*str + 1)) == reglist[1])
-			{
-				// second char matches
-				if (reglist[2] == ' ')
-				{
-					f = 1;
-					break;
-				}
-				if (toupper(*(*str + 2)) == reglist[2])
-				{
-					f = 1;
-					break;
-				}
-			}
-		}
-		reglist += 3;
-		rval++;
-	}
-	if (f == 0)
-		return -1;
-	
-	
-	reglist = rval * 3 + rlist;
-	if (reglist[1] == ' ')
-		(*str) += 1;
-	else if (reglist[2] == ' ')
-		(*str) += 2;
-	else
-		(*str)+=3;
-	return rval;
-}
-
-struct symstateinfo
-{
-	asmstate_t *as;
-	lwasm_line_t *l;
-	int flags;
-};	
-
-lwasm_expr_stack_t *lwasm_expr_lookup_symbol(char *sym, void *state)
-{
-	lwasm_symbol_ent_t *se;
-	struct symstateinfo *st;
-	lwasm_expr_stack_t *rs;
-	lwasm_expr_term_t *t;
-	lwasm_expr_stack_node_t *n;
-	
-	int val;
-	
-	st = state;
-	debug_message(3, "lwasm_expr_lookup_symbol(): find '%s' (context=%d)", sym, st -> as -> context);	
-
-	// check for special symbols first...
-	if (sym[1] == '\0')
-	{
-		switch (sym[0])
-		{
-		// current line address
-		case '*':
-		case '.':
-			val = st -> l -> codeaddr;
-			goto retconst;
-		
-		case '<':
-			// previous branch point
-			// not implemented
-			break;
-		case '>':
-			// next branch point
-			// not implemented
-			break;
-		}
-	}
-
-	// 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);
-	debug_message(3, "lwasm_expr_lookup_symbol(): got '%p'", se);
-	if (!se)
-	{
-		register_error(st -> as, st -> l, 2, "Undefined symbol '%s'", sym);
-		return NULL;
-	}
-	// external reference - can not resolve it
-	if (se -> flags & SYMBOL_EXTERN)
-	{
-		return NULL;
-	}
-	if (st -> flags & EXPR_SECTCONST)
-	{
-		if (se -> sect == st -> l -> sect)
-		{
-			if (se -> expr)
-				goto retsym;
-			val = se -> value;
-			goto retconst;
-		}
-	}
-	if (st -> as -> outformat == OUTPUT_OBJ && se -> sect != NULL)
-	{
-		return NULL;
-	}
-	if (st -> as -> outformat != OUTPUT_OBJ || se -> sect == NULL)
-	{
-		// global symbol, intrasegment reference, or not an object target
-		val = se -> value;
-		goto retconst;
-	}
-	
-	// an intersegment reference will return as NULL (to be resolved at output/link time)
-	// if se -> expr is NULL, it has to be an intersegment reference here
-	if (se -> expr == NULL)
-	{
-		return NULL;
-	}
-	
-retsym:
-	// duplicate the expression for return
-	rs = lwasm_expr_stack_create();
-	for (n = se -> expr -> head; n; n = n -> next)
-	{
-		lwasm_expr_stack_push(rs, n -> term);
-	}
-	return rs;
-
-retconst:
-	rs = lwasm_expr_stack_create();
-	t = lwasm_expr_term_create_int(val);
-	lwasm_expr_stack_push(rs, t);
-	lwasm_expr_term_free(t);
-	return rs;
-}
-
-lwasm_expr_stack_t *lwasm_evaluate_expr(asmstate_t *as, lwasm_line_t *l, const char *inp, const char **outp, int flags)
-{
-	struct symstateinfo st;
-	
-	st.as = as;
-	st.l = l;
-	st.flags = flags;
-	
-	debug_message(2, "Evaluate expression: %s", inp);
-	
-	return(lwasm_expr_eval(inp, outp, lwasm_expr_lookup_symbol, &st));
-}
-
-
-int lwasm_reevaluate_expr(asmstate_t *as, lwasm_line_t *l, lwasm_expr_stack_t *s, int flags)
-{
-	struct symstateinfo st;
-	
-	st.as = as;
-	st.l = l;
-	st.flags = flags;
-	return(lwasm_expr_reval(s, lwasm_expr_lookup_symbol, &st));
-}
-
-// return 1 if no undefined symbols (externals and incompletes are okay)
-// return 0 if there are undefined symbols
-int lwasm_expr_result_ckconst(asmstate_t *as, lwasm_expr_stack_t *s)
-{
-	lwasm_expr_stack_node_t *n;
-	lwasm_symbol_ent_t *se;
-	
-	if (as -> outformat != OUTPUT_OBJ)
-	{
-		if (lwasm_expr_is_constant(s))
-			return 1;
-		else
-			return 0;
-	}
-	
-	for (n = s -> head; n; n = n -> next)
-	{
-		if (n -> term -> term_type == LWASM_TERM_SYM)
-		{
-			se = lwasm_find_symbol(as, n -> term -> symbol, as -> context);
-			if (!se)
-				se = lwasm_find_symbol(as, n -> term -> symbol, -1);
-			if (!se)
-				return 0;
-		}
-	}
-	return 1;
-}
-
-/*
-Evaluate an expression according to the flag value. Return 0 if a constant result was
-obtained, 1 if an incomplete result was obtained, and -1 if an error was flagged.
-
-*/
-int lwasm_expr_result2(asmstate_t *as, lwasm_line_t *l, char **inp, int flag, int *val, int slot)
-{
-	lwasm_expr_stack_t *s = NULL;
-	const char *ep;
-	int rval;
-
-	if ((as -> passnum == 1 && !(flag & EXPR_REEVAL)) || slot < 0)
-	{		
-		s = lwasm_evaluate_expr(as, l, *inp, &ep, flag);
-		if (slot >= 0)
-			l -> exprs[slot] = s;
-		if (!s)
-		{
-			register_error(as, l, 1, "Bad expression");
-			*val = 0;
-			return -1;
-		}
-		*inp = (char *)ep;
-		if (slot >= 0)
-		{
-			l -> exprends[slot] = (char *)ep;
-			l -> exprvals[slot] = lwasm_expr_get_value(s);
-		}
-	}
-	else if (l -> exprs[slot])
-	{
-		s = l -> exprs[slot];
-		lwasm_reevaluate_expr(as, l, s, flag);
-		l -> exprvals[slot] = lwasm_expr_get_value(s);
-	}
-	if (as -> passnum == 2 && slot >= 0)
-		*inp = l -> exprends[slot];
-
-	if (s && lwasm_expr_is_constant(s))
-	{
-		*val = lwasm_expr_get_value(s);
-		lwasm_expr_stack_free(s);
-		l -> exprs[slot] = NULL;
-		s = NULL;
-		return 0;
-	}
-
-	if (!s && slot >= 0)
-	{
-		*val = l -> exprvals[slot];
-		return 0;
-	}
-	else if (!s)
-	{
-		*val = 0;
-		return 0;
-	}
-
-	// was a constant result on pass 1 requested?
-	// that means we must have a constant on either pass
-	if (flag & EXPR_PASS1CONST)
-	{
-		*val = 0;
-		if (slot >= 0)
-			l -> exprvals[slot] = 0;
-		register_error(as, l, 1, "Illegal forward, external, or inter-section reference");
-		lwasm_expr_stack_free(s);
-		if (slot >= 0)
-			l -> exprs[slot] = NULL;
-		return -1;
-	}
-	
-	return 1;
-}
-
-void debug_message(int level, const char *fmt, ...)
-{
-	va_list args;
-	
-	va_start(args, fmt);
-	if (debug_level >= level)
-	{
-		if (level > 0)
-			fprintf(stderr, "DEBUG %d: ", level);
-		vfprintf(stderr, fmt, args);
-		fputc('\n', stderr);
-	}
-	va_end(args);
-}
-
-int lwasm_next_context(asmstate_t *as)
-{
-	int r;
-	r = as -> nextcontext;
-	as -> nextcontext += 1;
-	debug_message(3, "lwasm_next_context(): %d (%d) pass %d", r, as -> nextcontext, as -> passnum);
-	return r;
-}
-
--- a/src/lwasm.h	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-/*
-lwasm.h
-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/>.
-
-Contains the main defs used by the assembler
-*/
-
-
-#ifndef __lwasm_h_seen__
-#define __lwasm_h_seen__
-
-#include <stdio.h>
-#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
-#define OUTPUT_RAWREL	3	// raw bytes where ORG causes a SEEK in the file
-
-// structure for tracking sections
-typedef struct section_reloc_list_s section_reloc_list_t;
-struct section_reloc_list_s
-{
-	int offset;						// offset into section
-	lwasm_expr_stack_t *expr;		// value definition
-	int context;					// symbol context (for local syms)
-	section_reloc_list_t *next;		// next relocation
-};
-
-typedef struct export_list_s export_list_t;
-struct export_list_s
-{
-	int offset;						// offset of symbol
-	char *sym;						// name of symbol
-	export_list_t *next;			// next export	
-};
-
-#define SECTION_BSS		1	// the section contains no actual code - just uninit vars
-typedef struct sectiontab_s sectiontab_t;
-struct sectiontab_s
-{
-	char *name;				// name of the section
-	int offset;				// current offset in the section
-	int flags;				// section flags
-	sectiontab_t *next;		// next section
-	// the following are used during code output
-	unsigned char *obytes;	// output bytes
-	int oblen;				// how many bytes output so far?
-	int obsize;				// how big is output buffer so far?
-	section_reloc_list_t *rl;	// relocation list
-	export_list_t *exports;	// export list for the section
-};
-
-// structure for tracking macros
-typedef struct macrotab_s macrotab_t;
-struct macrotab_s
-{
-	char *name;
-	char **lines;
-	int numlines;
-	macrotab_t *next;
-};
-
-// structure for tracking errors
-typedef struct lwasm_error_s lwasm_error_t;
-struct lwasm_error_s
-{
-	char *mess;				// the actual error message
-	lwasm_error_t *next;	// ptr to next error
-};
-
-// structure for keeping track of lines
-// it also as space for 4 expressions which is enough for all known
-// instructions and addressing modes
-// on pass 1, the expressions are parsed, on pass 2 they are re-evaluated
-// to determine constancy
-typedef struct lwasm_line_s lwasm_line_t;
-struct lwasm_line_s {
-	char *text;			// the actual text of the line
-	int lineno;			// line number within the file
-	char *filename;		// file name reference
-	lwasm_line_t *next;	// next line
-	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
-	unsigned char *bytes;	// actual bytes emitted
-	int codelen;		// number of bytes emitted
-	int codesize;		// the size of the code buffer
-	int codeaddr;		// address the code goes at
-	int nocodelen;		// for "RMB" type instructions
-	int addrset;		// set if this instruction sets the assembly address
-	int symaddr;		// set if this instruction sets a symbol addr with EQU or the like
-	int badop;			// bad operation - ignore it
-	int context;		// the symbol context for this line
-	
-	// the following are used for obj format - for external references, inter-section
-	// references, and intrasection relocations
-	int relocoff;		// offset into insn where relocation value goes
-	lwasm_expr_stack_t *exprs[4];	// non-constant expression values
-	int exprvals[4];	// constant expression values
-	char *exprends[4];	// pointer to character after end of expression
-	
-	sectiontab_t *sect;	// which section is the line in?
-};
-
-// for keeping track of symbols
-#define	SYMBOL_SET		1	// the symbol was used for "SET"
-#define SYMBOL_COMPLEX	2	// register symbol as a complex symbol (from l -> expr)
-#define SYMBOL_FORCE	4	// force resetting the symbol value if it already exists on pass 2
-#define SYMBOL_NORM		0	// no flags
-#define SYMBOL_EXTERN	8	// the symbol is an external reference
-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
-	int flags;					// flags for the symbol
-	char *externalname;			// for external references that are aliased locally
-	sectiontab_t *sect;			// the section the symbol exists in; NULL for none
-	lwasm_expr_stack_t *expr;	// expression for a symbol that is not constant NULL for const
-	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 ....)
-	int pragmas;				// what pragmas are in effect?
-
-	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
-	
-	macrotab_t *macros;			// macro table
-
-	const char *infile;			// input file
-	const char *outfile;		// output file
-	const char *listfile;		// output listing file
-	int outformat;				// output format type
-	char **filelist;			// files that have been read
-	int filelistlen;			// number of files in the list
-	
-	int endseen;				// set to true if "end" has been seen
-	int skipcond;				// skipping a condition?
-	int skipcount;				// how many?
-	int skipmacro;				// skipping a macro?
-	int inmacro;				// are we currently in a macro?
-	int macroex;				// current depth of macro expansion
-	int nextcontext;			// next context number
-	int skiplines;				// number of lines to skip
-	
-	// items used only for the "object" target
-	sectiontab_t *sections;		// pointer to section table
-	sectiontab_t *csect;		// current section - NULL if not in one
-} asmstate_t;
-
-// do not rewrite XXX,r to ,r if XXX evaluates to 0
-#define PRAGMA_NOINDEX0TONONE	1
-// any undefined symbols are considered external
-#define PRAGMA_UNDEFEXTERN	2
-
-#ifndef __lwasm_c_seen__
-#define __lwasm_E__ extern
-#else
-#define __lwasm_E__
-#endif
-
-__lwasm_E__ int debug_level;
-
-__lwasm_E__ int register_error(asmstate_t *as, lwasm_line_t *l, int pass, const char *fmt, ...);
-__lwasm_E__ void debug_message(int level, const char *fmt, ...);
-
-__lwasm_E__ void lwasm_emit(asmstate_t *as, lwasm_line_t *l, int b);
-__lwasm_E__ void lwasm_emitop(asmstate_t *as, lwasm_line_t *l, int o);
-__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, int flags);
-
-
-// return next context number and update it
-__lwasm_E__ int lwasm_next_context(asmstate_t *as);
-
-// also throw an error on expression eval failure
-// return 0 on ok, -1 on error, 1 if a complex expression was returned
-#define EXPR_NOFLAG			0
-#define EXPR_PASS1CONST		1	// no forward references on pass 1
-#define EXPR_SECTCONST		2	// resolve symbols local to section
-#define EXPR_REEVAL			4	// re-evaluate the expression
-__lwasm_E__ int lwasm_expr_result(asmstate_t *as, lwasm_line_t *l, char **inp, int flag, int *val);
-__lwasm_E__ int lwasm_expr_result2(asmstate_t *as, lwasm_line_t *l, char **inp, int flag, int *val, int slot);
-
-#undef __lwasm_E__
-
-
-#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, int flags);
-__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);
-__lwasm_E__ void lwasm_list_symbols(asmstate_t *as, FILE *f);
-#undef __lwasm_E__
-
-
-
-#endif //__lwasm_h_seen__
--- a/src/macro.c	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-/*
-macro.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/>.
-
-Contains stuff associated with macro processing
-*/
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include "lwasm.h"
-#include "instab.h"
-#include "util.h"
-
-OPFUNC(pseudo_macro)
-{
-	macrotab_t *m;
-
-	// if skipping a condition, flag in a macro
-	if (as -> skipcond)
-	{
-		as -> skipmacro = 1;
-		return;
-	}
-
-	// actually define a macro
-	if (as -> inmacro)
-	{
-		register_error(as, l, 1, "Attempt to define a macro inside a macro");
-		return;
-	}
-
-	as -> inmacro = 1;
-
-	// don't actually do anything if not pass 1
-	if (as -> passnum != 1)
-		return;
-
-
-	if (!l -> sym)
-	{
-		register_error(as, l, 1, "Macro definition with no effect - no symbol");
-		return;
-	}
-	
-	// search for macro by same name...
-	for (m = as -> macros; m; m = m -> next)
-	{
-		if (!strcmp(m -> name, l -> sym))
-			break;
-	}
-	if (m)
-	{
-		register_error(as, l, 1, "Duplicate macro definition");
-		return;
-	}
-	
-	m = lwasm_alloc(sizeof(macrotab_t));
-	m -> name = lwasm_strdup(l -> sym);
-	m -> next = as -> macros;
-	m -> lines = NULL;
-	m -> numlines = 0;
-	as -> macros = m;
-
-	while (**p && !isspace(**p))
-		(*p)++;
-}
-
-OPFUNC(pseudo_endm)
-{
-	if (as -> skipcond)
-	{
-		as -> skipmacro = 0;
-		return;
-	}
-	
-	if (!as -> inmacro)
-	{
-		register_error(as, l, 1, "ENDM without MACRO");
-		return;
-	}
-	
-	as -> inmacro = 0;
-	
-	// a macro definition counts as a context break for local symbols
-	as -> context = lwasm_next_context(as);
-}
-
-// the current macro will ALWAYS be the first one in the table
-int add_macro_line(asmstate_t *as, char *optr)
-{
-	if (!as -> inmacro)
-		return 0;
-	
-	if (as -> passnum == 2)
-		return 1;
-
-	as -> macros -> lines = lwasm_realloc(as -> macros -> lines, sizeof(char *) * (as -> macros -> numlines + 1));
-	as -> macros -> lines[as -> macros -> numlines] = lwasm_strdup(optr);
-	as -> macros -> numlines += 1;
-	return 1;
-}
-
-void macro_add_to_buff(char **buff, int *loc, int *len, char c)
-{
-	if (*loc == *len)
-	{
-		*buff = lwasm_realloc(*buff, *len + 32);
-		*len += 32;
-	}
-	(*buff)[(*loc)++] = c;
-}
-
-// this is just like a regular operation function
-/*
-macro args are referenced by "\n" where 1 <= n <= 9
-or by "\{n}"; a \ can be included by writing \\
-a comma separates argument but one can be included with "\,"
-whitespace ends argument list but can be included with "\ " or the like
-
-In pass 1, actually add the lines to the system, in pass 2, do not
-In pass 2, track the number of lines to skip because they already will be
-processed by this function - this will be in as -> skiplines
-
-*/
-int expand_macro(asmstate_t *as, lwasm_line_t *l, char **p, char *opc)
-{
-	int lc;
-	lwasm_line_t *cl, *nl;
-	int oldcontext;
-	macrotab_t *m;
-
-	char **args = NULL;		// macro arguments
-	int nargs = 0;			// number of arguments
-
-	char *p2, *p3;
-	
-	int bloc, blen;
-	char *linebuff;
-
-	for (m = as -> macros; m; m = m -> next)
-	{
-		if (!strcmp(opc, m -> name))
-			break;
-	}
-	// signal no macro expansion
-	if (!m)
-		return -1;
-	
-
-	// save current symbol context for after macro expansion
-	oldcontext = as -> context;
-
-	cl = l;
-
-	as -> context = lwasm_next_context(as);
-
-	// step 1: parse arguments (pass 1 only)
-	if (as -> passnum == 1)
-	{
-		while (**p && !isspace(**p) && **p != ',')
-		{
-			p2 = *p;
-			while (*p2 && !isspace(*p2) && *p2 != ',')
-			{
-				if (*p2 == '\\')
-				{
-					if (p2[1])
-						p2++;
-				}
-				p2++;
-			}
-			
-			// have arg here
-			args = lwasm_realloc(args, sizeof(char *) * (nargs + 1));
-			args[nargs] = lwasm_alloc(p2 - *p + 1);
-			args[nargs][p2 - *p] = '\0';
-			memcpy(args[nargs], *p, p2 - *p);
-			*p = p2;
-			
-			// now collapse out "\" characters
-			for (p3 = p2 = args[nargs]; *p2; p2++, p3++)
-			{
-				if (*p2 == '\\' && p2[1])
-				{
-					p2++;
-				}
-				*p3 = *p2;
-			}
-			*p3 = '\0';
-			
-			nargs++;
-			if (**p == ',')
-				(*p)++;
-		}
-	}
-	
-	{
-		int i;
-		for (i = 0; i < nargs; i++)
-		{
-			debug_message(10, "Macro (%s) arg %d: %s", m -> name, i + 1, args[i]);
-		}
-	}
-	
-	// step 2: iterate over the lines
-	if (as -> passnum == 2)
-	{
-		// pass 2 only - parse the lines and count them
-		for (lc = 0; lc < m -> numlines; lc++)
-		{
-			cl = cl -> next;
-			as -> skiplines++;
-			lwasm_parse_line(as, cl);
-		}
-	}
-	else
-	{
-		// pass 1 only - construct the lines and parse them
-		for (lc = 0; lc < m -> numlines; lc++)
-		{
-			nl = lwasm_alloc(sizeof(lwasm_line_t));
-			nl -> lineno = lc + 1;
-			nl -> filename = m -> name;
-			nl -> next = NULL;
-			nl -> prev = as -> linestail;
-			nl -> err = NULL;
-			nl -> fsize = 0;
-			nl -> sym = NULL;
-			nl -> bytes = NULL;
-			nl -> codelen = 0;
-			nl -> codesize = 0;
-			nl -> nocodelen = 0;
-			nl -> addrset = 0;
-			nl -> symaddr = -1;
-			nl -> badop = 0;
-			nl -> relocoff = -1;
-			if (as -> linestail)
-				as -> linestail -> next = nl;
-			as -> linestail = nl;
-			if (!(as -> lineshead))
-				as -> lineshead = nl;
-
-			bloc = blen = 0;
-			linebuff = NULL;
-			for (p2 = m -> lines[lc]; *p2; p2++)
-			{
-				if (*p2 == '\\' && isdigit(p2[1]))
-				{
-					int n;
-					
-					p2++;
-					n = *p2 - '0';
-					if (n == 0)
-					{
-						for (p3 = m -> name; *p3; p3++)
-							macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
-						continue;
-					}
-					if (n < 1 || n > nargs)
-						continue;
-					for (p3 = args[n - 1]; *p3; p3++)
-						macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
-					continue;
-				}
-				else if (*p2 == '{')
-				{
-					int n = 0, n2;
-					p2++;
-					while (*p2 && isdigit(*p2))
-					{
-						n2 = *p2 - '0';
-						if (n2 < 0 || n2 > 9)
-							n2 = 0;
-						n = n * 10 + n2;
-						p2++;
-					}
-					if (*p2 == '}')
-						p2++;
-					 
-					if (n == 0)
-					{
-						for (p3 = m -> name; *p3; p3++)
-							macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
-						continue;
-					}
-					if (n < 1 || n > nargs)
-						continue;
-					for (p3 = args[n - 1]; *p3; p3++)
-						macro_add_to_buff(&linebuff, &bloc, &blen, *p3);
-					continue;
-				}
-				else
-				{
-					macro_add_to_buff(&linebuff, &bloc, &blen, *p2);
-				}
-			}
-
-			macro_add_to_buff(&linebuff, &bloc, &blen, 0);
-			
-			nl -> text = linebuff;
-
-			lwasm_parse_line(as, nl);
-			if (as -> endseen)
-				break;
-
-		}
-	}
-	
-	// restore context from before the macro was called
-	as -> context = oldcontext;
-
-	// clean up
-	if (args)
-	{
-		while (nargs)
-		{
-			lwasm_free(args[--nargs]);
-		}
-		lwasm_free(args);
-	}
-
-	// indicate a macro was expanded
-	return 0;	
-}
--- a/src/main.c	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-/*
-main.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 the program startup code
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <argp.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "lwasm.h"
-
-// external declarations
-extern void lwasm_pass1(asmstate_t *as);
-extern void lwasm_pass2(asmstate_t *as);
-extern void lwasm_list(asmstate_t *as);
-extern void lwasm_output(asmstate_t *as);
-extern void pseudo_pragma_real(asmstate_t *as, lwasm_line_t *cl, char **optr, int error);
-
-// command line option handling
-const char *argp_program_version = "LWASM from " PACKAGE_STRING;
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
-
-static error_t parse_opts(int key, char *arg, struct argp_state *state)
-{
-	asmstate_t *as = state -> input;
-	char *p;
-	
-	switch (key)
-	{
-	case 'o':
-		// output
-		if (as -> outfile)
-		{
-		}
-		as -> outfile = arg;
-		break;
-	
-	case 'd':
-		// debug
-		debug_level++;
-		break;
-	
-	case 'l':
-		// list
-		if (arg)
-			as -> listfile = arg;
-		else
-			as -> listfile = "-";
-		break;
-	
-	case 'b':
-		// decb output
-		as -> outformat = OUTPUT_DECB;
-		break;
-	
-	case 'r':
-		// raw binary output
-		as -> outformat = OUTPUT_RAW;
-		break;
-	
-	case 0x100:
-		// proprietary object format
-		as -> outformat = OUTPUT_OBJ;
-		break;
-		
-	case 'f':
-		// output format
-		if (!strcasecmp(arg, "decb"))
-			as -> outformat = OUTPUT_DECB;
-		else if (!strcasecmp(arg, "raw"))
-			as -> outformat = OUTPUT_RAW;
-		else if (!strcasecmp(arg, "obj"))
-			as -> outformat = OUTPUT_OBJ;
-		else
-		{
-			fprintf(stderr, "Invalid output format: %s\n", arg);
-			exit(1);
-		}
-		break;
-	
-	case 'p':
-		// pragmas
-		p = arg;
-		pseudo_pragma_real(as, NULL, &p, 2);
-		if (!p)
-		{
-			fprintf(stderr, "Invalid pragma string: %s\n", arg);
-			exit(1);
-		}
-		break;
-
-	case ARGP_KEY_END:
-		// done; sanity check
-		if (!as -> outfile)
-			as -> outfile = "a.out";
-		break;
-	
-	case ARGP_KEY_ARG:
-		// non-option arg
-		if (as -> infile)
-			argp_usage(state);
-		as -> infile = arg;
-		break;
-		
-	default:
-		return ARGP_ERR_UNKNOWN;
-	}
-	return 0;
-}
-
-static struct argp_option options[] =
-{
-	{ "output",		'o',	"FILE",	0,
-				"Output to FILE"},
-	{ "debug",		'd',	0,		0,
-				"Set debug mode"},
-	{ "format",		'f',	"TYPE",	0,
-				"Select output format: decb, raw, obj"},
-	{ "list",		'l',	"FILE",	OPTION_ARG_OPTIONAL,
-				"Generate list [to FILE]"},
-	{ "decb",		'b',	0,		0,
-				"Generate DECB .bin format output, equivalent of --format=decb"},
-	{ "raw",		'r',	0,		0,
-				"Generate raw binary format output, equivalent of --format=raw"},
-	{ "obj",		0x100,		0,		0,
-				"Generate proprietary object file format for later linking, equivalent of --format=obj" },
-	{ "pragma",		'p',	"PRAGMA",	0,
-				"Set an assembler pragma to any value understood by the \"pragma\" pseudo op"},
-	{ 0 }
-};
-
-static struct argp argp =
-{
-	options,
-	parse_opts,
-	"<input file>",
-	"LWASM, a HD6309 and MC6809 cross-assembler"
-};
-
-// main function; parse command line, set up assembler state, and run the
-// assembler on the first file
-int main(int argc, char **argv)
-{
-	// assembler state
-	asmstate_t asmstate = { 0 };
-
-	argp_parse(&argp, argc, argv, 0, 0, &asmstate);
-
-	if (!asmstate.infile)
-	{
-		fprintf(stderr, "No input files specified.\n");
-		exit(1);
-	}	
-
-	/* pass 1 - collect the symbols and assign addresses where possible */
-	/* pass 1 also resolves included files, etc. */
-	/* that means files are read exactly once unless included multiple times */
-	lwasm_pass1(&asmstate);
-	
-	// pass 2: actually generate the code; if any phasing errors appear
-	// at this stage, we have a bug
-	lwasm_pass2(&asmstate);
-
-	// now make a pretty listing
-	lwasm_list(&asmstate);
-
-	// now write the code out to the output file
-	lwasm_output(&asmstate);
-
-	if (asmstate.errorcount > 0)
-		exit(1);
-
-	exit(0);
-}
-
--- a/src/output.c	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,419 +0,0 @@
-/*
-output.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/>.
-
-
-Contains the code for actually outputting the assembled code
-*/
-
-//#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-//#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#define __output_c_seen__
-//#include "instab.h"
-#include "lwasm.h"
-#include "util.h"
-
-void write_code_raw(asmstate_t *as, FILE *of);
-void write_code_decb(asmstate_t *as, FILE *of);
-void write_code_rawrel(asmstate_t *as, FILE *of);
-void write_code_obj(asmstate_t *as, FILE *of);
-
-// this prevents warnings about not using the return value of fwrite()
-#define writebytes(s, l, c, f)	do { int r; r = fwrite((s), (l), (c), (f)); } while (0)
-
-void lwasm_output(asmstate_t *as)
-{
-	FILE *of;
-	
-	if (as -> errorcount > 0)
-	{
-		fprintf(stderr, "Not doing output due to assembly errors.\n");
-		return;
-	}
-	
-	of = fopen(as -> outfile, "wb");
-	if (!of)
-	{
-		fprintf(stderr, "Cannot open '%s' for output", as -> outfile);
-		perror("");
-		return;
-	}
-
-	switch (as -> outformat)
-	{
-	case OUTPUT_RAW:
-		write_code_raw(as, of);
-		break;
-		
-	case OUTPUT_DECB:
-		write_code_decb(as, of);
-		break;
-		
-	case OUTPUT_RAWREL:
-		write_code_rawrel(as, of);
-		break;
-	
-	case OUTPUT_OBJ:
-		write_code_obj(as, of);
-		break;
-
-	default:
-		fprintf(stderr, "BUG: unrecognized output format when generating output file\n");
-		fclose(of);
-		unlink(as -> outfile);
-		return;
-	}
-
-	fclose(of);
-}
-
-/*
-rawrel output treats an ORG directive as an offset from the start of the
-file. Undefined results will occur if an ORG directive moves the output
-pointer backward. This particular implementation uses "fseek" to handle
-ORG requests and to skip over RMBs.
-
-This simple brain damanged method simply does an fseek before outputting
-each instruction.
-*/
-void write_code_rawrel(asmstate_t *as, FILE *of)
-{
-	lwasm_line_t *cl;
-	
-	for (cl = as -> lineshead; cl; cl = cl -> next)
-	{
-		if (cl -> codelen == 0)
-			continue;
-		
-		fseek(of, cl -> codeaddr, SEEK_SET);
-		writebytes(cl -> bytes, cl -> codelen, 1, of);
-	}
-}
-
-/*
-raw merely writes all the bytes directly to the file as is. ORG is just a
-reference for the assembler to handle absolute references. Multiple ORG
-statements will produce mostly useless results
-*/
-void write_code_raw(asmstate_t *as, FILE *of)
-{
-	lwasm_line_t *cl;
-	
-	for (cl = as -> lineshead; cl; cl = cl -> next)
-	{
-		if (cl -> nocodelen)
-		{
-			int i;
-			for (i = 0; i < cl -> nocodelen; i++)
-				writebytes("\0", 1, 1, of);
-			continue;
-		}
-		writebytes(cl -> bytes, cl -> codelen, 1, of);
-	}
-}
-
-void write_code_decb(asmstate_t *as, FILE *of)
-{
-	long preambloc;
-	lwasm_line_t *cl;
-	int blocklen = -1;
-	int nextcalc = -1;
-	unsigned char outbuf[5];
-	
-	for (cl = as -> lineshead; cl; cl = cl -> next)
-	{
-		if (cl -> nocodelen)
-			continue;
-		if (cl -> codeaddr != nextcalc && cl -> codelen > 0)
-		{
-			// need preamble here
-			if (blocklen > 0)
-			{
-				// update previous preamble if needed
-				fseek(of, preambloc, SEEK_SET);
-				outbuf[0] = (blocklen >> 8) & 0xFF;
-				outbuf[1] = blocklen & 0xFF;
-				writebytes(outbuf, 2, 1, of);
-				fseek(of, 0, SEEK_END);
-			}
-			blocklen = 0;
-			nextcalc = cl -> codeaddr;
-			outbuf[0] = 0x00;
-			outbuf[1] = 0x00;
-			outbuf[2] = 0x00;
-			outbuf[3] = (nextcalc >> 8) & 0xFF;
-			outbuf[4] = nextcalc & 0xFF;
-			preambloc = ftell(of) + 1;
-			writebytes(outbuf, 5, 1, of);
-		}
-		nextcalc += cl -> codelen;
-		writebytes(cl -> bytes, cl -> codelen, 1, of);
-		blocklen += cl -> codelen;
-	}
-	if (blocklen > 0)
-	{
-		fseek(of, preambloc, SEEK_SET);
-		outbuf[0] = (blocklen >> 8) & 0xFF;
-		outbuf[1] = blocklen & 0xFF;
-		writebytes(outbuf, 2, 1, of);
-		fseek(of, 0, SEEK_END);
-	}
-	
-	// now write postamble
-	outbuf[0] = 0xFF;
-	outbuf[1] = 0x00;
-	outbuf[2] = 0x00;
-	outbuf[3] = (as -> execaddr >> 8) & 0xFF;
-	outbuf[4] = (as -> execaddr) & 0xFF;
-	writebytes(outbuf, 5, 1, of);
-}
-
-void write_code_obj_sbadd(sectiontab_t *s, unsigned char b)
-{
-	if (s -> oblen >= s -> obsize)
-	{
-		s -> obytes = lwasm_realloc(s -> obytes, s -> obsize + 128);
-		s -> obsize += 128;
-	}
-	s -> obytes[s -> oblen] = b;
-	s -> oblen += 1;
-}
-
-void write_code_obj(asmstate_t *as, FILE *of)
-{
-	lwasm_line_t *l;
-	sectiontab_t *s;
-	lwasm_symbol_ent_t *se;
-	export_list_t *ex;
-	section_reloc_list_t *re;
-	lwasm_expr_stack_node_t *sn;			
-	
-	int i;
-	unsigned char buf[16];
-
-	// output the magic number and file header
-	// the 8 is NOT an error
-	writebytes("LWOBJ16", 8, 1, of);
-	
-	// run through the entire system and build the byte streams for each
-	// section; at the same time, generate a list of "local" symbols to
-	// output for each section
-	// NOTE: for "local" symbols, we will append \x01 and the ascii string
-	// of the context identifier (so sym in context 1 would be "sym\x011"
-	// we can do this because the linker can handle symbols with any
-	// character other than NUL.
-	// also we will generate a list of incomplete references for each
-	// section along with the actual definition that will be output
-	
-	// once all this information is generated, we will output each section
-	// to the file
-	
-	// NOTE: we build everything in memory then output it because the
-	// assembler accepts multiple instances of the same section but the
-	// linker expects only one instance of each section in the object file
-	// so we need to collect all the various pieces of a section together
-	// (also, the assembler treated multiple instances of the same section
-	// as continuations of previous sections so we would need to collect
-	// them together anyway.
-	
-	for (l = as -> lineshead; l; l = l -> next)
-	{
-		if (l -> sect)
-		{
-			// we're in a section - need to output some bytes
-			for (i = 0; i < l -> codelen; i++)
-				write_code_obj_sbadd(l -> sect, l -> bytes[i]);
-			for (i = 0; i < l -> nocodelen; i++)
-				write_code_obj_sbadd(l -> sect, 0);
-			
-			// do we have a "relocation"? If so, add a reference to the
-			// relocation table
-			if (l -> relocoff >= 0)
-			{
-				// build the relocation reference for the linker
-				re = lwasm_alloc(sizeof(section_reloc_list_t));
-				re -> next = l -> sect -> rl;
-				l -> sect -> rl = re;
-				
-				re -> offset = l -> codeaddr + l -> relocoff;
-				re -> expr = l -> exprs[0];
-				re -> context = l -> context;
-			}
-		}
-	}
-	
-	// run through the sections
-	for (s = as -> sections; s; s = s -> next)
-	{
-		// write the name
-		writebytes(s -> name, strlen(s -> name) + 1, 1, of);
-		
-		// write the flags
-		if (s -> flags & SECTION_BSS)
-			writebytes("\x01", 1, 1, of);
-		
-		// indicate end of flags - the "" is NOT an error
-		writebytes("", 1, 1, of);
-		
-		
-		// now the local symbols
-		for (se = as -> symhead; se; se = se -> next)
-		{
-			// ignore symbols not in this section
-			if (se -> sect != s)
-				continue;
-			
-			if (se -> flags & SYMBOL_SET)
-				continue;
-			
-			if (se -> flags & SYMBOL_EXTERN)
-				continue;
-			
-			writebytes(se -> sym, strlen(se -> sym), 1, of);
-			if (se -> context >= 0)
-			{
-				writebytes("\x01", 1, 1, of);
-				sprintf(buf, "%d", se -> context);
-				writebytes(buf, strlen(buf), 1, of);
-			}
-			// the "" is NOT an error
-			writebytes("", 1, 1, of);
-			
-			// write the address
-			buf[0] = (se -> value >> 8) & 0xff;
-			buf[1] = se -> value & 0xff;
-			writebytes(buf, 2, 1, of);
-		}	
-		// flag end of local symbol table - "" is NOT an error
-		writebytes("", 1, 1, of);
-		
-		// now the exports
-		for (ex = s -> exports; ex; ex = ex -> next)
-		{
-			writebytes(ex -> sym, strlen(ex -> sym) + 1, 1, of);
-			buf[0] = (ex -> offset >> 8) & 0xff;
-			buf[1] = ex -> offset & 0xff;
-			writebytes(buf, 2, 1, of);
-		}
-		
-		// flag end of exported symbols - "" is NOT an error
-		writebytes("", 1, 1, of);
-		
-		// now output the "incomplete references"
-		// this being the most complex bit
-		for (re = s -> rl; re; re = re -> next)
-		{
-			if (re -> expr == NULL)
-			{
-				// this is an error but we'll simply ignore it
-				// and not output this expression
-				continue;
-			}
-			
-			// work through each term in the expression and output
-			// the proper equivalent to the object file
-			for (sn = re -> expr -> head; sn; sn = sn -> next)
-			{
-				switch (sn -> term -> term_type)
-				{
-				case LWASM_TERM_OPER:
-					buf[0] =  0x04;
-					buf[1] = sn -> term -> value;
-					writebytes(buf, 2, 1, of);
-					break;
-					
-				case LWASM_TERM_INT:
-					buf[0] = 0x01;
-					buf[1] = (sn -> term -> value >> 8) & 0xff;
-					buf[2] = sn -> term -> value & 0xff;
-					writebytes(buf, 3, 1, of);
-					break;
-				
-				case LWASM_TERM_SECBASE:
-					writebytes("\x05", 1, 1, of);
-					break;
-
-				case LWASM_TERM_SYM:
-					// now for the ugly part - resolve a symbol reference
-					// and determine whether it's internal, external, or
-					// a section base
-					se = lwasm_find_symbol(as, sn -> term -> symbol, re -> context);
-					if (!se)
-						se = lwasm_find_symbol(as, sn -> term -> symbol, -1);
-					if (!se || se -> flags & SYMBOL_EXTERN)
-					{
-						// not found - assume external reference
-						// found but flagged external - handle it
-						writebytes("\x02", 1, 1, of);
-						writebytes(se -> sym, strlen(se -> sym) + 1, 1, of);
-						break;
-					}
-					// a local symbol reference here
-					writebytes("\x03", 1, 1, of);
-					writebytes(se -> sym, strlen(se -> sym), 1, of);
-					if (se -> context >= 0)
-					{
-						writebytes("\x01", 1, 1, of);
-						sprintf(buf, "%d", se -> context);
-						writebytes(buf, strlen(buf), 1, of);
-					}
-					writebytes("", 1, 1, of);
-					break;
-
-				default:
-					// unrecognized term type - replace with integer 0
-					buf[0] = 0x01;
-					buf[1] = 0x00;
-					buf[2] = 0x00;
-					writebytes(buf, 3, 1, of);
-					break;
-				}
-			}
-			
-			// flag end of expressions
-			writebytes("", 1, 1, of);
-			
-			// write the offset
-			buf[0] = (re -> offset >> 8) & 0xff;
-			buf[1] = re -> offset & 0xff;
-			writebytes(buf, 2, 1, of);
-		}
-		// flag end of incomplete references list
-		writebytes("", 1, 1, of);
-		
-		// now blast out the code
-		
-		// length
-		buf[0] = s -> oblen >> 8 & 0xff;
-		buf[1] = s -> oblen & 0xff;
-		writebytes(buf, 2, 1, of);
-		
-		if (!(s -> flags & SECTION_BSS))
-		{
-			writebytes(s -> obytes, s -> oblen, 1, of);
-		}
-	}
-	
-	// flag no more sections
-	// the "" is NOT an error
-	writebytes("", 1, 1, of);
-}
--- a/src/pragma.c	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
-pragma.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/>.
-
-
-This file contains stuff associated with lwasm specific strangeness
-*/
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include "lwasm.h"
-#include "instab.h"
-
-/*
-A pragma is a means of controlling code generation.
-
-The pseudo op "*pragma" which will be treated as a comment by an assembler
-that doesn't recognize it and thus will not cause assembly errors. This is
-the preferred way of flagging a pragma if it will not cause incorrect
-execution of the program.
-
-The pseudo op "pragma" which will cause an error on an assembler that does
-not understand it.
-
-In the case of "*pragma", unrecognized pragmas MUST be silently ignored. In
-the case of "pragma", unrecognized pragmas should raise an error.
-
-LWASM understands the following pragmas:
-
-index0tonone
-noindex0tonone
-
-When set (index0tonone), an expression that evaluates to 0, other than a
-bare constant, in a <offset>,r operand will cause the code for ",r" to be
-emitted rather than "0,r". If not set (noindex0tonone), the "0,r" output
-will be emitted. The default is to perform the optimization.
-
-This particular optimization will save a cycle for a direct operation. For
-an indirect operation, however, it will save several cycles and a program byte
-which may be very useful.
-*/
-
-void pseudo_pragma_real(asmstate_t *as, lwasm_line_t *cl, char **optr, int error)
-{
-	char pragma[128];
-	int c = 0;
-	
-	while (isspace(**optr))
-		(*optr)++;
-	
-	while (c < 127 && **optr && !isspace(**optr))
-	{
-		pragma[c++] = **optr;
-		(*optr)++;
-	}
-	
-	if (c == 0 || (**optr && !isspace(**optr)))
-	{
-		if (error)
-		{
-			register_error(as, cl, 1, "Unrecognized pragma");
-		}
-		if (error == 2)
-		{
-			*optr = NULL;
-		}
-		return;
-	}
-	pragma[c] = 0;
-	if (!strcasecmp(pragma, "noindex0tonone"))
-	{
-		as -> pragmas |= PRAGMA_NOINDEX0TONONE;
-	}
-	else if (!strcasecmp(pragma, "index0tonone"))
-	{
-		as -> pragmas &= ~PRAGMA_NOINDEX0TONONE;
-	}
-	else if (!strcasecmp(pragma, "undefextern"))
-	{
-		as -> pragmas |= PRAGMA_UNDEFEXTERN;
-	}
-	else if (!strcasecmp(pragma, "noundefextern"))
-	{
-		as -> pragmas &= ~PRAGMA_UNDEFEXTERN;
-	}
-	else
-	{
-		if (error)
-		{
-			register_error(as, cl, 1, "Unrecognized pragma");
-			if (error == 2)
-			{
-				*optr = NULL;
-			}
-		}
-	}
-}
-
-OPFUNC(pseudo_pragma)
-{
-	pseudo_pragma_real(as, l, p, 1);
-}
-
-OPFUNC(pseudo_starpragma)
-{
-	pseudo_pragma_real(as, l, p, 0);
-}
--- a/src/pseudo.c	Fri Jan 30 02:55:30 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,967 +0,0 @@
-/*
-pseudo.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/>.
-
-
-This file implements the various pseudo operations.
-*/
-
-#include <stdlib.h>
-#include <string.h>
-#include "lwasm.h"
-#include "instab.h"
-#include "expr.h"
-#include "util.h"
-
-extern int lwasm_read_file(asmstate_t *as, const char *filename);
-
-OPFUNC(pseudo_org)
-{
-	int v, r;
-
-	if (as -> csect)
-	{
-		register_error(as, l, 1, "ORG not allowed within sections");
-		return;
-	}
-
-	if (as -> passnum != 1)
-	{
-		// org is not needed to be processed on pass 2
-		// this will prevent phasing errors for forward references that
-		// resolve on the second pass
-		// we saved the org address in l -> codeaddr on pass 1
-		as -> addr = l -> codeaddr;
-		return;
-	}
-	
-	if (l -> sym)
-	{
-		register_error(as, l, 1, "No symbol allowed with ORG");
-	}
-	
-	r = lwasm_expr_result2(as, l, p, EXPR_PASS1CONST, &v, 0);
-	if (r != 0)
-		return;
-	l -> codeaddr = v;
-	l -> addrset = 1;
-	as -> addr = v;
-}
-
-/*
-The operand for include is a string optionally enclosed in "
-*/
-OPFUNC(pseudo_include)
-{
-	int v1;
-	char *fn;
-	
-	// only include files on pass 1
-	// but make sure local include context is right
-	// for the next line...
-	if (as -> passnum != 1)
-	{
-		as -> context = lwasm_next_context(as);
-		return;
-	}
-
-	while (**p && isspace(**p))
-		(*p)++;
-
-	if (!**p)
-	{
-		register_error(as, l, 1, "Bad file name");
-		return;
-	}
-
-	if (**p == '"')
-	{
-		// search for ending "
-		(*p)++;
-		for (v1 = 0; *((*p)+v1) && *((*p)+v1) != '"'; v1++)
-			/* do nothing */ ;
-		if (*((*p)+v1) != '"')
-		{
-			register_error(as, l, 1, "Bad file name");
-			return;
-		}
-	}
-	else
-	{
-		// search for a space type character
-		for (v1 = 0; *((*p)+v1) && !isspace(*((*p)+v1)); v1++)
-			;
-	}
-
-	fn = lwasm_alloc(v1 + 1);
-	memcpy(fn, *p, v1);
-	fn[v1] = '\0';
-
-	// end local label context on include	
-	as -> context = lwasm_next_context(as);
-	if (lwasm_read_file(as, fn) < 0)
-	{
-		register_error(as, l, 1, "File include error (%s)", fn);
-	}
-	lwasm_free(fn);
-}
-
-OPFUNC(pseudo_rmb)
-{
-	int r, v;
-	
-	if (as -> passnum == 2)
-	{
-		as -> addr += l -> nocodelen;
-		return;
-	}
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, -1);
-	if (r != 0)
-		return;
-	l -> nocodelen = v;
-	as -> addr += v;
-}
-
-OPFUNC(pseudo_rmd)
-{
-	int r, v;
-	
-	if (as -> passnum == 2)
-	{
-		as -> addr += l -> nocodelen;
-		return;
-	}
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
-	if (r != 0)
-		return;
-	v *= 2;
-	l -> nocodelen = v;
-	as -> addr += v;
-}
-
-OPFUNC(pseudo_rmq)
-{
-	int r, v;
-	
-	if (as -> passnum == 2)
-	{
-		as -> addr += l -> nocodelen;
-		return;
-	}
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
-	if (r != 0)
-		return;
-	v *= 4;
-	l -> nocodelen = v;
-	as -> addr += v;
-}
-
-OPFUNC(pseudo_zmb)
-{
-	int r, v;
-	
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
-	if (r != 0)
-		return;
-	while (v--)
-		lwasm_emit(as, l, 0);
-}
-
-OPFUNC(pseudo_zmd)
-{
-	int r, v;
-	
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
-	if (r != 0)
-		return;
-	v *= 2;
-	while (v--)
-		lwasm_emit(as, l, 0);
-}
-
-OPFUNC(pseudo_zmq)
-{
-	int r, v;
-	
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
-	if (r != 0)
-		return;
-	v *= 4;
-	while (v--)
-		lwasm_emit(as, l, 0);
-}
-
-OPFUNC(pseudo_end)
-{
-	int r, v;
-	lwasm_expr_stack_t *s;
-	
-
-	as -> endseen = 1;
-	
-	// address only matters for DECB output
-	if (as -> outformat != OUTPUT_DECB)
-		return;
-	
-	r = lwasm_expr_result2(as, l, p, 0, &v, 0);
-	if (r != 0)
-	{
-		register_error(as, l, 2, "Bad operand");
-	}
-
-	v = v & 0xffff;
-	if (as -> passnum == 2)
-	{
-		as -> execaddr = v;
-		l -> symaddr = v;
-		l -> addrset = 2;
-	}
-}
-
-
-OPFUNC(pseudo_align)
-{
-	int cn;
-	int r, v;
-	
-	if (as -> passnum == 2)
-	{
-		while (as -> addr < l -> symaddr)
-			lwasm_emit(as, l, 0);
-		return;
-	}
-	
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
-	if (r != 0)
-	{
-		l -> symaddr = as -> addr;
-		return;
-	}
-
-	if (v < 1)
-	{
-		register_error(as, l, 1, "Illegal alignment %d", v);
-		return;
-	}
-	
-	cn = l -> codeaddr % v;
-	if (cn)
-		cn = v - cn; 
-
-	while (cn--)
-	{
-		lwasm_emit(as, l, 0);
-	}
-	l -> symaddr = as -> addr;
-}
-
-OPFUNC(pseudo_equ)
-{
-	int r, v;
-
-	if (l -> sym == NULL)
-	{
-		register_error(as, l, 1, "No symbol specified");
-		return;
-	}
-
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
-	if (r < 0)
-		v = 0;
-
-	l -> symaddr = v & 0xFFFF;
-	l -> addrset = 2;
-	
-	// note: we need to do this because the symbol might have resolved
-	// to a constant!
-	lwasm_register_symbol(as, l, l -> sym, v, (r > 0 ? SYMBOL_COMPLEX: SYMBOL_NORM) | SYMBOL_FORCE);
-}
-
-OPFUNC(pseudo_set)
-{
-	int r, v;
-
-	// set MUST run on both passes as the symbol value changes!
-
-	if (l -> sym == NULL)
-	{
-		register_error(as, l, 1, "No symbol specified");
-		return;
-	}
-
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
-	if (r < 0)
-		v = 0;
-
-	l -> symaddr = v & 0xFFFF;
-	l -> addrset = 2;
-	
-	lwasm_register_symbol(as, l, l -> sym, v, (r > 0 ? SYMBOL_COMPLEX: SYMBOL_NORM) | SYMBOL_SET);
-}
-
-OPFUNC(pseudo_setdp)
-{
-	int r, v;
-
-	if (as -> outformat == OUTPUT_OBJ)
-	{
-		register_error(as, l, 1, "SETDP not permitted with OBJ target");
-		return;
-	}
-	
-	// setdp is needed on both passes; must resolve to a constant on pass 1
-	r = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v, 0);
-	if (r != 0)
-		return;
-
-	if (v < -127 || v > 255)
-	{
-		register_error(as, l, 1, "Byte overflow");
-		return;
-	}
-	
-	l -> symaddr = v & 0xFF;
-	l -> addrset = 2;
-	
-	as -> dpval = v & 0xFF;
-}
-
-OPFUNC(pseudo_fcc)
-{
-	int delim = 0;
-				
-	delim = **p;
-	if (!delim)
-	{
-		register_error(as, l, 1, "Bad operand");
-		return;
-	}
-	*p += 1;
-	while (**p && **p != delim)
-	{
-		lwasm_emit(as, l, **p);
-		(*p)++;
-	}
-	if (**p)
-		(*p)++;
-}
-		
-
-OPFUNC(pseudo_fcs)
-{
-	int delim = 0;
-
-	delim = **p;
-	if (!delim)
-	{
-		register_error(as, l, 1, "Bad operand");
-		return;
-	}
-	*p += 1;
-	while (**p && **p != delim)
-	{
-		if (!*((*p) + 1) || *((*p) + 1) == delim)
-			lwasm_emit(as, l, **p | 0x80);
-		else
-			lwasm_emit(as, l, **p);
-		(*p)++;
-	}
-	if (**p)
-		(*p)++;
-}
-
-OPFUNC(pseudo_fcn)
-{		
-	int delim = 0;
-				
-	delim = **p;
-	if (!delim)
-	{
-		register_error(as, l, 1, "Bad operand");
-		return;
-	}
-	*p += 1;
-	while (**p && **p != delim)
-	{
-		lwasm_emit(as, l, **p);
-		(*p)++;
-	}
-	if (**p)
-		(*p)++;
-	lwasm_emit(as, l, 0);
-}
-
-// FIXME: handle external, etc., references in a useful manner
-OPFUNC(pseudo_fcb)
-{
-	int r, v;
-	
-fcb_again:
-	r = lwasm_expr_result2(as, l, p, 0, &v, -1);
-	if (r < 0)
-		return;
-
-	if (r > 0)
-	{
-		register_error(as, l, 2, "Illegal external or inter-segment reference");
-		v = 0;
-	}
-
-	if (v < -127 || v > 255)
-	{
-		register_error(as, l, 1, "Byte overflow");
-	}
-	
-	lwasm_emit(as, l, v);
-	if (**p == ',')
-	{
-		(*p)++;
-		goto fcb_again;
-	}
-}
-
-// FIXME: handle external references in an intelligent way
-OPFUNC(pseudo_fdb)
-{			
-	int r, v;
-	int extseen = 0;
-	char *p1;
-	
-fdb_again:
-	p1 = *p;
-	r = lwasm_expr_result2(as, l, p, 0, &v, -1);
-	if (r < 0)
-		return;
-
-	if (r > 0 && extseen == 1)
-	{
-		register_error(as, l, 2, "Illegal external or inter-segment reference (only 1 per FDB line)");
-		v = 0;
-	}
-	else if (r > 0)
-	{
-		l -> relocoff = as -> addr - l -> codeaddr;
-		*p = p1;
-		r = lwasm_expr_result2(as, l, p, 0, &v, 0);
-	}
-
-	lwasm_emit(as, l, v >> 8);
-	lwasm_emit(as, l, v & 0xff);
-	if (**p == ',')
-	{
-		(*p)++;
-		goto fdb_again;
-	}
-}
-
-// FIXME: handle external references in a sensible way
-OPFUNC(pseudo_fqb)
-{	
-	int r, v;
-	
-fqb_again:
-	r = lwasm_expr_result2(as, l, p, 0, &v, -1);
-	if (r < 0)
-		return;
-
-	if (r > 0)
-	{
-		register_error(as, l, 2, "Illegal external or inter-segment reference");
-		v = 0;
-	}
-
-	lwasm_emit(as, l, v >> 24);
-	lwasm_emit(as, l, v >> 16);
-	lwasm_emit(as, l, v >> 8);
-	lwasm_emit(as, l, v & 0xff);
-	if (**p == ',')
-	{
-		(*p)++;
-		goto fqb_again;
-	}
-}
-
-// don't need to do anything if we are executing one of these
-OPFUNC(pseudo_endc)
-{
-	if (as -> skipcond && !(as -> skipmacro))
-	{
-		as -> skipcount -= 1;
-		if (as -> skipcount <= 0)
-		{
-			as -> skipcond = 0;
-		}
-	}
-	return;
-}
-
-// if "else" executes, we must be going into an "ignore" state
-OPFUNC(pseudo_else)
-{
-	if (as -> skipmacro)
-		return;
-	
-	if (as -> skipcond)
-	{
-		if (as -> skipcount == 1)
-		{
-			as -> skipcount = 0;
-			as -> skipcond = 0;
-		}
-		return;
-	}
-	
-	as -> skipcond = 1;
-	as -> skipcount = 1;
-}
-
-OPFUNC(pseudo_ifne)
-{
-	int v1;
-	int rval;
-
-	if (as -> skipcond && !(as -> skipmacro))
-	{
-		as -> skipcount++;
-		return;
-	}
-
-	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
-	if (rval != 0)
-		return;
-	if (!v1)
-	{
-		as -> skipcond = 1;
-		as -> skipcount = 1;
-	}
-}
-
-OPFUNC(pseudo_ifdef)
-{
-	lwasm_symbol_ent_t *se;
-	char *sym;
-	char *p2;
-	
-	if (as -> skipcond && !(as -> skipmacro))
-	{
-		as -> skipcount++;
-		return;
-	}
-
-	if (as -> passnum != 1)
-	{
-		if (!(l -> fsize))
-		{
-			as -> skipcond = 1;
-			as -> skipcount = 1;
-		}
-		return;
-	}
-
-	if (!**p)
-	{
-		register_error(as, l, 1, "Need symbol name");
-		return;
-	}
-	
-	for (p2 = *p; *p2 && !isspace(*p2); p2++)
-		/* do nothing */ ;
-	
-	sym = lwasm_alloc(p2 - *p + 1);
-	memcpy(sym, *p, p2 - *p);
-	sym[p2 - *p] = '\0';
-	
-	*p = p2;
-
-	se = lwasm_find_symbol(as, sym, l -> context);
-	if (!se)
-		se = lwasm_find_symbol(as, sym, -1);
-	
-	lwasm_free(sym);
-	
-	if (!se)
-	{
-		as -> skipcond = 1;
-		as -> skipcount = 1;
-		l -> fsize = 0;
-	}
-	else
-	{
-		l -> fsize = 1;
-	}
-}
-
-OPFUNC(pseudo_ifndef)
-{
-	lwasm_symbol_ent_t *se;
-	char *sym;
-	char *p2;
-	
-	if (as -> skipcond && !(as -> skipmacro))
-	{
-		as -> skipcount++;
-		return;
-	}
-
-	if (as -> passnum != 1)
-	{
-		if (l -> fsize)
-		{
-			as -> skipcond = 1;
-			as -> skipcount = 1;
-		}
-		return;
-	}
-
-	if (!**p)
-	{
-		register_error(as, l, 1, "Need symbol name");
-		return;
-	}
-	
-	for (p2 = *p; *p2 && !isspace(*p2); p2++)
-		/* do nothing */ ;
-	
-	sym = lwasm_alloc(p2 - *p + 1);
-	memcpy(sym, *p, p2 - *p);
-	sym[p2 - *p] = '\0';
-	
-	*p = p2;
-
-	se = lwasm_find_symbol(as, sym, l -> context);
-	if (!se)
-		se = lwasm_find_symbol(as, sym, -1);
-	
-	lwasm_free(sym);
-	
-	if (se)
-	{
-		as -> skipcond = 1;
-		as -> skipcount = 1;
-		l -> fsize = 0;
-	}
-	else
-	{
-		l -> fsize = 1;
-	}
-}
-
-OPFUNC(pseudo_ifeq)
-{
-	int v1;
-	int rval;
-
-	if (as -> skipcond && !(as -> skipmacro))
-	{
-		as -> skipcount++;
-		return;
-	}
-
-	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
-	if (rval != 0)
-		return;
-	if (v1)
-	{
-		as -> skipcond = 1;
-		as -> skipcount = 1;
-	}
-}
-
-OPFUNC(pseudo_iflt)
-{
-	int v1;
-	int rval;
-
-	if (as -> skipcond && !(as -> skipmacro))
-	{
-		as -> skipcount++;
-		return;
-	}
-
-	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
-	if (rval != 0)
-		return;
-	if (v1 >= 0)
-	{
-		as -> skipcond = 1;
-		as -> skipcount = 1;
-	}
-}
-
-OPFUNC(pseudo_ifle)
-{
-	int v1;
-	int rval;
-
-	if (as -> skipcond && !(as -> skipmacro))
-	{
-		as -> skipcount++;
-		return;
-	}
-
-	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
-	if (rval != 0)
-		return;
-	if (v1 > 0)
-	{
-		as -> skipcond = 1;
-		as -> skipcount = 1;
-	}
-}
-
-OPFUNC(pseudo_ifgt)
-{
-	int v1;
-	int rval;
-
-	if (as -> skipcond && !(as -> skipmacro))
-	{
-		as -> skipcount++;
-		return;
-	}
-
-	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
-	if (rval != 0)
-		return;
-	if (v1 <= 0)
-	{
-		as -> skipcond = 1;
-		as -> skipcount = 1;
-	}
-}
-
-OPFUNC(pseudo_ifge)
-{
-	int v1;
-	int rval;
-
-	if (as -> skipcond && !(as -> skipmacro))
-	{
-		as -> skipcount++;
-		return;
-	}
-
-	rval = lwasm_expr_result2(as, l, p, EXPR_SECTCONST | EXPR_PASS1CONST, &v1, 0);
-	if (rval != 0)
-		return;
-	if (v1 < 0)
-	{
-		as -> skipcond = 1;
-		as -> skipcount = 1;
-	}
-}
-
-OPFUNC(pseudo_error)
-{
-	register_error(as, l, 1, "User error: %s", *p);
-}
-
-
-OPFUNC(pseudo_section)
-{
-	sectiontab_t *s;
-	char *p2;
-	char *sn;
-	char *opts;
-	
-
-	if (as -> outformat != OUTPUT_OBJ)
-	{
-		register_error(as, l, 1, "Sections only supported for obj target");
-		return;
-	}
-	
-	if (as -> csect)
-	{
-		as -> csect -> offset = as -> addr;
-		as -> csect = NULL;
-	}
-	
-	if (!**p)
-	{
-		register_error(as, l, 1, "Need section name");
-		return;
-	}
-	
-	for (p2 = *p; *p2 && !isspace(*p2); p2++)
-		/* do nothing */ ;
-	
-	sn = lwasm_alloc(p2 - *p + 1);
-	memcpy(sn, *p, p2 - *p);
-	sn[p2 - *p] = '\0';
-	
-	*p = p2;
-	
-	opts = strchr(sn, ',');
-	if (opts)
-	{
-		*opts++ = '\0';
-	}
-	
-	// have we seen the section name already?
-	for (s = as -> sections; s; s = s -> next)
-	{
-		if (!strcmp(s -> name, sn))
-			break;
-	}
-	
-	if (s && as -> passnum == 1)
-	{
-		lwasm_free(sn);
-		if (opts)
-		{
-			register_error(as, l, 1, "Section options can only be specified the first time");
-			return;
-		}
-	}
-	else if (!s)
-	{
-		s = lwasm_alloc(sizeof(sectiontab_t));
-		s -> name = sn;
-		s -> offset = 0;
-		s -> flags = 0;
-		s -> obytes = NULL;
-		s -> oblen = 0;
-		s -> obsize = 0;
-		s -> rl = NULL;
-		s -> exports = NULL;
-		// parse options; only one "bss"
-		if (opts && as -> passnum == 1)
-		{
-			if (!strcasecmp(opts, "bss"))
-			{
-				s -> flags = SECTION_BSS;
-			}
-			else
-			{
-				register_error(as, l, 1, "Unrecognized section option '%s'", opts);
-				lwasm_free(s -> name);
-				lwasm_free(s);
-				return;
-			}
-		}
-		
-		s -> next = as -> sections;
-		as -> sections = s;
-	}
-	as -> addr = s -> offset;
-	as -> csect = s;
-	as -> context = lwasm_next_context(as);
-}
-
-OPFUNC(pseudo_endsection)
-{
-	if (as -> outformat != OUTPUT_OBJ)
-	{
-		register_error(as, l, 1, "Sections only supported for obj target");
-		return;
-	}
-	
-	if (!(as -> csect))
-	{
-		register_error(as, l, 1, "ENDSECTION when not in a section");
-		return;
-	}
-	
-	as -> csect -> offset = as -> addr;
-	as -> addr = 0;
-	as -> csect = 0;
-	as -> context = lwasm_next_context(as);
-}
-
-OPFUNC(pseudo_extern)
-{
-	if (as -> passnum != 1)
-		return;
-
-	if (as -> outformat != OUTPUT_OBJ)
-	{
-		register_error(as, l, 1, "External references only supported for obj target");
-		return;
-	}
-	
-	if (as -> csect)
-	{
-		register_error(as, l, 1, "Cannot declare external symbols within a section");
-		return;
-	}
-	
-	lwasm_register_symbol(as, l, l -> sym, 0, SYMBOL_EXTERN);
-}
-
-OPFUNC(pseudo_export)
-{
-	lwasm_symbol_ent_t *se;
-	export_list_t *ex;
-	
-	if (as -> outformat != OUTPUT_OBJ)
-	{
-		register_error(as, l, 1, "Symbol exports only supported for obj target");
-		return;
-	}
-	
-	if (as -> passnum == 1)
-		return;
-
-	// the symbol better be defined at this point (pass 2)
-	// local symbols cannot be exported nor can "global" symbols
-	se = lwasm_find_symbol(as, l -> sym, -1);
-	if (!se)
-	{
-		register_error(as, l, 2, "Exported symbols must be fully defined within a section");
-		return;
-	}
-	if (se -> sect == NULL)
-	{
-		register_error(as, l, 2, "Only non-local symbols within a section can be exported");
-		return;
-	}
-
-	if (se -> flags & SYMBOL_SET)
-	{
-		register_error(as, l, 2, "You cannot export symbols defined with SET");
-		return;
-	}
-
-	// if the symbol is not already a simple value, re-evaluate it
-	// and see if it becomes simple
-	
-
-	if (se -> flags & SYMBOL_COMPLEX)
-	{
-		register_error(as, l, 2, "Exported symbols must be fully resolved on pass 2");
-		return;
-	}
-
-	// search for existing export
-	for (ex = se -> sect -> exports; ex; ex = ex -> next)
-		if (!strcmp(l -> sym, ex -> sym))
-			break;
-	if (ex)
-	{
-		register_error(as, l, 2, "Symbol %s already exported", l -> sym);
-		return;
-	}
-
-	// add an external reference
-	ex = lwasm_alloc(sizeof(export_list_t));
-	ex -> next = se -> sect -> exports;
-	se -> sect -> exports = ex;
-	ex -> offset = se -> value;
-	ex -> sym = lwasm_strdup(se -> sym);
-}