ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/calexpr.c
(Generate patch)

Comparing ray/src/common/calexpr.c (file contents):
Revision 2.6 by greg, Mon Sep 21 12:01:54 1992 UTC vs.
Revision 2.22 by schorsch, Sat Jun 7 12:50:20 2003 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1992 Regents of the University of California */
2
1   #ifndef lint
2 < static char SCCSid[] = "$SunId$ LBL";
2 > static const char       RCSid[] = "$Id$";
3   #endif
6
4   /*
5   *  Compute data values using expression parser
6   *
# Line 16 | Line 13 | static char SCCSid[] = "$SunId$ LBL";
13   *  1/29/87  Made variables conditional (VARIABLE)
14   *
15   *  5/19/88  Added constant subexpression elimination (RCONST)
16 + *
17 + *  2/19/03     Eliminated conditional compiles in favor of esupport extern.
18   */
19  
20 < #include  <stdio.h>
20 > #include "copyright.h"
21  
22 + #include  <stdio.h>
23 + #include  <string.h>
24   #include  <ctype.h>
24
25   #include  <errno.h>
26 + #include  <math.h>
27 + #include  <stdlib.h>
28  
29   #include  "calcomp.h"
30  
# Line 32 | Line 34 | static char SCCSid[] = "$SunId$ LBL";
34  
35   #define  isdecimal(c)   (isdigit(c) || (c) == '.')
36  
37 < #ifndef atof
38 < extern double  atof();
37 < #endif
38 < extern double  pow();
39 < extern char  *fgets(), *savestr();
40 < extern char  *emalloc(), *ecalloc();
41 < extern EPNODE  *curfunc;
42 < extern double  efunc(), evariable();
43 < static double  euminus(), echannel(), eargument(), enumber();
37 > static double  euminus(), eargument(), enumber();
38 > static double  echannel();
39   static double  eadd(), esubtr(), emult(), edivi(), epow();
40   static double  ebotch();
41  
42 + unsigned int  esupport =                /* what to support */
43 +                E_VARIABLE | E_FUNCTION ;
44 +
45   int  nextc;                             /* lookahead character */
46  
47   double  (*eoper[])() = {                /* expression operations */
48          ebotch,
51 #ifdef  VARIABLE
49          evariable,
53 #else
54        ebotch,
55 #endif
50          enumber,
51          euminus,
58 #ifdef  INCHAN
52          echannel,
60 #else
61        ebotch,
62 #endif
63 #ifdef  FUNCTION
53          efunc,
54          eargument,
66 #else
55          ebotch,
56          ebotch,
69 #endif
70        ebotch,
71        ebotch,
57          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
58          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
59          emult,
# Line 100 | Line 85 | char  *expr;
85      EPNODE  *ep;
86  
87      initstr(expr, NULL, 0);
103 #if  defined(VARIABLE) && defined(FUNCTION)
88      curfunc = NULL;
105 #endif
89      ep = getE1();
90      if (nextc != EOF)
91          syntax("unexpected character");
# Line 124 | Line 107 | char  *expr;
107   }
108  
109  
110 + int
111 + epcmp(ep1, ep2)                 /* compare two expressions for equivalence */
112 + register EPNODE  *ep1, *ep2;
113 + {
114 +        double  d;
115 +
116 +        if (ep1->type != ep2->type)
117 +                return(1);
118 +
119 +        switch (ep1->type) {
120 +
121 +        case VAR:
122 +                return(ep1->v.ln != ep2->v.ln);
123 +
124 +        case NUM:
125 +                if (ep2->v.num == 0)
126 +                        return(ep1->v.num != 0);
127 +                d = ep1->v.num / ep2->v.num;
128 +                return(d > 1.000000000001 | d < 0.999999999999);
129 +
130 +        case CHAN:
131 +        case ARG:
132 +                return(ep1->v.chan != ep2->v.chan);
133 +
134 +        case '=':
135 +        case ':':
136 +                return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling));
137 +
138 +        case TICK:
139 +        case SYM:                       /* should never get this one */
140 +                return(0);
141 +
142 +        default:
143 +                ep1 = ep1->v.kid;
144 +                ep2 = ep2->v.kid;
145 +                while (ep1 != NULL) {
146 +                        if (ep2 == NULL)
147 +                                return(1);
148 +                        if (epcmp(ep1, ep2))
149 +                                return(1);
150 +                        ep1 = ep1->sibling;
151 +                        ep2 = ep2->sibling;
152 +                }
153 +                return(ep2 != NULL);
154 +        }
155 + }
156 +
157 +
158 + void
159   epfree(epar)                    /* free a parse tree */
160   register EPNODE  *epar;
161   {
# Line 131 | Line 163 | register EPNODE         *epar;
163  
164      switch (epar->type) {
165  
134 #if  defined(VARIABLE) || defined(FUNCTION)
166          case VAR:
167              varfree(epar->v.ln);
168              break;
# Line 139 | Line 170 | register EPNODE         *epar;
170          case SYM:
171              freestr(epar->v.name);
172              break;
142 #endif
173  
174          case NUM:
175          case CHAN:
# Line 148 | Line 178 | register EPNODE         *epar;
178              break;
179  
180          default:
181 <            for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
181 >            while ((ep = epar->v.kid) != NULL) {
182 >                epar->v.kid = ep->sibling;
183                  epfree(ep);
184 +            }
185              break;
186  
187      }
# Line 158 | Line 190 | register EPNODE         *epar;
190   }
191  
192                                  /* the following used to be a switch */
161 #ifdef  FUNCTION
193   static double
194   eargument(ep)
195   EPNODE  *ep;
196   {
197      return(argument(ep->v.chan));
198   }
168 #endif
199  
200   static double
201   enumber(ep)
# Line 183 | Line 213 | EPNODE *ep;
213      return(-evalue(ep1));
214   }
215  
186 #ifdef  INCHAN
216   static double
217   echannel(ep)
218   EPNODE  *ep;
219   {
220      return(chanvalue(ep->v.chan));
221   }
193 #endif
222  
223   static double
224   eadd(ep)
# Line 250 | Line 278 | EPNODE *ep;
278      if (!finite(d))
279          errno = EDOM;
280   #endif
281 <    if (errno) {
281 >    if (errno == EDOM || errno == ERANGE) {
282          wputs("Illegal power\n");
283          return(0.0);
284      }
# Line 264 | Line 292 | EPNODE *ep;
292   {
293      eputs("Bad expression!\n");
294      quit(1);
295 +        return 0.0; /* pro forma return */
296   }
297  
298  
# Line 294 | Line 323 | register EPNODE         *ep;
323   }
324  
325  
326 + void
327   initfile(fp, fn, ln)            /* prepare input file */
328   FILE  *fp;
329   char  *fn;
# Line 311 | Line 341 | int  ln;
341   }
342  
343  
344 + void
345   initstr(s, fn, ln)              /* prepare input string */
346   char  *s;
347   char  *fn;
# Line 325 | Line 356 | int  ln;
356   }
357  
358  
359 + void
360   getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
361   char  **fnp;
362   int  *lnp;
# Line 371 | Line 403 | scan()                         /* scan next character, return literal next
403  
404  
405   char *
406 < ltoa(l)                         /* convert long to ascii */
406 > long2ascii(l)                         /* convert long to ascii */
407   long  l;
408   {
409      static char  buf[16];
# Line 396 | Line 428 | long  l;
428   }
429  
430  
431 + void
432   syntax(err)                     /* report syntax error and quit */
433   char  *err;
434   {
# Line 405 | Line 438 | char  *err;
438          if (infile != NULL) eputs(infile);
439          if (lineno != 0) {
440              eputs(infile != NULL ? ", line " : "line ");
441 <            eputs(ltoa((long)lineno));
441 >            eputs(long2ascii((long)lineno));
442          }
443 <        eputs(": syntax error:\n");
443 >        eputs(":\n");
444      }
445      eputs(linbuf);
446      if (linbuf[strlen(linbuf)-1] != '\n')
# Line 421 | Line 454 | char  *err;
454   }
455  
456  
457 + void
458   addekid(ep, ekid)                       /* add a child to ep */
459   register EPNODE  *ep;
460   EPNODE  *ekid;
# Line 436 | Line 470 | EPNODE *ekid;
470   }
471  
472  
439 #if  defined(VARIABLE) || defined(FUNCTION)
473   char *
474   getname()                       /* scan an identifier */
475   {
# Line 452 | Line 485 | getname()                      /* scan an identifier */
485  
486      return(str);
487   }
455 #endif
488  
489  
490   int
# Line 485 | Line 517 | getnum()                       /* scan a positive float */
517      if (lnext == '.' && i < MAXWORD) {
518          str[i++] = lnext;
519          lnext = scan();
520 +        if (i == 1 && !isdigit(lnext))
521 +            syntax("badly formed number");
522          while (isdigit(lnext) && i < MAXWORD) {
523              str[i++] = lnext;
524              lnext = scan();
525          }
526      }
527 <    if ((lnext == 'e' || lnext == 'E') && i < MAXWORD) {
527 >    if ((lnext == 'e' | lnext == 'E') && i < MAXWORD) {
528          str[i++] = lnext;
529          lnext = scan();
530 <        if ((lnext == '-' || lnext == '+') && i < MAXWORD) {
530 >        if ((lnext == '-' | lnext == '+') && i < MAXWORD) {
531              str[i++] = lnext;
532              lnext = scan();
533          }
534 +        if (!isdigit(lnext))
535 +            syntax("missing exponent");
536          while (isdigit(lnext) && i < MAXWORD) {
537              str[i++] = lnext;
538              lnext = scan();
# Line 521 | Line 557 | getE1()                                /* E1 -> E1 ADDOP E2 */
557          scan();
558          addekid(ep2, ep1);
559          addekid(ep2, getE2());
560 < #ifdef  RCONST
561 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
560 >        if (esupport&E_RCONST &&
561 >                        ep1->type == NUM && ep1->sibling->type == NUM)
562                  ep2 = rconst(ep2);
527 #endif
563          ep1 = ep2;
564      }
565      return(ep1);
# Line 544 | Line 579 | getE2()                                /* E2 -> E2 MULOP E3 */
579          scan();
580          addekid(ep2, ep1);
581          addekid(ep2, getE3());
582 < #ifdef  RCONST
583 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
582 >        if (esupport&E_RCONST &&
583 >                        ep1->type == NUM && ep1->sibling->type == NUM)
584                  ep2 = rconst(ep2);
550 #endif
585          ep1 = ep2;
586      }
587      return(ep1);
# Line 567 | Line 601 | getE3()                                /* E3 -> E4 ^ E3 */
601          scan();
602          addekid(ep2, ep1);
603          addekid(ep2, getE3());
604 < #ifdef  RCONST
605 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
604 >        if (esupport&E_RCONST &&
605 >                        ep1->type == NUM && ep1->sibling->type == NUM)
606                  ep2 = rconst(ep2);
573 #endif
607          return(ep2);
608      }
609      return(ep1);
# Line 613 | Line 646 | getE5()                                /* E5 -> (E1) */
646                                  /*       FUNC(E1,..) */
647                                  /*       ARG */
648   {
649 <    int  i;
650 <    char  *nam;
651 <    register EPNODE  *ep1, *ep2;
649 >        int      i;
650 >        char  *nam;
651 >        register EPNODE  *ep1, *ep2;
652  
653 <    if (nextc == '(') {
654 <        scan();
655 <        ep1 = getE1();
656 <        if (nextc != ')')
657 <            syntax("')' expected");
658 <        scan();
659 <        return(ep1);
660 <    }
653 >        if (nextc == '(') {
654 >                scan();
655 >                ep1 = getE1();
656 >                if (nextc != ')')
657 >                        syntax("')' expected");
658 >                scan();
659 >                return(ep1);
660 >        }
661  
662 < #ifdef  INCHAN
663 <    if (nextc == '$') {
664 <        scan();
665 <        ep1 = newnode();
666 <        ep1->type = CHAN;
667 <        ep1->v.chan = getinum();
668 <        return(ep1);
636 <    }
637 < #endif
662 >        if (esupport&E_INCHAN && nextc == '$') {
663 >                scan();
664 >                ep1 = newnode();
665 >                ep1->type = CHAN;
666 >                ep1->v.chan = getinum();
667 >                return(ep1);
668 >        }
669  
670 < #if  defined(VARIABLE) || defined(FUNCTION)
671 <    if (isalpha(nextc) || nextc == CNTXMARK) {
672 <        nam = getname();
673 < #if  defined(VARIABLE) && defined(FUNCTION)
674 <        ep1 = NULL;
675 <        if (curfunc != NULL)
676 <            for (i = 1, ep2 = curfunc->v.kid->sibling;
677 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
678 <                if (!strcmp(ep2->v.name, nam)) {
679 <                    ep1 = newnode();
680 <                    ep1->type = ARG;
681 <                    ep1->v.chan = i;
682 <                    break;
670 >        if (esupport&(E_VARIABLE|E_FUNCTION) &&
671 >                        (isalpha(nextc) || nextc == CNTXMARK)) {
672 >                nam = getname();
673 >                ep1 = NULL;
674 >                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
675 >                                && curfunc != NULL)
676 >                        for (i = 1, ep2 = curfunc->v.kid->sibling;
677 >                                        ep2 != NULL; i++, ep2 = ep2->sibling)
678 >                                if (!strcmp(ep2->v.name, nam)) {
679 >                                        ep1 = newnode();
680 >                                        ep1->type = ARG;
681 >                                        ep1->v.chan = i;
682 >                                        break;
683 >                                }
684 >                if (ep1 == NULL) {
685 >                        ep1 = newnode();
686 >                        ep1->type = VAR;
687 >                        ep1->v.ln = varinsert(nam);
688                  }
689 <        if (ep1 == NULL)
690 < #endif
691 <        {
692 <            ep1 = newnode();
693 <            ep1->type = VAR;
694 <            ep1->v.ln = varinsert(nam);
689 >                if (esupport&E_FUNCTION && nextc == '(') {
690 >                        ep2 = newnode();
691 >                        ep2->type = FUNC;
692 >                        addekid(ep2, ep1);
693 >                        ep1 = ep2;
694 >                        do {
695 >                                scan();
696 >                                addekid(ep1, getE1());
697 >                        } while (nextc == ',');
698 >                        if (nextc != ')')
699 >                                syntax("')' expected");
700 >                        scan();
701 >                } else if (!(esupport&E_VARIABLE))
702 >                        syntax("'(' expected");
703 >                if (esupport&E_RCONST && isconstvar(ep1))
704 >                        ep1 = rconst(ep1);
705 >                return(ep1);
706          }
660 #ifdef  FUNCTION
661        if (nextc == '(') {
662            ep2 = newnode();
663            ep2->type = FUNC;
664            addekid(ep2, ep1);
665            ep1 = ep2;
666            do {
667                scan();
668                addekid(ep1, getE1());
669            } while (nextc == ',');
670            if (nextc != ')')
671                syntax("')' expected");
672            scan();
673        }
674 #ifndef  VARIABLE
675        else
676            syntax("'(' expected");
677 #endif
678 #endif
679 #ifdef  RCONST
680        if (isconstvar(ep1))
681            ep1 = rconst(ep1);
682 #endif
683        return(ep1);
684    }
685 #endif
707  
708 <    if (isdecimal(nextc)) {
709 <        ep1 = newnode();
710 <        ep1->type = NUM;
711 <        ep1->v.num = getnum();
712 <        return(ep1);
713 <    }
714 <    syntax("unexpected character");
708 >        if (isdecimal(nextc)) {
709 >                ep1 = newnode();
710 >                ep1->type = NUM;
711 >                ep1->v.num = getnum();
712 >                return(ep1);
713 >        }
714 >        syntax("unexpected character");
715 >        return NULL; /* pro forma return */
716   }
717  
718  
697 #ifdef  RCONST
719   EPNODE *
720   rconst(epar)                    /* reduce a constant expression */
721   register EPNODE  *epar;
# Line 705 | Line 726 | register EPNODE         *epar;
726      ep->type = NUM;
727      errno = 0;
728      ep->v.num = evalue(epar);
729 <    if (errno)
729 >    if (errno == EDOM || errno == ERANGE)
730          syntax("bad constant expression");
731      epfree(epar);
732  
# Line 713 | Line 734 | register EPNODE         *epar;
734   }
735  
736  
737 + int
738   isconstvar(ep)                  /* is ep linked to a constant expression? */
739   register EPNODE  *ep;
740   {
719 #ifdef  VARIABLE
741      register EPNODE  *ep1;
721 #ifdef  FUNCTION
742  
743 <    if (ep->type == FUNC) {
743 >    if (esupport&E_FUNCTION && ep->type == FUNC) {
744          if (!isconstfun(ep->v.kid))
745                  return(0);
746          for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
# Line 728 | Line 748 | register EPNODE         *ep;
748                  return(0);
749          return(1);
750      }
731 #endif
751      if (ep->type != VAR)
752          return(0);
753      ep1 = ep->v.ln->def;
754      if (ep1 == NULL || ep1->type != ':')
755          return(0);
756 < #ifdef  FUNCTION
738 <    if (ep1->v.kid->type != SYM)
756 >    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
757          return(0);
740 #endif
758      return(1);
742 #else
743    return(ep->type == FUNC);
744 #endif
759   }
760  
761  
762 < #if  defined(FUNCTION) && defined(VARIABLE)
762 > int
763   isconstfun(ep)                  /* is ep linked to a constant function? */
764   register EPNODE  *ep;
765   {
# Line 754 | Line 768 | register EPNODE         *ep;
768  
769      if (ep->type != VAR)
770          return(0);
771 <    if ((dp = ep->v.ln->def) != NULL && dp->v.kid->type == FUNC)
772 <        return(dp->type == ':');
771 >    if ((dp = ep->v.ln->def) != NULL)
772 >        if (dp->v.kid->type == FUNC)
773 >            return(dp->type == ':');
774 >        else
775 >            return(0);          /* don't identify masked library functions */
776      if ((lp = ep->v.ln->lib) != NULL)
777          return(lp->atyp == ':');
778      return(0);
779   }
763 #endif
764 #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines