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