--- ray/src/common/calexpr.c 2003/08/04 19:20:26 2.27 +++ 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.27 2003/08/04 19:20:26 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 @@ -26,6 +26,8 @@ static const char RCSid[] = "$Id: calexpr.c,v 2.27 200 #include #include +#include "rtmisc.h" +#include "rtio.h" #include "rterror.h" #include "calcomp.h" @@ -45,6 +47,7 @@ static double ebotch(EPNODE *); unsigned int esupport = /* what to support */ E_VARIABLE | E_FUNCTION ; +int eofc = 0; /* optional end-of-file character */ int nextc; /* lookahead character */ double (*eoper[])(EPNODE *) = { /* expression operations */ @@ -82,8 +85,9 @@ static int linepos; /* position in buffer */ EPNODE * -eparse(expr) /* parse an expression string */ -char *expr; +eparse( /* parse an expression string */ + char *expr +) { EPNODE *ep; @@ -97,8 +101,9 @@ char *expr; double -eval(expr) /* evaluate an expression string */ -char *expr; +eval( /* evaluate an expression string */ + char *expr +) { register EPNODE *ep; double rval; @@ -111,8 +116,10 @@ char *expr; int -epcmp(ep1, ep2) /* compare two expressions for equivalence */ -register EPNODE *ep1, *ep2; +epcmp( /* compare two expressions for equivalence */ + register EPNODE *ep1, + register EPNODE *ep2 +) { double d; @@ -138,7 +145,7 @@ register EPNODE *ep1, *ep2; case ':': return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling)); - case TICK: + case CLKT: case SYM: /* should never get this one */ return(0); @@ -159,8 +166,9 @@ register EPNODE *ep1, *ep2; void -epfree(epar) /* free a parse tree */ -register EPNODE *epar; +epfree( /* free a parse tree */ + register EPNODE *epar +) { register EPNODE *ep; @@ -177,7 +185,7 @@ register EPNODE *epar; case NUM: case CHAN: case ARG: - case TICK: + case CLKT: break; default: @@ -194,22 +202,25 @@ register EPNODE *epar; /* the following used to be a switch */ static double -eargument(ep) -EPNODE *ep; +eargument( + EPNODE *ep +) { return(argument(ep->v.chan)); } static double -enumber(ep) -EPNODE *ep; +enumber( + EPNODE *ep +) { return(ep->v.num); } static double -euminus(ep) -EPNODE *ep; +euminus( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; @@ -217,15 +228,17 @@ EPNODE *ep; } static double -echannel(ep) -EPNODE *ep; +echannel( + EPNODE *ep +) { return(chanvalue(ep->v.chan)); } static double -eadd(ep) -EPNODE *ep; +eadd( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; @@ -233,8 +246,9 @@ EPNODE *ep; } static double -esubtr(ep) -EPNODE *ep; +esubtr( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; @@ -242,8 +256,9 @@ EPNODE *ep; } static double -emult(ep) -EPNODE *ep; +emult( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; @@ -251,8 +266,9 @@ EPNODE *ep; } static double -edivi(ep) -EPNODE *ep; +edivi( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; double d; @@ -267,8 +283,9 @@ EPNODE *ep; } static double -epow(ep) -EPNODE *ep; +epow( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; double d; @@ -277,9 +294,12 @@ EPNODE *ep; 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"); @@ -290,8 +310,9 @@ EPNODE *ep; } static double -ebotch(ep) -EPNODE *ep; +ebotch( + EPNODE *ep +) { eputs("Bad expression!\n"); quit(1); @@ -300,9 +321,10 @@ EPNODE *ep; EPNODE * -ekid(ep, n) /* return pointer to a node's nth kid */ -register EPNODE *ep; -register int n; +ekid( /* return pointer to a node's nth kid */ + register EPNODE *ep, + register int n +) { for (ep = ep->v.kid; ep != NULL; ep = ep->sibling) @@ -314,8 +336,9 @@ register int n; int -nekids(ep) /* return # of kids for node ep */ -register EPNODE *ep; +nekids( /* return # of kids for node ep */ + register EPNODE *ep +) { register int n = 0; @@ -327,10 +350,11 @@ register EPNODE *ep; void -initfile(fp, fn, ln) /* prepare input file */ -FILE *fp; -char *fn; -int ln; +initfile( /* prepare input file */ + FILE *fp, + char *fn, + int ln +) { static char inpbuf[MAXLINE]; @@ -345,10 +369,11 @@ int ln; void -initstr(s, fn, ln) /* prepare input string */ -char *s; -char *fn; -int ln; +initstr( /* prepare input string */ + char *s, + char *fn, + int ln +) { infp = NULL; infile = fn; @@ -360,11 +385,12 @@ int ln; void -getscanpos(fnp, lnp, spp, fpp) /* return current scan position */ -char **fnp; -int *lnp; -char **spp; -FILE **fpp; +getscanpos( /* return current scan position */ + char **fnp, + int *lnp, + char **spp, + FILE **fpp +) { if (fnp != NULL) *fnp = infile; if (lnp != NULL) *lnp = lineno; @@ -374,7 +400,7 @@ FILE **fpp; int -scan() /* scan next character, return literal next */ +scan(void) /* scan next character, return literal next */ { register int lnext = 0; @@ -391,6 +417,10 @@ scan() /* scan next character, return literal next nextc = linbuf[linepos++]; if (!lnext) lnext = nextc; + if (nextc == eofc) { + nextc = EOF; + break; + } if (nextc == '{') { scan(); while (nextc != '}') @@ -406,8 +436,9 @@ scan() /* scan next character, return literal next char * -long2ascii(l) /* convert long to ascii */ -long l; +long2ascii( /* convert long to ascii */ + long l +) { static char buf[16]; register char *cp; @@ -432,8 +463,9 @@ long l; void -syntax(err) /* report syntax error and quit */ -char *err; +syntax( /* report syntax error and quit */ + char *err +) { register int i; @@ -458,9 +490,10 @@ char *err; void -addekid(ep, ekid) /* add a child to ep */ -register EPNODE *ep; -EPNODE *ekid; +addekid( /* add a child to ep */ + register EPNODE *ep, + EPNODE *ekid +) { if (ep->v.kid == NULL) ep->v.kid = ekid; @@ -474,7 +507,7 @@ EPNODE *ekid; char * -getname() /* scan an identifier */ +getname(void) /* scan an identifier */ { static char str[RMAXWORD+1]; register int i, lnext; @@ -491,7 +524,7 @@ getname() /* scan an identifier */ int -getinum() /* scan a positive integer */ +getinum(void) /* scan a positive integer */ { register int n, lnext; @@ -506,7 +539,7 @@ getinum() /* scan a positive integer */ double -getnum() /* scan a positive float */ +getnum(void) /* scan a positive float */ { register int i, lnext; char str[RMAXWORD+1]; @@ -548,7 +581,7 @@ getnum() /* scan a positive float */ EPNODE * -getE1() /* E1 -> E1 ADDOP E2 */ +getE1(void) /* E1 -> E1 ADDOP E2 */ /* E2 */ { register EPNODE *ep1, *ep2; @@ -570,7 +603,7 @@ getE1() /* E1 -> E1 ADDOP E2 */ EPNODE * -getE2() /* E2 -> E2 MULOP E3 */ +getE2(void) /* E2 -> E2 MULOP E3 */ /* E3 */ { register EPNODE *ep1, *ep2; @@ -582,9 +615,23 @@ getE2() /* 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); @@ -592,29 +639,42 @@ getE2() /* E2 -> E2 MULOP E3 */ EPNODE * -getE3() /* 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() /* E4 -> ADDOP E5 */ +getE4(void) /* E4 -> ADDOP E5 */ /* E5 */ { register EPNODE *ep1, *ep2; @@ -627,8 +687,9 @@ getE4() /* 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; @@ -642,7 +703,7 @@ getE4() /* E4 -> ADDOP E5 */ EPNODE * -getE5() /* E5 -> (E1) */ +getE5(void) /* E5 -> (E1) */ /* VAR */ /* NUM */ /* $N */ @@ -720,8 +781,9 @@ getE5() /* E5 -> (E1) */ EPNODE * -rconst(epar) /* reduce a constant expression */ -register EPNODE *epar; +rconst( /* reduce a constant expression */ + register EPNODE *epar +) { register EPNODE *ep; @@ -738,8 +800,9 @@ register EPNODE *epar; int -isconstvar(ep) /* is ep linked to a constant expression? */ -register EPNODE *ep; +isconstvar( /* is ep linked to a constant expression? */ + register EPNODE *ep +) { register EPNODE *ep1; @@ -763,8 +826,9 @@ register EPNODE *ep; int -isconstfun(ep) /* is ep linked to a constant function? */ -register EPNODE *ep; +isconstfun( /* is ep linked to a constant function? */ + register EPNODE *ep +) { register EPNODE *dp; register LIBR *lp;