14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1982-2009 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * David Korn <dgk@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin 224887Schin /* 234887Schin * D. G. Korn 244887Schin * AT&T Labs 254887Schin * 264887Schin * arithmetic expression evaluator 274887Schin * 284887Schin * this version compiles the expression onto a stack 294887Schin * and has a separate executor 304887Schin */ 314887Schin 324887Schin #include "streval.h" 334887Schin #include <ctype.h> 344887Schin #include <error.h> 354887Schin #include <stak.h> 364887Schin #include "FEATURE/externs" 374887Schin 384887Schin #ifndef ERROR_dictionary 394887Schin # define ERROR_dictionary(s) (s) 404887Schin #endif 414887Schin #ifndef SH_DICT 424887Schin # define SH_DICT "libshell" 434887Schin #endif 444887Schin 454887Schin #define MAXLEVEL 9 464887Schin #define SMALL_STACK 12 474887Schin 484887Schin /* 494887Schin * The following are used with tokenbits() macro 504887Schin */ 514887Schin #define T_OP 0x3f /* mask for operator number */ 524887Schin #define T_BINARY 0x40 /* binary operators */ 534887Schin #define T_NOFLOAT 0x80 /* non floating point operator */ 544887Schin #define A_LVALUE (2*MAXPREC+2) 554887Schin 564887Schin #define pow2size(x) ((x)<=2?2:(x)<=4?4:(x)<=8?8:(x)<=16?16:(x)<=32?32:64) 574887Schin #define round(x,size) (((x)+(size)-1)&~((size)-1)) 584887Schin #define stakpush(v,val,type) ((((v)->offset=round(staktell(),pow2size(sizeof(type)))),\ 594887Schin stakseek((v)->offset+sizeof(type)), \ 604887Schin *((type*)stakptr((v)->offset)) = (val)),(v)->offset) 614887Schin #define roundptr(ep,cp,type) (((unsigned char*)(ep))+round(cp-((unsigned char*)(ep)),pow2size(sizeof(type)))) 624887Schin 634887Schin static int level; 644887Schin 654887Schin struct vars /* vars stacked per invocation */ 664887Schin { 674887Schin const char *expr; /* current expression */ 684887Schin const char *nextchr; /* next char in current expression */ 694887Schin const char *errchr; /* next char after error */ 704887Schin const char *errstr; /* error string */ 714887Schin struct lval errmsg; /* error message text */ 724887Schin int offset; /* offset for pushchr macro */ 734887Schin int staksize; /* current stack size needed */ 744887Schin int stakmaxsize; /* maximum stack size needed */ 754887Schin unsigned char paren; /* parenthesis level */ 764887Schin char infun; /* incremented by comma inside function */ 774887Schin int emode; 784887Schin Sfdouble_t (*convert)(const char**,struct lval*,int,Sfdouble_t); 794887Schin }; 804887Schin 81*10898Sroland.mainz@nrubsig.org typedef Sfdouble_t (*Math_f)(Sfdouble_t,...); 82*10898Sroland.mainz@nrubsig.org typedef Sfdouble_t (*Math_1f_f)(Sfdouble_t); 83*10898Sroland.mainz@nrubsig.org typedef int (*Math_1i_f)(Sfdouble_t); 84*10898Sroland.mainz@nrubsig.org typedef Sfdouble_t (*Math_2f_f)(Sfdouble_t,Sfdouble_t); 85*10898Sroland.mainz@nrubsig.org typedef int (*Math_2i_f)(Sfdouble_t,Sfdouble_t); 86*10898Sroland.mainz@nrubsig.org typedef Sfdouble_t (*Math_3f_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t); 87*10898Sroland.mainz@nrubsig.org typedef int (*Math_3i_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t); 884887Schin 894887Schin #define getchr(vp) (*(vp)->nextchr++) 904887Schin #define peekchr(vp) (*(vp)->nextchr) 914887Schin #define ungetchr(vp) ((vp)->nextchr--) 924887Schin 934887Schin #if ('a'==97) /* ASCII encodings */ 944887Schin # define getop(c) (((c) >= sizeof(strval_states))? \ 954887Schin ((c)=='|'?A_OR:((c)=='^'?A_XOR:((c)=='~'?A_TILDE:A_REG))):\ 964887Schin strval_states[(c)]) 974887Schin #else 984887Schin # define getop(c) (isdigit(c)?A_DIG:((c==' '||c=='\t'||c=='\n'||c=='"')?0: \ 994887Schin (c=='<'?A_LT:(c=='>'?A_GT:(c=='='?A_ASSIGN: \ 1004887Schin (c=='+'?A_PLUS:(c=='-'?A_MINUS:(c=='*'?A_TIMES: \ 1014887Schin (c=='/'?A_DIV:(c=='%'?A_MOD:(c==','?A_COMMA: \ 1024887Schin (c=='&'?A_AND:(c=='!'?A_NOT:(c=='('?A_LPAR: \ 1034887Schin (c==')'?A_RPAR:(c==0?A_EOF:(c==':'?A_COLON: \ 1044887Schin (c=='?'?A_QUEST:(c=='|'?A_OR:(c=='^'?A_XOR: \ 1054887Schin (c=='\''?A_LIT: \ 1064887Schin (c=='.'?A_DOT:(c=='~'?A_TILDE:A_REG))))))))))))))))))))))) 1074887Schin #endif 1084887Schin 1094887Schin #define seterror(v,msg) _seterror(v,ERROR_dictionary(msg)) 1104887Schin #define ERROR(vp,msg) return(seterror((vp),msg)) 1114887Schin 1124887Schin /* 1134887Schin * set error message string and return(0) 1144887Schin */ 1154887Schin static int _seterror(struct vars *vp,const char *msg) 1164887Schin { 1174887Schin if(!vp->errmsg.value) 1184887Schin vp->errmsg.value = (char*)msg; 1194887Schin vp->errchr = vp->nextchr; 1204887Schin vp->nextchr = ""; 1214887Schin level = 0; 1224887Schin return(0); 1234887Schin } 1244887Schin 1254887Schin 1264887Schin static void arith_error(const char *message,const char *expr, int mode) 1274887Schin { 1284887Schin level = 0; 1294887Schin mode = (mode&3)!=0; 1304887Schin errormsg(SH_DICT,ERROR_exit(mode),message,expr); 1314887Schin } 1324887Schin 1334887Schin #if _ast_no_um2fm 1344887Schin static Sfdouble_t U2F(Sfulong_t u) 1354887Schin { 1364887Schin Sflong_t s = u; 1374887Schin Sfdouble_t f; 1384887Schin 1394887Schin if (s >= 0) 1404887Schin return s; 1414887Schin s = u / 2; 1424887Schin f = s; 1434887Schin f *= 2; 1444887Schin if (u & 1) 1454887Schin f++; 1464887Schin return f; 1474887Schin } 1484887Schin #else 1494887Schin #define U2F(x) x 1504887Schin #endif 1514887Schin 1524887Schin Sfdouble_t arith_exec(Arith_t *ep) 1534887Schin { 1544887Schin register Sfdouble_t num=0,*dp,*sp; 1554887Schin register unsigned char *cp = ep->code; 1564887Schin register int c,type=0; 1574887Schin register char *tp; 1584887Schin Sfdouble_t small_stack[SMALL_STACK+1]; 1594887Schin const char *ptr = ""; 160*10898Sroland.mainz@nrubsig.org Math_f fun; 1614887Schin struct lval node; 1624887Schin node.emode = ep->emode; 1634887Schin node.expr = ep->expr; 1644887Schin node.elen = ep->elen; 1654887Schin if(level++ >=MAXLEVEL) 1664887Schin { 1674887Schin arith_error(e_recursive,ep->expr,ep->emode); 1684887Schin return(0); 1694887Schin } 1704887Schin if(ep->staksize < SMALL_STACK) 1714887Schin sp = small_stack; 1724887Schin else 1734887Schin sp = (Sfdouble_t*)stakalloc(ep->staksize*(sizeof(Sfdouble_t)+1)); 1744887Schin tp = (char*)(sp+ep->staksize); 1754887Schin tp--,sp--; 1764887Schin while(c = *cp++) 1774887Schin { 1784887Schin if(c&T_NOFLOAT) 1794887Schin { 1804887Schin if(type==1 || ((c&T_BINARY) && (c&T_OP)!=A_MOD && tp[-1]==1)) 1814887Schin arith_error(e_incompatible,ep->expr,ep->emode); 1824887Schin } 1834887Schin switch(c&T_OP) 1844887Schin { 1854887Schin case A_JMP: case A_JMPZ: case A_JMPNZ: 1864887Schin c &= T_OP; 1874887Schin cp = roundptr(ep,cp,short); 1884887Schin if((c==A_JMPZ && num) || (c==A_JMPNZ &&!num)) 1894887Schin cp += sizeof(short); 1904887Schin else 1914887Schin cp = (unsigned char*)ep + *((short*)cp); 1924887Schin continue; 1934887Schin case A_NOTNOT: 1944887Schin num = (num!=0); 1954887Schin type=0; 1964887Schin break; 1974887Schin case A_PLUSPLUS: 1984887Schin (*ep->fun)(&ptr,&node,ASSIGN,num+1); 1994887Schin break; 2004887Schin case A_MINUSMINUS: 2014887Schin (*ep->fun)(&ptr,&node,ASSIGN,num-1); 2024887Schin break; 2034887Schin case A_INCR: 2044887Schin num = num+1; 2054887Schin num = (*ep->fun)(&ptr,&node,ASSIGN,num); 2064887Schin break; 2074887Schin case A_DECR: 2084887Schin num = num-1; 2094887Schin num = (*ep->fun)(&ptr,&node,ASSIGN,num); 2104887Schin break; 2114887Schin case A_SWAP: 2124887Schin num = sp[-1]; 2134887Schin sp[-1] = *sp; 2144887Schin type = tp[-1]; 2154887Schin tp[-1] = *tp; 2164887Schin break; 2174887Schin case A_POP: 2184887Schin sp--; 2194887Schin continue; 2204887Schin case A_PUSHV: 2214887Schin cp = roundptr(ep,cp,Sfdouble_t*); 2224887Schin dp = *((Sfdouble_t**)cp); 2234887Schin cp += sizeof(Sfdouble_t*); 2244887Schin c = *(short*)cp; 2254887Schin cp += sizeof(short); 2264887Schin node.value = (char*)dp; 2274887Schin node.flag = c; 2284887Schin node.isfloat=0; 2294887Schin node.level = level; 2304887Schin num = (*ep->fun)(&ptr,&node,VALUE,num); 2314887Schin if(node.value != (char*)dp) 2324887Schin arith_error(node.value,ptr,ep->emode); 2334887Schin *++sp = num; 2344887Schin type = node.isfloat; 2354887Schin if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN) 2364887Schin type = 1; 2374887Schin else 2384887Schin { 2394887Schin Sfdouble_t d=num; 2404887Schin if(num > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX) 2414887Schin { 2424887Schin type = 2; 2434887Schin d -= LDBL_LLONG_MAX; 2444887Schin } 2454887Schin if((Sflong_t)d!=d) 2464887Schin type = 1; 2474887Schin } 2484887Schin *++tp = type; 2494887Schin c = 0; 2504887Schin break; 2514887Schin case A_STORE: 2524887Schin cp = roundptr(ep,cp,Sfdouble_t*); 2534887Schin dp = *((Sfdouble_t**)cp); 2544887Schin cp += sizeof(Sfdouble_t*); 2554887Schin c = *(short*)cp; 2564887Schin if(c<0) 2574887Schin c = 0; 2584887Schin cp += sizeof(short); 2594887Schin node.value = (char*)dp; 2604887Schin node.flag = c; 2614887Schin num = (*ep->fun)(&ptr,&node,ASSIGN,num); 262*10898Sroland.mainz@nrubsig.org c=0; 2634887Schin break; 2644887Schin case A_PUSHF: 265*10898Sroland.mainz@nrubsig.org cp = roundptr(ep,cp,Math_f); 2664887Schin *++sp = (Sfdouble_t)(cp-ep->code); 267*10898Sroland.mainz@nrubsig.org cp += sizeof(Math_f); 2684887Schin *++tp = *cp++; 2694887Schin continue; 2704887Schin case A_PUSHN: 2714887Schin cp = roundptr(ep,cp,Sfdouble_t); 2724887Schin num = *((Sfdouble_t*)cp); 2734887Schin cp += sizeof(Sfdouble_t); 2744887Schin *++sp = num; 2754887Schin *++tp = type = *cp++; 2764887Schin break; 2774887Schin case A_NOT: 2784887Schin type=0; 2794887Schin num = !num; 2804887Schin break; 2814887Schin case A_UMINUS: 2824887Schin num = -num; 2834887Schin break; 2844887Schin case A_TILDE: 2854887Schin num = ~((Sflong_t)(num)); 2864887Schin break; 2874887Schin case A_PLUS: 2884887Schin num += sp[-1]; 2894887Schin break; 2904887Schin case A_MINUS: 2914887Schin num = sp[-1] - num; 2924887Schin break; 2934887Schin case A_TIMES: 2944887Schin num *= sp[-1]; 2954887Schin break; 2964887Schin case A_POW: 2974887Schin num = pow(sp[-1],num); 2984887Schin break; 2994887Schin case A_MOD: 3004887Schin if(!(Sflong_t)num) 3014887Schin arith_error(e_divzero,ep->expr,ep->emode); 3024887Schin if(type==2 || tp[-1]==2) 3034887Schin num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num)); 3044887Schin else 3054887Schin num = (Sflong_t)(sp[-1]) % (Sflong_t)(num); 3064887Schin break; 3074887Schin case A_DIV: 3084887Schin if(type==1 || tp[-1]==1) 3094887Schin { 3104887Schin num = sp[-1]/num; 3114887Schin type = 1; 3124887Schin } 3134887Schin else if((Sfulong_t)(num)==0) 3144887Schin arith_error(e_divzero,ep->expr,ep->emode); 3154887Schin else if(type==2 || tp[-1]==2) 3164887Schin num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num)); 3174887Schin else 3184887Schin num = (Sflong_t)(sp[-1]) / (Sflong_t)(num); 3194887Schin break; 3204887Schin case A_LSHIFT: 3214887Schin if(tp[-1]==2) 3224887Schin num = U2F((Sfulong_t)(sp[-1]) << (long)(num)); 3234887Schin else 3244887Schin num = (Sflong_t)(sp[-1]) << (long)(num); 3254887Schin break; 3264887Schin case A_RSHIFT: 3274887Schin if(tp[-1]==2) 3284887Schin num = U2F((Sfulong_t)(sp[-1]) >> (long)(num)); 3294887Schin else 3304887Schin num = (Sflong_t)(sp[-1]) >> (long)(num); 3314887Schin break; 3324887Schin case A_XOR: 3334887Schin if(type==2 || tp[-1]==2) 3344887Schin num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num)); 3354887Schin else 3364887Schin num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num); 3374887Schin break; 3384887Schin case A_OR: 3394887Schin if(type==2 || tp[-1]==2) 3404887Schin num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num)); 3414887Schin else 3424887Schin num = (Sflong_t)(sp[-1]) | (Sflong_t)(num); 3434887Schin break; 3444887Schin case A_AND: 3454887Schin if(type==2 || tp[-1]==2) 3464887Schin num = U2F((Sfulong_t)(sp[-1]) & (Sfulong_t)(num)); 3474887Schin else 3484887Schin num = (Sflong_t)(sp[-1]) & (Sflong_t)(num); 3494887Schin break; 3504887Schin case A_EQ: 3514887Schin num = (sp[-1]==num); 3524887Schin type=0; 3534887Schin break; 3544887Schin case A_NEQ: 3554887Schin num = (sp[-1]!=num); 3564887Schin type=0; 3574887Schin break; 3584887Schin case A_LE: 3594887Schin num = (sp[-1]<=num); 3604887Schin type=0; 3614887Schin break; 3624887Schin case A_GE: 3634887Schin num = (sp[-1]>=num); 3644887Schin type=0; 3654887Schin break; 3664887Schin case A_GT: 3674887Schin num = (sp[-1]>num); 3684887Schin type=0; 3694887Schin break; 3704887Schin case A_LT: 3714887Schin num = (sp[-1]<num); 3724887Schin type=0; 3734887Schin break; 374*10898Sroland.mainz@nrubsig.org case A_CALL1F: 3754887Schin sp--,tp--; 376*10898Sroland.mainz@nrubsig.org fun = *((Math_f*)(ep->code+(int)(*sp))); 3774887Schin type = 0; 378*10898Sroland.mainz@nrubsig.org num = (*((Math_1f_f)fun))(num); 3794887Schin break; 380*10898Sroland.mainz@nrubsig.org case A_CALL1I: 3814887Schin sp--,tp--; 382*10898Sroland.mainz@nrubsig.org fun = *((Math_f*)(ep->code+(int)(*sp))); 3834887Schin type = *tp; 384*10898Sroland.mainz@nrubsig.org num = (*((Math_1i_f)fun))(num); 3854887Schin break; 386*10898Sroland.mainz@nrubsig.org case A_CALL2F: 3874887Schin sp-=2,tp-=2; 388*10898Sroland.mainz@nrubsig.org fun = *((Math_f*)(ep->code+(int)(*sp))); 389*10898Sroland.mainz@nrubsig.org type = 0; 390*10898Sroland.mainz@nrubsig.org num = (*((Math_2f_f)fun))(sp[1],num); 3914887Schin break; 392*10898Sroland.mainz@nrubsig.org case A_CALL2I: 393*10898Sroland.mainz@nrubsig.org sp-=2,tp-=2; 394*10898Sroland.mainz@nrubsig.org fun = *((Math_f*)(ep->code+(int)(*sp))); 395*10898Sroland.mainz@nrubsig.org type = *tp; 396*10898Sroland.mainz@nrubsig.org num = (*((Math_2i_f)fun))(sp[1],num); 397*10898Sroland.mainz@nrubsig.org break; 398*10898Sroland.mainz@nrubsig.org case A_CALL3F: 3994887Schin sp-=3,tp-=3; 400*10898Sroland.mainz@nrubsig.org fun = *((Math_f*)(ep->code+(int)(*sp))); 401*10898Sroland.mainz@nrubsig.org type = 0; 402*10898Sroland.mainz@nrubsig.org num = (*((Math_3f_f)fun))(sp[1],sp[2],num); 4034887Schin break; 4044887Schin } 4054887Schin if(c&T_BINARY) 4064887Schin sp--,tp--; 4074887Schin *sp = num; 4084887Schin *tp = type; 4094887Schin } 4104887Schin if(level>0) 4114887Schin level--; 4124887Schin return(num); 4134887Schin } 4144887Schin 4154887Schin /* 4164887Schin * This returns operator tokens or A_REG or A_NUM 4174887Schin */ 4184887Schin static int gettok(register struct vars *vp) 4194887Schin { 4204887Schin register int c,op; 4214887Schin vp->errchr = vp->nextchr; 4224887Schin while(1) 4234887Schin { 4244887Schin c = getchr(vp); 4254887Schin switch(op=getop(c)) 4264887Schin { 4274887Schin case 0: 4284887Schin vp->errchr = vp->nextchr; 4294887Schin continue; 4304887Schin case A_EOF: 4314887Schin vp->nextchr--; 4324887Schin break; 4334887Schin /*FALL THRU*/ 4344887Schin case A_DIG: case A_REG: case A_DOT: case A_LIT: 4354887Schin if(op==A_DOT) 4364887Schin { 4374887Schin if((c=peekchr(vp))>='0' && c<='9') 4384887Schin op = A_DIG; 4394887Schin else 4404887Schin op = A_REG; 4414887Schin } 4424887Schin ungetchr(vp); 4434887Schin break; 4444887Schin case A_QUEST: 4454887Schin if(peekchr(vp)==':') 4464887Schin { 4474887Schin getchr(vp); 4484887Schin op = A_QCOLON; 4494887Schin } 4504887Schin break; 4514887Schin case A_LT: case A_GT: 4524887Schin if(peekchr(vp)==c) 4534887Schin { 4544887Schin getchr(vp); 4554887Schin op -= 2; 4564887Schin break; 4574887Schin } 4584887Schin /* FALL THRU */ 4594887Schin case A_NOT: case A_COLON: 4604887Schin c = '='; 4614887Schin /* FALL THRU */ 4624887Schin case A_ASSIGN: 4634887Schin case A_TIMES: 4644887Schin case A_PLUS: case A_MINUS: 4654887Schin case A_OR: case A_AND: 4664887Schin if(peekchr(vp)==c) 4674887Schin { 4684887Schin getchr(vp); 4694887Schin op--; 4704887Schin } 4714887Schin } 4724887Schin return(op); 4734887Schin } 4744887Schin } 4754887Schin 4764887Schin /* 4774887Schin * evaluate a subexpression with precedence 4784887Schin */ 4794887Schin 4804887Schin static int expr(register struct vars *vp,register int precedence) 4814887Schin { 4824887Schin register int c, op; 4834887Schin int invalid,wasop=0; 4844887Schin struct lval lvalue,assignop; 4854887Schin const char *pos; 4864887Schin Sfdouble_t d; 4874887Schin 4884887Schin lvalue.value = 0; 4894887Schin lvalue.fun = 0; 4904887Schin again: 4914887Schin op = gettok(vp); 4924887Schin c = 2*MAXPREC+1; 4934887Schin switch(op) 4944887Schin { 4954887Schin case A_PLUS: 4964887Schin goto again; 4974887Schin case A_EOF: 4988462SApril.Chin@Sun.COM if(precedence>2) 4994887Schin ERROR(vp,e_moretokens); 5004887Schin return(1); 5014887Schin case A_MINUS: 5024887Schin op = A_UMINUS; 5034887Schin goto common; 5044887Schin case A_NOT: 5054887Schin goto common; 5064887Schin case A_MINUSMINUS: 5074887Schin c = A_LVALUE; 5084887Schin op = A_DECR|T_NOFLOAT; 5094887Schin goto common; 5104887Schin case A_PLUSPLUS: 5114887Schin c = A_LVALUE; 5124887Schin op = A_INCR|T_NOFLOAT; 5134887Schin /* FALL THRU */ 5144887Schin case A_TILDE: 5154887Schin op |= T_NOFLOAT; 5164887Schin common: 5174887Schin if(!expr(vp,c)) 5184887Schin return(0); 5194887Schin stakputc(op); 5204887Schin break; 5214887Schin default: 5224887Schin vp->nextchr = vp->errchr; 5234887Schin wasop = 1; 5244887Schin } 5254887Schin invalid = wasop; 5264887Schin while(1) 5274887Schin { 5284887Schin assignop.value = 0; 5294887Schin op = gettok(vp); 5304887Schin if(op==A_DIG || op==A_REG || op==A_LIT) 5314887Schin { 5324887Schin if(!wasop) 5334887Schin ERROR(vp,e_synbad); 5344887Schin goto number; 5354887Schin } 5364887Schin if(wasop++ && op!=A_LPAR) 5374887Schin ERROR(vp,e_synbad); 5384887Schin /* check for assignment operation */ 5394887Schin if(peekchr(vp)== '=' && !(strval_precedence[op]&NOASSIGN)) 5404887Schin { 5414887Schin if((!lvalue.value || precedence > 3)) 5424887Schin ERROR(vp,e_notlvalue); 5434887Schin if(precedence==3) 5444887Schin precedence = 2; 5454887Schin assignop = lvalue; 5464887Schin getchr(vp); 5474887Schin c = 3; 5484887Schin } 5494887Schin else 5504887Schin { 5514887Schin c = (strval_precedence[op]&PRECMASK); 5524887Schin if(c==MAXPREC || op==A_POW) 5534887Schin c++; 5544887Schin c *= 2; 5554887Schin } 5564887Schin /* from here on c is the new precedence level */ 5574887Schin if(lvalue.value && (op!=A_ASSIGN)) 5584887Schin { 5594887Schin if(vp->staksize++>=vp->stakmaxsize) 5604887Schin vp->stakmaxsize = vp->staksize; 5614887Schin stakputc(A_PUSHV); 5624887Schin stakpush(vp,lvalue.value,char*); 5634887Schin if(lvalue.flag<0) 5644887Schin lvalue.flag = 0; 5654887Schin stakpush(vp,lvalue.flag,short); 5664887Schin if(vp->nextchr==0) 5674887Schin ERROR(vp,e_badnum); 5684887Schin if(!(strval_precedence[op]&SEQPOINT)) 5694887Schin lvalue.value = 0; 5704887Schin invalid = 0; 5714887Schin } 5724887Schin else if(precedence==A_LVALUE) 5734887Schin ERROR(vp,e_notlvalue); 5744887Schin if(invalid && op>A_ASSIGN) 5754887Schin ERROR(vp,e_synbad); 5764887Schin if(precedence >= c) 5774887Schin goto done; 5784887Schin if(strval_precedence[op]&RASSOC) 5794887Schin c--; 5804887Schin if((c < (2*MAXPREC+1)) && !(strval_precedence[op]&SEQPOINT)) 5814887Schin { 5824887Schin wasop = 0; 5834887Schin if(!expr(vp,c)) 5844887Schin return(0); 5854887Schin } 5864887Schin switch(op) 5874887Schin { 5884887Schin case A_RPAR: 5894887Schin if(!vp->paren) 5904887Schin ERROR(vp,e_paren); 5914887Schin if(invalid) 5924887Schin ERROR(vp,e_synbad); 5934887Schin goto done; 5944887Schin 5954887Schin case A_COMMA: 5964887Schin wasop = 0; 5974887Schin if(vp->infun) 5984887Schin vp->infun++; 5994887Schin else 6004887Schin { 6014887Schin stakputc(A_POP); 6024887Schin vp->staksize--; 6034887Schin } 6044887Schin if(!expr(vp,c)) 605*10898Sroland.mainz@nrubsig.org { 606*10898Sroland.mainz@nrubsig.org stakseek(-1); 6074887Schin return(0); 608*10898Sroland.mainz@nrubsig.org } 6094887Schin lvalue.value = 0; 6104887Schin break; 6114887Schin 6124887Schin case A_LPAR: 6134887Schin { 6144887Schin int infun = vp->infun; 6154887Schin Sfdouble_t (*fun)(Sfdouble_t,...); 6164887Schin int nargs = lvalue.nargs; 6174887Schin fun = lvalue.fun; 6184887Schin lvalue.fun = 0; 6194887Schin if(fun) 6204887Schin { 6214887Schin if(vp->staksize++>=vp->stakmaxsize) 6224887Schin vp->stakmaxsize = vp->staksize; 6234887Schin vp->infun=1; 6244887Schin stakputc(A_PUSHF); 625*10898Sroland.mainz@nrubsig.org stakpush(vp,fun,Math_f); 6264887Schin stakputc(1); 6274887Schin } 6284887Schin else 6294887Schin vp->infun = 0; 6304887Schin if(!invalid) 6314887Schin ERROR(vp,e_synbad); 6324887Schin vp->paren++; 6334887Schin if(!expr(vp,1)) 6344887Schin return(0); 6354887Schin vp->paren--; 6364887Schin if(fun) 6374887Schin { 638*10898Sroland.mainz@nrubsig.org int x= (nargs>7)?2:-1; 6394887Schin nargs &= 7; 6404887Schin if(vp->infun != nargs) 6414887Schin ERROR(vp,e_argcount); 6424887Schin if(vp->staksize+=nargs>=vp->stakmaxsize) 6434887Schin vp->stakmaxsize = vp->staksize+nargs; 644*10898Sroland.mainz@nrubsig.org stakputc(A_CALL1F+nargs+x); 6454887Schin vp->staksize -= nargs; 6464887Schin } 6474887Schin vp->infun = infun; 6484887Schin if (gettok(vp) != A_RPAR) 6494887Schin ERROR(vp,e_paren); 6504887Schin wasop = 0; 6514887Schin break; 6524887Schin } 6534887Schin 6544887Schin case A_PLUSPLUS: 6554887Schin case A_MINUSMINUS: 6564887Schin wasop=0; 6574887Schin op |= T_NOFLOAT; 6584887Schin case A_ASSIGN: 6594887Schin if(!lvalue.value) 6604887Schin ERROR(vp,e_notlvalue); 6614887Schin if(op==A_ASSIGN) 6624887Schin { 6634887Schin stakputc(A_STORE); 6644887Schin stakpush(vp,lvalue.value,char*); 6654887Schin stakpush(vp,lvalue.flag,short); 6664887Schin vp->staksize--; 6674887Schin } 6684887Schin else 6694887Schin stakputc(op); 6704887Schin lvalue.value = 0; 6714887Schin break; 6724887Schin 6734887Schin case A_QUEST: 6744887Schin { 6754887Schin int offset1,offset2; 6764887Schin stakputc(A_JMPZ); 6774887Schin offset1 = stakpush(vp,0,short); 6784887Schin stakputc(A_POP); 6794887Schin if(!expr(vp,1)) 6804887Schin return(0); 6814887Schin if(gettok(vp)!=A_COLON) 6824887Schin ERROR(vp,e_questcolon); 6834887Schin stakputc(A_JMP); 6844887Schin offset2 = stakpush(vp,0,short); 6854887Schin *((short*)stakptr(offset1)) = staktell(); 6864887Schin stakputc(A_POP); 6874887Schin if(!expr(vp,3)) 6884887Schin return(0); 6894887Schin *((short*)stakptr(offset2)) = staktell(); 6904887Schin lvalue.value = 0; 6914887Schin wasop = 0; 6924887Schin break; 6934887Schin } 6944887Schin 6954887Schin case A_COLON: 6964887Schin ERROR(vp,e_badcolon); 6974887Schin break; 6984887Schin 6994887Schin case A_QCOLON: 7004887Schin case A_ANDAND: 7014887Schin case A_OROR: 7024887Schin { 7034887Schin int offset; 7044887Schin if(op==A_ANDAND) 7054887Schin op = A_JMPZ; 7064887Schin else 7074887Schin op = A_JMPNZ; 7084887Schin stakputc(op); 7094887Schin offset = stakpush(vp,0,short); 7104887Schin stakputc(A_POP); 7114887Schin if(!expr(vp,c)) 7124887Schin return(0); 7134887Schin *((short*)stakptr(offset)) = staktell(); 7144887Schin if(op!=A_QCOLON) 7154887Schin stakputc(A_NOTNOT); 7164887Schin lvalue.value = 0; 7174887Schin wasop=0; 7184887Schin break; 7194887Schin } 7204887Schin case A_AND: case A_OR: case A_XOR: case A_LSHIFT: 7214887Schin case A_RSHIFT: case A_MOD: 7224887Schin op |= T_NOFLOAT; 7234887Schin /* FALL THRU */ 7244887Schin case A_PLUS: case A_MINUS: case A_TIMES: case A_DIV: 7254887Schin case A_EQ: case A_NEQ: case A_LT: case A_LE: 7264887Schin case A_GT: case A_GE: case A_POW: 7274887Schin stakputc(op|T_BINARY); 7284887Schin vp->staksize--; 7294887Schin break; 7304887Schin case A_NOT: case A_TILDE: 7314887Schin default: 7324887Schin ERROR(vp,e_synbad); 7334887Schin number: 7344887Schin wasop = 0; 7354887Schin if(*vp->nextchr=='L' && vp->nextchr[1]=='\'') 7364887Schin { 7374887Schin vp->nextchr++; 7384887Schin op = A_LIT; 7394887Schin } 7404887Schin pos = vp->nextchr; 7414887Schin lvalue.isfloat = 0; 7424887Schin lvalue.expr = vp->expr; 7434887Schin lvalue.emode = vp->emode; 7444887Schin if(op==A_LIT) 7454887Schin { 7464887Schin /* character constants */ 7474887Schin if(pos[1]=='\\' && pos[2]=='\'' && pos[3]!='\'') 7484887Schin { 7494887Schin d = '\\'; 7504887Schin vp->nextchr +=2; 7514887Schin } 7524887Schin else 7534887Schin d = chresc(pos+1,(char**)&vp->nextchr); 7544887Schin /* posix allows the trailing ' to be optional */ 7554887Schin if(*vp->nextchr=='\'') 7564887Schin vp->nextchr++; 7574887Schin } 7584887Schin else 7594887Schin d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0); 7604887Schin if (vp->nextchr == pos) 7614887Schin { 7624887Schin if(vp->errmsg.value = lvalue.value) 7634887Schin vp->errstr = pos; 7644887Schin ERROR(vp,op==A_LIT?e_charconst:e_synbad); 7654887Schin } 7664887Schin if(op==A_DIG || op==A_LIT) 7674887Schin { 7684887Schin stakputc(A_PUSHN); 7694887Schin if(vp->staksize++>=vp->stakmaxsize) 7704887Schin vp->stakmaxsize = vp->staksize; 7714887Schin stakpush(vp,d,Sfdouble_t); 7724887Schin stakputc(lvalue.isfloat); 7734887Schin } 7744887Schin 7754887Schin /* check for function call */ 7764887Schin if(lvalue.fun) 7774887Schin continue; 7784887Schin break; 7794887Schin } 7804887Schin invalid = 0; 7814887Schin if(assignop.value) 7824887Schin { 7834887Schin if(vp->staksize++>=vp->stakmaxsize) 7844887Schin vp->stakmaxsize = vp->staksize; 7854887Schin if(assignop.flag<0) 7864887Schin assignop.flag = 0; 7874887Schin stakputc(A_STORE); 7884887Schin stakpush(vp,assignop.value,char*); 7894887Schin stakpush(vp,assignop.flag,short); 7904887Schin } 7914887Schin } 7924887Schin done: 7934887Schin vp->nextchr = vp->errchr; 7944887Schin return(1); 7954887Schin } 7964887Schin 7974887Schin Arith_t *arith_compile(const char *string,char **last,Sfdouble_t(*fun)(const char**,struct lval*,int,Sfdouble_t),int emode) 7984887Schin { 7994887Schin struct vars cur; 8004887Schin register Arith_t *ep; 8014887Schin int offset; 8024887Schin memset((void*)&cur,0,sizeof(cur)); 8034887Schin cur.emode = emode; 8044887Schin cur.expr = cur.nextchr = string; 8054887Schin cur.convert = fun; 8064887Schin cur.emode = emode; 8074887Schin cur.errmsg.value = 0; 8084887Schin cur.errmsg.emode = emode; 8094887Schin stakseek(sizeof(Arith_t)); 8104887Schin if(!expr(&cur,0) && cur.errmsg.value) 8114887Schin { 8124887Schin if(cur.errstr) 8134887Schin string = cur.errstr; 8144887Schin (*fun)( &string , &cur.errmsg, MESSAGE, 0); 8154887Schin cur.nextchr = cur.errchr; 8164887Schin } 8174887Schin stakputc(0); 8184887Schin offset = staktell(); 8194887Schin ep = (Arith_t*)stakfreeze(0); 8204887Schin ep->expr = string; 8214887Schin ep->elen = strlen(string); 8224887Schin ep->code = (unsigned char*)(ep+1); 8234887Schin ep->fun = fun; 8244887Schin ep->emode = emode; 8254887Schin ep->size = offset - sizeof(Arith_t); 8264887Schin ep->staksize = cur.stakmaxsize+1; 8274887Schin if(last) 8284887Schin *last = (char*)(cur.nextchr); 8294887Schin return(ep); 8304887Schin } 8314887Schin 8324887Schin /* 8334887Schin * evaluate an integer arithmetic expression in s 8344887Schin * 8354887Schin * (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value) 8364887Schin * is a user supplied conversion routine that is called when unknown 8374887Schin * chars are encountered. 8384887Schin * *end points to the part to be converted and must be adjusted by convert to 8394887Schin * point to the next non-converted character; if typ is MESSAGE then string 8404887Schin * points to an error message string 8414887Schin * 8424887Schin * NOTE: (*convert)() may call strval() 8434887Schin */ 8444887Schin 8454887Schin Sfdouble_t strval(const char *s,char **end,Sfdouble_t(*conv)(const char**,struct lval*,int,Sfdouble_t),int emode) 8464887Schin { 8474887Schin Arith_t *ep; 8484887Schin Sfdouble_t d; 8494887Schin char *sp=0; 8504887Schin int offset; 8514887Schin if(offset=staktell()) 8524887Schin sp = stakfreeze(1); 8534887Schin ep = arith_compile(s,end,conv,emode); 8544887Schin ep->emode = emode; 8554887Schin d = arith_exec(ep); 8564887Schin stakset(sp?sp:(char*)ep,offset); 8574887Schin return(d); 8584887Schin } 8594887Schin 8604887Schin #if _mem_name__exception 8614887Schin #undef _mem_name_exception 8624887Schin #define _mem_name_exception 1 8634887Schin #undef exception 8644887Schin #define exception _exception 8654887Schin #undef matherr 8664887Schin #endif 8674887Schin 8684887Schin #if _mem_name_exception 8694887Schin 8704887Schin #undef error 8714887Schin 8724887Schin #if _BLD_shell && defined(__EXPORT__) 8734887Schin #define extern __EXPORT__ 8744887Schin #endif 8754887Schin 8764887Schin #ifndef DOMAIN 8774887Schin #define DOMAIN _DOMAIN 8784887Schin #endif 8794887Schin #ifndef OVERFLOW 8804887Schin #define OVERFLOW _OVERFLOW 8814887Schin #endif 8824887Schin #ifndef SING 8834887Schin #define SING _SING 8844887Schin #endif 8854887Schin 8864887Schin extern int matherr(struct exception *ep) 8874887Schin { 8884887Schin const char *message; 8894887Schin switch(ep->type) 8904887Schin { 8914887Schin #ifdef DOMAIN 8924887Schin case DOMAIN: 8934887Schin message = ERROR_dictionary(e_domain); 8944887Schin break; 8954887Schin #endif 8964887Schin #ifdef OVERFLOW 8974887Schin case OVERFLOW: 8984887Schin message = ERROR_dictionary(e_overflow); 8994887Schin break; 9004887Schin #endif 9014887Schin #ifdef SING 9024887Schin case SING: 9034887Schin message = ERROR_dictionary(e_singularity); 9044887Schin break; 9054887Schin #endif 9064887Schin default: 9074887Schin return(1); 9084887Schin } 9094887Schin level=0; 9104887Schin errormsg(SH_DICT,ERROR_exit(1),message,ep->name); 9114887Schin return(0); 9124887Schin } 9134887Schin 9144887Schin #undef extern 9154887Schin 9164887Schin #endif /* _mem_name_exception */ 917