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 */
_seterror(struct vars * vp,const char * msg)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
arith_error(const char * message,const char * expr,int mode)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
U2F(Sfulong_t u)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
arith_exec(Arith_t * ep)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 */
gettok(register struct vars * vp)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
expr(register struct vars * vp,register int precedence)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
arith_compile(const char * string,char ** last,Sfdouble_t (* fun)(const char **,struct lval *,int,Sfdouble_t),int emode)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
strval(const char * s,char ** end,Sfdouble_t (* conv)(const char **,struct lval *,int,Sfdouble_t),int emode)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
matherr(struct exception * ep)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