openenvutils/commandshell/shell/src/math.c
changeset 0 2e3d3ce01487
child 4 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // math.c - mathematical expression evaluation
       
     2 //
       
     3 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     4 //
       
     5 /*
       
     6  * This file is part of zsh, the Z shell.
       
     7  *
       
     8  * Copyright (c) 1992-1997 Paul Falstad
       
     9  * All rights reserved.
       
    10  *
       
    11  * Permission is hereby granted, without written agreement and without
       
    12  * license or royalty fees, to use, copy, modify, and distribute this
       
    13  * software and to distribute modified versions of this software for any
       
    14  * purpose, provided that the above copyright notice and the following
       
    15  * two paragraphs appear in all copies of this software.
       
    16  *
       
    17  * In no event shall Paul Falstad or the Zsh Development Group be liable
       
    18  * to any party for direct, indirect, special, incidental, or consequential
       
    19  * damages arising out of the use of this software and its documentation,
       
    20  * even if Paul Falstad and the Zsh Development Group have been advised of
       
    21  * the possibility of such damage.
       
    22  *
       
    23  * Paul Falstad and the Zsh Development Group specifically disclaim any
       
    24  * warranties, including, but not limited to, the implied warranties of
       
    25  * merchantability and fitness for a particular purpose.  The software
       
    26  * provided hereunder is on an "as is" basis, and Paul Falstad and the
       
    27  * Zsh Development Group have no obligation to provide maintenance,
       
    28  * support, updates, enhancements, or modifications.
       
    29  *
       
    30  */
       
    31 
       
    32 #include "zsh.mdh"
       
    33 #include "math.pro"
       
    34 
       
    35 #include <math.h>
       
    36 
       
    37 #ifdef __SYMBIAN32__
       
    38 #ifdef __WINSCW__
       
    39 #pragma warn_possunwant off
       
    40 #endif//__WINSCW__
       
    41 #endif//__SYMBIAN32__
       
    42 
       
    43 /* nonzero means we are not evaluating, just parsing */
       
    44  
       
    45 /**/
       
    46 int noeval;
       
    47  
       
    48 /* integer zero */
       
    49 
       
    50 /**/
       
    51 mod_export mnumber zero_mnumber;
       
    52 
       
    53 /* last input base we used */
       
    54 
       
    55 /**/
       
    56 int lastbase;
       
    57  
       
    58 static char *ptr;
       
    59 
       
    60 static mnumber yyval;
       
    61 static char *yylval;
       
    62 
       
    63 #define MAX_MLEVEL 256
       
    64 
       
    65 static int mlevel = 0;
       
    66 
       
    67 /* != 0 means recognize unary plus, minus, etc. */
       
    68 
       
    69 static int unary = 1;
       
    70 
       
    71 /* LR = left-to-right associativity *
       
    72  * RL = right-to-left associativity *
       
    73  * BOOL = short-circuiting boolean   */
       
    74 
       
    75 #define LR   0x0000
       
    76 #define RL   0x0001
       
    77 #define BOOL 0x0002
       
    78 
       
    79 #define MTYPE(x)  ((x) & 3)
       
    80 
       
    81 /*
       
    82  * OP_A2    2 arguments
       
    83  * OP_A2IR  2 arguments, return integer
       
    84  * OP_A2IO  2 arguments, must be integer, return integer
       
    85  * OP_E2    2 arguments with assignment
       
    86  * OP_E2IO  2 arguments with assignment, must be integer, return integer
       
    87  * OP_OP    None of the above, but occurs where we are expecting an operator
       
    88  *          rather than an operand.
       
    89  * OP_OPF   Followed by an operator, not an operand.
       
    90  *
       
    91  * OP_A2*, OP_E2*, OP_OP*:
       
    92  *   Occur when we need an operator; the next object must be an operand,
       
    93  *   unless OP_OPF is also supplied.
       
    94  *
       
    95  * Others:
       
    96  *   Occur when we need an operand; the next object must also be an operand,
       
    97  *   unless OP_OPF is also supplied.
       
    98  */
       
    99 #define OP_A2   0x0004
       
   100 #define OP_A2IR 0x0008
       
   101 #define OP_A2IO 0x0010
       
   102 #define OP_E2   0x0020
       
   103 #define OP_E2IO 0x0040
       
   104 #define OP_OP   0x0080
       
   105 #define OP_OPF  0x0100
       
   106 
       
   107 #define M_INPAR 0
       
   108 #define M_OUTPAR 1
       
   109 #define NOT 2
       
   110 #define COMP 3
       
   111 #define POSTPLUS 4
       
   112 #define POSTMINUS 5
       
   113 #define UPLUS 6
       
   114 #define UMINUS 7
       
   115 #define AND 8
       
   116 #define XOR 9
       
   117 #define OR 10
       
   118 #define MUL 11
       
   119 #define DIV 12
       
   120 #define MOD 13
       
   121 #define PLUS 14
       
   122 #define MINUS 15
       
   123 #define SHLEFT 16
       
   124 #define SHRIGHT 17
       
   125 #define LES 18
       
   126 #define LEQ 19
       
   127 #define GRE 20
       
   128 #define GEQ 21
       
   129 #define DEQ 22
       
   130 #define NEQ 23
       
   131 #define DAND 24
       
   132 #define DOR 25
       
   133 #define DXOR 26
       
   134 #define QUEST 27
       
   135 #define COLON 28
       
   136 #define EQ 29
       
   137 #define PLUSEQ 30
       
   138 #define MINUSEQ 31
       
   139 #define MULEQ 32
       
   140 #define DIVEQ 33
       
   141 #define MODEQ 34
       
   142 #define ANDEQ 35
       
   143 #define XOREQ 36
       
   144 #define OREQ 37
       
   145 #define SHLEFTEQ 38
       
   146 #define SHRIGHTEQ 39
       
   147 #define DANDEQ 40
       
   148 #define DOREQ 41
       
   149 #define DXOREQ 42
       
   150 #define COMMA 43
       
   151 #define EOI 44
       
   152 #define PREPLUS 45
       
   153 #define PREMINUS 46
       
   154 #define NUM 47
       
   155 #define ID 48
       
   156 #define POWER 49
       
   157 #define CID 50
       
   158 #define POWEREQ 51
       
   159 #define FUNC 52
       
   160 #define TOKCOUNT 53
       
   161 
       
   162 /* precedences */
       
   163 
       
   164 static int prec[TOKCOUNT] =
       
   165 {
       
   166      1, 137,  2,  2,   2,
       
   167      2,   2,  2,  4,   5,
       
   168      6,   8,  8,  8,   9,
       
   169      9,   3,  3, 10,  10,
       
   170     10,  10, 11, 11,  12,
       
   171     13,  13, 14, 15,  16,
       
   172     16,  16, 16, 16,  16,
       
   173     16,  16, 16, 16,  16,
       
   174     16,  16, 16, 17, 200,
       
   175      2,   2,  0,  0,   7,
       
   176      0,  16, 0
       
   177 };
       
   178 
       
   179 #define TOPPREC 18
       
   180 #define ARGPREC 16
       
   181 
       
   182 static int type[TOKCOUNT] =
       
   183 {
       
   184 /*  0 */  LR, LR|OP_OP|OP_OPF, RL, RL, RL|OP_OP|OP_OPF,
       
   185 /*  5 */  RL|OP_OP|OP_OPF, RL, RL, LR|OP_A2IO, LR|OP_A2IO,
       
   186 /* 10 */  LR|OP_A2IO, LR|OP_A2, LR|OP_A2, LR|OP_A2IO, LR|OP_A2,
       
   187 /* 15 */  LR|OP_A2, LR|OP_A2IO, LR|OP_A2IO, LR|OP_A2IR, LR|OP_A2IR,
       
   188 /* 20 */  LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, BOOL|OP_A2IO,
       
   189 /* 25 */  BOOL|OP_A2IO, LR|OP_A2IO, RL|OP_OP, RL|OP_OP, RL|OP_E2,
       
   190 /* 30 */  RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2IO,
       
   191 /* 35 */  RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO,
       
   192 /* 40 */  BOOL|OP_E2IO, BOOL|OP_E2IO, RL|OP_A2IO, RL|OP_A2, RL|OP_OP,
       
   193 /* 45 */  RL, RL, LR|OP_OPF, LR|OP_OPF, RL|OP_A2,
       
   194 /* 50 */  LR|OP_OPF, RL|OP_E2, LR|OP_OPF
       
   195 };
       
   196 
       
   197 static int
       
   198 lexconstant(void)
       
   199 {
       
   200 #ifdef USE_LOCALE
       
   201     char *prev_locale;
       
   202 #endif
       
   203     char *nptr;
       
   204 
       
   205     nptr = ptr;
       
   206     if (*nptr == '-')
       
   207 	nptr++;
       
   208 
       
   209     if (*nptr == '0')
       
   210     {
       
   211 	nptr++;
       
   212 	if (*nptr == 'x' || *nptr == 'X') {
       
   213 	    /* Let zstrtol parse number with base */
       
   214 	    yyval.u.l = zstrtol(ptr, &ptr, 0);
       
   215 	    /* Should we set lastbase here? */
       
   216 	    lastbase = 16;
       
   217 	    return NUM;
       
   218 	}
       
   219 	else if (isset(OCTALZEROES) &&
       
   220 		 (memchr(nptr, '.', strlen(nptr)) == NULL) &&
       
   221 		 idigit(*nptr)) {
       
   222 	    yyval.u.l = zstrtol(ptr, &ptr, 0);
       
   223 	    lastbase = 8;
       
   224 	    return NUM;
       
   225 	}
       
   226     }
       
   227 
       
   228     while (idigit(*nptr))
       
   229 	nptr++;
       
   230 
       
   231     if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') {
       
   232 	/* it's a float */
       
   233 	yyval.type = MN_FLOAT;
       
   234 #ifdef USE_LOCALE
       
   235 	prev_locale = dupstring(setlocale(LC_NUMERIC, NULL));
       
   236 	setlocale(LC_NUMERIC, "POSIX");
       
   237 #endif
       
   238 	yyval.u.d = strtod(ptr, &nptr);
       
   239 #ifdef USE_LOCALE
       
   240 	if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
       
   241 #endif
       
   242 	if (ptr == nptr || *nptr == '.') {
       
   243 	    zerr("bad floating point constant", NULL, 0);
       
   244 	    return EOI;
       
   245 	}
       
   246 	ptr = nptr;
       
   247     } else {
       
   248 	/* it's an integer */
       
   249 	yyval.u.l = zstrtol(ptr, &ptr, 10);
       
   250 
       
   251 	if (*ptr == '#') {
       
   252 	    ptr++;
       
   253 	    yyval.u.l = zstrtol(ptr, &ptr, lastbase = yyval.u.l);
       
   254 	}
       
   255     }
       
   256     return NUM;
       
   257 }
       
   258 
       
   259 /**/
       
   260 int outputradix;
       
   261 
       
   262 /**/
       
   263 static int
       
   264 zzlex(void)
       
   265 {
       
   266     int cct = 0;
       
   267     yyval.type = MN_INTEGER;
       
   268 
       
   269     for (;; cct = 0)
       
   270 	switch (*ptr++) {
       
   271 	case '+':
       
   272 	    if (*ptr == '+' && (unary || !ialnum(*ptr))) {
       
   273 		ptr++;
       
   274 		return (unary) ? PREPLUS : POSTPLUS;
       
   275 	    }
       
   276 	    if (*ptr == '=') {
       
   277 		ptr++;
       
   278 		return PLUSEQ;
       
   279 	    }
       
   280 	    return (unary) ? UPLUS : PLUS;
       
   281 	case '-':
       
   282 	    if (*ptr == '-' && (unary || !ialnum(*ptr))) {
       
   283 		ptr++;
       
   284 		return (unary) ? PREMINUS : POSTMINUS;
       
   285 	    }
       
   286 	    if (*ptr == '=') {
       
   287 		ptr++;
       
   288 		return MINUSEQ;
       
   289 	    }
       
   290 	    if (unary) {
       
   291 		if (idigit(*ptr) || *ptr == '.') {
       
   292 		    ptr--;
       
   293 		    return lexconstant();
       
   294 		} else
       
   295 		    return UMINUS;
       
   296 	    } else
       
   297 		return MINUS;
       
   298 	case '(':
       
   299 	    return M_INPAR;
       
   300 	case ')':
       
   301 	    return M_OUTPAR;
       
   302 	case '!':
       
   303 	    if (*ptr == '=') {
       
   304 		ptr++;
       
   305 		return NEQ;
       
   306 	    }
       
   307 	    return NOT;
       
   308 	case '~':
       
   309 	    return COMP;
       
   310 	case '&':
       
   311 	    if (*ptr == '&') {
       
   312 		if (*++ptr == '=') {
       
   313 		    ptr++;
       
   314 		    return DANDEQ;
       
   315 		}
       
   316 		return DAND;
       
   317 	    } else if (*ptr == '=') {
       
   318 		ptr++;
       
   319 		return ANDEQ;
       
   320 	    }
       
   321 	    return AND;
       
   322 	case '|':
       
   323 	    if (*ptr == '|') {
       
   324 		if (*++ptr == '=') {
       
   325 		    ptr++;
       
   326 		    return DOREQ;
       
   327 		}
       
   328 		return DOR;
       
   329 	    } else if (*ptr == '=') {
       
   330 		ptr++;
       
   331 		return OREQ;
       
   332 	    }
       
   333 	    return OR;
       
   334 	case '^':
       
   335 	    if (*ptr == '^') {
       
   336 		if (*++ptr == '=') {
       
   337 		    ptr++;
       
   338 		    return DXOREQ;
       
   339 		}
       
   340 		return DXOR;
       
   341 	    } else if (*ptr == '=') {
       
   342 		ptr++;
       
   343 		return XOREQ;
       
   344 	    }
       
   345 	    return XOR;
       
   346 	case '*':
       
   347 	    if (*ptr == '*') {
       
   348 		if (*++ptr == '=') {
       
   349 		    ptr++;
       
   350 		    return POWEREQ;
       
   351 		}
       
   352 		return POWER;
       
   353 	    }
       
   354 	    if (*ptr == '=') {
       
   355 		ptr++;
       
   356 		return MULEQ;
       
   357 	    }
       
   358 	    return MUL;
       
   359 	case '/':
       
   360 	    if (*ptr == '=') {
       
   361 		ptr++;
       
   362 		return DIVEQ;
       
   363 	    }
       
   364 	    return DIV;
       
   365 	case '%':
       
   366 	    if (*ptr == '=') {
       
   367 		ptr++;
       
   368 		return MODEQ;
       
   369 	    }
       
   370 	    return MOD;
       
   371 	case '<':
       
   372 	    if (*ptr == '<') {
       
   373 		if (*++ptr == '=') {
       
   374 		    ptr++;
       
   375 		    return SHLEFTEQ;
       
   376 		}
       
   377 		return SHLEFT;
       
   378 	    } else if (*ptr == '=') {
       
   379 		ptr++;
       
   380 		return LEQ;
       
   381 	    }
       
   382 	    return LES;
       
   383 	case '>':
       
   384 	    if (*ptr == '>') {
       
   385 		if (*++ptr == '=') {
       
   386 		    ptr++;
       
   387 		    return SHRIGHTEQ;
       
   388 		}
       
   389 		return SHRIGHT;
       
   390 	    } else if (*ptr == '=') {
       
   391 		ptr++;
       
   392 		return GEQ;
       
   393 	    }
       
   394 	    return GRE;
       
   395 	case '=':
       
   396 	    if (*ptr == '=') {
       
   397 		ptr++;
       
   398 		return DEQ;
       
   399 	    }
       
   400 	    return EQ;
       
   401 	case '$':
       
   402 	    yyval.u.l = mypid;
       
   403 	    return NUM;
       
   404 	case '?':
       
   405 	    if (unary) {
       
   406 		yyval.u.l = lastval;
       
   407 		return NUM;
       
   408 	    }
       
   409 	    return QUEST;
       
   410 	case ':':
       
   411 	    return COLON;
       
   412 	case ',':
       
   413 	    return COMMA;
       
   414 	case '\0':
       
   415 	    ptr--;
       
   416 	    return EOI;
       
   417 	case '[':
       
   418 	    {
       
   419 		int n;
       
   420 
       
   421 		if (idigit(*ptr)) {
       
   422 		    n = zstrtol(ptr, &ptr, 10);
       
   423 		    if (*ptr != ']' || !idigit(*++ptr)) {
       
   424 			zerr("bad base syntax", NULL, 0);
       
   425 			return EOI;
       
   426 		    }
       
   427 		    yyval.u.l = zstrtol(ptr, &ptr, lastbase = n);
       
   428 		    return NUM;
       
   429 		}
       
   430 		if (*ptr == '#') {
       
   431 		    n = 1;
       
   432 		    if (*++ptr == '#') {
       
   433 			n = -1;
       
   434 			ptr++;
       
   435 		    }
       
   436 		    if (!idigit(*ptr))
       
   437 			goto bofs;
       
   438 		    outputradix = n * zstrtol(ptr, &ptr, 10);
       
   439 		} else {
       
   440 		    bofs:
       
   441 		    zerr("bad output format specification", NULL, 0);
       
   442 		    return EOI;
       
   443 		}
       
   444 		if(*ptr != ']')
       
   445 			goto bofs;
       
   446 		ptr++;
       
   447 		break;
       
   448 	    }
       
   449 	case ' ':
       
   450 	case '\t':
       
   451 	case '\n':
       
   452 	    break;
       
   453 	/* Fall through! */
       
   454 	default:
       
   455 	    if (idigit(*--ptr) || *ptr == '.')
       
   456 		return lexconstant();
       
   457 	    if (*ptr == '#') {
       
   458 		if (*++ptr == '\\' || *ptr == '#') {
       
   459 		    int v;
       
   460 
       
   461 		    ptr++;
       
   462 		    if (!*ptr) {
       
   463 			zerr("character missing after ##", NULL, 0);
       
   464 			return EOI;
       
   465 		    }
       
   466 		    ptr = getkeystring(ptr, NULL, 6, &v);
       
   467 		    yyval.u.l = v;
       
   468 		    return NUM;
       
   469 		}
       
   470 		cct = 1;
       
   471 	    }
       
   472 	    if (iident(*ptr)) {
       
   473 		int func = 0;
       
   474 		char *p;
       
   475 
       
   476 		p = ptr;
       
   477 		while (iident(*++ptr));
       
   478 		if (*ptr == '[' || (!cct && *ptr == '(')) {
       
   479 		    char op = *ptr, cp = ((*ptr == '[') ? ']' : ')');
       
   480 		    int l;
       
   481 		    func = (op == '(');
       
   482 		    for (ptr++, l = 1; *ptr && l; ptr++) {
       
   483 			if (*ptr == op)
       
   484 			    l++;
       
   485 			if (*ptr == cp)
       
   486 			    l--;
       
   487 			if (*ptr == '\\' && ptr[1])
       
   488 			    ptr++;
       
   489 		    }
       
   490 		}
       
   491 		yylval = dupstrpfx(p, ptr - p);
       
   492 		return (func ? FUNC : (cct ? CID : ID));
       
   493 	    }
       
   494 	    else if (cct) {
       
   495 		yyval.u.l = poundgetfn(NULL);
       
   496 		return NUM;
       
   497 	    }
       
   498 	    return EOI;
       
   499 	}
       
   500 }
       
   501 
       
   502 /* the value stack */
       
   503 
       
   504 #define STACKSZ 100
       
   505 static int mtok;			/* last token */
       
   506 static int sp = -1;			/* stack pointer */
       
   507 
       
   508 struct mathvalue {
       
   509     char *lval;
       
   510     mnumber val;
       
   511 };
       
   512 
       
   513 static struct mathvalue *stack;
       
   514 
       
   515 /**/
       
   516 static void
       
   517 push(mnumber val, char *lval, int getme)
       
   518 {
       
   519     if (sp == STACKSZ - 1)
       
   520 	zerr("stack overflow", NULL, 0);
       
   521     else
       
   522 	sp++;
       
   523     stack[sp].val = val;
       
   524     stack[sp].lval = lval;
       
   525     if (getme)
       
   526 	stack[sp].val.type = MN_UNSET;
       
   527 }
       
   528 
       
   529 /**/
       
   530 static mnumber
       
   531 pop(int noget)
       
   532 {
       
   533     struct mathvalue *mv = stack+sp;
       
   534 
       
   535     if (mv->val.type == MN_UNSET && !noget)
       
   536 	mv->val = getnparam(mv->lval);
       
   537     sp--;
       
   538     return errflag ? zero_mnumber : mv->val;
       
   539 }
       
   540 
       
   541 /**/
       
   542 static mnumber
       
   543 getcvar(char *s)
       
   544 {
       
   545     char *t;
       
   546     mnumber mn;
       
   547     mn.type = MN_INTEGER;
       
   548 
       
   549     queue_signals();
       
   550     if (!(t = getsparam(s)))
       
   551 	mn.u.l = 0;
       
   552     else
       
   553         mn.u.l = STOUC(*t == Meta ? t[1] ^ 32 : *t);
       
   554     unqueue_signals();
       
   555     return mn;
       
   556 }
       
   557 
       
   558 
       
   559 /**/
       
   560 static mnumber
       
   561 setvar(char *s, mnumber v)
       
   562 {
       
   563     if (!s) {
       
   564 	zerr("lvalue required", NULL, 0);
       
   565 	v.type = MN_INTEGER;
       
   566 	v.u.l = 0;
       
   567 	return v;
       
   568     }
       
   569     if (noeval)
       
   570 	return v;
       
   571     untokenize(s);
       
   572     setnparam(s, v);
       
   573     return v;
       
   574 }
       
   575 
       
   576 
       
   577 /**/
       
   578 static mnumber
       
   579 callmathfunc(char *o)
       
   580 {
       
   581     MathFunc f;
       
   582     char *a, *n;
       
   583     static mnumber dummy;
       
   584 
       
   585     n = a = dupstring(o);
       
   586 
       
   587     while (*a != '(')
       
   588 	a++;
       
   589     *a++ = '\0';
       
   590     a[strlen(a) - 1] = '\0';
       
   591 
       
   592     if ((f = getmathfunc(n, 1))) {
       
   593 	if (f->flags & MFF_STR)
       
   594 	    return f->sfunc(n, a, f->funcid);
       
   595 	else {
       
   596 	    int argc = 0;
       
   597 	    mnumber *argv = NULL, *q;
       
   598 	    LinkList l = newlinklist();
       
   599 	    LinkNode node;
       
   600 
       
   601 	    while (iblank(*a))
       
   602 		a++;
       
   603 	    while (*a) {
       
   604 		if (*a) {
       
   605 		    argc++;
       
   606  		    q = (mnumber *) zhalloc(sizeof(mnumber));
       
   607 		    *q = mathevall(a, ARGPREC, &a);
       
   608 		    addlinknode(l, q);
       
   609 		    if (errflag || mtok != COMMA)
       
   610 			break;
       
   611 		}
       
   612 	    }
       
   613 	    if (*a && !errflag)
       
   614 		zerr("bad math expression: illegal character: %c",
       
   615 		     NULL, *a);
       
   616 	    if (!errflag) {
       
   617 		if (argc >= f->minargs && (f->maxargs < 0 ||
       
   618 					   argc <= f->maxargs)) {
       
   619 		    if (argc) {
       
   620 			q = argv = (mnumber *)zhalloc(argc * sizeof(mnumber));
       
   621 			for (node = firstnode(l); node; incnode(node))
       
   622 			    *q++ = *(mnumber *)getdata(node);
       
   623 		    }
       
   624 		    return f->nfunc(n, argc, argv, f->funcid);
       
   625 		} else
       
   626 		    zerr("wrong number of arguments: %s", o, 0);
       
   627 	    }
       
   628 	}
       
   629     } else
       
   630 	zerr("unknown function: %s", n, 0);
       
   631 
       
   632     dummy.type = MN_INTEGER;
       
   633     dummy.u.l = 0;
       
   634 
       
   635     return dummy;
       
   636 }
       
   637 
       
   638 /**/
       
   639 static int
       
   640 notzero(mnumber a)
       
   641 {
       
   642     if ((a.type & MN_INTEGER) ? a.u.l == 0 : a.u.d == 0.0) {
       
   643 	zerr("division by zero", NULL, 0);
       
   644 	return 0;
       
   645     }
       
   646     return 1;
       
   647 }
       
   648 
       
   649 /* macro to pop three values off the value stack */
       
   650 
       
   651 /**/
       
   652 void
       
   653 op(int what)
       
   654 {
       
   655     mnumber a, b, c, *spval;
       
   656     char *lv;
       
   657     int tp = type[what];
       
   658 
       
   659     if (errflag)
       
   660 	return;
       
   661     if (sp < 0) {
       
   662 	zerr("bad math expression: stack empty", NULL, 0);
       
   663 	return;
       
   664     }
       
   665 
       
   666     if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO)) {
       
   667 	/* Make sure anyone seeing this message reports it. */
       
   668 	DPUTS(sp < 1, "BUG: math: not enough wallabies in outback.");
       
   669 	b = pop(0);
       
   670 	a = pop(what == EQ);
       
   671 	if (errflag)
       
   672 	    return;
       
   673 
       
   674 	if (tp & (OP_A2IO|OP_E2IO)) {
       
   675 	    /* coerce to integers */
       
   676 	    if (a.type & MN_FLOAT) {
       
   677 		a.type = MN_INTEGER;
       
   678 		a.u.l = (zlong)a.u.d;
       
   679 	    }
       
   680 	    if (b.type & MN_FLOAT) {
       
   681 		b.type = MN_INTEGER;
       
   682 		b.u.l = (zlong)b.u.d;
       
   683 	    }
       
   684 	} else if (a.type != b.type && what != COMMA &&
       
   685 		   (a.type != MN_UNSET || what != EQ)) {
       
   686 	    /*
       
   687 	     * Different types, so coerce to float.
       
   688 	     * It may happen during an assignment that the LHS
       
   689 	     * variable is actually an integer, but there's still
       
   690 	     * no harm in doing the arithmetic in floating point;
       
   691 	     * the assignment will do the correct conversion.
       
   692 	     * This way, if the parameter is actually a scalar, but
       
   693 	     * used to contain an integer, we can write a float into it.
       
   694 	     */
       
   695 	    if (a.type & MN_INTEGER) {
       
   696 		a.type = MN_FLOAT;
       
   697 		a.u.d = (double)a.u.l;
       
   698 	    }
       
   699 	    if (b.type & MN_INTEGER) {
       
   700 		b.type = MN_FLOAT;
       
   701 		b.u.d = (double)b.u.l;
       
   702 	    }
       
   703 	}
       
   704 
       
   705 	if (noeval) {
       
   706 	    c.type = MN_INTEGER;
       
   707 	    c.u.l = 0;
       
   708 	} else {
       
   709 	    /*
       
   710 	     * type for operation: usually same as operands, but e.g.
       
   711 	     * (a == b) returns int.
       
   712 	     */
       
   713 	    c.type = (tp & OP_A2IR) ? MN_INTEGER : a.type;
       
   714 
       
   715 	    switch(what) {
       
   716 	    case AND:
       
   717 	    case ANDEQ:
       
   718 		c.u.l = a.u.l & b.u.l;
       
   719 		break;
       
   720 	    case XOR:
       
   721 	    case XOREQ:
       
   722 		c.u.l = a.u.l ^ b.u.l;
       
   723 		break;
       
   724 	    case OR:
       
   725 	    case OREQ:
       
   726 		c.u.l = a.u.l | b.u.l;
       
   727 		break;
       
   728 	    case MUL:
       
   729 	    case MULEQ:
       
   730 		if (c.type == MN_FLOAT)
       
   731 		    c.u.d = a.u.d * b.u.d;
       
   732 		else
       
   733 		    c.u.l = a.u.l * b.u.l;
       
   734 		break;
       
   735 	    case DIV:
       
   736 	    case DIVEQ:
       
   737 		if (!notzero(b))
       
   738 		    return;
       
   739 		if (c.type == MN_FLOAT)
       
   740 		    c.u.d = a.u.d / b.u.d;
       
   741 		else
       
   742 		    c.u.l = a.u.l / b.u.l;
       
   743 		break;
       
   744 	    case MOD:
       
   745 	    case MODEQ:
       
   746 		if (!notzero(b))
       
   747 		    return;
       
   748 		c.u.l = a.u.l % b.u.l;
       
   749 		break;
       
   750 	    case PLUS:
       
   751 	    case PLUSEQ:
       
   752 		if (c.type == MN_FLOAT)
       
   753 		    c.u.d = a.u.d + b.u.d;
       
   754 		else
       
   755 		    c.u.l = a.u.l + b.u.l;
       
   756 		break;
       
   757 	    case MINUS:
       
   758 	    case MINUSEQ:
       
   759 		if (c.type == MN_FLOAT)
       
   760 		    c.u.d = a.u.d - b.u.d;
       
   761 		else
       
   762 		    c.u.l = a.u.l - b.u.l;
       
   763 		break;
       
   764 	    case SHLEFT:
       
   765 	    case SHLEFTEQ:
       
   766 		c.u.l = a.u.l << b.u.l;
       
   767 		break;
       
   768 	    case SHRIGHT:
       
   769 	    case SHRIGHTEQ:
       
   770 		c.u.l = a.u.l >> b.u.l;
       
   771 		break;
       
   772 	    case LES:
       
   773 		c.u.l = (zlong)
       
   774 		    (a.type == MN_FLOAT ? (a.u.d < b.u.d) : (a.u.l < b.u.l));
       
   775 		break;
       
   776 	    case LEQ:
       
   777 		c.u.l = (zlong)
       
   778 		    (a.type == MN_FLOAT ? (a.u.d <= b.u.d) : (a.u.l <= b.u.l));
       
   779 		break;
       
   780 	    case GRE:
       
   781 		c.u.l = (zlong)
       
   782 		    (a.type == MN_FLOAT ? (a.u.d > b.u.d) : (a.u.l > b.u.l));
       
   783 		break;
       
   784 	    case GEQ:
       
   785 		c.u.l = (zlong)
       
   786 		    (a.type == MN_FLOAT ? (a.u.d >= b.u.d) : (a.u.l >= b.u.l));
       
   787 		break;
       
   788 	    case DEQ:
       
   789 		c.u.l = (zlong)
       
   790 		    (a.type == MN_FLOAT ? (a.u.d == b.u.d) : (a.u.l == b.u.l));
       
   791 		break;
       
   792 	    case NEQ:
       
   793 		c.u.l = (zlong)
       
   794 		    (a.type == MN_FLOAT ? (a.u.d != b.u.d) : (a.u.l != b.u.l));
       
   795 		break;
       
   796 	    case DAND:
       
   797 	    case DANDEQ:
       
   798 		c.u.l = (zlong)(a.u.l && b.u.l);
       
   799 		break;
       
   800 	    case DOR:
       
   801 	    case DOREQ:
       
   802 		c.u.l = (zlong)(a.u.l || b.u.l);
       
   803 		break;
       
   804 	    case DXOR:
       
   805 	    case DXOREQ:
       
   806 		c.u.l = (zlong)((a.u.l && !b.u.l) || (!a.u.l && b.u.l));
       
   807 		break;
       
   808 	    case COMMA:
       
   809 		c = b;
       
   810 		break;
       
   811 	    case POWER:
       
   812 	    case POWEREQ:
       
   813 		if (c.type == MN_INTEGER && b.u.l < 0) {
       
   814 		    /* produces a real result, so cast to real. */
       
   815 		    a.type = b.type = c.type = MN_FLOAT;
       
   816 		    a.u.d = (double) a.u.l;
       
   817 		    b.u.d = (double) b.u.l;
       
   818 		}
       
   819 		if (c.type == MN_INTEGER) {
       
   820 		    for (c.u.l = 1; b.u.l--; c.u.l *= a.u.l);
       
   821 		} else {
       
   822 		    if (b.u.d <= 0 && !notzero(a))
       
   823 			return;
       
   824 		    if (a.u.d < 0) {
       
   825 			/* Error if (-num ** b) and b is not an integer */
       
   826 			double tst = (double)(zlong)b.u.d;
       
   827 			if (tst != b.u.d) {
       
   828 			    zerr("imaginary power", NULL, 0);
       
   829 			    return;
       
   830 			}
       
   831 		    }
       
   832 		    c.u.d = pow(a.u.d, b.u.d);
       
   833 		}
       
   834 		break;
       
   835 	    case EQ:
       
   836 		c = b;
       
   837 		break;
       
   838 	    }
       
   839 	}
       
   840 	if (tp & (OP_E2|OP_E2IO)) {
       
   841 	    lv = stack[sp+1].lval;
       
   842 	    push(setvar(lv,c), lv, 0);
       
   843 	} else
       
   844 	    push(c,NULL, 0);
       
   845 	return;
       
   846     }
       
   847 
       
   848     spval = &stack[sp].val;
       
   849     if (stack[sp].val.type == MN_UNSET)
       
   850 	*spval = getnparam(stack[sp].lval);
       
   851     switch (what) {
       
   852     case NOT:
       
   853 	if (spval->type & MN_FLOAT) {
       
   854 	    spval->u.l = !spval->u.d;
       
   855 	    spval->type = MN_INTEGER;
       
   856 	} else
       
   857 	    spval->u.l = !spval->u.l;
       
   858 	stack[sp].lval = NULL;
       
   859 	break;
       
   860     case COMP:
       
   861 	if (spval->type & MN_FLOAT) {
       
   862 	    spval->u.l = ~((zlong)spval->u.d);
       
   863 	    spval->type = MN_INTEGER;
       
   864 	} else
       
   865 	    spval->u.l = ~spval->u.l;
       
   866 	stack[sp].lval = NULL;
       
   867 	break;
       
   868     case POSTPLUS:
       
   869 	a = *spval;
       
   870 	if (spval->type & MN_FLOAT)
       
   871 	    a.u.d++;
       
   872 	else
       
   873 	    a.u.l++;
       
   874 	(void)setvar(stack[sp].lval, a);
       
   875 	break;
       
   876     case POSTMINUS:
       
   877 	a = *spval;
       
   878 	if (spval->type & MN_FLOAT)
       
   879 	    a.u.d--;
       
   880 	else
       
   881 	    a.u.l--;
       
   882 	(void)setvar(stack[sp].lval, a);
       
   883 	break;
       
   884     case UPLUS:
       
   885 	stack[sp].lval = NULL;
       
   886 	break;
       
   887     case UMINUS:
       
   888 	if (spval->type & MN_FLOAT)
       
   889 	    spval->u.d = -spval->u.d;
       
   890 	else
       
   891 	    spval->u.l = -spval->u.l;
       
   892 	stack[sp].lval = NULL;
       
   893 	break;
       
   894     case QUEST:
       
   895 	DPUTS(sp < 2, "BUG: math: three shall be the number of the counting.");
       
   896 	c = pop(0);
       
   897 	b = pop(0);
       
   898 	a = pop(0);
       
   899 	if (errflag)
       
   900 	    return;
       
   901 	/* b and c can stay different types in this case. */
       
   902 	push(((a.type & MN_FLOAT) ? a.u.d : a.u.l) ? b : c, NULL, 0);
       
   903 	break;
       
   904     case COLON:
       
   905 	zerr("':' without '?'", NULL, 0);
       
   906 	break;
       
   907     case PREPLUS:
       
   908 	if (spval->type & MN_FLOAT)
       
   909 	    spval->u.d++;
       
   910 	else
       
   911 	    spval->u.l++;
       
   912 	setvar(stack[sp].lval, *spval);
       
   913 	break;
       
   914     case PREMINUS:
       
   915 	if (spval->type & MN_FLOAT)
       
   916 	    spval->u.d--;
       
   917 	else
       
   918 	    spval->u.l--;
       
   919 	setvar(stack[sp].lval, *spval);
       
   920 	break;
       
   921     default:
       
   922 	zerr("out of integers", NULL, 0);
       
   923 	return;
       
   924     }
       
   925 }
       
   926 
       
   927 
       
   928 /**/
       
   929 static void
       
   930 bop(int tk)
       
   931 {
       
   932     mnumber *spval = &stack[sp].val;
       
   933     int tst;
       
   934 
       
   935     if (stack[sp].val.type == MN_UNSET)
       
   936 	*spval = getnparam(stack[sp].lval);
       
   937     tst = (spval->type & MN_FLOAT) ? (zlong)spval->u.d : spval->u.l; 
       
   938 
       
   939     switch (tk) {
       
   940     case DAND:
       
   941     case DANDEQ:
       
   942 	if (!tst)
       
   943 	    noeval++;
       
   944 	break;
       
   945     case DOR:
       
   946     case DOREQ:
       
   947 	if (tst)
       
   948 	    noeval++;
       
   949 	break;
       
   950     };
       
   951 }
       
   952 
       
   953 
       
   954 /**/
       
   955 static mnumber
       
   956 mathevall(char *s, int prek, char **ep)
       
   957 {
       
   958     int xlastbase, xnoeval, xunary;
       
   959     char *xptr;
       
   960     mnumber xyyval;
       
   961     char *xyylval;
       
   962     int xsp;
       
   963     struct mathvalue *xstack = 0, nstack[STACKSZ];
       
   964     mnumber ret;
       
   965 
       
   966     if (mlevel >= MAX_MLEVEL) {
       
   967 	xyyval.type = MN_INTEGER;
       
   968 	xyyval.u.l = 0;
       
   969 
       
   970 	zerr("math recursion limit exceeded", NULL, 0);
       
   971 
       
   972 	return xyyval;
       
   973     }
       
   974     if (mlevel++) {
       
   975 	xlastbase = lastbase;
       
   976 	xnoeval = noeval;
       
   977 	xunary = unary;
       
   978 	xptr = ptr;
       
   979 	xyyval = yyval;
       
   980 	xyylval = yylval;
       
   981 
       
   982 	xsp = sp;
       
   983 	xstack = stack;
       
   984     } else {
       
   985 	xlastbase = xnoeval = xunary = xsp = 0;
       
   986 	xyyval.type = MN_INTEGER;
       
   987 	xyyval.u.l = 0;
       
   988 	xyylval = NULL;
       
   989 	xptr = NULL;
       
   990     }
       
   991     stack = nstack;
       
   992     lastbase = -1;
       
   993     ptr = s;
       
   994     sp = -1;
       
   995     unary = 1;
       
   996     stack[0].val.type = MN_INTEGER;
       
   997     stack[0].val.u.l = 0;
       
   998     mathparse(prek);
       
   999     *ep = ptr;
       
  1000     DPUTS(!errflag && sp > 0,
       
  1001 	  "BUG: math: wallabies roaming too freely in outback");
       
  1002 
       
  1003     if (errflag) {
       
  1004 	ret.type = MN_INTEGER;
       
  1005 	ret.u.l = errflag;
       
  1006     } else {
       
  1007 	if (stack[0].val.type == MN_UNSET)
       
  1008 	    ret = getnparam(stack[0].lval);
       
  1009 	else
       
  1010 	    ret = stack[0].val;
       
  1011     }
       
  1012 
       
  1013     if (--mlevel) {
       
  1014 	lastbase = xlastbase;
       
  1015 	noeval = xnoeval;
       
  1016 	unary = xunary;
       
  1017 	ptr = xptr;
       
  1018 	yyval = xyyval;
       
  1019 	yylval = xyylval;
       
  1020 
       
  1021 	sp = xsp;
       
  1022 	stack = xstack;
       
  1023     }
       
  1024     return ret;
       
  1025 }
       
  1026 
       
  1027 
       
  1028 /**/
       
  1029 mod_export mnumber
       
  1030 matheval(char *s)
       
  1031 {
       
  1032     char *junk;
       
  1033     mnumber x;
       
  1034     int xmtok = mtok;
       
  1035     /* maintain outputradix across levels of evaluation */
       
  1036     if (!mlevel)
       
  1037 	outputradix = 0;
       
  1038 
       
  1039     if (!*s) {
       
  1040 	x.type = MN_INTEGER;
       
  1041 	x.u.l = 0;
       
  1042 	return x;
       
  1043     }
       
  1044     x = mathevall(s, TOPPREC, &junk);
       
  1045     mtok = xmtok;
       
  1046     if (*junk)
       
  1047 	zerr("bad math expression: illegal character: %c", NULL, *junk);
       
  1048     return x;
       
  1049 }
       
  1050 
       
  1051 /**/
       
  1052 mod_export zlong
       
  1053 mathevali(char *s)
       
  1054 {
       
  1055     mnumber x = matheval(s);
       
  1056     return (x.type & MN_FLOAT) ? (zlong)x.u.d : x.u.l;
       
  1057 }
       
  1058 
       
  1059 
       
  1060 /**/
       
  1061 zlong
       
  1062 mathevalarg(char *s, char **ss)
       
  1063 {
       
  1064     mnumber x;
       
  1065     int xmtok = mtok;
       
  1066 
       
  1067     x = mathevall(s, ARGPREC, ss);
       
  1068     if (mtok == COMMA)
       
  1069 	(*ss)--;
       
  1070     mtok = xmtok;
       
  1071     return (x.type & MN_FLOAT) ? (zlong)x.u.d : x.u.l;
       
  1072 }
       
  1073 
       
  1074 /*
       
  1075  * Make sure we have an operator or an operand, whatever is expected.
       
  1076  * For this purpose, unary operators constitute part of an operand.
       
  1077  */
       
  1078 
       
  1079 /**/
       
  1080 static void
       
  1081 checkunary(int mtokc, char *mptr)
       
  1082 {
       
  1083     int errmsg = 0;
       
  1084     int tp = type[mtokc];
       
  1085     if (tp & (OP_A2|OP_A2IR|OP_A2IO|OP_E2|OP_E2IO|OP_OP)) {
       
  1086 	if (unary)
       
  1087 	    errmsg = 1;
       
  1088     } else {
       
  1089 	if (!unary)
       
  1090 	    errmsg = 2;
       
  1091     }
       
  1092     if (errmsg) {
       
  1093 	char errbuf[80];
       
  1094 	int len, over = 0;
       
  1095 	while (inblank(*mptr))
       
  1096 	    mptr++;
       
  1097 	len = ztrlen(mptr);
       
  1098 	if (len > 10) {
       
  1099 	    len = 10;
       
  1100 	    over = 1;
       
  1101 	}
       
  1102 	sprintf(errbuf, "bad math expression: %s expected at `%%l%s'",
       
  1103 		errmsg == 2 ? "operator" : "operand",
       
  1104 		over ? "..." : ""); 
       
  1105 	zerr(errbuf, mptr, len);
       
  1106     }
       
  1107     unary = !(tp & OP_OPF);
       
  1108 }
       
  1109 
       
  1110 /* operator-precedence parse the string and execute */
       
  1111 
       
  1112 /**/
       
  1113 static void
       
  1114 mathparse(int pc)
       
  1115 {
       
  1116     zlong q;
       
  1117     int otok, onoeval;
       
  1118     char *optr = ptr;
       
  1119 
       
  1120     if (errflag)
       
  1121 	return;
       
  1122     mtok = zzlex();
       
  1123     /* Handle empty input */
       
  1124     if (pc == TOPPREC && mtok == EOI)
       
  1125 	return;
       
  1126     checkunary(mtok, optr);
       
  1127     while (prec[mtok] <= pc) {
       
  1128 	if (errflag)
       
  1129 	    return;
       
  1130 	switch (mtok) {
       
  1131 	case NUM:
       
  1132 	    push(yyval, NULL, 0);
       
  1133 	    break;
       
  1134 	case ID:
       
  1135 	    push(zero_mnumber, yylval, !noeval);
       
  1136 	    break;
       
  1137 	case CID:
       
  1138 	    push((noeval ? zero_mnumber : getcvar(yylval)), yylval, 0);
       
  1139 	    break;
       
  1140 	case FUNC:
       
  1141 	    push((noeval ? zero_mnumber : callmathfunc(yylval)), yylval, 0);
       
  1142 	    break;
       
  1143 	case M_INPAR:
       
  1144 	    mathparse(TOPPREC);
       
  1145 	    if (mtok != M_OUTPAR) {
       
  1146 		if (!errflag)
       
  1147 		    zerr("')' expected", NULL, 0);
       
  1148 		return;
       
  1149 	    }
       
  1150 	    break;
       
  1151 	case QUEST:
       
  1152 	    if (stack[sp].val.type == MN_UNSET)
       
  1153 		stack[sp].val = getnparam(stack[sp].lval);
       
  1154 	    q = (stack[sp].val.type == MN_FLOAT) ? (zlong)stack[sp].val.u.d :
       
  1155 		stack[sp].val.u.l;
       
  1156 
       
  1157 	    if (!q)
       
  1158 		noeval++;
       
  1159 	    mathparse(prec[COLON] - 1);
       
  1160 	    if (!q)
       
  1161 		noeval--;
       
  1162 	    if (mtok != COLON) {
       
  1163 		if (!errflag)
       
  1164 		    zerr("':' expected", NULL, 0);
       
  1165 		return;
       
  1166 	    }
       
  1167 	    if (q)
       
  1168 		noeval++;
       
  1169 	    mathparse(prec[QUEST]);
       
  1170 	    if (q)
       
  1171 		noeval--;
       
  1172 	    op(QUEST);
       
  1173 	    continue;
       
  1174 	default:
       
  1175 	    otok = mtok;
       
  1176 	    onoeval = noeval;
       
  1177 	    if (MTYPE(type[otok]) == BOOL)
       
  1178 		bop(otok);
       
  1179 	    mathparse(prec[otok] - (MTYPE(type[otok]) != RL));
       
  1180 	    noeval = onoeval;
       
  1181 	    op(otok);
       
  1182 	    continue;
       
  1183 	}
       
  1184 	optr = ptr;
       
  1185 	mtok = zzlex();
       
  1186 	checkunary(mtok, optr);
       
  1187     }
       
  1188 }