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 }