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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines