comparison old-trunk/lwasm/old/expr.c @ 339:eb230fa7d28e

Prepare for migration to hg
author lost
date Fri, 19 Mar 2010 02:54:14 +0000
parents
children
comparison
equal deleted inserted replaced
338:e7885b3ee266 339:eb230fa7d28e
1 /*
2 expr.c
3 Copyright © 2008 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 This file contains the actual expression evaluator
23 */
24
25 #define __expr_c_seen__
26
27 #include <config.h>
28
29 #include <ctype.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "expr.h"
34 #include "util.h"
35 #include "lwasm.h"
36
37 lwasm_expr_stack_t *lwasm_expr_stack_create(void)
38 {
39 lwasm_expr_stack_t *s;
40
41 s = lwasm_alloc(sizeof(lwasm_expr_stack_t));
42 s -> head = NULL;
43 s -> tail = NULL;
44 return s;
45 }
46
47 void lwasm_expr_stack_free(lwasm_expr_stack_t *s)
48 {
49 while (s -> head)
50 {
51 s -> tail = s -> head;
52 s -> head = s -> head -> next;
53 lwasm_expr_term_free(s -> tail -> term);
54 lwasm_free(s -> tail);
55 }
56 lwasm_free(s);
57 }
58
59 void lwasm_expr_term_free(lwasm_expr_term_t *t)
60 {
61 if (t)
62 {
63 if (t -> term_type == LWASM_TERM_SYM)
64 lwasm_free(t -> symbol);
65 lwasm_free(t);
66 }
67 }
68
69 lwasm_expr_term_t *lwasm_expr_term_create_oper(int oper)
70 {
71 lwasm_expr_term_t *t;
72
73 debug_message(10, "Creating operator term: %d", oper);
74
75 t = lwasm_alloc(sizeof(lwasm_expr_term_t));
76 t -> term_type = LWASM_TERM_OPER;
77 t -> value = oper;
78 return t;
79 }
80
81 lwasm_expr_term_t *lwasm_expr_term_create_int(int val)
82 {
83 lwasm_expr_term_t *t;
84 debug_message(10, "Creating integer term: %d", val);
85
86 t = lwasm_alloc(sizeof(lwasm_expr_term_t));
87 t -> term_type = LWASM_TERM_INT;
88 t -> value = val;
89 return t;
90 }
91
92 lwasm_expr_term_t *lwasm_expr_term_create_secbase(void)
93 {
94 lwasm_expr_term_t *t;
95 debug_message(10, "Creating section base term");
96
97 t = lwasm_alloc(sizeof(lwasm_expr_term_t));
98 t -> term_type = LWASM_TERM_SECBASE;
99 return t;
100 }
101
102 lwasm_expr_term_t *lwasm_expr_term_create_sym(char *sym)
103 {
104 lwasm_expr_term_t *t;
105
106 debug_message(10, "Creating symbol term: %s", sym);
107
108 t = lwasm_alloc(sizeof(lwasm_expr_term_t));
109 t -> term_type = LWASM_TERM_SYM;
110 t -> symbol = lwasm_strdup(sym);
111 return t;
112 }
113
114 lwasm_expr_term_t *lwasm_expr_term_dup(lwasm_expr_term_t *t)
115 {
116 switch (t -> term_type)
117 {
118 case LWASM_TERM_INT:
119 return lwasm_expr_term_create_int(t -> value);
120
121 case LWASM_TERM_OPER:
122 return lwasm_expr_term_create_oper(t -> value);
123
124 case LWASM_TERM_SYM:
125 return lwasm_expr_term_create_sym(t -> symbol);
126
127 case LWASM_TERM_SECBASE:
128 return lwasm_expr_term_create_secbase();
129
130 default:
131 debug_message(0, "lwasm_expr_term_dup(): invalid term type %d", t -> term_type);
132 exit(1);
133 }
134 // can't get here
135 }
136
137 void lwasm_expr_stack_push(lwasm_expr_stack_t *s, lwasm_expr_term_t *t)
138 {
139 lwasm_expr_stack_node_t *n;
140
141 if (!s)
142 {
143 debug_message(0, "lwasm_expr_stack_push(): invalid stack pointer");
144 exit(1);
145 }
146
147 n = lwasm_alloc(sizeof(lwasm_expr_stack_node_t));
148 n -> next = NULL;
149 n -> prev = s -> tail;
150 n -> term = lwasm_expr_term_dup(t);
151
152 if (s -> head)
153 {
154 s -> tail -> next = n;
155 s -> tail = n;
156 }
157 else
158 {
159 s -> head = n;
160 s -> tail = n;
161 }
162 }
163
164 lwasm_expr_term_t *lwasm_expr_stack_pop(lwasm_expr_stack_t *s)
165 {
166 lwasm_expr_term_t *t;
167 lwasm_expr_stack_node_t *n;
168
169 if (!(s -> tail))
170 return NULL;
171
172 n = s -> tail;
173 s -> tail = n -> prev;
174 if (!(n -> prev))
175 {
176 s -> head = NULL;
177 }
178
179 t = n -> term;
180 n -> term = NULL;
181
182 lwasm_free(n);
183
184 return t;
185 }
186
187 // the following two functions are co-routines which actually parse
188 // an infix expression onto the expression stack, each returns -1
189 // if an error is encountered
190
191 /*
192 parse a term and push it onto the stack
193
194 this function handles unary prefix operators (-, +, .not., .com.)
195 as well as ()
196 */
197 int lwasm_expr_parse_term(lwasm_expr_stack_t *s, const char **p)
198 {
199 lwasm_expr_term_t *t;
200 debug_message(2, "Expression string %s", *p);
201
202 eval_next:
203 if (!**p || isspace(**p) || **p == ')' || **p == ']')
204 return -1;
205 if (**p == '(')
206 {
207 debug_message(3, "Starting paren");
208 (*p)++;
209 lwasm_expr_parse_expr(s, p, 0);
210 if (**p != ')')
211 return -1;
212 (*p)++;
213 return 0;
214 }
215
216 if (**p == '+')
217 {
218 debug_message(3, "Unary +");
219 (*p)++;
220 goto eval_next;
221 }
222
223 if (**p == '-')
224 {
225 // parse expression following "-"
226 (*p)++;
227 if (lwasm_expr_parse_expr(s, p, 200) < 0)
228 return -1;
229 t = lwasm_expr_term_create_oper(LWASM_OPER_NEG);
230 lwasm_expr_stack_push(s, t);
231 lwasm_expr_term_free(t);
232 return 0;
233 }
234
235 if (**p == '^' || **p == '~')
236 {
237 // parse expression following "^"
238 (*p)++;
239 if (lwasm_expr_parse_expr(s, p, 200) < 0)
240 return -1;
241 t = lwasm_expr_term_create_oper(LWASM_OPER_COM);
242 lwasm_expr_stack_push(s, t);
243 lwasm_expr_term_free(t);
244 return 0;
245 }
246
247 /*
248 we have an actual term here so evaluate it
249
250 it could be one of the following:
251
252 1. a decimal constant
253 2. a hexadecimal constant
254 3. an octal constant
255 4. a binary constant
256 5. a symbol reference
257 6. the "current" instruction address (*)
258 7. the "current" data address (.)
259 8. a "back reference" (<)
260 9. a "forward reference" (>)
261
262 items 6 through 9 are stored as symbol references
263
264 (a . followed by a . or a alpha char or number is a symbol)
265 */
266 if (**p == '*'
267 || (
268 **p == '.'
269 && (*p)[1] != '.'
270 && !((*p)[1] >= 'A' && (*p)[1] <= 'Z')
271 && !((*p)[1] >= 'a' && (*p)[1] <= 'z')
272 && !((*p)[1] >= '0' && (*p)[1] <= '9')
273 )
274 || **p == '<'
275 || **p == '>')
276 {
277 char tstr[2];
278 tstr[0] = **p;
279 tstr[1] = '\0';
280 t = lwasm_expr_term_create_sym(tstr);
281 lwasm_expr_stack_push(s, t);
282 lwasm_expr_term_free(t);
283 (*p)++;
284 return 0;
285 }
286
287 /*
288 - a symbol will be a string of characters introduced by a letter, ".",
289 "_" but NOT a number OR it may start with a digit if it contains a $
290 - a decimal constant will consist of only digits, optionally prefixed
291 with "&"
292 - a binary constant will consist of only 0s and 1s either prefixed with %
293 or suffixed with "B"
294 - a hex constant will consist of 0-9A-F either prefixed with $ or
295 suffixed with "H"; a hex number starting with A-F must be prefixed
296 with $ or start with 0 and end with H
297 - an octal constant will consist of 0-7 either prefixed with @ or
298 suffixed with "O" or "Q"
299 - an ascii constant will be a single character prefixed with a '
300 - a double ascii constant will be two characters prefixed with a "
301
302 */
303 if (**p == '"')
304 {
305 // double ascii constant
306 int val;
307 (*p)++;
308 if (!**p)
309 return -1;
310 if (!*((*p)+1))
311 return -1;
312 val = **p << 8 | *((*p) + 1);
313 (*p) += 2;
314 t = lwasm_expr_term_create_int(val);
315 lwasm_expr_stack_push(s, t);
316 lwasm_expr_term_free(t);
317 return 0;
318 }
319 else if (**p == '\'')
320 {
321 // single ascii constant
322 int val;
323 (*p)++;
324 debug_message(3, "Single ascii character constant '%c'", **p);
325 if (!**p)
326 return -1;
327 val = **p;
328 (*p)++;
329 t = lwasm_expr_term_create_int(val);
330 lwasm_expr_stack_push(s, t);
331 lwasm_expr_term_free(t);
332 return 0;
333 }
334 else if (**p == '&')
335 {
336 // decimal constant
337 int val = 0;
338
339 (*p)++;
340 while (**p && strchr("0123456789", **p))
341 {
342 val = val * 10 + (**p - '0');
343 (*p)++;
344 }
345 t = lwasm_expr_term_create_int(val);
346 lwasm_expr_stack_push(s, t);
347 lwasm_expr_term_free(t);
348 return 0;
349 }
350 else if (**p == '%')
351 {
352 // binary constant
353 int val = 0;
354
355 (*p)++;
356 while (**p == '0' || **p == '1')
357 {
358 val = val * 2 + (**p - '0');
359 (*p)++;
360 }
361 t = lwasm_expr_term_create_int(val);
362 lwasm_expr_stack_push(s, t);
363 lwasm_expr_term_free(t);
364 return 0;
365 }
366 else if (**p == '$')
367 {
368 // hexadecimal constant
369 int val = 0, val2;
370
371 (*p)++;
372 debug_message(3, "Found prefix hex constant: %s", *p);
373 while (**p && strchr("0123456789ABCDEFabcdef", **p))
374 {
375 val2 = toupper(**p) - '0';
376 if (val2 > 9)
377 val2 -= 7;
378 debug_message(3, "Got char: %c (%d)", **p, val2);
379 val = val * 16 + val2;
380 (*p)++;
381 }
382 t = lwasm_expr_term_create_int(val);
383 lwasm_expr_stack_push(s, t);
384 lwasm_expr_term_free(t);
385 return 0;
386 }
387 else if (**p == '0' && tolower(*(*p + 1)) == 'x')
388 {
389 // "C" style hexadecimal constant
390 int val = 0, val2;
391
392 (*p)+=2;
393 debug_message(3, "Found \"C\" style prefix hex constant: %s", *p);
394 while (**p && strchr("0123456789ABCDEFabcdef", **p))
395 {
396 val2 = toupper(**p) - '0';
397 if (val2 > 9)
398 val2 -= 7;
399 debug_message(3, "Got char: %c (%d)", **p, val2);
400 val = val * 16 + val2;
401 (*p)++;
402 }
403 t = lwasm_expr_term_create_int(val);
404 lwasm_expr_stack_push(s, t);
405 lwasm_expr_term_free(t);
406 return 0;
407 }
408 // an @ followed by a digit is an octal number
409 // but if it's followed by anything else, it is a symbol
410 else if (**p == '@' && isdigit(*(*p + 1)))
411 {
412 // octal constant
413 int val = 0;
414
415 (*p)++;
416 while (**p && strchr("01234567", **p))
417 {
418 val = val * 8 + (**p - '0');
419 (*p)++;
420 }
421 t = lwasm_expr_term_create_int(val);
422 lwasm_expr_stack_push(s, t);
423 lwasm_expr_term_free(t);
424 return 0;
425 }
426
427 // symbol or bare decimal or suffix identified constant here
428
429 // find the end of a potential symbol
430 do
431 {
432 int l = 0;
433 char *sb;
434 int havedol = 0;
435
436 // evaluate a symbol here
437 static const char *symchars = "_.$@?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
438 while ((*p)[l] && strchr(symchars, (*p)[l]))
439 {
440 if ((*p)[l] == '$')
441 havedol = 1;
442 l++;
443 }
444 if (l == 0)
445 return -1;
446
447 if (havedol || **p < '0' || **p > '9')
448 {
449 // have a symbol here
450
451 sb = lwasm_alloc(l + 1);
452 sb[l] = '\0';
453 memcpy(sb, *p, l);
454 t = lwasm_expr_term_create_sym(sb);
455 lwasm_expr_stack_push(s, t);
456 lwasm_expr_term_free(t);
457 (*p) += l;
458 debug_message(3, "Symbol: '%s'; (%s)", sb, *p);
459 lwasm_free(sb);
460 return 0;
461 }
462 } while (0);
463
464 if (!**p)
465 return -1;
466
467 // evaluate a suffix based constant
468 {
469 int decval = 0, binval = 0, hexval = 0, octval = 0;
470 int valtype = 15; // 1 = bin, 2 = oct, 4 = dec, 8 = hex
471 int bindone = 0;
472 int val;
473 int dval;
474
475 while (1)
476 {
477 if (!**p || !strchr("0123456789ABCDEFabcdefqhoQHO", **p))
478 {
479 // we can legally have bin or decimal here
480 if (bindone)
481 {
482 // we just finished a binary value
483 val = binval;
484 break;
485 }
486 else if (valtype & 4)
487 {
488 // otherwise we must be decimal (if we're still allowed one)
489 val = decval;
490 debug_message(3, "End of decimal value");
491 break;
492 }
493 else
494 {
495 // bad value
496 return -1;
497 }
498 }
499
500 dval = toupper(**p);
501 (*p)++;
502
503 if (bindone)
504 {
505 // any characters past "B" means it is not binary
506 bindone = 0;
507 valtype &= 14;
508 }
509
510 switch (dval)
511 {
512 case 'Q':
513 case 'O':
514 if (valtype & 2)
515 {
516 val = octval;
517 valtype = -1;
518 break;
519 }
520 else
521 {
522 // not a valid octal value
523 return -1;
524 }
525 /* can't get here */
526
527 case 'H':
528 if (valtype & 8)
529 {
530 val = hexval;
531 valtype = -1;
532 break;
533 }
534 else
535 {
536 // not a valid hex number
537 return -1;
538 }
539 /* can't get here */
540
541 case 'B':
542 // this is a bit of a sticky one since B is a legit hex
543 // digit so this may or may not be the end of the number
544 // so we fall through to the digit case
545
546 if (valtype & 1)
547 {
548 // could still be binary
549 bindone = 1;
550 valtype = 9; // hex and binary
551 }
552 /* fall through intentional */
553
554 default:
555 // digit
556 dval -= '0';
557 if (dval > 9)
558 dval -= 7;
559 debug_message(3, "Got digit: %d", dval);
560 // if (dval > 1)
561 // valtype &= 14;
562 // if (dval > 7)
563 // valtype &= 12;
564 // if (dval > 9)
565 // valtype &= 8;
566
567 if (valtype & 8)
568 {
569 hexval = hexval * 16 + dval;
570 }
571 if (valtype & 4)
572 {
573 if (dval > 9)
574 valtype &= 11;
575 else
576 decval = decval * 10 + dval;
577 }
578 if (valtype & 2)
579 {
580 if (dval > 7)
581 valtype &= 13;
582 else
583 octval = octval * 8 + dval;
584 }
585 if (valtype & 1)
586 {
587 if (dval > 1)
588 valtype &= 14;
589 else
590 binval = binval * 2 + dval;
591 }
592 }
593 // break out if we have a return value
594 if (valtype == -1)
595 break;
596 // return if no more valid possibilities!
597 if (valtype == 0)
598 return -1;
599 val = decval; // in case we fall through
600 }
601
602 // we get here when we have a value to return
603 t = lwasm_expr_term_create_int(val);
604 lwasm_expr_stack_push(s, t);
605 lwasm_expr_term_free(t);
606 return 0;
607 }
608 /* can't get here */
609 }
610
611 // parse an expression and push the result onto the stack
612 // if an operator of lower precedence than the value of "prec" is found,
613 int lwasm_expr_parse_expr(lwasm_expr_stack_t *s, const char **p, int prec)
614 {
615 static const struct operinfo
616 {
617 int opernum;
618 char *operstr;
619 int operprec;
620 } operators[] =
621 {
622 { LWASM_OPER_PLUS, "+", 100 },
623 { LWASM_OPER_MINUS, "-", 100 },
624 { LWASM_OPER_TIMES, "*", 150 },
625 { LWASM_OPER_DIVIDE, "/", 150 },
626 { LWASM_OPER_MOD, "%", 150 },
627 { LWASM_OPER_INTDIV, "\\", 150 },
628
629 // boolean AND/OR
630 { LWASM_OPER_AND, "&&", 25 },
631 { LWASM_OPER_OR, "||", 25 },
632
633 // bitwise ops
634 { LWASM_OPER_BWAND, "&", 50 },
635 { LWASM_OPER_BWOR, "|", 50 },
636
637 // this collides with the unary complement but shouldn't cause
638 // any trouble because of operator precedence
639 { LWASM_OPER_BWXOR, "^", 50 },
640
641 { LWASM_OPER_NONE, "", 0 }
642 };
643 int opern, i;
644 lwasm_expr_term_t *operterm;
645
646 // return if we are at the end of the expression or a subexpression
647 if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']')
648 return 0;
649
650 if (lwasm_expr_parse_term(s, p) < 0)
651 return -1;
652
653 eval_next:
654 if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']')
655 return 0;
656
657 // expecting an operator here
658 for (opern = 0; operators[opern].opernum != LWASM_OPER_NONE; opern++)
659 {
660 for (i = 0; (*p)[i] && operators[opern].operstr[i] && ((*p)[i] == operators[opern].operstr[i]); i++)
661 /* do nothing */ ;
662 if (operators[opern].operstr[i] == '\0')
663 break;
664 }
665 if (operators[opern].opernum == LWASM_OPER_NONE)
666 {
667 // unrecognized operator
668 return -1;
669 }
670
671 // the operator number in question is in opern; i is the length of the
672 // operator string
673
674 // logic:
675 // if the precedence of this operation is <= to the "prec" flag,
676 // we simply return without advancing the input pointer; the operator
677 // will be evaluated again in the enclosing function call
678 if (operators[opern].operprec <= prec)
679 return 0;
680
681 // logic:
682 // we have a higher precedence operator here so we will advance the
683 // input pointer to the next term and let the expression evaluator
684 // loose on it after which time we will push our operator onto the
685 // stack and then go on with the expression evaluation
686 (*p) += i; // advance input pointer
687
688 // evaluate next expression(s) of higher precedence
689 if (lwasm_expr_parse_expr(s, p, operators[opern].operprec) < 0)
690 return -1;
691
692 operterm = lwasm_expr_term_create_oper(operators[opern].opernum);
693 lwasm_expr_stack_push(s, operterm);
694 lwasm_expr_term_free(operterm);
695
696 // return if we are at the end of the expression or a subexpression
697 if (!**p || isspace(**p) || **p == ')')
698 return 0;
699
700 // continue evaluating
701 goto eval_next;
702 }
703
704 /*
705 actually evaluate an expression
706
707 This happens in two stages. The first stage merely parses the expression into
708 a lwasm_expr_stack_t * which is then evaluated as much as possible before the
709 result is returned.
710
711 Returns NULL on a parse error or otherwise invalid expression. *outp will
712 contain the pointer to the next character after the expression if and only
713 if there is no error. In the case of an error, *outp is undefined.
714 */
715 lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp, lwasm_expr_stack_t *(*sfunc)(char *sym, void *state), void *state)
716 {
717 lwasm_expr_stack_t *s;
718 const char *p;
719 int rval;
720
721 // actually parse the expression
722 p = inp;
723 s = lwasm_expr_stack_create();
724
725 rval = lwasm_expr_parse_expr(s, &p, 0);
726 if (rval < 0)
727 goto cleanup_error;
728
729 // save end of expression
730 if (outp)
731 (*outp) = p;
732
733 // return potentially partial expression
734 if (lwasm_expr_reval(s, sfunc, state) < 0)
735 goto cleanup_error;
736
737 if (lwasm_expr_is_constant(s))
738 debug_message(3, "Constant expression evaluates to: %d", lwasm_expr_get_value(s));
739
740 return s;
741
742 cleanup_error:
743 lwasm_expr_stack_free(s);
744 return NULL;
745 }
746
747 /*
748 take an expression stack s and scan for operations that can be completed
749
750 return -1 on error, 0 on no error
751
752 possible errors are: division by zero or unknown operator
753
754 theory of operation:
755
756 scan the stack for an operator which has two constants preceding it (binary)
757 or 1 constant preceding it (unary) and if found, perform the calculation
758 and replace the operator and its operands with the result
759
760 repeat the scan until no futher simplications are found or if there are no
761 further operators or only a single term remains
762
763 */
764 int lwasm_expr_reval(lwasm_expr_stack_t *s, lwasm_expr_stack_t *(*sfunc)(char *sym, void *state), void *state)
765 {
766 lwasm_expr_stack_node_t *n, *n2;
767 lwasm_expr_stack_t *ss;
768 int c;
769
770 next_iter_sym:
771 // resolve symbols
772 // symbols that do not resolve to an expression are left alone
773 for (c = 0, n = s -> head; n; n = n -> next)
774 {
775 if (n -> term -> term_type == LWASM_TERM_SYM)
776 {
777 ss = sfunc(n -> term -> symbol, state);
778 if (ss)
779 {
780 c++;
781 // splice in the result stack
782 if (n -> prev)
783 {
784 n -> prev -> next = ss -> head;
785 }
786 else
787 {
788 s -> head = ss -> head;
789 }
790 ss -> head -> prev = n -> prev;
791 ss -> tail -> next = n -> next;
792 if (n -> next)
793 {
794 n -> next -> prev = ss -> tail;
795 }
796 else
797 {
798 s -> tail = ss -> tail;
799 }
800 lwasm_expr_term_free(n -> term);
801 lwasm_free(n);
802 n = ss -> tail;
803
804 ss -> head = NULL;
805 ss -> tail = NULL;
806 lwasm_expr_stack_free(ss);
807 }
808 }
809 }
810 if (c)
811 goto next_iter_sym;
812
813 next_iter:
814 // a single term
815 if (s -> head == s -> tail)
816 return 0;
817
818 // search for an operator
819 for (n = s -> head; n; n = n -> next)
820 {
821 if (n -> term -> term_type == LWASM_TERM_OPER)
822 {
823 if (n -> term -> value == LWASM_OPER_NEG
824 || n -> term -> value == LWASM_OPER_COM
825 )
826 {
827 // unary operator
828 if (n -> prev && n -> prev -> term -> term_type == LWASM_TERM_INT)
829 {
830 // a unary operator we can resolve
831 // we do the op then remove the term "n" is pointing at
832 if (n -> term -> value == LWASM_OPER_NEG)
833 {
834 n -> prev -> term -> value = -(n -> prev -> term -> value);
835 }
836 else if (n -> term -> value == LWASM_OPER_COM)
837 {
838 n -> prev -> term -> value = ~(n -> prev -> term -> value);
839 }
840 n -> prev -> next = n -> next;
841 if (n -> next)
842 n -> next -> prev = n -> prev;
843 else
844 s -> tail = n -> prev;
845
846 lwasm_expr_term_free(n -> term);
847 lwasm_free(n);
848 break;
849 }
850 }
851 else
852 {
853 // binary operator
854 if (n -> prev && n -> prev -> prev && n -> prev -> term -> term_type == LWASM_TERM_INT && n -> prev -> prev -> term -> term_type == LWASM_TERM_INT)
855 {
856 // a binary operator we can resolve
857 switch (n -> term -> value)
858 {
859 case LWASM_OPER_PLUS:
860 n -> prev -> prev -> term -> value += n -> prev -> term -> value;
861 break;
862
863 case LWASM_OPER_MINUS:
864 n -> prev -> prev -> term -> value -= n -> prev -> term -> value;
865 break;
866
867 case LWASM_OPER_TIMES:
868 n -> prev -> prev -> term -> value *= n -> prev -> term -> value;
869 break;
870
871 case LWASM_OPER_DIVIDE:
872 if (n -> prev -> term -> value == 0)
873 return -1;
874 n -> prev -> prev -> term -> value /= n -> prev -> term -> value;
875 break;
876
877 case LWASM_OPER_MOD:
878 if (n -> prev -> term -> value == 0)
879 return -1;
880 n -> prev -> prev -> term -> value %= n -> prev -> term -> value;
881 break;
882
883 case LWASM_OPER_INTDIV:
884 if (n -> prev -> term -> value == 0)
885 return -1;
886 n -> prev -> prev -> term -> value /= n -> prev -> term -> value;
887 break;
888
889 case LWASM_OPER_BWAND:
890 n -> prev -> prev -> term -> value &= n -> prev -> term -> value;
891 break;
892
893 case LWASM_OPER_BWOR:
894 n -> prev -> prev -> term -> value |= n -> prev -> term -> value;
895 break;
896
897 case LWASM_OPER_BWXOR:
898 n -> prev -> prev -> term -> value ^= n -> prev -> term -> value;
899 break;
900
901 case LWASM_OPER_AND:
902 n -> prev -> prev -> term -> value = (n -> prev -> term -> value && n -> prev -> prev -> term -> value) ? 1 : 0;
903 break;
904
905 case LWASM_OPER_OR:
906 n -> prev -> prev -> term -> value = (n -> prev -> term -> value || n -> prev -> prev -> term -> value) ? 1 : 0;
907 break;
908
909 default:
910 // return error if unknown operator!
911 return -1;
912 }
913
914 // now remove the two unneeded entries from the stack
915 n -> prev -> prev -> next = n -> next;
916 if (n -> next)
917 n -> next -> prev = n -> prev -> prev;
918 else
919 s -> tail = n -> prev -> prev;
920
921 lwasm_expr_term_free(n -> term);
922 lwasm_expr_term_free(n -> prev -> term);
923 lwasm_free(n -> prev);
924 lwasm_free(n);
925 break;
926 }
927 }
928 }
929 }
930 // note for the terminally confused about dynamic memory and pointers:
931 // n will not be NULL even after the lwasm_free calls above so
932 // this test will still work (n will be a dangling pointer)
933 // (n will only be NULL if we didn't find any operators to simplify)
934 if (n)
935 goto next_iter;
936
937 return 0;
938 }