1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1982-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                  David Korn <dgk@research.att.com>                   *
18*4887Schin *                                                                      *
19*4887Schin ***********************************************************************/
20*4887Schin #pragma prototyped
21*4887Schin 
22*4887Schin /*
23*4887Schin  * D. G. Korn
24*4887Schin  * AT&T Labs
25*4887Schin  *
26*4887Schin  * arithmetic expression evaluator
27*4887Schin  *
28*4887Schin  * this version compiles the expression onto a stack
29*4887Schin  *	 and has a separate executor
30*4887Schin  */
31*4887Schin 
32*4887Schin #include	"streval.h"
33*4887Schin #include	<ctype.h>
34*4887Schin #include	<error.h>
35*4887Schin #include	<stak.h>
36*4887Schin #include	"FEATURE/externs"
37*4887Schin 
38*4887Schin #ifndef ERROR_dictionary
39*4887Schin #   define ERROR_dictionary(s)	(s)
40*4887Schin #endif
41*4887Schin #ifndef SH_DICT
42*4887Schin #   define SH_DICT	"libshell"
43*4887Schin #endif
44*4887Schin 
45*4887Schin #define MAXLEVEL	9
46*4887Schin #define SMALL_STACK	12
47*4887Schin 
48*4887Schin /*
49*4887Schin  * The following are used with tokenbits() macro
50*4887Schin  */
51*4887Schin #define T_OP		0x3f		/* mask for operator number */
52*4887Schin #define T_BINARY	0x40		/* binary operators */
53*4887Schin #define T_NOFLOAT	0x80		/* non floating point operator */
54*4887Schin #define A_LVALUE	(2*MAXPREC+2)
55*4887Schin 
56*4887Schin #define pow2size(x)		((x)<=2?2:(x)<=4?4:(x)<=8?8:(x)<=16?16:(x)<=32?32:64)
57*4887Schin #define round(x,size)		(((x)+(size)-1)&~((size)-1))
58*4887Schin #define stakpush(v,val,type)	((((v)->offset=round(staktell(),pow2size(sizeof(type)))),\
59*4887Schin 				stakseek((v)->offset+sizeof(type)), \
60*4887Schin 				*((type*)stakptr((v)->offset)) = (val)),(v)->offset)
61*4887Schin #define roundptr(ep,cp,type)	(((unsigned char*)(ep))+round(cp-((unsigned char*)(ep)),pow2size(sizeof(type))))
62*4887Schin 
63*4887Schin static int level;
64*4887Schin 
65*4887Schin struct vars				/* vars stacked per invocation */
66*4887Schin {
67*4887Schin 	const char	*expr;		/* current expression */
68*4887Schin 	const char	*nextchr;	/* next char in current expression */
69*4887Schin 	const char	*errchr; 	/* next char after error	*/
70*4887Schin 	const char	*errstr;	/* error string			*/
71*4887Schin 	struct lval	errmsg;	 	/* error message text		*/
72*4887Schin 	int		offset;		/* offset for pushchr macro	*/
73*4887Schin 	int		staksize;	/* current stack size needed	*/
74*4887Schin 	int		stakmaxsize;	/* maximum stack size needed	*/
75*4887Schin 	unsigned char	paren;	 	/* parenthesis level		*/
76*4887Schin 	char		infun;	/* incremented by comma inside function	*/
77*4887Schin 	int		emode;
78*4887Schin 	Sfdouble_t	(*convert)(const char**,struct lval*,int,Sfdouble_t);
79*4887Schin };
80*4887Schin 
81*4887Schin typedef int	   (*Math_0_f)(Sfdouble_t);
82*4887Schin typedef Sfdouble_t (*Fun_t)(Sfdouble_t,...);
83*4887Schin typedef Sfdouble_t (*Math_1_f)(Sfdouble_t);
84*4887Schin typedef Sfdouble_t (*Math_2_f)(Sfdouble_t,Sfdouble_t);
85*4887Schin typedef Sfdouble_t (*Math_3_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
86*4887Schin 
87*4887Schin #define getchr(vp)	(*(vp)->nextchr++)
88*4887Schin #define peekchr(vp)	(*(vp)->nextchr)
89*4887Schin #define ungetchr(vp)	((vp)->nextchr--)
90*4887Schin 
91*4887Schin #if ('a'==97)	/* ASCII encodings */
92*4887Schin #   define getop(c)	(((c) >= sizeof(strval_states))? \
93*4887Schin 				((c)=='|'?A_OR:((c)=='^'?A_XOR:((c)=='~'?A_TILDE:A_REG))):\
94*4887Schin 				strval_states[(c)])
95*4887Schin #else
96*4887Schin #   define getop(c)	(isdigit(c)?A_DIG:((c==' '||c=='\t'||c=='\n'||c=='"')?0: \
97*4887Schin 			(c=='<'?A_LT:(c=='>'?A_GT:(c=='='?A_ASSIGN: \
98*4887Schin 			(c=='+'?A_PLUS:(c=='-'?A_MINUS:(c=='*'?A_TIMES: \
99*4887Schin 			(c=='/'?A_DIV:(c=='%'?A_MOD:(c==','?A_COMMA: \
100*4887Schin 			(c=='&'?A_AND:(c=='!'?A_NOT:(c=='('?A_LPAR: \
101*4887Schin 			(c==')'?A_RPAR:(c==0?A_EOF:(c==':'?A_COLON: \
102*4887Schin 			(c=='?'?A_QUEST:(c=='|'?A_OR:(c=='^'?A_XOR: \
103*4887Schin 			(c=='\''?A_LIT: \
104*4887Schin 			(c=='.'?A_DOT:(c=='~'?A_TILDE:A_REG)))))))))))))))))))))))
105*4887Schin #endif
106*4887Schin 
107*4887Schin #define seterror(v,msg)		_seterror(v,ERROR_dictionary(msg))
108*4887Schin #define ERROR(vp,msg)		return(seterror((vp),msg))
109*4887Schin 
110*4887Schin /*
111*4887Schin  * set error message string and return(0)
112*4887Schin  */
113*4887Schin static int _seterror(struct vars *vp,const char *msg)
114*4887Schin {
115*4887Schin 	if(!vp->errmsg.value)
116*4887Schin 		vp->errmsg.value = (char*)msg;
117*4887Schin 	vp->errchr = vp->nextchr;
118*4887Schin 	vp->nextchr = "";
119*4887Schin 	level = 0;
120*4887Schin 	return(0);
121*4887Schin }
122*4887Schin 
123*4887Schin 
124*4887Schin static void arith_error(const char *message,const char *expr, int mode)
125*4887Schin {
126*4887Schin         level = 0;
127*4887Schin 	mode = (mode&3)!=0;
128*4887Schin         errormsg(SH_DICT,ERROR_exit(mode),message,expr);
129*4887Schin }
130*4887Schin 
131*4887Schin #if _ast_no_um2fm
132*4887Schin static Sfdouble_t U2F(Sfulong_t u)
133*4887Schin {
134*4887Schin 	Sflong_t	s = u;
135*4887Schin 	Sfdouble_t	f;
136*4887Schin 
137*4887Schin 	if (s >= 0)
138*4887Schin 		return s;
139*4887Schin 	s = u / 2;
140*4887Schin 	f = s;
141*4887Schin 	f *= 2;
142*4887Schin 	if (u & 1)
143*4887Schin 		f++;
144*4887Schin 	return f;
145*4887Schin }
146*4887Schin #else
147*4887Schin #define U2F(x)		x
148*4887Schin #endif
149*4887Schin 
150*4887Schin Sfdouble_t	arith_exec(Arith_t *ep)
151*4887Schin {
152*4887Schin 	register Sfdouble_t num=0,*dp,*sp;
153*4887Schin 	register unsigned char *cp = ep->code;
154*4887Schin 	register int c,type=0;
155*4887Schin 	register char *tp;
156*4887Schin 	Sfdouble_t small_stack[SMALL_STACK+1];
157*4887Schin 	const char *ptr = "";
158*4887Schin 	Fun_t fun;
159*4887Schin 	struct lval node;
160*4887Schin 	node.emode = ep->emode;
161*4887Schin 	node.expr = ep->expr;
162*4887Schin 	node.elen = ep->elen;
163*4887Schin 	if(level++ >=MAXLEVEL)
164*4887Schin 	{
165*4887Schin 		arith_error(e_recursive,ep->expr,ep->emode);
166*4887Schin 		return(0);
167*4887Schin 	}
168*4887Schin 	if(ep->staksize < SMALL_STACK)
169*4887Schin 		sp = small_stack;
170*4887Schin 	else
171*4887Schin 		sp = (Sfdouble_t*)stakalloc(ep->staksize*(sizeof(Sfdouble_t)+1));
172*4887Schin 	tp = (char*)(sp+ep->staksize);
173*4887Schin 	tp--,sp--;
174*4887Schin 	while(c = *cp++)
175*4887Schin 	{
176*4887Schin 		if(c&T_NOFLOAT)
177*4887Schin 		{
178*4887Schin 			if(type==1 || ((c&T_BINARY) && (c&T_OP)!=A_MOD  && tp[-1]==1))
179*4887Schin 				arith_error(e_incompatible,ep->expr,ep->emode);
180*4887Schin 		}
181*4887Schin 		switch(c&T_OP)
182*4887Schin 		{
183*4887Schin 		    case A_JMP: case A_JMPZ: case A_JMPNZ:
184*4887Schin 			c &= T_OP;
185*4887Schin 			cp = roundptr(ep,cp,short);
186*4887Schin 			if((c==A_JMPZ && num) || (c==A_JMPNZ &&!num))
187*4887Schin 				cp += sizeof(short);
188*4887Schin 			else
189*4887Schin 				cp = (unsigned char*)ep + *((short*)cp);
190*4887Schin 			continue;
191*4887Schin 		    case A_NOTNOT:
192*4887Schin 			num = (num!=0);
193*4887Schin 			type=0;
194*4887Schin 			break;
195*4887Schin 		    case A_PLUSPLUS:
196*4887Schin 			(*ep->fun)(&ptr,&node,ASSIGN,num+1);
197*4887Schin 			break;
198*4887Schin 		    case A_MINUSMINUS:
199*4887Schin 			(*ep->fun)(&ptr,&node,ASSIGN,num-1);
200*4887Schin 			break;
201*4887Schin 		    case A_INCR:
202*4887Schin 			num = num+1;
203*4887Schin 			num = (*ep->fun)(&ptr,&node,ASSIGN,num);
204*4887Schin 			break;
205*4887Schin 		    case A_DECR:
206*4887Schin 			num = num-1;
207*4887Schin 			num = (*ep->fun)(&ptr,&node,ASSIGN,num);
208*4887Schin 			break;
209*4887Schin 		    case A_SWAP:
210*4887Schin 			num = sp[-1];
211*4887Schin 			sp[-1] = *sp;
212*4887Schin 			type = tp[-1];
213*4887Schin 			tp[-1] = *tp;
214*4887Schin 			break;
215*4887Schin 		    case A_POP:
216*4887Schin 			sp--;
217*4887Schin 			continue;
218*4887Schin 		    case A_PUSHV:
219*4887Schin 			cp = roundptr(ep,cp,Sfdouble_t*);
220*4887Schin 			dp = *((Sfdouble_t**)cp);
221*4887Schin 			cp += sizeof(Sfdouble_t*);
222*4887Schin 			c = *(short*)cp;
223*4887Schin 			cp += sizeof(short);
224*4887Schin 			node.value = (char*)dp;
225*4887Schin 			node.flag = c;
226*4887Schin 			node.isfloat=0;
227*4887Schin 			node.level = level;
228*4887Schin 			num = (*ep->fun)(&ptr,&node,VALUE,num);
229*4887Schin 			if(node.value != (char*)dp)
230*4887Schin 				arith_error(node.value,ptr,ep->emode);
231*4887Schin 			*++sp = num;
232*4887Schin 			type = node.isfloat;
233*4887Schin 			if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN)
234*4887Schin 				type = 1;
235*4887Schin 			else
236*4887Schin 			{
237*4887Schin 				Sfdouble_t d=num;
238*4887Schin 				if(num > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX)
239*4887Schin 				{
240*4887Schin 					type = 2;
241*4887Schin 					d -= LDBL_LLONG_MAX;
242*4887Schin 				}
243*4887Schin 				if((Sflong_t)d!=d)
244*4887Schin 					type = 1;
245*4887Schin 			}
246*4887Schin 			*++tp = type;
247*4887Schin 			c = 0;
248*4887Schin 			break;
249*4887Schin 		    case A_STORE:
250*4887Schin 			cp = roundptr(ep,cp,Sfdouble_t*);
251*4887Schin 			dp = *((Sfdouble_t**)cp);
252*4887Schin 			cp += sizeof(Sfdouble_t*);
253*4887Schin 			c = *(short*)cp;
254*4887Schin 			if(c<0)
255*4887Schin 				c = 0;
256*4887Schin 			cp += sizeof(short);
257*4887Schin 			node.value = (char*)dp;
258*4887Schin 			node.flag = c;
259*4887Schin 			num = (*ep->fun)(&ptr,&node,ASSIGN,num);
260*4887Schin 			break;
261*4887Schin 		    case A_PUSHF:
262*4887Schin 			cp = roundptr(ep,cp,Fun_t);
263*4887Schin 			*++sp = (Sfdouble_t)(cp-ep->code);
264*4887Schin 			cp += sizeof(Fun_t);
265*4887Schin 			*++tp = *cp++;
266*4887Schin 			continue;
267*4887Schin 		    case A_PUSHN:
268*4887Schin 			cp = roundptr(ep,cp,Sfdouble_t);
269*4887Schin 			num = *((Sfdouble_t*)cp);
270*4887Schin 			cp += sizeof(Sfdouble_t);
271*4887Schin 			*++sp = num;
272*4887Schin 			*++tp = type = *cp++;
273*4887Schin 			break;
274*4887Schin 		    case A_NOT:
275*4887Schin 			type=0;
276*4887Schin 			num = !num;
277*4887Schin 			break;
278*4887Schin 		    case A_UMINUS:
279*4887Schin 			num = -num;
280*4887Schin 			break;
281*4887Schin 		    case A_TILDE:
282*4887Schin 			num = ~((Sflong_t)(num));
283*4887Schin 			break;
284*4887Schin 		    case A_PLUS:
285*4887Schin 			num += sp[-1];
286*4887Schin 			break;
287*4887Schin 		    case A_MINUS:
288*4887Schin 			num = sp[-1] - num;
289*4887Schin 			break;
290*4887Schin 		    case A_TIMES:
291*4887Schin 			num *= sp[-1];
292*4887Schin 			break;
293*4887Schin 		    case A_POW:
294*4887Schin 			num = pow(sp[-1],num);
295*4887Schin 			break;
296*4887Schin 		    case A_MOD:
297*4887Schin 			if(!(Sflong_t)num)
298*4887Schin 				arith_error(e_divzero,ep->expr,ep->emode);
299*4887Schin 			if(type==2 || tp[-1]==2)
300*4887Schin 				num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num));
301*4887Schin 			else
302*4887Schin 				num = (Sflong_t)(sp[-1]) % (Sflong_t)(num);
303*4887Schin 			break;
304*4887Schin 		    case A_DIV:
305*4887Schin 			if(type==1 || tp[-1]==1)
306*4887Schin 			{
307*4887Schin 				num = sp[-1]/num;
308*4887Schin 				type = 1;
309*4887Schin 			}
310*4887Schin 			else if((Sfulong_t)(num)==0)
311*4887Schin 				arith_error(e_divzero,ep->expr,ep->emode);
312*4887Schin 			else if(type==2 || tp[-1]==2)
313*4887Schin 				num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num));
314*4887Schin 			else
315*4887Schin 				num = (Sflong_t)(sp[-1]) / (Sflong_t)(num);
316*4887Schin 			break;
317*4887Schin 		    case A_LSHIFT:
318*4887Schin 			if(tp[-1]==2)
319*4887Schin 				num = U2F((Sfulong_t)(sp[-1]) << (long)(num));
320*4887Schin 			else
321*4887Schin 				num = (Sflong_t)(sp[-1]) << (long)(num);
322*4887Schin 			break;
323*4887Schin 		    case A_RSHIFT:
324*4887Schin 			if(tp[-1]==2)
325*4887Schin 				num = U2F((Sfulong_t)(sp[-1]) >> (long)(num));
326*4887Schin 			else
327*4887Schin 				num = (Sflong_t)(sp[-1]) >> (long)(num);
328*4887Schin 			break;
329*4887Schin 		    case A_XOR:
330*4887Schin 			if(type==2 || tp[-1]==2)
331*4887Schin 				num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num));
332*4887Schin 			else
333*4887Schin 				num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num);
334*4887Schin 			break;
335*4887Schin 		    case A_OR:
336*4887Schin 			if(type==2 || tp[-1]==2)
337*4887Schin 				num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num));
338*4887Schin 			else
339*4887Schin 				num = (Sflong_t)(sp[-1]) | (Sflong_t)(num);
340*4887Schin 			break;
341*4887Schin 		    case A_AND:
342*4887Schin 			if(type==2 || tp[-1]==2)
343*4887Schin 				num = U2F((Sfulong_t)(sp[-1]) & (Sfulong_t)(num));
344*4887Schin 			else
345*4887Schin 				num = (Sflong_t)(sp[-1]) & (Sflong_t)(num);
346*4887Schin 			break;
347*4887Schin 		    case A_EQ:
348*4887Schin 			num = (sp[-1]==num);
349*4887Schin 			type=0;
350*4887Schin 			break;
351*4887Schin 		    case A_NEQ:
352*4887Schin 			num = (sp[-1]!=num);
353*4887Schin 			type=0;
354*4887Schin 			break;
355*4887Schin 		    case A_LE:
356*4887Schin 			num = (sp[-1]<=num);
357*4887Schin 			type=0;
358*4887Schin 			break;
359*4887Schin 		    case A_GE:
360*4887Schin 			num = (sp[-1]>=num);
361*4887Schin 			type=0;
362*4887Schin 			break;
363*4887Schin 		    case A_GT:
364*4887Schin 			num = (sp[-1]>num);
365*4887Schin 			type=0;
366*4887Schin 			break;
367*4887Schin 		    case A_LT:
368*4887Schin 			num = (sp[-1]<num);
369*4887Schin 			type=0;
370*4887Schin 			break;
371*4887Schin 		    case A_CALL0:
372*4887Schin 			sp--,tp--;
373*4887Schin 			fun = *((Fun_t*)(ep->code+(int)(*sp)));
374*4887Schin 			type = 0;
375*4887Schin 			num = (*((Math_0_f)fun))(num);
376*4887Schin 			break;
377*4887Schin 		    case A_CALL1:
378*4887Schin 			sp--,tp--;
379*4887Schin 			fun = *((Fun_t*)(ep->code+(int)(*sp)));
380*4887Schin 			type = *tp;
381*4887Schin 			num = (*fun)(num);
382*4887Schin 			break;
383*4887Schin 		    case A_CALL2:
384*4887Schin 			sp-=2,tp-=2;
385*4887Schin 			fun = *((Fun_t*)(ep->code+(int)(*sp)));
386*4887Schin 			type = *tp;
387*4887Schin 			num = (*((Math_2_f)fun))(sp[1],num);
388*4887Schin 			break;
389*4887Schin 		    case A_CALL3:
390*4887Schin 			sp-=3,tp-=3;
391*4887Schin 			fun = *((Fun_t*)(ep->code+(int)(*sp)));
392*4887Schin 			type = *tp;
393*4887Schin 			num = (*((Math_3_f)fun))(sp[1],sp[2],num);
394*4887Schin 			break;
395*4887Schin 		}
396*4887Schin 		if(c&T_BINARY)
397*4887Schin 			sp--,tp--;
398*4887Schin 		*sp = num;
399*4887Schin 		*tp = type;
400*4887Schin 	}
401*4887Schin 	if(level>0)
402*4887Schin 		level--;
403*4887Schin 	return(num);
404*4887Schin }
405*4887Schin 
406*4887Schin /*
407*4887Schin  * This returns operator tokens or A_REG or A_NUM
408*4887Schin  */
409*4887Schin static int gettok(register struct vars *vp)
410*4887Schin {
411*4887Schin 	register int c,op;
412*4887Schin 	vp->errchr = vp->nextchr;
413*4887Schin 	while(1)
414*4887Schin 	{
415*4887Schin 		c = getchr(vp);
416*4887Schin 		switch(op=getop(c))
417*4887Schin 		{
418*4887Schin 		    case 0:
419*4887Schin 			vp->errchr = vp->nextchr;
420*4887Schin 			continue;
421*4887Schin 		    case A_EOF:
422*4887Schin 			vp->nextchr--;
423*4887Schin 			break;
424*4887Schin 			/*FALL THRU*/
425*4887Schin 		    case A_DIG: case A_REG: case A_DOT: case A_LIT:
426*4887Schin 			if(op==A_DOT)
427*4887Schin 			{
428*4887Schin 				if((c=peekchr(vp))>='0' && c<='9')
429*4887Schin 					op = A_DIG;
430*4887Schin 				else
431*4887Schin 					op = A_REG;
432*4887Schin 			}
433*4887Schin 			ungetchr(vp);
434*4887Schin 			break;
435*4887Schin 		    case A_QUEST:
436*4887Schin 			if(peekchr(vp)==':')
437*4887Schin 			{
438*4887Schin 				getchr(vp);
439*4887Schin 				op = A_QCOLON;
440*4887Schin 			}
441*4887Schin 			break;
442*4887Schin 		    case A_LT:	case A_GT:
443*4887Schin 			if(peekchr(vp)==c)
444*4887Schin 			{
445*4887Schin 				getchr(vp);
446*4887Schin 				op -= 2;
447*4887Schin 				break;
448*4887Schin 			}
449*4887Schin 			/* FALL THRU */
450*4887Schin 		    case A_NOT:	case A_COLON:
451*4887Schin 			c = '=';
452*4887Schin 			/* FALL THRU */
453*4887Schin 		    case A_ASSIGN:
454*4887Schin 		    case A_TIMES:
455*4887Schin 		    case A_PLUS:	case A_MINUS:
456*4887Schin 		    case A_OR:	case A_AND:
457*4887Schin 			if(peekchr(vp)==c)
458*4887Schin 			{
459*4887Schin 				getchr(vp);
460*4887Schin 				op--;
461*4887Schin 			}
462*4887Schin 		}
463*4887Schin 		return(op);
464*4887Schin 	}
465*4887Schin }
466*4887Schin 
467*4887Schin /*
468*4887Schin  * evaluate a subexpression with precedence
469*4887Schin  */
470*4887Schin 
471*4887Schin static int expr(register struct vars *vp,register int precedence)
472*4887Schin {
473*4887Schin 	register int	c, op;
474*4887Schin 	int		invalid,wasop=0;
475*4887Schin 	struct lval	lvalue,assignop;
476*4887Schin 	const char	*pos;
477*4887Schin 	Sfdouble_t		d;
478*4887Schin 
479*4887Schin 	lvalue.value = 0;
480*4887Schin 	lvalue.fun = 0;
481*4887Schin again:
482*4887Schin 	op = gettok(vp);
483*4887Schin 	c = 2*MAXPREC+1;
484*4887Schin 	switch(op)
485*4887Schin 	{
486*4887Schin 	    case A_PLUS:
487*4887Schin 		goto again;
488*4887Schin 	    case A_EOF:
489*4887Schin 		if(precedence>5)
490*4887Schin 			ERROR(vp,e_moretokens);
491*4887Schin 		return(1);
492*4887Schin 	    case A_MINUS:
493*4887Schin 		op =  A_UMINUS;
494*4887Schin 		goto common;
495*4887Schin 	    case A_NOT:
496*4887Schin 		goto common;
497*4887Schin 	    case A_MINUSMINUS:
498*4887Schin 		c = A_LVALUE;
499*4887Schin 		op = A_DECR|T_NOFLOAT;
500*4887Schin 		goto common;
501*4887Schin 	    case A_PLUSPLUS:
502*4887Schin 		c = A_LVALUE;
503*4887Schin 		op = A_INCR|T_NOFLOAT;
504*4887Schin 		/* FALL THRU */
505*4887Schin 	    case A_TILDE:
506*4887Schin 		op |= T_NOFLOAT;
507*4887Schin 	    common:
508*4887Schin 		if(!expr(vp,c))
509*4887Schin 			return(0);
510*4887Schin 		stakputc(op);
511*4887Schin 		break;
512*4887Schin 	    default:
513*4887Schin 		vp->nextchr = vp->errchr;
514*4887Schin 		wasop = 1;
515*4887Schin 	}
516*4887Schin 	invalid = wasop;
517*4887Schin 	while(1)
518*4887Schin 	{
519*4887Schin 		assignop.value = 0;
520*4887Schin 		op = gettok(vp);
521*4887Schin 		if(op==A_DIG || op==A_REG || op==A_LIT)
522*4887Schin 		{
523*4887Schin 			if(!wasop)
524*4887Schin 				ERROR(vp,e_synbad);
525*4887Schin 			goto number;
526*4887Schin 		}
527*4887Schin 		if(wasop++ && op!=A_LPAR)
528*4887Schin 			ERROR(vp,e_synbad);
529*4887Schin 		/* check for assignment operation */
530*4887Schin 		if(peekchr(vp)== '=' && !(strval_precedence[op]&NOASSIGN))
531*4887Schin 		{
532*4887Schin 			if((!lvalue.value || precedence > 3))
533*4887Schin 				ERROR(vp,e_notlvalue);
534*4887Schin 			if(precedence==3)
535*4887Schin 				precedence = 2;
536*4887Schin 			assignop = lvalue;
537*4887Schin 			getchr(vp);
538*4887Schin 			c = 3;
539*4887Schin 		}
540*4887Schin 		else
541*4887Schin 		{
542*4887Schin 			c = (strval_precedence[op]&PRECMASK);
543*4887Schin 			if(c==MAXPREC || op==A_POW)
544*4887Schin 				c++;
545*4887Schin 			c *= 2;
546*4887Schin 		}
547*4887Schin 		/* from here on c is the new precedence level */
548*4887Schin 		if(lvalue.value && (op!=A_ASSIGN))
549*4887Schin 		{
550*4887Schin 			if(vp->staksize++>=vp->stakmaxsize)
551*4887Schin 				vp->stakmaxsize = vp->staksize;
552*4887Schin 			stakputc(A_PUSHV);
553*4887Schin 			stakpush(vp,lvalue.value,char*);
554*4887Schin 			if(lvalue.flag<0)
555*4887Schin 				lvalue.flag = 0;
556*4887Schin 			stakpush(vp,lvalue.flag,short);
557*4887Schin 			if(vp->nextchr==0)
558*4887Schin 				ERROR(vp,e_badnum);
559*4887Schin 			if(!(strval_precedence[op]&SEQPOINT))
560*4887Schin 				lvalue.value = 0;
561*4887Schin 			invalid = 0;
562*4887Schin 		}
563*4887Schin 		else if(precedence==A_LVALUE)
564*4887Schin 			ERROR(vp,e_notlvalue);
565*4887Schin 		if(invalid && op>A_ASSIGN)
566*4887Schin 			ERROR(vp,e_synbad);
567*4887Schin 		if(precedence >= c)
568*4887Schin 			goto done;
569*4887Schin 		if(strval_precedence[op]&RASSOC)
570*4887Schin 			c--;
571*4887Schin 		if((c < (2*MAXPREC+1)) && !(strval_precedence[op]&SEQPOINT))
572*4887Schin 		{
573*4887Schin 			wasop = 0;
574*4887Schin 			if(!expr(vp,c))
575*4887Schin 				return(0);
576*4887Schin 		}
577*4887Schin 		switch(op)
578*4887Schin 		{
579*4887Schin 		case A_RPAR:
580*4887Schin 			if(!vp->paren)
581*4887Schin 				ERROR(vp,e_paren);
582*4887Schin 			if(invalid)
583*4887Schin 				ERROR(vp,e_synbad);
584*4887Schin 			goto done;
585*4887Schin 
586*4887Schin 		case A_COMMA:
587*4887Schin 			wasop = 0;
588*4887Schin 			if(vp->infun)
589*4887Schin 				vp->infun++;
590*4887Schin 			else
591*4887Schin 			{
592*4887Schin 				stakputc(A_POP);
593*4887Schin 				vp->staksize--;
594*4887Schin 			}
595*4887Schin 			if(!expr(vp,c))
596*4887Schin 				return(0);
597*4887Schin 			lvalue.value = 0;
598*4887Schin 			break;
599*4887Schin 
600*4887Schin 		case A_LPAR:
601*4887Schin 		{
602*4887Schin 			int	infun = vp->infun;
603*4887Schin 			Sfdouble_t (*fun)(Sfdouble_t,...);
604*4887Schin 			int nargs = lvalue.nargs;
605*4887Schin 			fun = lvalue.fun;
606*4887Schin 			lvalue.fun = 0;
607*4887Schin 			if(fun)
608*4887Schin 			{
609*4887Schin 				if(vp->staksize++>=vp->stakmaxsize)
610*4887Schin 					vp->stakmaxsize = vp->staksize;
611*4887Schin 				vp->infun=1;
612*4887Schin 				stakputc(A_PUSHF);
613*4887Schin 				stakpush(vp,fun,Fun_t);
614*4887Schin 				stakputc(1);
615*4887Schin 			}
616*4887Schin 			else
617*4887Schin 				vp->infun = 0;
618*4887Schin 			if(!invalid)
619*4887Schin 				ERROR(vp,e_synbad);
620*4887Schin 			vp->paren++;
621*4887Schin 			if(!expr(vp,1))
622*4887Schin 				return(0);
623*4887Schin 			vp->paren--;
624*4887Schin 			if(fun)
625*4887Schin 			{
626*4887Schin 				int  x= (nargs>7);
627*4887Schin 				nargs &= 7;
628*4887Schin 				if(vp->infun != nargs)
629*4887Schin 					ERROR(vp,e_argcount);
630*4887Schin 				if(vp->staksize+=nargs>=vp->stakmaxsize)
631*4887Schin 					vp->stakmaxsize = vp->staksize+nargs;
632*4887Schin 				stakputc(A_CALL0+nargs -x);
633*4887Schin 				vp->staksize -= nargs;
634*4887Schin 			}
635*4887Schin 			vp->infun = infun;
636*4887Schin 			if (gettok(vp) != A_RPAR)
637*4887Schin 				ERROR(vp,e_paren);
638*4887Schin 			wasop = 0;
639*4887Schin 			break;
640*4887Schin 		}
641*4887Schin 
642*4887Schin 		case A_PLUSPLUS:
643*4887Schin 		case A_MINUSMINUS:
644*4887Schin 			wasop=0;
645*4887Schin 			op |= T_NOFLOAT;
646*4887Schin 		case A_ASSIGN:
647*4887Schin 			if(!lvalue.value)
648*4887Schin 				ERROR(vp,e_notlvalue);
649*4887Schin 			if(op==A_ASSIGN)
650*4887Schin 			{
651*4887Schin 				stakputc(A_STORE);
652*4887Schin 				stakpush(vp,lvalue.value,char*);
653*4887Schin 				stakpush(vp,lvalue.flag,short);
654*4887Schin 				vp->staksize--;
655*4887Schin 			}
656*4887Schin 			else
657*4887Schin 				stakputc(op);
658*4887Schin 			lvalue.value = 0;
659*4887Schin 			break;
660*4887Schin 
661*4887Schin 		case A_QUEST:
662*4887Schin 		{
663*4887Schin 			int offset1,offset2;
664*4887Schin 			stakputc(A_JMPZ);
665*4887Schin 			offset1 = stakpush(vp,0,short);
666*4887Schin 			stakputc(A_POP);
667*4887Schin 			if(!expr(vp,1))
668*4887Schin 				return(0);
669*4887Schin 			if(gettok(vp)!=A_COLON)
670*4887Schin 				ERROR(vp,e_questcolon);
671*4887Schin 			stakputc(A_JMP);
672*4887Schin 			offset2 = stakpush(vp,0,short);
673*4887Schin 			*((short*)stakptr(offset1)) = staktell();
674*4887Schin 			stakputc(A_POP);
675*4887Schin 			if(!expr(vp,3))
676*4887Schin 				return(0);
677*4887Schin 			*((short*)stakptr(offset2)) = staktell();
678*4887Schin 			lvalue.value = 0;
679*4887Schin 			wasop = 0;
680*4887Schin 			break;
681*4887Schin 		}
682*4887Schin 
683*4887Schin 		case A_COLON:
684*4887Schin 			ERROR(vp,e_badcolon);
685*4887Schin 			break;
686*4887Schin 
687*4887Schin 		case A_QCOLON:
688*4887Schin 		case A_ANDAND:
689*4887Schin 		case A_OROR:
690*4887Schin 		{
691*4887Schin 			int offset;
692*4887Schin 			if(op==A_ANDAND)
693*4887Schin 				op = A_JMPZ;
694*4887Schin 			else
695*4887Schin 				op = A_JMPNZ;
696*4887Schin 			stakputc(op);
697*4887Schin 			offset = stakpush(vp,0,short);
698*4887Schin 			stakputc(A_POP);
699*4887Schin 			if(!expr(vp,c))
700*4887Schin 				return(0);
701*4887Schin 			*((short*)stakptr(offset)) = staktell();
702*4887Schin 			if(op!=A_QCOLON)
703*4887Schin 				stakputc(A_NOTNOT);
704*4887Schin 			lvalue.value = 0;
705*4887Schin 			wasop=0;
706*4887Schin 			break;
707*4887Schin 		}
708*4887Schin 		case A_AND:	case A_OR:	case A_XOR:	case A_LSHIFT:
709*4887Schin 		case A_RSHIFT:	case A_MOD:
710*4887Schin 			op |= T_NOFLOAT;
711*4887Schin 			/* FALL THRU */
712*4887Schin 		case A_PLUS:	case A_MINUS:	case A_TIMES:	case A_DIV:
713*4887Schin 		case A_EQ:	case A_NEQ:	case A_LT:	case A_LE:
714*4887Schin 		case A_GT:	case A_GE:	case A_POW:
715*4887Schin 			stakputc(op|T_BINARY);
716*4887Schin 			vp->staksize--;
717*4887Schin 			break;
718*4887Schin 		case A_NOT: case A_TILDE:
719*4887Schin 		default:
720*4887Schin 			ERROR(vp,e_synbad);
721*4887Schin 		number:
722*4887Schin 			wasop = 0;
723*4887Schin 			if(*vp->nextchr=='L' && vp->nextchr[1]=='\'')
724*4887Schin 			{
725*4887Schin 				vp->nextchr++;
726*4887Schin 				op = A_LIT;
727*4887Schin 			}
728*4887Schin 			pos = vp->nextchr;
729*4887Schin 			lvalue.isfloat = 0;
730*4887Schin 			lvalue.expr = vp->expr;
731*4887Schin 			lvalue.emode = vp->emode;
732*4887Schin 			if(op==A_LIT)
733*4887Schin 			{
734*4887Schin 				/* character constants */
735*4887Schin 				if(pos[1]=='\\' && pos[2]=='\'' && pos[3]!='\'')
736*4887Schin 				{
737*4887Schin 					d = '\\';
738*4887Schin 					vp->nextchr +=2;
739*4887Schin 				}
740*4887Schin 				else
741*4887Schin 					d = chresc(pos+1,(char**)&vp->nextchr);
742*4887Schin 				/* posix allows the trailing ' to be optional */
743*4887Schin 				if(*vp->nextchr=='\'')
744*4887Schin 					vp->nextchr++;
745*4887Schin 			}
746*4887Schin 			else
747*4887Schin 				d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0);
748*4887Schin 			if (vp->nextchr == pos)
749*4887Schin 			{
750*4887Schin 				if(vp->errmsg.value = lvalue.value)
751*4887Schin 					vp->errstr = pos;
752*4887Schin 				ERROR(vp,op==A_LIT?e_charconst:e_synbad);
753*4887Schin 			}
754*4887Schin 			if(op==A_DIG || op==A_LIT)
755*4887Schin 			{
756*4887Schin 				stakputc(A_PUSHN);
757*4887Schin 				if(vp->staksize++>=vp->stakmaxsize)
758*4887Schin 					vp->stakmaxsize = vp->staksize;
759*4887Schin 				stakpush(vp,d,Sfdouble_t);
760*4887Schin 				stakputc(lvalue.isfloat);
761*4887Schin 			}
762*4887Schin 
763*4887Schin 			/* check for function call */
764*4887Schin 			if(lvalue.fun)
765*4887Schin 				continue;
766*4887Schin 			break;
767*4887Schin 		}
768*4887Schin 		invalid = 0;
769*4887Schin 		if(assignop.value)
770*4887Schin 		{
771*4887Schin 			if(vp->staksize++>=vp->stakmaxsize)
772*4887Schin 				vp->stakmaxsize = vp->staksize;
773*4887Schin 			if(assignop.flag<0)
774*4887Schin 				assignop.flag = 0;
775*4887Schin 			stakputc(A_STORE);
776*4887Schin 			stakpush(vp,assignop.value,char*);
777*4887Schin 			stakpush(vp,assignop.flag,short);
778*4887Schin 		}
779*4887Schin 	}
780*4887Schin  done:
781*4887Schin 	vp->nextchr = vp->errchr;
782*4887Schin 	return(1);
783*4887Schin }
784*4887Schin 
785*4887Schin Arith_t *arith_compile(const char *string,char **last,Sfdouble_t(*fun)(const char**,struct lval*,int,Sfdouble_t),int emode)
786*4887Schin {
787*4887Schin 	struct vars cur;
788*4887Schin 	register Arith_t *ep;
789*4887Schin 	int offset;
790*4887Schin 	memset((void*)&cur,0,sizeof(cur));
791*4887Schin 	cur.emode = emode;
792*4887Schin      	cur.expr = cur.nextchr = string;
793*4887Schin 	cur.convert = fun;
794*4887Schin 	cur.emode = emode;
795*4887Schin 	cur.errmsg.value = 0;
796*4887Schin 	cur.errmsg.emode = emode;
797*4887Schin 	stakseek(sizeof(Arith_t));
798*4887Schin 	if(!expr(&cur,0) && cur.errmsg.value)
799*4887Schin         {
800*4887Schin 		if(cur.errstr)
801*4887Schin 			string = cur.errstr;
802*4887Schin 		(*fun)( &string , &cur.errmsg, MESSAGE, 0);
803*4887Schin 		cur.nextchr = cur.errchr;
804*4887Schin 	}
805*4887Schin 	stakputc(0);
806*4887Schin 	offset = staktell();
807*4887Schin 	ep = (Arith_t*)stakfreeze(0);
808*4887Schin 	ep->expr = string;
809*4887Schin 	ep->elen = strlen(string);
810*4887Schin 	ep->code = (unsigned char*)(ep+1);
811*4887Schin 	ep->fun = fun;
812*4887Schin 	ep->emode = emode;
813*4887Schin 	ep->size = offset - sizeof(Arith_t);
814*4887Schin 	ep->staksize = cur.stakmaxsize+1;
815*4887Schin 	if(last)
816*4887Schin 		*last = (char*)(cur.nextchr);
817*4887Schin 	return(ep);
818*4887Schin }
819*4887Schin 
820*4887Schin /*
821*4887Schin  * evaluate an integer arithmetic expression in s
822*4887Schin  *
823*4887Schin  * (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value)
824*4887Schin  *     is a user supplied conversion routine that is called when unknown
825*4887Schin  *     chars are encountered.
826*4887Schin  * *end points to the part to be converted and must be adjusted by convert to
827*4887Schin  * point to the next non-converted character; if typ is MESSAGE then string
828*4887Schin  * points to an error message string
829*4887Schin  *
830*4887Schin  * NOTE: (*convert)() may call strval()
831*4887Schin  */
832*4887Schin 
833*4887Schin Sfdouble_t strval(const char *s,char **end,Sfdouble_t(*conv)(const char**,struct lval*,int,Sfdouble_t),int emode)
834*4887Schin {
835*4887Schin 	Arith_t *ep;
836*4887Schin 	Sfdouble_t d;
837*4887Schin 	char *sp=0;
838*4887Schin 	int offset;
839*4887Schin 	if(offset=staktell())
840*4887Schin 		sp = stakfreeze(1);
841*4887Schin 	ep = arith_compile(s,end,conv,emode);
842*4887Schin 	ep->emode = emode;
843*4887Schin 	d = arith_exec(ep);
844*4887Schin 	stakset(sp?sp:(char*)ep,offset);
845*4887Schin 	return(d);
846*4887Schin }
847*4887Schin 
848*4887Schin #if _mem_name__exception
849*4887Schin #undef	_mem_name_exception
850*4887Schin #define	_mem_name_exception	1
851*4887Schin #undef	exception
852*4887Schin #define	exception		_exception
853*4887Schin #undef	matherr
854*4887Schin #endif
855*4887Schin 
856*4887Schin #if _mem_name_exception
857*4887Schin 
858*4887Schin #undef	error
859*4887Schin 
860*4887Schin #if _BLD_shell && defined(__EXPORT__)
861*4887Schin #define extern			__EXPORT__
862*4887Schin #endif
863*4887Schin 
864*4887Schin #ifndef DOMAIN
865*4887Schin #define DOMAIN			_DOMAIN
866*4887Schin #endif
867*4887Schin #ifndef OVERFLOW
868*4887Schin #define OVERFLOW		_OVERFLOW
869*4887Schin #endif
870*4887Schin #ifndef SING
871*4887Schin #define SING			_SING
872*4887Schin #endif
873*4887Schin 
874*4887Schin     extern int matherr(struct exception *ep)
875*4887Schin     {
876*4887Schin 	const char *message;
877*4887Schin 	switch(ep->type)
878*4887Schin 	{
879*4887Schin #ifdef DOMAIN
880*4887Schin 	    case DOMAIN:
881*4887Schin 		message = ERROR_dictionary(e_domain);
882*4887Schin 		break;
883*4887Schin #endif
884*4887Schin #ifdef OVERFLOW
885*4887Schin 	    case OVERFLOW:
886*4887Schin 		message = ERROR_dictionary(e_overflow);
887*4887Schin 		break;
888*4887Schin #endif
889*4887Schin #ifdef SING
890*4887Schin 	    case SING:
891*4887Schin 		message = ERROR_dictionary(e_singularity);
892*4887Schin 		break;
893*4887Schin #endif
894*4887Schin 	    default:
895*4887Schin 		return(1);
896*4887Schin 	}
897*4887Schin 	level=0;
898*4887Schin 	errormsg(SH_DICT,ERROR_exit(1),message,ep->name);
899*4887Schin 	return(0);
900*4887Schin     }
901*4887Schin 
902*4887Schin #undef	extern
903*4887Schin 
904*4887Schin #endif /* _mem_name_exception */
905