changeset 254:c7a41b4c89b3 2.x

Added struct support to LWASM
author lost
date Sat, 19 Dec 2009 06:38:43 +0000
parents c537a3a723fc
children 6363b9ebf825
files ChangeLog lwasm/Makefile.am lwasm/instab.c lwasm/instab.h lwasm/lwasm.h lwasm/parse.c lwasm/pass1.c lwasm/pass2.c lwasm/pseudo.c lwasm/struct.c lwasm/symbol.c m4/gnulib-cache.m4
diffstat 12 files changed, 286 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Dec 09 03:59:26 2009 +0000
+++ b/ChangeLog	Sat Dec 19 06:38:43 2009 +0000
@@ -16,6 +16,7 @@
 [!] Fixed symbol resolution so all externally referenced objects, including
     within library archives, are properly included [LWLINK]
 [!] Fixed bug that prevented setting non-default stack size for LWEX [LWLINK]
+[+] Added structure support (struct, endstruct) [LWASM]
 [+] Added "EXTDEP" pseudo op to force a dependency on an external symbol
     without an actual external reference - a zero-width external reference
     so to speak [LWASM,LWLINK]
--- a/lwasm/Makefile.am	Wed Dec 09 03:59:26 2009 +0000
+++ b/lwasm/Makefile.am	Sat Dec 19 06:38:43 2009 +0000
@@ -1,5 +1,5 @@
 AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib
 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 os9.c
+lwasm_SOURCES = main.c expr.c pass1.c pass2.c util.c instab.c parse.c lwasm.c insn_inh.c insn_rtor.c insn_rlist.c insn_rel.c insn_tfm.c insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c list.c symbol.c output.c pseudo.c macro.c pragma.c os9.c struct.c
 lwasm_LDADD = -L$(top_builddir)/lib -L$(top_srcdir)/lib -lgnu
 EXTRA_DIST = instab.h lwasm.h expr.h util.h
--- a/lwasm/instab.c	Wed Dec 09 03:59:26 2009 +0000
+++ b/lwasm/instab.c	Sat Dec 19 06:38:43 2009 +0000
@@ -86,6 +86,9 @@
 extern OPFUNC(pseudo_includebin);
 extern OPFUNC(pseudo_extdep);
 
+extern OPFUNC(pseudo_struct);
+extern OPFUNC(pseudo_endstruct);
+
 extern OPFUNC(pseudo_os9);
 extern OPFUNC(pseudo_mod);
 extern OPFUNC(pseudo_emod);
@@ -359,9 +362,9 @@
 
 	{ "extdep",	{ -1, -1, -1, -1 }, pseudo_extdep, 0, 0, 1 },
 
-	{ "rmb", 	{ -1, -1, -1, -1 }, pseudo_rmb },
-	{ "rmd", 	{ -1, -1, -1, -1 }, pseudo_rmd },
-	{ "rmq", 	{ -1, -1, -1, -1 }, pseudo_rmq },
+	{ "rmb", 	{ -1, -1, -1, -1 }, pseudo_rmb, 0, 0, 0, 0, 1 },
+	{ "rmd", 	{ -1, -1, -1, -1 }, pseudo_rmd, 0, 0, 0, 0, 1 },
+	{ "rmq", 	{ -1, -1, -1, -1 }, pseudo_rmq, 0, 0, 0, 0, 1 },
 
 	{ "zmb", 	{ -1, -1, -1, -1 }, pseudo_zmb },
 	{ "zmd", 	{ -1, -1, -1, -1 }, pseudo_zmd },
@@ -404,6 +407,10 @@
 	{ "macro",	{ -1, -1, -1, -1}, 	pseudo_macro,	1,	0,	1 },
 	{ "endm",	{ -1, -1, -1, -1},	pseudo_endm,	1,	1,	1 },
 
+	{ "struct",	{ -1, -1, -1, -1}, 	pseudo_struct,	0,	0,	0 },
+	{ "ends",	{ -1, -1, -1, -1},	pseudo_endstruct,	0,	0,	0, 0, 1},
+	{ "endstruct",	{ -1, -1, -1, -1},	pseudo_endstruct,	0,	0,	0, 0, 1 },
+
 	{ "setdp", 	{ -1, -1, -1, -1},	pseudo_setdp },
 	{ "set",	{ -1, -1, -1, -1},	pseudo_set,	0,	0,	1 },
 
@@ -444,9 +451,9 @@
 	{ ".asciz",	{ -1, -1, -1, -1},	pseudo_fcn },
 	{ ".strz",	{ -1, -1, -1, -1},	pseudo_fcn },
 	
-	{ ".blkb",	{ -1, -1, -1, -1},	pseudo_rmb },
-	{ ".ds",	{ -1, -1, -1, -1},	pseudo_rmb },
-	{ ".rs",	{ -1, -1, -1, -1},	pseudo_rmb },
+	{ ".blkb",	{ -1, -1, -1, -1},	pseudo_rmb, 0, 0, 0, 0, 1 },
+	{ ".ds",	{ -1, -1, -1, -1},	pseudo_rmb, 0, 0, 0, 0, 1 },
+	{ ".rs",	{ -1, -1, -1, -1},	pseudo_rmb, 0, 0, 0, 0, 1 },
 
 // needs to handle C escapes maybe?
 //	{ ".ascii",	{ -1, -1, -1, -1},	pseudo_ascii },
--- a/lwasm/instab.h	Wed Dec 09 03:59:26 2009 +0000
+++ b/lwasm/instab.h	Sat Dec 19 06:38:43 2009 +0000
@@ -35,6 +35,7 @@
 	int endm;					/* end of macro? */
 	int setsym;					/* does this set a symbol address? EQU, SET */
 	int is6309;					/* is this 6309 only? */
+	int isreserve;				/* reserves space but does not output anything */
 } instab_t;
 
 #define OPFUNC(fn)	void (fn)(asmstate_t *as, lwasm_line_t *l, char **p, int opnum)
--- a/lwasm/lwasm.h	Wed Dec 09 03:59:26 2009 +0000
+++ b/lwasm/lwasm.h	Sat Dec 19 06:38:43 2009 +0000
@@ -78,6 +78,26 @@
 	macrotab_t *next;
 };
 
+// structure for tracking structs
+struct struct_sym_e;
+
+typedef struct structtab_s structtab_t;
+struct structtab_s
+{
+	char *name;
+	int size;
+	struct struct_sym_e *fields;
+	structtab_t *next;
+};
+
+struct struct_sym_e
+{
+	char *name;
+	int size;
+	structtab_t *substruct;
+	struct struct_sym_e *next;
+};
+
 // structure for tracking errors
 typedef struct lwasm_error_s lwasm_error_t;
 struct lwasm_error_s
@@ -131,6 +151,7 @@
 #define SYMBOL_NORM		0	// no flags
 #define SYMBOL_EXTERN	8	// the symbol is an external reference
 #define SYMBOL_GLOBAL	16	// force global if non-complex symbol
+#define SYMBOL_NOCHECK	32	// don't check characters for validity
 typedef struct lwasm_symbol_ent_s lwasm_symbol_ent_t;
 struct lwasm_symbol_ent_s
 {
@@ -162,6 +183,8 @@
 	lwasm_symbol_ent_t *symtail;	// last entry in symbol table
 	
 	macrotab_t *macros;			// macro table
+	structtab_t *structs;		// structure table
+	structtab_t *cstruct;		// address within the current structure def
 
 	const char *infile;			// input file
 	const char *outfile;		// output file
@@ -178,6 +201,7 @@
 	int macroex;				// current depth of macro expansion
 	int nextcontext;			// next context number
 	int skiplines;				// number of lines to skip
+	int instruct;				// are we currently in a structure def?
 	
 	// items used only for the "object" target
 	sectiontab_t *sections;		// pointer to section table
--- a/lwasm/parse.c	Wed Dec 09 03:59:26 2009 +0000
+++ b/lwasm/parse.c	Sat Dec 19 06:38:43 2009 +0000
@@ -188,6 +188,62 @@
 	if (as -> skipcond && instab[opnum].iscond == 0)
 		goto done_line;
 
+	if (as -> instruct && as -> passnum == 1)
+	{
+		structtab_t *s = NULL;
+		struct struct_sym_e *e, *e2;
+
+		// look for a structure if not an acceptable opcode
+		if (!instab[opnum].opcode)
+		{
+			for (s = as -> structs; s; s = s -> next)
+			{
+				if (s == as -> cstruct)
+					continue;
+				if (!strcmp(opc, s -> name))
+					goto isok;
+			}
+		}
+		// check for a "reservation opcode"
+		if (instab[opnum].opcode && instab[opnum].isreserve)
+		{
+			(instab[opnum].fn)(as, l, &p2, opnum);
+			
+			// if we didn't end on a "space" character or EOL, throw error
+			if (p2 && *p2 && !isspace(*p2) && !(l -> err) && as -> passnum == 1)
+				register_error(as, l, 1, "Bad operand: %s (%d)", p2, as -> passnum);
+			
+			if (as -> instruct == 0)
+				goto done_line;
+			
+			goto isok;
+		}
+		// carp if not valid
+		register_error(as, l, 1, "Only other structs and rmb allowed in struct");
+		l -> badop = 1;
+		goto done_line;
+		
+	isok:
+		for (e2 = as -> cstruct -> fields; e2 && e2 -> next; e2 = e2 -> next)
+			/* do nothing */ ;
+		e = lwasm_alloc(sizeof(struct struct_sym_e));
+		e -> next = NULL;
+		e -> substruct = s;
+		if (sym)
+			e -> name = lwasm_strdup(sym);
+		else
+			e -> name = NULL;
+		if (s)
+			e -> size = s -> size;
+		else
+			e -> size = l -> nocodelen;
+		if (e2)
+			e2 -> next = e;
+		else
+			as -> cstruct -> fields = e;
+		as -> cstruct -> size += e -> size;
+	}
+
 	// 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
@@ -215,6 +271,9 @@
 		if (expand_macro(as, l, &p2, opc) == 0)
 			goto done_line;
 
+		if (expand_struct(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);
@@ -225,7 +284,7 @@
 	if (!(as -> skipcond || as -> inmacro))
 	{
 		// register symbol if the operation didn't
-		if (sym && instab[opnum].setsym == 0)
+		if (sym && instab[opnum].setsym == 0 && as -> instruct == 0)
 		{
 			if (as -> passnum == 1)
 			{
--- a/lwasm/pass1.c	Wed Dec 09 03:59:26 2009 +0000
+++ b/lwasm/pass1.c	Sat Dec 19 06:38:43 2009 +0000
@@ -166,6 +166,8 @@
 	as -> nextcontext = 1;
 
 	as -> inmod = 0;
+	
+	as -> instruct = 0;
 
 	as -> extdeps = NULL;
 	as -> nextdeps = 0;
--- a/lwasm/pass2.c	Wed Dec 09 03:59:26 2009 +0000
+++ b/lwasm/pass2.c	Sat Dec 19 06:38:43 2009 +0000
@@ -44,6 +44,7 @@
 	as -> skiplines = 0;
 	as -> dpval = 0;
 	as -> inmod = 0;
+	as -> instruct = 0;
 	
 	for (st = as -> sections; st; st = st -> next)
 		st -> offset = 0;
--- a/lwasm/pseudo.c	Wed Dec 09 03:59:26 2009 +0000
+++ b/lwasm/pseudo.c	Sat Dec 19 06:38:43 2009 +0000
@@ -222,6 +222,8 @@
 	if (r != 0)
 		return;
 	l -> nocodelen = v;
+	if (as -> instruct)
+		return;
 	as -> addr += v;
 }
 
@@ -240,6 +242,8 @@
 		return;
 	v *= 2;
 	l -> nocodelen = v;
+	if (as -> instruct)
+		return;
 	as -> addr += v;
 }
 
@@ -258,6 +262,8 @@
 		return;
 	v *= 4;
 	l -> nocodelen = v;
+	if (as -> instruct)
+		return;
 	as -> addr += v;
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/struct.c	Sat Dec 19 06:38:43 2009 +0000
@@ -0,0 +1,174 @@
+/*
+struct.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 stuff associated with structure definition.
+
+Structures have their own name space. Macros will shadow structures so it's
+a good idea to make sure no structures are name the same as macros.
+*/
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lwasm.h"
+#include "instab.h"
+#include "util.h"
+
+OPFUNC(pseudo_struct)
+{
+	structtab_t *m;
+
+	// actually define a structure
+	if (as -> instruct)
+	{
+		register_error(as, l, 1, "Attempt to define a structure inside a structure");
+		return;
+ 	}
+
+	as -> instruct = 1;
+
+	// don't actually do anything if not pass 1
+	if (as -> passnum != 1)
+		return;
+
+
+	if (!l -> sym)
+	{
+		register_error(as, l, 1, "Structure definition with no effect - no symbol");
+		return;
+	}
+	
+	// search for macro by same name...
+	for (m = as -> structs; m; m = m -> next)
+	{
+		if (!strcmp(m -> name, l -> sym))
+			break;
+	}
+	if (m)
+	{
+		register_error(as, l, 1, "Duplicate structure definition");
+		return;
+	}
+	
+	m = lwasm_alloc(sizeof(structtab_t));
+	m -> name = lwasm_strdup(l -> sym);
+	m -> next = as -> structs;
+	m -> fields = NULL;
+	m -> size = 0;
+	as -> structs = m;
+	as -> cstruct = m;
+	
+	while (**p && !isspace(**p))
+		(*p)++;
+}
+
+
+
+pseudo_endstruct_aux(asmstate_t *as, lwasm_line_t *l, struct struct_sym_e *e, const char *prefix, int *coff)
+{
+	char *symname = NULL;
+	
+	while (e)
+	{
+		if (e -> name)
+			0 == asprintf(&symname, "%s.%s", prefix, e -> name);
+		else
+			0 == asprintf(&symname, "%s.___%d", prefix, *coff);
+		
+		// register symbol "symname" as global at coff
+		lwasm_register_symbol(as, l, symname, *coff, SYMBOL_NOCHECK);
+
+		if (e -> substruct)
+		{
+			char * t;
+			0 == asprintf(&t, "sizeof{%s}", symname);
+			lwasm_register_symbol(as, l, t, e -> substruct -> size, SYMBOL_NOCHECK);
+			lwasm_free(t);
+			pseudo_endstruct_aux(as, l, e -> substruct -> fields, symname, coff);
+		}
+		else
+		{
+			*coff += e -> size;
+		}
+
+		lwasm_free(symname);
+		e = e -> next;
+	}
+}
+
+OPFUNC(pseudo_endstruct)
+{
+	int coff = 0;
+	char *t;
+	
+	as -> instruct = 0;
+
+	if (as -> passnum != 1)
+		return;
+
+	// now register the global symbols for the structure
+	// this is a recursive process
+	0 == asprintf(&t, "sizeof{%s}", as -> cstruct -> name);
+	lwasm_register_symbol(as, l, t, as -> cstruct -> size, SYMBOL_NOCHECK);
+	lwasm_free(t);
+
+	pseudo_endstruct_aux(as, l, as -> cstruct -> fields, as -> cstruct -> name, &coff);
+}
+
+
+int expand_struct(asmstate_t *as, lwasm_line_t *l, char **p, char *opc)
+{
+	structtab_t *s;
+	int addr;
+	char *t;
+	
+	if (as -> passnum != 1)
+		return 0;
+	
+	for (s = as -> structs; s; s = s -> next)
+	{
+		if (!strcmp(opc, s -> name))
+			break;
+	}
+	if (!s)
+		return -1;
+
+	if (!(l -> sym))
+	{
+		register_error(as, l, 1, "Cannot declare a structure without a symbol name.");
+		return; 
+	}
+
+	l -> nocodelen = s -> size;
+
+	addr = as -> addr;
+	as -> addr += s -> size;
+	
+	// now register the global symbols for the structure
+	// this is a recursive process
+	0 == asprintf(&t, "sizeof{%s}", l -> sym);
+	lwasm_register_symbol(as, l, t, s -> size, SYMBOL_NOCHECK);
+	lwasm_free(t);
+
+	pseudo_endstruct_aux(as, l, s -> fields, l -> sym, &addr);
+	
+	return 0;
+}
--- a/lwasm/symbol.c	Wed Dec 09 03:59:26 2009 +0000
+++ b/lwasm/symbol.c	Sat Dec 19 06:38:43 2009 +0000
@@ -62,7 +62,7 @@
 	// [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(sym, '$'))
+	if ((flags & SYMBOL_NOCHECK) == 0 && !strchr(sym, '$'))
 	{
 		if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._@?", *sym))
 		{
@@ -79,7 +79,7 @@
 	
 	for (p = sym; *p; p++)
 	{
-		if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._$?@0123456789", *sym))
+		if ((flags & SYMBOL_NOCHECK == 0) && !strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._$?@0123456789", *sym))
 		{
 			register_error(as, l, 1, "Bad symbol: %s", sym);
 			return -1;
--- a/m4/gnulib-cache.m4	Wed Dec 09 03:59:26 2009 +0000
+++ b/m4/gnulib-cache.m4	Sat Dec 19 06:38:43 2009 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2002-2008 Free Software Foundation, Inc.
+# Copyright (C) 2002-2009 Free Software Foundation, Inc.
 #
 # This file is free software, distributed under the terms of the GNU
 # General Public License.  As a special exception to the GNU General