--- ray/src/common/calexpr.c 2005/05/17 17:51:51 2.30 +++ ray/src/common/calexpr.c 2010/07/25 05:50:27 2.34 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: calexpr.c,v 2.30 2005/05/17 17:51:51 greg Exp $"; +static const char RCSid[] = "$Id: calexpr.c,v 2.34 2010/07/25 05:50:27 greg Exp $"; #endif /* * Compute data values using expression parser @@ -145,7 +145,7 @@ epcmp( /* compare two expressions for equivalence */ case ':': return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling)); - case TICK: + case CLKT: case SYM: /* should never get this one */ return(0); @@ -185,7 +185,7 @@ epfree( /* free a parse tree */ case NUM: case CHAN: case ARG: - case TICK: + case CLKT: break; default: @@ -294,9 +294,12 @@ epow( lasterrno = errno; errno = 0; d = pow(evalue(ep1), evalue(ep1->sibling)); -#ifdef IEEE - if (!finite(d)) - errno = EDOM; +#ifdef isnan + if (errno == 0) + if (isnan(d)) + errno = EDOM; + else if (isinf(d)) + errno = ERANGE; #endif if (errno == EDOM || errno == ERANGE) { wputs("Illegal power\n"); @@ -578,7 +581,7 @@ getnum(void) /* scan a positive float */ EPNODE * -getE1(void) /* E1 -> E1 ADDOP E2 */ +getE1(void) /* E1 -> E1 ADDOP E2 */ /* E2 */ { register EPNODE *ep1, *ep2; @@ -600,7 +603,7 @@ getE1(void) /* E1 -> E1 ADDOP E2 */ EPNODE * -getE2(void) /* E2 -> E2 MULOP E3 */ +getE2(void) /* E2 -> E2 MULOP E3 */ /* E3 */ { register EPNODE *ep1, *ep2; @@ -612,9 +615,23 @@ getE2(void) /* E2 -> E2 MULOP E3 */ scan(); addekid(ep2, ep1); addekid(ep2, getE3()); - if (esupport&E_RCONST && - ep1->type == NUM && ep1->sibling->type == NUM) - ep2 = rconst(ep2); + if (esupport&E_RCONST) { + EPNODE *ep3 = ep1->sibling; + if (ep1->type == NUM && ep3->type == NUM) { + ep2 = rconst(ep2); + } else if (ep3->type == NUM && ep3->v.num == 0) { + if (ep2->type == '/') + syntax("divide by zero constant"); + ep1->sibling = NULL; /* (E2 * 0) */ + epfree(ep2); + ep2 = ep3; + } else if (ep1->type == NUM && ep1->v.num == 0) { + epfree(ep3); /* (0 * E3) or (0 / E3) */ + ep1->sibling = NULL; + efree((char *)ep2); + ep2 = ep1; + } + } ep1 = ep2; } return(ep1); @@ -622,29 +639,42 @@ getE2(void) /* E2 -> E2 MULOP E3 */ EPNODE * -getE3(void) /* E3 -> E4 ^ E3 */ +getE3(void) /* E3 -> E4 ^ E3 */ /* E4 */ { - register EPNODE *ep1, *ep2; + register EPNODE *ep1, *ep2; - ep1 = getE4(); - if (nextc == '^') { + ep1 = getE4(); + if (nextc != '^') + return(ep1); ep2 = newnode(); ep2->type = nextc; scan(); addekid(ep2, ep1); addekid(ep2, getE3()); - if (esupport&E_RCONST && - ep1->type == NUM && ep1->sibling->type == NUM) - ep2 = rconst(ep2); + if (esupport&E_RCONST) { + EPNODE *ep3 = ep1->sibling; + if (ep1->type == NUM && ep3->type == NUM) { + ep2 = rconst(ep2); + } else if (ep1->type == NUM && ep1->v.num == 0) { + epfree(ep3); /* (0 ^ E3) */ + ep1->sibling = NULL; + efree((char *)ep2); + ep2 = ep1; + } else if ((ep3->type == NUM && ep3->v.num == 0) || + (ep1->type == NUM && ep1->v.num == 1)) { + epfree(ep2); /* (E4 ^ 0) or (1 ^ E3) */ + ep2 = newnode(); + ep2->type = NUM; + ep2->v.num = 1; + } + } return(ep2); - } - return(ep1); } EPNODE * -getE4(void) /* E4 -> ADDOP E5 */ +getE4(void) /* E4 -> ADDOP E5 */ /* E5 */ { register EPNODE *ep1, *ep2; @@ -657,8 +687,9 @@ getE4(void) /* E4 -> ADDOP E5 */ return(ep2); } if (ep2->type == UMINUS) { /* don't generate -(-E5) */ + ep1 = ep2->v.kid; efree((char *)ep2); - return(ep2->v.kid); + return(ep1); } ep1 = newnode(); ep1->type = UMINUS;