--- ray/src/common/calexpr.c 1993/06/04 15:04:48 2.14 +++ ray/src/common/calexpr.c 2003/08/04 19:20:26 2.27 @@ -1,9 +1,6 @@ -/* Copyright (c) 1992 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: calexpr.c,v 2.27 2003/08/04 19:20:26 greg Exp $"; #endif - /* * Compute data values using expression parser * @@ -16,16 +13,20 @@ static char SCCSid[] = "$SunId$ LBL"; * 1/29/87 Made variables conditional (VARIABLE) * * 5/19/88 Added constant subexpression elimination (RCONST) + * + * 2/19/03 Eliminated conditional compiles in favor of esupport extern. */ -#include +#include "copyright.h" +#include +#include #include - #include - #include +#include +#include "rterror.h" #include "calcomp.h" #define MAXLINE 256 /* maximum line length */ @@ -34,42 +35,28 @@ static char SCCSid[] = "$SunId$ LBL"; #define isdecimal(c) (isdigit(c) || (c) == '.') -extern char *savestr(); -extern char *emalloc(), *ecalloc(); -extern EPNODE *curfunc; -extern double efunc(), evariable(); -static double euminus(), eargument(), enumber(); -#ifdef INCHAN -static double echannel(); -#endif -static double eadd(), esubtr(), emult(), edivi(), epow(); -static double ebotch(); +static double euminus(EPNODE *), eargument(EPNODE *), enumber(EPNODE *); +static double echannel(EPNODE *); +static double eadd(EPNODE *), esubtr(EPNODE *), + emult(EPNODE *), edivi(EPNODE *), + epow(EPNODE *); +static double ebotch(EPNODE *); +unsigned int esupport = /* what to support */ + E_VARIABLE | E_FUNCTION ; + int nextc; /* lookahead character */ -double (*eoper[])() = { /* expression operations */ +double (*eoper[])(EPNODE *) = { /* expression operations */ ebotch, -#ifdef VARIABLE evariable, -#else - ebotch, -#endif enumber, euminus, -#ifdef INCHAN echannel, -#else - ebotch, -#endif -#ifdef FUNCTION efunc, eargument, -#else ebotch, ebotch, -#endif - ebotch, - ebotch, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, emult, @@ -101,9 +88,7 @@ char *expr; EPNODE *ep; initstr(expr, NULL, 0); -#if defined(VARIABLE) && defined(FUNCTION) curfunc = NULL; -#endif ep = getE1(); if (nextc != EOF) syntax("unexpected character"); @@ -125,6 +110,55 @@ char *expr; } +int +epcmp(ep1, ep2) /* compare two expressions for equivalence */ +register EPNODE *ep1, *ep2; +{ + double d; + + if (ep1->type != ep2->type) + return(1); + + switch (ep1->type) { + + case VAR: + return(ep1->v.ln != ep2->v.ln); + + case NUM: + if (ep2->v.num == 0) + return(ep1->v.num != 0); + d = ep1->v.num / ep2->v.num; + return((d > 1.000000000001) | (d < 0.999999999999)); + + case CHAN: + case ARG: + return(ep1->v.chan != ep2->v.chan); + + case '=': + case ':': + return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling)); + + case TICK: + case SYM: /* should never get this one */ + return(0); + + default: + ep1 = ep1->v.kid; + ep2 = ep2->v.kid; + while (ep1 != NULL) { + if (ep2 == NULL) + return(1); + if (epcmp(ep1, ep2)) + return(1); + ep1 = ep1->sibling; + ep2 = ep2->sibling; + } + return(ep2 != NULL); + } +} + + +void epfree(epar) /* free a parse tree */ register EPNODE *epar; { @@ -132,7 +166,6 @@ register EPNODE *epar; switch (epar->type) { -#if defined(VARIABLE) || defined(FUNCTION) case VAR: varfree(epar->v.ln); break; @@ -140,7 +173,6 @@ register EPNODE *epar; case SYM: freestr(epar->v.name); break; -#endif case NUM: case CHAN: @@ -161,14 +193,12 @@ register EPNODE *epar; } /* the following used to be a switch */ -#ifdef FUNCTION static double eargument(ep) EPNODE *ep; { return(argument(ep->v.chan)); } -#endif static double enumber(ep) @@ -186,14 +216,12 @@ EPNODE *ep; return(-evalue(ep1)); } -#ifdef INCHAN static double echannel(ep) EPNODE *ep; { return(chanvalue(ep->v.chan)); } -#endif static double eadd(ep) @@ -253,7 +281,7 @@ EPNODE *ep; if (!finite(d)) errno = EDOM; #endif - if (errno) { + if (errno == EDOM || errno == ERANGE) { wputs("Illegal power\n"); return(0.0); } @@ -267,6 +295,7 @@ EPNODE *ep; { eputs("Bad expression!\n"); quit(1); + return 0.0; /* pro forma return */ } @@ -297,6 +326,7 @@ register EPNODE *ep; } +void initfile(fp, fn, ln) /* prepare input file */ FILE *fp; char *fn; @@ -314,6 +344,7 @@ int ln; } +void initstr(s, fn, ln) /* prepare input string */ char *s; char *fn; @@ -328,6 +359,7 @@ int ln; } +void getscanpos(fnp, lnp, spp, fpp) /* return current scan position */ char **fnp; int *lnp; @@ -399,6 +431,7 @@ long l; } +void syntax(err) /* report syntax error and quit */ char *err; { @@ -424,6 +457,7 @@ char *err; } +void addekid(ep, ekid) /* add a child to ep */ register EPNODE *ep; EPNODE *ekid; @@ -439,15 +473,14 @@ EPNODE *ekid; } -#if defined(VARIABLE) || defined(FUNCTION) char * getname() /* scan an identifier */ { - static char str[MAXWORD+1]; + static char str[RMAXWORD+1]; register int i, lnext; lnext = nextc; - for (i = 0; i < MAXWORD && isid(lnext); i++, lnext = scan()) + for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan()) str[i] = lnext; str[i] = '\0'; while (isid(lnext)) /* skip rest of name */ @@ -455,7 +488,6 @@ getname() /* scan an identifier */ return(str); } -#endif int @@ -477,30 +509,34 @@ double getnum() /* scan a positive float */ { register int i, lnext; - char str[MAXWORD+1]; + char str[RMAXWORD+1]; i = 0; lnext = nextc; - while (isdigit(lnext) && i < MAXWORD) { + while (isdigit(lnext) && i < RMAXWORD) { str[i++] = lnext; lnext = scan(); } - if (lnext == '.' && i < MAXWORD) { + if (lnext == '.' && i < RMAXWORD) { str[i++] = lnext; lnext = scan(); - while (isdigit(lnext) && i < MAXWORD) { + if (i == 1 && !isdigit(lnext)) + syntax("badly formed number"); + while (isdigit(lnext) && i < RMAXWORD) { str[i++] = lnext; lnext = scan(); } } - if ((lnext == 'e' || lnext == 'E') && i < MAXWORD) { + if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) { str[i++] = lnext; lnext = scan(); - if ((lnext == '-' || lnext == '+') && i < MAXWORD) { + if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) { str[i++] = lnext; lnext = scan(); } - while (isdigit(lnext) && i < MAXWORD) { + if (!isdigit(lnext)) + syntax("missing exponent"); + while (isdigit(lnext) && i < RMAXWORD) { str[i++] = lnext; lnext = scan(); } @@ -524,10 +560,9 @@ getE1() /* E1 -> E1 ADDOP E2 */ scan(); addekid(ep2, ep1); addekid(ep2, getE2()); -#ifdef RCONST - if (ep1->type == NUM && ep1->sibling->type == NUM) + if (esupport&E_RCONST && + ep1->type == NUM && ep1->sibling->type == NUM) ep2 = rconst(ep2); -#endif ep1 = ep2; } return(ep1); @@ -547,10 +582,9 @@ getE2() /* E2 -> E2 MULOP E3 */ scan(); addekid(ep2, ep1); addekid(ep2, getE3()); -#ifdef RCONST - if (ep1->type == NUM && ep1->sibling->type == NUM) + if (esupport&E_RCONST && + ep1->type == NUM && ep1->sibling->type == NUM) ep2 = rconst(ep2); -#endif ep1 = ep2; } return(ep1); @@ -570,10 +604,9 @@ getE3() /* E3 -> E4 ^ E3 */ scan(); addekid(ep2, ep1); addekid(ep2, getE3()); -#ifdef RCONST - if (ep1->type == NUM && ep1->sibling->type == NUM) + if (esupport&E_RCONST && + ep1->type == NUM && ep1->sibling->type == NUM) ep2 = rconst(ep2); -#endif return(ep2); } return(ep1); @@ -616,88 +649,76 @@ getE5() /* E5 -> (E1) */ /* FUNC(E1,..) */ /* ARG */ { - int i; - char *nam; - register EPNODE *ep1, *ep2; + int i; + char *nam; + register EPNODE *ep1, *ep2; - if (nextc == '(') { - scan(); - ep1 = getE1(); - if (nextc != ')') - syntax("')' expected"); - scan(); - return(ep1); - } + if (nextc == '(') { + scan(); + ep1 = getE1(); + if (nextc != ')') + syntax("')' expected"); + scan(); + return(ep1); + } -#ifdef INCHAN - if (nextc == '$') { - scan(); - ep1 = newnode(); - ep1->type = CHAN; - ep1->v.chan = getinum(); - return(ep1); - } -#endif + if (esupport&E_INCHAN && nextc == '$') { + scan(); + ep1 = newnode(); + ep1->type = CHAN; + ep1->v.chan = getinum(); + return(ep1); + } -#if defined(VARIABLE) || defined(FUNCTION) - if (isalpha(nextc) || nextc == CNTXMARK) { - nam = getname(); -#if defined(VARIABLE) && defined(FUNCTION) - ep1 = NULL; - if (curfunc != NULL) - for (i = 1, ep2 = curfunc->v.kid->sibling; - ep2 != NULL; i++, ep2 = ep2->sibling) - if (!strcmp(ep2->v.name, nam)) { - ep1 = newnode(); - ep1->type = ARG; - ep1->v.chan = i; - break; + if (esupport&(E_VARIABLE|E_FUNCTION) && + (isalpha(nextc) || nextc == CNTXMARK)) { + nam = getname(); + ep1 = NULL; + if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION) + && curfunc != NULL) + for (i = 1, ep2 = curfunc->v.kid->sibling; + ep2 != NULL; i++, ep2 = ep2->sibling) + if (!strcmp(ep2->v.name, nam)) { + ep1 = newnode(); + ep1->type = ARG; + ep1->v.chan = i; + break; + } + if (ep1 == NULL) { + ep1 = newnode(); + ep1->type = VAR; + ep1->v.ln = varinsert(nam); } - if (ep1 == NULL) -#endif - { - ep1 = newnode(); - ep1->type = VAR; - ep1->v.ln = varinsert(nam); + if (esupport&E_FUNCTION && nextc == '(') { + ep2 = newnode(); + ep2->type = FUNC; + addekid(ep2, ep1); + ep1 = ep2; + do { + scan(); + addekid(ep1, getE1()); + } while (nextc == ','); + if (nextc != ')') + syntax("')' expected"); + scan(); + } else if (!(esupport&E_VARIABLE)) + syntax("'(' expected"); + if (esupport&E_RCONST && isconstvar(ep1)) + ep1 = rconst(ep1); + return(ep1); } -#ifdef FUNCTION - if (nextc == '(') { - ep2 = newnode(); - ep2->type = FUNC; - addekid(ep2, ep1); - ep1 = ep2; - do { - scan(); - addekid(ep1, getE1()); - } while (nextc == ','); - if (nextc != ')') - syntax("')' expected"); - scan(); - } -#ifndef VARIABLE - else - syntax("'(' expected"); -#endif -#endif -#ifdef RCONST - if (isconstvar(ep1)) - ep1 = rconst(ep1); -#endif - return(ep1); - } -#endif - if (isdecimal(nextc)) { - ep1 = newnode(); - ep1->type = NUM; - ep1->v.num = getnum(); - return(ep1); - } - syntax("unexpected character"); + if (isdecimal(nextc)) { + ep1 = newnode(); + ep1->type = NUM; + ep1->v.num = getnum(); + return(ep1); + } + syntax("unexpected character"); + return NULL; /* pro forma return */ } -#ifdef RCONST EPNODE * rconst(epar) /* reduce a constant expression */ register EPNODE *epar; @@ -708,7 +729,7 @@ register EPNODE *epar; ep->type = NUM; errno = 0; ep->v.num = evalue(epar); - if (errno) + if (errno == EDOM || errno == ERANGE) syntax("bad constant expression"); epfree(epar); @@ -716,14 +737,13 @@ register EPNODE *epar; } +int isconstvar(ep) /* is ep linked to a constant expression? */ register EPNODE *ep; { -#ifdef VARIABLE register EPNODE *ep1; -#ifdef FUNCTION - if (ep->type == FUNC) { + if (esupport&E_FUNCTION && ep->type == FUNC) { if (!isconstfun(ep->v.kid)) return(0); for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling) @@ -731,24 +751,18 @@ register EPNODE *ep; return(0); return(1); } -#endif if (ep->type != VAR) return(0); ep1 = ep->v.ln->def; if (ep1 == NULL || ep1->type != ':') return(0); -#ifdef FUNCTION - if (ep1->v.kid->type != SYM) + if (esupport&E_FUNCTION && ep1->v.kid->type != SYM) return(0); -#endif return(1); -#else - return(ep->type == FUNC); -#endif } -#if defined(FUNCTION) && defined(VARIABLE) +int isconstfun(ep) /* is ep linked to a constant function? */ register EPNODE *ep; { @@ -757,11 +771,13 @@ register EPNODE *ep; if (ep->type != VAR) return(0); - if ((dp = ep->v.ln->def) != NULL && dp->v.kid->type == FUNC) - return(dp->type == ':'); + if ((dp = ep->v.ln->def) != NULL) { + if (dp->v.kid->type == FUNC) + return(dp->type == ':'); + else + return(0); /* don't identify masked library functions */ + } if ((lp = ep->v.ln->lib) != NULL) return(lp->atyp == ':'); return(0); } -#endif -#endif