--- ray/src/common/calexpr.c 2003/02/22 02:07:21 2.18 +++ ray/src/common/calexpr.c 2003/11/14 17:22:06 2.28 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: calexpr.c,v 2.18 2003/02/22 02:07:21 greg Exp $"; +static const char RCSid[] = "$Id: calexpr.c,v 2.28 2003/11/14 17:22:06 schorsch Exp $"; #endif /* * Compute data values using expression parser @@ -17,73 +17,16 @@ static const char RCSid[] = "$Id: calexpr.c,v 2.18 200 * 2/19/03 Eliminated conditional compiles in favor of esupport extern. */ -/* ==================================================================== - * The Radiance Software License, Version 1.0 - * - * Copyright (c) 1990 - 2002 The Regents of the University of California, - * through Lawrence Berkeley National Laboratory. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes Radiance software - * (http://radsite.lbl.gov/) - * developed by the Lawrence Berkeley National Laboratory - * (http://www.lbl.gov/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Radiance," "Lawrence Berkeley National Laboratory" - * and "The Regents of the University of California" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact radiance@radsite.lbl.gov. - * - * 5. Products derived from this software may not be called "Radiance", - * nor may "Radiance" appear in their name, without prior written - * permission of Lawrence Berkeley National Laboratory. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of Lawrence Berkeley National Laboratory. For more - * information on Lawrence Berkeley National Laboratory, please see - * . - */ +#include "copyright.h" #include - +#include #include - #include - #include - #include +#include "rterror.h" #include "calcomp.h" #define MAXLINE 256 /* maximum line length */ @@ -92,17 +35,19 @@ static const char RCSid[] = "$Id: calexpr.c,v 2.18 200 #define isdecimal(c) (isdigit(c) || (c) == '.') -static double euminus(), eargument(), enumber(); -static double echannel(); -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 | E_REDEFW; + E_VARIABLE | E_FUNCTION ; int nextc; /* lookahead character */ -double (*eoper[])() = { /* expression operations */ +double (*eoper[])(EPNODE *) = { /* expression operations */ ebotch, evariable, enumber, @@ -137,8 +82,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; @@ -152,8 +98,9 @@ char *expr; double -eval(expr) /* evaluate an expression string */ -char *expr; +eval( /* evaluate an expression string */ + char *expr +) { register EPNODE *ep; double rval; @@ -166,8 +113,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; @@ -183,7 +132,7 @@ register EPNODE *ep1, *ep2; if (ep2->v.num == 0) return(ep1->v.num != 0); d = ep1->v.num / ep2->v.num; - return(d > 1.000000000001 | d < 0.999999999999); + return((d > 1.000000000001) | (d < 0.999999999999)); case CHAN: case ARG: @@ -214,8 +163,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; @@ -249,22 +199,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; @@ -272,15 +225,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; @@ -288,8 +243,9 @@ EPNODE *ep; } static double -esubtr(ep) -EPNODE *ep; +esubtr( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; @@ -297,8 +253,9 @@ EPNODE *ep; } static double -emult(ep) -EPNODE *ep; +emult( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; @@ -306,8 +263,9 @@ EPNODE *ep; } static double -edivi(ep) -EPNODE *ep; +edivi( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; double d; @@ -322,8 +280,9 @@ EPNODE *ep; } static double -epow(ep) -EPNODE *ep; +epow( + EPNODE *ep +) { register EPNODE *ep1 = ep->v.kid; double d; @@ -336,7 +295,7 @@ EPNODE *ep; if (!finite(d)) errno = EDOM; #endif - if (errno) { + if (errno == EDOM || errno == ERANGE) { wputs("Illegal power\n"); return(0.0); } @@ -345,18 +304,21 @@ EPNODE *ep; } static double -ebotch(ep) -EPNODE *ep; +ebotch( + EPNODE *ep +) { eputs("Bad expression!\n"); quit(1); + return 0.0; /* pro forma return */ } 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) @@ -368,8 +330,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; @@ -381,10 +344,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]; @@ -399,10 +363,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; @@ -414,11 +379,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; @@ -428,7 +394,7 @@ FILE **fpp; int -scan() /* scan next character, return literal next */ +scan(void) /* scan next character, return literal next */ { register int lnext = 0; @@ -460,8 +426,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; @@ -486,8 +453,9 @@ long l; void -syntax(err) /* report syntax error and quit */ -char *err; +syntax( /* report syntax error and quit */ + char *err +) { register int i; @@ -512,9 +480,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; @@ -528,13 +497,13 @@ EPNODE *ekid; char * -getname() /* scan an identifier */ +getname(void) /* 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 */ @@ -545,7 +514,7 @@ getname() /* scan an identifier */ int -getinum() /* scan a positive integer */ +getinum(void) /* scan a positive integer */ { register int n, lnext; @@ -560,37 +529,37 @@ getinum() /* scan a positive integer */ double -getnum() /* scan a positive float */ +getnum(void) /* 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(); if (i == 1 && !isdigit(lnext)) syntax("badly formed number"); - while (isdigit(lnext) && i < MAXWORD) { + 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(); } if (!isdigit(lnext)) syntax("missing exponent"); - while (isdigit(lnext) && i < MAXWORD) { + while (isdigit(lnext) && i < RMAXWORD) { str[i++] = lnext; lnext = scan(); } @@ -602,7 +571,7 @@ getnum() /* scan a positive float */ EPNODE * -getE1() /* E1 -> E1 ADDOP E2 */ +getE1(void) /* E1 -> E1 ADDOP E2 */ /* E2 */ { register EPNODE *ep1, *ep2; @@ -624,7 +593,7 @@ getE1() /* E1 -> E1 ADDOP E2 */ EPNODE * -getE2() /* E2 -> E2 MULOP E3 */ +getE2(void) /* E2 -> E2 MULOP E3 */ /* E3 */ { register EPNODE *ep1, *ep2; @@ -646,7 +615,7 @@ getE2() /* E2 -> E2 MULOP E3 */ EPNODE * -getE3() /* E3 -> E4 ^ E3 */ +getE3(void) /* E3 -> E4 ^ E3 */ /* E4 */ { register EPNODE *ep1, *ep2; @@ -668,7 +637,7 @@ getE3() /* E3 -> E4 ^ E3 */ EPNODE * -getE4() /* E4 -> ADDOP E5 */ +getE4(void) /* E4 -> ADDOP E5 */ /* E5 */ { register EPNODE *ep1, *ep2; @@ -696,85 +665,87 @@ getE4() /* E4 -> ADDOP E5 */ EPNODE * -getE5() /* E5 -> (E1) */ +getE5(void) /* E5 -> (E1) */ /* VAR */ /* NUM */ /* $N */ /* 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); + } - if (esupport&E_INCHAN && nextc == '$') { - scan(); - ep1 = newnode(); - ep1->type = CHAN; - ep1->v.chan = getinum(); - return(ep1); - } + if (esupport&E_INCHAN && nextc == '$') { + scan(); + ep1 = newnode(); + ep1->type = CHAN; + ep1->v.chan = getinum(); + return(ep1); + } - 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 (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) { - 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); } - 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); - } - 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 */ } EPNODE * -rconst(epar) /* reduce a constant expression */ -register EPNODE *epar; +rconst( /* reduce a constant expression */ + register EPNODE *epar +) { register EPNODE *ep; @@ -782,7 +753,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); @@ -791,8 +762,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; @@ -816,19 +788,21 @@ 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; if (ep->type != VAR) return(0); - if ((dp = ep->v.ln->def) != NULL) + 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);