1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/expr.c,v 1.6 2011/05/16 16:21:57 william Exp $
19 */
20
21 #define _INCLUDE_FROM_EXPR_C_
22
23 #include "tgifdefs.h"
24
25 #include "dialog.e"
26 #include "expr.e"
27 #include "msg.e"
28 #include "setup.e"
29 #include "strtbl.e"
30 #include "util.e"
31
32 #define OP_BEGIN 0
33 #define OP_IFTHEN 1
34 #define OP_ELSE 2
35 #define OP_OR 3
36 #define OP_AND 4
37 #define OP_BIT_OR 5
38 #define OP_BIT_XOR 6
39 #define OP_BIT_AND 7
40 #define OP_EQ 8
41 #define OP_NE 9
42 #define OP_GT 10
43 #define OP_LT 11
44 #define OP_GE 12
45 #define OP_LE 13
46 #define OP_SHIFT_LEFT 14
47 #define OP_SHIFT_RIGHT 15
48 #define OP_ADD 16
49 #define OP_SUB 17
50 #define OP_MUL 18
51 #define OP_DIV 19
52 #define OP_INTDIV 20
53 #define OP_MOD 21
54 #define OP_NOT 22
55 #define OP_BIT_NOT 23
56 #define OP_CLOSE 24
57 #define OP_OPEN 25
58 #define OP_END 26
59
60 struct OpRec {
61 int op_code;
62 int prec;
63 struct OpRec *next;
64 };
65
66 struct ValRec {
67 struct VRec v;
68 struct ValRec *next;
69 };
70
71 static char *pszCurExpr=NULL;
72 static char *pszExpr=NULL;
73 static struct OpRec *topOpStk=NULL;
74 static struct ValRec *topValStk=NULL;
75
76 #ifdef NOT_DEFINED
77 #ifdef _TGIF_DBG
78 static int gnExprDebug=FALSE;
79 #endif /* _TGIF_DBG */
80 #endif /* NOT_DEFINED */
81
82 static
BadOperandType(operator_str)83 int BadOperandType(operator_str)
84 char *operator_str;
85 {
86 sprintf(gszMsgBox, TgLoadString(STID_CANNOT_EVAL_INVALID_OP_TYPE),
87 pszCurExpr, operator_str);
88 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
89 return FALSE;
90 }
91
92 static
DivByZero(operator_str)93 int DivByZero(operator_str)
94 char *operator_str;
95 {
96 sprintf(gszMsgBox, TgLoadString(STID_DIVIDE_BY_ZERO_FOR_OP_TYPE),
97 operator_str);
98 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
99 return FALSE;
100 }
101
102 static
OpPrec(op_code)103 int OpPrec(op_code)
104 int op_code;
105 {
106 switch (op_code) {
107 case OP_BEGIN: return INVALID;
108 case OP_IFTHEN: return 1; /* '?' */
109 case OP_ELSE: return 2; /* ':' */
110 case OP_OR: return 3; /* || */
111 case OP_AND: return 4; /* && */
112 case OP_BIT_OR: return 5; /* | */
113 case OP_BIT_XOR: return 5; /* ^ */
114 case OP_BIT_AND: return 5; /* & */
115 case OP_EQ: return 6; /* == */
116 case OP_NE: return 6; /* != */
117 case OP_GT: return 7; /* > */
118 case OP_LT: return 7; /* < */
119 case OP_GE: return 7; /* >= */
120 case OP_LE: return 7; /* <= */
121 case OP_SHIFT_LEFT: return 8; /* << */
122 case OP_SHIFT_RIGHT: return 8; /* >> */
123 case OP_ADD: return 9; /* '+' */
124 case OP_SUB: return 9; /* '-' */
125 case OP_MUL: return 10; /* '*' */
126 case OP_DIV: return 10; /* '/' */
127 case OP_INTDIV: return 10; /* // */
128 case OP_MOD: return 10; /* % */
129 case OP_NOT: return 11; /* '!' */
130 case OP_BIT_NOT: return 11; /* ~ */
131 case OP_CLOSE: return 12; /* ')' */
132 case OP_OPEN: return 13; /* '(' */
133 case OP_END: return INVALID;
134 }
135 return 99;
136 }
137
138 #define MAX_OP_PREC 14
139
140 static
OpArity(op_code)141 int OpArity(op_code)
142 int op_code;
143 {
144 switch (op_code) {
145 case OP_BEGIN: return INVALID;
146 case OP_IFTHEN: return 3; /* '?' */
147 case OP_ELSE: return 0; /* ':' */
148 case OP_OR: return 2; /* || */
149 case OP_AND: return 2; /* && */
150 case OP_BIT_OR: return 2; /* | */
151 case OP_BIT_XOR: return 2; /* ^ */
152 case OP_BIT_AND: return 2; /* & */
153 case OP_EQ: return 2; /* == */
154 case OP_NE: return 2; /* != */
155 case OP_GT: return 2; /* > */
156 case OP_LT: return 2; /* < */
157 case OP_GE: return 2; /* >= */
158 case OP_LE: return 2; /* <= */
159 case OP_SHIFT_LEFT: return 2; /* << */
160 case OP_SHIFT_RIGHT: return 2; /* >> */
161 case OP_ADD: return 2; /* '+' */
162 case OP_SUB: return 2; /* '-' */
163 case OP_MUL: return 2; /* '*' */
164 case OP_DIV: return 2; /* '/' */
165 case OP_INTDIV: return 2; /* // */
166 case OP_MOD: return 2; /* % */
167 case OP_NOT: return 1; /* '!' */
168 case OP_BIT_NOT: return 1; /* '~' */
169 case OP_CLOSE: return 0; /* ')' */
170 case OP_OPEN: return 0; /* '(' */
171 case OP_END: return INVALID;
172 }
173 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_INVALID_OP_CODE),
174 pszCurExpr, op_code);
175 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
176 return INVALID;
177 }
178
179 static
OpPush(op_code,cur_depth)180 int OpPush(op_code, cur_depth)
181 int op_code;
182 int cur_depth;
183 {
184 struct OpRec *op_ptr=(struct OpRec *)malloc(sizeof(struct OpRec));
185
186 if (op_ptr == NULL) return FailAllocMessage();
187 memset(op_ptr, 0, sizeof(struct OpRec));
188 op_ptr->op_code = op_code;
189 op_ptr->prec = OpPrec(op_code)+cur_depth;
190 op_ptr->next = topOpStk;
191 topOpStk = op_ptr;
192 return TRUE;
193 }
194
195 static
ValPush(v_ptr)196 int ValPush(v_ptr)
197 struct VRec *v_ptr;
198 {
199 struct ValRec *val_ptr=(struct ValRec *)malloc(sizeof(struct ValRec));
200
201 if (val_ptr == NULL) return FailAllocMessage();
202 memset(val_ptr, 0, sizeof(struct ValRec));
203 memcpy(&val_ptr->v, v_ptr, sizeof(val_ptr->v));
204 val_ptr->next = topValStk;
205 topValStk = val_ptr;
206 return TRUE;
207 }
208
209 static
PopOpStk()210 int PopOpStk()
211 {
212 int op_code=topOpStk->op_code;
213 struct OpRec *op_ptr=topOpStk;
214
215 topOpStk = topOpStk->next;
216 free(op_ptr);
217 return op_code;
218 }
219
220 static
PopValStk(v_ptr)221 void PopValStk(v_ptr)
222 struct VRec *v_ptr;
223 {
224 struct ValRec *val_ptr=topValStk;
225
226 topValStk = topValStk->next;
227 if (v_ptr != NULL) {
228 v_ptr->vtype = val_ptr->v.vtype;
229 if (v_ptr->vtype == INT_VAL) {
230 v_ptr->val.i = val_ptr->v.val.i;
231 } else {
232 v_ptr->val.d = val_ptr->v.val.d;
233 }
234 }
235 free(val_ptr);
236 }
237
CleanUpExpr()238 void CleanUpExpr()
239 {
240 if (pszCurExpr != NULL) { free(pszCurExpr); pszCurExpr = NULL; }
241 if (pszExpr != NULL) { free(pszExpr); pszExpr = NULL; }
242 while (topOpStk != NULL) PopOpStk();
243 while (topValStk != NULL) PopValStk(NULL);
244 }
245
ExprAtomType(expr)246 int ExprAtomType(expr)
247 char *expr;
248 {
249 char *dup_str, *c_ptr;
250 int rc=INVALID;
251
252 UtilTrimBlanks(expr);
253 if (*expr == '\0') return NULL_VAL;
254
255 dup_str = UtilStrDup(expr);
256 if (dup_str == NULL) { FailAllocMessage(); return INVALID; }
257
258 c_ptr = dup_str;
259 if (*c_ptr == '-') c_ptr++;
260 /* do not translate -- program constants */
261 if (strtok(c_ptr, "0123456789") == NULL) rc = INT_VAL;
262 free(dup_str);
263 if (rc != INVALID) return rc;
264
265 dup_str = UtilStrDup(expr);
266 if (dup_str == NULL) { FailAllocMessage(); return INVALID; }
267
268 c_ptr = dup_str;
269 if (*c_ptr == '-') c_ptr++;
270 /* do not translate -- program constants */
271 rc = (strtok(c_ptr, ".0123456789") == NULL ? DBL_VAL : STR_VAL);
272 free(dup_str);
273 return rc;
274 }
275
276 static
EvalEquality(op_code,v,result_ptr)277 int EvalEquality(op_code, v, result_ptr)
278 int op_code;
279 struct VRec *v, *result_ptr;
280 {
281 int equal=TRUE;
282
283 if (!(((v[1].vtype == INT_VAL || v[1].vtype == DBL_VAL) &&
284 (v[0].vtype == INT_VAL || v[0].vtype == DBL_VAL)) ||
285 ((v[1].vtype == NULL_VAL || v[1].vtype == STR_VAL) &&
286 (v[0].vtype == NULL_VAL || v[0].vtype == STR_VAL)))) {
287 result_ptr->vtype = INT_VAL;
288 switch (op_code) {
289 case OP_EQ: result_ptr->val.i = FALSE; break;
290 case OP_NE: result_ptr->val.i = TRUE; break;
291 }
292 return TRUE;
293 }
294 switch (v[1].vtype) {
295 case INT_VAL:
296 switch (v[0].vtype) {
297 case INT_VAL: equal = (v[1].val.i == v[0].val.i); break;
298 case DBL_VAL:
299 equal = (fabs(((double)v[1].val.i)-v[0].val.d) < EQ_TOL);
300 break;
301 }
302 break;
303 case DBL_VAL:
304 switch (v[0].vtype) {
305 case INT_VAL:
306 equal = (fabs(v[1].val.d-((double)v[0].val.i)) < EQ_TOL);
307 break;
308 case DBL_VAL:
309 equal = (fabs(v[1].val.d-v[0].val.d) < EQ_TOL);
310 break;
311 }
312 break;
313 case NULL_VAL:
314 switch (v[0].vtype) {
315 case NULL_VAL: equal = TRUE; break;
316 case STR_VAL: equal = (*v[0].val.s == '\0'); break;
317 }
318 case STR_VAL:
319 switch (v[0].vtype) {
320 case NULL_VAL: equal = (*v[1].val.s == '\0'); break;
321 case STR_VAL:
322 equal = (strcmp(v[1].val.s, v[0].val.s) == 0);
323 break;
324 }
325 break;
326 }
327 result_ptr->vtype = INT_VAL;
328 switch (op_code) {
329 case OP_EQ: result_ptr->val.i = equal; break;
330 case OP_NE: result_ptr->val.i = (!equal); break;
331 }
332 return TRUE;
333 }
334
335 static
EvalInequality(op_code,v,result_ptr)336 int EvalInequality(op_code, v, result_ptr)
337 int op_code;
338 struct VRec *v, *result_ptr;
339 {
340 int equal=TRUE, greater=FALSE;
341
342 if (!(((v[1].vtype == INT_VAL || v[1].vtype == DBL_VAL) &&
343 (v[0].vtype == INT_VAL || v[0].vtype == DBL_VAL)) ||
344 ((v[1].vtype == NULL_VAL || v[1].vtype == STR_VAL) &&
345 (v[0].vtype == NULL_VAL || v[0].vtype == STR_VAL)))) {
346 return FALSE;
347 }
348 switch (v[1].vtype) {
349 case INT_VAL:
350 switch (v[0].vtype) {
351 case INT_VAL:
352 equal = (v[1].val.i == v[0].val.i);
353 if (!equal) {
354 greater = (v[1].val.i > v[0].val.i);
355 }
356 break;
357 case DBL_VAL:
358 equal = (fabs(((double)v[1].val.i)-v[0].val.d) < EQ_TOL);
359 if (!equal) {
360 greater = (((double)v[1].val.i) > v[0].val.d);
361 }
362 break;
363 }
364 break;
365 case DBL_VAL:
366 switch (v[0].vtype) {
367 case INT_VAL:
368 equal = (fabs(v[1].val.d-((double)v[0].val.i)) < EQ_TOL);
369 if (!equal) {
370 greater = (v[1].val.d > ((double)v[0].val.i));
371 }
372 break;
373 case DBL_VAL:
374 equal = (fabs(v[1].val.d-v[0].val.d) < EQ_TOL);
375 if (!equal) {
376 greater = (v[1].val.d > v[0].val.d);
377 }
378 break;
379 }
380 break;
381 case NULL_VAL:
382 switch (v[0].vtype) {
383 case NULL_VAL:
384 equal = TRUE;
385 break;
386 case STR_VAL:
387 equal = (*v[0].val.s == '\0');
388 if (!equal) {
389 greater = FALSE;
390 }
391 break;
392 }
393 case STR_VAL:
394 switch (v[0].vtype) {
395 case NULL_VAL:
396 equal = (*v[1].val.s == '\0');
397 if (!equal) {
398 greater = TRUE;
399 }
400 break;
401 case STR_VAL:
402 equal = strcmp(v[1].val.s, v[0].val.s);
403 if (equal != 0) {
404 greater = (equal > 0);
405 equal = FALSE;
406 } else {
407 equal = TRUE;
408 }
409 break;
410 }
411 break;
412 }
413 result_ptr->vtype = INT_VAL;
414 switch (op_code) {
415 case OP_GT: result_ptr->val.i = ((!equal) && greater); break;
416 case OP_LT: result_ptr->val.i = ((!equal) && (!greater)); break;
417 case OP_GE: result_ptr->val.i = (equal || greater); break;
418 case OP_LE: result_ptr->val.i = (equal || (!greater)); break;
419 }
420 return TRUE;
421 }
422
423 static
EvalMod(left,right)424 int EvalMod(left, right)
425 int left, right;
426 {
427 return (left-(right*((int)(left/right))));
428 }
429
430 static
MultipleOf(left,right)431 int MultipleOf(left, right)
432 double left, right;
433 {
434 double dmod=(left-(right*((int)(left/right))));
435
436 if (fabs(dmod) < EQ_TOL) return TRUE;
437 return FALSE;
438 }
439
440 static
EvalArithmaticOp(op_code,op_str,v,result_ptr)441 int EvalArithmaticOp(op_code, op_str, v, result_ptr)
442 int op_code;
443 char *op_str;
444 struct VRec *v, *result_ptr;
445 {
446 int left_ival, right_ival;
447 double left_dval, right_dval;
448
449 if (!((v[1].vtype == INT_VAL || v[1].vtype == DBL_VAL) &&
450 (v[0].vtype == INT_VAL || v[0].vtype == DBL_VAL))) {
451 return BadOperandType(op_str);
452 }
453 left_ival = right_ival = 0;
454 left_dval = right_dval = (double)0.0;
455 switch (v[1].vtype) {
456 case INT_VAL:
457 switch (v[0].vtype) {
458 case INT_VAL:
459 switch (op_code) {
460 case OP_ADD:
461 result_ptr->vtype = INT_VAL;
462 result_ptr->val.i = v[1].val.i + v[0].val.i;
463 break;
464 case OP_SUB:
465 result_ptr->vtype = INT_VAL;
466 result_ptr->val.i = v[1].val.i - v[0].val.i;
467 break;
468 case OP_MUL:
469 result_ptr->vtype = INT_VAL;
470 result_ptr->val.i = v[1].val.i * v[0].val.i;
471 break;
472 case OP_DIV:
473 if (v[0].val.i == 0) { DivByZero(op_str); return FALSE; }
474 if (EvalMod(v[1].val.i, v[0].val.i) == 0) {
475 result_ptr->vtype = INT_VAL;
476 result_ptr->val.i = v[1].val.i / v[0].val.i;
477 } else {
478 result_ptr->vtype = DBL_VAL;
479 result_ptr->val.d = ((double)v[1].val.i) / ((double)v[0].val.i);
480 }
481 break;
482 case OP_INTDIV:
483 if (v[0].val.i == 0) { DivByZero(op_str); return FALSE; }
484 result_ptr->vtype = INT_VAL;
485 result_ptr->val.i = v[1].val.i / v[0].val.i;
486 break;
487 case OP_MOD:
488 if (v[0].val.i == 0) { DivByZero(op_str); return FALSE; }
489 result_ptr->vtype = INT_VAL;
490 result_ptr->val.i = EvalMod(v[1].val.i, v[0].val.i);
491 break;
492 }
493 break;
494 case DBL_VAL:
495 /* int op double */
496 switch (op_code) {
497 case OP_ADD:
498 result_ptr->vtype = DBL_VAL;
499 result_ptr->val.d = ((double)v[1].val.i) + v[0].val.d;
500 break;
501 case OP_SUB:
502 result_ptr->vtype = DBL_VAL;
503 result_ptr->val.d = ((double)v[1].val.i) - v[0].val.d;
504 break;
505 case OP_MUL:
506 result_ptr->vtype = DBL_VAL;
507 result_ptr->val.d = ((double)v[1].val.i) * v[0].val.d;
508 break;
509 case OP_DIV:
510 if (fabs(v[0].val.d) < EQ_TOL) { DivByZero(op_str); return FALSE; }
511 result_ptr->vtype = DBL_VAL;
512 result_ptr->val.d = ((double)v[1].val.i) / v[0].val.d;
513 break;
514 case OP_INTDIV:
515 if (fabs(v[0].val.d) < EQ_TOL) { DivByZero(op_str); return FALSE; }
516 result_ptr->vtype = INT_VAL;
517 result_ptr->val.i = (int)(((double)v[1].val.i) / v[0].val.d);
518 break;
519 case OP_MOD:
520 return BadOperandType(op_str);
521 }
522 break;
523 }
524 break;
525 case DBL_VAL:
526 switch (v[0].vtype) {
527 case INT_VAL:
528 /* double op int */
529 switch (op_code) {
530 case OP_ADD:
531 result_ptr->vtype = DBL_VAL;
532 result_ptr->val.d = v[1].val.d + ((double)v[0].val.i);
533 break;
534 case OP_SUB:
535 result_ptr->vtype = DBL_VAL;
536 result_ptr->val.d = v[1].val.d - ((double)v[0].val.i);
537 break;
538 case OP_MUL:
539 result_ptr->vtype = DBL_VAL;
540 result_ptr->val.d = v[1].val.d * ((double)v[0].val.i);
541 break;
542 case OP_DIV:
543 if (v[0].val.i == 0) { DivByZero(op_str); return FALSE; }
544 result_ptr->vtype = DBL_VAL;
545 result_ptr->val.d = v[1].val.d / ((double)v[0].val.i);
546 break;
547 case OP_INTDIV:
548 if (v[0].val.i == 0) { DivByZero(op_str); return FALSE; }
549 result_ptr->vtype = INT_VAL;
550 result_ptr->val.i = (int)(v[1].val.d / ((double)v[0].val.i));
551 break;
552 case OP_MOD:
553 return BadOperandType(op_str);
554 }
555 break;
556 case DBL_VAL:
557 switch (op_code) {
558 case OP_ADD:
559 result_ptr->vtype = DBL_VAL;
560 result_ptr->val.d = v[1].val.d + v[0].val.d;
561 break;
562 case OP_SUB:
563 result_ptr->vtype = DBL_VAL;
564 result_ptr->val.d = v[1].val.d - v[0].val.d;
565 break;
566 case OP_MUL:
567 result_ptr->vtype = DBL_VAL;
568 result_ptr->val.d = v[1].val.d * v[0].val.d;
569 break;
570 case OP_DIV:
571 if (fabs(v[0].val.d) < EQ_TOL) { DivByZero(op_str); return FALSE; }
572 if (MultipleOf(v[1].val.d, v[0].val.d)) {
573 result_ptr->vtype = INT_VAL;
574 result_ptr->val.i = round(v[1].val.d / v[0].val.d);
575 } else {
576 result_ptr->vtype = DBL_VAL;
577 result_ptr->val.d = v[1].val.d / v[0].val.d;
578 }
579 break;
580 case OP_INTDIV:
581 if (fabs(v[0].val.d) < EQ_TOL) { DivByZero(op_str); return FALSE; }
582 result_ptr->vtype = INT_VAL;
583 result_ptr->val.i = (int)(v[1].val.d / v[0].val.d);
584 break;
585 case OP_MOD:
586 return BadOperandType(op_str);
587 }
588 break;
589 }
590 break;
591 }
592 return TRUE;
593 }
594
595 static
Operate()596 int Operate()
597 {
598 register int i;
599 int arity, op_code;
600 struct VRec v[3], result;
601
602 if (topOpStk == NULL) {
603 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_EMPTY_OP_STACK),
604 pszCurExpr);
605 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
606 return FALSE;
607 }
608 op_code = PopOpStk();
609 arity = OpArity(op_code);
610 if (arity == INVALID) return TRUE;
611
612 for (i=0; i < 3; i++) memset(&v[i], 0, sizeof(struct VRec));
613 memset(&result, 0, sizeof(struct VRec));
614
615 for (i=0; i < arity; i++) {
616 if (topValStk == NULL) {
617 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_EMPTY_OP_STACK),
618 pszCurExpr);
619 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
620 return FALSE;
621 }
622 PopValStk(&v[i]);
623 }
624 /* do not translate -- program constants */
625 switch (op_code) {
626 case OP_IFTHEN:
627 if (v[2].vtype != INT_VAL) return BadOperandType("?");
628 result.vtype = (v[2].val.i ? v[1].vtype : v[0].vtype);
629 switch (result.vtype) {
630 case NULL_VAL: return BadOperandType("?");
631 case INT_VAL:
632 result.val.i = (v[2].val.i ? v[1].val.i : v[0].val.i);
633 break;
634 case DBL_VAL:
635 result.val.d = (v[2].val.d ? v[1].val.d : v[0].val.d);
636 break;
637 case STR_VAL: return BadOperandType("?");
638 }
639 break;
640 case OP_ELSE: break;
641 case OP_OR:
642 if (v[1].vtype != INT_VAL || v[0].vtype != INT_VAL) {
643 return BadOperandType("||");
644 }
645 result.vtype = INT_VAL;
646 result.val.i = (v[1].val.i || v[0].val.i);
647 break;
648 case OP_AND:
649 if (v[1].vtype != INT_VAL || v[0].vtype != INT_VAL) {
650 return BadOperandType("&&");
651 }
652 result.vtype = INT_VAL;
653 result.val.i = (v[1].val.i && v[0].val.i);
654 break;
655 case OP_BIT_OR:
656 if (v[1].vtype != INT_VAL || v[0].vtype != INT_VAL) {
657 return BadOperandType("|");
658 }
659 result.vtype = INT_VAL;
660 result.val.i = (v[1].val.i | v[0].val.i);
661 break;
662 case OP_BIT_XOR:
663 if (v[1].vtype != INT_VAL || v[0].vtype != INT_VAL) {
664 return BadOperandType("^");
665 }
666 result.vtype = INT_VAL;
667 result.val.i = (v[1].val.i ^ v[0].val.i);
668 break;
669 case OP_BIT_AND:
670 if (v[1].vtype != INT_VAL || v[0].vtype != INT_VAL) {
671 return BadOperandType("&");
672 }
673 result.vtype = INT_VAL;
674 result.val.i = (v[1].val.i & v[0].val.i);
675 break;
676 case OP_EQ:
677 if (!EvalEquality(OP_EQ, v, &result)) {
678 return BadOperandType("==");
679 }
680 break;
681 case OP_NE:
682 if (!EvalEquality(OP_NE, v, &result)) {
683 return BadOperandType("!=");
684 }
685 break;
686 case OP_GT:
687 if (!EvalInequality(OP_GT, v, &result)) {
688 return BadOperandType(">");
689 }
690 break;
691 case OP_LT:
692 if (!EvalInequality(OP_LT, v, &result)) {
693 return BadOperandType("<");
694 }
695 break;
696 case OP_GE:
697 if (!EvalInequality(OP_GE, v, &result)) {
698 return BadOperandType(">=");
699 }
700 break;
701 case OP_LE:
702 if (!EvalInequality(OP_LE, v, &result)) {
703 return BadOperandType("<=");
704 }
705 break;
706 case OP_SHIFT_LEFT:
707 if (v[1].vtype != INT_VAL || v[0].vtype != INT_VAL) {
708 return BadOperandType("<<");
709 }
710 result.vtype = INT_VAL;
711 result.val.i = (v[1].val.i << v[0].val.i);
712 break;
713 case OP_SHIFT_RIGHT:
714 if (v[1].vtype != INT_VAL || v[0].vtype != INT_VAL) {
715 return BadOperandType(">>");
716 }
717 result.vtype = INT_VAL;
718 result.val.i = (v[1].val.i >> v[0].val.i);
719 break;
720 case OP_ADD:
721 if (!EvalArithmaticOp(OP_ADD, "+", v, &result)) {
722 return FALSE;
723 }
724 break;
725 case OP_SUB:
726 if (!EvalArithmaticOp(OP_SUB, "-", v, &result)) {
727 return FALSE;
728 }
729 break;
730 case OP_MUL:
731 if (!EvalArithmaticOp(OP_MUL, "*", v, &result)) {
732 return FALSE;
733 }
734 break;
735 case OP_DIV:
736 if (!EvalArithmaticOp(OP_DIV, "/", v, &result)) {
737 return FALSE;
738 }
739 break;
740 case OP_INTDIV:
741 if (!EvalArithmaticOp(OP_INTDIV, "//", v, &result)) {
742 return FALSE;
743 }
744 break;
745 case OP_MOD:
746 if (!EvalArithmaticOp(OP_MOD, "%", v, &result)) {
747 return FALSE;
748 }
749 break;
750 case OP_NOT:
751 if (v[0].vtype != INT_VAL) {
752 return BadOperandType("!");
753 }
754 result.vtype = INT_VAL;
755 result.val.i = (v[0].val.i == 0);
756 break;
757 case OP_BIT_NOT:
758 if (v[0].vtype != INT_VAL) {
759 return BadOperandType("~");
760 }
761 result.vtype = INT_VAL;
762 result.val.i = (~v[0].val.i);
763 break;
764 case OP_CLOSE:
765 case OP_OPEN:
766 break;
767 }
768 for (i=0; i < arity; i++) {
769 if (v[i].vtype == STR_VAL && v[i].val.s != NULL) {
770 free(v[i].val.s);
771 v[i].val.s = NULL;
772 }
773 }
774 return ValPush(&result);
775 }
776
777 static char szNumericChars[]=".0123456789";
778
779 static
ParseForNumericVal(ppsz_token,v)780 int ParseForNumericVal(ppsz_token, v)
781 char **ppsz_token;
782 struct VRec *v;
783 {
784 int seen_dot=FALSE;
785 char saved_ch, *token=(*ppsz_token);
786
787 for ( ; **ppsz_token != '\0'; (*ppsz_token)++) {
788 char *c_ptr=strchr(szNumericChars, **ppsz_token);
789
790 if (c_ptr == NULL) break;
791 if (c_ptr == szNumericChars) {
792 if (seen_dot) break;
793 seen_dot = TRUE;
794 }
795 }
796 memset(v, 0, sizeof(struct VRec));
797 saved_ch = **ppsz_token;
798 **ppsz_token = '\0';
799 if (seen_dot) {
800 v->vtype = DBL_VAL;
801 if (sscanf(token, "%lf", &(v->val.d)) != 1) {
802 **ppsz_token = saved_ch;
803 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_BAD_NUM_VALUE),
804 pszCurExpr, token);
805 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
806 return FALSE;
807 }
808 } else {
809 v->vtype = INT_VAL;
810 if (sscanf(token, "%d", &(v->val.i)) != 1) {
811 **ppsz_token = saved_ch;
812 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_BAD_NUM_VALUE),
813 pszCurExpr, token);
814 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
815 return FALSE;
816 }
817 }
818 **ppsz_token = saved_ch;
819 return TRUE;
820 }
821
822 static
ParseForStringVal(ppsz_token,v)823 int ParseForStringVal(ppsz_token, v)
824 char **ppsz_token;
825 struct VRec *v;
826 {
827 char *token=(*ppsz_token);
828
829 for ((*ppsz_token)++; **ppsz_token != '\0'; (*ppsz_token)++) {
830 if (**ppsz_token == '\\') {
831 (*ppsz_token)++;
832 } else if (**ppsz_token == '"') {
833 break;
834 }
835 }
836 if (**ppsz_token == '\0') {
837 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_BAD_STR_VALUE),
838 pszCurExpr, token);
839 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
840 return FALSE;
841 }
842 memset(v, 0, sizeof(struct VRec));
843 **ppsz_token = '\0';
844 v->vtype = STR_VAL;
845 v->val.s = UtilStrDup(&token[1]);
846 **ppsz_token = '"';
847 (*ppsz_token)++;
848 if (v->val.s == NULL) {
849 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_BAD_STR_VALUE),
850 pszCurExpr, token);
851 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
852 return FALSE;
853 }
854 return TRUE;
855 }
856
857 static
ParseForIDVal(ppsz_token,v)858 int ParseForIDVal(ppsz_token, v)
859 char **ppsz_token;
860 struct VRec *v;
861 {
862 char *token=(*ppsz_token), saved_ch;
863
864 for ( ; **ppsz_token != '\0'; (*ppsz_token)++) {
865 if (!(**ppsz_token == '_' ||
866 (**ppsz_token >= 'a' && **ppsz_token <= 'z') ||
867 (**ppsz_token >= 'A' && **ppsz_token <= 'Z') ||
868 (**ppsz_token >= '0' && **ppsz_token <= '9'))) {
869 break;
870 }
871 }
872 memset(v, 0, sizeof(struct VRec));
873 saved_ch = **ppsz_token;
874 **ppsz_token = '\0';
875 v->vtype = STR_VAL;
876 v->val.s = UtilStrDup(token);
877 **ppsz_token = saved_ch;
878 if (v->val.s == NULL) {
879 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_BAD_IDENTIFIER),
880 pszCurExpr, token);
881 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
882 return FALSE;
883 }
884 return TRUE;
885 }
886
887 #ifdef NOT_DEFINED
888 #ifdef _TGIF_DBG /* debug, do not translate */
889 static char *opName[] = {
890 "BEGIN", "?", ":", "||", "&&", "|", "^", "&", "==", "!=", ">", "<", ">=",
891 "<=", "<<", ">>", "+", "-", "*", "/", "//", "%", "!", "~", ")", "(", "END",
892 NULL
893 };
894 #define MAXOP 27
895
896 static
DebugOpStk()897 void DebugOpStk()
898 {
899 struct OpRec *op_ptr=NULL;
900
901 if (gnExprDebug) { }
902 fprintf(stderr, "top of op stack -->\n");
903 for (op_ptr=topOpStk; op_ptr != NULL; op_ptr=op_ptr->next) {
904 fprintf(stderr, " | %2s, %2d |\n",
905 opName[op_ptr->op_code], OpPrec(op_ptr->op_code));
906 }
907 fprintf(stderr, " |________|\n");
908 }
909 #endif /* _TGIF_DBG */
910
911 #ifdef _TGIF_DBG /* debug, do not translate */
912 static
DebugValStk()913 void DebugValStk()
914 {
915 struct ValRec *v_ptr=NULL;
916
917 if (gnExprDebug) { }
918 fprintf(stderr, "top of val stack ->\n");
919 for (v_ptr=topValStk; v_ptr != NULL; v_ptr=v_ptr->next) {
920 switch (v_ptr->v.vtype) {
921 case NULL_VAL:
922 fprintf(stderr, " | NULL\n");
923 break;
924 case INT_VAL:
925 fprintf(stderr, " | INT, %1d\n",
926 v_ptr->v.val.i);
927 break;
928 case DBL_VAL:
929 fprintf(stderr, " | DBL, %.3f\n",
930 (float)(v_ptr->v.val.d));
931 break;
932 case STR_VAL:
933 fprintf(stderr, " | STR, \"%s\"\n",
934 (v_ptr->v.val.s==NULL ? "NULL" : v_ptr->v.val.s));
935 break;
936 }
937 }
938 fprintf(stderr, " |________...\n");
939 }
940 #endif /* _TGIF_DBG */
941 #endif /* NOT_DEFINED */
942
943 static
ProcessOp(prec)944 int ProcessOp(prec)
945 int prec;
946 {
947 while (topOpStk != NULL && prec <= topOpStk->prec) {
948 if (!Operate()) {
949 return FALSE;
950 }
951 }
952 return TRUE;
953 }
954
EvalExpr(orig_expr,v_ptr)955 int EvalExpr(orig_expr, v_ptr)
956 char *orig_expr;
957 struct VRec *v_ptr;
958 {
959 int cur_depth=0, ok=TRUE, prev_token_is_op=TRUE;
960 char *token;
961
962 CleanUpExpr();
963 pszCurExpr = UtilStrDup(orig_expr);
964 if (pszCurExpr == NULL) return FailAllocMessage();
965 UtilTrimBlanks(pszCurExpr);
966 if (*pszCurExpr == '\0') {
967 v_ptr->vtype = NULL_VAL;
968 return TRUE;
969 }
970 memset(v_ptr, 0, sizeof(struct VRec));
971 pszExpr = UtilStrDup(pszCurExpr);
972 if (pszExpr == NULL) return FailAllocMessage();
973 if (!OpPush(OP_BEGIN, cur_depth)) return FALSE;
974 token = pszExpr;
975 while (ok && *token != '\0') {
976 struct VRec v;
977 int op_code=INVALID;
978
979 switch (*token) {
980 case ' ':
981 case '\t':
982 case '\n':
983 case '\r':
984 token++;
985 break;
986 case '-':
987 if (!prev_token_is_op || strchr(szNumericChars, token[1]) == NULL) {
988 op_code = OP_SUB;
989 token++;
990 } else {
991 char *new_token=(&token[1]);
992
993 if (ParseForNumericVal(&new_token, &v)) {
994 if (v.vtype == INT_VAL) {
995 v.val.i = (-v.val.i);
996 } else {
997 v.val.d = (-v.val.d);
998 }
999 if (!ValPush(&v)) {
1000 ok = FALSE;
1001 } else {
1002 prev_token_is_op = FALSE;
1003 }
1004 } else {
1005 ok = FALSE;
1006 }
1007 token = new_token;
1008 }
1009 break;
1010 case '.':
1011 case '0':
1012 case '1':
1013 case '2':
1014 case '3':
1015 case '4':
1016 case '5':
1017 case '6':
1018 case '7':
1019 case '8':
1020 case '9':
1021 if (ParseForNumericVal(&token, &v)) {
1022 if (!ValPush(&v)) {
1023 ok = FALSE;
1024 } else {
1025 prev_token_is_op = FALSE;
1026 }
1027 } else {
1028 ok = FALSE;
1029 }
1030 break;
1031 case '"':
1032 if (ParseForStringVal(&token, &v)) {
1033 if (!ValPush(&v)) {
1034 ok = FALSE;
1035 } else {
1036 prev_token_is_op = FALSE;
1037 }
1038 } else {
1039 ok = FALSE;
1040 }
1041 break;
1042 case '?': op_code = OP_IFTHEN; token++; break;
1043 case ':': op_code = OP_ELSE; token++; break;
1044 case '|':
1045 if (token[1] == '|') {
1046 op_code = OP_BIT_OR;
1047 token = &token[2];
1048 } else {
1049 op_code = OP_OR;
1050 token++;
1051 }
1052 break;
1053 case '^': op_code = OP_BIT_XOR; token++; break;
1054 case '&':
1055 if (token[1] == '&') {
1056 op_code = OP_BIT_AND;
1057 token = &token[2];
1058 } else {
1059 op_code = OP_AND;
1060 token++;
1061 }
1062 break;
1063 case '=':
1064 if (token[1] == '=') {
1065 op_code = OP_EQ;
1066 token = &token[2];
1067 } else {
1068 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_BAD_OPERATOR),
1069 pszCurExpr, "=");
1070 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1071 ok = FALSE;
1072 }
1073 break;
1074 case '>':
1075 switch (token[1]) {
1076 case '=': op_code = OP_GE; token = &token[2]; break;
1077 case '>': op_code = OP_SHIFT_RIGHT; token = &token[2]; break;
1078 default: op_code = OP_GT; token++; break;
1079 }
1080 break;
1081 case '<':
1082 switch (token[1]) {
1083 case '=': op_code = OP_LE; token = &token[2]; break;
1084 case '<': op_code = OP_SHIFT_LEFT; token = &token[2]; break;
1085 default: op_code = OP_LT; token++; break;
1086 }
1087 break;
1088 case '+': op_code = OP_ADD; token++; break;
1089 case '*': op_code = OP_MUL; token++; break;
1090 case '/':
1091 if (token[1] == '/') {
1092 op_code = OP_INTDIV;
1093 token = &token[2];
1094 } else if (token[1] == '*') {
1095 for (token=(&token[2]); *token != '\0'; token++) {
1096 if (*token == '*' && token[1] == '/') {
1097 token = &token[2];
1098 break;
1099 }
1100 }
1101 } else {
1102 op_code = OP_DIV;
1103 token++;
1104 }
1105 break;
1106 case '%': op_code = OP_MOD; token++; break;
1107 case '!':
1108 if (token[1] == '=') {
1109 op_code = OP_NE;
1110 token = &token[2];
1111 } else {
1112 op_code = OP_NOT;
1113 token++;
1114 }
1115 break;
1116 case '~': op_code = OP_BIT_NOT; token++; break;
1117 case ')': op_code = OP_CLOSE; token++; break;
1118 case '(': op_code = OP_OPEN; token++; break;
1119 default:
1120 if (*token == '_' || (*token >= 'a' && *token <= 'z') ||
1121 (*token >= 'A' && *token <= 'Z')) {
1122 if (ParseForIDVal(&token, &v)) {
1123 /*
1124 * if (*token == '(') {
1125 * push a function on the stack!
1126 * token++;
1127 * }
1128 */
1129 if (!ValPush(&v)) {
1130 ok = FALSE;
1131 } else {
1132 prev_token_is_op = FALSE;
1133 }
1134 } else {
1135 ok = FALSE;
1136 }
1137 } else {
1138 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_BAD_IDENTIFIER),
1139 pszCurExpr, token);
1140 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1141 ok = FALSE;
1142 }
1143 break;
1144 }
1145 if (!ok) break;
1146 if (op_code != INVALID) {
1147 switch (op_code) {
1148 case OP_CLOSE:
1149 if (cur_depth == 0) {
1150 sprintf(gszMsgBox,
1151 TgLoadString(STID_ILLEGAL_EXPR_TOO_MANY_SYMBOL),
1152 pszCurExpr, ')');
1153 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1154 ok = FALSE;
1155 } else {
1156 cur_depth -= MAX_OP_PREC;
1157 if (!ProcessOp(OpPrec(op_code)+cur_depth)) {
1158 ok = FALSE;
1159 }
1160 }
1161 break;
1162 case OP_OPEN: cur_depth += MAX_OP_PREC; break;
1163 default:
1164 if (ProcessOp(OpPrec(op_code)+cur_depth)) {
1165 if (!OpPush(op_code, cur_depth)) {
1166 ok = FALSE;
1167 }
1168 } else {
1169 ok = FALSE;
1170 }
1171 break;
1172 }
1173 prev_token_is_op = TRUE;
1174 }
1175 }
1176 if (ok) {
1177 if (cur_depth != 0) {
1178 sprintf(gszMsgBox, TgLoadString(STID_ILLEGAL_EXPR_TOO_MANY_SYMBOL),
1179 pszCurExpr, '(');
1180 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1181 ok = FALSE;
1182 } else if (!ProcessOp((-1))) {
1183 ok = FALSE;
1184 } else if (topOpStk != NULL) {
1185 sprintf(gszMsgBox, TgLoadString(STID_ILL_EXPR_OP_STACK_NON_EMPTY),
1186 pszCurExpr);
1187 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1188 ok = FALSE;
1189 } else if (topValStk == NULL) {
1190 sprintf(gszMsgBox, TgLoadString(STID_ILL_EXPR_VAL_STACK_NON_EMPTY),
1191 pszCurExpr);
1192 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1193 ok = FALSE;
1194 } else if (topValStk->next != NULL) {
1195 sprintf(gszMsgBox, TgLoadString(STID_ILL_EXPR_TOO_MANY_VALS_LEFT),
1196 pszCurExpr);
1197 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1198 ok = FALSE;
1199 } else {
1200 memcpy(v_ptr, &topValStk->v, sizeof(struct VRec));
1201 }
1202 }
1203 return ok;
1204 }
1205
1206