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.7 by greg, Sat Aug 18 16:28:52 1990 UTC vs.
Revision 2.29 by schorsch, Sun Mar 28 20:33:12 2004 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  nextc;                             /* lookahead character */
51  
52 < double  (*eoper[])() = {                /* expression operations */
52 > double  (*eoper[])(EPNODE *) = {        /* expression operations */
53          ebotch,
52 #ifdef  VARIABLE
54          evariable,
54 #else
55        ebotch,
56 #endif
55          enumber,
56          euminus,
59 #ifdef  INCHAN
57          echannel,
61 #else
62        ebotch,
63 #endif
64 #ifdef  FUNCTION
58          efunc,
59          eargument,
67 #else
60          ebotch,
61          ebotch,
70 #endif
71        ebotch,
72        ebotch,
62          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
63          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
64          emult,
# Line 78 | Line 67 | double  (*eoper[])() = {               /* expression operations */
67          esubtr,
68          0,
69          edivi,
70 <        0,0,0,0,0,0,0,0,0,0,0,0,0,
70 >        0,0,0,0,0,0,0,0,0,0,
71          ebotch,
72 +        0,0,
73 +        ebotch,
74          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
76          epow,
# Line 93 | Line 84 | static int  linepos;                   /* position in buffer */
84  
85  
86   EPNODE *
87 < eparse(expr)                    /* parse an expression string */
88 < char  *expr;
87 > eparse(                 /* parse an expression string */
88 >    char  *expr
89 > )
90   {
91      EPNODE  *ep;
92  
93      initstr(expr, NULL, 0);
102 #if  defined(VARIABLE) && defined(FUNCTION)
94      curfunc = NULL;
104 #endif
95      ep = getE1();
96      if (nextc != EOF)
97          syntax("unexpected character");
# Line 110 | Line 100 | char  *expr;
100  
101  
102   double
103 < eval(expr)                      /* evaluate an expression string */
104 < char  *expr;
103 > eval(                   /* evaluate an expression string */
104 >    char  *expr
105 > )
106   {
107      register EPNODE  *ep;
108      double  rval;
# Line 123 | Line 114 | char  *expr;
114   }
115  
116  
117 < epfree(epar)                    /* free a parse tree */
118 < register EPNODE  *epar;
117 > int
118 > epcmp(                  /* compare two expressions for equivalence */
119 >    register EPNODE  *ep1,
120 >    register EPNODE  *ep2
121 > )
122   {
123 +        double  d;
124 +
125 +        if (ep1->type != ep2->type)
126 +                return(1);
127 +
128 +        switch (ep1->type) {
129 +
130 +        case VAR:
131 +                return(ep1->v.ln != ep2->v.ln);
132 +
133 +        case NUM:
134 +                if (ep2->v.num == 0)
135 +                        return(ep1->v.num != 0);
136 +                d = ep1->v.num / ep2->v.num;
137 +                return((d > 1.000000000001) | (d < 0.999999999999));
138 +
139 +        case CHAN:
140 +        case ARG:
141 +                return(ep1->v.chan != ep2->v.chan);
142 +
143 +        case '=':
144 +        case ':':
145 +                return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling));
146 +
147 +        case TICK:
148 +        case SYM:                       /* should never get this one */
149 +                return(0);
150 +
151 +        default:
152 +                ep1 = ep1->v.kid;
153 +                ep2 = ep2->v.kid;
154 +                while (ep1 != NULL) {
155 +                        if (ep2 == NULL)
156 +                                return(1);
157 +                        if (epcmp(ep1, ep2))
158 +                                return(1);
159 +                        ep1 = ep1->sibling;
160 +                        ep2 = ep2->sibling;
161 +                }
162 +                return(ep2 != NULL);
163 +        }
164 + }
165 +
166 +
167 + void
168 + epfree(                 /* free a parse tree */
169 +    register EPNODE      *epar
170 + )
171 + {
172      register EPNODE  *ep;
173  
174      switch (epar->type) {
175  
133 #if  defined(VARIABLE) || defined(FUNCTION)
176          case VAR:
177              varfree(epar->v.ln);
178              break;
137 #endif
179              
180          case SYM:
181              freestr(epar->v.name);
# Line 147 | Line 188 | register EPNODE  *epar;
188              break;
189  
190          default:
191 <            for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
191 >            while ((ep = epar->v.kid) != NULL) {
192 >                epar->v.kid = ep->sibling;
193                  epfree(ep);
194 +            }
195              break;
196  
197      }
# Line 157 | Line 200 | register EPNODE  *epar;
200   }
201  
202                                  /* the following used to be a switch */
160 #ifdef  FUNCTION
203   static double
204 < eargument(ep)
205 < EPNODE  *ep;
204 > eargument(
205 >    EPNODE      *ep
206 > )
207   {
208      return(argument(ep->v.chan));
209   }
167 #endif
210  
211   static double
212 < enumber(ep)
213 < EPNODE  *ep;
212 > enumber(
213 >    EPNODE      *ep
214 > )
215   {
216      return(ep->v.num);
217   }
218  
219   static double
220 < euminus(ep)
221 < EPNODE  *ep;
220 > euminus(
221 >    EPNODE      *ep
222 > )
223   {
224      register EPNODE  *ep1 = ep->v.kid;
225  
226      return(-evalue(ep1));
227   }
228  
185 #ifdef  INCHAN
229   static double
230 < echannel(ep)
231 < EPNODE  *ep;
230 > echannel(
231 >    EPNODE      *ep
232 > )
233   {
234      return(chanvalue(ep->v.chan));
235   }
192 #endif
236  
237   static double
238 < eadd(ep)
239 < EPNODE  *ep;
238 > eadd(
239 >    EPNODE      *ep
240 > )
241   {
242      register EPNODE  *ep1 = ep->v.kid;
243  
# Line 201 | Line 245 | EPNODE  *ep;
245   }
246  
247   static double
248 < esubtr(ep)
249 < EPNODE  *ep;
248 > esubtr(
249 >    EPNODE      *ep
250 > )
251   {
252      register EPNODE  *ep1 = ep->v.kid;
253  
# Line 210 | Line 255 | EPNODE  *ep;
255   }
256  
257   static double
258 < emult(ep)
259 < EPNODE  *ep;
258 > emult(
259 >    EPNODE      *ep
260 > )
261   {
262      register EPNODE  *ep1 = ep->v.kid;
263  
# Line 219 | Line 265 | EPNODE  *ep;
265   }
266  
267   static double
268 < edivi(ep)
269 < EPNODE  *ep;
268 > edivi(
269 >    EPNODE      *ep
270 > )
271   {
272      register EPNODE  *ep1 = ep->v.kid;
273      double  d;
# Line 235 | Line 282 | EPNODE  *ep;
282   }
283  
284   static double
285 < epow(ep)
286 < EPNODE  *ep;
285 > epow(
286 >    EPNODE      *ep
287 > )
288   {
289      register EPNODE  *ep1 = ep->v.kid;
290      double  d;
291 <    int  lasterrno;
291 >    int  lasterrno;
292  
293      lasterrno = errno;
294      errno = 0;
295      d = pow(evalue(ep1), evalue(ep1->sibling));
296 < #ifdef  IEEE
296 > #ifdef  IEEE
297      if (!finite(d))
298          errno = EDOM;
299   #endif
300 <    if (errno) {
300 >    if (errno == EDOM || errno == ERANGE) {
301          wputs("Illegal power\n");
302          return(0.0);
303      }
# Line 258 | Line 306 | EPNODE  *ep;
306   }
307  
308   static double
309 < ebotch(ep)
310 < EPNODE  *ep;
309 > ebotch(
310 >    EPNODE      *ep
311 > )
312   {
313      eputs("Bad expression!\n");
314      quit(1);
315 +        return 0.0; /* pro forma return */
316   }
317  
318  
319   EPNODE *
320 < ekid(ep, n)                     /* return pointer to a node's nth kid */
321 < register EPNODE  *ep;
322 < register int  n;
320 > ekid(                   /* return pointer to a node's nth kid */
321 >    register EPNODE      *ep,
322 >    register int  n
323 > )
324   {
325  
326      for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
# Line 281 | Line 332 | register int  n;
332  
333  
334   int
335 < nekids(ep)                      /* return # of kids for node ep */
336 < register EPNODE  *ep;
335 > nekids(                 /* return # of kids for node ep */
336 >    register EPNODE      *ep
337 > )
338   {
339      register int  n = 0;
340  
# Line 293 | Line 345 | register EPNODE  *ep;
345   }
346  
347  
348 < initfile(fp, fn, ln)            /* prepare input file */
349 < FILE  *fp;
350 < char  *fn;
351 < int  ln;
348 > void
349 > initfile(               /* prepare input file */
350 >    FILE  *fp,
351 >    char  *fn,
352 >    int  ln
353 > )
354   {
355 <    static char  inpbuf[MAXLINE];
355 >    static char  inpbuf[MAXLINE];
356  
357      infp = fp;
358      linbuf = inpbuf;
# Line 310 | Line 364 | int  ln;
364   }
365  
366  
367 < initstr(s, fn, ln)              /* prepare input string */
368 < char  *s;
369 < char  *fn;
370 < int  ln;
367 > void
368 > initstr(                /* prepare input string */
369 >    char  *s,
370 >    char  *fn,
371 >    int  ln
372 > )
373   {
374      infp = NULL;
375      infile = fn;
# Line 324 | Line 380 | int  ln;
380   }
381  
382  
383 < scan()                          /* scan next character */
383 > void
384 > getscanpos(     /* return current scan position */
385 >    char  **fnp,
386 >    int  *lnp,
387 >    char  **spp,
388 >    FILE  **fpp
389 > )
390   {
391 +    if (fnp != NULL) *fnp = infile;
392 +    if (lnp != NULL) *lnp = lineno;
393 +    if (spp != NULL) *spp = linbuf+linepos;
394 +    if (fpp != NULL) *fpp = infp;
395 + }
396 +
397 +
398 + int
399 + scan(void)              /* scan next character, return literal next */
400 + {
401 +    register int  lnext = 0;
402 +
403      do {
404          if (linbuf[linepos] == '\0')
405              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
# Line 337 | Line 411 | scan()                         /* scan next character */
411              }
412          else
413              nextc = linbuf[linepos++];
414 +        if (!lnext)
415 +                lnext = nextc;
416          if (nextc == '{') {
417              scan();
418              while (nextc != '}')
# Line 347 | Line 423 | scan()                         /* scan next character */
423              scan();
424          }
425      } while (isspace(nextc));
426 +    return(lnext);
427   }
428  
429  
430   char *
431 < ltoa(l)                         /* convert long to ascii */
432 < long  l;
431 > long2ascii(                           /* convert long to ascii */
432 >    long  l
433 > )
434   {
435 <    static char  buf[16];
435 >    static char  buf[16];
436      register char  *cp;
437 <    int  neg = 0;
437 >    int  neg = 0;
438  
439      if (l == 0)
440          return("0");
# Line 376 | Line 454 | long  l;
454   }
455  
456  
457 < syntax(err)                     /* report syntax error and quit */
458 < char  *err;
457 > void
458 > syntax(                 /* report syntax error and quit */
459 >    char  *err
460 > )
461   {
462      register int  i;
463  
# Line 385 | Line 465 | char  *err;
465          if (infile != NULL) eputs(infile);
466          if (lineno != 0) {
467              eputs(infile != NULL ? ", line " : "line ");
468 <            eputs(ltoa((long)lineno));
468 >            eputs(long2ascii((long)lineno));
469          }
470 <        eputs(": syntax error:\n");
470 >        eputs(":\n");
471      }
472      eputs(linbuf);
473      if (linbuf[strlen(linbuf)-1] != '\n')
# Line 401 | Line 481 | char  *err;
481   }
482  
483  
484 < addekid(ep, ekid)                       /* add a child to ep */
485 < register EPNODE  *ep;
486 < EPNODE  *ekid;
484 > void
485 > addekid(                        /* add a child to ep */
486 >    register EPNODE      *ep,
487 >    EPNODE      *ekid
488 > )
489   {
490      if (ep->v.kid == NULL)
491          ep->v.kid = ekid;
# Line 417 | Line 499 | EPNODE  *ekid;
499  
500  
501   char *
502 < getname()                       /* scan an identifier */
502 > getname(void)                   /* scan an identifier */
503   {
504 <    static char  str[MAXWORD+1];
505 <    register int  i;
504 >    static char  str[RMAXWORD+1];
505 >    register int  i, lnext;
506  
507 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
508 <        str[i] = nextc;
507 >    lnext = nextc;
508 >    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
509 >        str[i] = lnext;
510      str[i] = '\0';
511 +    while (isid(lnext))         /* skip rest of name */
512 +        lnext = scan();
513  
514      return(str);
515   }
516  
517  
518   int
519 < getinum()                       /* scan a positive integer */
519 > getinum(void)                   /* scan a positive integer */
520   {
521 <    register int  n;
521 >    register int  n, lnext;
522  
523      n = 0;
524 <    while (isdigit(nextc)) {
525 <        n = n * 10 + nextc - '0';
526 <        scan();
524 >    lnext = nextc;
525 >    while (isdigit(lnext)) {
526 >        n = n * 10 + lnext - '0';
527 >        lnext = scan();
528      }
529      return(n);
530   }
531  
532  
533   double
534 < getnum()                        /* scan a positive float */
534 > getnum(void)                    /* scan a positive float */
535   {
536 <    register int  i;
537 <    char  str[MAXWORD+1];
536 >    register int  i, lnext;
537 >    char  str[RMAXWORD+1];
538  
539      i = 0;
540 <    while (isdigit(nextc) && i < MAXWORD) {
541 <        str[i++] = nextc;
542 <        scan();
540 >    lnext = nextc;
541 >    while (isdigit(lnext) && i < RMAXWORD) {
542 >        str[i++] = lnext;
543 >        lnext = scan();
544      }
545 <    if (nextc == '.' && i < MAXWORD) {
546 <        str[i++] = nextc;
547 <        scan();
548 <        while (isdigit(nextc) && i < MAXWORD) {
549 <            str[i++] = nextc;
550 <            scan();
545 >    if (lnext == '.' && i < RMAXWORD) {
546 >        str[i++] = lnext;
547 >        lnext = scan();
548 >        if (i == 1 && !isdigit(lnext))
549 >            syntax("badly formed number");
550 >        while (isdigit(lnext) && i < RMAXWORD) {
551 >            str[i++] = lnext;
552 >            lnext = scan();
553          }
554      }
555 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
556 <        str[i++] = nextc;
557 <        scan();
558 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
559 <            str[i++] = nextc;
560 <            scan();
555 >    if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
556 >        str[i++] = lnext;
557 >        lnext = scan();
558 >        if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
559 >            str[i++] = lnext;
560 >            lnext = scan();
561          }
562 <        while (isdigit(nextc) && i < MAXWORD) {
563 <            str[i++] = nextc;
564 <            scan();
562 >        if (!isdigit(lnext))
563 >            syntax("missing exponent");
564 >        while (isdigit(lnext) && i < RMAXWORD) {
565 >            str[i++] = lnext;
566 >            lnext = scan();
567          }
568      }
569      str[i] = '\0';
# Line 482 | Line 573 | getnum()                       /* scan a positive float */
573  
574  
575   EPNODE *
576 < getE1()                         /* E1 -> E1 ADDOP E2 */
577 <                                /*       E2 */
576 > getE1(void)                             /* E1 -> E1 ADDOP E2 */
577 >                                /*       E2 */
578   {
579      register EPNODE  *ep1, *ep2;
580  
# Line 494 | Line 585 | getE1()                                /* E1 -> E1 ADDOP E2 */
585          scan();
586          addekid(ep2, ep1);
587          addekid(ep2, getE2());
588 < #ifdef  RCONST
589 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
588 >        if (esupport&E_RCONST &&
589 >                        ep1->type == NUM && ep1->sibling->type == NUM)
590                  ep2 = rconst(ep2);
500 #endif
591          ep1 = ep2;
592      }
593      return(ep1);
# Line 505 | Line 595 | getE1()                                /* E1 -> E1 ADDOP E2 */
595  
596  
597   EPNODE *
598 < getE2()                         /* E2 -> E2 MULOP E3 */
599 <                                /*       E3 */
598 > getE2(void)                             /* E2 -> E2 MULOP E3 */
599 >                                /*       E3 */
600   {
601      register EPNODE  *ep1, *ep2;
602  
# Line 517 | Line 607 | getE2()                                /* E2 -> E2 MULOP E3 */
607          scan();
608          addekid(ep2, ep1);
609          addekid(ep2, getE3());
610 < #ifdef  RCONST
611 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
610 >        if (esupport&E_RCONST &&
611 >                        ep1->type == NUM && ep1->sibling->type == NUM)
612                  ep2 = rconst(ep2);
523 #endif
613          ep1 = ep2;
614      }
615      return(ep1);
# Line 528 | Line 617 | getE2()                                /* E2 -> E2 MULOP E3 */
617  
618  
619   EPNODE *
620 < getE3()                         /* E3 -> E3 ^ E4 */
621 <                                /*       E4 */
620 > getE3(void)                             /* E3 -> E4 ^ E3 */
621 >                                /*       E4 */
622   {
623      register EPNODE  *ep1, *ep2;
624  
625      ep1 = getE4();
626 <    while (nextc == '^') {
626 >    if (nextc == '^') {
627          ep2 = newnode();
628          ep2->type = nextc;
629          scan();
630          addekid(ep2, ep1);
631 <        addekid(ep2, getE4());
632 < #ifdef  RCONST
633 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
631 >        addekid(ep2, getE3());
632 >        if (esupport&E_RCONST &&
633 >                        ep1->type == NUM && ep1->sibling->type == NUM)
634                  ep2 = rconst(ep2);
635 < #endif
547 <        ep1 = ep2;
635 >        return(ep2);
636      }
637      return(ep1);
638   }
639  
640  
641   EPNODE *
642 < getE4()                         /* E4 -> ADDOP E5 */
643 <                                /*       E5 */
642 > getE4(void)                             /* E4 -> ADDOP E5 */
643 >                                /*       E5 */
644   {
645      register EPNODE  *ep1, *ep2;
646  
# Line 563 | Line 651 | getE4()                                /* E4 -> ADDOP E5 */
651                  ep2->v.num = -ep2->v.num;
652                  return(ep2);
653          }
654 +        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
655 +            efree((char *)ep2);
656 +            return(ep2->v.kid);
657 +        }
658          ep1 = newnode();
659          ep1->type = UMINUS;
660          addekid(ep1, ep2);
# Line 575 | Line 667 | getE4()                                /* E4 -> ADDOP E5 */
667  
668  
669   EPNODE *
670 < getE5()                         /* E5 -> (E1) */
671 <                                /*       VAR */
672 <                                /*       NUM */
673 <                                /*       $N */
674 <                                /*       FUNC(E1,..) */
675 <                                /*       ARG */
670 > getE5(void)                     /* E5 -> (E1) */
671 >                                /*       VAR */
672 >                                /*       NUM */
673 >                                /*       $N */
674 >                                /*       FUNC(E1,..) */
675 >                                /*       ARG */
676   {
677 <    int  i;
678 <    register EPNODE  *ep1, *ep2;
677 >        int      i;
678 >        char  *nam;
679 >        register EPNODE  *ep1, *ep2;
680  
681 <    if (nextc == '(') {
682 <        scan();
683 <        ep1 = getE1();
684 <        if (nextc != ')')
685 <            syntax("')' expected");
686 <        scan();
687 <        return(ep1);
688 <    }
681 >        if (nextc == '(') {
682 >                scan();
683 >                ep1 = getE1();
684 >                if (nextc != ')')
685 >                        syntax("')' expected");
686 >                scan();
687 >                return(ep1);
688 >        }
689  
690 < #ifdef  INCHAN
691 <    if (nextc == '$') {
692 <        scan();
693 <        ep1 = newnode();
694 <        ep1->type = CHAN;
695 <        ep1->v.chan = getinum();
696 <        return(ep1);
604 <    }
605 < #endif
690 >        if (esupport&E_INCHAN && nextc == '$') {
691 >                scan();
692 >                ep1 = newnode();
693 >                ep1->type = CHAN;
694 >                ep1->v.chan = getinum();
695 >                return(ep1);
696 >        }
697  
698 < #if  defined(VARIABLE) || defined(FUNCTION)
699 <    if (isalpha(nextc)) {
700 <        ep1 = newnode();
701 <        ep1->type = VAR;
702 <        ep1->v.ln = varinsert(getname());
703 <
704 < #if  defined(VARIABLE) && defined(FUNCTION)
705 <        if (curfunc != NULL)
706 <            for (i = 1, ep2 = curfunc->v.kid->sibling;
707 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
708 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
709 <                    epfree(ep1);
710 <                    ep1 = newnode();
711 <                    ep1->type = ARG;
712 <                    ep1->v.chan = i;
713 <                    break;
698 >        if (esupport&(E_VARIABLE|E_FUNCTION) &&
699 >                        (isalpha(nextc) || nextc == CNTXMARK)) {
700 >                nam = getname();
701 >                ep1 = NULL;
702 >                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
703 >                                && curfunc != NULL)
704 >                        for (i = 1, ep2 = curfunc->v.kid->sibling;
705 >                                        ep2 != NULL; i++, ep2 = ep2->sibling)
706 >                                if (!strcmp(ep2->v.name, nam)) {
707 >                                        ep1 = newnode();
708 >                                        ep1->type = ARG;
709 >                                        ep1->v.chan = i;
710 >                                        break;
711 >                                }
712 >                if (ep1 == NULL) {
713 >                        ep1 = newnode();
714 >                        ep1->type = VAR;
715 >                        ep1->v.ln = varinsert(nam);
716                  }
717 < #endif
718 < #ifdef  FUNCTION
719 <        if (nextc == '(') {
720 <            ep2 = newnode();
721 <            ep2->type = FUNC;
722 <            addekid(ep2, ep1);
723 <            ep1 = ep2;
724 <            do {
725 <                scan();
726 <                addekid(ep1, getE1());
727 <            } while (nextc == ',');
728 <            if (nextc != ')')
729 <                syntax("')' expected");
730 <            scan();
717 >                if (esupport&E_FUNCTION && nextc == '(') {
718 >                        ep2 = newnode();
719 >                        ep2->type = FUNC;
720 >                        addekid(ep2, ep1);
721 >                        ep1 = ep2;
722 >                        do {
723 >                                scan();
724 >                                addekid(ep1, getE1());
725 >                        } while (nextc == ',');
726 >                        if (nextc != ')')
727 >                                syntax("')' expected");
728 >                        scan();
729 >                } else if (!(esupport&E_VARIABLE))
730 >                        syntax("'(' expected");
731 >                if (esupport&E_RCONST && isconstvar(ep1))
732 >                        ep1 = rconst(ep1);
733 >                return(ep1);
734          }
639 #ifndef  VARIABLE
640        else
641            syntax("'(' expected");
642 #endif
643 #endif
644        return(ep1);
645    }
646 #endif
735  
736 <    if (isdecimal(nextc)) {
737 <        ep1 = newnode();
738 <        ep1->type = NUM;
739 <        ep1->v.num = getnum();
740 <        return(ep1);
741 <    }
742 <    syntax("unexpected character");
736 >        if (isdecimal(nextc)) {
737 >                ep1 = newnode();
738 >                ep1->type = NUM;
739 >                ep1->v.num = getnum();
740 >                return(ep1);
741 >        }
742 >        syntax("unexpected character");
743 >        return NULL; /* pro forma return */
744   }
745  
746  
658 #ifdef  RCONST
747   EPNODE *
748 < rconst(epar)                    /* reduce a constant expression */
749 < register EPNODE  *epar;
748 > rconst(                 /* reduce a constant expression */
749 >    register EPNODE      *epar
750 > )
751   {
752      register EPNODE  *ep;
753  
# Line 666 | Line 755 | register EPNODE  *epar;
755      ep->type = NUM;
756      errno = 0;
757      ep->v.num = evalue(epar);
758 <    if (errno)
759 <        syntax("bad constant expression");
758 >    if (errno == EDOM || errno == ERANGE)
759 >        syntax("bad constant expression");
760      epfree(epar);
761  
762      return(ep);
763   }
764 < #endif
764 >
765 >
766 > int
767 > isconstvar(                     /* is ep linked to a constant expression? */
768 >    register EPNODE      *ep
769 > )
770 > {
771 >    register EPNODE  *ep1;
772 >
773 >    if (esupport&E_FUNCTION && ep->type == FUNC) {
774 >        if (!isconstfun(ep->v.kid))
775 >                return(0);
776 >        for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
777 >            if (ep1->type != NUM && !isconstfun(ep1))
778 >                return(0);
779 >        return(1);
780 >    }
781 >    if (ep->type != VAR)
782 >        return(0);
783 >    ep1 = ep->v.ln->def;
784 >    if (ep1 == NULL || ep1->type != ':')
785 >        return(0);
786 >    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
787 >        return(0);
788 >    return(1);
789 > }
790 >
791 >
792 > int
793 > isconstfun(                     /* is ep linked to a constant function? */
794 >    register EPNODE      *ep
795 > )
796 > {
797 >    register EPNODE  *dp;
798 >    register LIBR  *lp;
799 >
800 >    if (ep->type != VAR)
801 >        return(0);
802 >    if ((dp = ep->v.ln->def) != NULL) {
803 >        if (dp->v.kid->type == FUNC)
804 >            return(dp->type == ':');
805 >        else
806 >            return(0);          /* don't identify masked library functions */
807 >    }
808 >    if ((lp = ep->v.ln->lib) != NULL)
809 >        return(lp->atyp == ':');
810 >    return(0);
811 > }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines