1 /***********************************************************************
2  *                                                                      *
3  *               This software is part of the ast package               *
4  *          Copyright (c) 1982-2014 AT&T Intellectual Property          *
5  *                      and is licensed under the                       *
6  *                 Eclipse Public License, Version 1.0                  *
7  *                    by AT&T Intellectual Property                     *
8  *                                                                      *
9  *                A copy of the License is available at                 *
10  *          http://www.eclipse.org/org/documents/epl-v10.html           *
11  *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12  *                                                                      *
13  *              Information and Software Systems Research               *
14  *                            AT&T Research                             *
15  *                           Florham Park NJ                            *
16  *                                                                      *
17  *                    David Korn <dgkorn@gmail.com>                     *
18  *                                                                      *
19  ***********************************************************************/
20 //
21 // D. G. Korn
22 // AT&T Labs
23 //
24 // arithmetic expression evaluator
25 //
26 // This version compiles the expression onto a stack and has a separate executor.
27 //
28 #include "config_ast.h"  // IWYU pragma: keep
29 
30 #include <limits.h>
31 #include <math.h>
32 #include <stdbool.h>
33 #include <string.h>
34 
35 #include "ast.h"
36 #include "ast_float.h"
37 #include "defs.h"
38 #include "error.h"
39 #include "name.h"
40 #include "sfio.h"
41 #include "stk.h"
42 #include "streval.h"
43 
44 #ifndef ERROR_dictionary
45 #define ERROR_dictionary(s) (s)
46 #endif
47 
48 #define MAXLEVEL 1024
49 #define SMALL_STACK 12
50 
51 //
52 // The following are used with tokenbits() macro.
53 //
54 #define T_OP 0x3f       // mask for operator number
55 #define T_BINARY 0x40   // binary operators
56 #define T_NOFLOAT 0x80  // non floating point operator
57 #define A_LVALUE (2 * MAXPREC + 2)
58 
59 #define pow2size(x) \
60     ((x) <= 2 ? 2 : (x) <= 4 ? 4 : (x) <= 8 ? 8 : (x) <= 16 ? 16 : (x) <= 32 ? 32 : 64)
61 #define round(x, size) (((x) + (size)-1) & ~((size)-1))
62 #define stkpush(stk, v, val, type)                                 \
63     ((((v)->offset = round(stktell(stk), pow2size(sizeof(type)))), \
64       stkseek(stk, (v)->offset + sizeof(type)), *((type *)stkptr(stk, (v)->offset)) = (val)))
65 #define stkoffset(stk, v) ((v)->offset)
66 #define roundptr(ep, cp, type) \
67     (((unsigned char *)(ep)) + round(cp - ((unsigned char *)(ep)), pow2size(sizeof(type))))
68 
69 static int level;
70 
71 typedef struct vars {  // vars stacked per invocation
72     Shell_t *shp;
73     const char *expr;     // current expression
74     const char *nextchr;  // next char in current expression
75     const char *errchr;   // next char after error
76     const char *errstr;   // error string
77     struct lval errmsg;   // error message text
78     int offset;           // offset for pushchr macro
79     int staksize;         // current stack size needed
80     int stakmaxsize;      // maximum stack size needed
81     unsigned char paren;  // parenthesis level
82     char infun;           // incremented by comma inside function
83     int emode;
84     Sfdouble_t (*convert)(const char **, struct lval *, int, Sfdouble_t);
85 } vars_t;
86 
87 typedef Sfdouble_t (*Math_f)(Sfdouble_t, ...);
88 typedef Sfdouble_t (*Math_1f_f)(Sfdouble_t);
89 typedef int (*Math_1i_f)(Sfdouble_t);
90 typedef Sfdouble_t (*Math_2f_f)(Sfdouble_t, Sfdouble_t);
91 typedef Sfdouble_t (*Math_2v_f)(int, Sfdouble_t, Sfdouble_t);
92 typedef Sfdouble_t (*Math_2f_i)(Sfdouble_t, int);
93 typedef int (*Math_2i_f)(Sfdouble_t, Sfdouble_t);
94 typedef Sfdouble_t (*Math_3f_f)(Sfdouble_t, Sfdouble_t, Sfdouble_t);
95 typedef int (*Math_3i_f)(Sfdouble_t, Sfdouble_t, Sfdouble_t);
96 
97 #define getchr(vp) (*(vp)->nextchr++)
98 #define nxtchr(vp) ((vp)->nextchr++)
99 #define peekchr(vp) (*(vp)->nextchr)
100 #define ungetchr(vp) ((vp)->nextchr--)
101 
102 // This is used to convert characters to math expression tokens.
getop(int c)103 static inline int getop(int c) {
104     if (c < sizeof(strval_states)) return strval_states[(c)];
105     switch (c) {
106         case '|': {
107             return A_OR;
108         }
109         case '^': {
110             return A_XOR;
111         }
112         case '~': {
113             return A_TILDE;
114         }
115         default: { return A_REG; }
116     }
117 }
118 
119 #define seterror(v, msg) _seterror(v, ERROR_dictionary(msg))
120 #define ERROR(vp, msg) return seterror((vp), msg)
121 
122 //
123 // Set error message string and return 0.
124 //
_seterror(vars_t * vp,const char * msg)125 static_fn int _seterror(vars_t *vp, const char *msg) {
126     if (!vp->errmsg.value) vp->errmsg.value = (char *)msg;
127     vp->errchr = vp->nextchr;
128     vp->nextchr = "";
129     level = 0;
130     return 0;
131 }
132 
arith_error(const char * message,const char * expr,int mode)133 static_fn void arith_error(const char *message, const char *expr, int mode) {
134     level = 0;
135     mode = (mode & 3) != 0;
136     errormsg(SH_DICT, ERROR_exit(mode), message, expr);
137 }
138 
139 #if _ast_no_um2fm
U2F(Sfulong_t u)140 static_fn Sfdouble_t U2F(Sfulong_t u) {
141     Sflong_t s = u;
142     Sfdouble_t f;
143 
144     if (s >= 0) return s;
145     s = u / 2;
146     f = s;
147     f *= 2;
148     if (u & 1) f++;
149     return f;
150 }
151 #else
152 #define U2F(x) x
153 #endif
154 
array_args(Shell_t * shp,char * tp,int n)155 static_fn void array_args(Shell_t *shp, char *tp, int n) {
156     while (n--) {
157         if (tp[n] == 5) {
158             Namval_t *np = nv_namptr(shp->mathnodes, n);
159             nv_offattr(np, NV_LDOUBLE);
160         }
161     }
162 }
163 
arith_exec(Arith_t * ep)164 Sfdouble_t arith_exec(Arith_t *ep) {
165     Sfdouble_t num = 0, *dp, *sp;
166     unsigned char *cp = ep->code;
167     int c, type = 0;
168     char *tp;
169     Sfdouble_t d, small_stack[SMALL_STACK + 1], arg[9];
170     const char *ptr = "";
171     char *lastval = NULL;
172     int lastsub = 0;
173     struct lval node;
174     Shell_t *shp = ep->shp;
175 
176     memset(&node, 0, sizeof(node));
177     node.shp = shp;
178     node.emode = ep->emode;
179     node.expr = ep->expr;
180     node.elen = ep->elen;
181     if (level++ >= MAXLEVEL) {
182         arith_error(e_recursive, ep->expr, ep->emode);
183         return 0;
184     }
185     if (ep->staksize < SMALL_STACK) {
186         sp = small_stack;
187     } else {
188         sp = stkalloc(shp->stk, ep->staksize * (sizeof(Sfdouble_t) + 1));
189     }
190     tp = (char *)(sp + ep->staksize);
191     tp--, sp--;
192     while ((c = *cp++)) {
193         if (c & T_NOFLOAT) {
194             if (type || ((c & T_BINARY) && (c & T_OP) != A_MOD && tp[-1] == 1)) {
195                 arith_error(e_incompatible, ep->expr, ep->emode);
196             }
197         }
198         switch (c & T_OP) {
199             case A_JMP:
200             case A_JMPZ:
201             case A_JMPNZ: {
202                 c &= T_OP;
203                 cp = roundptr(ep, cp, short);
204                 if ((c == A_JMPZ && num) || (c == A_JMPNZ && !num)) {
205                     cp += sizeof(short);
206                 } else {
207                     cp = (unsigned char *)ep + *((short *)cp);
208                 }
209                 continue;
210             }
211             case A_NOTNOT: {
212                 num = (num != 0);
213                 type = 0;
214                 break;
215             }
216             case A_PLUSPLUS: {
217                 node.nosub = -1;
218                 (*ep->fun)(&ptr, &node, ASSIGN, num + 1);
219                 break;
220             }
221             case A_MINUSMINUS: {
222                 node.nosub = -1;
223                 (*ep->fun)(&ptr, &node, ASSIGN, num - 1);
224                 break;
225             }
226             case A_INCR: {
227                 num = num + 1;
228                 node.nosub = -1;
229                 num = (*ep->fun)(&ptr, &node, ASSIGN, num);
230                 break;
231             }
232             case A_DECR: {
233                 num = num - 1;
234                 node.nosub = -1;
235                 num = (*ep->fun)(&ptr, &node, ASSIGN, num);
236                 break;
237             }
238             case A_SWAP: {
239                 num = sp[-1];
240                 sp[-1] = *sp;
241                 type = tp[-1];
242                 tp[-1] = *tp;
243                 break;
244             }
245             case A_POP: {
246                 sp--;
247                 continue;
248             }
249             case A_ASSIGNOP1: {
250                 node.emode |= ARITH_ASSIGNOP;
251             }
252             // TODO: Determine if this should be FALLTHRU.
253             // FALLTHRU
254             case A_PUSHV: {
255                 cp = roundptr(ep, cp, Sfdouble_t *);
256                 dp = *((Sfdouble_t **)cp);
257                 cp += sizeof(Sfdouble_t *);
258                 c = *(short *)cp;
259                 cp += sizeof(short);
260                 lastval = node.value = (char *)dp;
261                 node.flag = c;
262                 if (node.flag) lastval = NULL;
263                 node.isfloat = 0;
264                 node.level = level;
265                 node.nosub = 0;
266                 node.nextop = *cp;
267                 if (node.nextop == A_JMP) {
268                     node.nextop = ((unsigned char *)ep)[*((short *)roundptr(ep, cp + 1, short))];
269                 }
270                 num = (*ep->fun)(&ptr, &node, VALUE, num);
271                 if (lastval) lastval = node.ovalue;
272                 if (node.emode & ARITH_ASSIGNOP) {
273                     lastsub = node.nosub;
274                     node.nosub = 0;
275                     node.emode &= ~ARITH_ASSIGNOP;
276                 }
277                 if (node.value != (char *)dp) arith_error(node.value, ptr, ep->emode);
278                 *++sp = num;
279                 type = node.isfloat;
280                 if ((d = num) > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX) {
281                     type = TYPE_U;
282                     d -= LDBL_LLONG_MAX;
283                 }
284                 if ((Sflong_t)d != d) type = TYPE_LD;
285                 *++tp = type;
286                 c = 0;
287                 break;
288             }
289             case A_ENUM: {
290                 node.eflag = 1;
291                 continue;
292             }
293             case A_ASSIGNOP: {
294                 node.nosub = lastsub;
295             }
296             // TODO: Determine if this should be FALLTHRU.
297             // FALLTHRU
298             case A_STORE: {
299                 cp = roundptr(ep, cp, Sfdouble_t *);
300                 dp = *((Sfdouble_t **)cp);
301                 cp += sizeof(Sfdouble_t *);
302                 c = *(short *)cp;
303                 if (c < 0) c = 0;
304                 cp += sizeof(short);
305                 node.value = (char *)dp;
306                 node.flag = c;
307                 if (lastval) node.eflag = 1;
308                 node.ptr = NULL;
309                 num = (*ep->fun)(&ptr, &node, ASSIGN, num);
310                 if (lastval && node.ptr) {
311                     Sfdouble_t r;
312                     node.flag = 0;
313                     node.value = lastval;
314                     r = (*ep->fun)(&ptr, &node, VALUE, num);
315                     if (r != num) {
316                         node.flag = c;
317                         node.value = (char *)dp;
318                         num = (*ep->fun)(&ptr, &node, ASSIGN, r);
319                     }
320 
321                 } else if (lastval && num == 0 && sh_isoption(shp, SH_NOUNSET) &&
322                            nv_isnull((Namval_t *)lastval)) {
323                     arith_error((char *)ERROR_dictionary(e_notset), nv_name((Namval_t *)lastval),
324                                 3);
325                 }
326                 lastval = NULL;
327                 c = 0;
328                 break;
329             }
330             case A_PUSHF: {
331                 cp = roundptr(ep, cp, Math_f);
332                 *++sp = (Sfdouble_t)(cp - ep->code);
333                 cp += sizeof(Math_f);
334                 *++tp = *cp++;
335                 node.userfn = 0;
336                 if (*tp > 1) node.userfn = 1;
337                 *tp &= 1;
338                 continue;
339             }
340             case A_PUSHN: {
341                 cp = roundptr(ep, cp, Sfdouble_t);
342                 // cppcheck-suppress invalidPointerCast
343                 num = *((Sfdouble_t *)cp);
344                 cp += sizeof(Sfdouble_t);
345                 *++sp = num;
346                 *++tp = type = *cp++;
347                 break;
348             }
349             case A_NOT: {
350                 type = 0;
351                 num = !num;
352                 break;
353             }
354             case A_UMINUS: {
355                 num = -num;
356                 break;
357             }
358             case A_TILDE: {
359                 num = ~((Sflong_t)(num));
360                 break;
361             }
362             case A_PLUS: {
363                 num += sp[-1];
364                 break;
365             }
366             case A_MINUS: {
367                 num = sp[-1] - num;
368                 break;
369             }
370             case A_TIMES: {
371                 num *= sp[-1];
372                 break;
373             }
374             case A_POW: {
375                 extern Math_f sh_mathstdfun(const char *, size_t, short *);
376                 static Math_2f_f powfn;
377                 if (!powfn) {
378                     powfn = (Math_2f_f)sh_mathstdfun("pow", 3, NULL);
379                     if (!powfn) powfn = (Math_2f_f)pow;
380                 }
381                 num = powfn(sp[-1], num);
382                 break;
383             }
384             case A_MOD: {
385                 if (!(Sflong_t)num) arith_error(e_divzero, ep->expr, ep->emode);
386                 if (type == TYPE_U || tp[-1] == TYPE_U) {
387                     num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num));
388                 } else {
389                     num = (Sflong_t)(sp[-1]) % (Sflong_t)(num);
390                 }
391                 break;
392             }
393             case A_DIV: {
394                 if (type || tp[-1]) {
395                     num = sp[-1] / num;
396                     type = type > tp[-1] ? type : tp[-1];
397                 } else if ((Sfulong_t)(num < 0 ? -num : num) == 0) {
398                     arith_error(e_divzero, ep->expr, ep->emode);
399                 } else if (type == TYPE_U || tp[-1] == TYPE_U) {
400                     num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num));
401                 } else {
402                     Sfdouble_t x = floorl(sp[-1]);
403                     Sfdouble_t y = floorl(num);
404                     num = floorl(x / y);
405                 }
406                 break;
407             }
408             case A_LSHIFT: {
409                 if ((long)num >= CHAR_BIT * sizeof(Sfulong_t)) {
410                     num = 0;
411                 } else if (tp[-1] == TYPE_U) {
412                     num = U2F((Sfulong_t)(sp[-1]) << (long)(num));
413                 } else {
414                     num = (Sflong_t)(sp[-1]) << (long)(num);
415                 }
416                 break;
417             }
418             case A_RSHIFT: {
419                 if ((long)num >= CHAR_BIT * sizeof(Sfulong_t)) {
420                     num = 0;
421                 } else if (tp[-1] == TYPE_U) {
422                     num = U2F((Sfulong_t)(sp[-1]) >> (long)(num));
423                 } else {
424                     num = (Sflong_t)(sp[-1]) >> (long)(num);
425                 }
426                 break;
427             }
428             case A_XOR: {
429                 if (type == TYPE_U || tp[-1] == TYPE_U) {
430                     num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num));
431                 } else {
432                     num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num);
433                 }
434                 break;
435             }
436             case A_OR: {
437                 if (type == TYPE_U || tp[-1] == TYPE_U) {
438                     num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num));
439                 } else {
440                     num = (Sflong_t)(sp[-1]) | (Sflong_t)(num);
441                 }
442                 break;
443             }
444             case A_AND: {
445                 if (type == TYPE_U || tp[-1] == TYPE_U) {
446                     num = U2F((Sfulong_t)(sp[-1]) & (Sfulong_t)(num));
447                 } else {
448                     num = (Sflong_t)(sp[-1]) & (Sflong_t)(num);
449                 }
450                 break;
451             }
452             case A_EQ: {
453                 num = (sp[-1] == num);
454                 type = 0;
455                 break;
456             }
457             case A_NEQ: {
458                 num = (sp[-1] != num);
459                 type = 0;
460                 break;
461             }
462             case A_LE: {
463                 num = (sp[-1] <= num);
464                 type = 0;
465                 break;
466             }
467             case A_GE: {
468                 num = (sp[-1] >= num);
469                 type = 0;
470                 break;
471             }
472             case A_GT: {
473                 num = (sp[-1] > num);
474                 type = 0;
475                 break;
476             }
477             case A_LT: {
478                 num = (sp[-1] < num);
479                 type = 0;
480                 break;
481             }
482             case A_CALL1F: {
483                 sp--, tp--;
484                 Math_1f_f funx = *(Math_1f_f *)(ep->code + (int)(*sp));
485                 type = *tp;
486                 if (c & T_BINARY) {
487                     c &= ~T_BINARY;
488                     arg[0] = num;
489                     arg[1] = 0;
490                     array_args(shp, tp + 1, 1);
491                     num = sh_mathfun(shp, funx, 1, arg);
492                     node.userfn = 0;
493                     break;
494                 }
495                 num = (*funx)(num);
496                 break;
497             }
498             case A_CALL1I: {
499                 sp--, tp--;
500                 type = *tp;
501                 Math_1i_f funx = *((Math_1i_f *)(ep->code + (int)(*sp)));
502                 num = (*funx)(num);
503                 break;
504             }
505             case A_CALL2F: {
506                 sp -= 2, tp -= 2;
507                 type = *tp;
508                 if (c & T_BINARY) {
509                     c &= ~T_BINARY;
510                     arg[0] = sp[1];
511                     arg[1] = num;
512                     arg[2] = 0;
513                     array_args(shp, tp + 1, 2);
514                     Math_2f_i funx = *(Math_2f_i *)(ep->code + (int)(*sp));
515                     num = sh_mathfun(shp, funx, 2, arg);
516                     node.userfn = 0;
517                     break;
518                 }
519                 if (c & T_NOFLOAT) {
520                     Math_2f_i funx = *(Math_2f_i *)(ep->code + (int)(*sp));
521                     num = (*funx)(sp[1], (int)num);
522                 } else {
523                     Math_2f_f funx = *(Math_2f_f *)(ep->code + (int)(*sp));
524                     num = (*funx)(sp[1], num);
525                 }
526                 break;
527             }
528             case A_CALL2V: {
529                 sp -= 2, tp -= 2;
530                 type = tp[1];
531                 Math_2v_f funx = *(Math_2v_f *)(ep->code + (int)(*sp));
532                 num = (*funx)(type - 1, sp[1], num);
533                 break;
534             }
535             case A_CALL2I: {
536                 sp -= 2, tp -= 2;
537                 type = *tp;
538                 Math_2i_f funx = *(Math_2i_f *)(ep->code + (int)(*sp));
539                 num = (*funx)(sp[1], num);
540                 break;
541             }
542             case A_CALL3F: {
543                 sp -= 3, tp -= 3;
544                 Math_3f_f funx = *(Math_3f_f *)(ep->code + (int)(*sp));
545                 type = *tp;
546                 if (c & T_BINARY) {
547                     c &= ~T_BINARY;
548                     arg[0] = sp[1];
549                     arg[1] = sp[2];
550                     arg[2] = num;
551                     arg[3] = 0;
552                     array_args(shp, tp + 1, 3);
553                     num = sh_mathfun(shp, funx, 3, arg);
554                     node.userfn = 0;
555                     break;
556                 }
557                 num = (*funx)(sp[1], sp[2], num);
558                 break;
559             }
560         }
561         if (c) lastval = NULL;
562         if (c & T_BINARY) {
563             node.ptr = NULL;
564             sp--, tp--;
565             if (*tp > type) type = *tp;
566         }
567         *sp = num;
568         *tp = type;
569     }
570     if (level > 0) level--;
571     if (type == 0 && !num) num = 0;
572     return num;
573 }
574 
575 //
576 // This returns operator tokens or A_REG or A_NUM.
577 //
gettok(vars_t * vp)578 static_fn int gettok(vars_t *vp) {
579     int c, op;
580 
581     vp->errchr = vp->nextchr;
582     while (true) {
583         c = getchr(vp);
584         op = getop(c);
585         switch (op) {
586             case 0: {
587                 vp->errchr = vp->nextchr;
588                 break;
589             }
590             case A_EOF: {
591                 vp->nextchr--;
592                 return op;
593             }
594             case A_COMMA: {
595                 if (vp->shp->decomma && (c = peekchr(vp)) >= '0' && c <= '9') {
596                     op = A_DIG;
597                     ungetchr(vp);
598                 }
599                 return op;
600             }
601             case A_DOT: {
602                 if ((c = peekchr(vp)) >= '0' && c <= '9') {
603                     op = A_DIG;
604                 } else {
605                     op = A_REG;
606                 }
607                 ungetchr(vp);
608                 return op;
609             }
610             case A_DIG:
611             case A_REG:
612             case A_LIT: {
613                 ungetchr(vp);
614                 return op;
615             }
616             case A_QUEST: {
617                 if (peekchr(vp) == ':') {
618                     nxtchr(vp);
619                     op = A_QCOLON;
620                 }
621                 return op;
622             }
623             case A_LT:
624             case A_GT: {
625                 if (peekchr(vp) == c) {
626                     nxtchr(vp);
627                     op -= 2;
628                     return op;
629                 }
630             }
631             // FALLTHRU
632             case A_NOT:
633             case A_COLON: {
634                 c = '=';
635             }
636             // FALLTHRU
637             case A_ASSIGN:
638             case A_TIMES:
639             case A_PLUS:
640             case A_MINUS:
641             case A_OR:
642             case A_AND: {
643                 if (peekchr(vp) == c) {
644                     nxtchr(vp);
645                     op--;
646                 }
647                 return op;
648             }
649             // This handles all the tokens that don't need special fixups; e.g., A_LPAR.
650             default: { return op; }
651         }
652     }
653 }
654 
655 //
656 // Evaluate a subexpression with precedence.
657 //
expr(vars_t * vp,int precedence)658 static_fn bool expr(vars_t *vp, int precedence) {
659     int c, op;
660     int invalid, wasop = 0;
661     struct lval lvalue, assignop;
662     const char *pos;
663     Sfdouble_t d;
664     Shell_t *shp = vp->shp;
665 
666     lvalue.value = NULL;
667     lvalue.nargs = 0;
668     lvalue.fun = NULL;
669     lvalue.shp = shp;
670 again:
671     op = gettok(vp);
672     c = 2 * MAXPREC + 1;
673     switch (op) {
674         case A_PLUS: {
675             goto again;
676         }
677         case A_EOF: {
678             if (precedence > 2) ERROR(vp, e_moretokens);
679             return true;
680         }
681         case A_MINUS: {
682             op = A_UMINUS;
683             goto common;
684         }
685         case A_NOT: {
686             goto common;
687         }
688         case A_MINUSMINUS: {
689             c = A_LVALUE;
690             op = A_DECR | T_NOFLOAT;
691             goto common;
692         }
693         case A_PLUSPLUS: {
694             c = A_LVALUE;
695             op = A_INCR | T_NOFLOAT;
696         }
697         // FALLTHRU
698         case A_TILDE: {
699             op |= T_NOFLOAT;
700         common:
701             if (!expr(vp, c)) return false;
702             sfputc(shp->stk, op);
703             break;
704         }
705         default: {
706             vp->nextchr = vp->errchr;
707             wasop = 1;
708         }
709     }
710     invalid = wasop;
711     while (1) {
712         assignop.value = 0;
713         op = gettok(vp);
714         if (op == A_DIG || op == A_REG || op == A_LIT) {
715             if (!wasop) ERROR(vp, e_synbad);
716             goto number;
717         }
718         if (wasop++ && op != A_LPAR) ERROR(vp, e_synbad);
719         // Check for assignment operation.
720         if (peekchr(vp) == '=' && !(strval_precedence[op] & NOASSIGN)) {
721             if ((!lvalue.value || precedence > 3)) ERROR(vp, e_notlvalue);
722             if (precedence == 3) precedence = 2;
723             assignop = lvalue;
724             nxtchr(vp);
725             c = 3;
726         } else {
727             c = (strval_precedence[op] & PRECMASK);
728             if (c == MAXPREC || op == A_POW) c++;
729             c *= 2;
730         }
731         // From here on c is the new precedence level.
732         if (lvalue.value && (op != A_ASSIGN)) {
733             if (vp->staksize++ >= vp->stakmaxsize) vp->stakmaxsize = vp->staksize;
734             if (op == A_EQ || op == A_NEQ) sfputc(shp->stk, A_ENUM);
735             sfputc(stkstd, assignop.value ? A_ASSIGNOP1 : A_PUSHV);
736             stkpush(shp->stk, vp, lvalue.value, char *);
737             if (lvalue.flag < 0) lvalue.flag = 0;
738             stkpush(shp->stk, vp, lvalue.flag, short);
739             if (vp->nextchr == 0) ERROR(vp, e_badnum);
740             if (!(strval_precedence[op] & SEQPOINT)) lvalue.value = NULL;
741             invalid = 0;
742         } else if (precedence == A_LVALUE) {
743             ERROR(vp, e_notlvalue);
744         }
745         if (invalid && op > A_ASSIGN) ERROR(vp, e_synbad);
746         if (precedence >= c) goto done;
747         if (strval_precedence[op] & RASSOC) c--;
748         if ((c < (2 * MAXPREC + 1)) && !(strval_precedence[op] & SEQPOINT)) {
749             wasop = 0;
750             if (!expr(vp, c)) return false;
751         }
752         switch (op) {
753             case A_RPAR: {
754                 if (!vp->paren) ERROR(vp, e_paren);
755                 if (invalid) ERROR(vp, e_synbad);
756                 goto done;
757             }
758             case A_COMMA: {
759                 wasop = 0;
760                 if (vp->infun) {
761                     vp->infun++;
762                 } else {
763                     sfputc(shp->stk, A_POP);
764                     vp->staksize--;
765                 }
766                 if (!expr(vp, c)) {
767                     stkseek(shp->stk, stktell(shp->stk) - 1);
768                     return false;
769                 }
770                 lvalue.value = NULL;
771                 break;
772             }
773             case A_LPAR: {
774                 int infun = vp->infun;
775                 int userfun = 0;
776                 Sfdouble_t (*fun)(Sfdouble_t, ...);
777                 int nargs = lvalue.nargs;
778                 if (nargs < 0 && (nargs & 070) == 070) nargs = -nargs;
779                 fun = lvalue.fun;
780                 lvalue.fun = NULL;
781                 if (fun) {
782                     if (vp->staksize++ >= vp->stakmaxsize) vp->stakmaxsize = vp->staksize;
783                     vp->infun = 1;
784                     if ((int)lvalue.nargs < 0) {
785                         userfun = T_BINARY;
786                     } else if ((int)lvalue.nargs & 040) {
787                         userfun = T_NOFLOAT;
788                     }
789                     sfputc(shp->stk, A_PUSHF);
790                     stkpush(shp->stk, vp, fun, Math_f);
791                     sfputc(shp->stk, 1 + (userfun == T_BINARY));
792                 } else {
793                     vp->infun = 0;
794                 }
795                 if (!invalid) ERROR(vp, e_synbad);
796                 vp->paren++;
797                 if (!expr(vp, 1)) return false;
798                 vp->paren--;
799                 if (fun) {
800                     int x = (nargs & 010) ? 2 : -1;
801                     int call = A_CALL1F;
802                     if (nargs & 0100) call = A_CALL1V;
803                     nargs &= 7;
804                     if (vp->infun != nargs) ERROR(vp, e_argcount);
805                     if ((vp->staksize += nargs) >= vp->stakmaxsize) {
806                         vp->stakmaxsize = vp->staksize + nargs;
807                     }
808                     sfputc(shp->stk, call + userfun + nargs + x);
809                     vp->staksize -= nargs;
810                 }
811                 vp->infun = infun;
812                 if (gettok(vp) != A_RPAR) ERROR(vp, e_paren);
813                 wasop = 0;
814                 break;
815             }
816             case A_PLUSPLUS:
817             case A_MINUSMINUS: {
818                 wasop = 0;
819                 op |= T_NOFLOAT;
820             }
821             // FALLTHRU
822             case A_ASSIGN: {
823                 if (!lvalue.value) ERROR(vp, e_notlvalue);
824                 if (op == A_ASSIGN) {
825                     sfputc(shp->stk, A_STORE);
826                     stkpush(shp->stk, vp, lvalue.value, char *);
827                     stkpush(shp->stk, vp, lvalue.flag, short);
828                     vp->staksize--;
829                 } else {
830                     sfputc(shp->stk, op);
831                 }
832                 lvalue.value = NULL;
833                 break;
834             }
835             case A_QUEST: {
836                 int offset1, offset2;
837                 sfputc(shp->stk, A_JMPZ);
838                 stkpush(shp->stk, vp, 0, short);
839                 offset1 = stkoffset(shp->stk, vp);
840                 sfputc(shp->stk, A_POP);
841                 if (!expr(vp, 1)) return false;
842                 if (gettok(vp) != A_COLON) ERROR(vp, e_questcolon);
843                 sfputc(shp->stk, A_JMP);
844                 stkpush(shp->stk, vp, 0, short);
845                 offset2 = stkoffset(shp->stk, vp);
846                 *((short *)stkptr(shp->stk, offset1)) = stktell(shp->stk);
847                 sfputc(shp->stk, A_POP);
848                 if (!expr(vp, 3)) return false;
849                 *((short *)stkptr(shp->stk, offset2)) = stktell(shp->stk);
850                 lvalue.value = NULL;
851                 wasop = 0;
852                 break;
853             }
854             case A_COLON: {
855                 ERROR(vp, e_badcolon);
856                 break;
857             }
858             case A_QCOLON:
859             case A_ANDAND:
860             case A_OROR: {
861                 int offset;
862                 if (op == A_ANDAND) {
863                     op = A_JMPZ;
864                 } else {
865                     op = A_JMPNZ;
866                 }
867                 sfputc(shp->stk, op);
868                 stkpush(shp->stk, vp, 0, short);
869                 offset = stkoffset(shp->stk, vp);
870                 sfputc(shp->stk, A_POP);
871                 if (!expr(vp, c)) return false;
872                 *((short *)stkptr(shp->stk, offset)) = stktell(shp->stk);
873                 if (op != A_QCOLON) sfputc(shp->stk, A_NOTNOT);
874                 lvalue.value = NULL;
875                 wasop = 0;
876                 break;
877             }
878             case A_AND:
879             case A_OR:
880             case A_XOR:
881             case A_LSHIFT:
882             case A_RSHIFT:
883             case A_MOD:
884                 op |= T_NOFLOAT;
885             // FALLTHRU
886             case A_PLUS:
887             case A_MINUS:
888             case A_TIMES:
889             case A_DIV:
890             case A_EQ:
891             case A_NEQ:
892             case A_LT:
893             case A_LE:
894             case A_GT:
895             case A_GE:
896             case A_POW: {
897                 sfputc(shp->stk, op | T_BINARY);
898                 vp->staksize--;
899                 break;
900             }
901             case A_NOT:
902             case A_TILDE:
903             default: {
904                 ERROR(vp, e_synbad);
905             number:
906                 wasop = 0;
907                 if (*vp->nextchr == 'L' && vp->nextchr[1] == '\'') {
908                     vp->nextchr++;
909                     op = A_LIT;
910                 }
911                 pos = vp->nextchr;
912                 lvalue.isfloat = 0;
913                 lvalue.expr = vp->expr;
914                 lvalue.emode = vp->emode;
915                 if (op == A_LIT) {
916                     // Character constants.
917                     if (pos[1] == '\\' && pos[2] == '\'' && pos[3] != '\'') {
918                         d = '\\';
919                         vp->nextchr += 2;
920                     } else {
921                         d = chresc(pos + 1, (char **)&vp->nextchr);
922                     }
923                     // posix allows the trailing ' to be optional.
924                     if (*vp->nextchr == '\'') vp->nextchr++;
925                 } else {
926                     d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0);
927                 }
928                 if (vp->nextchr == pos) {
929                     vp->errmsg.value = lvalue.value;
930                     if (vp->errmsg.value) vp->errstr = pos;
931                     ERROR(vp, op == A_LIT ? e_charconst : e_synbad);
932                 }
933                 if (op == A_DIG || op == A_LIT || lvalue.isfloat == TYPE_LD) {
934                     sfputc(shp->stk, A_PUSHN);
935                     if (vp->staksize++ >= vp->stakmaxsize) vp->stakmaxsize = vp->staksize;
936                     // cppcheck-suppress invalidPointerCast
937                     stkpush(shp->stk, vp, d, Sfdouble_t);
938                     sfputc(shp->stk, lvalue.isfloat);
939                 }
940 
941                 // Check for function call.
942                 if (lvalue.fun) continue;
943                 break;
944             }
945         }
946         invalid = 0;
947         if (assignop.value) {
948             if (vp->staksize++ >= vp->stakmaxsize) vp->stakmaxsize = vp->staksize;
949             if (assignop.flag < 0) assignop.flag = 0;
950             sfputc(shp->stk, c & 1 ? A_ASSIGNOP : A_STORE);
951             stkpush(shp->stk, vp, assignop.value, char *);
952             stkpush(shp->stk, vp, assignop.flag, short);
953         }
954     }
955 
956 done:
957     vp->nextchr = vp->errchr;
958     return true;
959 }
960 
arith_compile(Shell_t * shp,const char * string,char ** last,Sfdouble_t (* fun)(const char **,struct lval *,int,Sfdouble_t),int emode)961 Arith_t *arith_compile(Shell_t *shp, const char *string, char **last,
962                        Sfdouble_t (*fun)(const char **, struct lval *, int, Sfdouble_t),
963                        int emode) {
964     vars_t cur;
965     Arith_t *ep;
966     int offset;
967     int nounset = sh_isoption(shp, SH_NOUNSET);
968 
969     memset(&cur, 0, sizeof(cur));
970     cur.shp = shp;
971     cur.expr = cur.nextchr = string;
972     cur.convert = fun;
973     cur.emode = emode;
974     cur.errmsg.value = 0;
975     cur.errmsg.emode = emode;
976     stkseek(shp->stk, sizeof(Arith_t));
977     if (nounset) sh_offoption(shp, SH_NOUNSET);
978     if (!expr(&cur, 0) && cur.errmsg.value) {
979         if (cur.errstr) string = cur.errstr;
980         if ((*fun)(&string, &cur.errmsg, MESSAGE, 0) < 0) {
981             stkseek(shp->stk, 0);
982             *last = (char *)Empty;
983             if (nounset) sh_onoption(shp, SH_NOUNSET);
984             return NULL;
985         }
986         cur.nextchr = cur.errchr;
987     }
988     sfputc(shp->stk, 0);
989     offset = stktell(shp->stk);
990     ep = (Arith_t *)stkfreeze(shp->stk, 0);
991     ep->shp = shp;
992     ep->expr = string;
993     ep->elen = (short)strlen(string);
994     ep->code = (unsigned char *)(ep + 1);
995     ep->fun = fun;
996     ep->emode = emode;
997     ep->size = offset - sizeof(Arith_t);
998     ep->staksize = cur.stakmaxsize + 1;
999     if (last) *last = (char *)(cur.nextchr);
1000     if (nounset) sh_onoption(shp, SH_NOUNSET);
1001     return ep;
1002 }
1003 
1004 //
1005 // Evaluate an integer arithmetic expression in s.
1006 //
1007 // (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value)
1008 //     is a user supplied conversion routine that is called when unknown
1009 //     chars are encountered.
1010 // *end points to the part to be converted and must be adjusted by convert to point to the next
1011 // non-converted character; if typ is MESSAGE then string points to an error message string.
1012 //
1013 // NOTE: (*convert)() may call strval().
1014 //
strval(Shell_t * shp,const char * s,char ** end,Sfdouble_t (* conv)(const char **,struct lval *,int,Sfdouble_t),int emode)1015 Sfdouble_t strval(Shell_t *shp, const char *s, char **end,
1016                   Sfdouble_t (*conv)(const char **, struct lval *, int, Sfdouble_t), int emode) {
1017     Arith_t *ep;
1018     Sfdouble_t d;
1019     char *sp = NULL;
1020     int offset;
1021 
1022     offset = stktell(shp->stk);
1023     if (offset) sp = stkfreeze(shp->stk, 1);
1024     ep = arith_compile(shp, s, end, conv, emode);
1025     ep->emode = emode;
1026     d = arith_exec(ep);
1027     stkset(shp->stk, sp ? sp : (char *)ep, offset);
1028     return d;
1029 }
1030