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