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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines