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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines