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 */ 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 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 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 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 */ 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 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 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 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 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