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