Mercurial > hg-old > index.cgi
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 } |