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