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.3 by greg, Wed Jun 14 22:29:01 1989 UTC vs.
Revision 2.15 by greg, Wed Sep 8 09:12:37 1993 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 24 | Line 24 | static char SCCSid[] = "$SunId$ LBL";
24  
25   #include  <errno.h>
26  
27 + #include  <math.h>
28 +
29   #include  "calcomp.h"
30  
31 < #define  MAXLINE        256             /* maximum line length */
30 < #define  MAXWORD        64              /* maximum word length */
31 > #define  MAXLINE        256             /* maximum line length */
32  
33 < #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
33 > #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
34  
35 < #define  isid(c)        (isalnum(c) || (c) == '_' || (c) == '.')
35 > #define  isdecimal(c)   (isdigit(c) || (c) == '.')
36  
37 < #define  isdecimal(c)   (isdigit(c) || (c) == '.')
37 <
38 < extern double  atof(), pow();
39 < extern char  *fgets(), *savestr();
37 > extern char  *savestr();
38   extern char  *emalloc(), *ecalloc();
39   extern EPNODE  *curfunc;
40 < extern double  efunc(), evariable(), enumber(), euminus(), echannel();
41 < extern double  eargument(), eadd(), esubtr(), emult(), edivi(), epow();
42 < extern double  ebotch();
43 < extern int  errno;
40 > extern double  efunc(), evariable();
41 > static double  euminus(), eargument(), enumber();
42 > #ifdef  INCHAN
43 > static double  echannel();
44 > #endif
45 > static double  eadd(), esubtr(), emult(), edivi(), epow();
46 > static double  ebotch();
47  
48 + #ifdef  DCL_ATOF
49 + extern double  atof();
50 + #endif
51 +
52   int  nextc;                             /* lookahead character */
53  
54 < double  (*eoper[])() = {                /* expression operations */
54 > double  (*eoper[])() = {                /* expression operations */
55          ebotch,
56 < #ifdef  VARIABLE
56 > #ifdef  VARIABLE
57          evariable,
58   #else
59          ebotch,
60   #endif
61          enumber,
62          euminus,
63 < #ifdef  INCHAN
63 > #ifdef  INCHAN
64          echannel,
65   #else
66          ebotch,
67   #endif
68 < #ifdef  FUNCTION
68 > #ifdef  FUNCTION
69          efunc,
70          eargument,
71   #else
# Line 77 | Line 82 | double  (*eoper[])() = {               /* expression operations */
82          esubtr,
83          0,
84          edivi,
85 <        0,0,0,0,0,0,0,0,0,0,0,0,0,
85 >        0,0,0,0,0,0,0,0,0,0,
86          ebotch,
87 +        0,0,
88 +        ebotch,
89          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
90          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
91          epow,
92   };
93  
87 static char  *infile;                   /* input file name */
94   static FILE  *infp;                     /* input file pointer */
95   static char  *linbuf;                   /* line buffer */
96 + static char  *infile;                   /* input file name */
97 + static int  lineno;                     /* input line number */
98   static int  linepos;                    /* position in buffer */
99  
100  
# Line 96 | Line 104 | char  *expr;
104   {
105      EPNODE  *ep;
106  
107 <    initstr(NULL, expr);
107 >    initstr(expr, NULL, 0);
108   #if  defined(VARIABLE) && defined(FUNCTION)
109      curfunc = NULL;
110   #endif
# Line 122 | Line 130 | char  *expr;
130  
131  
132   epfree(epar)                    /* free a parse tree */
133 < register EPNODE  *epar;
133 > register EPNODE  *epar;
134   {
135      register EPNODE  *ep;
136  
# Line 132 | Line 140 | register EPNODE  *epar;
140          case VAR:
141              varfree(epar->v.ln);
142              break;
135 #endif
143              
144          case SYM:
145              freestr(epar->v.name);
146              break;
147 + #endif
148  
149          case NUM:
150          case CHAN:
# Line 145 | Line 153 | register EPNODE  *epar;
153              break;
154  
155          default:
156 <            for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
156 >            while ((ep = epar->v.kid) != NULL) {
157 >                epar->v.kid = ep->sibling;
158                  epfree(ep);
159 +            }
160              break;
161  
162      }
# Line 155 | Line 165 | register EPNODE  *epar;
165   }
166  
167                                  /* the following used to be a switch */
168 < #ifdef  FUNCTION
168 > #ifdef  FUNCTION
169   static double
170   eargument(ep)
171 < EPNODE  *ep;
171 > EPNODE  *ep;
172   {
173      return(argument(ep->v.chan));
174   }
# Line 166 | Line 176 | EPNODE  *ep;
176  
177   static double
178   enumber(ep)
179 < EPNODE  *ep;
179 > EPNODE  *ep;
180   {
181      return(ep->v.num);
182   }
183  
184   static double
185   euminus(ep)
186 < EPNODE  *ep;
186 > EPNODE  *ep;
187   {
188      register EPNODE  *ep1 = ep->v.kid;
189  
190      return(-evalue(ep1));
191   }
192  
193 < #ifdef  INCHAN
193 > #ifdef  INCHAN
194   static double
195   echannel(ep)
196 < EPNODE  *ep;
196 > EPNODE  *ep;
197   {
198      return(chanvalue(ep->v.chan));
199   }
# Line 191 | Line 201 | EPNODE  *ep;
201  
202   static double
203   eadd(ep)
204 < EPNODE  *ep;
204 > EPNODE  *ep;
205   {
206      register EPNODE  *ep1 = ep->v.kid;
207  
# Line 200 | Line 210 | EPNODE  *ep;
210  
211   static double
212   esubtr(ep)
213 < EPNODE  *ep;
213 > EPNODE  *ep;
214   {
215      register EPNODE  *ep1 = ep->v.kid;
216  
# Line 209 | Line 219 | EPNODE  *ep;
219  
220   static double
221   emult(ep)
222 < EPNODE  *ep;
222 > EPNODE  *ep;
223   {
224      register EPNODE  *ep1 = ep->v.kid;
225  
# Line 218 | Line 228 | EPNODE  *ep;
228  
229   static double
230   edivi(ep)
231 < EPNODE  *ep;
231 > EPNODE  *ep;
232   {
233      register EPNODE  *ep1 = ep->v.kid;
234      double  d;
# Line 234 | Line 244 | EPNODE  *ep;
244  
245   static double
246   epow(ep)
247 < EPNODE  *ep;
247 > EPNODE  *ep;
248   {
249      register EPNODE  *ep1 = ep->v.kid;
250      double  d;
251 <    int  lasterrno;
251 >    int  lasterrno;
252  
253      lasterrno = errno;
254      errno = 0;
255      d = pow(evalue(ep1), evalue(ep1->sibling));
256 < #ifdef  IEEE
256 > #ifdef  IEEE
257      if (!finite(d))
258          errno = EDOM;
259   #endif
# Line 257 | Line 267 | EPNODE  *ep;
267  
268   static double
269   ebotch(ep)
270 < EPNODE  *ep;
270 > EPNODE  *ep;
271   {
272      eputs("Bad expression!\n");
273      quit(1);
# Line 266 | Line 276 | EPNODE  *ep;
276  
277   EPNODE *
278   ekid(ep, n)                     /* return pointer to a node's nth kid */
279 < register EPNODE  *ep;
279 > register EPNODE  *ep;
280   register int  n;
281   {
282  
# Line 280 | Line 290 | register int  n;
290  
291   int
292   nekids(ep)                      /* return # of kids for node ep */
293 < register EPNODE  *ep;
293 > register EPNODE  *ep;
294   {
295      register int  n = 0;
296  
# Line 291 | Line 301 | register EPNODE  *ep;
301   }
302  
303  
304 < initfile(file, fp)              /* prepare input file */
295 < char  *file;
304 > initfile(fp, fn, ln)            /* prepare input file */
305   FILE  *fp;
306 + char  *fn;
307 + int  ln;
308   {
309 <    static char  inpbuf[MAXLINE];
309 >    static char  inpbuf[MAXLINE];
310  
300    infile = file;
311      infp = fp;
312      linbuf = inpbuf;
313 +    infile = fn;
314 +    lineno = ln;
315      linepos = 0;
316      inpbuf[0] = '\0';
317      scan();
318   }
319  
320  
321 < initstr(file, s)                /* prepare input string */
310 < char  *file;
321 > initstr(s, fn, ln)              /* prepare input string */
322   char  *s;
323 + char  *fn;
324 + int  ln;
325   {
313    infile = file;
326      infp = NULL;
327 +    infile = fn;
328 +    lineno = ln;
329      linbuf = s;
330      linepos = 0;
331      scan();
332   }
333  
334  
335 < scan()                          /* scan next character */
335 > getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
336 > char  **fnp;
337 > int  *lnp;
338 > char  **spp;
339 > FILE  **fpp;
340   {
341 +    if (fnp != NULL) *fnp = infile;
342 +    if (lnp != NULL) *lnp = lineno;
343 +    if (spp != NULL) *spp = linbuf+linepos;
344 +    if (fpp != NULL) *fpp = infp;
345 + }
346 +
347 +
348 + int
349 + scan()                          /* scan next character, return literal next */
350 + {
351 +    register int  lnext = 0;
352 +
353      do {
354          if (linbuf[linepos] == '\0')
355              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
356                  nextc = EOF;
357              else {
358                  nextc = linbuf[0];
359 +                lineno++;
360                  linepos = 1;
361              }
362          else
363              nextc = linbuf[linepos++];
364 +        if (!lnext)
365 +                lnext = nextc;
366          if (nextc == '{') {
367              scan();
368              while (nextc != '}')
# Line 340 | Line 373 | scan()                         /* scan next character */
373              scan();
374          }
375      } while (isspace(nextc));
376 +    return(lnext);
377   }
378  
379  
380 + char *
381 + long2ascii(l)                         /* convert long to ascii */
382 + long  l;
383 + {
384 +    static char  buf[16];
385 +    register char  *cp;
386 +    int  neg = 0;
387 +
388 +    if (l == 0)
389 +        return("0");
390 +    if (l < 0) {
391 +        l = -l;
392 +        neg++;
393 +    }
394 +    cp = buf + sizeof(buf);
395 +    *--cp = '\0';
396 +    while (l) {
397 +        *--cp = l % 10 + '0';
398 +        l /= 10;
399 +    }
400 +    if (neg)
401 +        *--cp = '-';
402 +    return(cp);
403 + }
404 +
405 +
406   syntax(err)                     /* report syntax error and quit */
407   char  *err;
408   {
409      register int  i;
410  
411 +    if (infile != NULL || lineno != 0) {
412 +        if (infile != NULL) eputs(infile);
413 +        if (lineno != 0) {
414 +            eputs(infile != NULL ? ", line " : "line ");
415 +            eputs(long2ascii((long)lineno));
416 +        }
417 +        eputs(":\n");
418 +    }
419      eputs(linbuf);
420 <    if (linbuf[0] == '\0' || linbuf[strlen(linbuf)-1] != '\n')
420 >    if (linbuf[strlen(linbuf)-1] != '\n')
421          eputs("\n");
422      for (i = 0; i < linepos-1; i++)
423          eputs(linbuf[i] == '\t' ? "\t" : " ");
424      eputs("^ ");
357    if (infile != NULL) {
358        eputs(infile);
359        eputs(": ");
360    }
425      eputs(err);
426      eputs("\n");
427      quit(1);
# Line 365 | Line 429 | char  *err;
429  
430  
431   addekid(ep, ekid)                       /* add a child to ep */
432 < register EPNODE  *ep;
433 < EPNODE  *ekid;
432 > register EPNODE  *ep;
433 > EPNODE  *ekid;
434   {
435      if (ep->v.kid == NULL)
436          ep->v.kid = ekid;
# Line 379 | Line 443 | EPNODE  *ekid;
443   }
444  
445  
446 + #if  defined(VARIABLE) || defined(FUNCTION)
447   char *
448   getname()                       /* scan an identifier */
449   {
450 <    static char  str[MAXWORD+1];
451 <    register int  i;
450 >    static char  str[MAXWORD+1];
451 >    register int  i, lnext;
452  
453 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
454 <        str[i] = nextc;
453 >    lnext = nextc;
454 >    for (i = 0; i < MAXWORD && isid(lnext); i++, lnext = scan())
455 >        str[i] = lnext;
456      str[i] = '\0';
457 +    while (isid(lnext))         /* skip rest of name */
458 +        lnext = scan();
459  
460      return(str);
461   }
462 + #endif
463  
464  
465   int
466   getinum()                       /* scan a positive integer */
467   {
468 <    register int  n;
468 >    register int  n, lnext;
469  
470      n = 0;
471 <    while (isdigit(nextc)) {
472 <        n = n * 10 + nextc - '0';
473 <        scan();
471 >    lnext = nextc;
472 >    while (isdigit(lnext)) {
473 >        n = n * 10 + lnext - '0';
474 >        lnext = scan();
475      }
476      return(n);
477   }
# Line 410 | Line 480 | getinum()                      /* scan a positive integer */
480   double
481   getnum()                        /* scan a positive float */
482   {
483 <    register int  i;
483 >    register int  i, lnext;
484      char  str[MAXWORD+1];
485  
486      i = 0;
487 <    while (isdigit(nextc) && i < MAXWORD) {
488 <        str[i++] = nextc;
489 <        scan();
487 >    lnext = nextc;
488 >    while (isdigit(lnext) && i < MAXWORD) {
489 >        str[i++] = lnext;
490 >        lnext = scan();
491      }
492 <    if (nextc == '.' && i < MAXWORD) {
493 <        str[i++] = nextc;
494 <        scan();
495 <        while (isdigit(nextc) && i < MAXWORD) {
496 <            str[i++] = nextc;
497 <            scan();
492 >    if (lnext == '.' && i < MAXWORD) {
493 >        str[i++] = lnext;
494 >        lnext = scan();
495 >        while (isdigit(lnext) && i < MAXWORD) {
496 >            str[i++] = lnext;
497 >            lnext = scan();
498          }
499      }
500 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
501 <        str[i++] = nextc;
502 <        scan();
503 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
504 <            str[i++] = nextc;
505 <            scan();
500 >    if ((lnext == 'e' || lnext == 'E') && i < MAXWORD) {
501 >        str[i++] = lnext;
502 >        lnext = scan();
503 >        if ((lnext == '-' || lnext == '+') && i < MAXWORD) {
504 >            str[i++] = lnext;
505 >            lnext = scan();
506          }
507 <        while (isdigit(nextc) && i < MAXWORD) {
508 <            str[i++] = nextc;
509 <            scan();
507 >        while (isdigit(lnext) && i < MAXWORD) {
508 >            str[i++] = lnext;
509 >            lnext = scan();
510          }
511      }
512      str[i] = '\0';
# Line 446 | Line 517 | getnum()                       /* scan a positive float */
517  
518   EPNODE *
519   getE1()                         /* E1 -> E1 ADDOP E2 */
520 <                                /*       E2 */
520 >                                /*       E2 */
521   {
522      register EPNODE  *ep1, *ep2;
523  
# Line 457 | Line 528 | getE1()                                /* E1 -> E1 ADDOP E2 */
528          scan();
529          addekid(ep2, ep1);
530          addekid(ep2, getE2());
531 < #ifdef  RCONST
531 > #ifdef  RCONST
532          if (ep1->type == NUM && ep1->sibling->type == NUM)
533                  ep2 = rconst(ep2);
534   #endif
# Line 469 | Line 540 | getE1()                                /* E1 -> E1 ADDOP E2 */
540  
541   EPNODE *
542   getE2()                         /* E2 -> E2 MULOP E3 */
543 <                                /*       E3 */
543 >                                /*       E3 */
544   {
545      register EPNODE  *ep1, *ep2;
546  
# Line 480 | Line 551 | getE2()                                /* E2 -> E2 MULOP E3 */
551          scan();
552          addekid(ep2, ep1);
553          addekid(ep2, getE3());
554 < #ifdef  RCONST
554 > #ifdef  RCONST
555          if (ep1->type == NUM && ep1->sibling->type == NUM)
556                  ep2 = rconst(ep2);
557   #endif
# Line 491 | Line 562 | getE2()                                /* E2 -> E2 MULOP E3 */
562  
563  
564   EPNODE *
565 < getE3()                         /* E3 -> E3 ^ E4 */
566 <                                /*       E4 */
565 > getE3()                         /* E3 -> E4 ^ E3 */
566 >                                /*       E4 */
567   {
568      register EPNODE  *ep1, *ep2;
569  
570      ep1 = getE4();
571 <    while (nextc == '^') {
571 >    if (nextc == '^') {
572          ep2 = newnode();
573          ep2->type = nextc;
574          scan();
575          addekid(ep2, ep1);
576 <        addekid(ep2, getE4());
577 < #ifdef  RCONST
576 >        addekid(ep2, getE3());
577 > #ifdef  RCONST
578          if (ep1->type == NUM && ep1->sibling->type == NUM)
579                  ep2 = rconst(ep2);
580   #endif
581 <        ep1 = ep2;
581 >        return(ep2);
582      }
583      return(ep1);
584   }
# Line 515 | Line 586 | getE3()                                /* E3 -> E3 ^ E4 */
586  
587   EPNODE *
588   getE4()                         /* E4 -> ADDOP E5 */
589 <                                /*       E5 */
589 >                                /*       E5 */
590   {
591      register EPNODE  *ep1, *ep2;
592  
# Line 526 | Line 597 | getE4()                                /* E4 -> ADDOP E5 */
597                  ep2->v.num = -ep2->v.num;
598                  return(ep2);
599          }
600 +        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
601 +            efree((char *)ep2);
602 +            return(ep2->v.kid);
603 +        }
604          ep1 = newnode();
605          ep1->type = UMINUS;
606          addekid(ep1, ep2);
# Line 539 | Line 614 | getE4()                                /* E4 -> ADDOP E5 */
614  
615   EPNODE *
616   getE5()                         /* E5 -> (E1) */
617 <                                /*       VAR */
618 <                                /*       NUM */
619 <                                /*       $N */
620 <                                /*       FUNC(E1,..) */
621 <                                /*       ARG */
617 >                                /*       VAR */
618 >                                /*       NUM */
619 >                                /*       $N */
620 >                                /*       FUNC(E1,..) */
621 >                                /*       ARG */
622   {
623 <    int  i;
623 >    int  i;
624 >    char  *nam;
625      register EPNODE  *ep1, *ep2;
626  
627      if (nextc == '(') {
# Line 557 | Line 633 | getE5()                                /* E5 -> (E1) */
633          return(ep1);
634      }
635  
636 < #ifdef  INCHAN
636 > #ifdef  INCHAN
637      if (nextc == '$') {
638          scan();
639          ep1 = newnode();
# Line 568 | Line 644 | getE5()                                /* E5 -> (E1) */
644   #endif
645  
646   #if  defined(VARIABLE) || defined(FUNCTION)
647 <    if (isalpha(nextc)) {
648 <        ep1 = newnode();
573 <        ep1->type = VAR;
574 <        ep1->v.ln = varinsert(getname());
575 <
647 >    if (isalpha(nextc) || nextc == CNTXMARK) {
648 >        nam = getname();
649   #if  defined(VARIABLE) && defined(FUNCTION)
650 +        ep1 = NULL;
651          if (curfunc != NULL)
652              for (i = 1, ep2 = curfunc->v.kid->sibling;
653 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
654 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
581 <                    epfree(ep1);
653 >                                ep2 != NULL; i++, ep2 = ep2->sibling)
654 >                if (!strcmp(ep2->v.name, nam)) {
655                      ep1 = newnode();
656                      ep1->type = ARG;
657                      ep1->v.chan = i;
658                      break;
659                  }
660 +        if (ep1 == NULL)
661   #endif
662 < #ifdef  FUNCTION
662 >        {
663 >            ep1 = newnode();
664 >            ep1->type = VAR;
665 >            ep1->v.ln = varinsert(nam);
666 >        }
667 > #ifdef  FUNCTION
668          if (nextc == '(') {
669              ep2 = newnode();
670              ep2->type = FUNC;
# Line 599 | Line 678 | getE5()                                /* E5 -> (E1) */
678                  syntax("')' expected");
679              scan();
680          }
681 < #ifndef  VARIABLE
681 > #ifndef  VARIABLE
682          else
683              syntax("'(' expected");
684   #endif
685   #endif
686 + #ifdef  RCONST
687 +        if (isconstvar(ep1))
688 +            ep1 = rconst(ep1);
689 + #endif
690          return(ep1);
691      }
692   #endif
# Line 618 | Line 701 | getE5()                                /* E5 -> (E1) */
701   }
702  
703  
704 < #ifdef  RCONST
704 > #ifdef  RCONST
705   EPNODE *
706   rconst(epar)                    /* reduce a constant expression */
707 < register EPNODE  *epar;
707 > register EPNODE  *epar;
708   {
709      register EPNODE  *ep;
710  
# Line 630 | Line 713 | register EPNODE  *epar;
713      errno = 0;
714      ep->v.num = evalue(epar);
715      if (errno)
716 <        syntax("bad constant expression");
716 >        syntax("bad constant expression");
717      epfree(epar);
718  
719      return(ep);
720   }
721 +
722 +
723 + isconstvar(ep)                  /* is ep linked to a constant expression? */
724 + register EPNODE  *ep;
725 + {
726 + #ifdef  VARIABLE
727 +    register EPNODE  *ep1;
728 + #ifdef  FUNCTION
729 +
730 +    if (ep->type == FUNC) {
731 +        if (!isconstfun(ep->v.kid))
732 +                return(0);
733 +        for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
734 +            if (ep1->type != NUM && !isconstfun(ep1))
735 +                return(0);
736 +        return(1);
737 +    }
738 + #endif
739 +    if (ep->type != VAR)
740 +        return(0);
741 +    ep1 = ep->v.ln->def;
742 +    if (ep1 == NULL || ep1->type != ':')
743 +        return(0);
744 + #ifdef  FUNCTION
745 +    if (ep1->v.kid->type != SYM)
746 +        return(0);
747 + #endif
748 +    return(1);
749 + #else
750 +    return(ep->type == FUNC);
751 + #endif
752 + }
753 +
754 +
755 + #if  defined(FUNCTION) && defined(VARIABLE)
756 + isconstfun(ep)                  /* is ep linked to a constant function? */
757 + register EPNODE  *ep;
758 + {
759 +    register EPNODE  *dp;
760 +    register LIBR  *lp;
761 +
762 +    if (ep->type != VAR)
763 +        return(0);
764 +    if ((dp = ep->v.ln->def) != NULL && dp->v.kid->type == FUNC)
765 +        return(dp->type == ':');
766 +    if ((lp = ep->v.ln->lib) != NULL)
767 +        return(lp->atyp == ':');
768 +    return(0);
769 + }
770 + #endif
771   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines