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