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.5 by greg, Tue Jun 26 09:15:11 1990 UTC vs.
Revision 2.30 by greg, Tue May 17 17:51:51 2005 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 78 | 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  
88 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);
101 < #if  defined(VARIABLE) && defined(FUNCTION)
94 >    initstr(expr, NULL, 0);
95      curfunc = NULL;
103 #endif
96      ep = getE1();
97      if (nextc != EOF)
98          syntax("unexpected character");
# Line 109 | 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;
109      double  rval;
# Line 122 | 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 >    register EPNODE  *ep1,
121 >    register EPNODE  *ep2
122 > )
123   {
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 TICK:
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 +    register EPNODE      *epar
171 + )
172 + {
173      register EPNODE  *ep;
174  
175      switch (epar->type) {
176  
132 #if  defined(VARIABLE) || defined(FUNCTION)
177          case VAR:
178              varfree(epar->v.ln);
179              break;
136 #endif
180              
181          case SYM:
182              freestr(epar->v.name);
# Line 146 | Line 189 | register EPNODE  *epar;
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 156 | Line 201 | register EPNODE  *epar;
201   }
202  
203                                  /* the following used to be a switch */
159 #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   }
166 #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;
226  
227      return(-evalue(ep1));
228   }
229  
184 #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   }
191 #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;
244  
# Line 200 | Line 246 | EPNODE  *ep;
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;
254  
# Line 209 | Line 256 | EPNODE  *ep;
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;
264  
# Line 218 | Line 266 | EPNODE  *ep;
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;
274      double  d;
# Line 234 | 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;
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
297 > #ifdef  IEEE
298      if (!finite(d))
299          errno = EDOM;
300   #endif
301 <    if (errno) {
301 >    if (errno == EDOM || errno == ERANGE) {
302          wputs("Illegal power\n");
303          return(0.0);
304      }
# Line 257 | Line 307 | EPNODE  *ep;
307   }
308  
309   static double
310 < ebotch(ep)
311 < EPNODE  *ep;
310 > ebotch(
311 >    EPNODE      *ep
312 > )
313   {
314      eputs("Bad expression!\n");
315      quit(1);
316 +        return 0.0; /* pro forma return */
317   }
318  
319  
320   EPNODE *
321 < ekid(ep, n)                     /* return pointer to a node's nth kid */
322 < register EPNODE  *ep;
323 < register int  n;
321 > ekid(                   /* return pointer to a node's nth kid */
322 >    register EPNODE      *ep,
323 >    register int  n
324 > )
325   {
326  
327      for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
# Line 280 | Line 333 | register int  n;
333  
334  
335   int
336 < nekids(ep)                      /* return # of kids for node ep */
337 < register EPNODE  *ep;
336 > nekids(                 /* return # of kids for node ep */
337 >    register EPNODE      *ep
338 > )
339   {
340      register int  n = 0;
341  
# Line 292 | Line 346 | register EPNODE  *ep;
346   }
347  
348  
349 < initfile(file, fp)              /* prepare input file */
350 < char  *file;
351 < FILE  *fp;
349 > void
350 > initfile(               /* prepare input file */
351 >    FILE  *fp,
352 >    char  *fn,
353 >    int  ln
354 > )
355   {
356 <    static char  inpbuf[MAXLINE];
356 >    static char  inpbuf[MAXLINE];
357  
301    infile = file;
358      infp = fp;
359      linbuf = inpbuf;
360 +    infile = fn;
361 +    lineno = ln;
362      linepos = 0;
363      inpbuf[0] = '\0';
364      scan();
365   }
366  
367  
368 < initstr(file, s)                /* prepare input string */
369 < char  *file;
370 < char  *s;
368 > void
369 > initstr(                /* prepare input string */
370 >    char  *s,
371 >    char  *fn,
372 >    int  ln
373 > )
374   {
314    infile = file;
375      infp = NULL;
376 +    infile = fn;
377 +    lineno = ln;
378      linbuf = s;
379      linepos = 0;
380      scan();
381   }
382  
383  
384 < scan()                          /* scan next character */
384 > void
385 > getscanpos(     /* return current scan position */
386 >    char  **fnp,
387 >    int  *lnp,
388 >    char  **spp,
389 >    FILE  **fpp
390 > )
391   {
392 +    if (fnp != NULL) *fnp = infile;
393 +    if (lnp != NULL) *lnp = lineno;
394 +    if (spp != NULL) *spp = linbuf+linepos;
395 +    if (fpp != NULL) *fpp = infp;
396 + }
397 +
398 +
399 + int
400 + scan(void)              /* scan next character, return literal next */
401 + {
402 +    register int  lnext = 0;
403 +
404      do {
405          if (linbuf[linepos] == '\0')
406              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
407                  nextc = EOF;
408              else {
409                  nextc = linbuf[0];
410 +                lineno++;
411                  linepos = 1;
412              }
413          else
414              nextc = linbuf[linepos++];
415 +        if (!lnext)
416 +                lnext = nextc;
417 +        if (nextc == eofc) {
418 +                nextc = EOF;
419 +                break;
420 +        }
421          if (nextc == '{') {
422              scan();
423              while (nextc != '}')
# Line 341 | Line 428 | scan()                         /* scan next character */
428              scan();
429          }
430      } while (isspace(nextc));
431 +    return(lnext);
432   }
433  
434  
435 < syntax(err)                     /* report syntax error and quit */
436 < char  *err;
435 > char *
436 > long2ascii(                           /* convert long to ascii */
437 >    long  l
438 > )
439   {
440 +    static char  buf[16];
441 +    register char  *cp;
442 +    int  neg = 0;
443 +
444 +    if (l == 0)
445 +        return("0");
446 +    if (l < 0) {
447 +        l = -l;
448 +        neg++;
449 +    }
450 +    cp = buf + sizeof(buf);
451 +    *--cp = '\0';
452 +    while (l) {
453 +        *--cp = l % 10 + '0';
454 +        l /= 10;
455 +    }
456 +    if (neg)
457 +        *--cp = '-';
458 +    return(cp);
459 + }
460 +
461 +
462 + void
463 + syntax(                 /* report syntax error and quit */
464 +    char  *err
465 + )
466 + {
467      register int  i;
468  
469 +    if (infile != NULL || lineno != 0) {
470 +        if (infile != NULL) eputs(infile);
471 +        if (lineno != 0) {
472 +            eputs(infile != NULL ? ", line " : "line ");
473 +            eputs(long2ascii((long)lineno));
474 +        }
475 +        eputs(":\n");
476 +    }
477      eputs(linbuf);
478      if (linbuf[strlen(linbuf)-1] != '\n')
479          eputs("\n");
480      for (i = 0; i < linepos-1; i++)
481          eputs(linbuf[i] == '\t' ? "\t" : " ");
482      eputs("^ ");
358    if (infile != NULL) {
359        eputs(infile);
360        eputs(": ");
361    }
483      eputs(err);
484      eputs("\n");
485      quit(1);
486   }
487  
488  
489 < addekid(ep, ekid)                       /* add a child to ep */
490 < register EPNODE  *ep;
491 < EPNODE  *ekid;
489 > void
490 > addekid(                        /* add a child to ep */
491 >    register EPNODE      *ep,
492 >    EPNODE      *ekid
493 > )
494   {
495      if (ep->v.kid == NULL)
496          ep->v.kid = ekid;
# Line 381 | Line 504 | EPNODE  *ekid;
504  
505  
506   char *
507 < getname()                       /* scan an identifier */
507 > getname(void)                   /* scan an identifier */
508   {
509 <    static char  str[MAXWORD+1];
510 <    register int  i;
509 >    static char  str[RMAXWORD+1];
510 >    register int  i, lnext;
511  
512 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
513 <        str[i] = nextc;
512 >    lnext = nextc;
513 >    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
514 >        str[i] = lnext;
515      str[i] = '\0';
516 +    while (isid(lnext))         /* skip rest of name */
517 +        lnext = scan();
518  
519      return(str);
520   }
521  
522  
523   int
524 < getinum()                       /* scan a positive integer */
524 > getinum(void)                   /* scan a positive integer */
525   {
526 <    register int  n;
526 >    register int  n, lnext;
527  
528      n = 0;
529 <    while (isdigit(nextc)) {
530 <        n = n * 10 + nextc - '0';
531 <        scan();
529 >    lnext = nextc;
530 >    while (isdigit(lnext)) {
531 >        n = n * 10 + lnext - '0';
532 >        lnext = scan();
533      }
534      return(n);
535   }
536  
537  
538   double
539 < getnum()                        /* scan a positive float */
539 > getnum(void)                    /* scan a positive float */
540   {
541 <    register int  i;
542 <    char  str[MAXWORD+1];
541 >    register int  i, lnext;
542 >    char  str[RMAXWORD+1];
543  
544      i = 0;
545 <    while (isdigit(nextc) && i < MAXWORD) {
546 <        str[i++] = nextc;
547 <        scan();
545 >    lnext = nextc;
546 >    while (isdigit(lnext) && i < RMAXWORD) {
547 >        str[i++] = lnext;
548 >        lnext = scan();
549      }
550 <    if (nextc == '.' && i < MAXWORD) {
551 <        str[i++] = nextc;
552 <        scan();
553 <        while (isdigit(nextc) && i < MAXWORD) {
554 <            str[i++] = nextc;
555 <            scan();
550 >    if (lnext == '.' && i < RMAXWORD) {
551 >        str[i++] = lnext;
552 >        lnext = scan();
553 >        if (i == 1 && !isdigit(lnext))
554 >            syntax("badly formed number");
555 >        while (isdigit(lnext) && i < RMAXWORD) {
556 >            str[i++] = lnext;
557 >            lnext = scan();
558          }
559      }
560 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
561 <        str[i++] = nextc;
562 <        scan();
563 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
564 <            str[i++] = nextc;
565 <            scan();
560 >    if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
561 >        str[i++] = lnext;
562 >        lnext = scan();
563 >        if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
564 >            str[i++] = lnext;
565 >            lnext = scan();
566          }
567 <        while (isdigit(nextc) && i < MAXWORD) {
568 <            str[i++] = nextc;
569 <            scan();
567 >        if (!isdigit(lnext))
568 >            syntax("missing exponent");
569 >        while (isdigit(lnext) && i < RMAXWORD) {
570 >            str[i++] = lnext;
571 >            lnext = scan();
572          }
573      }
574      str[i] = '\0';
# Line 446 | Line 578 | getnum()                       /* scan a positive float */
578  
579  
580   EPNODE *
581 < getE1()                         /* E1 -> E1 ADDOP E2 */
582 <                                /*       E2 */
581 > getE1(void)                             /* E1 -> E1 ADDOP E2 */
582 >                                /*       E2 */
583   {
584      register EPNODE  *ep1, *ep2;
585  
# Line 458 | Line 590 | getE1()                                /* E1 -> E1 ADDOP E2 */
590          scan();
591          addekid(ep2, ep1);
592          addekid(ep2, getE2());
593 < #ifdef  RCONST
594 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
593 >        if (esupport&E_RCONST &&
594 >                        ep1->type == NUM && ep1->sibling->type == NUM)
595                  ep2 = rconst(ep2);
464 #endif
596          ep1 = ep2;
597      }
598      return(ep1);
# Line 469 | Line 600 | getE1()                                /* E1 -> E1 ADDOP E2 */
600  
601  
602   EPNODE *
603 < getE2()                         /* E2 -> E2 MULOP E3 */
604 <                                /*       E3 */
603 > getE2(void)                             /* E2 -> E2 MULOP E3 */
604 >                                /*       E3 */
605   {
606      register EPNODE  *ep1, *ep2;
607  
# Line 481 | Line 612 | getE2()                                /* E2 -> E2 MULOP E3 */
612          scan();
613          addekid(ep2, ep1);
614          addekid(ep2, getE3());
615 < #ifdef  RCONST
616 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
615 >        if (esupport&E_RCONST &&
616 >                        ep1->type == NUM && ep1->sibling->type == NUM)
617                  ep2 = rconst(ep2);
487 #endif
618          ep1 = ep2;
619      }
620      return(ep1);
# Line 492 | Line 622 | getE2()                                /* E2 -> E2 MULOP E3 */
622  
623  
624   EPNODE *
625 < getE3()                         /* E3 -> E3 ^ E4 */
626 <                                /*       E4 */
625 > getE3(void)                             /* E3 -> E4 ^ E3 */
626 >                                /*       E4 */
627   {
628      register EPNODE  *ep1, *ep2;
629  
630      ep1 = getE4();
631 <    while (nextc == '^') {
631 >    if (nextc == '^') {
632          ep2 = newnode();
633          ep2->type = nextc;
634          scan();
635          addekid(ep2, ep1);
636 <        addekid(ep2, getE4());
637 < #ifdef  RCONST
638 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
636 >        addekid(ep2, getE3());
637 >        if (esupport&E_RCONST &&
638 >                        ep1->type == NUM && ep1->sibling->type == NUM)
639                  ep2 = rconst(ep2);
640 < #endif
511 <        ep1 = ep2;
640 >        return(ep2);
641      }
642      return(ep1);
643   }
644  
645  
646   EPNODE *
647 < getE4()                         /* E4 -> ADDOP E5 */
648 <                                /*       E5 */
647 > getE4(void)                             /* E4 -> ADDOP E5 */
648 >                                /*       E5 */
649   {
650      register EPNODE  *ep1, *ep2;
651  
# Line 527 | Line 656 | getE4()                                /* E4 -> ADDOP E5 */
656                  ep2->v.num = -ep2->v.num;
657                  return(ep2);
658          }
659 +        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
660 +            efree((char *)ep2);
661 +            return(ep2->v.kid);
662 +        }
663          ep1 = newnode();
664          ep1->type = UMINUS;
665          addekid(ep1, ep2);
# Line 539 | Line 672 | getE4()                                /* E4 -> ADDOP E5 */
672  
673  
674   EPNODE *
675 < getE5()                         /* E5 -> (E1) */
676 <                                /*       VAR */
677 <                                /*       NUM */
678 <                                /*       $N */
679 <                                /*       FUNC(E1,..) */
680 <                                /*       ARG */
675 > getE5(void)                     /* E5 -> (E1) */
676 >                                /*       VAR */
677 >                                /*       NUM */
678 >                                /*       $N */
679 >                                /*       FUNC(E1,..) */
680 >                                /*       ARG */
681   {
682 <    int  i;
683 <    register EPNODE  *ep1, *ep2;
682 >        int      i;
683 >        char  *nam;
684 >        register EPNODE  *ep1, *ep2;
685  
686 <    if (nextc == '(') {
687 <        scan();
688 <        ep1 = getE1();
689 <        if (nextc != ')')
690 <            syntax("')' expected");
691 <        scan();
692 <        return(ep1);
693 <    }
686 >        if (nextc == '(') {
687 >                scan();
688 >                ep1 = getE1();
689 >                if (nextc != ')')
690 >                        syntax("')' expected");
691 >                scan();
692 >                return(ep1);
693 >        }
694  
695 < #ifdef  INCHAN
696 <    if (nextc == '$') {
697 <        scan();
698 <        ep1 = newnode();
699 <        ep1->type = CHAN;
700 <        ep1->v.chan = getinum();
701 <        return(ep1);
568 <    }
569 < #endif
695 >        if (esupport&E_INCHAN && nextc == '$') {
696 >                scan();
697 >                ep1 = newnode();
698 >                ep1->type = CHAN;
699 >                ep1->v.chan = getinum();
700 >                return(ep1);
701 >        }
702  
703 < #if  defined(VARIABLE) || defined(FUNCTION)
704 <    if (isalpha(nextc)) {
705 <        ep1 = newnode();
706 <        ep1->type = VAR;
707 <        ep1->v.ln = varinsert(getname());
708 <
709 < #if  defined(VARIABLE) && defined(FUNCTION)
710 <        if (curfunc != NULL)
711 <            for (i = 1, ep2 = curfunc->v.kid->sibling;
712 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
713 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
714 <                    epfree(ep1);
715 <                    ep1 = newnode();
716 <                    ep1->type = ARG;
717 <                    ep1->v.chan = i;
718 <                    break;
703 >        if (esupport&(E_VARIABLE|E_FUNCTION) &&
704 >                        (isalpha(nextc) || nextc == CNTXMARK)) {
705 >                nam = getname();
706 >                ep1 = NULL;
707 >                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
708 >                                && curfunc != NULL)
709 >                        for (i = 1, ep2 = curfunc->v.kid->sibling;
710 >                                        ep2 != NULL; i++, ep2 = ep2->sibling)
711 >                                if (!strcmp(ep2->v.name, nam)) {
712 >                                        ep1 = newnode();
713 >                                        ep1->type = ARG;
714 >                                        ep1->v.chan = i;
715 >                                        break;
716 >                                }
717 >                if (ep1 == NULL) {
718 >                        ep1 = newnode();
719 >                        ep1->type = VAR;
720 >                        ep1->v.ln = varinsert(nam);
721                  }
722 < #endif
723 < #ifdef  FUNCTION
724 <        if (nextc == '(') {
725 <            ep2 = newnode();
726 <            ep2->type = FUNC;
727 <            addekid(ep2, ep1);
728 <            ep1 = ep2;
729 <            do {
730 <                scan();
731 <                addekid(ep1, getE1());
732 <            } while (nextc == ',');
733 <            if (nextc != ')')
734 <                syntax("')' expected");
735 <            scan();
722 >                if (esupport&E_FUNCTION && nextc == '(') {
723 >                        ep2 = newnode();
724 >                        ep2->type = FUNC;
725 >                        addekid(ep2, ep1);
726 >                        ep1 = ep2;
727 >                        do {
728 >                                scan();
729 >                                addekid(ep1, getE1());
730 >                        } while (nextc == ',');
731 >                        if (nextc != ')')
732 >                                syntax("')' expected");
733 >                        scan();
734 >                } else if (!(esupport&E_VARIABLE))
735 >                        syntax("'(' expected");
736 >                if (esupport&E_RCONST && isconstvar(ep1))
737 >                        ep1 = rconst(ep1);
738 >                return(ep1);
739          }
603 #ifndef  VARIABLE
604        else
605            syntax("'(' expected");
606 #endif
607 #endif
608        return(ep1);
609    }
610 #endif
740  
741 <    if (isdecimal(nextc)) {
742 <        ep1 = newnode();
743 <        ep1->type = NUM;
744 <        ep1->v.num = getnum();
745 <        return(ep1);
746 <    }
747 <    syntax("unexpected character");
741 >        if (isdecimal(nextc)) {
742 >                ep1 = newnode();
743 >                ep1->type = NUM;
744 >                ep1->v.num = getnum();
745 >                return(ep1);
746 >        }
747 >        syntax("unexpected character");
748 >        return NULL; /* pro forma return */
749   }
750  
751  
622 #ifdef  RCONST
752   EPNODE *
753 < rconst(epar)                    /* reduce a constant expression */
754 < register EPNODE  *epar;
753 > rconst(                 /* reduce a constant expression */
754 >    register EPNODE      *epar
755 > )
756   {
757      register EPNODE  *ep;
758  
# Line 630 | Line 760 | register EPNODE  *epar;
760      ep->type = NUM;
761      errno = 0;
762      ep->v.num = evalue(epar);
763 <    if (errno)
764 <        syntax("bad constant expression");
763 >    if (errno == EDOM || errno == ERANGE)
764 >        syntax("bad constant expression");
765      epfree(epar);
766  
767      return(ep);
768   }
769 < #endif
769 >
770 >
771 > int
772 > isconstvar(                     /* is ep linked to a constant expression? */
773 >    register EPNODE      *ep
774 > )
775 > {
776 >    register EPNODE  *ep1;
777 >
778 >    if (esupport&E_FUNCTION && ep->type == FUNC) {
779 >        if (!isconstfun(ep->v.kid))
780 >                return(0);
781 >        for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
782 >            if (ep1->type != NUM && !isconstfun(ep1))
783 >                return(0);
784 >        return(1);
785 >    }
786 >    if (ep->type != VAR)
787 >        return(0);
788 >    ep1 = ep->v.ln->def;
789 >    if (ep1 == NULL || ep1->type != ':')
790 >        return(0);
791 >    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
792 >        return(0);
793 >    return(1);
794 > }
795 >
796 >
797 > int
798 > isconstfun(                     /* is ep linked to a constant function? */
799 >    register EPNODE      *ep
800 > )
801 > {
802 >    register EPNODE  *dp;
803 >    register LIBR  *lp;
804 >
805 >    if (ep->type != VAR)
806 >        return(0);
807 >    if ((dp = ep->v.ln->def) != NULL) {
808 >        if (dp->v.kid->type == FUNC)
809 >            return(dp->type == ':');
810 >        else
811 >            return(0);          /* don't identify masked library functions */
812 >    }
813 >    if ((lp = ep->v.ln->lib) != NULL)
814 >        return(lp->atyp == ':');
815 >    return(0);
816 > }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines