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