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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines