# HG changeset patch
# User lost@l-w.ca
# Date 1279168435 21600
# Node ID fbb7bfed80768cd10ade41a57a1f1f4a44c1e15e
# Parent 8991eb507d2d46de1d8fe80678b93d273c2f026c
Added in structure support and fixed up some warts in the listing code (by adding more warts)
diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/Makefile.am
--- a/lwasm/Makefile.am Wed Jul 14 20:17:57 2010 -0600
+++ b/lwasm/Makefile.am Wed Jul 14 22:33:55 2010 -0600
@@ -4,6 +4,7 @@
instab.c symbol.c macro.c pass2.c pass3.c pass4.c pass5.c pass6.c \
insn_inh.c insn_rtor.c insn_tfm.c insn_rlist.c insn_rel.c \
insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c \
- pseudo.c section.c os9.c pass7.c debug.c output.c list.c
+ pseudo.c section.c os9.c pass7.c debug.c output.c list.c \
+ struct.c
lwasm_LDADD = -L$(top_builddir)/lib -L$(top_srcdir)/lib -L$(top_builddir)/lwlib -L$(top_srcdir)/lwlib -lgnu -llw
EXTRA_DIST = lwasm.h input.h instab.h
diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/instab.c
--- a/lwasm/instab.c Wed Jul 14 20:17:57 2010 -0600
+++ b/lwasm/instab.c Wed Jul 14 22:33:55 2010 -0600
@@ -285,6 +285,14 @@
extern RESOLVEFUNC(pseudo_resolve_align);
extern EMITFUNC(pseudo_emit_align);
+extern PARSEFUNC(pseudo_parse_struct);
+#define pseudo_resolve_struct NULL
+#define pseudo_emit_struct NULL
+
+extern PARSEFUNC(pseudo_parse_endstruct);
+#define pseudo_resolve_endstruct NULL
+#define pseudo_emit_endstruct NULL
+
instab_t instab[] =
{
@@ -555,9 +563,9 @@
{ "export", { -1, -1, -1, -1 }, pseudo_parse_export, pseudo_resolve_export, pseudo_emit_export, lwasm_insn_setsym},
{ "extdep", { -1, -1, -1, -1 }, pseudo_parse_extdep, pseudo_resolve_extdep, pseudo_emit_extdep, lwasm_insn_setsym},
- { "rmb", { -1, -1, -1, -1 }, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_normal},
- { "rmd", { -1, -1, -1, -1 }, pseudo_parse_rmd, pseudo_resolve_rmd, pseudo_emit_rmd, lwasm_insn_normal},
- { "rmq", { -1, -1, -1, -1 }, pseudo_parse_rmq, pseudo_resolve_rmq, pseudo_emit_rmq, lwasm_insn_normal},
+ { "rmb", { -1, -1, -1, -1 }, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_struct},
+ { "rmd", { -1, -1, -1, -1 }, pseudo_parse_rmd, pseudo_resolve_rmd, pseudo_emit_rmd, lwasm_insn_struct},
+ { "rmq", { -1, -1, -1, -1 }, pseudo_parse_rmq, pseudo_resolve_rmq, pseudo_emit_rmq, lwasm_insn_struct},
{ "zmb", { -1, -1, -1, -1 }, pseudo_parse_zmb, pseudo_resolve_zmb, pseudo_emit_zmb, lwasm_insn_normal},
{ "zmd", { -1, -1, -1, -1 }, pseudo_parse_zmd, pseudo_resolve_zmd, pseudo_emit_zmd, lwasm_insn_normal},
@@ -608,6 +616,9 @@
{ "ends", { -1, -1, -1, -1}, pseudo_parse_endsection,pseudo_resolve_endsection, pseudo_emit_endsection, lwasm_insn_normal},
{ "endsect", { -1, -1, -1, -1}, pseudo_parse_endsection,pseudo_resolve_endsection, pseudo_emit_endsection, lwasm_insn_normal},
{ "endsection", { -1, -1, -1, -1}, pseudo_parse_endsection,pseudo_resolve_endsection, pseudo_emit_endsection, lwasm_insn_normal},
+
+ { "struct", { -1, -1, -1, -1}, pseudo_parse_struct, pseudo_resolve_struct, pseudo_emit_struct, lwasm_insn_normal},
+ { "endstruct", { -1, -1, -1, -1}, pseudo_parse_endstruct, pseudo_resolve_endstruct, pseudo_emit_endstruct, lwasm_insn_struct},
{ "pragma", { -1, -1, -1, -1}, pseudo_parse_pragma, pseudo_resolve_pragma, pseudo_emit_pragma, lwasm_insn_normal},
@@ -643,9 +654,9 @@
{ ".asciz", { -1, -1, -1, -1}, pseudo_parse_fcn, pseudo_resolve_fcn, pseudo_emit_fcn, lwasm_insn_normal},
{ ".strz", { -1, -1, -1, -1}, pseudo_parse_fcn, pseudo_resolve_fcn, pseudo_emit_fcn, lwasm_insn_normal},
- { ".blkb", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_normal},
- { ".ds", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_normal},
- { ".rs", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_normal},
+ { ".blkb", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_struct},
+ { ".ds", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_struct},
+ { ".rs", { -1, -1, -1, -1}, pseudo_parse_rmb, pseudo_resolve_rmb, pseudo_emit_rmb, lwasm_insn_struct},
// for compatibility
{ ".end", { -1, -1, -1, -1 }, pseudo_parse_end, pseudo_resolve_end, pseudo_emit_end, lwasm_insn_normal},
diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/instab.h
--- a/lwasm/instab.h Wed Jul 14 20:17:57 2010 -0600
+++ b/lwasm/instab.h Wed Jul 14 22:33:55 2010 -0600
@@ -38,11 +38,12 @@
enum
{
- lwasm_insn_normal = 0,
lwasm_insn_cond = 1, /* conditional instruction */
lwasm_insn_endm = 2, /* end of macro */
lwasm_insn_setsym = 4, /* insn sets symbol address */
- lwasm_insn_is6309 = 8 /* insn is 6309 only */
+ lwasm_insn_is6309 = 8, /* insn is 6309 only */
+ lwasm_insn_struct = 16, /* insn allowed in a struct */
+ lwasm_insn_normal = 0
};
diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/list.c
--- a/lwasm/list.c Wed Jul 14 20:17:57 2010 -0600
+++ b/lwasm/list.c Wed Jul 14 22:33:55 2010 -0600
@@ -55,15 +55,53 @@
{
if (cl -> len < 1)
{
- fprintf(of, " ");
+ if (cl -> soff >= 0)
+ {
+ fprintf(of, "%04X ", cl -> soff & 0xffff);
+ }
+ else if (cl -> dshow >= 0)
+ {
+ if (cl -> dsize == 1)
+ {
+ fprintf(of, " %02X ", cl -> dshow & 0xff);
+ }
+ else
+ {
+ fprintf(of, " %04X ", cl -> dshow & 0xff);
+ }
+ }
+ else if (cl -> dptr)
+ {
+ lw_expr_t te;
+ te = lw_expr_copy(cl -> dptr -> value);
+ as -> exportcheck = 1;
+ as -> csect = cl -> csect;
+ lwasm_reduce_expr(as, te);
+ as -> exportcheck = 0;
+ if (lw_expr_istype(te, lw_expr_type_int))
+ {
+ fprintf(of, " %04X ", lw_expr_intval(te) & 0xffff);
+ }
+ else
+ {
+ fprintf(of, " ???? ");
+ }
+ lw_expr_destroy(te);
+ }
+ else
+ {
+ fprintf(of, " ");
+ }
}
else
{
lw_expr_t te;
te = lw_expr_copy(cl -> addr);
as -> exportcheck = 1;
+ as -> csect = cl -> csect;
lwasm_reduce_expr(as, te);
as -> exportcheck = 0;
+// fprintf(of, "%s\n", lw_expr_print(te));
fprintf(of, "%04X ", lw_expr_intval(te) & 0xffff);
lw_expr_destroy(te);
for (i = 0; i < cl -> outputl && i < 8; i++)
@@ -76,7 +114,7 @@
}
fprintf(of, " ");
}
- fprintf(of, "%15s:%05d %s\n", cl -> linespec, cl -> lineno, cl -> ltext);
+ fprintf(of, "(%31.31s):%05d %s\n", cl -> linespec, cl -> lineno, cl -> ltext);
if (cl -> outputl > 8)
{
for (i = 8; i < cl -> outputl; i++)
diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/lwasm.h
--- a/lwasm/lwasm.h Wed Jul 14 20:17:57 2010 -0600
+++ b/lwasm/lwasm.h Wed Jul 14 22:33:55 2010 -0600
@@ -166,11 +166,16 @@
char *ltext; // line number
char *linespec; // line spec
int lineno; // line number
+ int soff; // struct offset (for listings)
+ int dshow; // data value to show (for listings)
+ int dsize; // set to 1 for 8 bit dshow value
+ struct symtabe *dptr; // symbol value to display
};
enum
{
symbol_flag_set = 1, // symbol was used with "set"
+ symbol_flag_nocheck = 2, // do not check symbol characters
symbol_flag_none = 0 // no flags
};
@@ -198,6 +203,26 @@
int numlines; // number lines in macro
macrotab_t *next; // next macro in list
};
+
+typedef struct structtab_s structtab_t;
+typedef struct structtab_field_s structtab_field_t;
+
+struct structtab_field_s
+{
+ char *name; // structure field name - NULL for anonymous
+ int size; // structure field size
+ structtab_t *substruct; // sub structure if there is one
+ structtab_field_t *next; // next field entry
+};
+
+struct structtab_s
+{
+ char *name; // name of structure
+ int size; // number of bytes taken by struct
+ structtab_field_t *fields; // fields in the structure
+ structtab_t *next; // next structure
+};
+
struct asmstate_s
{
int output_format; // output format
@@ -208,6 +233,7 @@
int pragmas; // pragmas currently in effect
int errorcount; // number of errors encountered
int inmacro; // are we in a macro?
+ int instruct; // are w in a structure?
int skipcond; // skipping a condition?
int skipcount; // depth of "skipping"
int skipmacro; // are we skipping in a macro?
@@ -239,6 +265,9 @@
lw_stringlist_t include_list; // include paths
lw_stack_t file_dir; // stack of the "current file" dir
lw_stack_t includelist;
+
+ structtab_t *structs; // defined structures
+ structtab_t *cstruct; // current structure
int exportcheck; // set if we need to collapse out the section base to 0
};
diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/pass1.c
--- a/lwasm/pass1.c Wed Jul 14 20:17:57 2010 -0600
+++ b/lwasm/pass1.c Wed Jul 14 22:33:55 2010 -0600
@@ -31,6 +31,9 @@
#include "instab.h"
#include "input.h"
+extern int expand_macro(asmstate_t *as, line_t *l, char **p, char *opc);
+extern int expand_struct(asmstate_t *as, line_t *l, char **p, char *opc);
+
/*
pass 1: parse the lines
@@ -91,6 +94,10 @@
cl -> pragmas = as -> pragmas;
cl -> context = as -> context;
cl -> ltext = lw_strdup(line);
+ cl -> soff = -1;
+ cl -> dshow = -1;
+ cl -> dsize = 0;
+ cl -> dptr = NULL;
as -> cl = cl;
if (!as -> line_tail)
{
@@ -226,7 +233,7 @@
// do nothing
if (as -> skipcond && !(instab[opnum].flags & lwasm_insn_cond))
goto linedone;
-
+
if (instab[opnum].opcode == NULL)
{
cl -> insn = -1;
@@ -236,7 +243,11 @@
if (expand_macro(as, cl, &p1, sym) != 0)
{
// macro expansion failed
- lwasm_register_error(as, cl, "Bad opcode");
+ if (expand_struct(as, cl, &p1, sym) != 0)
+ {
+ // structure expansion failed
+ lwasm_register_error(as, cl, "Bad opcode");
+ }
}
}
}
@@ -246,13 +257,20 @@
// no parse func means operand doesn't matter
if (instab[opnum].parse)
{
- cl -> len = -1;
- // call parse function
- (instab[opnum].parse)(as, cl, &p1);
+ if (as -> instruct == 0 || instab[opnum].flags & lwasm_insn_struct)
+ {
+ cl -> len = -1;
+ // call parse function
+ (instab[opnum].parse)(as, cl, &p1);
- if (*p1 && !isspace(*p1))
+ if (*p1 && !isspace(*p1))
+ {
+ // flag bad operand error
+ lwasm_register_error(as, cl, "Bad operand (%s)", p1);
+ }
+ }
+ else if (as -> instruct == 1)
{
- // flag bad operand error
lwasm_register_error(as, cl, "Bad operand (%s)", p1);
}
}
diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/pseudo.c
--- a/lwasm/pseudo.c Wed Jul 14 20:17:57 2010 -0600
+++ b/lwasm/pseudo.c Wed Jul 14 22:33:55 2010 -0600
@@ -29,6 +29,8 @@
#include "lw_string.h"
+extern void register_struct_entry(asmstate_t *as, line_t *l, int size, structtab_t *ss);
+
// for "end"
PARSEFUNC(pseudo_parse_end)
{
@@ -302,6 +304,22 @@
{
lwasm_register_error(as, l, "Bad expression");
}
+
+ if (as -> instruct)
+ {
+ lwasm_reduce_expr(as, expr);
+ if (!lw_expr_istype(expr, lw_expr_type_int))
+ {
+ lwasm_register_error(as, l, "Expression must be constant at parse time");
+ }
+ else
+ {
+ int e;
+ e = lw_expr_intval(expr);
+ register_struct_entry(as, l, e, NULL);
+ l -> len = 0;
+ }
+ }
lwasm_save_expr(l, 0, expr);
}
@@ -337,6 +355,21 @@
lwasm_register_error(as, l, "Bad expression");
}
+ if (as -> instruct)
+ {
+ lwasm_reduce_expr(as, expr);
+ if (!lw_expr_istype(expr, lw_expr_type_int))
+ {
+ lwasm_register_error(as, l, "Expression must be constant at parse time");
+ }
+ else
+ {
+ int e;
+ e = lw_expr_intval(expr) * 2;
+ register_struct_entry(as, l, e, NULL);
+ l -> len = 0;
+ }
+ }
lwasm_save_expr(l, 0, expr);
}
@@ -371,6 +404,21 @@
{
lwasm_register_error(as, l, "Bad expression");
}
+ if (as -> instruct)
+ {
+ lwasm_reduce_expr(as, expr);
+ if (!lw_expr_istype(expr, lw_expr_type_int))
+ {
+ lwasm_register_error(as, l, "Expression must be constant at parse time");
+ }
+ else
+ {
+ int e;
+ e = lw_expr_intval(expr) * 4;
+ register_struct_entry(as, l, e, NULL);
+ l -> len = 0;
+ }
+ }
lwasm_save_expr(l, 0, expr);
}
@@ -563,6 +611,7 @@
register_symbol(as, l, l -> sym, e, symbol_flag_none);
l -> symset = 1;
+ l -> dptr = lookup_symbol(as, l, l -> sym);
}
PARSEFUNC(pseudo_parse_set)
@@ -586,6 +635,7 @@
register_symbol(as, l, l -> sym, e, symbol_flag_set);
l -> symset = 1;
+ l -> dptr = lookup_symbol(as, l, l -> sym);
}
PARSEFUNC(pseudo_parse_setdp)
@@ -613,6 +663,8 @@
return;
}
l -> dpval = lw_expr_intval(e) & 0xff;
+ l -> dshow = l -> dpval;
+ l -> dsize = 1;
}
PARSEFUNC(pseudo_parse_ifp1)
diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/struct.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lwasm/struct.c Wed Jul 14 22:33:55 2010 -0600
@@ -0,0 +1,218 @@
+/*
+struct.c
+Copyright © 2010 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 processing
+*/
+
+#include
+
+#include
+
+#include
+#include
+
+#include "lwasm.h"
+#include "instab.h"
+
+PARSEFUNC(pseudo_parse_struct)
+{
+ structtab_t *s;
+
+ if (as -> instruct)
+ {
+ lwasm_register_error(as, l, "Attempt to define a structure inside a structure");
+ return;
+ }
+
+ if (l -> sym == NULL)
+ {
+ lwasm_register_error(as, l, "Structure definition with no effect - no symbol");
+ return;
+ }
+
+ for (s = as -> structs; s; s = s -> next)
+ {
+ if (!strcmp(s -> name, l -> sym))
+ break;
+ }
+
+ if (s)
+ {
+ lwasm_register_error(as, l, "Duplicate structure definition");
+ return;
+ }
+
+ as -> instruct = 1;
+
+ s = lw_alloc(sizeof(structtab_t));
+ s -> name = lw_strdup(l -> sym);
+ s -> next = as -> structs;
+ s -> fields = NULL;
+ s -> size = 0;
+ as -> structs = s;
+ as -> cstruct = s;
+
+ skip_operand(p);
+
+ l -> len = 0;
+ l -> symset = 1;
+}
+
+void pseudo_endstruct_aux(asmstate_t *as, line_t *l, structtab_field_t *e, const char *prefix, int *coff)
+{
+ char *symname = NULL;
+ lw_expr_t te1, te2;
+
+ while (e)
+ {
+ if (e -> name)
+ 0 == asprintf(&symname, "%s.%s", prefix, e -> name);
+ else
+ 0 == asprintf(&symname, "%s.____%d", prefix, *coff);
+
+ // register the symbol
+ te1 = lw_expr_build(lw_expr_type_int, *coff);
+ te2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_plus, te1, l -> addr);
+ register_symbol(as, l, symname, te2, symbol_flag_nocheck);
+ lw_expr_destroy(te2);
+ lw_expr_destroy(te1);
+
+ if (e -> substruct)
+ {
+ char *t;
+ 0 == asprintf(&t, "sizeof{%s}", symname);
+ te1 = lw_expr_build(lw_expr_type_int, e -> substruct -> size);
+ register_symbol(as, l, t, te1, symbol_flag_nocheck);
+ lw_expr_destroy(te1);
+ lw_free(t);
+ pseudo_endstruct_aux(as, l, e -> substruct -> fields, symname, coff);
+ }
+ else
+ {
+ *coff += e -> size;
+ }
+ e = e -> next;
+ }
+}
+
+
+PARSEFUNC(pseudo_parse_endstruct)
+{
+ char *t;
+ int coff = 0;
+ lw_expr_t te;
+
+ if (as -> instruct == 0)
+ {
+ lwasm_register_warning(as, l, "endstruct without struct");
+ skip_operand(p);
+ return;
+ }
+
+ 0 == asprintf(&t, "sizeof{%s}", as -> cstruct -> name);
+ te = lw_expr_build(lw_expr_type_int, as -> cstruct -> size);
+ register_symbol(as, l, t, te, symbol_flag_nocheck);
+ lw_expr_destroy(te);
+ lw_free(t);
+
+ l -> soff = as -> cstruct -> size;
+ as -> instruct = 0;
+
+ skip_operand(p);
+
+ pseudo_endstruct_aux(as, l, as -> cstruct -> fields, as -> cstruct -> name, &coff);
+
+ l -> len = 0;
+}
+
+void register_struct_entry(asmstate_t *as, line_t *l, int size, structtab_t *ss)
+{
+ structtab_field_t *e, *e2;
+
+ l -> soff = as -> cstruct -> size;
+ e = lw_alloc(sizeof(structtab_field_t));
+ e -> next = NULL;
+ e -> size = size;
+ if (l -> sym)
+ e -> name = lw_strdup(l -> sym);
+ else
+ e -> name = NULL;
+ e -> substruct = ss;
+ if (as -> cstruct -> fields)
+ {
+ for (e2 = as -> cstruct -> fields; e2 -> next; e2 = e2 -> next)
+ /* do nothing */ ;
+ e2 -> next = e;
+ }
+ else
+ {
+ as -> cstruct -> fields = e;
+ }
+ as -> cstruct -> size += size;
+}
+
+int expand_struct(asmstate_t *as, line_t *l, char **p, char *opc)
+{
+ structtab_t *s;
+ char *t;
+ lw_expr_t te;
+ int addr = 0;
+
+ debug_message(as, 200, "Checking for structure expansion: %s", opc);
+
+ for (s = as -> structs; s; s = s -> next)
+ {
+ if (!strcmp(opc, s -> name))
+ break;
+ }
+
+ if (!s)
+ return -1;
+
+ debug_message(as, 10, "Expanding structure: %s", opc);
+
+ if (!(l -> sym))
+ {
+ lwasm_register_error(as, l, "Cannot declare a structure without a symbol name.");
+ return;
+ }
+
+ l -> len = s -> size;
+
+ if (as -> instruct)
+ 0 == asprintf(&t, "sizeof(%s.%s}", as -> cstruct -> name, l -> sym);
+ else
+ 0 == asprintf(&t, "sizeof{%s}", l -> sym);
+ te = lw_expr_build(lw_expr_type_int, s -> size);
+ register_symbol(as, l, t, te, symbol_flag_nocheck);
+ lw_expr_destroy(te);
+ lw_free(t);
+
+ if (as -> instruct)
+ 0 == asprintf(&t, "%s.%s", as -> cstruct -> name, l -> sym);
+ else
+ t = lw_strdup(l -> sym);
+ pseudo_endstruct_aux(as, l, s -> fields, t, &addr);
+ lw_free(t);
+ l -> symset = 1;
+ if (as -> instruct)
+ register_struct_entry(as, l, s -> size, s);
+ return 0;
+}
+
diff -r 8991eb507d2d -r fbb7bfed8076 lwasm/symbol.c
--- a/lwasm/symbol.c Wed Jul 14 20:17:57 2010 -0600
+++ b/lwasm/symbol.c Wed Jul 14 22:33:55 2010 -0600
@@ -38,16 +38,19 @@
int version = -1;
char *cp;
- if (*sym < 0x80 && !strchr(SSYMCHARS, *sym))
+ if (!(flags & symbol_flag_nocheck))
{
- lwasm_register_error(as, cl, "Bad symbol (%s)", sym);
- return NULL;
- }
+ if (*sym < 0x80 && !strchr(SSYMCHARS, *sym))
+ {
+ lwasm_register_error(as, cl, "Bad symbol (%s)", sym);
+ return NULL;
+ }
- if ((*sym == '$' || *sym == '@') && (sym[1] >= '0' && sym[1] <= '9'))
- {
- lwasm_register_error(as, cl, "Bad symbol (%s)", sym);
- return NULL;
+ if ((*sym == '$' || *sym == '@') && (sym[1] >= '0' && sym[1] <= '9'))
+ {
+ lwasm_register_error(as, cl, "Bad symbol (%s)", sym);
+ return NULL;
+ }
}
for (cp = sym; *cp; cp++)
@@ -58,7 +61,7 @@
islocal = 1;
// bad symbol
- if (*cp < 0x80 && !strchr(SYMCHARS, *cp))
+ if (!(flags & symbol_flag_nocheck) && *cp < 0x80 && !strchr(SYMCHARS, *cp))
{
lwasm_register_error(as, cl, "Bad symbol (%s)", sym);
return NULL;
@@ -84,6 +87,7 @@
break;
}
}
+
if (se)
{
// multiply defined symbol