0
|
1 /*
|
|
2 * symtab.c
|
|
3 *
|
|
4 * main code for lwasm
|
|
5 */
|
|
6
|
|
7 #include <ctype.h>
|
|
8 #include <errno.h>
|
|
9 #include <stdio.h>
|
|
10 #include <stdlib.h>
|
|
11 #include <string.h>
|
|
12 #define __symtab_c_seen__
|
|
13 #include "lwasm.h"
|
|
14
|
|
15 void register_symbol(asmstate_t *as, sourceline_t *cl, char *symstr, int val, int flags)
|
|
16 {
|
|
17 symtab_t *st;
|
|
18 symtab_t *prev;
|
|
19 int cv = -2;
|
|
20
|
|
21 for (prev = NULL, st = as -> symbol_table; st; st = st -> next)
|
|
22 {
|
|
23 cv = strcasecmp(st -> symbol, symstr);
|
|
24 if (cv == 0)
|
|
25 {
|
|
26 cv = strcmp(st -> symbol, symstr);
|
|
27 }
|
|
28 if (cv >= 0)
|
|
29 break;
|
|
30 prev = st;
|
|
31 }
|
|
32 // cv is 0 if we found the symbol, > 0 if we didn't and found one
|
|
33 // later in order, or -2 if we never did a comparison
|
|
34 // if st is NULL, the value of cv is irrelevant as it means
|
|
35 // we fell off the end of the list
|
|
36 // if st is NULL and prev is not, then prev is the tail of the list
|
|
37 // if both are NULL, the list is empty
|
|
38
|
|
39 // handle adding the symbol if needed
|
|
40 if (!st || cv != 0)
|
|
41 {
|
|
42 symtab_t *st2;
|
|
43 // register the symbol
|
|
44 st2 = malloc(sizeof(symtab_t));
|
|
45 st2 -> symbol = strdup(symstr);
|
|
46 st2 -> addr = val;
|
|
47 st2 -> flags = 0;
|
|
48 if (flags & SYMFLAG_SET)
|
|
49 st2 -> flags |= SYMFLAG_SET;
|
|
50
|
|
51 if (prev)
|
|
52 prev -> next = st2;
|
|
53 else
|
|
54 as -> symbol_table = st2;
|
|
55
|
|
56 st2 -> next = st;
|
|
57 return;
|
|
58 }
|
|
59
|
|
60 // st is NOT NULL here and cv IS 0
|
|
61 if ((flags & SYMFLAG_SET) && ((st -> flags) & SYMFLAG_SET))
|
|
62 {
|
|
63 // symbol already exists but it is a "SET" symbol so reset the value
|
|
64 st -> addr = val;
|
|
65 return;
|
|
66 }
|
|
67 if (st && as -> passnum == 1)
|
|
68 {
|
|
69 // duplicate symbol, flag error
|
|
70 errorp1(ERR_DUPSYM);
|
|
71 }
|
|
72 if (st -> addr != val)
|
|
73 errorp2(ERR_PHASE);
|
|
74 }
|
|
75
|
|
76 int lookup_symbol(asmstate_t *as, char *symstr)
|
|
77 {
|
|
78 symtab_t *st;
|
|
79
|
|
80 for (st = as -> symbol_table; st; st = st -> next)
|
|
81 {
|
|
82 if (!strcmp(symstr, st -> symbol))
|
|
83 break;
|
|
84 }
|
|
85 if (st)
|
|
86 return st -> addr;
|
|
87 return -1;
|
|
88 }
|
|
89
|
|
90 void list_symbols(asmstate_t *as, FILE *f)
|
|
91 {
|
|
92 symtab_t *st;
|
|
93 for (st = as -> symbol_table; st; st = st -> next)
|
|
94 {
|
|
95 fprintf(f, "%04X %s%s\n", st -> addr, st -> symbol, (st -> flags & SYMFLAG_SET) ? "(S)" : "");
|
|
96 }
|
|
97 }
|