--- 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);