Mercurial > hg > index.cgi
comparison lwlib/lw_expr.c @ 339:6138e304ab9a
Revert 3b5a45c6ab92
The speedup fix in 3b5a45c6ab92 contains some sort of bug related to operand
manipulation during expression simplification or copying. This leads to
crashes that so have have eluded tracing. Revert back to known working
version of the code, even though slower, to avoid regressions.
author | William Astle <lost@l-w.ca> |
---|---|
date | Fri, 08 Aug 2014 12:14:22 -0600 |
parents | 3b5a45c6ab92 |
children | 12e2453f8417 |
comparison
equal
deleted
inserted
replaced
338:5d401d1eb3e9 | 339:6138e304ab9a |
---|---|
103 { | 103 { |
104 lw_expr_t r; | 104 lw_expr_t r; |
105 | 105 |
106 r = lw_alloc(sizeof(struct lw_expr_priv)); | 106 r = lw_alloc(sizeof(struct lw_expr_priv)); |
107 r -> operands = NULL; | 107 r -> operands = NULL; |
108 r -> operand_tail = NULL; | |
109 r -> value2 = NULL; | 108 r -> value2 = NULL; |
110 r -> type = lw_expr_type_int; | 109 r -> type = lw_expr_type_int; |
111 r -> value = 0; | 110 r -> value = 0; |
112 return r; | 111 return r; |
113 } | 112 } |
114 | 113 |
115 static lw_expr_t lw_expr_remove_operand(lw_expr_t E, struct lw_expr_opers *o) | |
116 { | |
117 lw_expr_t r; | |
118 if (E -> operands == o) | |
119 E -> operands = o -> next; | |
120 else | |
121 o -> prev -> next = o -> next; | |
122 | |
123 if (E -> operand_tail == o) | |
124 E -> operand_tail = o -> prev; | |
125 else | |
126 o -> next -> prev = o -> prev; | |
127 | |
128 r = o -> p; | |
129 lw_free(o); | |
130 return r; | |
131 } | |
132 | |
133 void lw_expr_destroy(lw_expr_t E); | |
134 static void lw_expr_remove_operands(lw_expr_t E) | |
135 { | |
136 while (E -> operands) | |
137 lw_expr_destroy(lw_expr_remove_operand(E, E -> operands)); | |
138 } | |
139 | |
140 void lw_expr_destroy(lw_expr_t E) | 114 void lw_expr_destroy(lw_expr_t E) |
141 { | 115 { |
116 struct lw_expr_opers *o; | |
142 if (!E) | 117 if (!E) |
143 return; | 118 return; |
144 lw_expr_remove_operands(E); | 119 while (E -> operands) |
120 { | |
121 o = E -> operands; | |
122 E -> operands = o -> next; | |
123 lw_expr_destroy(o -> p); | |
124 lw_free(o); | |
125 } | |
145 if (E -> type == lw_expr_type_var) | 126 if (E -> type == lw_expr_type_var) |
146 lw_free(E -> value2); | 127 lw_free(E -> value2); |
147 lw_free(E); | 128 lw_free(E); |
148 } | 129 } |
149 | 130 |
170 return r; | 151 return r; |
171 } | 152 } |
172 | 153 |
173 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O) | 154 void lw_expr_add_operand(lw_expr_t E, lw_expr_t O) |
174 { | 155 { |
175 struct lw_expr_opers *o; | 156 struct lw_expr_opers *o, *t; |
176 | 157 |
177 o = lw_alloc(sizeof(struct lw_expr_opers)); | 158 o = lw_alloc(sizeof(struct lw_expr_opers)); |
178 o -> p = lw_expr_copy(O); | 159 o -> p = lw_expr_copy(O); |
179 o -> next = NULL; | 160 o -> next = NULL; |
180 o -> prev = E -> operand_tail; | 161 for (t = E -> operands; t && t -> next; t = t -> next) |
181 | 162 /* do nothing */ ; |
182 if (E -> operands) | 163 |
183 E -> operand_tail -> next = o; | 164 if (t) |
165 t -> next = o; | |
184 else | 166 else |
185 E -> operands = o; | 167 E -> operands = o; |
186 E -> operand_tail = o; | |
187 } | 168 } |
188 | 169 |
189 lw_expr_t lw_expr_build_aux(int exprtype, va_list args) | 170 lw_expr_t lw_expr_build_aux(int exprtype, va_list args) |
190 { | 171 { |
191 lw_expr_t r; | 172 lw_expr_t r; |
439 { | 420 { |
440 if (o -> p -> type == lw_expr_type_oper && (o -> p -> value == lw_expr_oper_times || o -> p -> value == lw_expr_oper_plus)) | 421 if (o -> p -> type == lw_expr_type_oper && (o -> p -> value == lw_expr_oper_times || o -> p -> value == lw_expr_oper_plus)) |
441 lw_expr_simplify_sortconstfirst(o -> p); | 422 lw_expr_simplify_sortconstfirst(o -> p); |
442 } | 423 } |
443 | 424 |
444 for (o = E -> operands; o; ) | 425 for (o = E -> operands; o; o = o -> next) |
445 { | 426 { |
446 struct lw_expr_opers *o2; | |
447 o2 = o -> next; | |
448 if (o -> p -> type == lw_expr_type_int && o != E -> operands) | 427 if (o -> p -> type == lw_expr_type_int && o != E -> operands) |
449 { | 428 { |
450 // because o cannot be the first operand, we don't have to | 429 struct lw_expr_opers *o2; |
451 // handle the single element list here | 430 for (o2 = E -> operands; o2 -> next != o; o2 = o2 -> next) |
452 o2 = o -> next; | 431 /* do nothing */ ; |
453 if (E -> operand_tail == o) | 432 o2 -> next = o -> next; |
454 E -> operand_tail = o -> prev; | |
455 o -> prev -> next = o -> next; | |
456 if (o -> next) | |
457 o -> next -> prev = o -> prev; | |
458 E -> operands -> prev = o; | |
459 o -> next = E -> operands; | 433 o -> next = E -> operands; |
460 o -> prev = NULL; | |
461 E -> operands = o; | 434 E -> operands = o; |
462 E -> operands = o; | 435 o = o2; |
463 } | 436 } |
464 o = o2; | |
465 } | 437 } |
466 } | 438 } |
467 | 439 |
468 void lw_expr_sortoperandlist(struct lw_expr_opers **o) | 440 void lw_expr_sortoperandlist(struct lw_expr_opers **o) |
469 { | 441 { |
611 lw_expr_destroy(o -> p); | 583 lw_expr_destroy(o -> p); |
612 if (E -> type == lw_expr_type_var) | 584 if (E -> type == lw_expr_type_var) |
613 lw_free(E -> value2); | 585 lw_free(E -> value2); |
614 *E = *te; | 586 *E = *te; |
615 E -> operands = NULL; | 587 E -> operands = NULL; |
616 E -> operand_tail = NULL; | 588 |
617 | |
618 if (te -> type == lw_expr_type_var) | 589 if (te -> type == lw_expr_type_var) |
619 E -> value2 = lw_strdup(te -> value2); | 590 E -> value2 = lw_strdup(te -> value2); |
620 for (o = te -> operands; o; o = o -> next) | 591 for (o = te -> operands; o; o = o -> next) |
621 { | 592 { |
622 lw_expr_t xxx; | 593 lw_expr_t xxx; |
643 lw_expr_destroy(o -> p); | 614 lw_expr_destroy(o -> p); |
644 if (E -> type == lw_expr_type_var) | 615 if (E -> type == lw_expr_type_var) |
645 lw_free(E -> value2); | 616 lw_free(E -> value2); |
646 *E = *te; | 617 *E = *te; |
647 E -> operands = NULL; | 618 E -> operands = NULL; |
648 E -> operand_tail = NULL; | |
649 | 619 |
650 if (te -> type == lw_expr_type_var) | 620 if (te -> type == lw_expr_type_var) |
651 E -> value2 = lw_strdup(te -> value2); | 621 E -> value2 = lw_strdup(te -> value2); |
652 for (o = te -> operands; o; o = o -> next) | 622 for (o = te -> operands; o; o = o -> next) |
653 { | 623 { |
669 tryagainplus: | 639 tryagainplus: |
670 for (o = E -> operands; o; o = o -> next) | 640 for (o = E -> operands; o; o = o -> next) |
671 { | 641 { |
672 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_plus) | 642 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_plus) |
673 { | 643 { |
674 if (o -> p -> operands) | 644 struct lw_expr_opers *o2; |
675 { | 645 // we have a + operation - bring operands up |
676 if (E -> operands == NULL) | 646 |
677 { | 647 for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next) |
678 E -> operands = o -> p -> operands; | 648 /* do nothing */ ; |
679 E -> operand_tail = o -> p -> operand_tail; | 649 if (o2) |
680 } | 650 o2 -> next = o -> p -> operands; |
681 else | 651 else |
682 { | 652 E -> operands = o -> p -> operands; |
683 E -> operand_tail -> next = o -> p -> operands; | 653 for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next) |
684 o -> p -> operands -> prev = E -> operand_tail; | 654 /* do nothing */ ; |
685 E -> operand_tail = o -> p -> operand_tail; | 655 o2 -> next = o -> next; |
686 } | |
687 o -> p -> operands = NULL; | |
688 o -> p -> operand_tail = NULL; | |
689 } | |
690 o -> p -> operands = NULL; | 656 o -> p -> operands = NULL; |
691 lw_expr_destroy(o -> p); | 657 lw_expr_destroy(o -> p); |
692 if (o -> prev) | |
693 o -> prev -> next = o -> next; | |
694 else | |
695 E -> operands = o -> next; | |
696 if (o -> next) | |
697 o -> next -> prev = o -> prev; | |
698 else | |
699 E -> operand_tail = o -> prev; | |
700 lw_free(o); | 658 lw_free(o); |
701 goto tryagainplus; | 659 goto tryagainplus; |
702 } | 660 } |
703 } | 661 } |
704 } | 662 } |
709 tryagaintimes: | 667 tryagaintimes: |
710 for (o = E -> operands; o; o = o -> next) | 668 for (o = E -> operands; o; o = o -> next) |
711 { | 669 { |
712 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) | 670 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) |
713 { | 671 { |
714 if (o -> p -> operands) | 672 struct lw_expr_opers *o2; |
715 { | 673 // we have a + operation - bring operands up |
716 if (E -> operands == NULL) | 674 |
717 { | 675 for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next) |
718 E -> operands = o -> p -> operands; | 676 /* do nothing */ ; |
719 E -> operand_tail = o -> p -> operand_tail; | 677 if (o2) |
720 } | 678 o2 -> next = o -> p -> operands; |
721 else | 679 else |
722 { | 680 E -> operands = o -> p -> operands; |
723 E -> operand_tail -> next = o -> p -> operands; | 681 for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next) |
724 o -> p -> operands -> prev = E -> operand_tail; | 682 /* do nothing */ ; |
725 E -> operand_tail = o -> p -> operand_tail; | 683 o2 -> next = o -> next; |
726 } | |
727 o -> p -> operands = NULL; | |
728 o -> p -> operand_tail = NULL; | |
729 } | |
730 o -> p -> operands = NULL; | 684 o -> p -> operands = NULL; |
731 lw_expr_destroy(o -> p); | 685 lw_expr_destroy(o -> p); |
732 if (o -> prev) | |
733 o -> prev -> next = o -> next; | |
734 else | |
735 E -> operands = o -> next; | |
736 if (o -> next) | |
737 o -> next -> prev = o -> prev; | |
738 else | |
739 E -> operand_tail = o -> prev; | |
740 lw_free(o); | 686 lw_free(o); |
741 goto tryagaintimes; | 687 goto tryagaintimes; |
742 } | 688 } |
743 } | 689 } |
744 } | 690 } |
837 tr = E -> operands -> p -> value || E -> operands -> next -> p -> value; | 783 tr = E -> operands -> p -> value || E -> operands -> next -> p -> value; |
838 break; | 784 break; |
839 | 785 |
840 } | 786 } |
841 | 787 |
842 lw_expr_remove_operands(E); | 788 while (E -> operands) |
789 { | |
790 o = E -> operands; | |
791 E -> operands = o -> next; | |
792 lw_expr_destroy(o -> p); | |
793 lw_free(o); | |
794 } | |
843 E -> type = lw_expr_type_int; | 795 E -> type = lw_expr_type_int; |
844 E -> value = tr; | 796 E -> value = tr; |
845 return; | 797 return; |
846 } | 798 } |
847 | 799 |
850 lw_expr_t e1; | 802 lw_expr_t e1; |
851 int cval = 0; | 803 int cval = 0; |
852 | 804 |
853 e1 = lw_expr_create(); | 805 e1 = lw_expr_create(); |
854 e1 -> operands = E -> operands; | 806 e1 -> operands = E -> operands; |
855 e1 -> operand_tail = E -> operand_tail; | |
856 E -> operands = 0; | 807 E -> operands = 0; |
857 E -> operand_tail = NULL; | |
858 | 808 |
859 for (o = e1 -> operands; o; o = o -> next) | 809 for (o = e1 -> operands; o; o = o -> next) |
860 { | 810 { |
861 if (o -> p -> type == lw_expr_type_int) | 811 if (o -> p -> type == lw_expr_type_int) |
862 cval += o -> p -> value; | 812 cval += o -> p -> value; |
877 lw_expr_t e1; | 827 lw_expr_t e1; |
878 int cval = 1; | 828 int cval = 1; |
879 | 829 |
880 e1 = lw_expr_create(); | 830 e1 = lw_expr_create(); |
881 e1 -> operands = E -> operands; | 831 e1 -> operands = E -> operands; |
882 e1 -> operand_tail = E -> operand_tail; | |
883 E -> operands = 0; | 832 E -> operands = 0; |
884 E -> operand_tail = NULL; | |
885 | 833 |
886 for (o = e1 -> operands; o; o = o -> next) | 834 for (o = e1 -> operands; o; o = o -> next) |
887 { | 835 { |
888 if (o -> p -> type == lw_expr_type_int) | 836 if (o -> p -> type == lw_expr_type_int) |
889 cval *= o -> p -> value; | 837 cval *= o -> p -> value; |
904 for (o = E -> operands; o; o = o -> next) | 852 for (o = E -> operands; o; o = o -> next) |
905 { | 853 { |
906 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) | 854 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) |
907 { | 855 { |
908 // one operand of times is 0, replace operation with 0 | 856 // one operand of times is 0, replace operation with 0 |
909 lw_expr_remove_operands(E); | 857 while (E -> operands) |
858 { | |
859 o = E -> operands; | |
860 E -> operands = o -> next; | |
861 lw_expr_destroy(o -> p); | |
862 lw_free(o); | |
863 } | |
910 E -> type = lw_expr_type_int; | 864 E -> type = lw_expr_type_int; |
911 E -> value = 0; | 865 E -> value = 0; |
912 return; | 866 return; |
913 } | 867 } |
914 } | 868 } |
1008 o = E -> operands; | 962 o = E -> operands; |
1009 if (o -> p -> type != lw_expr_type_int || o -> p -> value != 0) | 963 if (o -> p -> type != lw_expr_type_int || o -> p -> value != 0) |
1010 { | 964 { |
1011 r = lw_expr_copy(o -> p); | 965 r = lw_expr_copy(o -> p); |
1012 } | 966 } |
1013 lw_expr_destroy(lw_expr_remove_operand(E, E -> operands)); | 967 E -> operands = o -> next; |
968 lw_expr_destroy(o -> p); | |
969 lw_free(o); | |
1014 } | 970 } |
1015 *E = *r; | 971 *E = *r; |
1016 lw_free(r); | 972 lw_free(r); |
1017 return; | 973 return; |
1018 } | 974 } |
1019 else if (c == 0) | 975 else if (c == 0) |
1020 { | 976 { |
1021 // replace with 0 | 977 // replace with 0 |
1022 lw_expr_remove_operands(E); | 978 while (E -> operands) |
979 { | |
980 o = E -> operands; | |
981 E -> operands = o -> next; | |
982 lw_expr_destroy(o -> p); | |
983 lw_free(o); | |
984 } | |
1023 E -> type = lw_expr_type_int; | 985 E -> type = lw_expr_type_int; |
1024 E -> value = 0; | 986 E -> value = 0; |
1025 return; | 987 return; |
1026 } | 988 } |
1027 else if (c != t) | 989 else if (c != t) |
1028 { | 990 { |
1029 // collapse out zero terms | 991 // collapse out zero terms |
1030 struct lw_expr_opers *o2; | 992 struct lw_expr_opers *o2; |
1031 | 993 |
1032 for (o = E -> operands; o; o = o2) | 994 for (o = E -> operands; o; o = o -> next) |
1033 { | 995 { |
1034 o2 = o -> next; | |
1035 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) | 996 if (o -> p -> type == lw_expr_type_int && o -> p -> value == 0) |
1036 { | 997 { |
1037 lw_expr_destroy(lw_expr_remove_operand(E, o)); | 998 if (o == E -> operands) |
999 { | |
1000 E -> operands = o -> next; | |
1001 lw_expr_destroy(o -> p); | |
1002 lw_free(o); | |
1003 o = E -> operands; | |
1004 } | |
1005 else | |
1006 { | |
1007 for (o2 = E -> operands; o2 -> next == o; o2 = o2 -> next) | |
1008 /* do nothing */ ; | |
1009 o2 -> next = o -> next; | |
1010 lw_expr_destroy(o -> p); | |
1011 lw_free(o); | |
1012 o = o2; | |
1013 } | |
1038 } | 1014 } |
1039 } | 1015 } |
1040 } | 1016 } |
1041 return; | 1017 return; |
1042 } | 1018 } |
1057 if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus) | 1033 if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus) |
1058 { | 1034 { |
1059 lw_free(E -> operands -> next); | 1035 lw_free(E -> operands -> next); |
1060 lw_free(E -> operands); | 1036 lw_free(E -> operands); |
1061 E -> operands = NULL; | 1037 E -> operands = NULL; |
1062 E -> operand_tail = NULL; | |
1063 E -> value = lw_expr_oper_plus; | 1038 E -> value = lw_expr_oper_plus; |
1064 | 1039 |
1065 for (o = E2 -> operands; o; o = o -> next) | 1040 for (o = E2 -> operands; o; o = o -> next) |
1066 { | 1041 { |
1067 t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p); | 1042 t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p); |
1068 lw_expr_add_operand(E, t1); | 1043 lw_expr_add_operand(E, t1); |
1069 lw_expr_destroy(t1); | 1044 lw_expr_destroy(t1); |
1070 } | 1045 } |
1046 | |
1047 lw_expr_destroy(E2); | |
1048 lw_expr_destroy(E3); | |
1071 } | 1049 } |
1072 } | 1050 } |
1073 else if (E -> operands -> next -> p -> type == lw_expr_type_int) | 1051 else if (E -> operands -> next -> p -> type == lw_expr_type_int) |
1074 { | 1052 { |
1075 /* <other> TIMES <int> */ | 1053 /* <other> TIMES <int> */ |
1078 if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus) | 1056 if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus) |
1079 { | 1057 { |
1080 lw_free(E -> operands -> next); | 1058 lw_free(E -> operands -> next); |
1081 lw_free(E -> operands); | 1059 lw_free(E -> operands); |
1082 E -> operands = NULL; | 1060 E -> operands = NULL; |
1083 E -> operand_tail = NULL; | |
1084 E -> value = lw_expr_oper_plus; | 1061 E -> value = lw_expr_oper_plus; |
1085 | 1062 |
1086 for (o = E2 -> operands; o; o = o -> next) | 1063 for (o = E2 -> operands; o; o = o -> next) |
1087 { | 1064 { |
1088 t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p); | 1065 t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p); |