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