comparison lwlib/lw_expr.c @ 431:d7d7e4dca3e7

Eliminated infinite loop on recursive symbol resolution with a Q&D hack: limit the depth that lw_expr_simplify can be called to globally. Not thread friendly.
author lost@l-w.ca
date Sun, 24 Oct 2010 20:05:15 -0600
parents 652eee8f0c82
children 22bbb716dea6
comparison
equal deleted inserted replaced
430:4bcb763bddde 431:d7d7e4dca3e7
32 #include "lw_string.h" 32 #include "lw_string.h"
33 33
34 static lw_expr_fn_t *evaluate_special = NULL; 34 static lw_expr_fn_t *evaluate_special = NULL;
35 static lw_expr_fn2_t *evaluate_var = NULL; 35 static lw_expr_fn2_t *evaluate_var = NULL;
36 static lw_expr_fn3_t *parse_term = NULL; 36 static lw_expr_fn3_t *parse_term = NULL;
37
38 /* Q&D to break out of infinite recursion */
39 static int level = 0;
40 static int bailing = 0;
37 41
38 int lw_expr_istype(lw_expr_t e, int t) 42 int lw_expr_istype(lw_expr_t e, int t)
39 { 43 {
40 if (e -> type == t) 44 if (e -> type == t)
41 return 1; 45 return 1;
335 struct lw_expr_opers *o1, *o2; 339 struct lw_expr_opers *o1, *o2;
336 340
337 if (E1 == E2) 341 if (E1 == E2)
338 return 1; 342 return 1;
339 343
344 if (!E1 || !E2)
345 return 0;
346
340 if (!(E1 -> type == E2 -> type && E1 -> value == E2 -> value)) 347 if (!(E1 -> type == E2 -> type && E1 -> value == E2 -> value))
341 return 0; 348 return 0;
342 349
343 if (E1 -> type == lw_expr_type_var) 350 if (E1 -> type == lw_expr_type_var)
344 { 351 {
451 return 0; 458 return 0;
452 } 459 }
453 460
454 // not a times - have to assume it's the operand list 461 // not a times - have to assume it's the operand list
455 // with a "1 *" in front if it 462 // with a "1 *" in front if it
463 if (!e1 -> operands -> next)
464 return 0;
456 if (e1 -> operands -> next -> next) 465 if (e1 -> operands -> next -> next)
457 return 0; 466 return 0;
458 if (!lw_expr_compare(e1 -> operands -> next -> p, e2)) 467 if (!lw_expr_compare(e1 -> operands -> next -> p, e2))
459 return 0; 468 return 0;
460 return 1; 469 return 1;
475 if (!lw_expr_compare(e1, e2)) 484 if (!lw_expr_compare(e1, e2))
476 return 0; 485 return 0;
477 return 1; 486 return 1;
478 } 487 }
479 488
480 void lw_expr_simplify(lw_expr_t E, void *priv); 489 int lw_expr_contains(lw_expr_t E, lw_expr_t E1)
490 {
491 struct lw_expr_opers *o;
492
493 // NULL expr contains nothing :)
494 if (!E)
495 return 0;
496
497 if (E1 -> type != lw_expr_type_var && E1 -> type != lw_expr_type_special)
498 return 0;
499
500 if (lw_expr_compare(E, E1))
501 return 1;
502
503 for (o = E -> operands; o; o = o -> next)
504 {
505 if (lw_expr_contains(o -> p, E1))
506 return 1;
507 }
508 return 0;
509 }
510
511 void lw_expr_simplify_l(lw_expr_t E, void *priv);
481 512
482 void lw_expr_simplify_go(lw_expr_t E, void *priv) 513 void lw_expr_simplify_go(lw_expr_t E, void *priv)
483 { 514 {
484 struct lw_expr_opers *o; 515 struct lw_expr_opers *o;
485 516
516 if (E -> type == lw_expr_type_special && evaluate_special) 547 if (E -> type == lw_expr_type_special && evaluate_special)
517 { 548 {
518 lw_expr_t te; 549 lw_expr_t te;
519 550
520 te = evaluate_special(E -> value, E -> value2, priv); 551 te = evaluate_special(E -> value, E -> value2, priv);
552 if (lw_expr_contains(te, E))
553 lw_expr_destroy(te);
521 if (te) 554 if (te)
522 { 555 {
523 for (o = E -> operands; o; o = o -> next) 556 for (o = E -> operands; o; o = o -> next)
524 lw_expr_destroy(o -> p); 557 lw_expr_destroy(o -> p);
525 if (E -> type == lw_expr_type_var) 558 if (E -> type == lw_expr_type_var)
542 if (E -> type == lw_expr_type_var && evaluate_var) 575 if (E -> type == lw_expr_type_var && evaluate_var)
543 { 576 {
544 lw_expr_t te; 577 lw_expr_t te;
545 578
546 te = evaluate_var(E -> value2, priv); 579 te = evaluate_var(E -> value2, priv);
547 if (te) 580 if (lw_expr_contains(te, E))
581 lw_expr_destroy(te);
582 else if (te)
548 { 583 {
549 for (o = E -> operands; o; o = o -> next) 584 for (o = E -> operands; o; o = o -> next)
550 lw_expr_destroy(o -> p); 585 lw_expr_destroy(o -> p);
551 if (E -> type == lw_expr_type_var) 586 if (E -> type == lw_expr_type_var)
552 lw_free(E -> value2); 587 lw_free(E -> value2);
629 } 664 }
630 } 665 }
631 666
632 // simplify operands 667 // simplify operands
633 for (o = E -> operands; o; o = o -> next) 668 for (o = E -> operands; o; o = o -> next)
634 lw_expr_simplify(o -> p, priv); 669 lw_expr_simplify_l(o -> p, priv);
635 670
636 for (o = E -> operands; o; o = o -> next) 671 for (o = E -> operands; o; o = o -> next)
637 { 672 {
638 if (o -> p -> type != lw_expr_type_int) 673 if (o -> p -> type != lw_expr_type_int)
639 break; 674 break;
991 } 1026 }
992 } 1027 }
993 } 1028 }
994 } 1029 }
995 1030
996 void lw_expr_simplify(lw_expr_t E, void *priv) 1031 void lw_expr_simplify_l(lw_expr_t E, void *priv)
997 { 1032 {
998 lw_expr_t te; 1033 lw_expr_t te;
999 int c; 1034 int c;
1035
1036 (level)++;
1037 // bail out if the level gets too deep
1038 if (level >= 500 || bailing)
1039 {
1040 bailing = 1;
1041 level--;
1042 if (level == 0)
1043 bailing = 0;
1044 return;
1045 }
1000 do 1046 do
1001 { 1047 {
1002 te = lw_expr_copy(E); 1048 te = lw_expr_copy(E);
1003 lw_expr_simplify_go(E, priv); 1049 lw_expr_simplify_go(E, priv);
1004 c = 0; 1050 c = 0;
1005 if (lw_expr_compare(te, E) == 0) 1051 if (lw_expr_compare(te, E) == 0)
1006 c = 1; 1052 c = 1;
1007 lw_expr_destroy(te); 1053 lw_expr_destroy(te);
1008 } 1054 }
1009 while (c); 1055 while (c);
1010 } 1056 (level)--;
1011 1057 }
1058
1059 void lw_expr_simplify(lw_expr_t E, void *priv)
1060 {
1061 lw_expr_simplify_l(E, priv);
1062 }
1012 1063
1013 /* 1064 /*
1014 1065
1015 The following two functions are co-routines which evaluate an infix 1066 The following two functions are co-routines which evaluate an infix
1016 expression. lw_expr_parse_term checks for unary prefix operators then, if 1067 expression. lw_expr_parse_term checks for unary prefix operators then, if