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