# HG changeset patch
# User lost
# Date 1261204723 0
# Node ID c7a41b4c89b3c1927420f2614b7317be65d32a97
# Parent c537a3a723fc16d423e50d520433e368ec811d28
Added struct support to LWASM
diff -r c537a3a723fc -r c7a41b4c89b3 ChangeLog
--- 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]
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/Makefile.am
--- 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
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/instab.c
--- 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 },
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/instab.h
--- 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)
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/lwasm.h
--- 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
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/parse.c
--- 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)
{
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/pass1.c
--- 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;
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/pass2.c
--- 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;
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/pseudo.c
--- 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;
}
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/struct.c
--- /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 .
+
+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
+
+#include
+#include
+#include
+#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;
+}
diff -r c537a3a723fc -r c7a41b4c89b3 lwasm/symbol.c
--- 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;
diff -r c537a3a723fc -r c7a41b4c89b3 m4/gnulib-cache.m4
--- 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