1 /*
2 * math.c - mathematical expression evaluation
3 *
4 * This file is part of zsh, the Z shell.
5 *
6 * Copyright (c) 1992-1997 Paul Falstad
7 * All rights reserved.
8 *
9 * Permission is hereby granted, without written agreement and without
10 * license or royalty fees, to use, copy, modify, and distribute this
11 * software and to distribute modified versions of this software for any
12 * purpose, provided that the above copyright notice and the following
13 * two paragraphs appear in all copies of this software.
14 *
15 * In no event shall Paul Falstad or the Zsh Development Group be liable
16 * to any party for direct, indirect, special, incidental, or consequential
17 * damages arising out of the use of this software and its documentation,
18 * even if Paul Falstad and the Zsh Development Group have been advised of
19 * the possibility of such damage.
20 *
21 * Paul Falstad and the Zsh Development Group specifically disclaim any
22 * warranties, including, but not limited to, the implied warranties of
23 * merchantability and fitness for a particular purpose. The software
24 * provided hereunder is on an "as is" basis, and Paul Falstad and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
27 *
28 */
29
30 struct mathvalue;
31
32 #include "zsh.mdh"
33 #include "math.pro"
34
35 #include <math.h>
36
37 /* nonzero means we are not evaluating, just parsing */
38
39 /**/
40 int noeval;
41
42 /* integer zero */
43
44 /**/
45 mod_export mnumber zero_mnumber;
46
47 /*
48 * The last value we computed: note this isn't cleared
49 * until the next computation, unlike yyval.
50 * Everything else is saved and returned to allow recursive calls.
51 */
52 /**/
53 mnumber lastmathval;
54
55 /* last input base we used */
56
57 /**/
58 int lastbase;
59
60 static char *ptr;
61
62 static mnumber yyval;
63 static char *yylval;
64
65 #define MAX_MLEVEL 256
66
67 static int mlevel = 0;
68
69 /* != 0 means recognize unary plus, minus, etc. */
70
71 static int unary = 1;
72
73 /* LR = left-to-right associativity *
74 * RL = right-to-left associativity *
75 * BOOL = short-circuiting boolean */
76
77 #define LR 0x0000
78 #define RL 0x0001
79 #define BOOL 0x0002
80
81 #define MTYPE(x) ((x) & 3)
82
83 /*
84 * OP_A2 2 arguments
85 * OP_A2IR 2 arguments, return integer
86 * OP_A2IO 2 arguments, must be integer, return integer
87 * OP_E2 2 arguments with assignment
88 * OP_E2IO 2 arguments with assignment, must be integer, return integer
89 * OP_OP None of the above, but occurs where we are expecting an operator
90 * rather than an operand.
91 * OP_OPF Followed by an operator, not an operand.
92 *
93 * OP_A2*, OP_E2*, OP_OP*:
94 * Occur when we need an operator; the next object must be an operand,
95 * unless OP_OPF is also supplied.
96 *
97 * Others:
98 * Occur when we need an operand; the next object must also be an operand,
99 * unless OP_OPF is also supplied.
100 */
101 #define OP_A2 0x0004
102 #define OP_A2IR 0x0008
103 #define OP_A2IO 0x0010
104 #define OP_E2 0x0020
105 #define OP_E2IO 0x0040
106 #define OP_OP 0x0080
107 #define OP_OPF 0x0100
108
109 #define M_INPAR 0
110 #define M_OUTPAR 1
111 #define NOT 2
112 #define COMP 3
113 #define POSTPLUS 4
114 #define POSTMINUS 5
115 #define UPLUS 6
116 #define UMINUS 7
117 #define AND 8
118 #define XOR 9
119 #define OR 10
120 #define MUL 11
121 #define DIV 12
122 #define MOD 13
123 #define PLUS 14
124 #define MINUS 15
125 #define SHLEFT 16
126 #define SHRIGHT 17
127 #define LES 18
128 #define LEQ 19
129 #define GRE 20
130 #define GEQ 21
131 #define DEQ 22
132 #define NEQ 23
133 #define DAND 24
134 #define DOR 25
135 #define DXOR 26
136 #define QUEST 27
137 #define COLON 28
138 #define EQ 29
139 #define PLUSEQ 30
140 #define MINUSEQ 31
141 #define MULEQ 32
142 #define DIVEQ 33
143 #define MODEQ 34
144 #define ANDEQ 35
145 #define XOREQ 36
146 #define OREQ 37
147 #define SHLEFTEQ 38
148 #define SHRIGHTEQ 39
149 #define DANDEQ 40
150 #define DOREQ 41
151 #define DXOREQ 42
152 #define COMMA 43
153 #define EOI 44
154 #define PREPLUS 45
155 #define PREMINUS 46
156 #define NUM 47
157 #define ID 48
158 #define POWER 49
159 #define CID 50
160 #define POWEREQ 51
161 #define FUNC 52
162 #define TOKCOUNT 53
163
164 /*
165 * Opeator recedences: in reverse order, i.e. lower number, high precedence.
166 * These are the C precedences.
167 *
168 * 0 Non-operators: NUM (numeric constant), ID (identifier),
169 * CID (identifier with '#'), FUNC (math function)
170 * 1 Opening parenthesis: M_INPAR '(' (for convenience, not an operator)
171 * 2 Unary operators: PREPLUS/POSTPLUS '++', PREMINUS/POSTMINUS '--',
172 * NOT '!', COMP '~', UPLUS '+', UMINUS '-'
173 * 3 POWER '**' (not in C but at high precedence in Perl)
174 * 4 MUL '*', DIV '/', MOD '%'
175 * 5 PLUS '+', MINUS '-'
176 * 6 SHLEFT '<<', SHRIGHT '>>'
177 * 7 GRE '>', 'GEQ' '>=', LES '<', LEQ '<='
178 * 8 DEQ '==', NEQ '!='
179 * 9 AND '&'
180 * 10 XOR '^'
181 * 11 OR '|'
182 * 12 DAND '&&'
183 * 13 DXOR '^^' (not in C)
184 * 14 DOR '||'
185 * 15 QUEST '?'
186 * 16 COLON ':'
187 * 17 EQ '=', PLUSEQ '+=', MINUSEQ '-=', MULEQ '*=', DIVEQ '/=',
188 * MODEQ '%=', ANDEQ '&=', XOREQ '^=', OREQ '|=',
189 * SHFLEFTEQ '<<=', SHRIGHTEQ '>>=', DANDEQ '&&=', DOREQ '||=',
190 * DXOREQ '^^='
191 * 18 COMMA ','
192 * 137 M_OUTPAR ')' (for convenience, not an operator)
193 * 200 EOI (end of input: for convenience, not an operator)
194 */
195 static int c_prec[TOKCOUNT] =
196 {
197 /* M_INPAR M_OUTPAR NOT COMP POSTPLUS */
198 /* 0 */ 1, 137, 2, 2, 2,
199 /* POSTMINUS UPLUS UMINUS AND XOR */
200 /* 5 */ 2, 2, 2, 9, 10,
201 /* OR MUL DIV MOD PLUS */
202 /* 10 */ 11, 4, 4, 4, 5,
203 /* MINUS SHLEFT SHRIGHT LES LEQ */
204 /* 15 */ 5, 6, 6, 7, 7,
205 /* GRE GEQ DEQ NEQ DAND */
206 /* 20 */ 7, 7, 8, 8, 12,
207 /* DOR DXOR QUEST COLON EQ */
208 /* 25 */ 14, 13, 15, 16, 17,
209 /* PLUSEQ MINUSEQ MULEQ DIVEQ MODEQ */
210 /* 30 */ 17, 17, 17, 17, 17,
211 /* ANDEQ XOREQ OREQ SHLEFTEQ SHRIGHTEQ */
212 /* 35 */ 17, 17, 17, 17, 17,
213 /* DANDEQ DOREQ DXOREQ COMMA EOI */
214 /* 40 */ 17, 17, 17, 18, 200,
215 /* PREPLUS PREMINUS NUM ID POWER */
216 /* 45 */ 2, 2, 0, 0, 3,
217 /* CID POWEREQ FUNC */
218 /* 50 */ 0, 17, 0
219 };
220
221 /*
222 * Opeator recedences: in reverse order, i.e. lower number, high precedence.
223 * These are the default zsh precedences.
224 *
225 * 0 Non-operators: NUM (numeric constant), ID (identifier),
226 * CID (identifier with '#'), FUNC (math function)
227 * 1 Opening parenthesis: M_INPAR '(' (for convenience, not an operator)
228 * 2 Unary operators: PREPLUS/POSTPLUS '++', PREMINUS/POSTMINUS '--',
229 * NOT '!', COMP '~', UPLUS '+', UMINUS '-'
230 * 3 SHLEFT '<<', SHRIGHT '>>'
231 * 4 AND '&'
232 * 5 XOR '^'
233 * 6 OR '|'
234 * 7 POWER '**' (not in C but at high precedence in Perl)
235 * 8 MUL '*', DIV '/', MOD '%'
236 * 9 PLUS '+', MINUS '-'
237 * 10 GRE '>', 'GEQ' '>=', LES '<', LEQ '<='
238 * 11 DEQ '==', NEQ '!='
239 * 12 DAND '&&'
240 * 13 DOR '||', DXOR '^^' (not in C)
241 * 14 QUEST '?'
242 * 15 COLON ':'
243 * 16 EQ '=', PLUSEQ '+=', MINUSEQ '-=', MULEQ '*=', DIVEQ '/=',
244 * MODEQ '%=', ANDEQ '&=', XOREQ '^=', OREQ '|=',
245 * SHFLEFTEQ '<<=', SHRIGHTEQ '>>=', DANDEQ '&&=', DOREQ '||=',
246 * DXOREQ '^^='
247 * 17 COMMA ','
248 * 137 M_OUTPAR ')' (for convenience, not an operator)
249 * 200 EOI (end of input: for convenience, not an operator)
250 */
251 static int z_prec[TOKCOUNT] =
252 {
253 /* M_INPAR M_OUTPAR NOT COMP POSTPLUS */
254 /* 0 */ 1, 137, 2, 2, 2,
255 /* POSTMINUS UPLUS UMINUS AND XOR */
256 /* 5 */ 2, 2, 2, 4, 5,
257 /* OR MUL DIV MOD PLUS */
258 /* 10 */ 6, 8, 8, 8, 9,
259 /* MINUS SHLEFT SHRIGHT LES LEQ */
260 /* 15 */ 9, 3, 3, 10, 10,
261 /* GRE GEQ DEQ NEQ DAND */
262 /* 20 */ 10, 10, 11, 11, 12,
263 /* DOR DXOR QUEST COLON EQ */
264 /* 25 */ 13, 13, 14, 15, 16,
265 /* PLUSEQ MINUSEQ MULEQ DIVEQ MODEQ */
266 /* 30 */ 16, 16, 16, 16, 16,
267 /* ANDEQ XOREQ OREQ SHLEFTEQ SHRIGHTEQ */
268 /* 35 */ 16, 16, 16, 16, 16,
269 /* DANDEQ DOREQ DXOREQ COMMA EOI */
270 /* 40 */ 16, 16, 16, 17, 200,
271 /* PREPLUS PREMINUS NUM ID POWER */
272 /* 45 */ 2, 2, 0, 0, 7,
273 /* CID POWEREQ FUNC */
274 /* 50 */ 0, 16, 0
275 };
276
277 /* Option-selectable preference table */
278 static int *prec;
279
280 /*
281 * Precedences for top and argument evaluation. Careful:
282 * prec needs to be set before we use these.
283 */
284 #define TOPPREC (prec[COMMA]+1)
285 #define ARGPREC (prec[COMMA]-1)
286
287 static int type[TOKCOUNT] =
288 {
289 /* 0 */ LR, LR|OP_OP|OP_OPF, RL, RL, RL|OP_OP|OP_OPF,
290 /* 5 */ RL|OP_OP|OP_OPF, RL, RL, LR|OP_A2IO, LR|OP_A2IO,
291 /* 10 */ LR|OP_A2IO, LR|OP_A2, LR|OP_A2, LR|OP_A2, LR|OP_A2,
292 /* 15 */ LR|OP_A2, LR|OP_A2IO, LR|OP_A2IO, LR|OP_A2IR, LR|OP_A2IR,
293 /* 20 */ LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, BOOL|OP_A2IO,
294 /* 25 */ BOOL|OP_A2IO, LR|OP_A2IO, RL|OP_OP, RL|OP_OP, RL|OP_E2,
295 /* 30 */ RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2,
296 /* 35 */ RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO,
297 /* 40 */ BOOL|OP_E2IO, BOOL|OP_E2IO, RL|OP_A2IO, RL|OP_A2, RL|OP_OP,
298 /* 45 */ RL, RL, LR|OP_OPF, LR|OP_OPF, RL|OP_A2,
299 /* 50 */ LR|OP_OPF, RL|OP_E2, LR|OP_OPF
300 };
301
302 /* the value stack */
303
304 #define STACKSZ 100
305 static int mtok; /* last token */
306 static int sp = -1; /* stack pointer */
307
308 struct mathvalue {
309 /*
310 * If we need to get a variable, this is the string to be passed
311 * to the parameter code. It may include a subscript.
312 */
313 char *lval;
314 /*
315 * If this is not zero, we've retrieved a variable and this
316 * stores a reference to it.
317 */
318 Value pval;
319 mnumber val;
320 };
321
322 static struct mathvalue *stack;
323
324 enum prec_type {
325 /* Evaluating a top-level expression */
326 MPREC_TOP,
327 /* Evaluating a function argument */
328 MPREC_ARG
329 };
330
331
332 /*
333 * Get a number from a variable.
334 * Try to be clever about reusing subscripts by caching the Value structure.
335 */
336 static mnumber
getmathparam(struct mathvalue * mptr)337 getmathparam(struct mathvalue *mptr)
338 {
339 mnumber result;
340 if (!mptr->pval) {
341 char *s = mptr->lval;
342 mptr->pval = (Value)zhalloc(sizeof(struct value));
343 if (!getvalue(mptr->pval, &s, 1))
344 {
345 if (unset(UNSET))
346 zerr("%s: parameter not set", mptr->lval);
347 mptr->pval = NULL;
348 if (isset(FORCEFLOAT)) {
349 result.type = MN_FLOAT;
350 result.u.d = 0.0;
351 return result;
352 }
353 return zero_mnumber;
354 }
355 }
356 result = getnumvalue(mptr->pval);
357 if (isset(FORCEFLOAT) && result.type == MN_INTEGER) {
358 result.type = MN_FLOAT;
359 result.u.d = (double)result.u.l;
360 }
361 return result;
362 }
363
364 static mnumber
mathevall(char * s,enum prec_type prec_tp,char ** ep)365 mathevall(char *s, enum prec_type prec_tp, char **ep)
366 {
367 int xlastbase, xnoeval, xunary, *xprec;
368 char *xptr;
369 mnumber xyyval;
370 char *xyylval;
371 int xsp;
372 struct mathvalue *xstack = 0, nstack[STACKSZ];
373 mnumber ret;
374
375 if (mlevel >= MAX_MLEVEL) {
376 xyyval.type = MN_INTEGER;
377 xyyval.u.l = 0;
378 *ep = s;
379
380 zerr("math recursion limit exceeded: %s", *ep);
381
382 return xyyval;
383 }
384 if (mlevel++) {
385 xlastbase = lastbase;
386 xnoeval = noeval;
387 xunary = unary;
388 xptr = ptr;
389 xyyval = yyval;
390 xyylval = yylval;
391
392 xsp = sp;
393 xstack = stack;
394 xprec = prec;
395 } else {
396 xlastbase = xnoeval = xunary = xsp = 0;
397 xyyval.type = MN_INTEGER;
398 xyyval.u.l = 0;
399 xyylval = NULL;
400 xptr = NULL;
401 xprec = NULL;
402 }
403 prec = isset(CPRECEDENCES) ? c_prec : z_prec;
404 stack = nstack;
405 lastbase = -1;
406 ptr = s;
407 sp = -1;
408 unary = 1;
409 stack[0].val.type = MN_INTEGER;
410 stack[0].val.u.l = 0;
411 mathparse(prec_tp == MPREC_TOP ? TOPPREC : ARGPREC);
412 /*
413 * Internally, we parse the contents of parentheses at top
414 * precedence... so we can return a parenthesis here if
415 * there are too many at the end.
416 */
417 if (mtok == M_OUTPAR && !errflag)
418 zerr("bad math expression: unexpected ')'");
419 *ep = ptr;
420 DPUTS(!errflag && sp > 0,
421 "BUG: math: wallabies roaming too freely in outback");
422
423 if (errflag) {
424 /*
425 * This used to set the return value to errflag.
426 * I don't understand how that could be useful; the
427 * caller doesn't know that's what's happened and
428 * may not get a value at all.
429 * Worse, we reset errflag in execarith() and setting
430 * this explicitly non-zero means a (( ... )) returns
431 * status 0 if there's an error. That surely can't
432 * be right. execarith() now detects an error and returns
433 * status 2.
434 */
435 ret.type = MN_INTEGER;
436 ret.u.l = 0;
437 } else {
438 if (stack[0].val.type == MN_UNSET)
439 ret = getmathparam(stack);
440 else
441 ret = stack[0].val;
442 }
443
444 if (--mlevel) {
445 lastbase = xlastbase;
446 noeval = xnoeval;
447 unary = xunary;
448 ptr = xptr;
449 yyval = xyyval;
450 yylval = xyylval;
451
452 sp = xsp;
453 stack = xstack;
454 prec = xprec;
455 }
456 return lastmathval = ret;
457 }
458
459 static int
lexconstant(void)460 lexconstant(void)
461 {
462 #ifdef USE_LOCALE
463 char *prev_locale;
464 #endif
465 char *nptr;
466
467 nptr = ptr;
468 if (IS_DASH(*nptr))
469 nptr++;
470
471 if (*nptr == '0') {
472 int lowchar;
473 nptr++;
474 lowchar = tolower(*nptr);
475 if (lowchar == 'x' || lowchar == 'b') {
476 /* Let zstrtol parse number with base */
477 yyval.u.l = zstrtol_underscore(ptr, &ptr, 0, 1);
478 /* Should we set lastbase here? */
479 lastbase = (lowchar == 'b') ? 2 : 16;
480 if (isset(FORCEFLOAT))
481 {
482 yyval.type = MN_FLOAT;
483 yyval.u.d = (double)yyval.u.l;
484 }
485 return NUM;
486 }
487 else if (isset(OCTALZEROES))
488 {
489 char *ptr2;
490
491 /*
492 * Make sure this is a real octal constant;
493 * it can't be a base indication (always decimal)
494 * or a floating point number.
495 */
496 for (ptr2 = nptr; idigit(*ptr2) || *ptr2 == '_'; ptr2++)
497 ;
498
499 if (ptr2 > nptr && *ptr2 != '.' && *ptr2 != 'e' &&
500 *ptr2 != 'E' && *ptr2 != '#')
501 {
502 yyval.u.l = zstrtol_underscore(ptr, &ptr, 0, 1);
503 lastbase = 8;
504 if (isset(FORCEFLOAT))
505 {
506 yyval.type = MN_FLOAT;
507 yyval.u.d = (double)yyval.u.l;
508 }
509 return NUM;
510 }
511 nptr = ptr2;
512 }
513 }
514 while (idigit(*nptr) || *nptr == '_')
515 nptr++;
516
517 if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') {
518 char *ptr2;
519 /* it's a float */
520 yyval.type = MN_FLOAT;
521 #ifdef USE_LOCALE
522 prev_locale = dupstring(setlocale(LC_NUMERIC, NULL));
523 setlocale(LC_NUMERIC, "POSIX");
524 #endif
525 if (*nptr == '.') {
526 nptr++;
527 while (idigit(*nptr) || *nptr == '_')
528 nptr++;
529 }
530 if (*nptr == 'e' || *nptr == 'E') {
531 nptr++;
532 if (*nptr == '+' || IS_DASH(*nptr))
533 nptr++;
534 while (idigit(*nptr) || *nptr == '_')
535 nptr++;
536 }
537 for (ptr2 = ptr; ptr2 < nptr; ptr2++) {
538 if (*ptr2 == '_') {
539 int len = nptr - ptr;
540 ptr = dupstring(ptr);
541 for (ptr2 = ptr; len; len--) {
542 if (*ptr2 == '_')
543 chuck(ptr2);
544 else
545 ptr2++;
546 }
547 break;
548 }
549 }
550 yyval.u.d = strtod(ptr, &nptr);
551 #ifdef USE_LOCALE
552 if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
553 #endif
554 if (ptr == nptr || *nptr == '.') {
555 zerr("bad floating point constant");
556 return EOI;
557 }
558 ptr = nptr;
559 } else {
560 /* it's an integer */
561 yyval.u.l = zstrtol_underscore(ptr, &ptr, 10, 1);
562
563 if (*ptr == '#') {
564 ptr++;
565 lastbase = yyval.u.l;
566 yyval.u.l = zstrtol_underscore(ptr, &ptr, lastbase, 1);
567 }
568 if (isset(FORCEFLOAT))
569 {
570 yyval.type = MN_FLOAT;
571 yyval.u.d = (double)yyval.u.l;
572 }
573 }
574 return NUM;
575 }
576
577 /**/
578 int outputradix;
579
580 /**/
581 int outputunderscore;
582
583 #ifndef HAVE_ISINF
584 /**/
585 int
isinf(double x)586 isinf(double x)
587 {
588 if ((-1.0 < x) && (x < 1.0)) /* x is small, and thus finite */
589 return (0);
590 else if ((x + x) == x) /* only true if x == Infinity */
591 return (1);
592 else /* must be finite (normal or subnormal), or NaN */
593 return (0);
594 }
595 #endif
596
597 #if !defined(HAVE_ISNAN)
598 static double
store(double * x)599 store(double *x)
600 {
601 return (*x);
602 }
603
604 /**/
605 int
isnan(double x)606 isnan(double x)
607 {
608 /* (x != x) should be sufficient, but some compilers incorrectly optimize it away */
609 return (store(&x) != store(&x));
610 }
611 #endif
612
613 /**/
614 static int
zzlex(void)615 zzlex(void)
616 {
617 int cct = 0;
618 char *ie;
619 yyval.type = MN_INTEGER;
620
621 for (;; cct = 0)
622 switch (*ptr++) {
623 case '+':
624 if (*ptr == '+') {
625 ptr++;
626 return (unary) ? PREPLUS : POSTPLUS;
627 }
628 if (*ptr == '=') {
629 ptr++;
630 return PLUSEQ;
631 }
632 return (unary) ? UPLUS : PLUS;
633 case '-':
634 case Dash:
635 if (IS_DASH(*ptr)) {
636 ptr++;
637 return (unary) ? PREMINUS : POSTMINUS;
638 }
639 if (*ptr == '=') {
640 ptr++;
641 return MINUSEQ;
642 }
643 if (unary) {
644 if (idigit(*ptr) || *ptr == '.') {
645 int ctype = lexconstant();
646 if (ctype == NUM)
647 {
648 if (yyval.type == MN_FLOAT)
649 {
650 yyval.u.d = -yyval.u.d;
651 }
652 else
653 {
654 yyval.u.l = -yyval.u.l;
655 }
656 }
657 return ctype;
658 } else
659 return UMINUS;
660 } else
661 return MINUS;
662 case '(':
663 return M_INPAR;
664 case ')':
665 return M_OUTPAR;
666 case '!':
667 if (*ptr == '=') {
668 ptr++;
669 return NEQ;
670 }
671 return NOT;
672 case '~':
673 return COMP;
674 case '&':
675 if (*ptr == '&') {
676 if (*++ptr == '=') {
677 ptr++;
678 return DANDEQ;
679 }
680 return DAND;
681 } else if (*ptr == '=') {
682 ptr++;
683 return ANDEQ;
684 }
685 return AND;
686 case '|':
687 if (*ptr == '|') {
688 if (*++ptr == '=') {
689 ptr++;
690 return DOREQ;
691 }
692 return DOR;
693 } else if (*ptr == '=') {
694 ptr++;
695 return OREQ;
696 }
697 return OR;
698 case '^':
699 if (*ptr == '^') {
700 if (*++ptr == '=') {
701 ptr++;
702 return DXOREQ;
703 }
704 return DXOR;
705 } else if (*ptr == '=') {
706 ptr++;
707 return XOREQ;
708 }
709 return XOR;
710 case '*':
711 if (*ptr == '*') {
712 if (*++ptr == '=') {
713 ptr++;
714 return POWEREQ;
715 }
716 return POWER;
717 }
718 if (*ptr == '=') {
719 ptr++;
720 return MULEQ;
721 }
722 return MUL;
723 case '/':
724 if (*ptr == '=') {
725 ptr++;
726 return DIVEQ;
727 }
728 return DIV;
729 case '%':
730 if (*ptr == '=') {
731 ptr++;
732 return MODEQ;
733 }
734 return MOD;
735 case '<':
736 if (*ptr == '<') {
737 if (*++ptr == '=') {
738 ptr++;
739 return SHLEFTEQ;
740 }
741 return SHLEFT;
742 } else if (*ptr == '=') {
743 ptr++;
744 return LEQ;
745 }
746 return LES;
747 case '>':
748 if (*ptr == '>') {
749 if (*++ptr == '=') {
750 ptr++;
751 return SHRIGHTEQ;
752 }
753 return SHRIGHT;
754 } else if (*ptr == '=') {
755 ptr++;
756 return GEQ;
757 }
758 return GRE;
759 case '=':
760 if (*ptr == '=') {
761 ptr++;
762 return DEQ;
763 }
764 return EQ;
765 case '$':
766 yyval.u.l = mypid;
767 return NUM;
768 case '?':
769 if (unary) {
770 yyval.u.l = lastval;
771 return NUM;
772 }
773 return QUEST;
774 case ':':
775 return COLON;
776 case ',':
777 return COMMA;
778 case '\0':
779 ptr--;
780 return EOI;
781 case '[':
782 {
783 int n, checkradix = 0;
784
785 if (idigit(*ptr)) {
786 n = zstrtol(ptr, &ptr, 10);
787 if (*ptr != ']' || !idigit(*++ptr)) {
788 zerr("bad base syntax");
789 return EOI;
790 }
791 yyval.u.l = zstrtol(ptr, &ptr, lastbase = n);
792 return NUM;
793 }
794 if (*ptr == '#') {
795 n = 1;
796 if (*++ptr == '#') {
797 n = -1;
798 ptr++;
799 }
800 if (!idigit(*ptr) && *ptr != '_')
801 goto bofs;
802 if (idigit(*ptr)) {
803 outputradix = n * zstrtol(ptr, &ptr, 10);
804 checkradix = 1;
805 }
806 if (*ptr == '_') {
807 ptr++;
808 if (idigit(*ptr))
809 outputunderscore = zstrtol(ptr, &ptr, 10);
810 else
811 outputunderscore = 3;
812 }
813 } else {
814 bofs:
815 zerr("bad output format specification");
816 return EOI;
817 }
818 if(*ptr != ']')
819 goto bofs;
820 if (checkradix) {
821 n = (outputradix < 0) ? -outputradix : outputradix;
822 if (n < 2 || n > 36) {
823 zerr("invalid base (must be 2 to 36 inclusive): %d",
824 outputradix);
825 return EOI;
826 }
827 }
828 ptr++;
829 break;
830 }
831 case ' ': /* Fall through! */
832 case '\t':
833 case '\n':
834 break;
835 default:
836 if (idigit(*--ptr) || *ptr == '.')
837 return lexconstant();
838 if (*ptr == '#') {
839 if (*++ptr == '\\' || *ptr == '#') {
840 int v;
841
842 ptr++;
843 if (!*ptr) {
844 zerr("bad math expression: character missing after ##");
845 return EOI;
846 }
847 ptr = getkeystring(ptr, NULL, GETKEYS_MATH, &v);
848 yyval.u.l = v;
849 return NUM;
850 }
851 cct = 1;
852 }
853 if ((ie = itype_end(ptr, IIDENT, 0)) != ptr) {
854 int func = 0;
855 char *p;
856
857 p = ptr;
858 ptr = ie;
859 if (ie - p == 3) {
860 if (strncasecmp(p, "NaN", 3) == 0) {
861 yyval.type = MN_FLOAT;
862 yyval.u.d = 0.0;
863 yyval.u.d /= yyval.u.d;
864 return NUM;
865 }
866 else if (strncasecmp(p, "Inf", 3) == 0) {
867 yyval.type = MN_FLOAT;
868 yyval.u.d = 0.0;
869 yyval.u.d = 1.0 / yyval.u.d;
870 return NUM;
871 }
872 }
873 if (*ptr == '[' || (!cct && *ptr == '(')) {
874 char op = *ptr, cp = ((*ptr == '[') ? ']' : ')');
875 int l;
876 func = (op == '(');
877 for (ptr++, l = 1; *ptr && l; ptr++) {
878 if (*ptr == op)
879 l++;
880 if (*ptr == cp)
881 l--;
882 if (*ptr == '\\' && ptr[1])
883 ptr++;
884 }
885 }
886 yylval = dupstrpfx(p, ptr - p);
887 return (func ? FUNC : (cct ? CID : ID));
888 }
889 else if (cct) {
890 yyval.u.l = poundgetfn(NULL);
891 return NUM;
892 }
893 return EOI;
894 }
895 }
896
897 /**/
898 static void
push(mnumber val,char * lval,int getme)899 push(mnumber val, char *lval, int getme)
900 {
901 if (sp == STACKSZ - 1)
902 zerr("stack overflow");
903 else
904 sp++;
905 stack[sp].val = val;
906 stack[sp].lval = lval;
907 stack[sp].pval = NULL;
908 if (getme)
909 stack[sp].val.type = MN_UNSET;
910 }
911
912 /**/
913 static mnumber
pop(int noget)914 pop(int noget)
915 {
916 struct mathvalue *mv = stack+sp;
917
918 if (mv->val.type == MN_UNSET && !noget)
919 mv->val = getmathparam(mv);
920 sp--;
921 return errflag ? zero_mnumber : mv->val;
922 }
923
924 /**/
925 static mnumber
getcvar(char * s)926 getcvar(char *s)
927 {
928 char *t;
929 mnumber mn;
930 mn.type = MN_INTEGER;
931
932 queue_signals();
933 if (!(t = getsparam(s)))
934 mn.u.l = 0;
935 else {
936 #ifdef MULTIBYTE_SUPPORT
937 if (isset(MULTIBYTE)) {
938 wint_t wc;
939 (void)mb_metacharlenconv(t, &wc);
940 if (wc != WEOF) {
941 mn.u.l = (zlong)wc;
942 unqueue_signals();
943 return mn;
944 }
945 }
946 #endif
947 mn.u.l = STOUC(*t == Meta ? t[1] ^ 32 : *t);
948 }
949 unqueue_signals();
950 return mn;
951 }
952
953 /**/
954 static mnumber
setmathvar(struct mathvalue * mvp,mnumber v)955 setmathvar(struct mathvalue *mvp, mnumber v)
956 {
957 Param pm;
958
959 if (mvp->pval) {
960 /*
961 * This value may have been hanging around for a while.
962 * Be ultra-paranoid in checking the variable is still valid.
963 */
964 char *s = mvp->lval, *ptr;
965 Param pm;
966 DPUTS(!mvp->lval, "no variable name but variable value in math");
967 if ((ptr = strchr(s, '[')))
968 s = dupstrpfx(s, ptr - s);
969 pm = (Param) paramtab->getnode(paramtab, s);
970 if (pm == mvp->pval->pm) {
971 if (noeval)
972 return v;
973 setnumvalue(mvp->pval, v);
974 return v;
975 }
976 /* Different parameter, start again from scratch */
977 mvp->pval = NULL;
978 }
979 if (!mvp->lval) {
980 zerr("bad math expression: lvalue required");
981 v.type = MN_INTEGER;
982 v.u.l = 0;
983 return v;
984 }
985 if (noeval)
986 return v;
987 untokenize(mvp->lval);
988 pm = setnparam(mvp->lval, v);
989 if (pm) {
990 /*
991 * If we are performing an assignment, we return the
992 * number with the same type as the parameter we are
993 * assigning to, in the spirit of the way assignments
994 * in C work. Note this was a change to long-standing
995 * zsh behaviour.
996 */
997 switch (PM_TYPE(pm->node.flags)) {
998 case PM_INTEGER:
999 if (v.type != MN_INTEGER) {
1000 v.u.l = (zlong)v.u.d;
1001 v.type = MN_INTEGER;
1002 }
1003 break;
1004
1005 case PM_EFLOAT:
1006 case PM_FFLOAT:
1007 if (v.type != MN_FLOAT) {
1008 v.u.d = (double)v.u.l;
1009 v.type = MN_FLOAT;
1010 }
1011 break;
1012 }
1013 }
1014 return v;
1015 }
1016
1017
1018 /**/
1019 static mnumber
callmathfunc(char * o)1020 callmathfunc(char *o)
1021 {
1022 MathFunc f;
1023 char *a, *n;
1024 static mnumber dummy;
1025
1026 n = a = dupstring(o);
1027
1028 while (*a != '(')
1029 a++;
1030 *a++ = '\0';
1031 a[strlen(a) - 1] = '\0';
1032
1033 if ((f = getmathfunc(n, 1))) {
1034 if ((f->flags & (MFF_STR|MFF_USERFUNC)) == MFF_STR) {
1035 return f->sfunc(n, a, f->funcid);
1036 } else {
1037 int argc = 0;
1038 mnumber *argv = NULL, *q, marg;
1039 LinkList l = newlinklist();
1040 LinkNode node;
1041
1042 if (f->flags & MFF_USERFUNC) {
1043 /* first argument is function name: always use mathfunc */
1044 addlinknode(l, n);
1045 }
1046
1047 if (f->flags & MFF_STR) {
1048 if (!*a) {
1049 addlinknode(l, dupstring(""));
1050 argc++;
1051 }
1052 } else {
1053 while (iblank(*a))
1054 a++;
1055 }
1056 while (*a) {
1057 if (*a) {
1058 argc++;
1059 if (f->flags & MFF_USERFUNC) {
1060 /* need to pass strings */
1061 char *str;
1062 if (f->flags & MFF_STR) {
1063 str = dupstring(a);
1064 a = "";
1065 } else {
1066 marg = mathevall(a, MPREC_ARG, &a);
1067 if (marg.type & MN_FLOAT) {
1068 /* convfloat is off the heap */
1069 str = convfloat(marg.u.d, 0, 0, NULL);
1070 } else {
1071 char buf[BDIGBUFSIZE];
1072 convbase(buf, marg.u.l, 10);
1073 str = dupstring(buf);
1074 }
1075 }
1076 addlinknode(l, str);
1077 } else {
1078 q = (mnumber *) zhalloc(sizeof(mnumber));
1079 *q = mathevall(a, MPREC_ARG, &a);
1080 addlinknode(l, q);
1081 }
1082 if (errflag || mtok != COMMA)
1083 break;
1084 }
1085 }
1086 if (*a && !errflag)
1087 zerr("bad math expression: illegal character: %c", *a);
1088 if (!errflag) {
1089 if (argc >= f->minargs && (f->maxargs < 0 ||
1090 argc <= f->maxargs)) {
1091 if (f->flags & MFF_USERFUNC) {
1092 char *shfnam = f->module ? f->module : n;
1093 Shfunc shfunc = getshfunc(shfnam);
1094 if (!shfunc)
1095 zerr("no such function: %s", shfnam);
1096 else {
1097 doshfunc(shfunc, l, 1);
1098 return lastmathval;
1099 }
1100 } else {
1101 if (argc) {
1102 q = argv =
1103 (mnumber *)zhalloc(argc * sizeof(mnumber));
1104 for (node = firstnode(l); node; incnode(node))
1105 *q++ = *(mnumber *)getdata(node);
1106 }
1107 return f->nfunc(n, argc, argv, f->funcid);
1108 }
1109 } else
1110 zerr("wrong number of arguments: %s", o);
1111 }
1112 }
1113 } else {
1114 zerr("unknown function: %s", n);
1115 }
1116
1117 dummy.type = MN_INTEGER;
1118 dummy.u.l = 0;
1119
1120 return dummy;
1121 }
1122
1123 /**/
1124 static int
notzero(mnumber a)1125 notzero(mnumber a)
1126 {
1127 if ((a.type & MN_INTEGER) && a.u.l == 0) {
1128 zerr("division by zero");
1129 return 0;
1130 }
1131 return 1;
1132 }
1133
1134 /* macro to pop three values off the value stack */
1135
1136 static void
op(int what)1137 op(int what)
1138 {
1139 mnumber a, b, c, *spval;
1140 int tp = type[what];
1141
1142 if (errflag)
1143 return;
1144 if (sp < 0) {
1145 zerr("bad math expression: stack empty");
1146 return;
1147 }
1148
1149 if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO)) {
1150 /* Make sure anyone seeing this message reports it. */
1151 DPUTS(sp < 1, "BUG: math: not enough wallabies in outback.");
1152 b = pop(0);
1153 a = pop(what == EQ);
1154 if (errflag)
1155 return;
1156
1157 if (tp & (OP_A2IO|OP_E2IO)) {
1158 /* coerce to integers */
1159 if (a.type & MN_FLOAT) {
1160 a.type = MN_INTEGER;
1161 a.u.l = (zlong)a.u.d;
1162 }
1163 if (b.type & MN_FLOAT) {
1164 b.type = MN_INTEGER;
1165 b.u.l = (zlong)b.u.d;
1166 }
1167 } else if (a.type != b.type && what != COMMA &&
1168 (a.type != MN_UNSET || what != EQ)) {
1169 /*
1170 * Different types, so coerce to float.
1171 * It may happen during an assignment that the LHS
1172 * variable is actually an integer, but there's still
1173 * no harm in doing the arithmetic in floating point;
1174 * the assignment will do the correct conversion.
1175 * This way, if the parameter is actually a scalar, but
1176 * used to contain an integer, we can write a float into it.
1177 */
1178 if (a.type & MN_INTEGER) {
1179 a.type = MN_FLOAT;
1180 a.u.d = (double)a.u.l;
1181 }
1182 if (b.type & MN_INTEGER) {
1183 b.type = MN_FLOAT;
1184 b.u.d = (double)b.u.l;
1185 }
1186 }
1187
1188 if (noeval) {
1189 c.type = MN_INTEGER;
1190 c.u.l = 0;
1191 } else {
1192 /*
1193 * type for operation: usually same as operands, but e.g.
1194 * (a == b) returns int.
1195 */
1196 c.type = (tp & OP_A2IR) ? MN_INTEGER : a.type;
1197
1198 switch(what) {
1199 case AND:
1200 case ANDEQ:
1201 c.u.l = a.u.l & b.u.l;
1202 break;
1203 case XOR:
1204 case XOREQ:
1205 c.u.l = a.u.l ^ b.u.l;
1206 break;
1207 case OR:
1208 case OREQ:
1209 c.u.l = a.u.l | b.u.l;
1210 break;
1211 case MUL:
1212 case MULEQ:
1213 if (c.type == MN_FLOAT)
1214 c.u.d = a.u.d * b.u.d;
1215 else
1216 c.u.l = a.u.l * b.u.l;
1217 break;
1218 case DIV:
1219 case DIVEQ:
1220 if (!notzero(b))
1221 return;
1222 if (c.type == MN_FLOAT)
1223 c.u.d = a.u.d / b.u.d;
1224 else {
1225 /*
1226 * Avoid exception when dividing the smallest
1227 * negative integer by -1. Always treat it the
1228 * same as multiplication. This still doesn't give
1229 * numerically the right answer in two's complement,
1230 * but treating both these in the same way seems
1231 * reasonable.
1232 */
1233 if (b.u.l == -1)
1234 c.u.l = - a.u.l;
1235 else
1236 c.u.l = a.u.l / b.u.l;
1237 }
1238 break;
1239 case MOD:
1240 case MODEQ:
1241 if (!notzero(b))
1242 return;
1243 /*
1244 * Avoid exception as above.
1245 * Any integer mod -1 is the same as any integer mod 1
1246 * i.e. zero.
1247 */
1248 if (c.type == MN_FLOAT)
1249 c.u.d = fmod(a.u.d, b.u.d);
1250 else if (b.u.l == -1)
1251 c.u.l = 0;
1252 else
1253 c.u.l = a.u.l % b.u.l;
1254 break;
1255 case PLUS:
1256 case PLUSEQ:
1257 if (c.type == MN_FLOAT)
1258 c.u.d = a.u.d + b.u.d;
1259 else
1260 c.u.l = a.u.l + b.u.l;
1261 break;
1262 case MINUS:
1263 case MINUSEQ:
1264 if (c.type == MN_FLOAT)
1265 c.u.d = a.u.d - b.u.d;
1266 else
1267 c.u.l = a.u.l - b.u.l;
1268 break;
1269 case SHLEFT:
1270 case SHLEFTEQ:
1271 c.u.l = a.u.l << b.u.l;
1272 break;
1273 case SHRIGHT:
1274 case SHRIGHTEQ:
1275 c.u.l = a.u.l >> b.u.l;
1276 break;
1277 case LES:
1278 c.u.l = (zlong)
1279 (a.type == MN_FLOAT ? (a.u.d < b.u.d) : (a.u.l < b.u.l));
1280 break;
1281 case LEQ:
1282 c.u.l = (zlong)
1283 (a.type == MN_FLOAT ? (a.u.d <= b.u.d) : (a.u.l <= b.u.l));
1284 break;
1285 case GRE:
1286 c.u.l = (zlong)
1287 (a.type == MN_FLOAT ? (a.u.d > b.u.d) : (a.u.l > b.u.l));
1288 break;
1289 case GEQ:
1290 c.u.l = (zlong)
1291 (a.type == MN_FLOAT ? (a.u.d >= b.u.d) : (a.u.l >= b.u.l));
1292 break;
1293 case DEQ:
1294 c.u.l = (zlong)
1295 (a.type == MN_FLOAT ? (a.u.d == b.u.d) : (a.u.l == b.u.l));
1296 break;
1297 case NEQ:
1298 c.u.l = (zlong)
1299 (a.type == MN_FLOAT ? (a.u.d != b.u.d) : (a.u.l != b.u.l));
1300 break;
1301 case DAND:
1302 case DANDEQ:
1303 c.u.l = (zlong)(a.u.l && b.u.l);
1304 break;
1305 case DOR:
1306 case DOREQ:
1307 c.u.l = (zlong)(a.u.l || b.u.l);
1308 break;
1309 case DXOR:
1310 case DXOREQ:
1311 c.u.l = (zlong)((a.u.l && !b.u.l) || (!a.u.l && b.u.l));
1312 break;
1313 case COMMA:
1314 c = b;
1315 break;
1316 case POWER:
1317 case POWEREQ:
1318 if (c.type == MN_INTEGER && b.u.l < 0) {
1319 /* produces a real result, so cast to real. */
1320 a.type = b.type = c.type = MN_FLOAT;
1321 a.u.d = (double) a.u.l;
1322 b.u.d = (double) b.u.l;
1323 }
1324 if (c.type == MN_INTEGER) {
1325 for (c.u.l = 1; b.u.l--; c.u.l *= a.u.l);
1326 } else {
1327 if (b.u.d <= 0 && !notzero(a))
1328 return;
1329 if (a.u.d < 0) {
1330 /* Error if (-num ** b) and b is not an integer */
1331 double tst = (double)(zlong)b.u.d;
1332 if (tst != b.u.d) {
1333 zerr("bad math expression: imaginary power");
1334 return;
1335 }
1336 }
1337 c.u.d = pow(a.u.d, b.u.d);
1338 }
1339 break;
1340 case EQ:
1341 c = b;
1342 break;
1343 }
1344 }
1345 if (tp & (OP_E2|OP_E2IO)) {
1346 struct mathvalue *mvp = stack + sp + 1;
1347 c = setmathvar(mvp, c);
1348 push(c, mvp->lval, 0);
1349 } else
1350 push(c,NULL, 0);
1351 return;
1352 }
1353
1354 spval = &stack[sp].val;
1355 if (stack[sp].val.type == MN_UNSET)
1356 *spval = getmathparam(stack + sp);
1357 switch (what) {
1358 case NOT:
1359 if (spval->type & MN_FLOAT) {
1360 spval->u.l = !spval->u.d;
1361 spval->type = MN_INTEGER;
1362 } else
1363 spval->u.l = !spval->u.l;
1364 break;
1365 case COMP:
1366 if (spval->type & MN_FLOAT) {
1367 spval->u.l = ~((zlong)spval->u.d);
1368 spval->type = MN_INTEGER;
1369 } else
1370 spval->u.l = ~spval->u.l;
1371 break;
1372 case POSTPLUS:
1373 a = *spval;
1374 if (spval->type & MN_FLOAT)
1375 a.u.d++;
1376 else
1377 a.u.l++;
1378 (void)setmathvar(stack + sp, a);
1379 break;
1380 case POSTMINUS:
1381 a = *spval;
1382 if (spval->type & MN_FLOAT)
1383 a.u.d--;
1384 else
1385 a.u.l--;
1386 (void)setmathvar(stack + sp, a);
1387 break;
1388 case UPLUS:
1389 break;
1390 case UMINUS:
1391 if (spval->type & MN_FLOAT)
1392 spval->u.d = -spval->u.d;
1393 else
1394 spval->u.l = -spval->u.l;
1395 break;
1396 case QUEST:
1397 DPUTS(sp < 2, "BUG: math: three shall be the number of the counting.");
1398 c = pop(0);
1399 b = pop(0);
1400 a = pop(0);
1401 if (errflag)
1402 return;
1403 /* b and c can stay different types in this case. */
1404 push(((a.type & MN_FLOAT) ? a.u.d : a.u.l) ? b : c, NULL, 0);
1405 break;
1406 case COLON:
1407 zerr("bad math expression: ':' without '?'");
1408 break;
1409 case PREPLUS:
1410 if (spval->type & MN_FLOAT)
1411 spval->u.d++;
1412 else
1413 spval->u.l++;
1414 setmathvar(stack + sp, *spval);
1415 break;
1416 case PREMINUS:
1417 if (spval->type & MN_FLOAT)
1418 spval->u.d--;
1419 else
1420 spval->u.l--;
1421 setmathvar(stack + sp, *spval);
1422 break;
1423 default:
1424 zerr("bad math expression: out of integers");
1425 return;
1426 }
1427 stack[sp].lval = NULL;
1428 stack[sp].pval = NULL;
1429 }
1430
1431
1432 /**/
1433 static void
bop(int tk)1434 bop(int tk)
1435 {
1436 mnumber *spval = &stack[sp].val;
1437 int tst;
1438
1439 if (stack[sp].val.type == MN_UNSET)
1440 *spval = getmathparam(stack + sp);
1441 tst = (spval->type & MN_FLOAT) ? (zlong)spval->u.d : spval->u.l;
1442
1443 switch (tk) {
1444 case DAND:
1445 case DANDEQ:
1446 if (!tst)
1447 noeval++;
1448 break;
1449 case DOR:
1450 case DOREQ:
1451 if (tst)
1452 noeval++;
1453 break;
1454 };
1455 }
1456
1457
1458 /**/
1459 mod_export mnumber
matheval(char * s)1460 matheval(char *s)
1461 {
1462 char *junk;
1463 mnumber x;
1464 int xmtok = mtok;
1465 /* maintain outputradix and outputunderscore across levels of evaluation */
1466 if (!mlevel)
1467 outputradix = outputunderscore = 0;
1468
1469 if (*s == Nularg)
1470 s++;
1471 if (!*s) {
1472 x.type = MN_INTEGER;
1473 x.u.l = 0;
1474 return x;
1475 }
1476 x = mathevall(s, MPREC_TOP, &junk);
1477 mtok = xmtok;
1478 if (*junk)
1479 zerr("bad math expression: illegal character: %c", *junk);
1480 return x;
1481 }
1482
1483 /**/
1484 mod_export zlong
mathevali(char * s)1485 mathevali(char *s)
1486 {
1487 mnumber x = matheval(s);
1488 return (x.type & MN_FLOAT) ? (zlong)x.u.d : x.u.l;
1489 }
1490
1491
1492 /**/
1493 zlong
mathevalarg(char * s,char ** ss)1494 mathevalarg(char *s, char **ss)
1495 {
1496 mnumber x;
1497 int xmtok = mtok;
1498
1499 /*
1500 * At this entry point we don't allow an empty expression,
1501 * whereas we do with matheval(). I'm not sure if this
1502 * difference is deliberate, but it does mean that e.g.
1503 * $array[$ind] where ind hasn't been set produces an error,
1504 * which is probably safe.
1505 *
1506 * To avoid a more opaque error further in, bail out here.
1507 */
1508 if (*s == Nularg)
1509 s++;
1510 if (!*s) {
1511 zerr("bad math expression: empty string");
1512 return (zlong)0;
1513 }
1514 x = mathevall(s, MPREC_ARG, ss);
1515 if (mtok == COMMA)
1516 (*ss)--;
1517 mtok = xmtok;
1518 return (x.type & MN_FLOAT) ? (zlong)x.u.d : x.u.l;
1519 }
1520
1521 /*
1522 * Make sure we have an operator or an operand, whatever is expected.
1523 * For this purpose, unary operators constitute part of an operand.
1524 */
1525
1526 /**/
1527 static void
checkunary(int mtokc,char * mptr)1528 checkunary(int mtokc, char *mptr)
1529 {
1530 int errmsg = 0;
1531 int tp = type[mtokc];
1532 if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO|OP_OP)) {
1533 if (unary)
1534 errmsg = 1;
1535 } else {
1536 if (!unary)
1537 errmsg = 2;
1538 }
1539 if (errmsg) {
1540 int len, over = 0;
1541 char *errtype = errmsg == 2 ? "operator" : "operand";
1542 while (inblank(*mptr))
1543 mptr++;
1544 len = ztrlen(mptr);
1545 if (len > 10) {
1546 len = 10;
1547 over = 1;
1548 }
1549 if (!*mptr)
1550 zerr("bad math expression: %s expected at end of string",
1551 errtype);
1552 else
1553 zerr("bad math expression: %s expected at `%l%s'",
1554 errtype, mptr, len, over ? "..." : "");
1555 }
1556 unary = !(tp & OP_OPF);
1557 }
1558
1559 /* operator-precedence parse the string and execute */
1560
1561 /**/
1562 static void
mathparse(int pc)1563 mathparse(int pc)
1564 {
1565 zlong q;
1566 int otok, onoeval;
1567 char *optr = ptr;
1568
1569 if (errflag)
1570 return;
1571 queue_signals();
1572 mtok = zzlex();
1573 /* Handle empty input */
1574 if (pc == TOPPREC && mtok == EOI) {
1575 unqueue_signals();
1576 return;
1577 }
1578 checkunary(mtok, optr);
1579 while (prec[mtok] <= pc) {
1580 if (errflag) {
1581 unqueue_signals();
1582 return;
1583 }
1584 switch (mtok) {
1585 case NUM:
1586 push(yyval, NULL, 0);
1587 break;
1588 case ID:
1589 push(zero_mnumber, yylval, !noeval);
1590 break;
1591 case CID:
1592 push((noeval ? zero_mnumber : getcvar(yylval)), yylval, 0);
1593 break;
1594 case FUNC:
1595 push((noeval ? zero_mnumber : callmathfunc(yylval)), yylval, 0);
1596 break;
1597 case M_INPAR:
1598 mathparse(TOPPREC);
1599 if (mtok != M_OUTPAR) {
1600 if (!errflag)
1601 zerr("bad math expression: ')' expected");
1602 unqueue_signals();
1603 return;
1604 }
1605 break;
1606 case QUEST:
1607 if (stack[sp].val.type == MN_UNSET)
1608 stack[sp].val = getmathparam(stack + sp);
1609 q = (stack[sp].val.type == MN_FLOAT) ?
1610 (stack[sp].val.u.d == 0 ? 0 : 1) :
1611 stack[sp].val.u.l;
1612
1613 if (!q)
1614 noeval++;
1615 mathparse(prec[COLON] - 1);
1616 if (!q)
1617 noeval--;
1618 if (mtok != COLON) {
1619 if (!errflag)
1620 zerr("bad math expression: ':' expected");
1621 unqueue_signals();
1622 return;
1623 }
1624 if (q)
1625 noeval++;
1626 mathparse(prec[QUEST]);
1627 if (q)
1628 noeval--;
1629 op(QUEST);
1630 continue;
1631 default:
1632 otok = mtok;
1633 onoeval = noeval;
1634 if (MTYPE(type[otok]) == BOOL)
1635 bop(otok);
1636 mathparse(prec[otok] - (MTYPE(type[otok]) != RL));
1637 noeval = onoeval;
1638 op(otok);
1639 continue;
1640 }
1641 optr = ptr;
1642 mtok = zzlex();
1643 checkunary(mtok, optr);
1644 }
1645 unqueue_signals();
1646 }
1647