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.10 by greg, Tue Apr 23 15:44:41 1991 UTC vs.
Revision 2.31 by greg, Wed May 10 15:21:20 2006 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;
109      double  rval;
# Line 125 | 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  
135 #if  defined(VARIABLE) || defined(FUNCTION)
177          case VAR:
178              varfree(epar->v.ln);
179              break;
139 #endif
180              
181          case SYM:
182              freestr(epar->v.name);
# Line 149 | 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 159 | Line 201 | register EPNODE  *epar;
201   }
202  
203                                  /* the following used to be a switch */
162 #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   }
169 #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  
187 #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   }
194 #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 203 | 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 212 | 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 221 | 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 237 | 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
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   #endif
304 <    if (errno) {
304 >    if (errno == EDOM || errno == ERANGE) {
305          wputs("Illegal power\n");
306          return(0.0);
307      }
# Line 260 | Line 310 | EPNODE  *ep;
310   }
311  
312   static double
313 < ebotch(ep)
314 < EPNODE  *ep;
313 > ebotch(
314 >    EPNODE      *ep
315 > )
316   {
317      eputs("Bad expression!\n");
318      quit(1);
319 +        return 0.0; /* pro forma return */
320   }
321  
322  
323   EPNODE *
324 < ekid(ep, n)                     /* return pointer to a node's nth kid */
325 < register EPNODE  *ep;
326 < register int  n;
324 > ekid(                   /* return pointer to a node's nth kid */
325 >    register EPNODE      *ep,
326 >    register int  n
327 > )
328   {
329  
330      for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
# Line 283 | Line 336 | register int  n;
336  
337  
338   int
339 < nekids(ep)                      /* return # of kids for node ep */
340 < register EPNODE  *ep;
339 > nekids(                 /* return # of kids for node ep */
340 >    register EPNODE      *ep
341 > )
342   {
343      register int  n = 0;
344  
# Line 295 | Line 349 | register EPNODE  *ep;
349   }
350  
351  
352 < initfile(fp, fn, ln)            /* prepare input file */
353 < FILE  *fp;
354 < char  *fn;
355 < int  ln;
352 > void
353 > initfile(               /* prepare input file */
354 >    FILE  *fp,
355 >    char  *fn,
356 >    int  ln
357 > )
358   {
359 <    static char  inpbuf[MAXLINE];
359 >    static char  inpbuf[MAXLINE];
360  
361      infp = fp;
362      linbuf = inpbuf;
# Line 312 | Line 368 | int  ln;
368   }
369  
370  
371 < initstr(s, fn, ln)              /* prepare input string */
372 < char  *s;
373 < char  *fn;
374 < int  ln;
371 > void
372 > initstr(                /* prepare input string */
373 >    char  *s,
374 >    char  *fn,
375 >    int  ln
376 > )
377   {
378      infp = NULL;
379      infile = fn;
# Line 326 | Line 384 | int  ln;
384   }
385  
386  
387 < scan()                          /* scan next character */
387 > void
388 > getscanpos(     /* return current scan position */
389 >    char  **fnp,
390 >    int  *lnp,
391 >    char  **spp,
392 >    FILE  **fpp
393 > )
394   {
395 +    if (fnp != NULL) *fnp = infile;
396 +    if (lnp != NULL) *lnp = lineno;
397 +    if (spp != NULL) *spp = linbuf+linepos;
398 +    if (fpp != NULL) *fpp = infp;
399 + }
400 +
401 +
402 + int
403 + scan(void)              /* scan next character, return literal next */
404 + {
405 +    register int  lnext = 0;
406 +
407      do {
408          if (linbuf[linepos] == '\0')
409              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
# Line 339 | Line 415 | scan()                         /* scan next character */
415              }
416          else
417              nextc = linbuf[linepos++];
418 +        if (!lnext)
419 +                lnext = nextc;
420 +        if (nextc == eofc) {
421 +                nextc = EOF;
422 +                break;
423 +        }
424          if (nextc == '{') {
425              scan();
426              while (nextc != '}')
# Line 349 | Line 431 | scan()                         /* scan next character */
431              scan();
432          }
433      } while (isspace(nextc));
434 +    return(lnext);
435   }
436  
437  
438   char *
439 < ltoa(l)                         /* convert long to ascii */
440 < long  l;
439 > long2ascii(                           /* convert long to ascii */
440 >    long  l
441 > )
442   {
443 <    static char  buf[16];
443 >    static char  buf[16];
444      register char  *cp;
445 <    int  neg = 0;
445 >    int  neg = 0;
446  
447      if (l == 0)
448          return("0");
# Line 378 | Line 462 | long  l;
462   }
463  
464  
465 < syntax(err)                     /* report syntax error and quit */
466 < char  *err;
465 > void
466 > syntax(                 /* report syntax error and quit */
467 >    char  *err
468 > )
469   {
470      register int  i;
471  
# Line 387 | Line 473 | char  *err;
473          if (infile != NULL) eputs(infile);
474          if (lineno != 0) {
475              eputs(infile != NULL ? ", line " : "line ");
476 <            eputs(ltoa((long)lineno));
476 >            eputs(long2ascii((long)lineno));
477          }
478 <        eputs(": syntax error:\n");
478 >        eputs(":\n");
479      }
480      eputs(linbuf);
481      if (linbuf[strlen(linbuf)-1] != '\n')
# Line 403 | Line 489 | char  *err;
489   }
490  
491  
492 < addekid(ep, ekid)                       /* add a child to ep */
493 < register EPNODE  *ep;
494 < EPNODE  *ekid;
492 > void
493 > addekid(                        /* add a child to ep */
494 >    register EPNODE      *ep,
495 >    EPNODE      *ekid
496 > )
497   {
498      if (ep->v.kid == NULL)
499          ep->v.kid = ekid;
# Line 419 | Line 507 | EPNODE  *ekid;
507  
508  
509   char *
510 < getname()                       /* scan an identifier */
510 > getname(void)                   /* scan an identifier */
511   {
512 <    static char  str[MAXWORD+1];
513 <    register int  i;
512 >    static char  str[RMAXWORD+1];
513 >    register int  i, lnext;
514  
515 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
516 <        str[i] = nextc;
515 >    lnext = nextc;
516 >    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
517 >        str[i] = lnext;
518      str[i] = '\0';
519 +    while (isid(lnext))         /* skip rest of name */
520 +        lnext = scan();
521  
522      return(str);
523   }
524  
525  
526   int
527 < getinum()                       /* scan a positive integer */
527 > getinum(void)                   /* scan a positive integer */
528   {
529 <    register int  n;
529 >    register int  n, lnext;
530  
531      n = 0;
532 <    while (isdigit(nextc)) {
533 <        n = n * 10 + nextc - '0';
534 <        scan();
532 >    lnext = nextc;
533 >    while (isdigit(lnext)) {
534 >        n = n * 10 + lnext - '0';
535 >        lnext = scan();
536      }
537      return(n);
538   }
539  
540  
541   double
542 < getnum()                        /* scan a positive float */
542 > getnum(void)                    /* scan a positive float */
543   {
544 <    register int  i;
545 <    char  str[MAXWORD+1];
544 >    register int  i, lnext;
545 >    char  str[RMAXWORD+1];
546  
547      i = 0;
548 <    while (isdigit(nextc) && i < MAXWORD) {
549 <        str[i++] = nextc;
550 <        scan();
548 >    lnext = nextc;
549 >    while (isdigit(lnext) && i < RMAXWORD) {
550 >        str[i++] = lnext;
551 >        lnext = scan();
552      }
553 <    if (nextc == '.' && i < MAXWORD) {
554 <        str[i++] = nextc;
555 <        scan();
556 <        while (isdigit(nextc) && i < MAXWORD) {
557 <            str[i++] = nextc;
558 <            scan();
553 >    if (lnext == '.' && i < RMAXWORD) {
554 >        str[i++] = lnext;
555 >        lnext = scan();
556 >        if (i == 1 && !isdigit(lnext))
557 >            syntax("badly formed number");
558 >        while (isdigit(lnext) && i < RMAXWORD) {
559 >            str[i++] = lnext;
560 >            lnext = scan();
561          }
562      }
563 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
564 <        str[i++] = nextc;
565 <        scan();
566 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
567 <            str[i++] = nextc;
568 <            scan();
563 >    if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
564 >        str[i++] = lnext;
565 >        lnext = scan();
566 >        if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
567 >            str[i++] = lnext;
568 >            lnext = scan();
569          }
570 <        while (isdigit(nextc) && i < MAXWORD) {
571 <            str[i++] = nextc;
572 <            scan();
570 >        if (!isdigit(lnext))
571 >            syntax("missing exponent");
572 >        while (isdigit(lnext) && i < RMAXWORD) {
573 >            str[i++] = lnext;
574 >            lnext = scan();
575          }
576      }
577      str[i] = '\0';
# Line 484 | Line 581 | getnum()                       /* scan a positive float */
581  
582  
583   EPNODE *
584 < getE1()                         /* E1 -> E1 ADDOP E2 */
585 <                                /*       E2 */
584 > getE1(void)                             /* E1 -> E1 ADDOP E2 */
585 >                                /*       E2 */
586   {
587      register EPNODE  *ep1, *ep2;
588  
# Line 496 | Line 593 | getE1()                                /* E1 -> E1 ADDOP E2 */
593          scan();
594          addekid(ep2, ep1);
595          addekid(ep2, getE2());
596 < #ifdef  RCONST
597 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
596 >        if (esupport&E_RCONST &&
597 >                        ep1->type == NUM && ep1->sibling->type == NUM)
598                  ep2 = rconst(ep2);
502 #endif
599          ep1 = ep2;
600      }
601      return(ep1);
# Line 507 | Line 603 | getE1()                                /* E1 -> E1 ADDOP E2 */
603  
604  
605   EPNODE *
606 < getE2()                         /* E2 -> E2 MULOP E3 */
607 <                                /*       E3 */
606 > getE2(void)                             /* E2 -> E2 MULOP E3 */
607 >                                /*       E3 */
608   {
609      register EPNODE  *ep1, *ep2;
610  
# Line 519 | Line 615 | getE2()                                /* E2 -> E2 MULOP E3 */
615          scan();
616          addekid(ep2, ep1);
617          addekid(ep2, getE3());
618 < #ifdef  RCONST
619 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
618 >        if (esupport&E_RCONST &&
619 >                        ep1->type == NUM && ep1->sibling->type == NUM)
620                  ep2 = rconst(ep2);
525 #endif
621          ep1 = ep2;
622      }
623      return(ep1);
# Line 530 | Line 625 | getE2()                                /* E2 -> E2 MULOP E3 */
625  
626  
627   EPNODE *
628 < getE3()                         /* E3 -> E4 ^ E3 */
629 <                                /*       E4 */
628 > getE3(void)                             /* E3 -> E4 ^ E3 */
629 >                                /*       E4 */
630   {
631      register EPNODE  *ep1, *ep2;
632  
# Line 542 | Line 637 | getE3()                                /* E3 -> E4 ^ E3 */
637          scan();
638          addekid(ep2, ep1);
639          addekid(ep2, getE3());
640 < #ifdef  RCONST
641 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
640 >        if (esupport&E_RCONST &&
641 >                        ep1->type == NUM && ep1->sibling->type == NUM)
642                  ep2 = rconst(ep2);
548 #endif
643          return(ep2);
644      }
645      return(ep1);
# Line 553 | Line 647 | getE3()                                /* E3 -> E4 ^ E3 */
647  
648  
649   EPNODE *
650 < getE4()                         /* E4 -> ADDOP E5 */
651 <                                /*       E5 */
650 > getE4(void)                             /* E4 -> ADDOP E5 */
651 >                                /*       E5 */
652   {
653      register EPNODE  *ep1, *ep2;
654  
# Line 565 | Line 659 | getE4()                                /* E4 -> ADDOP E5 */
659                  ep2->v.num = -ep2->v.num;
660                  return(ep2);
661          }
662 +        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
663 +            efree((char *)ep2);
664 +            return(ep2->v.kid);
665 +        }
666          ep1 = newnode();
667          ep1->type = UMINUS;
668          addekid(ep1, ep2);
# Line 577 | Line 675 | getE4()                                /* E4 -> ADDOP E5 */
675  
676  
677   EPNODE *
678 < getE5()                         /* E5 -> (E1) */
679 <                                /*       VAR */
680 <                                /*       NUM */
681 <                                /*       $N */
682 <                                /*       FUNC(E1,..) */
683 <                                /*       ARG */
678 > getE5(void)                     /* E5 -> (E1) */
679 >                                /*       VAR */
680 >                                /*       NUM */
681 >                                /*       $N */
682 >                                /*       FUNC(E1,..) */
683 >                                /*       ARG */
684   {
685 <    int  i;
686 <    register EPNODE  *ep1, *ep2;
685 >        int      i;
686 >        char  *nam;
687 >        register EPNODE  *ep1, *ep2;
688  
689 <    if (nextc == '(') {
690 <        scan();
691 <        ep1 = getE1();
692 <        if (nextc != ')')
693 <            syntax("')' expected");
694 <        scan();
695 <        return(ep1);
696 <    }
689 >        if (nextc == '(') {
690 >                scan();
691 >                ep1 = getE1();
692 >                if (nextc != ')')
693 >                        syntax("')' expected");
694 >                scan();
695 >                return(ep1);
696 >        }
697  
698 < #ifdef  INCHAN
699 <    if (nextc == '$') {
700 <        scan();
701 <        ep1 = newnode();
702 <        ep1->type = CHAN;
703 <        ep1->v.chan = getinum();
704 <        return(ep1);
606 <    }
607 < #endif
698 >        if (esupport&E_INCHAN && nextc == '$') {
699 >                scan();
700 >                ep1 = newnode();
701 >                ep1->type = CHAN;
702 >                ep1->v.chan = getinum();
703 >                return(ep1);
704 >        }
705  
706 < #if  defined(VARIABLE) || defined(FUNCTION)
707 <    if (isalpha(nextc)) {
708 <        ep1 = newnode();
709 <        ep1->type = VAR;
710 <        ep1->v.ln = varinsert(getname());
711 <
712 < #if  defined(VARIABLE) && defined(FUNCTION)
713 <        if (curfunc != NULL)
714 <            for (i = 1, ep2 = curfunc->v.kid->sibling;
715 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
716 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
717 <                    epfree(ep1);
718 <                    ep1 = newnode();
719 <                    ep1->type = ARG;
720 <                    ep1->v.chan = i;
721 <                    break;
706 >        if (esupport&(E_VARIABLE|E_FUNCTION) &&
707 >                        (isalpha(nextc) || nextc == CNTXMARK)) {
708 >                nam = getname();
709 >                ep1 = NULL;
710 >                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
711 >                                && curfunc != NULL)
712 >                        for (i = 1, ep2 = curfunc->v.kid->sibling;
713 >                                        ep2 != NULL; i++, ep2 = ep2->sibling)
714 >                                if (!strcmp(ep2->v.name, nam)) {
715 >                                        ep1 = newnode();
716 >                                        ep1->type = ARG;
717 >                                        ep1->v.chan = i;
718 >                                        break;
719 >                                }
720 >                if (ep1 == NULL) {
721 >                        ep1 = newnode();
722 >                        ep1->type = VAR;
723 >                        ep1->v.ln = varinsert(nam);
724                  }
725 < #endif
726 < #ifdef  FUNCTION
727 <        if (nextc == '(') {
728 <            ep2 = newnode();
729 <            ep2->type = FUNC;
730 <            addekid(ep2, ep1);
731 <            ep1 = ep2;
732 <            do {
733 <                scan();
734 <                addekid(ep1, getE1());
735 <            } while (nextc == ',');
736 <            if (nextc != ')')
737 <                syntax("')' expected");
738 <            scan();
725 >                if (esupport&E_FUNCTION && nextc == '(') {
726 >                        ep2 = newnode();
727 >                        ep2->type = FUNC;
728 >                        addekid(ep2, ep1);
729 >                        ep1 = ep2;
730 >                        do {
731 >                                scan();
732 >                                addekid(ep1, getE1());
733 >                        } while (nextc == ',');
734 >                        if (nextc != ')')
735 >                                syntax("')' expected");
736 >                        scan();
737 >                } else if (!(esupport&E_VARIABLE))
738 >                        syntax("'(' expected");
739 >                if (esupport&E_RCONST && isconstvar(ep1))
740 >                        ep1 = rconst(ep1);
741 >                return(ep1);
742          }
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
743  
744 <    if (isdecimal(nextc)) {
745 <        ep1 = newnode();
746 <        ep1->type = NUM;
747 <        ep1->v.num = getnum();
748 <        return(ep1);
749 <    }
750 <    syntax("unexpected character");
744 >        if (isdecimal(nextc)) {
745 >                ep1 = newnode();
746 >                ep1->type = NUM;
747 >                ep1->v.num = getnum();
748 >                return(ep1);
749 >        }
750 >        syntax("unexpected character");
751 >        return NULL; /* pro forma return */
752   }
753  
754  
664 #ifdef  RCONST
755   EPNODE *
756 < rconst(epar)                    /* reduce a constant expression */
757 < register EPNODE  *epar;
756 > rconst(                 /* reduce a constant expression */
757 >    register EPNODE      *epar
758 > )
759   {
760      register EPNODE  *ep;
761  
# Line 672 | Line 763 | register EPNODE  *epar;
763      ep->type = NUM;
764      errno = 0;
765      ep->v.num = evalue(epar);
766 <    if (errno)
767 <        syntax("bad constant expression");
766 >    if (errno == EDOM || errno == ERANGE)
767 >        syntax("bad constant expression");
768      epfree(epar);
769  
770      return(ep);
771   }
772  
773  
774 < isconstvar(ep)                  /* is ep linked to a constant? */
775 < register EPNODE  *ep;
774 > int
775 > isconstvar(                     /* is ep linked to a constant expression? */
776 >    register EPNODE      *ep
777 > )
778   {
686 #ifdef  VARIABLE
779      register EPNODE  *ep1;
688 #ifdef  FUNCTION
689    LIBR  *lp;
780  
781 <    if (ep->type == FUNC) {
782 <        if (ep->v.kid->type != VAR)
783 <            return(0);
694 <        ep1 = ep->v.kid->v.ln->def;
695 <        if (ep1 != NULL && ep1->type != ':')
696 <            return(0);
697 <        if ((ep1 == NULL || ep1->v.kid->type != FUNC)
698 <                && ((lp = liblookup(ep->v.kid->v.ln->name)) == NULL
699 <                        || lp->atyp != ':'))
700 <            return(0);
781 >    if (esupport&E_FUNCTION && ep->type == FUNC) {
782 >        if (!isconstfun(ep->v.kid))
783 >                return(0);
784          for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
785 <            if (ep1->type != NUM)
785 >            if (ep1->type != NUM && !isconstfun(ep1))
786                  return(0);
787          return(1);
788      }
706 #endif
789      if (ep->type != VAR)
790          return(0);
791      ep1 = ep->v.ln->def;
792      if (ep1 == NULL || ep1->type != ':')
793          return(0);
794 < #ifdef  FUNCTION
713 <    if (ep1->v.kid->type != SYM)
794 >    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
795          return(0);
715 #endif
796      return(1);
717 #else
718    return(ep->type == FUNC);
719 #endif
797   }
798 < #endif
798 >
799 >
800 > int
801 > isconstfun(                     /* is ep linked to a constant function? */
802 >    register EPNODE      *ep
803 > )
804 > {
805 >    register EPNODE  *dp;
806 >    register LIBR  *lp;
807 >
808 >    if (ep->type != VAR)
809 >        return(0);
810 >    if ((dp = ep->v.ln->def) != NULL) {
811 >        if (dp->v.kid->type == FUNC)
812 >            return(dp->type == ':');
813 >        else
814 >            return(0);          /* don't identify masked library functions */
815 >    }
816 >    if ((lp = ep->v.ln->lib) != NULL)
817 >        return(lp->atyp == ':');
818 >    return(0);
819 > }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines