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.2 by greg, Mon Apr 10 22:06:37 1989 UTC vs.
Revision 2.40 by greg, Fri Jun 19 22:33:45 2020 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1986 Regents of the University of California */
2
1   #ifndef lint
2 < static char SCCSid[] = "$SunId$ LBL";
2 > static const char       RCSid[] = "$Id$";
3   #endif
6
4   /*
5   *  Compute data values using expression parser
6   *
# Line 16 | Line 13 | static char SCCSid[] = "$SunId$ LBL";
13   *  1/29/87  Made variables conditional (VARIABLE)
14   *
15   *  5/19/88  Added constant subexpression elimination (RCONST)
16 + *
17 + *  2/19/03     Eliminated conditional compiles in favor of esupport extern.
18   */
19  
20 < #include  <stdio.h>
20 > #include "copyright.h"
21  
22   #include  <ctype.h>
24
23   #include  <errno.h>
24 + #include  <math.h>
25 + #include  <stdlib.h>
26  
27 + #include  "rtmisc.h"
28 + #include  "rtio.h"
29 + #include  "rterror.h"
30   #include  "calcomp.h"
31  
32 < #define  MAXLINE        256             /* maximum line length */
30 < #define  MAXWORD        64              /* maximum word length */
32 > #define  MAXLINE        256             /* maximum line length */
33  
34 < #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
34 > #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
35  
36 < #define  isid(c)        (isalnum(c) || (c) == '_' || (c) == '.')
36 > #define  isdecimal(c)   (isdigit(c) || (c) == '.')
37  
38 < #define  isdecimal(c)   (isdigit(c) || (c) == '.')
38 > static double  euminus(EPNODE *), eargument(EPNODE *), enumber(EPNODE *);
39 > static double  echannel(EPNODE *);
40 > static double  eadd(EPNODE *), esubtr(EPNODE *),
41 >               emult(EPNODE *), edivi(EPNODE *),
42 >               epow(EPNODE *);
43 > static double  ebotch(EPNODE *);
44  
45 < extern double  atof(), pow();
46 < 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;
45 > unsigned int  esupport =                /* what to support */
46 >                E_VARIABLE | E_FUNCTION ;
47  
48 + int  eofc = 0;                          /* optional end-of-file character */
49   int  nextc;                             /* lookahead character */
50  
51 < double  (*eoper[])() = {                /* expression operations */
51 > double  (*eoper[])(EPNODE *) = {        /* expression operations */
52          ebotch,
51 #ifdef  VARIABLE
53          evariable,
53 #else
54        ebotch,
55 #endif
54          enumber,
55          euminus,
58 #ifdef  INCHAN
56          echannel,
60 #else
61        ebotch,
62 #endif
63 #ifdef  FUNCTION
57          efunc,
58          eargument,
66 #else
59          ebotch,
60          ebotch,
69 #endif
70        ebotch,
71        ebotch,
61          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63          emult,
# Line 77 | Line 66 | double  (*eoper[])() = {               /* expression operations */
66          esubtr,
67          0,
68          edivi,
69 <        0,0,0,0,0,0,0,0,0,0,0,0,0,
69 >        0,0,0,0,0,0,0,0,0,0,
70          ebotch,
71 +        0,0,
72 +        ebotch,
73          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75          epow,
76   };
77  
87 static char  *infile;                   /* input file name */
78   static FILE  *infp;                     /* input file pointer */
79   static char  *linbuf;                   /* line buffer */
80 + static char  *infile;                   /* input file name */
81 + static int  lineno;                     /* input line number */
82   static int  linepos;                    /* position in buffer */
83  
84  
85   EPNODE *
86 < eparse(expr)                    /* parse an expression string */
87 < char  *expr;
86 > eparse(                 /* parse an expression string */
87 >    char  *expr
88 > )
89   {
90      EPNODE  *ep;
91  
92 <    initstr(NULL, expr);
100 < #if  defined(VARIABLE) && defined(FUNCTION)
92 >    initstr(expr, NULL, 0);
93      curfunc = NULL;
102 #endif
94      ep = getE1();
95      if (nextc != EOF)
96          syntax("unexpected character");
# Line 108 | Line 99 | char  *expr;
99  
100  
101   double
102 < eval(expr)                      /* evaluate an expression string */
103 < char  *expr;
102 > eval(                   /* evaluate an expression string */
103 >    char  *expr
104 > )
105   {
106 <    register EPNODE  *ep;
106 >    int  prev_support = esupport;
107 >    EPNODE  *ep;
108      double  rval;
109  
110 +    esupport &= ~E_RCONST;      /* don't bother reducing constant expr */
111      ep = eparse(expr);
112 +    esupport = prev_support;    /* as you were */
113      rval = evalue(ep);
114      epfree(ep);
115      return(rval);
116   }
117  
118  
119 < epfree(epar)                    /* free a parse tree */
120 < register EPNODE  *epar;
119 > int
120 > epcmp(                  /* compare two expressions for equivalence */
121 >    EPNODE  *ep1,
122 >    EPNODE  *ep2
123 > )
124   {
125 <    register EPNODE  *ep;
125 >        double  d;
126  
127 +        if (ep1->type != ep2->type)
128 +                return(1);
129 +
130 +        switch (ep1->type) {
131 +
132 +        case VAR:
133 +                return(ep1->v.ln != ep2->v.ln);
134 +
135 +        case NUM:
136 +                if (ep2->v.num == 0)
137 +                        return(ep1->v.num != 0);
138 +                d = ep1->v.num / ep2->v.num;
139 +                return((d > 1.000000000001) | (d < 0.999999999999));
140 +
141 +        case CHAN:
142 +        case ARG:
143 +                return(ep1->v.chan != ep2->v.chan);
144 +
145 +        case '=':
146 +        case ':':
147 +                return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling));
148 +
149 +        case CLKT:
150 +        case SYM:                       /* should never get this one */
151 +                return(0);
152 +
153 +        default:
154 +                ep1 = ep1->v.kid;
155 +                ep2 = ep2->v.kid;
156 +                while (ep1 != NULL) {
157 +                        if (ep2 == NULL)
158 +                                return(1);
159 +                        if (epcmp(ep1, ep2))
160 +                                return(1);
161 +                        ep1 = ep1->sibling;
162 +                        ep2 = ep2->sibling;
163 +                }
164 +                return(ep2 != NULL);
165 +        }
166 + }
167 +
168 +
169 + void
170 + epfree(                 /* free a parse tree */
171 +    EPNODE       *epar
172 + )
173 + {
174 +    EPNODE  *ep;
175 +
176      switch (epar->type) {
177  
131 #if  defined(VARIABLE) || defined(FUNCTION)
178          case VAR:
179              varfree(epar->v.ln);
180              break;
135 #endif
181              
182          case SYM:
183              freestr(epar->v.name);
# Line 141 | Line 186 | register EPNODE  *epar;
186          case NUM:
187          case CHAN:
188          case ARG:
189 <        case TICK:
189 >        case CLKT:
190              break;
191  
192          default:
193 <            for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
193 >            while ((ep = epar->v.kid) != NULL) {
194 >                epar->v.kid = ep->sibling;
195                  epfree(ep);
196 +            }
197              break;
198  
199      }
# Line 155 | Line 202 | register EPNODE  *epar;
202   }
203  
204                                  /* the following used to be a switch */
158 #ifdef  FUNCTION
205   static double
206 < eargument(ep)
207 < EPNODE  *ep;
206 > eargument(
207 >    EPNODE      *ep
208 > )
209   {
210      return(argument(ep->v.chan));
211   }
165 #endif
212  
213   static double
214 < enumber(ep)
215 < EPNODE  *ep;
214 > enumber(
215 >    EPNODE      *ep
216 > )
217   {
218      return(ep->v.num);
219   }
220  
221   static double
222 < euminus(ep)
223 < EPNODE  *ep;
222 > euminus(
223 >    EPNODE      *ep
224 > )
225   {
226 <    register EPNODE  *ep1 = ep->v.kid;
226 >    EPNODE  *ep1 = ep->v.kid;
227  
228      return(-evalue(ep1));
229   }
230  
183 #ifdef  INCHAN
231   static double
232 < echannel(ep)
233 < EPNODE  *ep;
232 > echannel(
233 >    EPNODE      *ep
234 > )
235   {
236      return(chanvalue(ep->v.chan));
237   }
190 #endif
238  
239   static double
240 < eadd(ep)
241 < EPNODE  *ep;
240 > eadd(
241 >    EPNODE      *ep
242 > )
243   {
244 <    register EPNODE  *ep1 = ep->v.kid;
244 >    EPNODE  *ep1 = ep->v.kid;
245  
246      return(evalue(ep1) + evalue(ep1->sibling));
247   }
248  
249   static double
250 < esubtr(ep)
251 < EPNODE  *ep;
250 > esubtr(
251 >    EPNODE      *ep
252 > )
253   {
254 <    register EPNODE  *ep1 = ep->v.kid;
254 >    EPNODE  *ep1 = ep->v.kid;
255  
256      return(evalue(ep1) - evalue(ep1->sibling));
257   }
258  
259   static double
260 < emult(ep)
261 < EPNODE  *ep;
260 > emult(
261 >    EPNODE      *ep
262 > )
263   {
264 <    register EPNODE  *ep1 = ep->v.kid;
264 >    EPNODE  *ep1 = ep->v.kid;
265  
266      return(evalue(ep1) * evalue(ep1->sibling));
267   }
268  
269   static double
270 < edivi(ep)
271 < EPNODE  *ep;
270 > edivi(
271 >    EPNODE      *ep
272 > )
273   {
274 <    register EPNODE  *ep1 = ep->v.kid;
274 >    EPNODE  *ep1 = ep->v.kid;
275      double  d;
276  
277      d = evalue(ep1->sibling);
# Line 233 | Line 284 | EPNODE  *ep;
284   }
285  
286   static double
287 < epow(ep)
288 < EPNODE  *ep;
287 > epow(
288 >    EPNODE      *ep
289 > )
290   {
291 <    register EPNODE  *ep1 = ep->v.kid;
291 >    EPNODE  *ep1 = ep->v.kid;
292      double  d;
293 <    int  lasterrno;
293 >    int  lasterrno;
294  
295      lasterrno = errno;
296      errno = 0;
297      d = pow(evalue(ep1), evalue(ep1->sibling));
298 < #ifdef  IEEE
299 <    if (!finite(d))
300 <        errno = EDOM;
298 > #ifdef  isnan
299 >    if (errno == 0) {
300 >        if (isnan(d))
301 >            errno = EDOM;
302 >        else if (isinf(d))
303 >            errno = ERANGE;
304 >    }
305   #endif
306 <    if (errno) {
306 >    if (errno == EDOM || errno == ERANGE) {
307          wputs("Illegal power\n");
308          return(0.0);
309      }
# Line 256 | Line 312 | EPNODE  *ep;
312   }
313  
314   static double
315 < ebotch(ep)
316 < EPNODE  *ep;
315 > ebotch(
316 >    EPNODE      *ep
317 > )
318   {
319      eputs("Bad expression!\n");
320      quit(1);
321 +        return 0.0; /* pro forma return */
322   }
323  
324  
325   EPNODE *
326 < ekid(ep, n)                     /* return pointer to a node's nth kid */
327 < register EPNODE  *ep;
328 < register int  n;
326 > ekid(                   /* return pointer to a node's nth kid */
327 >    EPNODE       *ep,
328 >    int  n
329 > )
330   {
331  
332      for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
# Line 279 | Line 338 | register int  n;
338  
339  
340   int
341 < nekids(ep)                      /* return # of kids for node ep */
342 < register EPNODE  *ep;
341 > nekids(                 /* return # of kids for node ep */
342 >    EPNODE       *ep
343 > )
344   {
345 <    register int  n = 0;
345 >    int  n = 0;
346  
347      for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
348          n++;
# Line 291 | Line 351 | register EPNODE  *ep;
351   }
352  
353  
354 < initfile(file, fp)              /* prepare input file */
355 < char  *file;
356 < FILE  *fp;
354 > void
355 > initfile(               /* prepare input file */
356 >    FILE  *fp,
357 >    char  *fn,
358 >    int  ln
359 > )
360   {
361 <    static char  inpbuf[MAXLINE];
361 >    static char  inpbuf[MAXLINE];
362  
300    infile = file;
363      infp = fp;
364      linbuf = inpbuf;
365 +    infile = fn;
366 +    lineno = ln;
367      linepos = 0;
368      inpbuf[0] = '\0';
369      scan();
370   }
371  
372  
373 < initstr(file, s)                /* prepare input string */
374 < char  *file;
375 < char  *s;
373 > void
374 > initstr(                /* prepare input string */
375 >    char  *s,
376 >    char  *fn,
377 >    int  ln
378 > )
379   {
313    infile = file;
380      infp = NULL;
381 +    infile = fn;
382 +    lineno = ln;
383      linbuf = s;
384      linepos = 0;
385      scan();
386   }
387  
388  
389 < scan()                          /* scan next character */
389 > void
390 > getscanpos(     /* return current scan position */
391 >    char  **fnp,
392 >    int  *lnp,
393 >    char  **spp,
394 >    FILE  **fpp
395 > )
396   {
397 +    if (fnp != NULL) *fnp = infile;
398 +    if (lnp != NULL) *lnp = lineno;
399 +    if (spp != NULL) *spp = linbuf+linepos;
400 +    if (fpp != NULL) *fpp = infp;
401 + }
402 +
403 +
404 + int
405 + scan(void)              /* scan next character, return literal next */
406 + {
407 +    int  lnext = 0;
408 +
409      do {
410          if (linbuf[linepos] == '\0')
411              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
412                  nextc = EOF;
413              else {
414                  nextc = linbuf[0];
415 +                lineno++;
416                  linepos = 1;
417              }
418          else
419              nextc = linbuf[linepos++];
420 +        if (!lnext)
421 +                lnext = nextc;
422 +        if (nextc == eofc) {
423 +                nextc = EOF;
424 +                break;
425 +        }
426          if (nextc == '{') {
427              scan();
428              while (nextc != '}')
# Line 340 | Line 433 | scan()                         /* scan next character */
433              scan();
434          }
435      } while (isspace(nextc));
436 +    return(lnext);
437   }
438  
439  
440 < syntax(err)                     /* report syntax error and quit */
441 < char  *err;
440 > char *
441 > long2ascii(                           /* convert long to ascii */
442 >    long  l
443 > )
444   {
445 <    register int  i;
445 >    static char  buf[16];
446 >    char  *cp;
447 >    int  neg = 0;
448  
449 +    if (l == 0)
450 +        return("0");
451 +    if (l < 0) {
452 +        l = -l;
453 +        neg++;
454 +    }
455 +    cp = buf + sizeof(buf);
456 +    *--cp = '\0';
457 +    while (l) {
458 +        *--cp = l % 10 + '0';
459 +        l /= 10;
460 +    }
461 +    if (neg)
462 +        *--cp = '-';
463 +    return(cp);
464 + }
465 +
466 +
467 + void
468 + syntax(                 /* report syntax error and quit */
469 +    char  *err
470 + )
471 + {
472 +    int  i;
473 +
474 +    if (infile != NULL || lineno != 0) {
475 +        if (infile != NULL) eputs(infile);
476 +        if (lineno != 0) {
477 +            eputs(infile != NULL ? ", line " : "line ");
478 +            eputs(long2ascii((long)lineno));
479 +        }
480 +        eputs(":\n");
481 +    }
482      eputs(linbuf);
483 <    if (linbuf[0] == '\0' || linbuf[strlen(linbuf)-1] != '\n')
483 >    if (linbuf[strlen(linbuf)-1] != '\n')
484          eputs("\n");
485      for (i = 0; i < linepos-1; i++)
486          eputs(linbuf[i] == '\t' ? "\t" : " ");
487      eputs("^ ");
357    if (infile != NULL) {
358        eputs(infile);
359        eputs(": ");
360    }
488      eputs(err);
489      eputs("\n");
490      quit(1);
491   }
492  
493  
494 < addekid(ep, ekid)                       /* add a child to ep */
495 < register EPNODE  *ep;
496 < EPNODE  *ekid;
494 > void
495 > addekid(                        /* add a child to ep */
496 >    EPNODE       *ep,
497 >    EPNODE      *ekid
498 > )
499   {
500      if (ep->v.kid == NULL)
501          ep->v.kid = ekid;
# Line 380 | Line 509 | EPNODE  *ekid;
509  
510  
511   char *
512 < getname()                       /* scan an identifier */
512 > getname(void)                   /* scan an identifier */
513   {
514 <    static char  str[MAXWORD+1];
515 <    register int  i;
514 >    static char  str[RMAXWORD+1];
515 >    int  i, lnext;
516  
517 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
518 <        str[i] = nextc;
517 >    lnext = nextc;
518 >    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
519 >        str[i] = lnext;
520      str[i] = '\0';
521 +    while (isid(lnext))         /* skip rest of name */
522 +        lnext = scan();
523  
524      return(str);
525   }
526  
527  
528   int
529 < getinum()                       /* scan a positive integer */
529 > getinum(void)                   /* scan a positive integer */
530   {
531 <    register int  n;
531 >    int  n, lnext;
532  
533      n = 0;
534 <    while (isdigit(nextc)) {
535 <        n = n * 10 + nextc - '0';
536 <        scan();
534 >    lnext = nextc;
535 >    while (isdigit(lnext)) {
536 >        n = n * 10 + lnext - '0';
537 >        lnext = scan();
538      }
539      return(n);
540   }
541  
542  
543   double
544 < getnum()                        /* scan a positive float */
544 > getnum(void)                    /* scan a positive float */
545   {
546 <    register int  i;
547 <    char  str[MAXWORD+1];
546 >    int  i, lnext;
547 >    char  str[RMAXWORD+1];
548  
549      i = 0;
550 <    while (isdigit(nextc) && i < MAXWORD) {
551 <        str[i++] = nextc;
552 <        scan();
550 >    lnext = nextc;
551 >    while (isdigit(lnext) && i < RMAXWORD) {
552 >        str[i++] = lnext;
553 >        lnext = scan();
554      }
555 <    if (nextc == '.' && i < MAXWORD) {
556 <        str[i++] = nextc;
557 <        scan();
558 <        while (isdigit(nextc) && i < MAXWORD) {
559 <            str[i++] = nextc;
560 <            scan();
555 >    if (lnext == '.' && i < RMAXWORD) {
556 >        str[i++] = lnext;
557 >        lnext = scan();
558 >        if (i == 1 && !isdigit(lnext))
559 >            syntax("badly formed number");
560 >        while (isdigit(lnext) && i < RMAXWORD) {
561 >            str[i++] = lnext;
562 >            lnext = scan();
563          }
564      }
565 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
566 <        str[i++] = nextc;
567 <        scan();
568 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
569 <            str[i++] = nextc;
570 <            scan();
565 >    if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
566 >        str[i++] = lnext;
567 >        lnext = scan();
568 >        if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
569 >            str[i++] = lnext;
570 >            lnext = scan();
571          }
572 <        while (isdigit(nextc) && i < MAXWORD) {
573 <            str[i++] = nextc;
574 <            scan();
572 >        if (!isdigit(lnext))
573 >            syntax("missing exponent");
574 >        while (isdigit(lnext) && i < RMAXWORD) {
575 >            str[i++] = lnext;
576 >            lnext = scan();
577          }
578      }
579      str[i] = '\0';
# Line 445 | Line 583 | getnum()                       /* scan a positive float */
583  
584  
585   EPNODE *
586 < getE1()                         /* E1 -> E1 ADDOP E2 */
587 <                                /*       E2 */
586 > getE1(void)                     /* E1 -> E1 ADDOP E2 */
587 >                                /*       E2 */
588   {
589 <    register EPNODE  *ep1, *ep2;
589 >    EPNODE  *ep1, *ep2;
590  
591      ep1 = getE2();
592      while (nextc == '+' || nextc == '-') {
# Line 457 | Line 595 | getE1()                                /* E1 -> E1 ADDOP E2 */
595          scan();
596          addekid(ep2, ep1);
597          addekid(ep2, getE2());
598 < #ifdef  RCONST
599 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
598 >        if (esupport&E_RCONST &&
599 >                        ep1->type == NUM && ep1->sibling->type == NUM)
600                  ep2 = rconst(ep2);
463 #endif
601          ep1 = ep2;
602      }
603      return(ep1);
# Line 468 | Line 605 | getE1()                                /* E1 -> E1 ADDOP E2 */
605  
606  
607   EPNODE *
608 < getE2()                         /* E2 -> E2 MULOP E3 */
609 <                                /*       E3 */
608 > getE2(void)                     /* E2 -> E2 MULOP E3 */
609 >                                /*       E3 */
610   {
611 <    register EPNODE  *ep1, *ep2;
611 >    EPNODE  *ep1, *ep2;
612  
613      ep1 = getE3();
614      while (nextc == '*' || nextc == '/') {
# Line 480 | Line 617 | getE2()                                /* E2 -> E2 MULOP E3 */
617          scan();
618          addekid(ep2, ep1);
619          addekid(ep2, getE3());
620 < #ifdef  RCONST
621 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
622 <                ep2 = rconst(ep2);
623 < #endif
620 >        if (esupport&E_RCONST) {
621 >                EPNODE  *ep3 = ep1->sibling;
622 >                if (ep1->type == NUM && ep3->type == NUM) {
623 >                        ep2 = rconst(ep2);
624 >                } else if (ep3->type == NUM) {
625 >                        if (ep2->type == '/') {
626 >                                if (ep3->v.num == 0)
627 >                                        syntax("divide by zero constant");
628 >                                ep2->type = '*';        /* for speed */
629 >                                ep3->v.num = 1./ep3->v.num;
630 >                        } else if (ep3->v.num == 0) {
631 >                                ep1->sibling = NULL;    /* (E2 * 0) */
632 >                                epfree(ep2);
633 >                                ep2 = ep3;
634 >                        }
635 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
636 >                        epfree(ep3);            /* (0 * E3) or (0 / E3) */
637 >                        ep1->sibling = NULL;
638 >                        efree((char *)ep2);
639 >                        ep2 = ep1;
640 >                }
641 >        }
642          ep1 = ep2;
643      }
644      return(ep1);
# Line 491 | Line 646 | getE2()                                /* E2 -> E2 MULOP E3 */
646  
647  
648   EPNODE *
649 < getE3()                         /* E3 -> E3 ^ E4 */
650 <                                /*       E4 */
649 > getE3(void)                     /* E3 -> E4 ^ E3 */
650 >                                /*       E4 */
651   {
652 <    register EPNODE  *ep1, *ep2;
652 >        EPNODE  *ep1, *ep2;
653  
654 <    ep1 = getE4();
655 <    while (nextc == '^') {
654 >        ep1 = getE4();
655 >        if (nextc != '^')
656 >                return(ep1);
657          ep2 = newnode();
658          ep2->type = nextc;
659          scan();
660          addekid(ep2, ep1);
661 <        addekid(ep2, getE4());
662 < #ifdef  RCONST
663 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
664 <                ep2 = rconst(ep2);
665 < #endif
666 <        ep1 = ep2;
667 <    }
668 <    return(ep1);
661 >        addekid(ep2, getE3());
662 >        if (esupport&E_RCONST) {
663 >                EPNODE  *ep3 = ep1->sibling;
664 >                if (ep1->type == NUM && ep3->type == NUM) {
665 >                        ep2 = rconst(ep2);
666 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
667 >                        epfree(ep3);            /* (0 ^ E3) */
668 >                        ep1->sibling = NULL;
669 >                        efree((char *)ep2);
670 >                        ep2 = ep1;
671 >                } else if ((ep3->type == NUM && ep3->v.num == 0) ||
672 >                                (ep1->type == NUM && ep1->v.num == 1)) {
673 >                        epfree(ep2);            /* (E4 ^ 0) or (1 ^ E3) */
674 >                        ep2 = newnode();
675 >                        ep2->type = NUM;
676 >                        ep2->v.num = 1;
677 >                } else if (ep3->type == NUM && ep3->v.num == 1) {
678 >                        efree((char *)ep3);     /* (E4 ^ 1) */
679 >                        ep1->sibling = NULL;
680 >                        efree((char *)ep2);
681 >                        ep2 = ep1;
682 >                }
683 >        }
684 >        return(ep2);
685   }
686  
687  
688   EPNODE *
689 < getE4()                         /* E4 -> ADDOP E5 */
690 <                                /*       E5 */
689 > getE4(void)                     /* E4 -> ADDOP E5 */
690 >                                /*       E5 */
691   {
692 <    register EPNODE  *ep1;
692 >    EPNODE  *ep1, *ep2;
693  
694      if (nextc == '-') {
695          scan();
696 <        ep1 = newnode();
697 < #ifndef  RCONST
698 <        if (isdecimal(nextc)) {
699 <            ep1->type = NUM;
700 <            ep1->v.num = -getnum();
696 >        ep2 = getE5();
697 >        if (ep2->type == NUM) {
698 >                ep2->v.num = -ep2->v.num;
699 >                return(ep2);
700 >        }
701 >        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
702 >            ep1 = ep2->v.kid;
703 >            efree((char *)ep2);
704              return(ep1);
705          }
706 < #endif
706 >        ep1 = newnode();
707          ep1->type = UMINUS;
708 <        addekid(ep1, getE5());
534 < #ifdef  RCONST
535 <        if (ep1->v.kid->type == NUM)
536 <                ep1 = rconst(ep1);
537 < #endif
708 >        addekid(ep1, ep2);
709          return(ep1);
710      }
711      if (nextc == '+')
# Line 544 | Line 715 | getE4()                                /* E4 -> ADDOP E5 */
715  
716  
717   EPNODE *
718 < getE5()                         /* E5 -> (E1) */
719 <                                /*       VAR */
720 <                                /*       NUM */
721 <                                /*       $N */
722 <                                /*       FUNC(E1,..) */
723 <                                /*       ARG */
718 > getE5(void)                     /* E5 -> (E1) */
719 >                                /*       VAR */
720 >                                /*       NUM */
721 >                                /*       $N */
722 >                                /*       FUNC(E1,..) */
723 >                                /*       ARG */
724   {
725 <    int  i;
726 <    register EPNODE  *ep1, *ep2;
725 >        int      i;
726 >        char  *nam;
727 >        EPNODE  *ep1, *ep2;
728  
729 <    if (nextc == '(') {
730 <        scan();
731 <        ep1 = getE1();
732 <        if (nextc != ')')
733 <            syntax("')' expected");
734 <        scan();
735 <        return(ep1);
736 <    }
729 >        if (nextc == '(') {
730 >                scan();
731 >                ep1 = getE1();
732 >                if (nextc != ')')
733 >                        syntax("')' expected");
734 >                scan();
735 >                return(ep1);
736 >        }
737  
738 < #ifdef  INCHAN
739 <    if (nextc == '$') {
740 <        scan();
741 <        ep1 = newnode();
742 <        ep1->type = CHAN;
743 <        ep1->v.chan = getinum();
744 <        return(ep1);
573 <    }
574 < #endif
738 >        if (esupport&E_INCHAN && nextc == '$') {
739 >                scan();
740 >                ep1 = newnode();
741 >                ep1->type = CHAN;
742 >                ep1->v.chan = getinum();
743 >                return(ep1);
744 >        }
745  
746 < #if  defined(VARIABLE) || defined(FUNCTION)
747 <    if (isalpha(nextc)) {
748 <        ep1 = newnode();
749 <        ep1->type = VAR;
750 <        ep1->v.ln = varinsert(getname());
751 <
752 < #if  defined(VARIABLE) && defined(FUNCTION)
753 <        if (curfunc != NULL)
754 <            for (i = 1, ep2 = curfunc->v.kid->sibling;
755 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
756 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
757 <                    epfree(ep1);
758 <                    ep1 = newnode();
759 <                    ep1->type = ARG;
760 <                    ep1->v.chan = i;
761 <                    break;
746 >        if (esupport&(E_VARIABLE|E_FUNCTION) &&
747 >                        (isalpha(nextc) || nextc == CNTXMARK)) {
748 >                nam = getname();
749 >                ep1 = NULL;
750 >                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
751 >                                && curfunc != NULL)
752 >                        for (i = 1, ep2 = curfunc->v.kid->sibling;
753 >                                        ep2 != NULL; i++, ep2 = ep2->sibling)
754 >                                if (!strcmp(ep2->v.name, nam)) {
755 >                                        ep1 = newnode();
756 >                                        ep1->type = ARG;
757 >                                        ep1->v.chan = i;
758 >                                        break;
759 >                                }
760 >                if (ep1 == NULL) {
761 >                        ep1 = newnode();
762 >                        ep1->type = VAR;
763 >                        ep1->v.ln = varinsert(nam);
764                  }
765 < #endif
766 < #ifdef  FUNCTION
767 <        if (nextc == '(') {
768 <            ep2 = newnode();
769 <            ep2->type = FUNC;
770 <            addekid(ep2, ep1);
771 <            ep1 = ep2;
772 <            do {
773 <                scan();
774 <                addekid(ep1, getE1());
775 <            } while (nextc == ',');
776 <            if (nextc != ')')
777 <                syntax("')' expected");
778 <            scan();
765 >                if (esupport&E_FUNCTION && nextc == '(') {
766 >                        ep2 = newnode();
767 >                        ep2->type = FUNC;
768 >                        addekid(ep2, ep1);
769 >                        ep1 = ep2;
770 >                        do {
771 >                                scan();
772 >                                addekid(ep1, getE1());
773 >                        } while (nextc == ',');
774 >                        if (nextc != ')')
775 >                                syntax("')' expected");
776 >                        scan();
777 >                } else if (!(esupport&E_VARIABLE))
778 >                        syntax("'(' expected");
779 >                if (esupport&E_RCONST && isconstvar(ep1))
780 >                        ep1 = rconst(ep1);
781 >                return(ep1);
782          }
608 #ifndef  VARIABLE
609        else
610            syntax("'(' expected");
611 #endif
612 #endif
613        return(ep1);
614    }
615 #endif
783  
784 <    if (isdecimal(nextc)) {
785 <        ep1 = newnode();
786 <        ep1->type = NUM;
787 <        ep1->v.num = getnum();
788 <        return(ep1);
789 <    }
790 <    syntax("unexpected character");
784 >        if (isdecimal(nextc)) {
785 >                ep1 = newnode();
786 >                ep1->type = NUM;
787 >                ep1->v.num = getnum();
788 >                return(ep1);
789 >        }
790 >        syntax("unexpected character");
791 >        return NULL; /* pro forma return */
792   }
793  
794  
627 #ifdef  RCONST
795   EPNODE *
796 < rconst(epar)                    /* reduce a constant expression */
797 < register EPNODE  *epar;
796 > rconst(                 /* reduce a constant expression */
797 >    EPNODE       *epar
798 > )
799   {
800 <    register EPNODE  *ep;
800 >    EPNODE  *ep;
801  
802      ep = newnode();
803      ep->type = NUM;
804      errno = 0;
805      ep->v.num = evalue(epar);
806 <    if (errno)
807 <        syntax("bad constant expression");
806 >    if (errno == EDOM || errno == ERANGE)
807 >        syntax("bad constant expression");
808      epfree(epar);
809  
810      return(ep);
811   }
812 < #endif
812 >
813 >
814 > int
815 > isconstvar(                     /* is ep linked to a constant expression? */
816 >    EPNODE       *ep
817 > )
818 > {
819 >    EPNODE  *ep1;
820 >
821 >    if (esupport&E_FUNCTION && ep->type == FUNC) {
822 >        if (!isconstfun(ep->v.kid))
823 >                return(0);
824 >        for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
825 >            if (ep1->type != NUM && !isconstfun(ep1))
826 >                return(0);
827 >        return(1);
828 >    }
829 >    if (ep->type != VAR)
830 >        return(0);
831 >    ep1 = ep->v.ln->def;
832 >    if (ep1 == NULL || ep1->type != ':')
833 >        return(0);
834 >    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
835 >        return(0);
836 >    return(1);
837 > }
838 >
839 >
840 > int
841 > isconstfun(                     /* is ep linked to a constant function? */
842 >    EPNODE       *ep
843 > )
844 > {
845 >    EPNODE  *dp;
846 >    LIBR  *lp;
847 >
848 >    if (ep->type != VAR)
849 >        return(0);
850 >    if ((dp = ep->v.ln->def) != NULL) {
851 >        if (dp->v.kid->type == FUNC)
852 >            return(dp->type == ':');
853 >        else
854 >            return(0);          /* don't identify masked library functions */
855 >    }
856 >    if ((lp = ep->v.ln->lib) != NULL)
857 >        return(lp->atyp == ':');
858 >    return(0);
859 > }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines