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 1.6 by greg, Thu Jul 19 12:56:50 1990 UTC vs.
Revision 2.6 by greg, Mon Sep 21 12:01:54 1992 UTC

# Line 1 | Line 1
1 < /* Copyright (c) 1986 Regents of the University of California */
1 > /* Copyright (c) 1992 Regents of the University of California */
2  
3   #ifndef lint
4   static char SCCSid[] = "$SunId$ LBL";
# Line 26 | Line 26 | static char SCCSid[] = "$SunId$ LBL";
26  
27   #include  "calcomp.h"
28  
29 < #define  MAXLINE        256             /* maximum line length */
30 < #define  MAXWORD        64              /* maximum word length */
29 > #define  MAXLINE        256             /* maximum line length */
30  
31 < #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
31 > #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
32  
33 < #define  isid(c)        (isalnum(c) || (c) == '_' || (c) == '.')
33 > #define  isdecimal(c)   (isdigit(c) || (c) == '.')
34  
35 < #define  isdecimal(c)   (isdigit(c) || (c) == '.')
36 <
37 < extern double  atof(), pow();
35 > #ifndef atof
36 > extern double  atof();
37 > #endif
38 > extern double  pow();
39   extern char  *fgets(), *savestr();
40   extern char  *emalloc(), *ecalloc();
41   extern EPNODE  *curfunc;
# Line 43 | Line 43 | extern double  efunc(), evariable();
43   static double  euminus(), echannel(), eargument(), enumber();
44   static double  eadd(), esubtr(), emult(), edivi(), epow();
45   static double  ebotch();
46 extern int  errno;
46  
47   int  nextc;                             /* lookahead character */
48  
49 < double  (*eoper[])() = {                /* expression operations */
49 > double  (*eoper[])() = {                /* expression operations */
50          ebotch,
51 < #ifdef  VARIABLE
51 > #ifdef  VARIABLE
52          evariable,
53   #else
54          ebotch,
55   #endif
56          enumber,
57          euminus,
58 < #ifdef  INCHAN
58 > #ifdef  INCHAN
59          echannel,
60   #else
61          ebotch,
62   #endif
63 < #ifdef  FUNCTION
63 > #ifdef  FUNCTION
64          efunc,
65          eargument,
66   #else
# Line 78 | Line 77 | double  (*eoper[])() = {               /* expression operations */
77          esubtr,
78          0,
79          edivi,
80 <        0,0,0,0,0,0,0,0,0,0,0,0,0,
80 >        0,0,0,0,0,0,0,0,0,0,
81          ebotch,
82 +        0,0,
83 +        ebotch,
84          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
85          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
86          epow,
# Line 124 | Line 125 | char  *expr;
125  
126  
127   epfree(epar)                    /* free a parse tree */
128 < register EPNODE  *epar;
128 > register EPNODE  *epar;
129   {
130      register EPNODE  *ep;
131  
# Line 134 | Line 135 | register EPNODE  *epar;
135          case VAR:
136              varfree(epar->v.ln);
137              break;
137 #endif
138              
139          case SYM:
140              freestr(epar->v.name);
141              break;
142 + #endif
143  
144          case NUM:
145          case CHAN:
# Line 157 | Line 158 | register EPNODE  *epar;
158   }
159  
160                                  /* the following used to be a switch */
161 < #ifdef  FUNCTION
161 > #ifdef  FUNCTION
162   static double
163   eargument(ep)
164 < EPNODE  *ep;
164 > EPNODE  *ep;
165   {
166      return(argument(ep->v.chan));
167   }
# Line 168 | Line 169 | EPNODE  *ep;
169  
170   static double
171   enumber(ep)
172 < EPNODE  *ep;
172 > EPNODE  *ep;
173   {
174      return(ep->v.num);
175   }
176  
177   static double
178   euminus(ep)
179 < EPNODE  *ep;
179 > EPNODE  *ep;
180   {
181      register EPNODE  *ep1 = ep->v.kid;
182  
183      return(-evalue(ep1));
184   }
185  
186 < #ifdef  INCHAN
186 > #ifdef  INCHAN
187   static double
188   echannel(ep)
189 < EPNODE  *ep;
189 > EPNODE  *ep;
190   {
191      return(chanvalue(ep->v.chan));
192   }
# Line 193 | Line 194 | EPNODE  *ep;
194  
195   static double
196   eadd(ep)
197 < EPNODE  *ep;
197 > EPNODE  *ep;
198   {
199      register EPNODE  *ep1 = ep->v.kid;
200  
# Line 202 | Line 203 | EPNODE  *ep;
203  
204   static double
205   esubtr(ep)
206 < EPNODE  *ep;
206 > EPNODE  *ep;
207   {
208      register EPNODE  *ep1 = ep->v.kid;
209  
# Line 211 | Line 212 | EPNODE  *ep;
212  
213   static double
214   emult(ep)
215 < EPNODE  *ep;
215 > EPNODE  *ep;
216   {
217      register EPNODE  *ep1 = ep->v.kid;
218  
# Line 220 | Line 221 | EPNODE  *ep;
221  
222   static double
223   edivi(ep)
224 < EPNODE  *ep;
224 > EPNODE  *ep;
225   {
226      register EPNODE  *ep1 = ep->v.kid;
227      double  d;
# Line 236 | Line 237 | EPNODE  *ep;
237  
238   static double
239   epow(ep)
240 < EPNODE  *ep;
240 > EPNODE  *ep;
241   {
242      register EPNODE  *ep1 = ep->v.kid;
243      double  d;
244 <    int  lasterrno;
244 >    int  lasterrno;
245  
246      lasterrno = errno;
247      errno = 0;
248      d = pow(evalue(ep1), evalue(ep1->sibling));
249 < #ifdef  IEEE
249 > #ifdef  IEEE
250      if (!finite(d))
251          errno = EDOM;
252   #endif
# Line 259 | Line 260 | EPNODE  *ep;
260  
261   static double
262   ebotch(ep)
263 < EPNODE  *ep;
263 > EPNODE  *ep;
264   {
265      eputs("Bad expression!\n");
266      quit(1);
# Line 268 | Line 269 | EPNODE  *ep;
269  
270   EPNODE *
271   ekid(ep, n)                     /* return pointer to a node's nth kid */
272 < register EPNODE  *ep;
272 > register EPNODE  *ep;
273   register int  n;
274   {
275  
# Line 282 | Line 283 | register int  n;
283  
284   int
285   nekids(ep)                      /* return # of kids for node ep */
286 < register EPNODE  *ep;
286 > register EPNODE  *ep;
287   {
288      register int  n = 0;
289  
# Line 298 | Line 299 | FILE  *fp;
299   char  *fn;
300   int  ln;
301   {
302 <    static char  inpbuf[MAXLINE];
302 >    static char  inpbuf[MAXLINE];
303  
304      infp = fp;
305      linbuf = inpbuf;
# Line 324 | Line 325 | int  ln;
325   }
326  
327  
328 < scan()                          /* scan next character */
328 > getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
329 > char  **fnp;
330 > int  *lnp;
331 > char  **spp;
332 > FILE  **fpp;
333   {
334 +    if (fnp != NULL) *fnp = infile;
335 +    if (lnp != NULL) *lnp = lineno;
336 +    if (spp != NULL) *spp = linbuf+linepos;
337 +    if (fpp != NULL) *fpp = infp;
338 + }
339 +
340 +
341 + int
342 + scan()                          /* scan next character, return literal next */
343 + {
344 +    register int  lnext = 0;
345 +
346      do {
347          if (linbuf[linepos] == '\0')
348              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
# Line 337 | Line 354 | scan()                         /* scan next character */
354              }
355          else
356              nextc = linbuf[linepos++];
357 +        if (!lnext)
358 +                lnext = nextc;
359          if (nextc == '{') {
360              scan();
361              while (nextc != '}')
# Line 347 | Line 366 | scan()                         /* scan next character */
366              scan();
367          }
368      } while (isspace(nextc));
369 +    return(lnext);
370   }
371  
372  
# Line 354 | Line 374 | char *
374   ltoa(l)                         /* convert long to ascii */
375   long  l;
376   {
377 <    static char  buf[16];
377 >    static char  buf[16];
378      register char  *cp;
379 <    int  neg = 0;
379 >    int  neg = 0;
380  
381      if (l == 0)
382          return("0");
# Line 381 | Line 401 | char  *err;
401   {
402      register int  i;
403  
384    eputs(linbuf);
385    if (linbuf[strlen(linbuf)-1] != '\n')
386        eputs("\n");
387    for (i = 0; i < linepos-1; i++)
388        eputs(linbuf[i] == '\t' ? "\t" : " ");
389    eputs("^ ");
404      if (infile != NULL || lineno != 0) {
391        eputs("\n");
405          if (infile != NULL) eputs(infile);
406          if (lineno != 0) {
407              eputs(infile != NULL ? ", line " : "line ");
408              eputs(ltoa((long)lineno));
409          }
410 <        eputs(": ");
410 >        eputs(": syntax error:\n");
411      }
412 +    eputs(linbuf);
413 +    if (linbuf[strlen(linbuf)-1] != '\n')
414 +        eputs("\n");
415 +    for (i = 0; i < linepos-1; i++)
416 +        eputs(linbuf[i] == '\t' ? "\t" : " ");
417 +    eputs("^ ");
418      eputs(err);
419      eputs("\n");
420      quit(1);
# Line 403 | Line 422 | char  *err;
422  
423  
424   addekid(ep, ekid)                       /* add a child to ep */
425 < register EPNODE  *ep;
426 < EPNODE  *ekid;
425 > register EPNODE  *ep;
426 > EPNODE  *ekid;
427   {
428      if (ep->v.kid == NULL)
429          ep->v.kid = ekid;
# Line 417 | Line 436 | EPNODE  *ekid;
436   }
437  
438  
439 + #if  defined(VARIABLE) || defined(FUNCTION)
440   char *
441   getname()                       /* scan an identifier */
442   {
443 <    static char  str[MAXWORD+1];
444 <    register int  i;
443 >    static char  str[MAXWORD+1];
444 >    register int  i, lnext;
445  
446 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
447 <        str[i] = nextc;
446 >    lnext = nextc;
447 >    for (i = 0; i < MAXWORD && isid(lnext); i++, lnext = scan())
448 >        str[i] = lnext;
449      str[i] = '\0';
450 +    while (isid(lnext))         /* skip rest of name */
451 +        lnext = scan();
452  
453      return(str);
454   }
455 + #endif
456  
457  
458   int
459   getinum()                       /* scan a positive integer */
460   {
461 <    register int  n;
461 >    register int  n, lnext;
462  
463      n = 0;
464 <    while (isdigit(nextc)) {
465 <        n = n * 10 + nextc - '0';
466 <        scan();
464 >    lnext = nextc;
465 >    while (isdigit(lnext)) {
466 >        n = n * 10 + lnext - '0';
467 >        lnext = scan();
468      }
469      return(n);
470   }
# Line 448 | Line 473 | getinum()                      /* scan a positive integer */
473   double
474   getnum()                        /* scan a positive float */
475   {
476 <    register int  i;
476 >    register int  i, lnext;
477      char  str[MAXWORD+1];
478  
479      i = 0;
480 <    while (isdigit(nextc) && i < MAXWORD) {
481 <        str[i++] = nextc;
482 <        scan();
480 >    lnext = nextc;
481 >    while (isdigit(lnext) && i < MAXWORD) {
482 >        str[i++] = lnext;
483 >        lnext = scan();
484      }
485 <    if (nextc == '.' && i < MAXWORD) {
486 <        str[i++] = nextc;
487 <        scan();
488 <        while (isdigit(nextc) && i < MAXWORD) {
489 <            str[i++] = nextc;
490 <            scan();
485 >    if (lnext == '.' && i < MAXWORD) {
486 >        str[i++] = lnext;
487 >        lnext = scan();
488 >        while (isdigit(lnext) && i < MAXWORD) {
489 >            str[i++] = lnext;
490 >            lnext = scan();
491          }
492      }
493 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
494 <        str[i++] = nextc;
495 <        scan();
496 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
497 <            str[i++] = nextc;
498 <            scan();
493 >    if ((lnext == 'e' || lnext == 'E') && i < MAXWORD) {
494 >        str[i++] = lnext;
495 >        lnext = scan();
496 >        if ((lnext == '-' || lnext == '+') && i < MAXWORD) {
497 >            str[i++] = lnext;
498 >            lnext = scan();
499          }
500 <        while (isdigit(nextc) && i < MAXWORD) {
501 <            str[i++] = nextc;
502 <            scan();
500 >        while (isdigit(lnext) && i < MAXWORD) {
501 >            str[i++] = lnext;
502 >            lnext = scan();
503          }
504      }
505      str[i] = '\0';
# Line 484 | Line 510 | getnum()                       /* scan a positive float */
510  
511   EPNODE *
512   getE1()                         /* E1 -> E1 ADDOP E2 */
513 <                                /*       E2 */
513 >                                /*       E2 */
514   {
515      register EPNODE  *ep1, *ep2;
516  
# Line 495 | Line 521 | getE1()                                /* E1 -> E1 ADDOP E2 */
521          scan();
522          addekid(ep2, ep1);
523          addekid(ep2, getE2());
524 < #ifdef  RCONST
524 > #ifdef  RCONST
525          if (ep1->type == NUM && ep1->sibling->type == NUM)
526                  ep2 = rconst(ep2);
527   #endif
# Line 507 | Line 533 | getE1()                                /* E1 -> E1 ADDOP E2 */
533  
534   EPNODE *
535   getE2()                         /* E2 -> E2 MULOP E3 */
536 <                                /*       E3 */
536 >                                /*       E3 */
537   {
538      register EPNODE  *ep1, *ep2;
539  
# Line 518 | Line 544 | getE2()                                /* E2 -> E2 MULOP E3 */
544          scan();
545          addekid(ep2, ep1);
546          addekid(ep2, getE3());
547 < #ifdef  RCONST
547 > #ifdef  RCONST
548          if (ep1->type == NUM && ep1->sibling->type == NUM)
549                  ep2 = rconst(ep2);
550   #endif
# Line 529 | Line 555 | getE2()                                /* E2 -> E2 MULOP E3 */
555  
556  
557   EPNODE *
558 < getE3()                         /* E3 -> E3 ^ E4 */
559 <                                /*       E4 */
558 > getE3()                         /* E3 -> E4 ^ E3 */
559 >                                /*       E4 */
560   {
561      register EPNODE  *ep1, *ep2;
562  
563      ep1 = getE4();
564 <    while (nextc == '^') {
564 >    if (nextc == '^') {
565          ep2 = newnode();
566          ep2->type = nextc;
567          scan();
568          addekid(ep2, ep1);
569 <        addekid(ep2, getE4());
570 < #ifdef  RCONST
569 >        addekid(ep2, getE3());
570 > #ifdef  RCONST
571          if (ep1->type == NUM && ep1->sibling->type == NUM)
572                  ep2 = rconst(ep2);
573   #endif
574 <        ep1 = ep2;
574 >        return(ep2);
575      }
576      return(ep1);
577   }
# Line 553 | Line 579 | getE3()                                /* E3 -> E3 ^ E4 */
579  
580   EPNODE *
581   getE4()                         /* E4 -> ADDOP E5 */
582 <                                /*       E5 */
582 >                                /*       E5 */
583   {
584      register EPNODE  *ep1, *ep2;
585  
# Line 564 | Line 590 | getE4()                                /* E4 -> ADDOP E5 */
590                  ep2->v.num = -ep2->v.num;
591                  return(ep2);
592          }
593 +        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
594 +            efree((char *)ep2);
595 +            return(ep2->v.kid);
596 +        }
597          ep1 = newnode();
598          ep1->type = UMINUS;
599          addekid(ep1, ep2);
# Line 577 | Line 607 | getE4()                                /* E4 -> ADDOP E5 */
607  
608   EPNODE *
609   getE5()                         /* E5 -> (E1) */
610 <                                /*       VAR */
611 <                                /*       NUM */
612 <                                /*       $N */
613 <                                /*       FUNC(E1,..) */
614 <                                /*       ARG */
610 >                                /*       VAR */
611 >                                /*       NUM */
612 >                                /*       $N */
613 >                                /*       FUNC(E1,..) */
614 >                                /*       ARG */
615   {
616 <    int  i;
616 >    int  i;
617 >    char  *nam;
618      register EPNODE  *ep1, *ep2;
619  
620      if (nextc == '(') {
# Line 595 | Line 626 | getE5()                                /* E5 -> (E1) */
626          return(ep1);
627      }
628  
629 < #ifdef  INCHAN
629 > #ifdef  INCHAN
630      if (nextc == '$') {
631          scan();
632          ep1 = newnode();
# Line 606 | Line 637 | getE5()                                /* E5 -> (E1) */
637   #endif
638  
639   #if  defined(VARIABLE) || defined(FUNCTION)
640 <    if (isalpha(nextc)) {
641 <        ep1 = newnode();
611 <        ep1->type = VAR;
612 <        ep1->v.ln = varinsert(getname());
613 <
640 >    if (isalpha(nextc) || nextc == CNTXMARK) {
641 >        nam = getname();
642   #if  defined(VARIABLE) && defined(FUNCTION)
643 +        ep1 = NULL;
644          if (curfunc != NULL)
645              for (i = 1, ep2 = curfunc->v.kid->sibling;
646 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
647 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
619 <                    epfree(ep1);
646 >                                ep2 != NULL; i++, ep2 = ep2->sibling)
647 >                if (!strcmp(ep2->v.name, nam)) {
648                      ep1 = newnode();
649                      ep1->type = ARG;
650                      ep1->v.chan = i;
651                      break;
652                  }
653 +        if (ep1 == NULL)
654   #endif
655 < #ifdef  FUNCTION
655 >        {
656 >            ep1 = newnode();
657 >            ep1->type = VAR;
658 >            ep1->v.ln = varinsert(nam);
659 >        }
660 > #ifdef  FUNCTION
661          if (nextc == '(') {
662              ep2 = newnode();
663              ep2->type = FUNC;
# Line 637 | Line 671 | getE5()                                /* E5 -> (E1) */
671                  syntax("')' expected");
672              scan();
673          }
674 < #ifndef  VARIABLE
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
# Line 656 | Line 694 | getE5()                                /* E5 -> (E1) */
694   }
695  
696  
697 < #ifdef  RCONST
697 > #ifdef  RCONST
698   EPNODE *
699   rconst(epar)                    /* reduce a constant expression */
700 < register EPNODE  *epar;
700 > register EPNODE  *epar;
701   {
702      register EPNODE  *ep;
703  
# Line 668 | Line 706 | register EPNODE  *epar;
706      errno = 0;
707      ep->v.num = evalue(epar);
708      if (errno)
709 <        syntax("bad constant expression");
709 >        syntax("bad constant expression");
710      epfree(epar);
711  
712      return(ep);
713   }
714 +
715 +
716 + isconstvar(ep)                  /* is ep linked to a constant expression? */
717 + register EPNODE  *ep;
718 + {
719 + #ifdef  VARIABLE
720 +    register EPNODE  *ep1;
721 + #ifdef  FUNCTION
722 +
723 +    if (ep->type == FUNC) {
724 +        if (!isconstfun(ep->v.kid))
725 +                return(0);
726 +        for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
727 +            if (ep1->type != NUM && !isconstfun(ep1))
728 +                return(0);
729 +        return(1);
730 +    }
731 + #endif
732 +    if (ep->type != VAR)
733 +        return(0);
734 +    ep1 = ep->v.ln->def;
735 +    if (ep1 == NULL || ep1->type != ':')
736 +        return(0);
737 + #ifdef  FUNCTION
738 +    if (ep1->v.kid->type != SYM)
739 +        return(0);
740 + #endif
741 +    return(1);
742 + #else
743 +    return(ep->type == FUNC);
744 + #endif
745 + }
746 +
747 +
748 + #if  defined(FUNCTION) && defined(VARIABLE)
749 + isconstfun(ep)                  /* is ep linked to a constant function? */
750 + register EPNODE  *ep;
751 + {
752 +    register EPNODE  *dp;
753 +    register LIBR  *lp;
754 +
755 +    if (ep->type != VAR)
756 +        return(0);
757 +    if ((dp = ep->v.ln->def) != NULL && dp->v.kid->type == FUNC)
758 +        return(dp->type == ':');
759 +    if ((lp = ep->v.ln->lib) != NULL)
760 +        return(lp->atyp == ':');
761 +    return(0);
762 + }
763 + #endif
764   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines