1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * David Korn <dgk@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin 22*4887Schin /* 23*4887Schin * D. G. Korn 24*4887Schin * AT&T Labs 25*4887Schin * 26*4887Schin * arithmetic expression evaluator 27*4887Schin * 28*4887Schin * this version compiles the expression onto a stack 29*4887Schin * and has a separate executor 30*4887Schin */ 31*4887Schin 32*4887Schin #include "streval.h" 33*4887Schin #include <ctype.h> 34*4887Schin #include <error.h> 35*4887Schin #include <stak.h> 36*4887Schin #include "FEATURE/externs" 37*4887Schin 38*4887Schin #ifndef ERROR_dictionary 39*4887Schin # define ERROR_dictionary(s) (s) 40*4887Schin #endif 41*4887Schin #ifndef SH_DICT 42*4887Schin # define SH_DICT "libshell" 43*4887Schin #endif 44*4887Schin 45*4887Schin #define MAXLEVEL 9 46*4887Schin #define SMALL_STACK 12 47*4887Schin 48*4887Schin /* 49*4887Schin * The following are used with tokenbits() macro 50*4887Schin */ 51*4887Schin #define T_OP 0x3f /* mask for operator number */ 52*4887Schin #define T_BINARY 0x40 /* binary operators */ 53*4887Schin #define T_NOFLOAT 0x80 /* non floating point operator */ 54*4887Schin #define A_LVALUE (2*MAXPREC+2) 55*4887Schin 56*4887Schin #define pow2size(x) ((x)<=2?2:(x)<=4?4:(x)<=8?8:(x)<=16?16:(x)<=32?32:64) 57*4887Schin #define round(x,size) (((x)+(size)-1)&~((size)-1)) 58*4887Schin #define stakpush(v,val,type) ((((v)->offset=round(staktell(),pow2size(sizeof(type)))),\ 59*4887Schin stakseek((v)->offset+sizeof(type)), \ 60*4887Schin *((type*)stakptr((v)->offset)) = (val)),(v)->offset) 61*4887Schin #define roundptr(ep,cp,type) (((unsigned char*)(ep))+round(cp-((unsigned char*)(ep)),pow2size(sizeof(type)))) 62*4887Schin 63*4887Schin static int level; 64*4887Schin 65*4887Schin struct vars /* vars stacked per invocation */ 66*4887Schin { 67*4887Schin const char *expr; /* current expression */ 68*4887Schin const char *nextchr; /* next char in current expression */ 69*4887Schin const char *errchr; /* next char after error */ 70*4887Schin const char *errstr; /* error string */ 71*4887Schin struct lval errmsg; /* error message text */ 72*4887Schin int offset; /* offset for pushchr macro */ 73*4887Schin int staksize; /* current stack size needed */ 74*4887Schin int stakmaxsize; /* maximum stack size needed */ 75*4887Schin unsigned char paren; /* parenthesis level */ 76*4887Schin char infun; /* incremented by comma inside function */ 77*4887Schin int emode; 78*4887Schin Sfdouble_t (*convert)(const char**,struct lval*,int,Sfdouble_t); 79*4887Schin }; 80*4887Schin 81*4887Schin typedef int (*Math_0_f)(Sfdouble_t); 82*4887Schin typedef Sfdouble_t (*Fun_t)(Sfdouble_t,...); 83*4887Schin typedef Sfdouble_t (*Math_1_f)(Sfdouble_t); 84*4887Schin typedef Sfdouble_t (*Math_2_f)(Sfdouble_t,Sfdouble_t); 85*4887Schin typedef Sfdouble_t (*Math_3_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t); 86*4887Schin 87*4887Schin #define getchr(vp) (*(vp)->nextchr++) 88*4887Schin #define peekchr(vp) (*(vp)->nextchr) 89*4887Schin #define ungetchr(vp) ((vp)->nextchr--) 90*4887Schin 91*4887Schin #if ('a'==97) /* ASCII encodings */ 92*4887Schin # define getop(c) (((c) >= sizeof(strval_states))? \ 93*4887Schin ((c)=='|'?A_OR:((c)=='^'?A_XOR:((c)=='~'?A_TILDE:A_REG))):\ 94*4887Schin strval_states[(c)]) 95*4887Schin #else 96*4887Schin # define getop(c) (isdigit(c)?A_DIG:((c==' '||c=='\t'||c=='\n'||c=='"')?0: \ 97*4887Schin (c=='<'?A_LT:(c=='>'?A_GT:(c=='='?A_ASSIGN: \ 98*4887Schin (c=='+'?A_PLUS:(c=='-'?A_MINUS:(c=='*'?A_TIMES: \ 99*4887Schin (c=='/'?A_DIV:(c=='%'?A_MOD:(c==','?A_COMMA: \ 100*4887Schin (c=='&'?A_AND:(c=='!'?A_NOT:(c=='('?A_LPAR: \ 101*4887Schin (c==')'?A_RPAR:(c==0?A_EOF:(c==':'?A_COLON: \ 102*4887Schin (c=='?'?A_QUEST:(c=='|'?A_OR:(c=='^'?A_XOR: \ 103*4887Schin (c=='\''?A_LIT: \ 104*4887Schin (c=='.'?A_DOT:(c=='~'?A_TILDE:A_REG))))))))))))))))))))))) 105*4887Schin #endif 106*4887Schin 107*4887Schin #define seterror(v,msg) _seterror(v,ERROR_dictionary(msg)) 108*4887Schin #define ERROR(vp,msg) return(seterror((vp),msg)) 109*4887Schin 110*4887Schin /* 111*4887Schin * set error message string and return(0) 112*4887Schin */ 113*4887Schin static int _seterror(struct vars *vp,const char *msg) 114*4887Schin { 115*4887Schin if(!vp->errmsg.value) 116*4887Schin vp->errmsg.value = (char*)msg; 117*4887Schin vp->errchr = vp->nextchr; 118*4887Schin vp->nextchr = ""; 119*4887Schin level = 0; 120*4887Schin return(0); 121*4887Schin } 122*4887Schin 123*4887Schin 124*4887Schin static void arith_error(const char *message,const char *expr, int mode) 125*4887Schin { 126*4887Schin level = 0; 127*4887Schin mode = (mode&3)!=0; 128*4887Schin errormsg(SH_DICT,ERROR_exit(mode),message,expr); 129*4887Schin } 130*4887Schin 131*4887Schin #if _ast_no_um2fm 132*4887Schin static Sfdouble_t U2F(Sfulong_t u) 133*4887Schin { 134*4887Schin Sflong_t s = u; 135*4887Schin Sfdouble_t f; 136*4887Schin 137*4887Schin if (s >= 0) 138*4887Schin return s; 139*4887Schin s = u / 2; 140*4887Schin f = s; 141*4887Schin f *= 2; 142*4887Schin if (u & 1) 143*4887Schin f++; 144*4887Schin return f; 145*4887Schin } 146*4887Schin #else 147*4887Schin #define U2F(x) x 148*4887Schin #endif 149*4887Schin 150*4887Schin Sfdouble_t arith_exec(Arith_t *ep) 151*4887Schin { 152*4887Schin register Sfdouble_t num=0,*dp,*sp; 153*4887Schin register unsigned char *cp = ep->code; 154*4887Schin register int c,type=0; 155*4887Schin register char *tp; 156*4887Schin Sfdouble_t small_stack[SMALL_STACK+1]; 157*4887Schin const char *ptr = ""; 158*4887Schin Fun_t fun; 159*4887Schin struct lval node; 160*4887Schin node.emode = ep->emode; 161*4887Schin node.expr = ep->expr; 162*4887Schin node.elen = ep->elen; 163*4887Schin if(level++ >=MAXLEVEL) 164*4887Schin { 165*4887Schin arith_error(e_recursive,ep->expr,ep->emode); 166*4887Schin return(0); 167*4887Schin } 168*4887Schin if(ep->staksize < SMALL_STACK) 169*4887Schin sp = small_stack; 170*4887Schin else 171*4887Schin sp = (Sfdouble_t*)stakalloc(ep->staksize*(sizeof(Sfdouble_t)+1)); 172*4887Schin tp = (char*)(sp+ep->staksize); 173*4887Schin tp--,sp--; 174*4887Schin while(c = *cp++) 175*4887Schin { 176*4887Schin if(c&T_NOFLOAT) 177*4887Schin { 178*4887Schin if(type==1 || ((c&T_BINARY) && (c&T_OP)!=A_MOD && tp[-1]==1)) 179*4887Schin arith_error(e_incompatible,ep->expr,ep->emode); 180*4887Schin } 181*4887Schin switch(c&T_OP) 182*4887Schin { 183*4887Schin case A_JMP: case A_JMPZ: case A_JMPNZ: 184*4887Schin c &= T_OP; 185*4887Schin cp = roundptr(ep,cp,short); 186*4887Schin if((c==A_JMPZ && num) || (c==A_JMPNZ &&!num)) 187*4887Schin cp += sizeof(short); 188*4887Schin else 189*4887Schin cp = (unsigned char*)ep + *((short*)cp); 190*4887Schin continue; 191*4887Schin case A_NOTNOT: 192*4887Schin num = (num!=0); 193*4887Schin type=0; 194*4887Schin break; 195*4887Schin case A_PLUSPLUS: 196*4887Schin (*ep->fun)(&ptr,&node,ASSIGN,num+1); 197*4887Schin break; 198*4887Schin case A_MINUSMINUS: 199*4887Schin (*ep->fun)(&ptr,&node,ASSIGN,num-1); 200*4887Schin break; 201*4887Schin case A_INCR: 202*4887Schin num = num+1; 203*4887Schin num = (*ep->fun)(&ptr,&node,ASSIGN,num); 204*4887Schin break; 205*4887Schin case A_DECR: 206*4887Schin num = num-1; 207*4887Schin num = (*ep->fun)(&ptr,&node,ASSIGN,num); 208*4887Schin break; 209*4887Schin case A_SWAP: 210*4887Schin num = sp[-1]; 211*4887Schin sp[-1] = *sp; 212*4887Schin type = tp[-1]; 213*4887Schin tp[-1] = *tp; 214*4887Schin break; 215*4887Schin case A_POP: 216*4887Schin sp--; 217*4887Schin continue; 218*4887Schin case A_PUSHV: 219*4887Schin cp = roundptr(ep,cp,Sfdouble_t*); 220*4887Schin dp = *((Sfdouble_t**)cp); 221*4887Schin cp += sizeof(Sfdouble_t*); 222*4887Schin c = *(short*)cp; 223*4887Schin cp += sizeof(short); 224*4887Schin node.value = (char*)dp; 225*4887Schin node.flag = c; 226*4887Schin node.isfloat=0; 227*4887Schin node.level = level; 228*4887Schin num = (*ep->fun)(&ptr,&node,VALUE,num); 229*4887Schin if(node.value != (char*)dp) 230*4887Schin arith_error(node.value,ptr,ep->emode); 231*4887Schin *++sp = num; 232*4887Schin type = node.isfloat; 233*4887Schin if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN) 234*4887Schin type = 1; 235*4887Schin else 236*4887Schin { 237*4887Schin Sfdouble_t d=num; 238*4887Schin if(num > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX) 239*4887Schin { 240*4887Schin type = 2; 241*4887Schin d -= LDBL_LLONG_MAX; 242*4887Schin } 243*4887Schin if((Sflong_t)d!=d) 244*4887Schin type = 1; 245*4887Schin } 246*4887Schin *++tp = type; 247*4887Schin c = 0; 248*4887Schin break; 249*4887Schin case A_STORE: 250*4887Schin cp = roundptr(ep,cp,Sfdouble_t*); 251*4887Schin dp = *((Sfdouble_t**)cp); 252*4887Schin cp += sizeof(Sfdouble_t*); 253*4887Schin c = *(short*)cp; 254*4887Schin if(c<0) 255*4887Schin c = 0; 256*4887Schin cp += sizeof(short); 257*4887Schin node.value = (char*)dp; 258*4887Schin node.flag = c; 259*4887Schin num = (*ep->fun)(&ptr,&node,ASSIGN,num); 260*4887Schin break; 261*4887Schin case A_PUSHF: 262*4887Schin cp = roundptr(ep,cp,Fun_t); 263*4887Schin *++sp = (Sfdouble_t)(cp-ep->code); 264*4887Schin cp += sizeof(Fun_t); 265*4887Schin *++tp = *cp++; 266*4887Schin continue; 267*4887Schin case A_PUSHN: 268*4887Schin cp = roundptr(ep,cp,Sfdouble_t); 269*4887Schin num = *((Sfdouble_t*)cp); 270*4887Schin cp += sizeof(Sfdouble_t); 271*4887Schin *++sp = num; 272*4887Schin *++tp = type = *cp++; 273*4887Schin break; 274*4887Schin case A_NOT: 275*4887Schin type=0; 276*4887Schin num = !num; 277*4887Schin break; 278*4887Schin case A_UMINUS: 279*4887Schin num = -num; 280*4887Schin break; 281*4887Schin case A_TILDE: 282*4887Schin num = ~((Sflong_t)(num)); 283*4887Schin break; 284*4887Schin case A_PLUS: 285*4887Schin num += sp[-1]; 286*4887Schin break; 287*4887Schin case A_MINUS: 288*4887Schin num = sp[-1] - num; 289*4887Schin break; 290*4887Schin case A_TIMES: 291*4887Schin num *= sp[-1]; 292*4887Schin break; 293*4887Schin case A_POW: 294*4887Schin num = pow(sp[-1],num); 295*4887Schin break; 296*4887Schin case A_MOD: 297*4887Schin if(!(Sflong_t)num) 298*4887Schin arith_error(e_divzero,ep->expr,ep->emode); 299*4887Schin if(type==2 || tp[-1]==2) 300*4887Schin num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num)); 301*4887Schin else 302*4887Schin num = (Sflong_t)(sp[-1]) % (Sflong_t)(num); 303*4887Schin break; 304*4887Schin case A_DIV: 305*4887Schin if(type==1 || tp[-1]==1) 306*4887Schin { 307*4887Schin num = sp[-1]/num; 308*4887Schin type = 1; 309*4887Schin } 310*4887Schin else if((Sfulong_t)(num)==0) 311*4887Schin arith_error(e_divzero,ep->expr,ep->emode); 312*4887Schin else if(type==2 || tp[-1]==2) 313*4887Schin num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num)); 314*4887Schin else 315*4887Schin num = (Sflong_t)(sp[-1]) / (Sflong_t)(num); 316*4887Schin break; 317*4887Schin case A_LSHIFT: 318*4887Schin if(tp[-1]==2) 319*4887Schin num = U2F((Sfulong_t)(sp[-1]) << (long)(num)); 320*4887Schin else 321*4887Schin num = (Sflong_t)(sp[-1]) << (long)(num); 322*4887Schin break; 323*4887Schin case A_RSHIFT: 324*4887Schin if(tp[-1]==2) 325*4887Schin num = U2F((Sfulong_t)(sp[-1]) >> (long)(num)); 326*4887Schin else 327*4887Schin num = (Sflong_t)(sp[-1]) >> (long)(num); 328*4887Schin break; 329*4887Schin case A_XOR: 330*4887Schin if(type==2 || tp[-1]==2) 331*4887Schin num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num)); 332*4887Schin else 333*4887Schin num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num); 334*4887Schin break; 335*4887Schin case A_OR: 336*4887Schin if(type==2 || tp[-1]==2) 337*4887Schin num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num)); 338*4887Schin else 339*4887Schin num = (Sflong_t)(sp[-1]) | (Sflong_t)(num); 340*4887Schin break; 341*4887Schin case A_AND: 342*4887Schin if(type==2 || tp[-1]==2) 343*4887Schin num = U2F((Sfulong_t)(sp[-1]) & (Sfulong_t)(num)); 344*4887Schin else 345*4887Schin num = (Sflong_t)(sp[-1]) & (Sflong_t)(num); 346*4887Schin break; 347*4887Schin case A_EQ: 348*4887Schin num = (sp[-1]==num); 349*4887Schin type=0; 350*4887Schin break; 351*4887Schin case A_NEQ: 352*4887Schin num = (sp[-1]!=num); 353*4887Schin type=0; 354*4887Schin break; 355*4887Schin case A_LE: 356*4887Schin num = (sp[-1]<=num); 357*4887Schin type=0; 358*4887Schin break; 359*4887Schin case A_GE: 360*4887Schin num = (sp[-1]>=num); 361*4887Schin type=0; 362*4887Schin break; 363*4887Schin case A_GT: 364*4887Schin num = (sp[-1]>num); 365*4887Schin type=0; 366*4887Schin break; 367*4887Schin case A_LT: 368*4887Schin num = (sp[-1]<num); 369*4887Schin type=0; 370*4887Schin break; 371*4887Schin case A_CALL0: 372*4887Schin sp--,tp--; 373*4887Schin fun = *((Fun_t*)(ep->code+(int)(*sp))); 374*4887Schin type = 0; 375*4887Schin num = (*((Math_0_f)fun))(num); 376*4887Schin break; 377*4887Schin case A_CALL1: 378*4887Schin sp--,tp--; 379*4887Schin fun = *((Fun_t*)(ep->code+(int)(*sp))); 380*4887Schin type = *tp; 381*4887Schin num = (*fun)(num); 382*4887Schin break; 383*4887Schin case A_CALL2: 384*4887Schin sp-=2,tp-=2; 385*4887Schin fun = *((Fun_t*)(ep->code+(int)(*sp))); 386*4887Schin type = *tp; 387*4887Schin num = (*((Math_2_f)fun))(sp[1],num); 388*4887Schin break; 389*4887Schin case A_CALL3: 390*4887Schin sp-=3,tp-=3; 391*4887Schin fun = *((Fun_t*)(ep->code+(int)(*sp))); 392*4887Schin type = *tp; 393*4887Schin num = (*((Math_3_f)fun))(sp[1],sp[2],num); 394*4887Schin break; 395*4887Schin } 396*4887Schin if(c&T_BINARY) 397*4887Schin sp--,tp--; 398*4887Schin *sp = num; 399*4887Schin *tp = type; 400*4887Schin } 401*4887Schin if(level>0) 402*4887Schin level--; 403*4887Schin return(num); 404*4887Schin } 405*4887Schin 406*4887Schin /* 407*4887Schin * This returns operator tokens or A_REG or A_NUM 408*4887Schin */ 409*4887Schin static int gettok(register struct vars *vp) 410*4887Schin { 411*4887Schin register int c,op; 412*4887Schin vp->errchr = vp->nextchr; 413*4887Schin while(1) 414*4887Schin { 415*4887Schin c = getchr(vp); 416*4887Schin switch(op=getop(c)) 417*4887Schin { 418*4887Schin case 0: 419*4887Schin vp->errchr = vp->nextchr; 420*4887Schin continue; 421*4887Schin case A_EOF: 422*4887Schin vp->nextchr--; 423*4887Schin break; 424*4887Schin /*FALL THRU*/ 425*4887Schin case A_DIG: case A_REG: case A_DOT: case A_LIT: 426*4887Schin if(op==A_DOT) 427*4887Schin { 428*4887Schin if((c=peekchr(vp))>='0' && c<='9') 429*4887Schin op = A_DIG; 430*4887Schin else 431*4887Schin op = A_REG; 432*4887Schin } 433*4887Schin ungetchr(vp); 434*4887Schin break; 435*4887Schin case A_QUEST: 436*4887Schin if(peekchr(vp)==':') 437*4887Schin { 438*4887Schin getchr(vp); 439*4887Schin op = A_QCOLON; 440*4887Schin } 441*4887Schin break; 442*4887Schin case A_LT: case A_GT: 443*4887Schin if(peekchr(vp)==c) 444*4887Schin { 445*4887Schin getchr(vp); 446*4887Schin op -= 2; 447*4887Schin break; 448*4887Schin } 449*4887Schin /* FALL THRU */ 450*4887Schin case A_NOT: case A_COLON: 451*4887Schin c = '='; 452*4887Schin /* FALL THRU */ 453*4887Schin case A_ASSIGN: 454*4887Schin case A_TIMES: 455*4887Schin case A_PLUS: case A_MINUS: 456*4887Schin case A_OR: case A_AND: 457*4887Schin if(peekchr(vp)==c) 458*4887Schin { 459*4887Schin getchr(vp); 460*4887Schin op--; 461*4887Schin } 462*4887Schin } 463*4887Schin return(op); 464*4887Schin } 465*4887Schin } 466*4887Schin 467*4887Schin /* 468*4887Schin * evaluate a subexpression with precedence 469*4887Schin */ 470*4887Schin 471*4887Schin static int expr(register struct vars *vp,register int precedence) 472*4887Schin { 473*4887Schin register int c, op; 474*4887Schin int invalid,wasop=0; 475*4887Schin struct lval lvalue,assignop; 476*4887Schin const char *pos; 477*4887Schin Sfdouble_t d; 478*4887Schin 479*4887Schin lvalue.value = 0; 480*4887Schin lvalue.fun = 0; 481*4887Schin again: 482*4887Schin op = gettok(vp); 483*4887Schin c = 2*MAXPREC+1; 484*4887Schin switch(op) 485*4887Schin { 486*4887Schin case A_PLUS: 487*4887Schin goto again; 488*4887Schin case A_EOF: 489*4887Schin if(precedence>5) 490*4887Schin ERROR(vp,e_moretokens); 491*4887Schin return(1); 492*4887Schin case A_MINUS: 493*4887Schin op = A_UMINUS; 494*4887Schin goto common; 495*4887Schin case A_NOT: 496*4887Schin goto common; 497*4887Schin case A_MINUSMINUS: 498*4887Schin c = A_LVALUE; 499*4887Schin op = A_DECR|T_NOFLOAT; 500*4887Schin goto common; 501*4887Schin case A_PLUSPLUS: 502*4887Schin c = A_LVALUE; 503*4887Schin op = A_INCR|T_NOFLOAT; 504*4887Schin /* FALL THRU */ 505*4887Schin case A_TILDE: 506*4887Schin op |= T_NOFLOAT; 507*4887Schin common: 508*4887Schin if(!expr(vp,c)) 509*4887Schin return(0); 510*4887Schin stakputc(op); 511*4887Schin break; 512*4887Schin default: 513*4887Schin vp->nextchr = vp->errchr; 514*4887Schin wasop = 1; 515*4887Schin } 516*4887Schin invalid = wasop; 517*4887Schin while(1) 518*4887Schin { 519*4887Schin assignop.value = 0; 520*4887Schin op = gettok(vp); 521*4887Schin if(op==A_DIG || op==A_REG || op==A_LIT) 522*4887Schin { 523*4887Schin if(!wasop) 524*4887Schin ERROR(vp,e_synbad); 525*4887Schin goto number; 526*4887Schin } 527*4887Schin if(wasop++ && op!=A_LPAR) 528*4887Schin ERROR(vp,e_synbad); 529*4887Schin /* check for assignment operation */ 530*4887Schin if(peekchr(vp)== '=' && !(strval_precedence[op]&NOASSIGN)) 531*4887Schin { 532*4887Schin if((!lvalue.value || precedence > 3)) 533*4887Schin ERROR(vp,e_notlvalue); 534*4887Schin if(precedence==3) 535*4887Schin precedence = 2; 536*4887Schin assignop = lvalue; 537*4887Schin getchr(vp); 538*4887Schin c = 3; 539*4887Schin } 540*4887Schin else 541*4887Schin { 542*4887Schin c = (strval_precedence[op]&PRECMASK); 543*4887Schin if(c==MAXPREC || op==A_POW) 544*4887Schin c++; 545*4887Schin c *= 2; 546*4887Schin } 547*4887Schin /* from here on c is the new precedence level */ 548*4887Schin if(lvalue.value && (op!=A_ASSIGN)) 549*4887Schin { 550*4887Schin if(vp->staksize++>=vp->stakmaxsize) 551*4887Schin vp->stakmaxsize = vp->staksize; 552*4887Schin stakputc(A_PUSHV); 553*4887Schin stakpush(vp,lvalue.value,char*); 554*4887Schin if(lvalue.flag<0) 555*4887Schin lvalue.flag = 0; 556*4887Schin stakpush(vp,lvalue.flag,short); 557*4887Schin if(vp->nextchr==0) 558*4887Schin ERROR(vp,e_badnum); 559*4887Schin if(!(strval_precedence[op]&SEQPOINT)) 560*4887Schin lvalue.value = 0; 561*4887Schin invalid = 0; 562*4887Schin } 563*4887Schin else if(precedence==A_LVALUE) 564*4887Schin ERROR(vp,e_notlvalue); 565*4887Schin if(invalid && op>A_ASSIGN) 566*4887Schin ERROR(vp,e_synbad); 567*4887Schin if(precedence >= c) 568*4887Schin goto done; 569*4887Schin if(strval_precedence[op]&RASSOC) 570*4887Schin c--; 571*4887Schin if((c < (2*MAXPREC+1)) && !(strval_precedence[op]&SEQPOINT)) 572*4887Schin { 573*4887Schin wasop = 0; 574*4887Schin if(!expr(vp,c)) 575*4887Schin return(0); 576*4887Schin } 577*4887Schin switch(op) 578*4887Schin { 579*4887Schin case A_RPAR: 580*4887Schin if(!vp->paren) 581*4887Schin ERROR(vp,e_paren); 582*4887Schin if(invalid) 583*4887Schin ERROR(vp,e_synbad); 584*4887Schin goto done; 585*4887Schin 586*4887Schin case A_COMMA: 587*4887Schin wasop = 0; 588*4887Schin if(vp->infun) 589*4887Schin vp->infun++; 590*4887Schin else 591*4887Schin { 592*4887Schin stakputc(A_POP); 593*4887Schin vp->staksize--; 594*4887Schin } 595*4887Schin if(!expr(vp,c)) 596*4887Schin return(0); 597*4887Schin lvalue.value = 0; 598*4887Schin break; 599*4887Schin 600*4887Schin case A_LPAR: 601*4887Schin { 602*4887Schin int infun = vp->infun; 603*4887Schin Sfdouble_t (*fun)(Sfdouble_t,...); 604*4887Schin int nargs = lvalue.nargs; 605*4887Schin fun = lvalue.fun; 606*4887Schin lvalue.fun = 0; 607*4887Schin if(fun) 608*4887Schin { 609*4887Schin if(vp->staksize++>=vp->stakmaxsize) 610*4887Schin vp->stakmaxsize = vp->staksize; 611*4887Schin vp->infun=1; 612*4887Schin stakputc(A_PUSHF); 613*4887Schin stakpush(vp,fun,Fun_t); 614*4887Schin stakputc(1); 615*4887Schin } 616*4887Schin else 617*4887Schin vp->infun = 0; 618*4887Schin if(!invalid) 619*4887Schin ERROR(vp,e_synbad); 620*4887Schin vp->paren++; 621*4887Schin if(!expr(vp,1)) 622*4887Schin return(0); 623*4887Schin vp->paren--; 624*4887Schin if(fun) 625*4887Schin { 626*4887Schin int x= (nargs>7); 627*4887Schin nargs &= 7; 628*4887Schin if(vp->infun != nargs) 629*4887Schin ERROR(vp,e_argcount); 630*4887Schin if(vp->staksize+=nargs>=vp->stakmaxsize) 631*4887Schin vp->stakmaxsize = vp->staksize+nargs; 632*4887Schin stakputc(A_CALL0+nargs -x); 633*4887Schin vp->staksize -= nargs; 634*4887Schin } 635*4887Schin vp->infun = infun; 636*4887Schin if (gettok(vp) != A_RPAR) 637*4887Schin ERROR(vp,e_paren); 638*4887Schin wasop = 0; 639*4887Schin break; 640*4887Schin } 641*4887Schin 642*4887Schin case A_PLUSPLUS: 643*4887Schin case A_MINUSMINUS: 644*4887Schin wasop=0; 645*4887Schin op |= T_NOFLOAT; 646*4887Schin case A_ASSIGN: 647*4887Schin if(!lvalue.value) 648*4887Schin ERROR(vp,e_notlvalue); 649*4887Schin if(op==A_ASSIGN) 650*4887Schin { 651*4887Schin stakputc(A_STORE); 652*4887Schin stakpush(vp,lvalue.value,char*); 653*4887Schin stakpush(vp,lvalue.flag,short); 654*4887Schin vp->staksize--; 655*4887Schin } 656*4887Schin else 657*4887Schin stakputc(op); 658*4887Schin lvalue.value = 0; 659*4887Schin break; 660*4887Schin 661*4887Schin case A_QUEST: 662*4887Schin { 663*4887Schin int offset1,offset2; 664*4887Schin stakputc(A_JMPZ); 665*4887Schin offset1 = stakpush(vp,0,short); 666*4887Schin stakputc(A_POP); 667*4887Schin if(!expr(vp,1)) 668*4887Schin return(0); 669*4887Schin if(gettok(vp)!=A_COLON) 670*4887Schin ERROR(vp,e_questcolon); 671*4887Schin stakputc(A_JMP); 672*4887Schin offset2 = stakpush(vp,0,short); 673*4887Schin *((short*)stakptr(offset1)) = staktell(); 674*4887Schin stakputc(A_POP); 675*4887Schin if(!expr(vp,3)) 676*4887Schin return(0); 677*4887Schin *((short*)stakptr(offset2)) = staktell(); 678*4887Schin lvalue.value = 0; 679*4887Schin wasop = 0; 680*4887Schin break; 681*4887Schin } 682*4887Schin 683*4887Schin case A_COLON: 684*4887Schin ERROR(vp,e_badcolon); 685*4887Schin break; 686*4887Schin 687*4887Schin case A_QCOLON: 688*4887Schin case A_ANDAND: 689*4887Schin case A_OROR: 690*4887Schin { 691*4887Schin int offset; 692*4887Schin if(op==A_ANDAND) 693*4887Schin op = A_JMPZ; 694*4887Schin else 695*4887Schin op = A_JMPNZ; 696*4887Schin stakputc(op); 697*4887Schin offset = stakpush(vp,0,short); 698*4887Schin stakputc(A_POP); 699*4887Schin if(!expr(vp,c)) 700*4887Schin return(0); 701*4887Schin *((short*)stakptr(offset)) = staktell(); 702*4887Schin if(op!=A_QCOLON) 703*4887Schin stakputc(A_NOTNOT); 704*4887Schin lvalue.value = 0; 705*4887Schin wasop=0; 706*4887Schin break; 707*4887Schin } 708*4887Schin case A_AND: case A_OR: case A_XOR: case A_LSHIFT: 709*4887Schin case A_RSHIFT: case A_MOD: 710*4887Schin op |= T_NOFLOAT; 711*4887Schin /* FALL THRU */ 712*4887Schin case A_PLUS: case A_MINUS: case A_TIMES: case A_DIV: 713*4887Schin case A_EQ: case A_NEQ: case A_LT: case A_LE: 714*4887Schin case A_GT: case A_GE: case A_POW: 715*4887Schin stakputc(op|T_BINARY); 716*4887Schin vp->staksize--; 717*4887Schin break; 718*4887Schin case A_NOT: case A_TILDE: 719*4887Schin default: 720*4887Schin ERROR(vp,e_synbad); 721*4887Schin number: 722*4887Schin wasop = 0; 723*4887Schin if(*vp->nextchr=='L' && vp->nextchr[1]=='\'') 724*4887Schin { 725*4887Schin vp->nextchr++; 726*4887Schin op = A_LIT; 727*4887Schin } 728*4887Schin pos = vp->nextchr; 729*4887Schin lvalue.isfloat = 0; 730*4887Schin lvalue.expr = vp->expr; 731*4887Schin lvalue.emode = vp->emode; 732*4887Schin if(op==A_LIT) 733*4887Schin { 734*4887Schin /* character constants */ 735*4887Schin if(pos[1]=='\\' && pos[2]=='\'' && pos[3]!='\'') 736*4887Schin { 737*4887Schin d = '\\'; 738*4887Schin vp->nextchr +=2; 739*4887Schin } 740*4887Schin else 741*4887Schin d = chresc(pos+1,(char**)&vp->nextchr); 742*4887Schin /* posix allows the trailing ' to be optional */ 743*4887Schin if(*vp->nextchr=='\'') 744*4887Schin vp->nextchr++; 745*4887Schin } 746*4887Schin else 747*4887Schin d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0); 748*4887Schin if (vp->nextchr == pos) 749*4887Schin { 750*4887Schin if(vp->errmsg.value = lvalue.value) 751*4887Schin vp->errstr = pos; 752*4887Schin ERROR(vp,op==A_LIT?e_charconst:e_synbad); 753*4887Schin } 754*4887Schin if(op==A_DIG || op==A_LIT) 755*4887Schin { 756*4887Schin stakputc(A_PUSHN); 757*4887Schin if(vp->staksize++>=vp->stakmaxsize) 758*4887Schin vp->stakmaxsize = vp->staksize; 759*4887Schin stakpush(vp,d,Sfdouble_t); 760*4887Schin stakputc(lvalue.isfloat); 761*4887Schin } 762*4887Schin 763*4887Schin /* check for function call */ 764*4887Schin if(lvalue.fun) 765*4887Schin continue; 766*4887Schin break; 767*4887Schin } 768*4887Schin invalid = 0; 769*4887Schin if(assignop.value) 770*4887Schin { 771*4887Schin if(vp->staksize++>=vp->stakmaxsize) 772*4887Schin vp->stakmaxsize = vp->staksize; 773*4887Schin if(assignop.flag<0) 774*4887Schin assignop.flag = 0; 775*4887Schin stakputc(A_STORE); 776*4887Schin stakpush(vp,assignop.value,char*); 777*4887Schin stakpush(vp,assignop.flag,short); 778*4887Schin } 779*4887Schin } 780*4887Schin done: 781*4887Schin vp->nextchr = vp->errchr; 782*4887Schin return(1); 783*4887Schin } 784*4887Schin 785*4887Schin Arith_t *arith_compile(const char *string,char **last,Sfdouble_t(*fun)(const char**,struct lval*,int,Sfdouble_t),int emode) 786*4887Schin { 787*4887Schin struct vars cur; 788*4887Schin register Arith_t *ep; 789*4887Schin int offset; 790*4887Schin memset((void*)&cur,0,sizeof(cur)); 791*4887Schin cur.emode = emode; 792*4887Schin cur.expr = cur.nextchr = string; 793*4887Schin cur.convert = fun; 794*4887Schin cur.emode = emode; 795*4887Schin cur.errmsg.value = 0; 796*4887Schin cur.errmsg.emode = emode; 797*4887Schin stakseek(sizeof(Arith_t)); 798*4887Schin if(!expr(&cur,0) && cur.errmsg.value) 799*4887Schin { 800*4887Schin if(cur.errstr) 801*4887Schin string = cur.errstr; 802*4887Schin (*fun)( &string , &cur.errmsg, MESSAGE, 0); 803*4887Schin cur.nextchr = cur.errchr; 804*4887Schin } 805*4887Schin stakputc(0); 806*4887Schin offset = staktell(); 807*4887Schin ep = (Arith_t*)stakfreeze(0); 808*4887Schin ep->expr = string; 809*4887Schin ep->elen = strlen(string); 810*4887Schin ep->code = (unsigned char*)(ep+1); 811*4887Schin ep->fun = fun; 812*4887Schin ep->emode = emode; 813*4887Schin ep->size = offset - sizeof(Arith_t); 814*4887Schin ep->staksize = cur.stakmaxsize+1; 815*4887Schin if(last) 816*4887Schin *last = (char*)(cur.nextchr); 817*4887Schin return(ep); 818*4887Schin } 819*4887Schin 820*4887Schin /* 821*4887Schin * evaluate an integer arithmetic expression in s 822*4887Schin * 823*4887Schin * (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value) 824*4887Schin * is a user supplied conversion routine that is called when unknown 825*4887Schin * chars are encountered. 826*4887Schin * *end points to the part to be converted and must be adjusted by convert to 827*4887Schin * point to the next non-converted character; if typ is MESSAGE then string 828*4887Schin * points to an error message string 829*4887Schin * 830*4887Schin * NOTE: (*convert)() may call strval() 831*4887Schin */ 832*4887Schin 833*4887Schin Sfdouble_t strval(const char *s,char **end,Sfdouble_t(*conv)(const char**,struct lval*,int,Sfdouble_t),int emode) 834*4887Schin { 835*4887Schin Arith_t *ep; 836*4887Schin Sfdouble_t d; 837*4887Schin char *sp=0; 838*4887Schin int offset; 839*4887Schin if(offset=staktell()) 840*4887Schin sp = stakfreeze(1); 841*4887Schin ep = arith_compile(s,end,conv,emode); 842*4887Schin ep->emode = emode; 843*4887Schin d = arith_exec(ep); 844*4887Schin stakset(sp?sp:(char*)ep,offset); 845*4887Schin return(d); 846*4887Schin } 847*4887Schin 848*4887Schin #if _mem_name__exception 849*4887Schin #undef _mem_name_exception 850*4887Schin #define _mem_name_exception 1 851*4887Schin #undef exception 852*4887Schin #define exception _exception 853*4887Schin #undef matherr 854*4887Schin #endif 855*4887Schin 856*4887Schin #if _mem_name_exception 857*4887Schin 858*4887Schin #undef error 859*4887Schin 860*4887Schin #if _BLD_shell && defined(__EXPORT__) 861*4887Schin #define extern __EXPORT__ 862*4887Schin #endif 863*4887Schin 864*4887Schin #ifndef DOMAIN 865*4887Schin #define DOMAIN _DOMAIN 866*4887Schin #endif 867*4887Schin #ifndef OVERFLOW 868*4887Schin #define OVERFLOW _OVERFLOW 869*4887Schin #endif 870*4887Schin #ifndef SING 871*4887Schin #define SING _SING 872*4887Schin #endif 873*4887Schin 874*4887Schin extern int matherr(struct exception *ep) 875*4887Schin { 876*4887Schin const char *message; 877*4887Schin switch(ep->type) 878*4887Schin { 879*4887Schin #ifdef DOMAIN 880*4887Schin case DOMAIN: 881*4887Schin message = ERROR_dictionary(e_domain); 882*4887Schin break; 883*4887Schin #endif 884*4887Schin #ifdef OVERFLOW 885*4887Schin case OVERFLOW: 886*4887Schin message = ERROR_dictionary(e_overflow); 887*4887Schin break; 888*4887Schin #endif 889*4887Schin #ifdef SING 890*4887Schin case SING: 891*4887Schin message = ERROR_dictionary(e_singularity); 892*4887Schin break; 893*4887Schin #endif 894*4887Schin default: 895*4887Schin return(1); 896*4887Schin } 897*4887Schin level=0; 898*4887Schin errormsg(SH_DICT,ERROR_exit(1),message,ep->name); 899*4887Schin return(0); 900*4887Schin } 901*4887Schin 902*4887Schin #undef extern 903*4887Schin 904*4887Schin #endif /* _mem_name_exception */ 905