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.1 by greg, Thu Feb 2 10:34:27 1989 UTC vs.
Revision 2.27 by greg, Mon Aug 4 19:20:26 2003 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  "rterror.h"
30   #include  "calcomp.h"
31  
32 < #define  MAXLINE        256             /* maximum line length */
30 < #define  MAXWORD        64              /* maximum word length */
32 > #define  MAXLINE        256             /* maximum line length */
33  
34 < #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
34 > #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
35  
36 < #define  isid(c)        (isalnum(c) || (c) == '_' || (c) == '.')
36 > #define  isdecimal(c)   (isdigit(c) || (c) == '.')
37  
38 < #define  isdecimal(c)   (isdigit(c) || (c) == '.')
38 > static double  euminus(EPNODE *), eargument(EPNODE *), enumber(EPNODE *);
39 > static double  echannel(EPNODE *);
40 > static double  eadd(EPNODE *), esubtr(EPNODE *),
41 >               emult(EPNODE *), edivi(EPNODE *),
42 >               epow(EPNODE *);
43 > static double  ebotch(EPNODE *);
44  
45 < extern double  atof(), pow();
46 < extern char  *fgets(), *savestr();
40 < extern char  *emalloc(), *ecalloc();
41 < extern EPNODE  *curfunc;
42 < extern double  efunc(), evariable(), enumber(), euminus(), echannel();
43 < extern double  eargument(), eadd(), esubtr(), emult(), edivi(), epow();
44 < extern double  ebotch();
45 < extern int  errno;
45 > unsigned int  esupport =                /* what to support */
46 >                E_VARIABLE | E_FUNCTION ;
47  
48   int  nextc;                             /* lookahead character */
49  
50 < double  (*eoper[])() = {                /* expression operations */
50 > double  (*eoper[])(EPNODE *) = {        /* expression operations */
51          ebotch,
51 #ifdef  VARIABLE
52          evariable,
53 #else
54        ebotch,
55 #endif
53          enumber,
54          euminus,
58 #ifdef  INCHAN
55          echannel,
60 #else
61        ebotch,
62 #endif
63 #ifdef  FUNCTION
56          efunc,
57          eargument,
66 #else
58          ebotch,
59          ebotch,
69 #endif
70        ebotch,
71        ebotch,
60          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
61          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62          emult,
# Line 77 | Line 65 | double  (*eoper[])() = {               /* expression operations */
65          esubtr,
66          0,
67          edivi,
68 <        0,0,0,0,0,0,0,0,0,0,0,0,0,
68 >        0,0,0,0,0,0,0,0,0,0,
69          ebotch,
70 +        0,0,
71 +        ebotch,
72          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74          epow,
75   };
76  
87 static char  *infile;                   /* input file name */
77   static FILE  *infp;                     /* input file pointer */
78   static char  *linbuf;                   /* line buffer */
79 + static char  *infile;                   /* input file name */
80 + static int  lineno;                     /* input line number */
81   static int  linepos;                    /* position in buffer */
82  
83  
# Line 96 | Line 87 | char  *expr;
87   {
88      EPNODE  *ep;
89  
90 <    initstr(NULL, expr);
100 < #if  defined(VARIABLE) && defined(FUNCTION)
90 >    initstr(expr, NULL, 0);
91      curfunc = NULL;
102 #endif
92      ep = getE1();
93      if (nextc != EOF)
94          syntax("unexpected character");
# Line 121 | Line 110 | char  *expr;
110   }
111  
112  
113 + int
114 + epcmp(ep1, ep2)                 /* compare two expressions for equivalence */
115 + register EPNODE  *ep1, *ep2;
116 + {
117 +        double  d;
118 +
119 +        if (ep1->type != ep2->type)
120 +                return(1);
121 +
122 +        switch (ep1->type) {
123 +
124 +        case VAR:
125 +                return(ep1->v.ln != ep2->v.ln);
126 +
127 +        case NUM:
128 +                if (ep2->v.num == 0)
129 +                        return(ep1->v.num != 0);
130 +                d = ep1->v.num / ep2->v.num;
131 +                return((d > 1.000000000001) | (d < 0.999999999999));
132 +
133 +        case CHAN:
134 +        case ARG:
135 +                return(ep1->v.chan != ep2->v.chan);
136 +
137 +        case '=':
138 +        case ':':
139 +                return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling));
140 +
141 +        case TICK:
142 +        case SYM:                       /* should never get this one */
143 +                return(0);
144 +
145 +        default:
146 +                ep1 = ep1->v.kid;
147 +                ep2 = ep2->v.kid;
148 +                while (ep1 != NULL) {
149 +                        if (ep2 == NULL)
150 +                                return(1);
151 +                        if (epcmp(ep1, ep2))
152 +                                return(1);
153 +                        ep1 = ep1->sibling;
154 +                        ep2 = ep2->sibling;
155 +                }
156 +                return(ep2 != NULL);
157 +        }
158 + }
159 +
160 +
161 + void
162   epfree(epar)                    /* free a parse tree */
163 < register EPNODE  *epar;
163 > register EPNODE  *epar;
164   {
165      register EPNODE  *ep;
166  
# Line 143 | Line 181 | register EPNODE  *epar;
181              break;
182  
183          default:
184 <            for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
184 >            while ((ep = epar->v.kid) != NULL) {
185 >                epar->v.kid = ep->sibling;
186                  epfree(ep);
187 +            }
188              break;
189  
190      }
# Line 153 | Line 193 | register EPNODE  *epar;
193   }
194  
195                                  /* the following used to be a switch */
156 #ifdef  FUNCTION
196   static double
197   eargument(ep)
198 < EPNODE  *ep;
198 > EPNODE  *ep;
199   {
200      return(argument(ep->v.chan));
201   }
163 #endif
202  
203   static double
204   enumber(ep)
205 < EPNODE  *ep;
205 > EPNODE  *ep;
206   {
207      return(ep->v.num);
208   }
209  
210   static double
211   euminus(ep)
212 < EPNODE  *ep;
212 > EPNODE  *ep;
213   {
214      register EPNODE  *ep1 = ep->v.kid;
215  
216      return(-evalue(ep1));
217   }
218  
181 #ifdef  INCHAN
219   static double
220   echannel(ep)
221 < EPNODE  *ep;
221 > EPNODE  *ep;
222   {
223      return(chanvalue(ep->v.chan));
224   }
188 #endif
225  
226   static double
227   eadd(ep)
228 < EPNODE  *ep;
228 > EPNODE  *ep;
229   {
230      register EPNODE  *ep1 = ep->v.kid;
231  
# Line 198 | Line 234 | EPNODE  *ep;
234  
235   static double
236   esubtr(ep)
237 < EPNODE  *ep;
237 > EPNODE  *ep;
238   {
239      register EPNODE  *ep1 = ep->v.kid;
240  
# Line 207 | Line 243 | EPNODE  *ep;
243  
244   static double
245   emult(ep)
246 < EPNODE  *ep;
246 > EPNODE  *ep;
247   {
248      register EPNODE  *ep1 = ep->v.kid;
249  
# Line 216 | Line 252 | EPNODE  *ep;
252  
253   static double
254   edivi(ep)
255 < EPNODE  *ep;
255 > EPNODE  *ep;
256   {
257      register EPNODE  *ep1 = ep->v.kid;
258      double  d;
# Line 232 | Line 268 | EPNODE  *ep;
268  
269   static double
270   epow(ep)
271 < EPNODE  *ep;
271 > EPNODE  *ep;
272   {
273      register EPNODE  *ep1 = ep->v.kid;
274      double  d;
275 <    int  lasterrno;
275 >    int  lasterrno;
276  
277      lasterrno = errno;
278      errno = 0;
279      d = pow(evalue(ep1), evalue(ep1->sibling));
280 < #ifdef  IEEE
280 > #ifdef  IEEE
281      if (!finite(d))
282          errno = EDOM;
283   #endif
284 <    if (errno) {
284 >    if (errno == EDOM || errno == ERANGE) {
285          wputs("Illegal power\n");
286          return(0.0);
287      }
# Line 255 | Line 291 | EPNODE  *ep;
291  
292   static double
293   ebotch(ep)
294 < EPNODE  *ep;
294 > EPNODE  *ep;
295   {
296      eputs("Bad expression!\n");
297      quit(1);
298 +        return 0.0; /* pro forma return */
299   }
300  
301  
302   EPNODE *
303   ekid(ep, n)                     /* return pointer to a node's nth kid */
304 < register EPNODE  *ep;
304 > register EPNODE  *ep;
305   register int  n;
306   {
307  
# Line 278 | Line 315 | register int  n;
315  
316   int
317   nekids(ep)                      /* return # of kids for node ep */
318 < register EPNODE  *ep;
318 > register EPNODE  *ep;
319   {
320      register int  n = 0;
321  
# Line 289 | Line 326 | register EPNODE  *ep;
326   }
327  
328  
329 < initfile(file, fp)              /* prepare input file */
330 < char  *file;
329 > void
330 > initfile(fp, fn, ln)            /* prepare input file */
331   FILE  *fp;
332 + char  *fn;
333 + int  ln;
334   {
335 <    static char  inpbuf[MAXLINE];
335 >    static char  inpbuf[MAXLINE];
336  
298    infile = file;
337      infp = fp;
338      linbuf = inpbuf;
339 +    infile = fn;
340 +    lineno = ln;
341      linepos = 0;
342      inpbuf[0] = '\0';
343      scan();
344   }
345  
346  
347 < initstr(file, s)                /* prepare input string */
348 < char  *file;
347 > void
348 > initstr(s, fn, ln)              /* prepare input string */
349   char  *s;
350 + char  *fn;
351 + int  ln;
352   {
311    infile = file;
353      infp = NULL;
354 +    infile = fn;
355 +    lineno = ln;
356      linbuf = s;
357      linepos = 0;
358      scan();
359   }
360  
361  
362 < scan()                          /* scan next character */
362 > void
363 > getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
364 > char  **fnp;
365 > int  *lnp;
366 > char  **spp;
367 > FILE  **fpp;
368   {
369 +    if (fnp != NULL) *fnp = infile;
370 +    if (lnp != NULL) *lnp = lineno;
371 +    if (spp != NULL) *spp = linbuf+linepos;
372 +    if (fpp != NULL) *fpp = infp;
373 + }
374 +
375 +
376 + int
377 + scan()                          /* scan next character, return literal next */
378 + {
379 +    register int  lnext = 0;
380 +
381      do {
382          if (linbuf[linepos] == '\0')
383              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
384                  nextc = EOF;
385              else {
386                  nextc = linbuf[0];
387 +                lineno++;
388                  linepos = 1;
389              }
390          else
391              nextc = linbuf[linepos++];
392 +        if (!lnext)
393 +                lnext = nextc;
394          if (nextc == '{') {
395              scan();
396              while (nextc != '}')
# Line 338 | Line 401 | scan()                         /* scan next character */
401              scan();
402          }
403      } while (isspace(nextc));
404 +    return(lnext);
405   }
406  
407  
408 + char *
409 + long2ascii(l)                         /* convert long to ascii */
410 + long  l;
411 + {
412 +    static char  buf[16];
413 +    register char  *cp;
414 +    int  neg = 0;
415 +
416 +    if (l == 0)
417 +        return("0");
418 +    if (l < 0) {
419 +        l = -l;
420 +        neg++;
421 +    }
422 +    cp = buf + sizeof(buf);
423 +    *--cp = '\0';
424 +    while (l) {
425 +        *--cp = l % 10 + '0';
426 +        l /= 10;
427 +    }
428 +    if (neg)
429 +        *--cp = '-';
430 +    return(cp);
431 + }
432 +
433 +
434 + void
435   syntax(err)                     /* report syntax error and quit */
436   char  *err;
437   {
438      register int  i;
439  
440 +    if (infile != NULL || lineno != 0) {
441 +        if (infile != NULL) eputs(infile);
442 +        if (lineno != 0) {
443 +            eputs(infile != NULL ? ", line " : "line ");
444 +            eputs(long2ascii((long)lineno));
445 +        }
446 +        eputs(":\n");
447 +    }
448      eputs(linbuf);
449 <    if (linbuf[0] == '\0' || linbuf[strlen(linbuf)-1] != '\n')
449 >    if (linbuf[strlen(linbuf)-1] != '\n')
450          eputs("\n");
451      for (i = 0; i < linepos-1; i++)
452          eputs(linbuf[i] == '\t' ? "\t" : " ");
453      eputs("^ ");
355    if (infile != NULL) {
356        eputs(infile);
357        eputs(": ");
358    }
454      eputs(err);
455      eputs("\n");
456      quit(1);
457   }
458  
459  
460 + void
461   addekid(ep, ekid)                       /* add a child to ep */
462 < register EPNODE  *ep;
463 < EPNODE  *ekid;
462 > register EPNODE  *ep;
463 > EPNODE  *ekid;
464   {
465      if (ep->v.kid == NULL)
466          ep->v.kid = ekid;
# Line 380 | Line 476 | EPNODE  *ekid;
476   char *
477   getname()                       /* scan an identifier */
478   {
479 <    static char  str[MAXWORD+1];
480 <    register int  i;
479 >    static char  str[RMAXWORD+1];
480 >    register int  i, lnext;
481  
482 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
483 <        str[i] = nextc;
482 >    lnext = nextc;
483 >    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
484 >        str[i] = lnext;
485      str[i] = '\0';
486 +    while (isid(lnext))         /* skip rest of name */
487 +        lnext = scan();
488  
489      return(str);
490   }
# Line 394 | Line 493 | getname()                      /* scan an identifier */
493   int
494   getinum()                       /* scan a positive integer */
495   {
496 <    register int  n;
496 >    register int  n, lnext;
497  
498      n = 0;
499 <    while (isdigit(nextc)) {
500 <        n = n * 10 + nextc - '0';
501 <        scan();
499 >    lnext = nextc;
500 >    while (isdigit(lnext)) {
501 >        n = n * 10 + lnext - '0';
502 >        lnext = scan();
503      }
504      return(n);
505   }
# Line 408 | Line 508 | getinum()                      /* scan a positive integer */
508   double
509   getnum()                        /* scan a positive float */
510   {
511 <    register int  i;
512 <    char  str[MAXWORD+1];
511 >    register int  i, lnext;
512 >    char  str[RMAXWORD+1];
513  
514      i = 0;
515 <    while (isdigit(nextc) && i < MAXWORD) {
516 <        str[i++] = nextc;
517 <        scan();
515 >    lnext = nextc;
516 >    while (isdigit(lnext) && i < RMAXWORD) {
517 >        str[i++] = lnext;
518 >        lnext = scan();
519      }
520 <    if (nextc == '.' && i < MAXWORD) {
521 <        str[i++] = nextc;
522 <        scan();
523 <        while (isdigit(nextc) && i < MAXWORD) {
524 <            str[i++] = nextc;
525 <            scan();
520 >    if (lnext == '.' && i < RMAXWORD) {
521 >        str[i++] = lnext;
522 >        lnext = scan();
523 >        if (i == 1 && !isdigit(lnext))
524 >            syntax("badly formed number");
525 >        while (isdigit(lnext) && i < RMAXWORD) {
526 >            str[i++] = lnext;
527 >            lnext = scan();
528          }
529      }
530 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
531 <        str[i++] = nextc;
532 <        scan();
533 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
534 <            str[i++] = nextc;
535 <            scan();
530 >    if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
531 >        str[i++] = lnext;
532 >        lnext = scan();
533 >        if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
534 >            str[i++] = lnext;
535 >            lnext = scan();
536          }
537 <        while (isdigit(nextc) && i < MAXWORD) {
538 <            str[i++] = nextc;
539 <            scan();
537 >        if (!isdigit(lnext))
538 >            syntax("missing exponent");
539 >        while (isdigit(lnext) && i < RMAXWORD) {
540 >            str[i++] = lnext;
541 >            lnext = scan();
542          }
543      }
544      str[i] = '\0';
# Line 444 | Line 549 | getnum()                       /* scan a positive float */
549  
550   EPNODE *
551   getE1()                         /* E1 -> E1 ADDOP E2 */
552 <                                /*       E2 */
552 >                                /*       E2 */
553   {
554      register EPNODE  *ep1, *ep2;
555  
# Line 455 | Line 560 | getE1()                                /* E1 -> E1 ADDOP E2 */
560          scan();
561          addekid(ep2, ep1);
562          addekid(ep2, getE2());
563 < #ifdef  RCONST
564 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
563 >        if (esupport&E_RCONST &&
564 >                        ep1->type == NUM && ep1->sibling->type == NUM)
565                  ep2 = rconst(ep2);
461 #endif
566          ep1 = ep2;
567      }
568      return(ep1);
# Line 467 | Line 571 | getE1()                                /* E1 -> E1 ADDOP E2 */
571  
572   EPNODE *
573   getE2()                         /* E2 -> E2 MULOP E3 */
574 <                                /*       E3 */
574 >                                /*       E3 */
575   {
576      register EPNODE  *ep1, *ep2;
577  
# Line 478 | Line 582 | getE2()                                /* E2 -> E2 MULOP E3 */
582          scan();
583          addekid(ep2, ep1);
584          addekid(ep2, getE3());
585 < #ifdef  RCONST
586 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
585 >        if (esupport&E_RCONST &&
586 >                        ep1->type == NUM && ep1->sibling->type == NUM)
587                  ep2 = rconst(ep2);
484 #endif
588          ep1 = ep2;
589      }
590      return(ep1);
# Line 489 | Line 592 | getE2()                                /* E2 -> E2 MULOP E3 */
592  
593  
594   EPNODE *
595 < getE3()                         /* E3 -> E3 ^ E4 */
596 <                                /*       E4 */
595 > getE3()                         /* E3 -> E4 ^ E3 */
596 >                                /*       E4 */
597   {
598      register EPNODE  *ep1, *ep2;
599  
600      ep1 = getE4();
601 <    while (nextc == '^') {
601 >    if (nextc == '^') {
602          ep2 = newnode();
603          ep2->type = nextc;
604          scan();
605          addekid(ep2, ep1);
606 <        addekid(ep2, getE4());
607 < #ifdef  RCONST
608 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
606 >        addekid(ep2, getE3());
607 >        if (esupport&E_RCONST &&
608 >                        ep1->type == NUM && ep1->sibling->type == NUM)
609                  ep2 = rconst(ep2);
610 < #endif
508 <        ep1 = ep2;
610 >        return(ep2);
611      }
612      return(ep1);
613   }
# Line 513 | Line 615 | getE3()                                /* E3 -> E3 ^ E4 */
615  
616   EPNODE *
617   getE4()                         /* E4 -> ADDOP E5 */
618 <                                /*       E5 */
618 >                                /*       E5 */
619   {
620 <    register EPNODE  *ep1;
620 >    register EPNODE  *ep1, *ep2;
621  
622      if (nextc == '-') {
623          scan();
624 <        ep1 = newnode();
625 < #ifndef  RCONST
626 <        if (isdecimal(nextc)) {
627 <            ep1->type = NUM;
526 <            ep1->v.num = -getnum();
527 <            return(ep1);
624 >        ep2 = getE5();
625 >        if (ep2->type == NUM) {
626 >                ep2->v.num = -ep2->v.num;
627 >                return(ep2);
628          }
629 < #endif
629 >        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
630 >            efree((char *)ep2);
631 >            return(ep2->v.kid);
632 >        }
633 >        ep1 = newnode();
634          ep1->type = UMINUS;
635 <        addekid(ep1, getE5());
532 < #ifdef  RCONST
533 <        if (ep1->v.kid->type == NUM)
534 <                ep1 = rconst(ep1);
535 < #endif
635 >        addekid(ep1, ep2);
636          return(ep1);
637      }
638      if (nextc == '+')
# Line 543 | Line 643 | getE4()                                /* E4 -> ADDOP E5 */
643  
644   EPNODE *
645   getE5()                         /* E5 -> (E1) */
646 <                                /*       VAR */
647 <                                /*       NUM */
648 <                                /*       $N */
649 <                                /*       FUNC(E1,..) */
650 <                                /*       ARG */
646 >                                /*       VAR */
647 >                                /*       NUM */
648 >                                /*       $N */
649 >                                /*       FUNC(E1,..) */
650 >                                /*       ARG */
651   {
652 <    int  i;
653 <    register EPNODE  *ep1, *ep2;
652 >        int      i;
653 >        char  *nam;
654 >        register EPNODE  *ep1, *ep2;
655  
656 <    if (nextc == '(') {
657 <        scan();
658 <        ep1 = getE1();
659 <        if (nextc != ')')
660 <            syntax("')' expected");
661 <        scan();
662 <        return(ep1);
663 <    }
656 >        if (nextc == '(') {
657 >                scan();
658 >                ep1 = getE1();
659 >                if (nextc != ')')
660 >                        syntax("')' expected");
661 >                scan();
662 >                return(ep1);
663 >        }
664  
665 < #ifdef  INCHAN
666 <    if (nextc == '$') {
667 <        scan();
668 <        ep1 = newnode();
669 <        ep1->type = CHAN;
670 <        ep1->v.chan = getinum();
671 <        return(ep1);
571 <    }
572 < #endif
665 >        if (esupport&E_INCHAN && nextc == '$') {
666 >                scan();
667 >                ep1 = newnode();
668 >                ep1->type = CHAN;
669 >                ep1->v.chan = getinum();
670 >                return(ep1);
671 >        }
672  
673 < #if  defined(VARIABLE) || defined(FUNCTION)
674 <    if (isalpha(nextc)) {
675 <        ep1 = newnode();
676 <        ep1->type = VAR;
677 <        ep1->v.ln = varinsert(getname());
678 <
679 < #if  defined(VARIABLE) && defined(FUNCTION)
680 <        if (curfunc != NULL)
681 <            for (i = 1, ep2 = curfunc->v.kid->sibling;
682 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
683 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
684 <                    epfree(ep1);
685 <                    ep1 = newnode();
686 <                    ep1->type = ARG;
687 <                    ep1->v.chan = i;
688 <                    break;
673 >        if (esupport&(E_VARIABLE|E_FUNCTION) &&
674 >                        (isalpha(nextc) || nextc == CNTXMARK)) {
675 >                nam = getname();
676 >                ep1 = NULL;
677 >                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
678 >                                && curfunc != NULL)
679 >                        for (i = 1, ep2 = curfunc->v.kid->sibling;
680 >                                        ep2 != NULL; i++, ep2 = ep2->sibling)
681 >                                if (!strcmp(ep2->v.name, nam)) {
682 >                                        ep1 = newnode();
683 >                                        ep1->type = ARG;
684 >                                        ep1->v.chan = i;
685 >                                        break;
686 >                                }
687 >                if (ep1 == NULL) {
688 >                        ep1 = newnode();
689 >                        ep1->type = VAR;
690 >                        ep1->v.ln = varinsert(nam);
691                  }
692 < #endif
693 < #ifdef  FUNCTION
694 <        if (nextc == '(') {
695 <            ep2 = newnode();
696 <            ep2->type = FUNC;
697 <            addekid(ep2, ep1);
698 <            ep1 = ep2;
699 <            do {
700 <                scan();
701 <                addekid(ep1, getE1());
702 <            } while (nextc == ',');
703 <            if (nextc != ')')
704 <                syntax("')' expected");
705 <            scan();
692 >                if (esupport&E_FUNCTION && nextc == '(') {
693 >                        ep2 = newnode();
694 >                        ep2->type = FUNC;
695 >                        addekid(ep2, ep1);
696 >                        ep1 = ep2;
697 >                        do {
698 >                                scan();
699 >                                addekid(ep1, getE1());
700 >                        } while (nextc == ',');
701 >                        if (nextc != ')')
702 >                                syntax("')' expected");
703 >                        scan();
704 >                } else if (!(esupport&E_VARIABLE))
705 >                        syntax("'(' expected");
706 >                if (esupport&E_RCONST && isconstvar(ep1))
707 >                        ep1 = rconst(ep1);
708 >                return(ep1);
709          }
606 #ifndef  VARIABLE
607        else
608            syntax("'(' expected");
609 #endif
610 #endif
611        return(ep1);
612    }
613 #endif
710  
711 <    if (isdecimal(nextc)) {
712 <        ep1 = newnode();
713 <        ep1->type = NUM;
714 <        ep1->v.num = getnum();
715 <        return(ep1);
716 <    }
717 <    syntax("unexpected character");
711 >        if (isdecimal(nextc)) {
712 >                ep1 = newnode();
713 >                ep1->type = NUM;
714 >                ep1->v.num = getnum();
715 >                return(ep1);
716 >        }
717 >        syntax("unexpected character");
718 >        return NULL; /* pro forma return */
719   }
720  
721  
625 #ifdef  RCONST
722   EPNODE *
723   rconst(epar)                    /* reduce a constant expression */
724 < register EPNODE  *epar;
724 > register EPNODE  *epar;
725   {
726      register EPNODE  *ep;
727  
# Line 633 | Line 729 | register EPNODE  *epar;
729      ep->type = NUM;
730      errno = 0;
731      ep->v.num = evalue(epar);
732 <    if (errno)
733 <        syntax("bad constant expression");
732 >    if (errno == EDOM || errno == ERANGE)
733 >        syntax("bad constant expression");
734      epfree(epar);
735  
736      return(ep);
737   }
738 < #endif
738 >
739 >
740 > int
741 > isconstvar(ep)                  /* is ep linked to a constant expression? */
742 > register EPNODE  *ep;
743 > {
744 >    register EPNODE  *ep1;
745 >
746 >    if (esupport&E_FUNCTION && ep->type == FUNC) {
747 >        if (!isconstfun(ep->v.kid))
748 >                return(0);
749 >        for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
750 >            if (ep1->type != NUM && !isconstfun(ep1))
751 >                return(0);
752 >        return(1);
753 >    }
754 >    if (ep->type != VAR)
755 >        return(0);
756 >    ep1 = ep->v.ln->def;
757 >    if (ep1 == NULL || ep1->type != ':')
758 >        return(0);
759 >    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
760 >        return(0);
761 >    return(1);
762 > }
763 >
764 >
765 > int
766 > isconstfun(ep)                  /* is ep linked to a constant function? */
767 > register EPNODE  *ep;
768 > {
769 >    register EPNODE  *dp;
770 >    register LIBR  *lp;
771 >
772 >    if (ep->type != VAR)
773 >        return(0);
774 >    if ((dp = ep->v.ln->def) != NULL) {
775 >        if (dp->v.kid->type == FUNC)
776 >            return(dp->type == ':');
777 >        else
778 >            return(0);          /* don't identify masked library functions */
779 >    }
780 >    if ((lp = ep->v.ln->lib) != NULL)
781 >        return(lp->atyp == ':');
782 >    return(0);
783 > }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines