comparison lwlib/lw_expr.c @ 0:2c24602be78f

Initial import from lwtools 3.0.1 version, with new hand built build system and file reorganization
author lost@l-w.ca
date Wed, 19 Jan 2011 22:27:17 -0700
parents
children 7317fbe024af
comparison
equal deleted inserted replaced
-1:000000000000 0:2c24602be78f
1 /*
2 lwexpr.c
3
4 Copyright © 2010 William Astle
5
6 This file is part of LWTOOLS.
7
8 LWTOOLS is free software: you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation, either version 3 of the License, or (at your option) any later
11 version.
12
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 more details.
17
18 You should have received a copy of the GNU General Public License along with
19 this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 #define ___lw_expr_c_seen___
27 #include "lw_alloc.h"
28 #include "lw_expr.h"
29 #include "lw_error.h"
30 #include "lw_string.h"
31
32 static lw_expr_fn_t *evaluate_special = NULL;
33 static lw_expr_fn2_t *evaluate_var = NULL;
34 static lw_expr_fn3_t *parse_term = NULL;
35
36 /* Q&D to break out of infinite recursion */
37 static int level = 0;
38 static int bailing = 0;
39
40 int lw_expr_istype(lw_expr_t e, int t)
41 {
42 if (e -> type == t)
43 return 1;
44 return 0;
45 }
46
47 int lw_expr_intval(lw_expr_t e)
48 {
49 if (e -> type == lw_expr_type_int)
50 return e -> value;
51 return -1;
52 }
53
54 int lw_expr_whichop(lw_expr_t e)
55 {
56 if (e -> type == lw_expr_type_oper)
57 return e -> value;
58 return -1;
59 }
60
61 int lw_expr_specint(lw_expr_t e)
62 {
63 if (e -> type == lw_expr_type_special)
64 return e -> value;
65 return -1;
66 }
67
68 void lw_expr_set_term_parser(lw_expr_fn3_t *fn)
69 {
70 parse_term = fn;
71 }
72
73 void lw_expr_set_special_handler(lw_expr_fn_t *fn)
74 {
75 evaluate_special = fn;
76 }
77
78 void lw_expr_set_var_handler(lw_expr_fn2_t *fn)
79 {
80 evaluate_var = fn;
81 }
82
83 lw_expr_t lw_expr_create(void)
84 {
85 lw_expr_t r;
86
87 r = lw_alloc(sizeof(struct lw_expr_priv));
88 r -> operands = NULL;
89
90 return r;
91 }
92
93 void lw_expr_destroy(lw_expr_t E)
94 {
95 struct lw_expr_opers *o;
96 if (!E)
97 return;
98 while (E -> operands)
99 {
100 o = E -> operands;
101 E -> operands = o -> next;
102 lw_expr_destroy(o -> p);
103 lw_free(o);
104 }
105 if (E -> type == lw_expr_type_var)
106 lw_free(E -> value2);
107 lw_free(E);
108 }
109
110 /* actually duplicates the entire expression */
111 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O);
112 lw_expr_t lw_expr_copy(lw_expr_t E)
113 {
114 lw_expr_t r, t;
115 struct lw_expr_opers *o;
116
117 r = lw_alloc(sizeof(struct lw_expr_priv));
118 *r = *E;
119 r -> operands = NULL;
120
121 if (E -> type == lw_expr_type_var)
122 r -> value2 = lw_strdup(E -> value2);
123 for (o = E -> operands; o; o = o -> next)
124 {
125 lw_expr_add_operand(r, o -> p);
126 }
127
128 return r;
129 }
130
131 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O)
132 {
133 struct lw_expr_opers *o, *t;
134
135 o = lw_alloc(sizeof(struct lw_expr_opers));
136 o -> p = lw_expr_copy(O);
137 o -> next = NULL;
138 for (t = E -> operands; t && t -> next; t = t -> next)
139 /* do nothing */ ;
140
141 if (t)
142 t -> next = o;
143 else
144 E -> operands = o;
145 }
146
147 lw_expr_t lw_expr_build_aux(int exprtype, va_list args)
148 {
149 lw_expr_t r;
150 int t;
151 void *p;
152
153 lw_expr_t te1, te2;
154
155 r = lw_expr_create();
156
157 switch (exprtype)
158 {
159 case lw_expr_type_int:
160 t = va_arg(args, int);
161 r -> type = lw_expr_type_int;
162 r -> value = t;
163 break;
164
165 case lw_expr_type_var:
166 p = va_arg(args, char *);
167 r -> type = lw_expr_type_var;
168 r -> value2 = lw_strdup(p);
169 break;
170
171 case lw_expr_type_special:
172 t = va_arg(args, int);
173 p = va_arg(args, char *);
174 r -> type = lw_expr_type_special;
175 r -> value = t;
176 r -> value2 = p;
177 break;
178
179 case lw_expr_type_oper:
180 t = va_arg(args, int);
181 te1 = va_arg(args, lw_expr_t);
182 if (t != lw_expr_oper_com && t != lw_expr_oper_neg)
183 te2 = va_arg(args, lw_expr_t);
184 else
185 te2 = NULL;
186
187 r -> type = lw_expr_type_oper;
188 r -> value = t;
189 lw_expr_add_operand(r, te1);
190 if (te2)
191 lw_expr_add_operand(r, te2);
192 break;
193
194 default:
195 lw_error("Invalid expression type specified to lw_expr_build");
196 }
197
198 return r;
199 }
200
201 lw_expr_t lw_expr_build(int exprtype, ...)
202 {
203 va_list args;
204 lw_expr_t r;
205
206 va_start(args, exprtype);
207 r = lw_expr_build_aux(exprtype, args);
208 va_end(args);
209 return r;
210 }
211
212 void lw_expr_print_aux(lw_expr_t E, char **obuf, int *buflen, int *bufloc)
213 {
214 struct lw_expr_opers *o;
215 int c = 0;
216 char buf[256];
217
218 if (!E)
219 {
220 strcpy(buf, "(NULL)");
221 return;
222 }
223 for (o = E -> operands; o; o = o -> next)
224 {
225 c++;
226 lw_expr_print_aux(o -> p, obuf, buflen, bufloc);
227 }
228
229 switch (E -> type)
230 {
231 case lw_expr_type_int:
232 if (E -> value < 0)
233 snprintf(buf, 256, "-%#x ", -(E -> value));
234 else
235 snprintf(buf, 256, "%#x ", E -> value);
236 break;
237
238 case lw_expr_type_var:
239 snprintf(buf, 256, "V(%s) ", (char *)(E -> value2));
240 break;
241
242 case lw_expr_type_special:
243 snprintf(buf, 256, "S(%d,%p) ", E -> value, E -> value2);
244 break;
245
246 case lw_expr_type_oper:
247 snprintf(buf, 256, "[%d]", c);
248 switch (E -> value)
249 {
250 case lw_expr_oper_plus:
251 strcat(buf, "+ ");
252 break;
253
254 case lw_expr_oper_minus:
255 strcat(buf, "- ");
256 break;
257
258 case lw_expr_oper_times:
259 strcat(buf, "* ");
260 break;
261
262 case lw_expr_oper_divide:
263 strcat(buf, "/ ");
264 break;
265
266 case lw_expr_oper_mod:
267 strcat(buf, "% ");
268 break;
269
270 case lw_expr_oper_intdiv:
271 strcat(buf, "\\ ");
272 break;
273
274 case lw_expr_oper_bwand:
275 strcat(buf, "BWAND ");
276 break;
277
278 case lw_expr_oper_bwor:
279 strcat(buf, "BWOR ");
280 break;
281
282 case lw_expr_oper_bwxor:
283 strcat(buf, "BWXOR ");
284 break;
285
286 case lw_expr_oper_and:
287 strcat(buf, "AND ");
288 break;
289
290 case lw_expr_oper_or:
291 strcat(buf, "OR ");
292 break;
293
294 case lw_expr_oper_neg:
295 strcat(buf, "NEG ");
296 break;
297
298 case lw_expr_oper_com:
299 strcat(buf, "COM ");
300 break;
301
302 default:
303 strcat(buf, "OPER ");
304 break;
305 }
306 break;
307 default:
308 snprintf(buf, 256, "ERR ");
309 break;
310 }
311
312 c = strlen(buf);
313 if (*bufloc + c >= *buflen)
314 {
315 *buflen += 128;
316 *obuf = lw_realloc(*obuf, *buflen);
317 }
318 strcpy(*obuf + *bufloc, buf);
319 *bufloc += c;
320 }
321
322 char *lw_expr_print(lw_expr_t E)
323 {
324 static char *obuf = NULL;
325 static int obufsize = 0;
326
327 int obufloc = 0;
328
329 lw_expr_print_aux(E, &obuf, &obufsize, &obufloc);
330
331 return obuf;
332 }
333
334 /*
335 Return:
336 nonzero if expressions are the same (identical pointers or matching values)
337 zero if expressions are not the same
338
339 */
340 int lw_expr_compare(lw_expr_t E1, lw_expr_t E2)
341 {
342 struct lw_expr_opers *o1, *o2;
343
344 if (E1 == E2)
345 return 1;
346
347 if (!E1 || !E2)
348 return 0;
349
350 if (!(E1 -> type == E2 -> type && E1 -> value == E2 -> value))
351 return 0;
352
353 if (E1 -> type == lw_expr_type_var)
354 {
355 if (!strcmp(E1 -> value2, E2 -> value2))
356 return 1;
357 else
358 return 0;
359 }
360
361 if (E1 -> type == lw_expr_type_special)
362 {
363 if (E1 -> value2 == E2 -> value2)
364 return 1;
365 else
366 return 0;
367 }
368
369 for (o1 = E1 -> operands, o2 = E2 -> operands; o1 && o2; o1 = o1 -> next, o2 = o2 -> next)
370 if (lw_expr_compare(o1 -> p, o2 -> p) == 0)
371 return 0;
372 if (o1 || o2)
373 return 0;
374
375 return 1;
376 }
377
378 /* return true if E is an operator of type oper */
379 int lw_expr_isoper(lw_expr_t E, int oper)
380 {
381 if (E -> type == lw_expr_type_oper && E -> value == oper)
382 return 1;
383 return 0;
384 }
385
386
387 void lw_expr_simplify_sortconstfirst(lw_expr_t E)
388 {
389 struct lw_expr_opers *o;
390
391 if (E -> type != lw_expr_type_oper)
392 return;
393 if (E -> value != lw_expr_oper_times && E -> value != lw_expr_oper_plus)
394 return;
395
396 for (o = E -> operands; o; o = o -> next)
397 {
398 if (o -> p -> type == lw_expr_type_oper && (o -> p -> value == lw_expr_oper_times || o -> p -> value == lw_expr_oper_plus))
399 lw_expr_simplify_sortconstfirst(o -> p);
400 }
401
402 for (o = E -> operands; o; o = o -> next)
403 {
404 if (o -> p -> type == lw_expr_type_int && o != E -> operands)
405 {
406 struct lw_expr_opers *o2;
407 for (o2 = E -> operands; o2 -> next != o; o2 = o2 -> next)
408 /* do nothing */ ;
409 o2 -> next = o -> next;
410 o -> next = E -> operands;
411 E -> operands = o;
412 o = o2;
413 }
414 }
415 }
416
417 void lw_expr_sortoperandlist(struct lw_expr_opers **o)
418 {
419 // fprintf(stderr, "lw_expr_sortoperandlist() not yet implemented\n");
420 }
421
422 // return 1 if the operand lists match, 0 if not
423 // may re-order the argument lists
424 int lw_expr_simplify_compareoperandlist(struct lw_expr_opers **ol1, struct lw_expr_opers **ol2)
425 {
426 struct lw_expr_opers *o1, *o2;
427
428 lw_expr_sortoperandlist(ol1);
429 lw_expr_sortoperandlist(ol2);
430
431 for (o1 = *ol1, o2 = *ol2; o1 && o2; o1 = o1 -> next, o2 = o2 -> next)
432 {
433 if (!lw_expr_compare(o1 -> p, o2 -> p))
434 return 0;
435 }
436 if (o1 || o2)
437 return 0;
438 return 1;
439 }
440
441 int lw_expr_simplify_isliketerm(lw_expr_t e1, lw_expr_t e2)
442 {
443 // first term is a "times"
444 if (e1 -> type == lw_expr_type_oper && e1 -> value == lw_expr_oper_times)
445 {
446 // second term is a "times"
447 if (e2 -> type == lw_expr_type_oper && e2 -> value == lw_expr_oper_times)
448 {
449 // both times - easy check
450 struct lw_expr_opers *o1, *o2;
451 for (o1 = e1 -> operands; o1; o1 = o1 -> next)
452 if (o1 -> p -> type != lw_expr_type_int)
453 break;
454
455 for (o2 = e2 -> operands; o2; o2 = o2 -> next)
456 if (o2 -> p -> type != lw_expr_type_int)
457 break;
458
459 if (lw_expr_simplify_compareoperandlist(&o1, &o2))
460 return 1;
461 return 0;
462 }
463
464 // not a times - have to assume it's the operand list
465 // with a "1 *" in front if it
466 if (!e1 -> operands -> next)
467 return 0;
468 if (e1 -> operands -> next -> next)
469 return 0;
470 if (!lw_expr_compare(e1 -> operands -> next -> p, e2))
471 return 0;
472 return 1;
473 }
474
475 // e1 is not a times
476 if (e2 -> type == lw_expr_type_oper && e2 -> value == lw_expr_oper_times)
477 {
478 // e2 is a times
479 if (e2 -> operands -> next -> next)
480 return 0;
481 if (!lw_expr_compare(e1, e2 -> operands -> next -> p))
482 return 0;
483 return 1;
484 }
485
486 // neither are times
487 if (!lw_expr_compare(e1, e2))
488 return 0;
489 return 1;
490 }
491
492 int lw_expr_contains(lw_expr_t E, lw_expr_t E1)
493 {
494 struct lw_expr_opers *o;
495
496 // NULL expr contains nothing :)
497 if (!E)
498 return 0;
499
500 if (E1 -> type != lw_expr_type_var && E1 -> type != lw_expr_type_special)
501 return 0;
502
503 if (lw_expr_compare(E, E1))
504 return 1;
505
506 for (o = E -> operands; o; o = o -> next)
507 {
508 if (lw_expr_contains(o -> p, E1))
509 return 1;
510 }
511 return 0;
512 }
513
514 void lw_expr_simplify_l(lw_expr_t E, void *priv);
515
516 void lw_expr_simplify_go(lw_expr_t E, void *priv)
517 {
518 struct lw_expr_opers *o;
519
520 // replace subtraction with O1 + -1(O2)...
521 // needed for like term collection
522 if (E -> type == lw_expr_type_oper && E -> value == lw_expr_oper_minus)
523 {
524 for (o = E -> operands -> next; o; o = o -> next)
525 {
526 lw_expr_t e1, e2;
527
528 e2 = lw_expr_build(lw_expr_type_int, -1);
529 e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, e2, o -> p);
530 lw_expr_destroy(o -> p);
531 lw_expr_destroy(e2);
532 o -> p = e1;
533 }
534 E -> value = lw_expr_oper_plus;
535 }
536
537 // turn "NEG" into -1(O) - needed for like term collection
538 if (E -> type == lw_expr_type_oper && E -> value == lw_expr_oper_neg)
539 {
540 lw_expr_t e1;
541
542 E -> value = lw_expr_oper_times;
543 e1 = lw_expr_build(lw_expr_type_int, -1);
544 lw_expr_add_operand(E, e1);
545 lw_expr_destroy(e1);
546 }
547
548 again:
549 // try to resolve non-constant terms to constants here
550 if (E -> type == lw_expr_type_special && evaluate_special)
551 {
552 lw_expr_t te;
553
554 te = evaluate_special(E -> value, E -> value2, priv);
555 if (lw_expr_contains(te, E))
556 lw_expr_destroy(te);
557 if (te)
558 {
559 for (o = E -> operands; o; o = o -> next)
560 lw_expr_destroy(o -> p);
561 if (E -> type == lw_expr_type_var)
562 lw_free(E -> value2);
563 *E = *te;
564 E -> operands = NULL;
565
566 if (te -> type == lw_expr_type_var)
567 E -> value2 = lw_strdup(te -> value2);
568 for (o = te -> operands; o; o = o -> next)
569 {
570 lw_expr_add_operand(E, lw_expr_copy(o -> p));
571 }
572 lw_expr_destroy(te);
573 goto again;
574 }
575 return;
576 }
577
578 if (E -> type == lw_expr_type_var && evaluate_var)
579 {
580 lw_expr_t te;
581
582 te = evaluate_var(E -> value2, priv);
583 if (lw_expr_contains(te, E))
584 lw_expr_destroy(te);
585 else if (te)
586 {
587 for (o = E -> operands; o; o = o -> next)
588 lw_expr_destroy(o -> p);
589 if (E -> type == lw_expr_type_var)
590 lw_free(E -> value2);
591 *E = *te;
592 E -> operands = NULL;
593
594 if (te -> type == lw_expr_type_var)
595 E -> value2 = lw_strdup(te -> value2);
596 for (o = te -> operands; o; o = o -> next)
597 {
598 lw_expr_add_operand(E, lw_expr_copy(o -> p));
599 }
600 lw_expr_destroy(te);
601 goto again;
602 }
603 return;
604 }
605
606 // non-operators have no simplification to do!
607 if (E -> type != lw_expr_type_oper)
608 return;
609
610 // merge plus operations
611 if (E -> value == lw_expr_oper_plus)
612 {
613 lw_expr_t e2;
614
615 tryagainplus:
616 for (o = E -> operands; o; o = o -> next)
617 {
618 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_plus)
619 {
620 struct lw_expr_opers *o2, *o3;
621 // we have a + operation - bring operands up
622
623 for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next)
624 /* do nothing */ ;
625 if (o2)
626 o2 -> next = o -> p -> operands;
627 else
628 E -> operands = o -> p -> operands;
629 for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next)
630 /* do nothing */ ;
631 o2 -> next = o -> next;
632 o -> p -> operands = NULL;
633 lw_expr_destroy(o -> p);
634 lw_free(o);
635 goto tryagainplus;
636 }
637 }
638 }
639
640 // merge times operations
641 if (E -> value == lw_expr_oper_times)
642 {
643 lw_expr_t e2;
644
645 tryagaintimes:
646 for (o = E -> operands; o; o = o -> next)
647 {
648 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times)
649 {
650 struct lw_expr_opers *o2, *o3;
651 // we have a + operation - bring operands up
652
653 for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next)
654 /* do nothing */ ;
655 if (o2)
656 o2 -> next = o -> p -> operands;
657 else
658 E -> operands = o -> p -> operands;
659 for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next)
660 /* do nothing */ ;
661 o2 -> next = o -> next;
662 o -> p -> operands = NULL;
663 lw_expr_destroy(o -> p);
664 lw_free(o);
665 goto tryagaintimes;
666 }
667 }
668 }
669
670 // simplify operands
671 for (o = E -> operands; o; o = o -> next)
672 lw_expr_simplify_l(o -> p, priv);
673
674 for (o = E -> operands; o; o = o -> next)
675 {
676 if (o -> p -> type != lw_expr_type_int)
677 break;
678 }
679
680 if (!o)
681 {
682 // we can do the operation here!
683 int tr = -42424242;
684
685 switch (E -> value)
686 {
687 case lw_expr_oper_neg:
688 tr = -(E -> operands -> p -> value);
689 break;
690
691 case lw_expr_oper_com:
692 tr = ~(E -> operands -> p -> value);
693 break;
694
695 case lw_expr_oper_plus:
696 tr = E -> operands -> p -> value;
697 for (o = E -> operands -> next; o; o = o -> next)
698 tr += o -> p -> value;
699 break;
700
701 case lw_expr_oper_minus:
702 tr = E -> operands -> p -> value;
703 for (o = E -> operands -> next; o; o = o -> next)
704 tr -= o -> p -> value;
705 break;
706
707 case lw_expr_oper_times:
708 tr = E -> operands -> p -> value;
709 for (o = E -> operands -> next; o; o = o -> next)
710 tr *= o -> p -> value;
711 break;
712
713 case lw_expr_oper_divide:
714 tr = E -> operands -> p -> value / E -> operands -> next -> p -> value;
715 break;
716
717 case lw_expr_oper_mod:
718 tr = E -> operands -> p -> value % E -> operands -> next -> p -> value;
719 break;
720
721 case lw_expr_oper_intdiv:
722 tr = E -> operands -> p -> value / E -> operands -> next -> p -> value;
723 break;
724
725 case lw_expr_oper_bwand:
726 tr = E -> operands -> p -> value & E -> operands -> next -> p -> value;
727 break;
728
729 case lw_expr_oper_bwor:
730 tr = E -> operands -> p -> value | E -> operands -> next -> p -> value;
731 break;
732
733 case lw_expr_oper_bwxor:
734 tr = E -> operands -> p -> value ^ E -> operands -> next -> p -> value;
735 break;
736
737 case lw_expr_oper_and:
738 tr = E -> operands -> p -> value && E -> operands -> next -> p -> value;
739 break;
740
741 case lw_expr_oper_or:
742 tr = E -> operands -> p -> value || E -> operands -> next -> p -> value;
743 break;
744
745 }
746
747 while (E -> operands)
748 {
749 o = E -> operands;
750 E -> operands = o -> next;
751 lw_expr_destroy(o -> p);
752 lw_free(o);
753 }
754 E -> type = lw_expr_type_int;
755 E -> value = tr;
756 return;
757 }
758
759 if (E -> value == lw_expr_oper_plus)
760 {
761 lw_expr_t e1;
762 int cval = 0;
763
764 e1 = lw_expr_create();
765 e1 -> operands = E -> operands;
766 E -> operands = 0;
767
768 for (o = e1 -> operands; o; o = o -> next)
769 {
770 if (o -> p -> type == lw_expr_type_int)
771 cval += o -> p -> value;
772 else
773 lw_expr_add_operand(E, o -> p);
774 }
775 lw_expr_destroy(e1);
776 if (cval)
777 {
778 e1 = lw_expr_build(lw_expr_type_int, cval);
779 lw_expr_add_operand(E, e1);
780 lw_expr_destroy(e1);
781 }
782 }
783
784 if (E -> value == lw_expr_oper_times)
785 {
786 lw_expr_t e1;
787 int cval = 1;
788
789 e1 = lw_expr_create();
790 e1 -> operands = E -> operands;
791 E -> operands = 0;
792
793 for (o = e1 -> operands; o; o = o -> next)
794 {
795 if (o -> p -> type == lw_expr_type_int)
796 cval *= o -> p -> value;
797 else
798 lw_expr_add_operand(E, o -> p);
799 }
800 lw_expr_destroy(e1);
801 if (cval != 1)
802 {
803 e1 = lw_expr_build(lw_expr_type_int, cval);
804 lw_expr_add_operand(E, e1);
805 lw_expr_destroy(e1);
806 }
807 }
808
809 if (E -> value == lw_expr_oper_times)
810 {
811 for (o = E -> operands; o; o = o -> next)
812 {
813 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0)
814 {
815 // one operand of times is 0, replace operation with 0
816 while (E -> operands)
817 {
818 o = E -> operands;
819 E -> operands = o -> next;
820 lw_expr_destroy(o -> p);
821 lw_free(o);
822 }
823 E -> type = lw_expr_type_int;
824 E -> value = 0;
825 return;
826 }
827 }
828 }
829
830 // sort "constants" to the start of each operand list for + and *
831 if (E -> value == lw_expr_oper_plus || E -> value == lw_expr_oper_times)
832 lw_expr_simplify_sortconstfirst(E);
833
834 // look for like terms and collect them together
835 if (E -> value == lw_expr_oper_plus)
836 {
837 struct lw_expr_opers *o2;
838 for (o = E -> operands; o; o = o -> next)
839 {
840 // skip constants
841 if (o -> p -> type == lw_expr_type_int)
842 continue;
843
844 // we have a term to match
845 // (o -> p) is first term
846 for (o2 = o -> next; o2; o2 = o2 -> next)
847 {
848 lw_expr_t e1, e2;
849
850 if (o2 -> p -> type == lw_expr_type_int)
851 continue;
852
853 if (lw_expr_simplify_isliketerm(o -> p, o2 -> p))
854 {
855 int coef, coef2;
856
857 // we have a like term here
858 // do something about it
859 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times)
860 {
861 if (o -> p -> operands -> p -> type == lw_expr_type_int)
862 coef = o -> p -> operands -> p -> value;
863 else
864 coef = 1;
865 }
866 else
867 coef = 1;
868 if (o2 -> p -> type == lw_expr_type_oper && o2 -> p -> value == lw_expr_oper_times)
869 {
870 if (o2 -> p -> operands -> p -> type == lw_expr_type_int)
871 coef2 = o2 -> p -> operands -> p -> value;
872 else
873 coef2 = 1;
874 }
875 else
876 coef2 = 1;
877 coef += coef2;
878 e1 = lw_expr_create();
879 e1 -> type = lw_expr_type_oper;
880 e1 -> value = lw_expr_oper_times;
881 if (coef != 1)
882 {
883 e2 = lw_expr_build(lw_expr_type_int, coef);
884 lw_expr_add_operand(e1, e2);
885 lw_expr_destroy(e2);
886 }
887 lw_expr_destroy(o -> p);
888 o -> p = e1;
889 for (o = o2 -> p -> operands; o; o = o -> next)
890 {
891 if (o -> p -> type == lw_expr_type_int)
892 continue;
893 lw_expr_add_operand(e1, o -> p);
894 }
895 lw_expr_destroy(o2 -> p);
896 o2 -> p = lw_expr_build(lw_expr_type_int, 0);
897 goto again;
898 }
899 }
900 }
901 }
902
903
904 if (E -> value == lw_expr_oper_plus)
905 {
906 int c = 0, t = 0;
907 for (o = E -> operands; o; o = o -> next)
908 {
909 t++;
910 if (!(o -> p -> type == lw_expr_type_int && o -> p -> value == 0))
911 {
912 c++;
913 }
914 }
915 if (c == 1)
916 {
917 lw_expr_t r;
918 // find the value and "move it up"
919 while (E -> operands)
920 {
921 o = E -> operands;
922 if (o -> p -> type != lw_expr_type_int || o -> p -> value != 0)
923 {
924 r = lw_expr_copy(o -> p);
925 }
926 E -> operands = o -> next;
927 lw_expr_destroy(o -> p);
928 lw_free(o);
929 }
930 *E = *r;
931 return;
932 }
933 else if (c == 0)
934 {
935 // replace with 0
936 while (E -> operands)
937 {
938 o = E -> operands;
939 E -> operands = o -> next;
940 lw_expr_destroy(o -> p);
941 lw_free(o);
942 }
943 E -> type = lw_expr_type_int;
944 E -> value = 0;
945 return;
946 }
947 else if (c != t)
948 {
949 // collapse out zero terms
950 struct lw_expr_opers *o2;
951
952 for (o = E -> operands; o; o = o -> next)
953 {
954 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0)
955 {
956 if (o == E -> operands)
957 {
958 E -> operands = o -> next;
959 lw_expr_destroy(o -> p);
960 lw_free(o);
961 o = E -> operands;
962 }
963 else
964 {
965 for (o2 = E -> operands; o2 -> next == o; o2 = o2 -> next)
966 /* do nothing */ ;
967 o2 -> next = o -> next;
968 lw_expr_destroy(o -> p);
969 lw_free(o);
970 o = o2;
971 }
972 }
973 }
974 }
975 return;
976 }
977
978 /* handle <int> times <plus> - expand the terms - only with exactly two operands */
979 if (E -> value == lw_expr_oper_times)
980 {
981 lw_expr_t t1;
982 lw_expr_t E2;
983 lw_expr_t E3;
984 if (E -> operands && E -> operands -> next && !(E -> operands -> next -> next))
985 {
986 if (E -> operands -> p -> type == lw_expr_type_int)
987 {
988 /* <int> TIMES <other> */
989 E2 = E -> operands -> next -> p;
990 E3 = E -> operands -> p;
991 if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus)
992 {
993 lw_free(E -> operands -> next);
994 lw_free(E -> operands);
995 E -> operands = NULL;
996 E -> value = lw_expr_oper_plus;
997
998 for (o = E2 -> operands; o; o = o -> next)
999 {
1000 t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p);
1001 lw_expr_add_operand(E, t1);
1002 }
1003
1004 lw_expr_destroy(E2);
1005 lw_expr_destroy(E3);
1006 }
1007 }
1008 else if (E -> operands -> next -> p -> type == lw_expr_type_int)
1009 {
1010 /* <other> TIMES <int> */
1011 E2 = E -> operands -> p;
1012 E3 = E -> operands -> next -> p;
1013 if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus)
1014 {
1015 lw_free(E -> operands -> next);
1016 lw_free(E -> operands);
1017 E -> operands = NULL;
1018 E -> value = lw_expr_oper_plus;
1019
1020 for (o = E2 -> operands; o; o = o -> next)
1021 {
1022 t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p);
1023 lw_expr_add_operand(E, t1);
1024 }
1025
1026 lw_expr_destroy(E2);
1027 lw_expr_destroy(E3);
1028 }
1029 }
1030 }
1031 }
1032 }
1033
1034 void lw_expr_simplify_l(lw_expr_t E, void *priv)
1035 {
1036 lw_expr_t te;
1037 int c;
1038
1039 (level)++;
1040 // bail out if the level gets too deep
1041 if (level >= 500 || bailing)
1042 {
1043 bailing = 1;
1044 level--;
1045 if (level == 0)
1046 bailing = 0;
1047 return;
1048 }
1049 do
1050 {
1051 te = lw_expr_copy(E);
1052 lw_expr_simplify_go(E, priv);
1053 c = 0;
1054 if (lw_expr_compare(te, E) == 0)
1055 c = 1;
1056 lw_expr_destroy(te);
1057 }
1058 while (c);
1059 (level)--;
1060 }
1061
1062 void lw_expr_simplify(lw_expr_t E, void *priv)
1063 {
1064 lw_expr_simplify_l(E, priv);
1065 }
1066
1067 /*
1068
1069 The following two functions are co-routines which evaluate an infix
1070 expression. lw_expr_parse_term checks for unary prefix operators then, if
1071 none found, passes the string off the the defined helper function to
1072 determine what the term really is. It also handles parentheses.
1073
1074 lw_expr_parse_expr evaluates actual expressions with infix operators. It
1075 respects the order of operations.
1076
1077 The end of an expression is determined by the presence of any of the
1078 following conditions:
1079
1080 1. a NUL character
1081 2. a whitespace character
1082 3. a )
1083 4. a ,
1084 5. any character that is not recognized as a term
1085
1086 lw_expr_parse_term returns NULL if there is no term (end of expr, etc.)
1087
1088 lw_expr_parse_expr returns NULL if there is no expression or on a syntax
1089 error.
1090
1091 */
1092
1093 lw_expr_t lw_expr_parse_expr(char **p, void *priv, int prec);
1094
1095 lw_expr_t lw_expr_parse_term(char **p, void *priv)
1096 {
1097 lw_expr_t term, term2;
1098
1099 eval_next:
1100 if (!**p || isspace(**p) || **p == ')' || **p == ']')
1101 return NULL;
1102
1103 // parentheses
1104 if (**p == '(')
1105 {
1106 (*p)++;
1107 term = lw_expr_parse_expr(p, priv, 0);
1108 if (**p != ')')
1109 {
1110 lw_expr_destroy(term);
1111 return NULL;
1112 }
1113 (*p)++;
1114 return term;
1115 }
1116
1117 // unary +
1118 if (**p == '+')
1119 {
1120 (*p)++;
1121 goto eval_next;
1122 }
1123
1124 // unary - (prec 200)
1125 if (**p == '-')
1126 {
1127 (*p)++;
1128 term = lw_expr_parse_expr(p, priv, 200);
1129 if (!term)
1130 return NULL;
1131
1132 term2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_neg, term);
1133 lw_expr_destroy(term);
1134 return term2;
1135 }
1136
1137 // unary ^ or ~ (complement, prec 200)
1138 if (**p == '^' || **p == '~')
1139 {
1140 (*p)++;
1141 term = lw_expr_parse_expr(p, priv, 200);
1142 if (!term)
1143 return NULL;
1144
1145 term2 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_com, term);
1146 lw_expr_destroy(term);
1147 return term2;
1148 }
1149
1150 // non-operator - pass to caller
1151 return parse_term(p, priv);
1152 }
1153
1154 lw_expr_t lw_expr_parse_expr(char **p, void *priv, int prec)
1155 {
1156 static const struct operinfo
1157 {
1158 int opernum;
1159 char *operstr;
1160 int operprec;
1161 } operators[] =
1162 {
1163 { lw_expr_oper_plus, "+", 100 },
1164 { lw_expr_oper_minus, "-", 100 },
1165 { lw_expr_oper_times, "*", 150 },
1166 { lw_expr_oper_divide, "/", 150 },
1167 { lw_expr_oper_mod, "%", 150 },
1168 { lw_expr_oper_intdiv, "\\", 150 },
1169
1170 { lw_expr_oper_and, "&&", 25 },
1171 { lw_expr_oper_or, "||", 25 },
1172
1173 { lw_expr_oper_bwand, "&", 50 },
1174 { lw_expr_oper_bwor, "|", 50 },
1175 { lw_expr_oper_bwxor, "^", 50 },
1176
1177 { lw_expr_oper_none, "", 0 }
1178 };
1179
1180 int opern, i;
1181 lw_expr_t term1, term2, term3;
1182
1183 if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']')
1184 return NULL;
1185
1186 term1 = lw_expr_parse_term(p, priv);
1187 if (!term1)
1188 return NULL;
1189
1190 eval_next:
1191 if (!**p || isspace(**p) || **p == ')' || **p == ',' || **p == ']')
1192 return term1;
1193
1194 // expecting an operator here
1195 for (opern = 0; operators[opern].opernum != lw_expr_oper_none; opern++)
1196 {
1197 for (i = 0; (*p)[i] && operators[opern].operstr[i] && ((*p)[i] == operators[opern].operstr[i]); i++)
1198 /* do nothing */;
1199 if (operators[opern].operstr[i] == '\0')
1200 break;
1201 }
1202
1203 if (operators[opern].opernum == lw_expr_oper_none)
1204 {
1205 // unrecognized operator
1206 lw_expr_destroy(term1);
1207 return NULL;
1208 }
1209
1210 // operator number is in opern, length of oper in i
1211
1212 // logic:
1213 // if the precedence of this operation is <= to the "prec" flag,
1214 // we simply return without advancing the input pointer; the operator
1215 // will be evaluated again in the enclosing function call
1216 if (operators[opern].operprec <= prec)
1217 return term1;
1218
1219 // logic:
1220 // we have a higher precedence operator here so we will advance the
1221 // input pointer to the next term and let the expression evaluator
1222 // loose on it after which time we will push our operator onto the
1223 // stack and then go on with the expression evaluation
1224 (*p) += i;
1225
1226 // evaluate next expression(s) of higher precedence
1227 term2 = lw_expr_parse_expr(p, priv, operators[opern].operprec);
1228 if (!term2)
1229 {
1230 lw_expr_destroy(term1);
1231 return NULL;
1232 }
1233
1234 // now create operator
1235 term3 = lw_expr_build(lw_expr_type_oper, operators[opern].opernum, term1, term2);
1236 lw_expr_destroy(term1);
1237 lw_expr_destroy(term2);
1238
1239 // the new "expression" is the next "left operand"
1240 term1 = term3;
1241
1242 // continue evaluating
1243 goto eval_next;
1244 }
1245
1246 lw_expr_t lw_expr_parse(char **p, void *priv)
1247 {
1248 return lw_expr_parse_expr(p, priv, 0);
1249 }
1250
1251 int lw_expr_testterms(lw_expr_t e, lw_expr_testfn_t *fn, void *priv)
1252 {
1253 struct lw_expr_opers *o;
1254 int r;
1255
1256 for (o = e -> operands; o; o = o -> next)
1257 {
1258 r = lw_expr_testterms(o -> p, fn, priv);
1259 if (r)
1260 return r;
1261 }
1262 return (fn)(e, priv);
1263 }
1264
1265 int lw_expr_type(lw_expr_t e)
1266 {
1267 return e -> type;
1268 }
1269
1270 void *lw_expr_specptr(lw_expr_t e)
1271 {
1272 return e -> value2;
1273 }