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.3 by greg, Wed Jun 14 22:29:01 1989 UTC vs.
Revision 2.20 by greg, Wed Mar 5 16:16:52 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 "copyright.h"
21 +
22   #include  <stdio.h>
23  
24   #include  <ctype.h>
25  
26   #include  <errno.h>
27  
28 + #include  <math.h>
29 +
30 + #include  <stdlib.h>
31 +
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(), eargument(), enumber();
41 > static double  echannel();
42 > static double  eadd(), esubtr(), emult(), edivi(), epow();
43 > static double  ebotch();
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 | E_REDEFW;
47  
48   int  nextc;                             /* lookahead character */
49  
50 < double  (*eoper[])() = {                /* expression operations */
50 > double  (*eoper[])() = {                /* 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  
167      switch (epar->type) {
168  
131 #if  defined(VARIABLE) || defined(FUNCTION)
169          case VAR:
170              varfree(epar->v.ln);
171              break;
135 #endif
172              
173          case SYM:
174              freestr(epar->v.name);
# Line 145 | 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 155 | Line 193 | register EPNODE  *epar;
193   }
194  
195                                  /* the following used to be a switch */
158 #ifdef  FUNCTION
196   static double
197   eargument(ep)
198 < EPNODE  *ep;
198 > EPNODE  *ep;
199   {
200      return(argument(ep->v.chan));
201   }
165 #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  
183 #ifdef  INCHAN
219   static double
220   echannel(ep)
221 < EPNODE  *ep;
221 > EPNODE  *ep;
222   {
223      return(chanvalue(ep->v.chan));
224   }
190 #endif
225  
226   static double
227   eadd(ep)
228 < EPNODE  *ep;
228 > EPNODE  *ep;
229   {
230      register EPNODE  *ep1 = ep->v.kid;
231  
# Line 200 | 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 209 | 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 218 | 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 234 | 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 257 | 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);
# Line 266 | Line 300 | EPNODE  *ep;
300  
301   EPNODE *
302   ekid(ep, n)                     /* return pointer to a node's nth kid */
303 < register EPNODE  *ep;
303 > register EPNODE  *ep;
304   register int  n;
305   {
306  
# Line 280 | Line 314 | register int  n;
314  
315   int
316   nekids(ep)                      /* return # of kids for node ep */
317 < register EPNODE  *ep;
317 > register EPNODE  *ep;
318   {
319      register int  n = 0;
320  
# Line 291 | Line 325 | register EPNODE  *ep;
325   }
326  
327  
328 < initfile(file, fp)              /* prepare input file */
329 < char  *file;
328 > void
329 > initfile(fp, fn, ln)            /* prepare input file */
330   FILE  *fp;
331 + char  *fn;
332 + int  ln;
333   {
334 <    static char  inpbuf[MAXLINE];
334 >    static char  inpbuf[MAXLINE];
335  
300    infile = file;
336      infp = fp;
337      linbuf = inpbuf;
338 +    infile = fn;
339 +    lineno = ln;
340      linepos = 0;
341      inpbuf[0] = '\0';
342      scan();
343   }
344  
345  
346 < initstr(file, s)                /* prepare input string */
347 < char  *file;
346 > void
347 > initstr(s, fn, ln)              /* prepare input string */
348   char  *s;
349 + char  *fn;
350 + int  ln;
351   {
313    infile = file;
352      infp = NULL;
353 +    infile = fn;
354 +    lineno = ln;
355      linbuf = s;
356      linepos = 0;
357      scan();
358   }
359  
360  
361 < scan()                          /* scan next character */
361 > void
362 > getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
363 > char  **fnp;
364 > int  *lnp;
365 > char  **spp;
366 > FILE  **fpp;
367   {
368 +    if (fnp != NULL) *fnp = infile;
369 +    if (lnp != NULL) *lnp = lineno;
370 +    if (spp != NULL) *spp = linbuf+linepos;
371 +    if (fpp != NULL) *fpp = infp;
372 + }
373 +
374 +
375 + int
376 + scan()                          /* scan next character, return literal next */
377 + {
378 +    register int  lnext = 0;
379 +
380      do {
381          if (linbuf[linepos] == '\0')
382              if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
383                  nextc = EOF;
384              else {
385                  nextc = linbuf[0];
386 +                lineno++;
387                  linepos = 1;
388              }
389          else
390              nextc = linbuf[linepos++];
391 +        if (!lnext)
392 +                lnext = nextc;
393          if (nextc == '{') {
394              scan();
395              while (nextc != '}')
# Line 340 | Line 400 | scan()                         /* scan next character */
400              scan();
401          }
402      } while (isspace(nextc));
403 +    return(lnext);
404   }
405  
406  
407 + char *
408 + long2ascii(l)                         /* convert long to ascii */
409 + long  l;
410 + {
411 +    static char  buf[16];
412 +    register char  *cp;
413 +    int  neg = 0;
414 +
415 +    if (l == 0)
416 +        return("0");
417 +    if (l < 0) {
418 +        l = -l;
419 +        neg++;
420 +    }
421 +    cp = buf + sizeof(buf);
422 +    *--cp = '\0';
423 +    while (l) {
424 +        *--cp = l % 10 + '0';
425 +        l /= 10;
426 +    }
427 +    if (neg)
428 +        *--cp = '-';
429 +    return(cp);
430 + }
431 +
432 +
433 + void
434   syntax(err)                     /* report syntax error and quit */
435   char  *err;
436   {
437      register int  i;
438  
439 +    if (infile != NULL || lineno != 0) {
440 +        if (infile != NULL) eputs(infile);
441 +        if (lineno != 0) {
442 +            eputs(infile != NULL ? ", line " : "line ");
443 +            eputs(long2ascii((long)lineno));
444 +        }
445 +        eputs(":\n");
446 +    }
447      eputs(linbuf);
448 <    if (linbuf[0] == '\0' || linbuf[strlen(linbuf)-1] != '\n')
448 >    if (linbuf[strlen(linbuf)-1] != '\n')
449          eputs("\n");
450      for (i = 0; i < linepos-1; i++)
451          eputs(linbuf[i] == '\t' ? "\t" : " ");
452      eputs("^ ");
357    if (infile != NULL) {
358        eputs(infile);
359        eputs(": ");
360    }
453      eputs(err);
454      eputs("\n");
455      quit(1);
456   }
457  
458  
459 + void
460   addekid(ep, ekid)                       /* add a child to ep */
461 < register EPNODE  *ep;
462 < EPNODE  *ekid;
461 > register EPNODE  *ep;
462 > EPNODE  *ekid;
463   {
464      if (ep->v.kid == NULL)
465          ep->v.kid = ekid;
# Line 382 | Line 475 | EPNODE  *ekid;
475   char *
476   getname()                       /* scan an identifier */
477   {
478 <    static char  str[MAXWORD+1];
479 <    register int  i;
478 >    static char  str[MAXWORD+1];
479 >    register int  i, lnext;
480  
481 <    for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
482 <        str[i] = nextc;
481 >    lnext = nextc;
482 >    for (i = 0; i < MAXWORD && isid(lnext); i++, lnext = scan())
483 >        str[i] = lnext;
484      str[i] = '\0';
485 +    while (isid(lnext))         /* skip rest of name */
486 +        lnext = scan();
487  
488      return(str);
489   }
# Line 396 | Line 492 | getname()                      /* scan an identifier */
492   int
493   getinum()                       /* scan a positive integer */
494   {
495 <    register int  n;
495 >    register int  n, lnext;
496  
497      n = 0;
498 <    while (isdigit(nextc)) {
499 <        n = n * 10 + nextc - '0';
500 <        scan();
498 >    lnext = nextc;
499 >    while (isdigit(lnext)) {
500 >        n = n * 10 + lnext - '0';
501 >        lnext = scan();
502      }
503      return(n);
504   }
# Line 410 | Line 507 | getinum()                      /* scan a positive integer */
507   double
508   getnum()                        /* scan a positive float */
509   {
510 <    register int  i;
510 >    register int  i, lnext;
511      char  str[MAXWORD+1];
512  
513      i = 0;
514 <    while (isdigit(nextc) && i < MAXWORD) {
515 <        str[i++] = nextc;
516 <        scan();
514 >    lnext = nextc;
515 >    while (isdigit(lnext) && i < MAXWORD) {
516 >        str[i++] = lnext;
517 >        lnext = scan();
518      }
519 <    if (nextc == '.' && i < MAXWORD) {
520 <        str[i++] = nextc;
521 <        scan();
522 <        while (isdigit(nextc) && i < MAXWORD) {
523 <            str[i++] = nextc;
524 <            scan();
519 >    if (lnext == '.' && i < MAXWORD) {
520 >        str[i++] = lnext;
521 >        lnext = scan();
522 >        if (i == 1 && !isdigit(lnext))
523 >            syntax("badly formed number");
524 >        while (isdigit(lnext) && i < MAXWORD) {
525 >            str[i++] = lnext;
526 >            lnext = scan();
527          }
528      }
529 <    if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
530 <        str[i++] = nextc;
531 <        scan();
532 <        if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
533 <            str[i++] = nextc;
534 <            scan();
529 >    if ((lnext == 'e' | lnext == 'E') && i < MAXWORD) {
530 >        str[i++] = lnext;
531 >        lnext = scan();
532 >        if ((lnext == '-' | lnext == '+') && i < MAXWORD) {
533 >            str[i++] = lnext;
534 >            lnext = scan();
535          }
536 <        while (isdigit(nextc) && i < MAXWORD) {
537 <            str[i++] = nextc;
538 <            scan();
536 >        if (!isdigit(lnext))
537 >            syntax("missing exponent");
538 >        while (isdigit(lnext) && i < MAXWORD) {
539 >            str[i++] = lnext;
540 >            lnext = scan();
541          }
542      }
543      str[i] = '\0';
# Line 446 | Line 548 | getnum()                       /* scan a positive float */
548  
549   EPNODE *
550   getE1()                         /* E1 -> E1 ADDOP E2 */
551 <                                /*       E2 */
551 >                                /*       E2 */
552   {
553      register EPNODE  *ep1, *ep2;
554  
# Line 457 | Line 559 | getE1()                                /* E1 -> E1 ADDOP E2 */
559          scan();
560          addekid(ep2, ep1);
561          addekid(ep2, getE2());
562 < #ifdef  RCONST
563 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
562 >        if (esupport&E_RCONST &&
563 >                        ep1->type == NUM && ep1->sibling->type == NUM)
564                  ep2 = rconst(ep2);
463 #endif
565          ep1 = ep2;
566      }
567      return(ep1);
# Line 469 | Line 570 | getE1()                                /* E1 -> E1 ADDOP E2 */
570  
571   EPNODE *
572   getE2()                         /* E2 -> E2 MULOP E3 */
573 <                                /*       E3 */
573 >                                /*       E3 */
574   {
575      register EPNODE  *ep1, *ep2;
576  
# Line 480 | Line 581 | getE2()                                /* E2 -> E2 MULOP E3 */
581          scan();
582          addekid(ep2, ep1);
583          addekid(ep2, getE3());
584 < #ifdef  RCONST
585 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
584 >        if (esupport&E_RCONST &&
585 >                        ep1->type == NUM && ep1->sibling->type == NUM)
586                  ep2 = rconst(ep2);
486 #endif
587          ep1 = ep2;
588      }
589      return(ep1);
# Line 491 | Line 591 | getE2()                                /* E2 -> E2 MULOP E3 */
591  
592  
593   EPNODE *
594 < getE3()                         /* E3 -> E3 ^ E4 */
595 <                                /*       E4 */
594 > getE3()                         /* E3 -> E4 ^ E3 */
595 >                                /*       E4 */
596   {
597      register EPNODE  *ep1, *ep2;
598  
599      ep1 = getE4();
600 <    while (nextc == '^') {
600 >    if (nextc == '^') {
601          ep2 = newnode();
602          ep2->type = nextc;
603          scan();
604          addekid(ep2, ep1);
605 <        addekid(ep2, getE4());
606 < #ifdef  RCONST
607 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
605 >        addekid(ep2, getE3());
606 >        if (esupport&E_RCONST &&
607 >                        ep1->type == NUM && ep1->sibling->type == NUM)
608                  ep2 = rconst(ep2);
609 < #endif
510 <        ep1 = ep2;
609 >        return(ep2);
610      }
611      return(ep1);
612   }
# Line 515 | Line 614 | getE3()                                /* E3 -> E3 ^ E4 */
614  
615   EPNODE *
616   getE4()                         /* E4 -> ADDOP E5 */
617 <                                /*       E5 */
617 >                                /*       E5 */
618   {
619      register EPNODE  *ep1, *ep2;
620  
# Line 526 | Line 625 | getE4()                                /* E4 -> ADDOP E5 */
625                  ep2->v.num = -ep2->v.num;
626                  return(ep2);
627          }
628 +        if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
629 +            efree((char *)ep2);
630 +            return(ep2->v.kid);
631 +        }
632          ep1 = newnode();
633          ep1->type = UMINUS;
634          addekid(ep1, ep2);
# Line 539 | Line 642 | getE4()                                /* E4 -> ADDOP E5 */
642  
643   EPNODE *
644   getE5()                         /* E5 -> (E1) */
645 <                                /*       VAR */
646 <                                /*       NUM */
647 <                                /*       $N */
648 <                                /*       FUNC(E1,..) */
649 <                                /*       ARG */
645 >                                /*       VAR */
646 >                                /*       NUM */
647 >                                /*       $N */
648 >                                /*       FUNC(E1,..) */
649 >                                /*       ARG */
650   {
651 <    int  i;
651 >    int  i;
652 >    char  *nam;
653      register EPNODE  *ep1, *ep2;
654  
655      if (nextc == '(') {
# Line 557 | Line 661 | getE5()                                /* E5 -> (E1) */
661          return(ep1);
662      }
663  
664 < #ifdef  INCHAN
561 <    if (nextc == '$') {
664 >    if (esupport&E_INCHAN && nextc == '$') {
665          scan();
666          ep1 = newnode();
667          ep1->type = CHAN;
668          ep1->v.chan = getinum();
669          return(ep1);
670      }
568 #endif
671  
672 < #if  defined(VARIABLE) || defined(FUNCTION)
673 <    if (isalpha(nextc)) {
674 <        ep1 = newnode();
675 <        ep1->type = VAR;
676 <        ep1->v.ln = varinsert(getname());
677 <
576 < #if  defined(VARIABLE) && defined(FUNCTION)
577 <        if (curfunc != NULL)
672 >  if (esupport&(E_VARIABLE|E_FUNCTION) &&
673 >                (isalpha(nextc) || nextc == CNTXMARK)) {
674 >      nam = getname();
675 >      ep1 = NULL;
676 >      if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
677 >                        && curfunc != NULL)
678              for (i = 1, ep2 = curfunc->v.kid->sibling;
679 <                                ep2 != NULL; i++, ep2 = ep2->sibling)
680 <                if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
581 <                    epfree(ep1);
679 >                                ep2 != NULL; i++, ep2 = ep2->sibling)
680 >                if (!strcmp(ep2->v.name, nam)) {
681                      ep1 = newnode();
682                      ep1->type = ARG;
683                      ep1->v.chan = i;
684                      break;
685                  }
686 < #endif
687 < #ifdef  FUNCTION
688 <        if (nextc == '(') {
686 >        if (ep1 == NULL) {
687 >            ep1 = newnode();
688 >            ep1->type = VAR;
689 >            ep1->v.ln = varinsert(nam);
690 >        }
691 >        if (esupport&E_FUNCTION && nextc == '(') {
692              ep2 = newnode();
693              ep2->type = FUNC;
694              addekid(ep2, ep1);
# Line 598 | Line 700 | getE5()                                /* E5 -> (E1) */
700              if (nextc != ')')
701                  syntax("')' expected");
702              scan();
703 <        }
602 < #ifndef  VARIABLE
603 <        else
703 >        } else if (!(esupport&E_VARIABLE))
704              syntax("'(' expected");
705 < #endif
706 < #endif
705 >        if (esupport&E_RCONST && isconstvar(ep1))
706 >            ep1 = rconst(ep1);
707          return(ep1);
708      }
609 #endif
709  
710      if (isdecimal(nextc)) {
711          ep1 = newnode();
# Line 618 | Line 717 | getE5()                                /* E5 -> (E1) */
717   }
718  
719  
621 #ifdef  RCONST
720   EPNODE *
721   rconst(epar)                    /* reduce a constant expression */
722 < register EPNODE  *epar;
722 > register EPNODE  *epar;
723   {
724      register EPNODE  *ep;
725  
# Line 629 | Line 727 | register EPNODE  *epar;
727      ep->type = NUM;
728      errno = 0;
729      ep->v.num = evalue(epar);
730 <    if (errno)
731 <        syntax("bad constant expression");
730 >    if (errno == EDOM || errno == ERANGE)
731 >        syntax("bad constant expression");
732      epfree(epar);
733  
734      return(ep);
735   }
736 < #endif
736 >
737 >
738 > int
739 > isconstvar(ep)                  /* is ep linked to a constant expression? */
740 > register EPNODE  *ep;
741 > {
742 >    register EPNODE  *ep1;
743 >
744 >    if (esupport&E_FUNCTION && ep->type == FUNC) {
745 >        if (!isconstfun(ep->v.kid))
746 >                return(0);
747 >        for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
748 >            if (ep1->type != NUM && !isconstfun(ep1))
749 >                return(0);
750 >        return(1);
751 >    }
752 >    if (ep->type != VAR)
753 >        return(0);
754 >    ep1 = ep->v.ln->def;
755 >    if (ep1 == NULL || ep1->type != ':')
756 >        return(0);
757 >    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
758 >        return(0);
759 >    return(1);
760 > }
761 >
762 >
763 > int
764 > isconstfun(ep)                  /* is ep linked to a constant function? */
765 > register EPNODE  *ep;
766 > {
767 >    register EPNODE  *dp;
768 >    register LIBR  *lp;
769 >
770 >    if (ep->type != VAR)
771 >        return(0);
772 >    if ((dp = ep->v.ln->def) != NULL)
773 >        if (dp->v.kid->type == FUNC)
774 >            return(dp->type == ':');
775 >        else
776 >            return(0);          /* don't identify masked library functions */
777 >    if ((lp = ep->v.ln->lib) != NULL)
778 >        return(lp->atyp == ':');
779 >    return(0);
780 > }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines