14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1982-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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 814887Schin typedef int (*Math_0_f)(Sfdouble_t); 824887Schin typedef Sfdouble_t (*Fun_t)(Sfdouble_t,...); 834887Schin typedef Sfdouble_t (*Math_1_f)(Sfdouble_t); 844887Schin typedef Sfdouble_t (*Math_2_f)(Sfdouble_t,Sfdouble_t); 854887Schin typedef Sfdouble_t (*Math_3_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t); 864887Schin 874887Schin #define getchr(vp) (*(vp)->nextchr++) 884887Schin #define peekchr(vp) (*(vp)->nextchr) 894887Schin #define ungetchr(vp) ((vp)->nextchr--) 904887Schin 914887Schin #if ('a'==97) /* ASCII encodings */ 924887Schin # define getop(c) (((c) >= sizeof(strval_states))? \ 934887Schin ((c)=='|'?A_OR:((c)=='^'?A_XOR:((c)=='~'?A_TILDE:A_REG))):\ 944887Schin strval_states[(c)]) 954887Schin #else 964887Schin # define getop(c) (isdigit(c)?A_DIG:((c==' '||c=='\t'||c=='\n'||c=='"')?0: \ 974887Schin (c=='<'?A_LT:(c=='>'?A_GT:(c=='='?A_ASSIGN: \ 984887Schin (c=='+'?A_PLUS:(c=='-'?A_MINUS:(c=='*'?A_TIMES: \ 994887Schin (c=='/'?A_DIV:(c=='%'?A_MOD:(c==','?A_COMMA: \ 1004887Schin (c=='&'?A_AND:(c=='!'?A_NOT:(c=='('?A_LPAR: \ 1014887Schin (c==')'?A_RPAR:(c==0?A_EOF:(c==':'?A_COLON: \ 1024887Schin (c=='?'?A_QUEST:(c=='|'?A_OR:(c=='^'?A_XOR: \ 1034887Schin (c=='\''?A_LIT: \ 1044887Schin (c=='.'?A_DOT:(c=='~'?A_TILDE:A_REG))))))))))))))))))))))) 1054887Schin #endif 1064887Schin 1074887Schin #define seterror(v,msg) _seterror(v,ERROR_dictionary(msg)) 1084887Schin #define ERROR(vp,msg) return(seterror((vp),msg)) 1094887Schin 1104887Schin /* 1114887Schin * set error message string and return(0) 1124887Schin */ 1134887Schin static int _seterror(struct vars *vp,const char *msg) 1144887Schin { 1154887Schin if(!vp->errmsg.value) 1164887Schin vp->errmsg.value = (char*)msg; 1174887Schin vp->errchr = vp->nextchr; 1184887Schin vp->nextchr = ""; 1194887Schin level = 0; 1204887Schin return(0); 1214887Schin } 1224887Schin 1234887Schin 1244887Schin static void arith_error(const char *message,const char *expr, int mode) 1254887Schin { 1264887Schin level = 0; 1274887Schin mode = (mode&3)!=0; 1284887Schin errormsg(SH_DICT,ERROR_exit(mode),message,expr); 1294887Schin } 1304887Schin 1314887Schin #if _ast_no_um2fm 1324887Schin static Sfdouble_t U2F(Sfulong_t u) 1334887Schin { 1344887Schin Sflong_t s = u; 1354887Schin Sfdouble_t f; 1364887Schin 1374887Schin if (s >= 0) 1384887Schin return s; 1394887Schin s = u / 2; 1404887Schin f = s; 1414887Schin f *= 2; 1424887Schin if (u & 1) 1434887Schin f++; 1444887Schin return f; 1454887Schin } 1464887Schin #else 1474887Schin #define U2F(x) x 1484887Schin #endif 1494887Schin 1504887Schin Sfdouble_t arith_exec(Arith_t *ep) 1514887Schin { 1524887Schin register Sfdouble_t num=0,*dp,*sp; 1534887Schin register unsigned char *cp = ep->code; 1544887Schin register int c,type=0; 1554887Schin register char *tp; 1564887Schin Sfdouble_t small_stack[SMALL_STACK+1]; 1574887Schin const char *ptr = ""; 1584887Schin Fun_t fun; 1594887Schin struct lval node; 1604887Schin node.emode = ep->emode; 1614887Schin node.expr = ep->expr; 1624887Schin node.elen = ep->elen; 1634887Schin if(level++ >=MAXLEVEL) 1644887Schin { 1654887Schin arith_error(e_recursive,ep->expr,ep->emode); 1664887Schin return(0); 1674887Schin } 1684887Schin if(ep->staksize < SMALL_STACK) 1694887Schin sp = small_stack; 1704887Schin else 1714887Schin sp = (Sfdouble_t*)stakalloc(ep->staksize*(sizeof(Sfdouble_t)+1)); 1724887Schin tp = (char*)(sp+ep->staksize); 1734887Schin tp--,sp--; 1744887Schin while(c = *cp++) 1754887Schin { 1764887Schin if(c&T_NOFLOAT) 1774887Schin { 1784887Schin if(type==1 || ((c&T_BINARY) && (c&T_OP)!=A_MOD && tp[-1]==1)) 1794887Schin arith_error(e_incompatible,ep->expr,ep->emode); 1804887Schin } 1814887Schin switch(c&T_OP) 1824887Schin { 1834887Schin case A_JMP: case A_JMPZ: case A_JMPNZ: 1844887Schin c &= T_OP; 1854887Schin cp = roundptr(ep,cp,short); 1864887Schin if((c==A_JMPZ && num) || (c==A_JMPNZ &&!num)) 1874887Schin cp += sizeof(short); 1884887Schin else 1894887Schin cp = (unsigned char*)ep + *((short*)cp); 1904887Schin continue; 1914887Schin case A_NOTNOT: 1924887Schin num = (num!=0); 1934887Schin type=0; 1944887Schin break; 1954887Schin case A_PLUSPLUS: 1964887Schin (*ep->fun)(&ptr,&node,ASSIGN,num+1); 1974887Schin break; 1984887Schin case A_MINUSMINUS: 1994887Schin (*ep->fun)(&ptr,&node,ASSIGN,num-1); 2004887Schin break; 2014887Schin case A_INCR: 2024887Schin num = num+1; 2034887Schin num = (*ep->fun)(&ptr,&node,ASSIGN,num); 2044887Schin break; 2054887Schin case A_DECR: 2064887Schin num = num-1; 2074887Schin num = (*ep->fun)(&ptr,&node,ASSIGN,num); 2084887Schin break; 2094887Schin case A_SWAP: 2104887Schin num = sp[-1]; 2114887Schin sp[-1] = *sp; 2124887Schin type = tp[-1]; 2134887Schin tp[-1] = *tp; 2144887Schin break; 2154887Schin case A_POP: 2164887Schin sp--; 2174887Schin continue; 2184887Schin case A_PUSHV: 2194887Schin cp = roundptr(ep,cp,Sfdouble_t*); 2204887Schin dp = *((Sfdouble_t**)cp); 2214887Schin cp += sizeof(Sfdouble_t*); 2224887Schin c = *(short*)cp; 2234887Schin cp += sizeof(short); 2244887Schin node.value = (char*)dp; 2254887Schin node.flag = c; 2264887Schin node.isfloat=0; 2274887Schin node.level = level; 2284887Schin num = (*ep->fun)(&ptr,&node,VALUE,num); 2294887Schin if(node.value != (char*)dp) 2304887Schin arith_error(node.value,ptr,ep->emode); 2314887Schin *++sp = num; 2324887Schin type = node.isfloat; 2334887Schin if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN) 2344887Schin type = 1; 2354887Schin else 2364887Schin { 2374887Schin Sfdouble_t d=num; 2384887Schin if(num > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX) 2394887Schin { 2404887Schin type = 2; 2414887Schin d -= LDBL_LLONG_MAX; 2424887Schin } 2434887Schin if((Sflong_t)d!=d) 2444887Schin type = 1; 2454887Schin } 2464887Schin *++tp = type; 2474887Schin c = 0; 2484887Schin break; 2494887Schin case A_STORE: 2504887Schin cp = roundptr(ep,cp,Sfdouble_t*); 2514887Schin dp = *((Sfdouble_t**)cp); 2524887Schin cp += sizeof(Sfdouble_t*); 2534887Schin c = *(short*)cp; 2544887Schin if(c<0) 2554887Schin c = 0; 2564887Schin cp += sizeof(short); 2574887Schin node.value = (char*)dp; 2584887Schin node.flag = c; 2594887Schin num = (*ep->fun)(&ptr,&node,ASSIGN,num); 2604887Schin break; 2614887Schin case A_PUSHF: 2624887Schin cp = roundptr(ep,cp,Fun_t); 2634887Schin *++sp = (Sfdouble_t)(cp-ep->code); 2644887Schin cp += sizeof(Fun_t); 2654887Schin *++tp = *cp++; 2664887Schin continue; 2674887Schin case A_PUSHN: 2684887Schin cp = roundptr(ep,cp,Sfdouble_t); 2694887Schin num = *((Sfdouble_t*)cp); 2704887Schin cp += sizeof(Sfdouble_t); 2714887Schin *++sp = num; 2724887Schin *++tp = type = *cp++; 2734887Schin break; 2744887Schin case A_NOT: 2754887Schin type=0; 2764887Schin num = !num; 2774887Schin break; 2784887Schin case A_UMINUS: 2794887Schin num = -num; 2804887Schin break; 2814887Schin case A_TILDE: 2824887Schin num = ~((Sflong_t)(num)); 2834887Schin break; 2844887Schin case A_PLUS: 2854887Schin num += sp[-1]; 2864887Schin break; 2874887Schin case A_MINUS: 2884887Schin num = sp[-1] - num; 2894887Schin break; 2904887Schin case A_TIMES: 2914887Schin num *= sp[-1]; 2924887Schin break; 2934887Schin case A_POW: 2944887Schin num = pow(sp[-1],num); 2954887Schin break; 2964887Schin case A_MOD: 2974887Schin if(!(Sflong_t)num) 2984887Schin arith_error(e_divzero,ep->expr,ep->emode); 2994887Schin if(type==2 || tp[-1]==2) 3004887Schin num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num)); 3014887Schin else 3024887Schin num = (Sflong_t)(sp[-1]) % (Sflong_t)(num); 3034887Schin break; 3044887Schin case A_DIV: 3054887Schin if(type==1 || tp[-1]==1) 3064887Schin { 3074887Schin num = sp[-1]/num; 3084887Schin type = 1; 3094887Schin } 3104887Schin else if((Sfulong_t)(num)==0) 3114887Schin arith_error(e_divzero,ep->expr,ep->emode); 3124887Schin else if(type==2 || tp[-1]==2) 3134887Schin num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num)); 3144887Schin else 3154887Schin num = (Sflong_t)(sp[-1]) / (Sflong_t)(num); 3164887Schin break; 3174887Schin case A_LSHIFT: 3184887Schin if(tp[-1]==2) 3194887Schin num = U2F((Sfulong_t)(sp[-1]) << (long)(num)); 3204887Schin else 3214887Schin num = (Sflong_t)(sp[-1]) << (long)(num); 3224887Schin break; 3234887Schin case A_RSHIFT: 3244887Schin if(tp[-1]==2) 3254887Schin num = U2F((Sfulong_t)(sp[-1]) >> (long)(num)); 3264887Schin else 3274887Schin num = (Sflong_t)(sp[-1]) >> (long)(num); 3284887Schin break; 3294887Schin case A_XOR: 3304887Schin if(type==2 || tp[-1]==2) 3314887Schin num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num)); 3324887Schin else 3334887Schin num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num); 3344887Schin break; 3354887Schin case A_OR: 3364887Schin if(type==2 || tp[-1]==2) 3374887Schin num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num)); 3384887Schin else 3394887Schin num = (Sflong_t)(sp[-1]) | (Sflong_t)(num); 3404887Schin break; 3414887Schin case A_AND: 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_EQ: 3484887Schin num = (sp[-1]==num); 3494887Schin type=0; 3504887Schin break; 3514887Schin case A_NEQ: 3524887Schin num = (sp[-1]!=num); 3534887Schin type=0; 3544887Schin break; 3554887Schin case A_LE: 3564887Schin num = (sp[-1]<=num); 3574887Schin type=0; 3584887Schin break; 3594887Schin case A_GE: 3604887Schin num = (sp[-1]>=num); 3614887Schin type=0; 3624887Schin break; 3634887Schin case A_GT: 3644887Schin num = (sp[-1]>num); 3654887Schin type=0; 3664887Schin break; 3674887Schin case A_LT: 3684887Schin num = (sp[-1]<num); 3694887Schin type=0; 3704887Schin break; 3714887Schin case A_CALL0: 3724887Schin sp--,tp--; 3734887Schin fun = *((Fun_t*)(ep->code+(int)(*sp))); 3744887Schin type = 0; 3754887Schin num = (*((Math_0_f)fun))(num); 3764887Schin break; 3774887Schin case A_CALL1: 3784887Schin sp--,tp--; 3794887Schin fun = *((Fun_t*)(ep->code+(int)(*sp))); 3804887Schin type = *tp; 3814887Schin num = (*fun)(num); 3824887Schin break; 3834887Schin case A_CALL2: 3844887Schin sp-=2,tp-=2; 3854887Schin fun = *((Fun_t*)(ep->code+(int)(*sp))); 3864887Schin type = *tp; 3874887Schin num = (*((Math_2_f)fun))(sp[1],num); 3884887Schin break; 3894887Schin case A_CALL3: 3904887Schin sp-=3,tp-=3; 3914887Schin fun = *((Fun_t*)(ep->code+(int)(*sp))); 3924887Schin type = *tp; 3934887Schin num = (*((Math_3_f)fun))(sp[1],sp[2],num); 3944887Schin break; 3954887Schin } 3964887Schin if(c&T_BINARY) 3974887Schin sp--,tp--; 3984887Schin *sp = num; 3994887Schin *tp = type; 4004887Schin } 4014887Schin if(level>0) 4024887Schin level--; 4034887Schin return(num); 4044887Schin } 4054887Schin 4064887Schin /* 4074887Schin * This returns operator tokens or A_REG or A_NUM 4084887Schin */ 4094887Schin static int gettok(register struct vars *vp) 4104887Schin { 4114887Schin register int c,op; 4124887Schin vp->errchr = vp->nextchr; 4134887Schin while(1) 4144887Schin { 4154887Schin c = getchr(vp); 4164887Schin switch(op=getop(c)) 4174887Schin { 4184887Schin case 0: 4194887Schin vp->errchr = vp->nextchr; 4204887Schin continue; 4214887Schin case A_EOF: 4224887Schin vp->nextchr--; 4234887Schin break; 4244887Schin /*FALL THRU*/ 4254887Schin case A_DIG: case A_REG: case A_DOT: case A_LIT: 4264887Schin if(op==A_DOT) 4274887Schin { 4284887Schin if((c=peekchr(vp))>='0' && c<='9') 4294887Schin op = A_DIG; 4304887Schin else 4314887Schin op = A_REG; 4324887Schin } 4334887Schin ungetchr(vp); 4344887Schin break; 4354887Schin case A_QUEST: 4364887Schin if(peekchr(vp)==':') 4374887Schin { 4384887Schin getchr(vp); 4394887Schin op = A_QCOLON; 4404887Schin } 4414887Schin break; 4424887Schin case A_LT: case A_GT: 4434887Schin if(peekchr(vp)==c) 4444887Schin { 4454887Schin getchr(vp); 4464887Schin op -= 2; 4474887Schin break; 4484887Schin } 4494887Schin /* FALL THRU */ 4504887Schin case A_NOT: case A_COLON: 4514887Schin c = '='; 4524887Schin /* FALL THRU */ 4534887Schin case A_ASSIGN: 4544887Schin case A_TIMES: 4554887Schin case A_PLUS: case A_MINUS: 4564887Schin case A_OR: case A_AND: 4574887Schin if(peekchr(vp)==c) 4584887Schin { 4594887Schin getchr(vp); 4604887Schin op--; 4614887Schin } 4624887Schin } 4634887Schin return(op); 4644887Schin } 4654887Schin } 4664887Schin 4674887Schin /* 4684887Schin * evaluate a subexpression with precedence 4694887Schin */ 4704887Schin 4714887Schin static int expr(register struct vars *vp,register int precedence) 4724887Schin { 4734887Schin register int c, op; 4744887Schin int invalid,wasop=0; 4754887Schin struct lval lvalue,assignop; 4764887Schin const char *pos; 4774887Schin Sfdouble_t d; 4784887Schin 4794887Schin lvalue.value = 0; 4804887Schin lvalue.fun = 0; 4814887Schin again: 4824887Schin op = gettok(vp); 4834887Schin c = 2*MAXPREC+1; 4844887Schin switch(op) 4854887Schin { 4864887Schin case A_PLUS: 4874887Schin goto again; 4884887Schin case A_EOF: 489*8462SApril.Chin@Sun.COM if(precedence>2) 4904887Schin ERROR(vp,e_moretokens); 4914887Schin return(1); 4924887Schin case A_MINUS: 4934887Schin op = A_UMINUS; 4944887Schin goto common; 4954887Schin case A_NOT: 4964887Schin goto common; 4974887Schin case A_MINUSMINUS: 4984887Schin c = A_LVALUE; 4994887Schin op = A_DECR|T_NOFLOAT; 5004887Schin goto common; 5014887Schin case A_PLUSPLUS: 5024887Schin c = A_LVALUE; 5034887Schin op = A_INCR|T_NOFLOAT; 5044887Schin /* FALL THRU */ 5054887Schin case A_TILDE: 5064887Schin op |= T_NOFLOAT; 5074887Schin common: 5084887Schin if(!expr(vp,c)) 5094887Schin return(0); 5104887Schin stakputc(op); 5114887Schin break; 5124887Schin default: 5134887Schin vp->nextchr = vp->errchr; 5144887Schin wasop = 1; 5154887Schin } 5164887Schin invalid = wasop; 5174887Schin while(1) 5184887Schin { 5194887Schin assignop.value = 0; 5204887Schin op = gettok(vp); 5214887Schin if(op==A_DIG || op==A_REG || op==A_LIT) 5224887Schin { 5234887Schin if(!wasop) 5244887Schin ERROR(vp,e_synbad); 5254887Schin goto number; 5264887Schin } 5274887Schin if(wasop++ && op!=A_LPAR) 5284887Schin ERROR(vp,e_synbad); 5294887Schin /* check for assignment operation */ 5304887Schin if(peekchr(vp)== '=' && !(strval_precedence[op]&NOASSIGN)) 5314887Schin { 5324887Schin if((!lvalue.value || precedence > 3)) 5334887Schin ERROR(vp,e_notlvalue); 5344887Schin if(precedence==3) 5354887Schin precedence = 2; 5364887Schin assignop = lvalue; 5374887Schin getchr(vp); 5384887Schin c = 3; 5394887Schin } 5404887Schin else 5414887Schin { 5424887Schin c = (strval_precedence[op]&PRECMASK); 5434887Schin if(c==MAXPREC || op==A_POW) 5444887Schin c++; 5454887Schin c *= 2; 5464887Schin } 5474887Schin /* from here on c is the new precedence level */ 5484887Schin if(lvalue.value && (op!=A_ASSIGN)) 5494887Schin { 5504887Schin if(vp->staksize++>=vp->stakmaxsize) 5514887Schin vp->stakmaxsize = vp->staksize; 5524887Schin stakputc(A_PUSHV); 5534887Schin stakpush(vp,lvalue.value,char*); 5544887Schin if(lvalue.flag<0) 5554887Schin lvalue.flag = 0; 5564887Schin stakpush(vp,lvalue.flag,short); 5574887Schin if(vp->nextchr==0) 5584887Schin ERROR(vp,e_badnum); 5594887Schin if(!(strval_precedence[op]&SEQPOINT)) 5604887Schin lvalue.value = 0; 5614887Schin invalid = 0; 5624887Schin } 5634887Schin else if(precedence==A_LVALUE) 5644887Schin ERROR(vp,e_notlvalue); 5654887Schin if(invalid && op>A_ASSIGN) 5664887Schin ERROR(vp,e_synbad); 5674887Schin if(precedence >= c) 5684887Schin goto done; 5694887Schin if(strval_precedence[op]&RASSOC) 5704887Schin c--; 5714887Schin if((c < (2*MAXPREC+1)) && !(strval_precedence[op]&SEQPOINT)) 5724887Schin { 5734887Schin wasop = 0; 5744887Schin if(!expr(vp,c)) 5754887Schin return(0); 5764887Schin } 5774887Schin switch(op) 5784887Schin { 5794887Schin case A_RPAR: 5804887Schin if(!vp->paren) 5814887Schin ERROR(vp,e_paren); 5824887Schin if(invalid) 5834887Schin ERROR(vp,e_synbad); 5844887Schin goto done; 5854887Schin 5864887Schin case A_COMMA: 5874887Schin wasop = 0; 5884887Schin if(vp->infun) 5894887Schin vp->infun++; 5904887Schin else 5914887Schin { 5924887Schin stakputc(A_POP); 5934887Schin vp->staksize--; 5944887Schin } 5954887Schin if(!expr(vp,c)) 5964887Schin return(0); 5974887Schin lvalue.value = 0; 5984887Schin break; 5994887Schin 6004887Schin case A_LPAR: 6014887Schin { 6024887Schin int infun = vp->infun; 6034887Schin Sfdouble_t (*fun)(Sfdouble_t,...); 6044887Schin int nargs = lvalue.nargs; 6054887Schin fun = lvalue.fun; 6064887Schin lvalue.fun = 0; 6074887Schin if(fun) 6084887Schin { 6094887Schin if(vp->staksize++>=vp->stakmaxsize) 6104887Schin vp->stakmaxsize = vp->staksize; 6114887Schin vp->infun=1; 6124887Schin stakputc(A_PUSHF); 6134887Schin stakpush(vp,fun,Fun_t); 6144887Schin stakputc(1); 6154887Schin } 6164887Schin else 6174887Schin vp->infun = 0; 6184887Schin if(!invalid) 6194887Schin ERROR(vp,e_synbad); 6204887Schin vp->paren++; 6214887Schin if(!expr(vp,1)) 6224887Schin return(0); 6234887Schin vp->paren--; 6244887Schin if(fun) 6254887Schin { 6264887Schin int x= (nargs>7); 6274887Schin nargs &= 7; 6284887Schin if(vp->infun != nargs) 6294887Schin ERROR(vp,e_argcount); 6304887Schin if(vp->staksize+=nargs>=vp->stakmaxsize) 6314887Schin vp->stakmaxsize = vp->staksize+nargs; 6324887Schin stakputc(A_CALL0+nargs -x); 6334887Schin vp->staksize -= nargs; 6344887Schin } 6354887Schin vp->infun = infun; 6364887Schin if (gettok(vp) != A_RPAR) 6374887Schin ERROR(vp,e_paren); 6384887Schin wasop = 0; 6394887Schin break; 6404887Schin } 6414887Schin 6424887Schin case A_PLUSPLUS: 6434887Schin case A_MINUSMINUS: 6444887Schin wasop=0; 6454887Schin op |= T_NOFLOAT; 6464887Schin case A_ASSIGN: 6474887Schin if(!lvalue.value) 6484887Schin ERROR(vp,e_notlvalue); 6494887Schin if(op==A_ASSIGN) 6504887Schin { 6514887Schin stakputc(A_STORE); 6524887Schin stakpush(vp,lvalue.value,char*); 6534887Schin stakpush(vp,lvalue.flag,short); 6544887Schin vp->staksize--; 6554887Schin } 6564887Schin else 6574887Schin stakputc(op); 6584887Schin lvalue.value = 0; 6594887Schin break; 6604887Schin 6614887Schin case A_QUEST: 6624887Schin { 6634887Schin int offset1,offset2; 6644887Schin stakputc(A_JMPZ); 6654887Schin offset1 = stakpush(vp,0,short); 6664887Schin stakputc(A_POP); 6674887Schin if(!expr(vp,1)) 6684887Schin return(0); 6694887Schin if(gettok(vp)!=A_COLON) 6704887Schin ERROR(vp,e_questcolon); 6714887Schin stakputc(A_JMP); 6724887Schin offset2 = stakpush(vp,0,short); 6734887Schin *((short*)stakptr(offset1)) = staktell(); 6744887Schin stakputc(A_POP); 6754887Schin if(!expr(vp,3)) 6764887Schin return(0); 6774887Schin *((short*)stakptr(offset2)) = staktell(); 6784887Schin lvalue.value = 0; 6794887Schin wasop = 0; 6804887Schin break; 6814887Schin } 6824887Schin 6834887Schin case A_COLON: 6844887Schin ERROR(vp,e_badcolon); 6854887Schin break; 6864887Schin 6874887Schin case A_QCOLON: 6884887Schin case A_ANDAND: 6894887Schin case A_OROR: 6904887Schin { 6914887Schin int offset; 6924887Schin if(op==A_ANDAND) 6934887Schin op = A_JMPZ; 6944887Schin else 6954887Schin op = A_JMPNZ; 6964887Schin stakputc(op); 6974887Schin offset = stakpush(vp,0,short); 6984887Schin stakputc(A_POP); 6994887Schin if(!expr(vp,c)) 7004887Schin return(0); 7014887Schin *((short*)stakptr(offset)) = staktell(); 7024887Schin if(op!=A_QCOLON) 7034887Schin stakputc(A_NOTNOT); 7044887Schin lvalue.value = 0; 7054887Schin wasop=0; 7064887Schin break; 7074887Schin } 7084887Schin case A_AND: case A_OR: case A_XOR: case A_LSHIFT: 7094887Schin case A_RSHIFT: case A_MOD: 7104887Schin op |= T_NOFLOAT; 7114887Schin /* FALL THRU */ 7124887Schin case A_PLUS: case A_MINUS: case A_TIMES: case A_DIV: 7134887Schin case A_EQ: case A_NEQ: case A_LT: case A_LE: 7144887Schin case A_GT: case A_GE: case A_POW: 7154887Schin stakputc(op|T_BINARY); 7164887Schin vp->staksize--; 7174887Schin break; 7184887Schin case A_NOT: case A_TILDE: 7194887Schin default: 7204887Schin ERROR(vp,e_synbad); 7214887Schin number: 7224887Schin wasop = 0; 7234887Schin if(*vp->nextchr=='L' && vp->nextchr[1]=='\'') 7244887Schin { 7254887Schin vp->nextchr++; 7264887Schin op = A_LIT; 7274887Schin } 7284887Schin pos = vp->nextchr; 7294887Schin lvalue.isfloat = 0; 7304887Schin lvalue.expr = vp->expr; 7314887Schin lvalue.emode = vp->emode; 7324887Schin if(op==A_LIT) 7334887Schin { 7344887Schin /* character constants */ 7354887Schin if(pos[1]=='\\' && pos[2]=='\'' && pos[3]!='\'') 7364887Schin { 7374887Schin d = '\\'; 7384887Schin vp->nextchr +=2; 7394887Schin } 7404887Schin else 7414887Schin d = chresc(pos+1,(char**)&vp->nextchr); 7424887Schin /* posix allows the trailing ' to be optional */ 7434887Schin if(*vp->nextchr=='\'') 7444887Schin vp->nextchr++; 7454887Schin } 7464887Schin else 7474887Schin d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0); 7484887Schin if (vp->nextchr == pos) 7494887Schin { 7504887Schin if(vp->errmsg.value = lvalue.value) 7514887Schin vp->errstr = pos; 7524887Schin ERROR(vp,op==A_LIT?e_charconst:e_synbad); 7534887Schin } 7544887Schin if(op==A_DIG || op==A_LIT) 7554887Schin { 7564887Schin stakputc(A_PUSHN); 7574887Schin if(vp->staksize++>=vp->stakmaxsize) 7584887Schin vp->stakmaxsize = vp->staksize; 7594887Schin stakpush(vp,d,Sfdouble_t); 7604887Schin stakputc(lvalue.isfloat); 7614887Schin } 7624887Schin 7634887Schin /* check for function call */ 7644887Schin if(lvalue.fun) 7654887Schin continue; 7664887Schin break; 7674887Schin } 7684887Schin invalid = 0; 7694887Schin if(assignop.value) 7704887Schin { 7714887Schin if(vp->staksize++>=vp->stakmaxsize) 7724887Schin vp->stakmaxsize = vp->staksize; 7734887Schin if(assignop.flag<0) 7744887Schin assignop.flag = 0; 7754887Schin stakputc(A_STORE); 7764887Schin stakpush(vp,assignop.value,char*); 7774887Schin stakpush(vp,assignop.flag,short); 7784887Schin } 7794887Schin } 7804887Schin done: 7814887Schin vp->nextchr = vp->errchr; 7824887Schin return(1); 7834887Schin } 7844887Schin 7854887Schin Arith_t *arith_compile(const char *string,char **last,Sfdouble_t(*fun)(const char**,struct lval*,int,Sfdouble_t),int emode) 7864887Schin { 7874887Schin struct vars cur; 7884887Schin register Arith_t *ep; 7894887Schin int offset; 7904887Schin memset((void*)&cur,0,sizeof(cur)); 7914887Schin cur.emode = emode; 7924887Schin cur.expr = cur.nextchr = string; 7934887Schin cur.convert = fun; 7944887Schin cur.emode = emode; 7954887Schin cur.errmsg.value = 0; 7964887Schin cur.errmsg.emode = emode; 7974887Schin stakseek(sizeof(Arith_t)); 7984887Schin if(!expr(&cur,0) && cur.errmsg.value) 7994887Schin { 8004887Schin if(cur.errstr) 8014887Schin string = cur.errstr; 8024887Schin (*fun)( &string , &cur.errmsg, MESSAGE, 0); 8034887Schin cur.nextchr = cur.errchr; 8044887Schin } 8054887Schin stakputc(0); 8064887Schin offset = staktell(); 8074887Schin ep = (Arith_t*)stakfreeze(0); 8084887Schin ep->expr = string; 8094887Schin ep->elen = strlen(string); 8104887Schin ep->code = (unsigned char*)(ep+1); 8114887Schin ep->fun = fun; 8124887Schin ep->emode = emode; 8134887Schin ep->size = offset - sizeof(Arith_t); 8144887Schin ep->staksize = cur.stakmaxsize+1; 8154887Schin if(last) 8164887Schin *last = (char*)(cur.nextchr); 8174887Schin return(ep); 8184887Schin } 8194887Schin 8204887Schin /* 8214887Schin * evaluate an integer arithmetic expression in s 8224887Schin * 8234887Schin * (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value) 8244887Schin * is a user supplied conversion routine that is called when unknown 8254887Schin * chars are encountered. 8264887Schin * *end points to the part to be converted and must be adjusted by convert to 8274887Schin * point to the next non-converted character; if typ is MESSAGE then string 8284887Schin * points to an error message string 8294887Schin * 8304887Schin * NOTE: (*convert)() may call strval() 8314887Schin */ 8324887Schin 8334887Schin Sfdouble_t strval(const char *s,char **end,Sfdouble_t(*conv)(const char**,struct lval*,int,Sfdouble_t),int emode) 8344887Schin { 8354887Schin Arith_t *ep; 8364887Schin Sfdouble_t d; 8374887Schin char *sp=0; 8384887Schin int offset; 8394887Schin if(offset=staktell()) 8404887Schin sp = stakfreeze(1); 8414887Schin ep = arith_compile(s,end,conv,emode); 8424887Schin ep->emode = emode; 8434887Schin d = arith_exec(ep); 8444887Schin stakset(sp?sp:(char*)ep,offset); 8454887Schin return(d); 8464887Schin } 8474887Schin 8484887Schin #if _mem_name__exception 8494887Schin #undef _mem_name_exception 8504887Schin #define _mem_name_exception 1 8514887Schin #undef exception 8524887Schin #define exception _exception 8534887Schin #undef matherr 8544887Schin #endif 8554887Schin 8564887Schin #if _mem_name_exception 8574887Schin 8584887Schin #undef error 8594887Schin 8604887Schin #if _BLD_shell && defined(__EXPORT__) 8614887Schin #define extern __EXPORT__ 8624887Schin #endif 8634887Schin 8644887Schin #ifndef DOMAIN 8654887Schin #define DOMAIN _DOMAIN 8664887Schin #endif 8674887Schin #ifndef OVERFLOW 8684887Schin #define OVERFLOW _OVERFLOW 8694887Schin #endif 8704887Schin #ifndef SING 8714887Schin #define SING _SING 8724887Schin #endif 8734887Schin 8744887Schin extern int matherr(struct exception *ep) 8754887Schin { 8764887Schin const char *message; 8774887Schin switch(ep->type) 8784887Schin { 8794887Schin #ifdef DOMAIN 8804887Schin case DOMAIN: 8814887Schin message = ERROR_dictionary(e_domain); 8824887Schin break; 8834887Schin #endif 8844887Schin #ifdef OVERFLOW 8854887Schin case OVERFLOW: 8864887Schin message = ERROR_dictionary(e_overflow); 8874887Schin break; 8884887Schin #endif 8894887Schin #ifdef SING 8904887Schin case SING: 8914887Schin message = ERROR_dictionary(e_singularity); 8924887Schin break; 8934887Schin #endif 8944887Schin default: 8954887Schin return(1); 8964887Schin } 8974887Schin level=0; 8984887Schin errormsg(SH_DICT,ERROR_exit(1),message,ep->name); 8994887Schin return(0); 9004887Schin } 9014887Schin 9024887Schin #undef extern 9034887Schin 9044887Schin #endif /* _mem_name_exception */ 905