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