# HG changeset patch
# User lost
# Date 1230956449 0
# Node ID 538e15927776824d969ae4681480133a4a90ba9c
# Parent 99e3b3310bacd5040610bb604a62c80518c51142
Added symbol handling to expression subsystem; adpated instruction handlers to the new scheme; misc fixes
diff -r 99e3b3310bac -r 538e15927776 src/Makefile.am
--- a/src/Makefile.am Fri Jan 02 06:07:40 2009 +0000
+++ b/src/Makefile.am Sat Jan 03 04:20:49 2009 +0000
@@ -1,3 +1,3 @@
bin_PROGRAMS = lwasm
-lwasm_SOURCES = main.c expr.c pass1.c pass2.c util.c instab.c parse.c lwasm.c insn_inh.c insn_rtor.c insn_rlist.c insn_rel.c insn_tfm.c insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c list.c
+lwasm_SOURCES = main.c expr.c pass1.c pass2.c util.c instab.c parse.c lwasm.c insn_inh.c insn_rtor.c insn_rlist.c insn_rel.c insn_tfm.c insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c list.c symbol.c
EXTRA_DIST = instab.h lwasm.h expr.h util.h
diff -r 99e3b3310bac -r 538e15927776 src/expr.c
--- a/src/expr.c Fri Jan 02 06:07:40 2009 +0000
+++ b/src/expr.c Sat Jan 03 04:20:49 2009 +0000
@@ -67,6 +67,8 @@
lwasm_expr_term_t *lwasm_expr_term_create_oper(int oper)
{
lwasm_expr_term_t *t;
+
+fprintf(stderr, "Creating operator term: %d\n", oper);
t = lwasm_alloc(sizeof(lwasm_expr_term_t));
t -> term_type = LWASM_TERM_OPER;
@@ -77,6 +79,7 @@
lwasm_expr_term_t *lwasm_expr_term_create_int(int val)
{
lwasm_expr_term_t *t;
+fprintf(stderr, "Creating integer term: %d\n", val);
t = lwasm_alloc(sizeof(lwasm_expr_term_t));
t -> term_type = LWASM_TERM_INT;
@@ -88,6 +91,7 @@
{
lwasm_expr_term_t *t;
+fprintf(stderr, "Creating symbol term: %s\n", sym);
t = lwasm_alloc(sizeof(lwasm_expr_term_t));
t -> term_type = LWASM_TERM_SYM;
t -> symbol = lwasm_strdup(sym);
@@ -177,10 +181,11 @@
int lwasm_expr_parse_term(lwasm_expr_stack_t *s, const char **p)
{
lwasm_expr_term_t *t;
-
+fprintf(stderr, "Expression string %s\n", *p);
eval_next:
if (**p == '(')
{
+ fprintf(stderr, "Starting paren\n");
(*p)++;
lwasm_expr_parse_expr(s, p, 0);
if (**p != ')')
@@ -191,6 +196,7 @@
if (**p == '+')
{
+ fprintf(stderr, "Unary +\n");
(*p)++;
goto eval_next;
}
@@ -424,6 +430,7 @@
{
// otherwise we must be decimal (if we're still allowed one)
val = decval;
+ fprintf(stderr, "End of decimal value\n");
break;
}
else
@@ -492,7 +499,14 @@
dval -= '0';
if (dval > 9)
dval -= 7;
-
+ fprintf(stderr, "Got digit: %d\n", dval);
+// if (dval > 1)
+// valtype &= 14;
+// if (dval > 7)
+// valtype &= 12;
+// if (dval > 9)
+// valtype &= 8;
+
if (valtype & 8)
{
hexval = hexval * 16 + dval;
@@ -520,11 +534,12 @@
}
}
// break out if we have a return value
- if (valtype = -1)
+ if (valtype == -1)
break;
// return if no more valid possibilities!
if (valtype == 0)
return -1;
+ val = decval; // in case we fall through
}
// we get here when we have a value to return
@@ -560,12 +575,15 @@
lwasm_expr_term_t *operterm;
// return if we are at the end of the expression or a subexpression
- if (!**p || isspace(**p) || **p == ')')
+ if (!**p || isspace(**p) || **p == ')' || **p == ',')
return 0;
-eval_next:
if (lwasm_expr_parse_term(s, p) < 0)
return -1;
+
+eval_next:
+ if (!**p || isspace(**p) || **p == ')' || **p == ',')
+ return 0;
// expecting an operator here
for (opern = 0; operators[opern].opernum != LWASM_OPER_NONE; opern++)
@@ -625,15 +643,18 @@
contain the pointer to the next character after the expression if and only
if there is no error. In the case of an error, *outp is undefined.
*/
-lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp)
+lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp, int (*sfunc)(char *sym, void *state, int *val), void *state)
{
lwasm_expr_stack_t *s;
const char *p;
-
+ int rval;
+
// actually parse the expression
p = inp;
s = lwasm_expr_stack_create();
- if (lwasm_expr_parse_expr(s, &p, 0) < 0)
+
+ rval = lwasm_expr_parse_expr(s, &p, 0);
+ if (rval < 0)
goto cleanup_error;
// save end of expression
@@ -641,8 +662,11 @@
(*outp) = p;
// return potentially partial expression
- if (lwasm_expr_reval(s) < 0)
+ if (lwasm_expr_reval(s, sfunc, state) < 0)
goto cleanup_error;
+
+ if (lwasm_expr_is_constant(s))
+ fprintf(stderr, "Constant expression evaluates to: %d\n", lwasm_expr_get_value(s));
return s;
@@ -668,9 +692,26 @@
further operators or only a single term remains
*/
-int lwasm_expr_reval(lwasm_expr_stack_t *s)
+int lwasm_expr_reval(lwasm_expr_stack_t *s, int (*sfunc)(char *sym, void *state, int *val), void *state)
{
lwasm_expr_stack_node_t *n;
+ int sval;
+
+ // resolve symbols
+ // symbols that do not resolve to a constant are left alone
+ for (n = s -> head; n; n = n -> next)
+ {
+ if (n -> term -> term_type == LWASM_TERM_SYM)
+ {
+ if (sfunc(n -> term -> symbol, state, &sval) == 0)
+ {
+ n -> term -> term_type = LWASM_TERM_INT;
+ n -> term -> value = sval;
+ lwasm_free(n -> term -> symbol);
+ n -> term -> symbol = NULL;
+ }
+ }
+ }
next_iter:
// a single term
diff -r 99e3b3310bac -r 538e15927776 src/expr.h
--- a/src/expr.h Fri Jan 02 06:07:40 2009 +0000
+++ b/src/expr.h Sat Jan 03 04:20:49 2009 +0000
@@ -97,10 +97,10 @@
You must call lwasm_expr_stack_free() on the result when you are finished
with it.
*/
-__expr_E__ lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp);
+__expr_E__ lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp, int (*sfunc)(char *sym, void *state, int *val), void *state);
// simplify expression
-__expr_E__ int lwasm_expr_reval(lwasm_expr_stack_t *s);
+__expr_E__ int lwasm_expr_reval(lwasm_expr_stack_t *s, int (*sfunc)(char *sym, void *state, int *val), void *state);
// useful macros
// is the expression "simple" (one term)?
diff -r 99e3b3310bac -r 538e15927776 src/insn_bitbit.c
--- a/src/insn_bitbit.c Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_bitbit.c Sat Jan 03 04:20:49 2009 +0000
@@ -59,7 +59,7 @@
register_error(as, l, 1, "Bad operand");
return;
}
- s = lwasm_expr_eval(*p, NULL);
+ s = lwasm_evaluate_expr(as, l, *p, NULL);
if (!s)
{
register_error(as, l, 1, "Bad operand");
@@ -83,7 +83,7 @@
}
r = (r << 6) | (v1 << 3);
- s = lwasm_expr_eval(*p, NULL);
+ s = lwasm_evaluate_expr(as, l, *p, NULL);
if (!s)
{
register_error(as, l, 1, "Bad operand");
@@ -113,7 +113,7 @@
if (**p == '<')
(*p)++;
- s = lwasm_expr_eval(*p, NULL);
+ s = lwasm_evaluate_expr(as, l, *p, NULL);
if (!s)
{
register_error(as, l, 1, "Bad operand");
diff -r 99e3b3310bac -r 538e15927776 src/insn_gen.c
--- a/src/insn_gen.c Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_gen.c Sat Jan 03 04:20:49 2009 +0000
@@ -61,7 +61,7 @@
(*optr)++;
f16 = 1;
}
- s = lwasm_expr_eval(*optr, NULL);
+ s = lwasm_evaluate_expr(as, l, *optr, NULL);
if (!s)
{
register_error(as, l, 1, "Bad expression");
@@ -138,7 +138,7 @@
{
lwasm_emitop(as, l, instab[opnum].ops[3]);
(*p)++;
- s = lwasm_expr_eval(*p, NULL);
+ s = lwasm_evaluate_expr(as, l, *p, NULL);
if (!s)
{
register_error(as, l, 1, "Bad expression");
@@ -169,7 +169,7 @@
{
lwasm_emitop(as, l, instab[opnum].ops[3]);
(*p)++;
- s = lwasm_expr_eval(*p, NULL);
+ s = lwasm_evaluate_expr(as, l, *p, NULL);
if (!s)
{
register_error(as, l, 1, "Bad expression");
@@ -199,7 +199,7 @@
{
lwasm_emitop(as, l, instab[opnum].ops[3]);
(*p)++;
- s = lwasm_expr_eval(*p, NULL);
+ s = lwasm_evaluate_expr(as, l, *p, NULL);
if (!s)
{
register_error(as, l, 1, "Bad expression");
@@ -231,7 +231,7 @@
{
lwasm_emitop(as, l, instab[opnum].ops[0]);
(*p)++;
- s = lwasm_expr_eval(*p, NULL);
+ s = lwasm_evaluate_expr(as, l, *p, NULL);
if (!s)
{
register_error(as, l, 1, "Bad expression");
diff -r 99e3b3310bac -r 538e15927776 src/insn_indexed.c
--- a/src/insn_indexed.c Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_indexed.c Sat Jan 03 04:20:49 2009 +0000
@@ -129,7 +129,7 @@
*b1 = 0x9f;
*b2 = 0;
*b3 = 0;
- s = lwasm_expr_eval(*p, &p2);
+ s = lwasm_evaluate_expr(as, l, *p, &p2);
if (!s)
{
register_error(as, l, 1, "Bad expression");
@@ -170,7 +170,7 @@
}
// now we have to evaluate the expression
- s = lwasm_expr_eval(*p, &p2);
+ s = lwasm_evaluate_expr(as, l, *p, &p2);
*p = p2;
if (!s)
{
diff -r 99e3b3310bac -r 538e15927776 src/insn_logicmem.c
--- a/src/insn_logicmem.c Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_logicmem.c Sat Jan 03 04:20:49 2009 +0000
@@ -40,7 +40,7 @@
if (**p == '#')
(*p)++;
- s = lwasm_expr_eval(*p, &p2);
+ s = lwasm_evaluate_expr(as, l, *p, &p2);
*p = (char *)p2;
if (!s)
diff -r 99e3b3310bac -r 538e15927776 src/insn_rel.c
--- a/src/insn_rel.c Fri Jan 02 06:07:40 2009 +0000
+++ b/src/insn_rel.c Sat Jan 03 04:20:49 2009 +0000
@@ -37,7 +37,7 @@
lwasm_emitop(as, l, instab[opnum].ops[0]);
- s = lwasm_expr_eval(*p, NULL);
+ s = lwasm_evaluate_expr(as, l, *p, NULL);
if (!s)
{
register_error(as, l, 1, "Bad operand");
@@ -62,7 +62,7 @@
lwasm_emitop(as, l, instab[opnum].ops[0]);
- s = lwasm_expr_eval(*p, NULL);
+ s = lwasm_evaluate_expr(as, l, *p, NULL);
if (!s)
{
register_error(as, l, 1, "Bad operand");
diff -r 99e3b3310bac -r 538e15927776 src/lwasm.c
--- a/src/lwasm.c Fri Jan 02 06:07:40 2009 +0000
+++ b/src/lwasm.c Sat Jan 03 04:20:49 2009 +0000
@@ -29,6 +29,7 @@
#include "lwasm.h"
#include "util.h"
+#include "expr.h"
int register_error(asmstate_t *as, lwasm_line_t *l, int pass, const char *fmt, ...)
{
@@ -147,3 +148,36 @@
(*str)+=3;
return rval;
}
+
+struct symstateinfo
+{
+ asmstate_t *as;
+ lwasm_line_t *l;
+};
+
+int lwasm_expr_lookup_symbol(char *sym, void *state, int *val)
+{
+ lwasm_symbol_ent_t *se;
+ struct symstateinfo *st;
+
+ st = state;
+
+ // look for local symbol first then global symbol
+ se = lwasm_find_symbol(st -> as, sym, st -> as -> context);
+ if (!se)
+ se = lwasm_find_symbol(st -> as, sym, -1);
+ if (!se)
+ return -1;
+ *val = se -> value;
+ return 0;
+}
+
+lwasm_expr_stack_t *lwasm_evaluate_expr(asmstate_t *as, lwasm_line_t *l, const char *inp, const char **outp)
+{
+ struct symstateinfo st;
+
+ st.as = as;
+ st.l = l;
+
+ return(lwasm_expr_eval(inp, outp, lwasm_expr_lookup_symbol, &st));
+}
diff -r 99e3b3310bac -r 538e15927776 src/lwasm.h
--- a/src/lwasm.h Fri Jan 02 06:07:40 2009 +0000
+++ b/src/lwasm.h Sat Jan 03 04:20:49 2009 +0000
@@ -24,10 +24,13 @@
#ifndef __lwasm_h_seen__
#define __lwasm_h_seen__
+#include "expr.h"
+
#define OUTPUT_DECB 0 // DECB multirecord format
#define OUTPUT_RAW 1 // raw sequence of bytes
#define OUTPUT_OBJ 2 // proprietary object file format
+
// structure for tracking errors
typedef struct lwasm_error_s lwasm_error_t;
struct lwasm_error_s
@@ -46,12 +49,25 @@
lwasm_line_t *prev; // previous line
lwasm_error_t *err; // error messages
int fsize; // forced size (0 = no forced size)
+ char *sym; // scratch area to record the presence of a symbol
+};
+
+// for keeping track of symbols
+typedef struct lwasm_symbol_ent_s lwasm_symbol_ent_t;
+struct lwasm_symbol_ent_s
+{
+ char *sym; // the symbol
+ int context; // the context number of the symbol (-1 for global)
+ int value; // the value of the symbol
+ lwasm_symbol_ent_t *next; // next symbol in the table
+ lwasm_symbol_ent_t *prev; // previous symbol in the table
};
// keep track of current assembler state
typedef struct {
int dpval; // current dp value (setdp)
int addr; // current address
+ int context; // context counter (for local symbols)
int errorcount; // error count
int passnum; // which pass are we on?
int execaddr; // execution address for the program (END ....)
@@ -59,6 +75,9 @@
lwasm_line_t *lineshead; // first line of source code
lwasm_line_t *linestail; // last line of source code
+
+ lwasm_symbol_ent_t *symhead; // first entry in symbol table
+ lwasm_symbol_ent_t *symtail; // last entry in symbol table
const char *infile; // input file
const char *outfile; // output file
@@ -84,14 +103,23 @@
__lwasm_E__ int lwasm_lookupreg2(const char *reglist, char **str);
__lwasm_E__ int lwasm_lookupreg3(const char *rlist, const char **str);
+__lwasm_E__ lwasm_expr_stack_t *lwasm_evaluate_expr(asmstate_t *as, lwasm_line_t *l, const char *inp, const char **outp);
+
#undef __lwasm_E__
-#ifndef __symtab_c_seen__
-//extern void register_symbol(asmstate_t *as, sourceline_t *cl, char *symstr, int val, int flags);
-//extern int lookup_symbol(asmstate_t *as, char *symstr);
-//extern void list_symbols(asmstate_t *as, FILE *f);
+#ifndef __symbol_c_seen__
+#define __lwasm_E__ extern
+#else
+#define __lwasm_E__
#endif
+__lwasm_E__ int lwasm_register_symbol(asmstate_t *as, lwasm_line_t *l, char *sym, int val);
+__lwasm_E__ lwasm_symbol_ent_t *lwasm_find_symbol(asmstate_t *as, char *sym, int scontext);
+__lwasm_E__ int lwasm_set_symbol(asmstate_t *as, char *sym, int scontext, int val);
+
+#undef __lwasm_E__
+
+
#endif //__lwasm_h_seen__
diff -r 99e3b3310bac -r 538e15927776 src/parse.c
--- a/src/parse.c Fri Jan 02 06:07:40 2009 +0000
+++ b/src/parse.c Sat Jan 03 04:20:49 2009 +0000
@@ -37,17 +37,43 @@
char *p, *p2;
char *opc;
int opnum;
+ char *sym;
p = l -> text;
if (!*p)
+ {
+ as -> context += 1;
return 0;
+ }
if (!isspace(*p) && *p != '*' && *p != ';')
{
// we have a symbol specified here
// parse it and define
// need to handle local symbols here...
+ for (p2 = p; *p2 && !isspace(*p2); p2++)
+ /* do nothing */ ;
+
+ sym = lwasm_alloc((p2 - p) + 1);
+ sym[p2 - p] = '\0';
+ memcpy(sym, p, p2 - p);
+
+ l -> sym = sym;
+ // have a symbol; now determine if it is valid and register it
+ // at the current address of the line
+ if (lwasm_register_symbol(as, l, sym, as -> addr) < 0)
+ l -> sym = NULL;
+ }
+ else
+ {
+ while (*p && isspace(*p))
+ (*p)++;
+ if (!*p)
+ {
+ as -> context += 1;
+ return 0;
+ }
}
// skip white space
@@ -56,7 +82,10 @@
// if comment or end of line, return
if (!*p || *p == '*' || *p == ';')
+ {
+ lwasm_free(l -> sym);
return 0;
+ }
// parse the opcode
for (p2 = p; *p2 && !isspace(*p2); p2++)
@@ -83,6 +112,7 @@
{
// invalid operation code, throw error
register_error(as, l, 1, "Invalid operation code '%s'", opc);
+ lwasm_free(l -> sym);
lwasm_free(opc);
return -1;
}
@@ -91,4 +121,5 @@
(instab[opnum].fn)(as, l, &p2, opnum);
lwasm_free(opc);
+ lwasm_free(sym);
}
diff -r 99e3b3310bac -r 538e15927776 src/pass1.c
--- a/src/pass1.c Fri Jan 02 06:07:40 2009 +0000
+++ b/src/pass1.c Sat Jan 03 04:20:49 2009 +0000
@@ -135,6 +135,7 @@
nl -> prev = as -> linestail;
nl -> err = NULL;
nl -> fsize = 0;
+ nl -> sym = NULL;
if (as -> linestail)
as -> linestail -> next = nl;
else
diff -r 99e3b3310bac -r 538e15927776 src/symbol.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/symbol.c Sat Jan 03 04:20:49 2009 +0000
@@ -0,0 +1,120 @@
+/*
+symbol.c
+Copyright © 2009 William Astle
+
+This file is part of LWASM.
+
+LWASM is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see .
+*/
+
+/*
+for handling the symbol table
+*/
+
+#define __symbol_c_seen__
+
+#include
+
+#include "lwasm.h"
+#include "util.h"
+
+int lwasm_register_symbol(asmstate_t *as, lwasm_line_t *l, char *sym, int val)
+{
+ lwasm_symbol_ent_t *se, *se2;
+ char *p;
+
+ int scontext = -1;
+
+ // first check if the symbol is valid
+ // the following characters are allowed in a symbol:
+ // [a-zA-Z0-9._$?@] and any byte value larger than 0x7F
+ // although symbols should be restricted to the 7 bit range
+ // symbols must start with [a-zA-Z._]
+ if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._@?", *sym))
+ {
+ register_error(as, l, 1, "Bad symbol: %s", sym);
+ return -1;
+ }
+
+ for (p = sym; *p; p++)
+ {
+ if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._$?@0123456789", *sym) && (unsigned char)*sym < 0x80)
+ {
+ register_error(as, l, 1, "Bad symbol: %s", sym);
+ return -1;
+ }
+ // flag local symbols while we're at it...
+ if (*p == '?' || *p == '@')
+ scontext = as -> context;
+ }
+
+ // now look it for to see if it is a duplicate
+ se = lwasm_find_symbol(as, sym, scontext);
+ if (se)
+ {
+ register_error(as, l, 1, "Mulitply defined symbol: %s", sym);
+ return -1;
+ }
+
+ // if not a duplicate, register it with the value
+ se = lwasm_alloc(sizeof(lwasm_symbol_ent_t));
+ if (as -> symhead)
+ {
+ se -> prev = NULL;
+ se -> next = as -> symhead;
+ as -> symhead -> prev = se;
+ as -> symhead = se;
+ }
+ else
+ {
+ se -> next = NULL;
+ se -> prev = NULL;
+ as -> symhead = se;
+ as -> symtail = se;
+ }
+ se -> value = val;
+ se -> sym = lwasm_strdup(sym);
+ se -> context = scontext;
+
+ return 0;
+}
+
+lwasm_symbol_ent_t *lwasm_find_symbol(asmstate_t *as, char *sym, int scontext)
+{
+ lwasm_symbol_ent_t *se;
+
+ for (se = as -> symhead; se; se = se -> next)
+ {
+ if (scontext == se -> context && !strcmp(sym, se -> sym))
+ {
+ return se;
+ }
+ }
+ return NULL;
+}
+
+// reset the value of a symbol - should not be used normally
+// it is intended for use by such operations as EQU
+// returns -1 if the symbol is not registered
+int lwasm_set_symbol(asmstate_t *as, char *sym, int scontext, int val)
+{
+ lwasm_symbol_ent_t *se;
+
+ se = lwasm_find_symbol(as, sym, scontext);
+ if (!se)
+ return -1;
+
+ se -> value = val;
+ return 0;
+}
diff -r 99e3b3310bac -r 538e15927776 src/symtab.c
--- a/src/symtab.c Fri Jan 02 06:07:40 2009 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
-symtab.c
-Copyright © 2008 William Astle
-
-This file is part of LWASM.
-
-LWASM is free software: you can redistribute it and/or modify it under the
-terms of the GNU General Public License as published by the Free Software
-Foundation, either version 3 of the License, or (at your option) any later
-version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-more details.
-
-You should have received a copy of the GNU General Public License along with
-this program. If not, see .
-
-Implements code for handling the symbol table.
-*/
-
-#include
-#include
-#include
-#include
-#include
-#define __symtab_c_seen__
-#include "lwasm.h"
-
-void register_symbol(asmstate_t *as, sourceline_t *cl, char *symstr, int val, int flags)
-{
- symtab_t *st;
- symtab_t *prev;
- int cv = -2;
-
- for (prev = NULL, st = as -> symbol_table; st; st = st -> next)
- {
- cv = strcasecmp(st -> symbol, symstr);
- if (cv == 0)
- {
- cv = strcmp(st -> symbol, symstr);
- }
- if (cv >= 0)
- break;
- prev = st;
- }
- // cv is 0 if we found the symbol, > 0 if we didn't and found one
- // later in order, or -2 if we never did a comparison
- // if st is NULL, the value of cv is irrelevant as it means
- // we fell off the end of the list
- // if st is NULL and prev is not, then prev is the tail of the list
- // if both are NULL, the list is empty
-
- // handle adding the symbol if needed
- if (!st || cv != 0)
- {
- symtab_t *st2;
- // register the symbol
- st2 = malloc(sizeof(symtab_t));
- st2 -> symbol = strdup(symstr);
- st2 -> addr = val;
- st2 -> flags = 0;
- if (flags & SYMFLAG_SET)
- st2 -> flags |= SYMFLAG_SET;
-
- if (prev)
- prev -> next = st2;
- else
- as -> symbol_table = st2;
-
- st2 -> next = st;
- return;
- }
-
- // st is NOT NULL here and cv IS 0
- if ((flags & SYMFLAG_SET) && ((st -> flags) & SYMFLAG_SET))
- {
- // symbol already exists but it is a "SET" symbol so reset the value
- st -> addr = val;
- return;
- }
- if (st && as -> passnum == 1)
- {
- // duplicate symbol, flag error
- errorp1(ERR_DUPSYM);
- }
- if (st -> addr != val)
- errorp2(ERR_PHASE);
-}
-
-int lookup_symbol(asmstate_t *as, char *symstr)
-{
- symtab_t *st;
-
- for (st = as -> symbol_table; st; st = st -> next)
- {
- if (!strcmp(symstr, st -> symbol))
- break;
- }
- if (st)
- return st -> addr;
- return -1;
-}
-
-void list_symbols(asmstate_t *as, FILE *f)
-{
- symtab_t *st;
- for (st = as -> symbol_table; st; st = st -> next)
- {
- fprintf(f, "%04X %s%s\n", st -> addr, st -> symbol, (st -> flags & SYMFLAG_SET) ? "(S)" : "");
- }
-}