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.7 by greg, Sat Sep 26 08:13:32 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;
42 < extern double  efunc(), evariable(), enumber(), euminus(), echannel();
43 < extern double  eargument(), eadd(), esubtr(), emult(), edivi(), epow();
44 < extern double  ebotch();
45 < extern int  errno;
42 > extern double  efunc(), evariable();
43 > static double  euminus(), echannel(), eargument(), enumber();
44 > static double  eadd(), esubtr(), emult(), edivi(), epow();
45 > static double  ebotch();
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 77 | 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,
87   };
88  
87 static char  *infile;                   /* input file name */
89   static FILE  *infp;                     /* input file pointer */
90   static char  *linbuf;                   /* line buffer */
91 + static char  *infile;                   /* input file name */
92 + static int  lineno;                     /* input line number */
93   static int  linepos;                    /* position in buffer */
94  
95  
# Line 96 | Line 99 | char  *expr;
99   {
100      EPNODE  *ep;
101  
102 <    initstr(NULL, expr);
102 >    initstr(expr, NULL, 0);
103   #if  defined(VARIABLE) && defined(FUNCTION)
104      curfunc = NULL;
105   #endif
# Line 122 | 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 132 | Line 135 | register EPNODE  *epar;
135          case VAR:
136              varfree(epar->v.ln);
137              break;
135 #endif
138              
139          case SYM:
140              freestr(epar->v.name);
141              break;
142 + #endif
143  
144          case NUM:
145          case CHAN:
# Line 155 | 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 166 | 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 191 | 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 200 | 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 209 | 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 218 | 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 234 | 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 257 | 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 266 | 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 280 | 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 291 | Line 294 | register EPNODE  *ep;
294   }
295  
296  
297 < initfile(file, fp)              /* prepare input file */
295 < char  *file;
297 > initfile(fp, fn, ln)            /* prepare input file */
298   FILE  *fp;
299 + char  *fn;
300 + int  ln;
301   {
302 <    static char  inpbuf[MAXLINE];
302 >    static char  inpbuf[MAXLINE];
303  
300    infile = file;
304      infp = fp;
305      linbuf = inpbuf;
306 +    infile = fn;
307 +    lineno = ln;
308      linepos = 0;
309      inpbuf[0] = '\0';
310      scan();
311   }
312  
313  
314 < initstr(file, s)                /* prepare input string */
310 < char  *file;
314 > initstr(s, fn, ln)              /* prepare input string */
315   char  *s;
316 + char  *fn;
317 + int  ln;
318   {
313    infile = file;
319      infp = NULL;
320 +    infile = fn;
321 +    lineno = ln;
322      linbuf = s;
323      linepos = 0;
324      scan();
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)
349                  nextc = EOF;
350              else {
351                  nextc = linbuf[0];
352 +                lineno++;
353                  linepos = 1;
354              }
355          else
356              nextc = linbuf[linepos++];
357 +        if (!lnext)
358 +                lnext = nextc;
359          if (nextc == '{') {
360              scan();
361              while (nextc != '}')
# Line 340 | Line 366 | scan()                         /* scan next character */
366              scan();
367          }
368      } while (isspace(nextc));
369 +    return(lnext);
370   }
371  
372  
373 + char *
374 + ltoa(l)                         /* convert long to ascii */
375 + long  l;
376 + {
377 +    static char  buf[16];
378 +    register char  *cp;
379 +    int  neg = 0;
380 +
381 +    if (l == 0)
382 +        return("0");
383 +    if (l < 0) {
384 +        l = -l;
385 +        neg++;
386 +    }
387 +    cp = buf + sizeof(buf);
388 +    *--cp = '\0';
389 +    while (l) {
390 +        *--cp = l % 10 + '0';
391 +        l /= 10;
392 +    }
393 +    if (neg)
394 +        *--cp = '-';
395 +    return(cp);
396 + }
397 +
398 +
399   syntax(err)                     /* report syntax error and quit */
400   char  *err;
401   {
402      register int  i;
403  
404 +    if (infile != NULL || lineno != 0) {
405 +        if (infile != NULL) eputs(infile);
406 +        if (lineno != 0) {
407 +            eputs(infile != NULL ? ", line " : "line ");
408 +            eputs(ltoa((long)lineno));
409 +        }
410 +        eputs(":\n");
411 +    }
412      eputs(linbuf);
413 <    if (linbuf[0] == '\0' || linbuf[strlen(linbuf)-1] != '\n')
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("^ ");
357    if (infile != NULL) {
358        eputs(infile);
359        eputs(": ");
360    }
418      eputs(err);
419      eputs("\n");
420      quit(1);
# Line 365 | 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 379 | 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 410 | 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 446 | 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 457 | 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 469 | 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 480 | 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 491 | 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 515 | 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 526 | 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 539 | 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 557 | 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 568 | Line 637 | getE5()                                /* E5 -> (E1) */
637   #endif
638  
639   #if  defined(VARIABLE) || defined(FUNCTION)
640 <    if (isalpha(nextc)) {
641 <        ep1 = newnode();
573 <        ep1->type = VAR;
574 <        ep1->v.ln = varinsert(getname());
575 <
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)) {
581 <                    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 599 | 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 618 | 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 630 | 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