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