Mercurial > hg-old > index.cgi
comparison lwasm/lwasm.c @ 346:a82c55070624
Added expression parsing infrastructure and misc fixes
author | lost@starbug |
---|---|
date | Sat, 27 Mar 2010 19:04:03 -0600 |
parents | 7416c3f9c321 |
children | 1649bc7bda5a |
comparison
equal
deleted
inserted
replaced
345:7416c3f9c321 | 346:a82c55070624 |
---|---|
23 | 23 |
24 #include <config.h> | 24 #include <config.h> |
25 | 25 |
26 #include <stdio.h> | 26 #include <stdio.h> |
27 #include <stdarg.h> | 27 #include <stdarg.h> |
28 #include <string.h> | |
28 | 29 |
29 #include <lw_expr.h> | 30 #include <lw_expr.h> |
30 #include <lw_alloc.h> | 31 #include <lw_alloc.h> |
31 #include <lw_string.h> | 32 #include <lw_string.h> |
32 | 33 |
33 #include "lwasm.h" | 34 #include "lwasm.h" |
34 | 35 |
35 lw_expr_t lwasm_evaluate_var(char *var) | 36 lw_expr_t lwasm_evaluate_var(char *var, void *priv) |
36 { | 37 { |
37 return NULL; | 38 return NULL; |
38 } | 39 } |
39 | 40 |
40 lw_expr_t lwasm_evaluate_special(int t, void *ptr) | 41 lw_expr_t lwasm_evaluate_special(int t, void *ptr, void *priv) |
41 { | 42 { |
42 switch (t) | 43 switch (t) |
43 { | 44 { |
44 case lwasm_expr_linelen: | 45 case lwasm_expr_linelen: |
45 { | 46 { |
47 if (cl -> len == -1) | 48 if (cl -> len == -1) |
48 return NULL; | 49 return NULL; |
49 return lw_expr_build(lw_expr_type_int, cl -> len); | 50 return lw_expr_build(lw_expr_type_int, cl -> len); |
50 } | 51 } |
51 break; | 52 break; |
53 | |
54 case lwasm_expr_lineaddr: | |
55 { | |
56 line_t *cl = ptr; | |
57 if (cl -> addr) | |
58 return lw_expr_copy(cl -> addr); | |
59 else | |
60 return NULL; | |
61 } | |
52 } | 62 } |
53 return NULL; | 63 return NULL; |
54 } | 64 } |
55 | 65 |
56 void lwasm_register_error(asmstate_t *as, line_t *l, const char *msg, ...) | 66 void lwasm_register_error(asmstate_t *as, line_t *l, const char *msg, ...) |
83 int r; | 93 int r; |
84 r = as -> nextcontext; | 94 r = as -> nextcontext; |
85 as -> nextcontext++; | 95 as -> nextcontext++; |
86 return r; | 96 return r; |
87 } | 97 } |
98 | |
99 void lwasm_emit(line_t *cl, int byte) | |
100 { | |
101 if (cl -> outputl == cl -> outputbl) | |
102 { | |
103 cl -> output = lw_realloc(cl -> output, cl -> outputbl + 8); | |
104 cl -> outputbl += 8; | |
105 } | |
106 cl -> output[cl -> outputl++] = byte & 0xff; | |
107 } | |
108 | |
109 void lwasm_emitop(line_t *cl, int opc) | |
110 { | |
111 if (opc > 0x100) | |
112 lwasm_emit(cl, opc >> 8); | |
113 lwasm_emit(cl, opc); | |
114 } | |
115 | |
116 lw_expr_t lwasm_parse_term(char **p, void *priv) | |
117 { | |
118 asmstate_t *as = priv; | |
119 int val; | |
120 | |
121 if (!**p) | |
122 return NULL; | |
123 | |
124 if (**p == '*' || ( | |
125 **p == '.' | |
126 && !((*p)[1] >= 'A' && (*p)[1] <= 'Z') | |
127 && !((*p)[1] >= 'a' && (*p)[1] <= 'z') | |
128 && !((*p)[1] >= '0' && (*p)[1] <= '9') | |
129 )) | |
130 { | |
131 // special "symbol" for current line addr (*, .) | |
132 (*p)++; | |
133 return lw_expr_build(lw_expr_type_special, lwasm_expr_lineaddr, as -> cl); | |
134 } | |
135 | |
136 // branch points | |
137 if (**p == '<') | |
138 { | |
139 (*p)++; | |
140 return lw_expr_build(lw_expr_type_special, lwasm_expr_prevbp, as -> cl); | |
141 } | |
142 if (**p == '>') | |
143 { | |
144 (*p)++; | |
145 return lw_expr_build(lw_expr_type_special, lwasm_expr_nextbp, as -> cl); | |
146 } | |
147 | |
148 // double ascii constant | |
149 if (**p == '"') | |
150 { | |
151 int v; | |
152 (*p)++; | |
153 if (!**p) | |
154 return NULL; | |
155 if (!*((*p)+1)) | |
156 return NULL; | |
157 v = (unsigned char)**p << 8 | (unsigned char)*((*p)+1); | |
158 (*p) += 2; | |
159 return lw_expr_build(lw_expr_type_int, v); | |
160 } | |
161 | |
162 if (**p == '\'') | |
163 { | |
164 int v; | |
165 | |
166 (*p)++; | |
167 if (!**p) | |
168 return NULL; | |
169 | |
170 v = (unsigned char)**p; | |
171 (*p)++; | |
172 return lw_expr_build(lw_expr_type_int, v); | |
173 } | |
174 | |
175 if (**p == '&') | |
176 { | |
177 // decimal constant | |
178 int v = 0; | |
179 (*p)++; | |
180 | |
181 if (!strchr("0123456789", **p)) | |
182 return NULL; | |
183 | |
184 while (**p && strchr("0123456789", **p)) | |
185 { | |
186 val = val * 10 + (**p - '0'); | |
187 (*p)++; | |
188 } | |
189 return lw_expr_build(lw_expr_type_int, v); | |
190 } | |
191 | |
192 if (**p == '%') | |
193 { | |
194 // binary constant | |
195 int v = 0; | |
196 (*p)++; | |
197 | |
198 if (**p != '0' && **p != '1') | |
199 return NULL; | |
200 | |
201 while (**p && (**p == '0' || **p == '1')) | |
202 { | |
203 val = val * 2 + (**p - '0'); | |
204 (*p)++; | |
205 } | |
206 return lw_expr_build(lw_expr_type_int, v); | |
207 } | |
208 | |
209 if (**p == '$') | |
210 { | |
211 // hexadecimal constant | |
212 int v = 0, v2; | |
213 (*p)++; | |
214 | |
215 if (!strchr("0123456789abcdefABCDEF", **p)) | |
216 return NULL; | |
217 | |
218 while (**p && strchr("0123456789abcdefABCDEF", **p)) | |
219 { | |
220 v2 = toupper(**p) - '0'; | |
221 if (v2 > 9) | |
222 v2 -= 7; | |
223 val = val * 16 + v2; | |
224 (*p)++; | |
225 } | |
226 return lw_expr_build(lw_expr_type_int, v); | |
227 } | |
228 | |
229 if (**p == '0' && (*((*p)+1) == 'x' || *((*p)+1) == 'X')) | |
230 { | |
231 // hexadecimal constant, C style | |
232 int v = 0, v2; | |
233 (*p)+=2; | |
234 | |
235 if (!strchr("0123456789abcdefABCDEF", **p)) | |
236 return NULL; | |
237 | |
238 while (**p && strchr("0123456789abcdefABCDEF", **p)) | |
239 { | |
240 v2 = toupper(**p) - '0'; | |
241 if (v2 > 9) | |
242 v2 -= 7; | |
243 val = val * 16 + v2; | |
244 (*p)++; | |
245 } | |
246 return lw_expr_build(lw_expr_type_int, v); | |
247 } | |
248 | |
249 if (**p == '@' && (*((*p)+1) >= '0' && *((*p)+1) <= '7')) | |
250 { | |
251 // octal constant | |
252 int v = 0; | |
253 (*p)++; | |
254 | |
255 if (!strchr("01234567", **p)) | |
256 return NULL; | |
257 | |
258 while (**p && strchr("01234567", **p)) | |
259 { | |
260 val = val * 8 + (**p - '0'); | |
261 (*p)++; | |
262 } | |
263 return lw_expr_build(lw_expr_type_int, v); | |
264 } | |
265 | |
266 | |
267 // symbol or bare decimal or suffix constant here | |
268 do | |
269 { | |
270 int havedol = 0; | |
271 int l = 0; | |
272 | |
273 while ((*p)[l] && strchr(SYMCHARS, (*p)[l])) | |
274 { | |
275 if ((*p)[l] == '$') | |
276 havedol = 1; | |
277 l++; | |
278 } | |
279 if (l == 0) | |
280 return NULL; | |
281 | |
282 if (havedol || **p < '0' || **p > '9') | |
283 { | |
284 // have a symbol here | |
285 char *sym; | |
286 lw_expr_t term; | |
287 | |
288 sym = lw_strndup(*p, l); | |
289 (*p) += l; | |
290 term = lw_expr_build(lw_expr_type_var, sym); | |
291 lw_free(sym); | |
292 return term; | |
293 } | |
294 } while (0); | |
295 | |
296 if (!**p) | |
297 return NULL; | |
298 | |
299 // we have a numeric constant here, either decimal or postfix base notation | |
300 { | |
301 int decval = 0, binval = 0, hexval = 0, octval = 0; | |
302 int valtype = 15; // 1 = bin, 2 = oct, 4 = dec, 8 = hex | |
303 int bindone = 0; | |
304 int val; | |
305 int dval; | |
306 | |
307 while (1) | |
308 { | |
309 if (!**p || !strchr("0123456789ABCDEFabcdefqhoQHO", **p)) | |
310 { | |
311 // we can legally be bin or decimal here | |
312 if (bindone) | |
313 { | |
314 // just finished a binary value | |
315 val = binval; | |
316 break; | |
317 } | |
318 else if (valtype & 4) | |
319 { | |
320 val = decval; | |
321 break; | |
322 } | |
323 else | |
324 { | |
325 // bad value | |
326 return NULL; | |
327 } | |
328 } | |
329 | |
330 dval = toupper(**p); | |
331 (*p)++; | |
332 | |
333 if (bindone) | |
334 { | |
335 // any characters past "B" means it is not binary | |
336 bindone = 0; | |
337 valtype &= 14; | |
338 } | |
339 | |
340 switch (dval) | |
341 { | |
342 case 'Q': | |
343 case 'O': | |
344 if (valtype & 2) | |
345 { | |
346 val = octval; | |
347 valtype = -1; | |
348 break; | |
349 } | |
350 else | |
351 { | |
352 return NULL; | |
353 } | |
354 /* can't get here */ | |
355 | |
356 case 'H': | |
357 if (valtype & 8) | |
358 { | |
359 val = hexval; | |
360 valtype = -1; | |
361 break; | |
362 } | |
363 else | |
364 { | |
365 return NULL; | |
366 } | |
367 /* can't get here */ | |
368 | |
369 case 'B': | |
370 // this is a bit of a sticky one since B may be a | |
371 // hex number instead of the end of a binary number | |
372 // so it falls through to the digit case | |
373 if (valtype & 1) | |
374 { | |
375 // could still be binary of hex | |
376 bindone = 1; | |
377 valtype = 9; | |
378 } | |
379 /* fall through intented */ | |
380 | |
381 default: | |
382 // digit | |
383 dval -= '0'; | |
384 if (dval > 9) | |
385 dval -= 7; | |
386 if (valtype & 8) | |
387 hexval = hexval * 16 + dval; | |
388 if (valtype & 4) | |
389 { | |
390 if (dval > 9) | |
391 valtype &= 11; | |
392 else | |
393 decval = decval * 10 + dval; | |
394 } | |
395 if (valtype & 2) | |
396 { | |
397 if (dval > 7) | |
398 valtype &= 13; | |
399 else | |
400 octval = octval * 8 + dval; | |
401 } | |
402 if (valtype & 1) | |
403 { | |
404 if (dval > 1) | |
405 valtype &= 14; | |
406 else | |
407 binval = binval * 2 + dval; | |
408 } | |
409 } | |
410 if (valtype == -1) | |
411 break; | |
412 | |
413 // return if no more valid types | |
414 if (valtype == 0) | |
415 return NULL; | |
416 | |
417 val = decval; // in case we fall through | |
418 } | |
419 | |
420 // get here if we have a value | |
421 return lw_expr_build(lw_expr_type_int, val); | |
422 } | |
423 // can't get here | |
424 } | |
425 | |
426 lw_expr_t lwasm_parse_expr(asmstate_t *as, char **p) | |
427 { | |
428 lw_expr_t e; | |
429 | |
430 e = lw_expr_parse(p, as); | |
431 | |
432 return e; | |
433 } |