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