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