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.5 by greg, Tue Jun 26 09:15:11 1990 UTC vs.
Revision 2.11 by greg, Sun Nov 22 11:53:36 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 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) == '.')
38 <
39 < extern double  atof(), pow();
37 > #ifndef atof
38 > extern double  atof();
39 > #endif
40   extern char  *fgets(), *savestr();
41   extern char  *emalloc(), *ecalloc();
42   extern EPNODE  *curfunc;
# Line 43 | Line 44 | extern double  efunc(), evariable();
44   static double  euminus(), echannel(), eargument(), enumber();
45   static double  eadd(), esubtr(), emult(), edivi(), epow();
46   static double  ebotch();
46 extern int  errno;
47  
48   int  nextc;                             /* lookahead character */
49  
50 < double  (*eoper[])() = {                /* expression operations */
50 > double  (*eoper[])() = {                /* expression operations */
51          ebotch,
52 < #ifdef  VARIABLE
52 > #ifdef  VARIABLE
53          evariable,
54   #else
55          ebotch,
56   #endif
57          enumber,
58          euminus,
59 < #ifdef  INCHAN
59 > #ifdef  INCHAN
60          echannel,
61   #else
62          ebotch,
63   #endif
64 < #ifdef  FUNCTION
64 > #ifdef  FUNCTION
65          efunc,
66          eargument,
67   #else
# Line 78 | Line 78 | double  (*eoper[])() = {               /* expression operations */
78          esubtr,
79          0,
80          edivi,
81 <        0,0,0,0,0,0,0,0,0,0,0,0,0,
81 >        0,0,0,0,0,0,0,0,0,0,
82          ebotch,
83 +        0,0,
84 +        ebotch,
85          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
86          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
87          epow,
88   };
89  
88 static char  *infile;                   /* input file name */
90   static FILE  *infp;                     /* input file pointer */
91   static char  *linbuf;                   /* line buffer */
92 + static char  *infile;                   /* input file name */
93 + static int  lineno;                     /* input line number */
94   static int  linepos;                    /* position in buffer */
95  
96  
# Line 97 | Line 100 | char  *expr;
100   {
101      EPNODE  *ep;
102  
103 <    initstr(NULL, expr);
103 >    initstr(expr, NULL, 0);
104   #if  defined(VARIABLE) && defined(FUNCTION)
105      curfunc = NULL;
106   #endif
# Line 123 | Line 126 | char  *expr;
126  
127  
128   epfree(epar)                    /* free a parse tree */
129 < register EPNODE  *epar;
129 > register EPNODE  *epar;
130   {
131      register EPNODE  *ep;
132  
# Line 133 | Line 136 | register EPNODE  *epar;
136          case VAR:
137              varfree(epar->v.ln);
138              break;
136 #endif
139              
140          case SYM:
141              freestr(epar->v.name);
142              break;
143 + #endif
144  
145          case NUM:
146          case CHAN:
# Line 146 | Line 149 | register EPNODE  *epar;
149              break;
150  
151          default:
152 <            for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
152 >            while ((ep = epar->v.kid) != NULL) {
153 >                epar->v.kid = ep->sibling;
154                  epfree(ep);
155 +            }
156              break;
157  
158      }
# Line 156 | Line 161 | register EPNODE  *epar;
161   }
162  
163                                  /* the following used to be a switch */
164 < #ifdef  FUNCTION
164 > #ifdef  FUNCTION
165   static double
166   eargument(ep)
167 < EPNODE  *ep;
167 > EPNODE  *ep;
168   {
169      return(argument(ep->v.chan));
170   }
# Line 167 | Line 172 | EPNODE  *ep;
172  
173   static double
174   enumber(ep)
175 < EPNODE  *ep;
175 > EPNODE  *ep;
176   {
177      return(ep->v.num);
178   }
179  
180   static double
181   euminus(ep)
182 < EPNODE  *ep;
182 > EPNODE  *ep;
183   {
184      register EPNODE  *ep1 = ep->v.kid;
185  
186      return(-evalue(ep1));
187   }
188  
189 < #ifdef  INCHAN
189 > #ifdef  INCHAN
190   static double
191   echannel(ep)
192 < EPNODE  *ep;
192 > EPNODE  *ep;
193   {
194      return(chanvalue(ep->v.chan));
195   }
# Line 192 | Line 197 | EPNODE  *ep;
197  
198   static double
199   eadd(ep)
200 < EPNODE  *ep;
200 > EPNODE  *ep;
201   {
202      register EPNODE  *ep1 = ep->v.kid;
203  
# Line 201 | Line 206 | EPNODE  *ep;
206  
207   static double
208   esubtr(ep)
209 < EPNODE  *ep;
209 > EPNODE  *ep;
210   {
211      register EPNODE  *ep1 = ep->v.kid;
212  
# Line 210 | Line 215 | EPNODE  *ep;
215  
216   static double
217   emult(ep)
218 < EPNODE  *ep;
218 > EPNODE  *ep;
219   {
220      register EPNODE  *ep1 = ep->v.kid;
221  
# Line 219 | Line 224 | EPNODE  *ep;
224  
225   static double
226   edivi(ep)
227 < EPNODE  *ep;
227 > EPNODE  *ep;
228   {
229      register EPNODE  *ep1 = ep->v.kid;
230      double  d;
# Line 235 | Line 240 | EPNODE  *ep;
240  
241   static double
242   epow(ep)
243 < EPNODE  *ep;
243 > EPNODE  *ep;
244   {
245      register EPNODE  *ep1 = ep->v.kid;
246      double  d;
247 <    int  lasterrno;
247 >    int  lasterrno;
248  
249      lasterrno = errno;
250      errno = 0;
251      d = pow(evalue(ep1), evalue(ep1->sibling));
252 < #ifdef  IEEE
252 > #ifdef  IEEE
253      if (!finite(d))
254          errno = EDOM;
255   #endif
# Line 258 | Line 263 | EPNODE  *ep;
263  
264   static double
265   ebotch(ep)
266 < EPNODE  *ep;
266 > EPNODE  *ep;
267   {
268      eputs("Bad expression!\n");
269      quit(1);
# Line 267 | Line 272 | EPNODE  *ep;
272  
273   EPNODE *
274   ekid(ep, n)                     /* return pointer to a node's nth kid */
275 < register EPNODE  *ep;
275 > register EPNODE  *ep;
276   register int  n;
277   {
278  
# Line 281 | Line 286 | register int  n;
286  
287   int
288   nekids(ep)                      /* return # of kids for node ep */
289 < register EPNODE  *ep;
289 > register EPNODE  *ep;
290   {
291      register int  n = 0;
292  
# Line 292 | Line 297 | register EPNODE  *ep;
297   }
298  
299  
300 < initfile(file, fp)              /* prepare input file */
296 < char  *file;
300 > initfile(fp, fn, ln)            /* prepare input file */
301   FILE  *fp;
302 + char  *fn;
303 + int  ln;
304   {
305 <    static char  inpbuf[MAXLINE];
305 >    static char  inpbuf[MAXLINE];
306  
301    infile = file;
307      infp = fp;
308      linbuf = inpbuf;
309 +    infile = fn;
310 +    lineno = ln;
311      linepos = 0;
312      inpbuf[0] = '\0';
313      scan();
314   }
315  
316  
317 < initstr(file, s)                /* prepare input string */
311 < char  *file;
317 > initstr(s, fn, ln)              /* prepare input string */
318   char  *s;
319 + char  *fn;
320 + int  ln;
321   {
314    infile = file;
322      infp = NULL;
323 +    infile = fn;
324 +    lineno = ln;
325      linbuf = s;
326      linepos = 0;
327      scan();
328   }
329  
330  
331 < scan()                          /* scan next character */
331 > getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
332 > char  **fnp;
333 > int  *lnp;
334 > char  **spp;
335 > FILE  **fpp;
336   {
337 +    if (fnp != NULL) *fnp = infile;
338 +    if (lnp != NULL) *lnp = lineno;
339 +    if (spp != NULL) *spp = linbuf+linepos;
340 +    if (fpp != NULL) *fpp = infp;
341 + }
342 +
343 +
344 + int
345 + scan()                          /* scan next character, return literal next */
346 + {
347 +    register int  lnext = 0;
348 +
349      do {
350          if (linbuf[linepos] == '\0')
351              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
352                  nextc = EOF;
353              else {
354                  nextc = linbuf[0];
355 +                lineno++;
356                  linepos = 1;
357              }
358          else
359              nextc = linbuf[linepos++];
360 +        if (!lnext)
361 +                lnext = nextc;
362          if (nextc == '{') {
363              scan();
364              while (nextc != '}')
# Line 341 | Line 369 | scan()                         /* scan next character */
369              scan();
370          }
371      } while (isspace(nextc));
372 +    return(lnext);
373   }
374  
375  
376 + char *
377 + long2ascii(l)                         /* convert long to ascii */
378 + long  l;
379 + {
380 +    static char  buf[16];
381 +    register char  *cp;
382 +    int  neg = 0;
383 +
384 +    if (l == 0)
385 +        return("0");
386 +    if (l < 0) {
387 +        l = -l;
388 +        neg++;
389 +    }
390 +    cp = buf + sizeof(buf);
391 +    *--cp = '\0';
392 +    while (l) {
393 +        *--cp = l % 10 + '0';
394 +        l /= 10;
395 +    }
396 +    if (neg)
397 +        *--cp = '-';
398 +    return(cp);
399 + }
400 +
401 +
402   syntax(err)                     /* report syntax error and quit */
403   char  *err;
404   {
405      register int  i;
406  
407 +    if (infile != NULL || lineno != 0) {
408 +        if (infile != NULL) eputs(infile);
409 +        if (lineno != 0) {
410 +            eputs(infile != NULL ? ", line " : "line ");
411 +            eputs(long2ascii((long)lineno));
412 +        }
413 +        eputs(":\n");
414 +    }
415      eputs(linbuf);
416      if (linbuf[strlen(linbuf)-1] != '\n')
417          eputs("\n");
418      for (i = 0; i < linepos-1; i++)
419          eputs(linbuf[i] == '\t' ? "\t" : " ");
420      eputs("^ ");
358    if (infile != NULL) {
359        eputs(infile);
360        eputs(": ");
361    }
421      eputs(err);
422      eputs("\n");
423      quit(1);
# Line 366 | Line 425 | char  *err;
425  
426  
427   addekid(ep, ekid)                       /* add a child to ep */
428 < register EPNODE  *ep;
429 < EPNODE  *ekid;
428 > register EPNODE  *ep;
429 > EPNODE  *ekid;
430   {
431      if (ep->v.kid == NULL)
432          ep->v.kid = ekid;
# Line 380 | Line 439 | EPNODE  *ekid;
439   }
440  
441  
442 + #if  defined(VARIABLE) || defined(FUNCTION)
443   char *
444   getname()                       /* scan an identifier */
445   {
446 <    static char  str[MAXWORD+1];
447 <    register int  i;
446 >    static char  str[MAXWORD+1];
447 >    register int  i, lnext;
448  
449 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
450 <        str[i] = nextc;
449 >    lnext = nextc;
450 >    for (i = 0; i < MAXWORD && isid(lnext); i++, lnext = scan())
451 >        str[i] = lnext;
452      str[i] = '\0';
453 +    while (isid(lnext))         /* skip rest of name */
454 +        lnext = scan();
455  
456      return(str);
457   }
458 + #endif
459  
460  
461   int
462   getinum()                       /* scan a positive integer */
463   {
464 <    register int  n;
464 >    register int  n, lnext;
465  
466      n = 0;
467 <    while (isdigit(nextc)) {
468 <        n = n * 10 + nextc - '0';
469 <        scan();
467 >    lnext = nextc;
468 >    while (isdigit(lnext)) {
469 >        n = n * 10 + lnext - '0';
470 >        lnext = scan();
471      }
472      return(n);
473   }
# Line 411 | Line 476 | getinum()                      /* scan a positive integer */
476   double
477   getnum()                        /* scan a positive float */
478   {
479 <    register int  i;
479 >    register int  i, lnext;
480      char  str[MAXWORD+1];
481  
482      i = 0;
483 <    while (isdigit(nextc) && i < MAXWORD) {
484 <        str[i++] = nextc;
485 <        scan();
483 >    lnext = nextc;
484 >    while (isdigit(lnext) && i < MAXWORD) {
485 >        str[i++] = lnext;
486 >        lnext = scan();
487      }
488 <    if (nextc == '.' && i < MAXWORD) {
489 <        str[i++] = nextc;
490 <        scan();
491 <        while (isdigit(nextc) && i < MAXWORD) {
492 <            str[i++] = nextc;
493 <            scan();
488 >    if (lnext == '.' && i < MAXWORD) {
489 >        str[i++] = lnext;
490 >        lnext = scan();
491 >        while (isdigit(lnext) && i < MAXWORD) {
492 >            str[i++] = lnext;
493 >            lnext = scan();
494          }
495      }
496 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
497 <        str[i++] = nextc;
498 <        scan();
499 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
500 <            str[i++] = nextc;
501 <            scan();
496 >    if ((lnext == 'e' || lnext == 'E') && i < MAXWORD) {
497 >        str[i++] = lnext;
498 >        lnext = scan();
499 >        if ((lnext == '-' || lnext == '+') && i < MAXWORD) {
500 >            str[i++] = lnext;
501 >            lnext = scan();
502          }
503 <        while (isdigit(nextc) && i < MAXWORD) {
504 <            str[i++] = nextc;
505 <            scan();
503 >        while (isdigit(lnext) && i < MAXWORD) {
504 >            str[i++] = lnext;
505 >            lnext = scan();
506          }
507      }
508      str[i] = '\0';
# Line 447 | Line 513 | getnum()                       /* scan a positive float */
513  
514   EPNODE *
515   getE1()                         /* E1 -> E1 ADDOP E2 */
516 <                                /*       E2 */
516 >                                /*       E2 */
517   {
518      register EPNODE  *ep1, *ep2;
519  
# Line 458 | Line 524 | getE1()                                /* E1 -> E1 ADDOP E2 */
524          scan();
525          addekid(ep2, ep1);
526          addekid(ep2, getE2());
527 < #ifdef  RCONST
527 > #ifdef  RCONST
528          if (ep1->type == NUM && ep1->sibling->type == NUM)
529                  ep2 = rconst(ep2);
530   #endif
# Line 470 | Line 536 | getE1()                                /* E1 -> E1 ADDOP E2 */
536  
537   EPNODE *
538   getE2()                         /* E2 -> E2 MULOP E3 */
539 <                                /*       E3 */
539 >                                /*       E3 */
540   {
541      register EPNODE  *ep1, *ep2;
542  
# Line 481 | Line 547 | getE2()                                /* E2 -> E2 MULOP E3 */
547          scan();
548          addekid(ep2, ep1);
549          addekid(ep2, getE3());
550 < #ifdef  RCONST
550 > #ifdef  RCONST
551          if (ep1->type == NUM && ep1->sibling->type == NUM)
552                  ep2 = rconst(ep2);
553   #endif
# Line 492 | Line 558 | getE2()                                /* E2 -> E2 MULOP E3 */
558  
559  
560   EPNODE *
561 < getE3()                         /* E3 -> E3 ^ E4 */
562 <                                /*       E4 */
561 > getE3()                         /* E3 -> E4 ^ E3 */
562 >                                /*       E4 */
563   {
564      register EPNODE  *ep1, *ep2;
565  
566      ep1 = getE4();
567 <    while (nextc == '^') {
567 >    if (nextc == '^') {
568          ep2 = newnode();
569          ep2->type = nextc;
570          scan();
571          addekid(ep2, ep1);
572 <        addekid(ep2, getE4());
573 < #ifdef  RCONST
572 >        addekid(ep2, getE3());
573 > #ifdef  RCONST
574          if (ep1->type == NUM && ep1->sibling->type == NUM)
575                  ep2 = rconst(ep2);
576   #endif
577 <        ep1 = ep2;
577 >        return(ep2);
578      }
579      return(ep1);
580   }
# Line 516 | Line 582 | getE3()                                /* E3 -> E3 ^ E4 */
582  
583   EPNODE *
584   getE4()                         /* E4 -> ADDOP E5 */
585 <                                /*       E5 */
585 >                                /*       E5 */
586   {
587      register EPNODE  *ep1, *ep2;
588  
# Line 527 | Line 593 | getE4()                                /* E4 -> ADDOP E5 */
593                  ep2->v.num = -ep2->v.num;
594                  return(ep2);
595          }
596 +        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
597 +            efree((char *)ep2);
598 +            return(ep2->v.kid);
599 +        }
600          ep1 = newnode();
601          ep1->type = UMINUS;
602          addekid(ep1, ep2);
# Line 540 | Line 610 | getE4()                                /* E4 -> ADDOP E5 */
610  
611   EPNODE *
612   getE5()                         /* E5 -> (E1) */
613 <                                /*       VAR */
614 <                                /*       NUM */
615 <                                /*       $N */
616 <                                /*       FUNC(E1,..) */
617 <                                /*       ARG */
613 >                                /*       VAR */
614 >                                /*       NUM */
615 >                                /*       $N */
616 >                                /*       FUNC(E1,..) */
617 >                                /*       ARG */
618   {
619 <    int  i;
619 >    int  i;
620 >    char  *nam;
621      register EPNODE  *ep1, *ep2;
622  
623      if (nextc == '(') {
# Line 558 | Line 629 | getE5()                                /* E5 -> (E1) */
629          return(ep1);
630      }
631  
632 < #ifdef  INCHAN
632 > #ifdef  INCHAN
633      if (nextc == '$') {
634          scan();
635          ep1 = newnode();
# Line 569 | Line 640 | getE5()                                /* E5 -> (E1) */
640   #endif
641  
642   #if  defined(VARIABLE) || defined(FUNCTION)
643 <    if (isalpha(nextc)) {
644 <        ep1 = newnode();
574 <        ep1->type = VAR;
575 <        ep1->v.ln = varinsert(getname());
576 <
643 >    if (isalpha(nextc) || nextc == CNTXMARK) {
644 >        nam = getname();
645   #if  defined(VARIABLE) && defined(FUNCTION)
646 +        ep1 = NULL;
647          if (curfunc != NULL)
648              for (i = 1, ep2 = curfunc->v.kid->sibling;
649 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
650 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
582 <                    epfree(ep1);
649 >                                ep2 != NULL; i++, ep2 = ep2->sibling)
650 >                if (!strcmp(ep2->v.name, nam)) {
651                      ep1 = newnode();
652                      ep1->type = ARG;
653                      ep1->v.chan = i;
654                      break;
655                  }
656 +        if (ep1 == NULL)
657   #endif
658 < #ifdef  FUNCTION
658 >        {
659 >            ep1 = newnode();
660 >            ep1->type = VAR;
661 >            ep1->v.ln = varinsert(nam);
662 >        }
663 > #ifdef  FUNCTION
664          if (nextc == '(') {
665              ep2 = newnode();
666              ep2->type = FUNC;
# Line 600 | Line 674 | getE5()                                /* E5 -> (E1) */
674                  syntax("')' expected");
675              scan();
676          }
677 < #ifndef  VARIABLE
677 > #ifndef  VARIABLE
678          else
679              syntax("'(' expected");
680   #endif
681   #endif
682 + #ifdef  RCONST
683 +        if (isconstvar(ep1))
684 +            ep1 = rconst(ep1);
685 + #endif
686          return(ep1);
687      }
688   #endif
# Line 619 | Line 697 | getE5()                                /* E5 -> (E1) */
697   }
698  
699  
700 < #ifdef  RCONST
700 > #ifdef  RCONST
701   EPNODE *
702   rconst(epar)                    /* reduce a constant expression */
703 < register EPNODE  *epar;
703 > register EPNODE  *epar;
704   {
705      register EPNODE  *ep;
706  
# Line 631 | Line 709 | register EPNODE  *epar;
709      errno = 0;
710      ep->v.num = evalue(epar);
711      if (errno)
712 <        syntax("bad constant expression");
712 >        syntax("bad constant expression");
713      epfree(epar);
714  
715      return(ep);
716   }
717 +
718 +
719 + isconstvar(ep)                  /* is ep linked to a constant expression? */
720 + register EPNODE  *ep;
721 + {
722 + #ifdef  VARIABLE
723 +    register EPNODE  *ep1;
724 + #ifdef  FUNCTION
725 +
726 +    if (ep->type == FUNC) {
727 +        if (!isconstfun(ep->v.kid))
728 +                return(0);
729 +        for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
730 +            if (ep1->type != NUM && !isconstfun(ep1))
731 +                return(0);
732 +        return(1);
733 +    }
734 + #endif
735 +    if (ep->type != VAR)
736 +        return(0);
737 +    ep1 = ep->v.ln->def;
738 +    if (ep1 == NULL || ep1->type != ':')
739 +        return(0);
740 + #ifdef  FUNCTION
741 +    if (ep1->v.kid->type != SYM)
742 +        return(0);
743 + #endif
744 +    return(1);
745 + #else
746 +    return(ep->type == FUNC);
747 + #endif
748 + }
749 +
750 +
751 + #if  defined(FUNCTION) && defined(VARIABLE)
752 + isconstfun(ep)                  /* is ep linked to a constant function? */
753 + register EPNODE  *ep;
754 + {
755 +    register EPNODE  *dp;
756 +    register LIBR  *lp;
757 +
758 +    if (ep->type != VAR)
759 +        return(0);
760 +    if ((dp = ep->v.ln->def) != NULL && dp->v.kid->type == FUNC)
761 +        return(dp->type == ':');
762 +    if ((lp = ep->v.ln->lib) != NULL)
763 +        return(lp->atyp == ':');
764 +    return(0);
765 + }
766 + #endif
767   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines