comparison lwasm/symbol.c @ 151:427e268e876b

renamed src to lwasm to better reflect its purpose
author lost
date Fri, 30 Jan 2009 04:01:55 +0000
parents src/symbol.c@0ee5f65bccf9
children 563adfccb645
comparison
equal deleted inserted replaced
150:f0881c115010 151:427e268e876b
1 /*
2 symbol.c
3 Copyright © 2009 William Astle
4
5 This file is part of LWASM.
6
7 LWASM is free software: you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation, either version 3 of the License, or (at your option) any later
10 version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
16
17 You should have received a copy of the GNU General Public License along with
18 this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /*
22 for handling the symbol table
23 */
24
25 #define __symbol_c_seen__
26
27 #include <string.h>
28
29 #include "lwasm.h"
30 #include "util.h"
31 #include "expr.h"
32
33 /*
34 Note that this function may accept symbols that the expression evaluator doesn't
35 recognize because the expression evaluator must avoid all ambiguity in order
36 to achieve predictable results. The checks here are simply a fuzz check.
37 */
38
39 /*
40 NOTE: complex symbols always take their value from slot 0 on the expression placeholders
41 for a line!
42 */
43 int lwasm_register_symbol(asmstate_t *as, lwasm_line_t *l, char *sym, int val, int flags)
44 {
45 lwasm_symbol_ent_t *se, *se2;
46 char *p;
47
48 int scontext = -1;
49
50 // if the symbol is constant, fall back to simple registration!
51 if (flags & SYMBOL_COMPLEX)
52 {
53 if (l -> exprs[0] == NULL)
54 {
55 val = l -> exprvals[0];
56 flags &= ~SYMBOL_COMPLEX;
57 }
58 }
59
60 // first check if the symbol is valid
61 // the following characters are allowed in a symbol:
62 // [a-zA-Z0-9._$?@] and any byte value larger than 0x7F
63 // although symbols should be restricted to the 7 bit range
64 // symbols must start with [a-zA-Z._]
65 if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._@?", *sym))
66 {
67 register_error(as, l, 1, "Bad symbol: %s", sym);
68 return -1;
69 }
70
71 if (*sym == '@' && isdigit(sym[1]))
72 {
73 register_error(as, l, 1, "Bad symbol: %s", sym);
74 return -1;
75 }
76
77 for (p = sym; *p; p++)
78 {
79 if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._$?@0123456789", *sym))
80 {
81 register_error(as, l, 1, "Bad symbol: %s", sym);
82 return -1;
83 }
84 // flag local symbols while we're at it...
85 if (*p == '?' || *p == '@')
86 scontext = as -> context;
87 }
88
89 debug_message(3, "lwasm_register_symbol(): registering '%s' (%d) at %04X; flags=%d", sym, scontext, val, flags);
90
91 // now look it for to see if it is a duplicate
92 se = lwasm_find_symbol(as, sym, scontext);
93 if (se)
94 {
95 if (flags & SYMBOL_FORCE && as -> passnum != 2)
96 {
97 register_error(as, l, 1, "Multiply defined symbol: %s", sym);
98 return -1;
99 }
100 if (!(flags & SYMBOL_SET) || (flags & SYMBOL_SET && !(se -> flags & SYMBOL_SET)))
101 {
102 register_error(as, l, 1, "Mulitply defined symbol: %s", sym);
103 return -1;
104 }
105 }
106 if (se)
107 {
108 se -> value = val;
109 if (flags & SYMBOL_COMPLEX)
110 {
111 se -> expr = l -> exprs[0];
112 }
113 else
114 {
115 se -> expr = NULL;
116 }
117 return;
118 }
119
120 // if not a duplicate, register it with the value
121 se = lwasm_alloc(sizeof(lwasm_symbol_ent_t));
122 if (as -> symhead)
123 {
124 se -> prev = NULL;
125 se -> next = as -> symhead;
126 as -> symhead -> prev = se;
127 as -> symhead = se;
128 }
129 else
130 {
131 se -> next = NULL;
132 se -> prev = NULL;
133 as -> symhead = se;
134 as -> symtail = se;
135 }
136 se -> value = val;
137 if (flags & SYMBOL_COMPLEX)
138 se -> expr = l -> exprs[0];
139 se -> sym = lwasm_strdup(sym);
140 se -> context = scontext;
141
142 if (!(flags & SYMBOL_EXTERN))
143 se -> sect = as -> csect;
144 else
145 se -> sect = NULL;
146
147 se -> expr = NULL;
148 se -> flags = flags;
149 se -> externalname = NULL;
150
151 return 0;
152 }
153
154 lwasm_symbol_ent_t *lwasm_find_symbol(asmstate_t *as, char *sym, int scontext)
155 {
156 lwasm_symbol_ent_t *se;
157 static int st = 0;
158
159 for (se = as -> symhead; se; se = se -> next)
160 {
161 if (scontext == se -> context && !strcmp(sym, se -> sym))
162 {
163 return se;
164 }
165 }
166 if (as -> passnum == 2 && st == 0 && scontext == -1 && as -> outformat == OUTPUT_OBJ && as -> pragmas & PRAGMA_UNDEFEXTERN)
167 {
168 // we want undefined symbols to be considered external
169 // we didn't find it on a lookup so register it as external
170 // but we only do so when looking up in global context
171 st = 1;
172 if (lwasm_register_symbol(as, NULL, sym, 0, SYMBOL_EXTERN))
173 {
174 st = 0;
175 return NULL;
176 }
177 st = 0;
178
179 // find the newly registered symbol and return it
180 for (se = as -> symhead; se; se = se -> next)
181 {
182 if (scontext == se -> context && !strcmp(sym, se -> sym))
183 {
184 return se;
185 }
186 }
187 }
188
189 return NULL;
190 }
191
192 // reset the value of a symbol - should not be used normally
193 // it is intended for use by such operations as EQU
194 // returns -1 if the symbol is not registered
195 int lwasm_set_symbol(asmstate_t *as, char *sym, int scontext, int val)
196 {
197 lwasm_symbol_ent_t *se;
198
199 se = lwasm_find_symbol(as, sym, scontext);
200 if (!se)
201 return -1;
202
203 se -> value = val;
204 return 0;
205 }
206
207 void lwasm_list_symbols(asmstate_t *as, FILE *lf)
208 {
209 lwasm_symbol_ent_t *se;
210
211 for (se = as -> symhead; se; se = se -> next)
212 {
213 if (se -> expr)
214 {
215 fprintf(lf, "<incompl>");
216 }
217 else if (se -> value > 0xffff || se -> value < -0x8000)
218 {
219 fprintf(lf, "%08X ", se -> value);
220 }
221 else
222 {
223 fprintf(lf, " %04X ", se -> value);
224 }
225 if (se -> context < 0)
226 fputc('G', lf);
227 else
228 fputc('L', lf);
229
230 if (se -> flags & SYMBOL_SET)
231 fputc('S', lf);
232 else if (se -> flags & SYMBOL_EXTERN)
233 fputc('E', lf);
234 else
235 fputc(' ', lf);
236
237 fprintf(lf, " %s", se -> sym);
238
239 if (se -> context >= 0)
240 fprintf(lf, " (%d)", se -> context);
241
242 if (se -> sect)
243 {
244 fprintf(lf, " [%s]", se -> sect -> name);
245 }
246
247 fputc('\n', lf);
248 }
249 }