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