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 2.3 by greg, Thu May 7 22:30:41 1992 UTC vs.
Revision 2.50 by greg, Tue Feb 27 01:24:10 2024 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1991 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  <ctype.h>
24
23   #include  <errno.h>
24 + #include  <math.h>
25 + #include  <stdlib.h>
26  
27 + #include  "rtmisc.h"
28 + #include  "rtio.h"
29 + #include  "rterror.h"
30   #include  "calcomp.h"
31  
32 < #define  MAXLINE        256             /* maximum line 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  isdecimal(c)   (isdigit(c) || (c) == '.')
36 > #define  isdecimal(c)   (isdigit(c) | ((c) == '.'))
37  
38 < #ifndef atof
36 < extern double  atof();
37 < #endif
38 < extern double  pow();
39 < 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;
38 > #define  envalue(ep)    ((ep)->type==NUM ? (ep)->v.num : evalue(ep))
39  
40 + static double  euminus(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 + 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;
108 >    int  prev_support = esupport;
109 >    EPNODE  *ep;
110      double  rval;
111  
112 +    esupport &= ~E_RCONST;      /* don't bother reducing constant expr */
113      ep = eparse(expr);
114 +    esupport = prev_support;    /* as you were */
115      rval = evalue(ep);
116 <    epfree(ep);
116 >    epfree(ep,1);
117      return(rval);
118   }
119  
120  
121 < epfree(epar)                    /* free a parse tree */
122 < register EPNODE  *epar;
121 > int
122 > epcmp(                  /* compare two expressions for equivalence */
123 >    EPNODE  *ep1,
124 >    EPNODE  *ep2
125 > )
126   {
127 <    register EPNODE  *ep;
127 >        double  d;
128  
129 +        if (ep1->type != ep2->type)
130 +                return(1);
131 +
132 +        switch (ep1->type) {
133 +
134 +        case VAR:
135 +                return(ep1->v.ln != ep2->v.ln);
136 +
137 +        case NUM:
138 +                if (ep2->v.num == 0)
139 +                        return(ep1->v.num != 0);
140 +                d = ep1->v.num / ep2->v.num;
141 +                return((d > 1.000000000001) | (d < 0.999999999999));
142 +
143 +        case CHAN:
144 +        case ARG:
145 +                return(ep1->v.chan != ep2->v.chan);
146 +
147 +        case '=':
148 +        case ':':
149 +                return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling));
150 +
151 +        case CLKT:
152 +        case SYM:                       /* should never get this one */
153 +                return(0);
154 +
155 +        default:
156 +                ep1 = ep1->v.kid;
157 +                ep2 = ep2->v.kid;
158 +                while (ep1 != NULL) {
159 +                        if (ep2 == NULL)
160 +                                return(1);
161 +                        if (epcmp(ep1, ep2))
162 +                                return(1);
163 +                        ep1 = ep1->sibling;
164 +                        ep2 = ep2->sibling;
165 +                }
166 +                return(ep2 != NULL);
167 +        }
168 + }
169 +
170 +
171 + void
172 + epfree(                 /* free a parse tree */
173 +    EPNODE       *epar,
174 +    int         frep
175 + )
176 + {
177 +    EPNODE      *ep;
178 +
179      switch (epar->type) {
180  
135 #if  defined(VARIABLE) || defined(FUNCTION)
181          case VAR:
182              varfree(epar->v.ln);
183              break;
139 #endif
184              
185          case SYM:
186              freestr(epar->v.name);
# Line 145 | Line 189 | register EPNODE  *epar;
189          case NUM:
190          case CHAN:
191          case ARG:
192 <        case TICK:
192 >        case CLKT:
193              break;
194  
195          default:
196 <            for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
197 <                epfree(ep);
196 >            if (epar->nkids < 0) {
197 >                ep = epar->v.kid - epar->nkids;
198 >                while (ep > epar->v.kid)
199 >                        epfree(--ep, 0);
200 >                efree(ep);      /* free array space */
201 >            } else
202 >                while ((ep = epar->v.kid) != NULL) {
203 >                    epar->v.kid = ep->sibling;
204 >                    epfree(ep, 1);
205 >                }
206              break;
207  
208      }
209 +    if (frep)
210 +        efree(epar);
211 +    else
212 +        memset(epar, 0, sizeof(EPNODE));
213 + }
214  
215 <    efree((char *)epar);
215 >
216 > static void
217 > epflatten(                      /* flatten hierarchies for '+', '*' */
218 >        EPNODE *epar
219 > )
220 > {
221 >    EPNODE      *ep;
222 >
223 >    if (epar->nkids < 0)        /* can't handle array allocations */
224 >        return;
225 >
226 >    for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
227 >        while (ep->type == epar->type && ep->nkids > 0) {
228 >            EPNODE      *ep1 = ep->v.kid;
229 >            while (ep1->sibling != NULL)
230 >                ep1 = ep1->sibling;
231 >            ep1->sibling = ep->sibling;
232 >            epar->nkids += ep->nkids - 1;
233 >            ep1 = ep->v.kid;
234 >            *ep = *ep1;
235 >            efree(ep1);         /* not epfree()! */
236 >        }
237   }
238  
239 <                                /* the following used to be a switch */
240 < #ifdef  FUNCTION
241 < static double
242 < eargument(ep)
243 < EPNODE  *ep;
239 >
240 > void
241 > epoptimize(                     /* flatten operations, lists -> arrays */
242 >        EPNODE  *epar
243 > )
244   {
245 <    return(argument(ep->v.chan));
245 >    EPNODE      *ep;
246 >
247 >    if ((epar->type == '+') | (epar->type == '*'))
248 >        epflatten(epar);        /* flatten associative operations */
249 >
250 >    if (epar->nkids)            /* do children if any */
251 >        for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
252 >            epoptimize(ep);
253 >
254 >    if (epar->nkids > 4) {      /* make list into array if > 4 kids */
255 >        int     n = 1;
256 >        epar->v.kid = (EPNODE *)erealloc(epar->v.kid,
257 >                                        sizeof(EPNODE)*epar->nkids);
258 >        while (n < epar->nkids) {
259 >            ep = epar->v.kid[n-1].sibling;
260 >            epar->v.kid[n] = *ep;
261 >            efree(ep);          /* not epfree()! */
262 >            epar->v.kid[n-1].sibling = epar->v.kid + n;
263 >            n++;
264 >        }
265 >        epar->nkids = -n;
266 >    }
267   }
169 #endif
268  
269 +                                /* the following used to be a switch */
270   static double
271 < enumber(ep)
272 < EPNODE  *ep;
271 > enumber(
272 >    EPNODE      *ep
273 > )
274   {
275      return(ep->v.num);
276   }
277  
278   static double
279 < euminus(ep)
280 < EPNODE  *ep;
279 > euminus(
280 >    EPNODE      *ep
281 > )
282   {
283 <    register EPNODE  *ep1 = ep->v.kid;
283 >    EPNODE  *ep1 = ep->v.kid;
284  
285      return(-evalue(ep1));
286   }
287  
187 #ifdef  INCHAN
288   static double
289 < echannel(ep)
290 < EPNODE  *ep;
289 > echannel(
290 >    EPNODE      *ep
291 > )
292   {
293      return(chanvalue(ep->v.chan));
294   }
194 #endif
295  
296   static double
297 < eadd(ep)
298 < EPNODE  *ep;
297 > eadd(
298 >    EPNODE      *ep
299 > )
300   {
301 <    register EPNODE  *ep1 = ep->v.kid;
301 >    double  sum = 0;
302 >    EPNODE  *ep1 = ep->v.kid;
303  
304 <    return(evalue(ep1) + evalue(ep1->sibling));
304 >    do
305 >        sum += envalue(ep1);
306 >    while ((ep1 = ep1->sibling) != NULL);
307 >
308 >    return(sum);
309   }
310  
311   static double
312 < esubtr(ep)
313 < EPNODE  *ep;
312 > esubtr(
313 >    EPNODE      *ep
314 > )
315   {
316 <    register EPNODE  *ep1 = ep->v.kid;
316 >    EPNODE  *ep1 = ep->v.kid;
317 >    EPNODE  *ep2 = ep1->sibling;
318  
319 <    return(evalue(ep1) - evalue(ep1->sibling));
319 >    return(envalue(ep1) - envalue(ep2));
320   }
321  
322   static double
323 < emult(ep)
324 < EPNODE  *ep;
323 > emult(
324 >    EPNODE      *ep
325 > )
326   {
327 <    register EPNODE  *ep1 = ep->v.kid;
327 >    double  prod = 1;
328 >    EPNODE  *ep1 = ep->v.kid;
329  
330 <    return(evalue(ep1) * evalue(ep1->sibling));
330 >    do
331 >        prod *= envalue(ep1);
332 >    while ((ep1 = ep1->sibling) != NULL);
333 >
334 >    return(prod);
335   }
336  
337   static double
338 < edivi(ep)
339 < EPNODE  *ep;
338 > edivi(
339 >    EPNODE      *ep
340 > )
341   {
342 <    register EPNODE  *ep1 = ep->v.kid;
343 <    double  d;
342 >    EPNODE  *ep1 = ep->v.kid;
343 >    double  den = evalue(ep1->sibling);
344  
345 <    d = evalue(ep1->sibling);
231 <    if (d == 0.0) {
345 >    if (den == 0.0) {
346          wputs("Division by zero\n");
347          errno = ERANGE;
348          return(0.0);
349      }
350 <    return(evalue(ep1) / d);
350 >    return(envalue(ep1) / den);
351   }
352  
353   static double
354 < epow(ep)
355 < EPNODE  *ep;
354 > epow(
355 >    EPNODE      *ep
356 > )
357   {
358 <    register EPNODE  *ep1 = ep->v.kid;
358 >    EPNODE  *ep1 = ep->v.kid;
359      double  d;
360 <    int  lasterrno;
360 >    int  lasterrno;
361  
362      lasterrno = errno;
363      errno = 0;
364      d = pow(evalue(ep1), evalue(ep1->sibling));
365 < #ifdef  IEEE
366 <    if (!finite(d))
367 <        errno = EDOM;
365 > #ifdef  isnan
366 >    if (errno == 0) {
367 >        if (isnan(d))
368 >            errno = EDOM;
369 >        else if (isinf(d))
370 >            errno = ERANGE;
371 >    }
372   #endif
373 <    if (errno) {
373 >    if ((errno == EDOM) | (errno == ERANGE)) {
374          wputs("Illegal power\n");
375          return(0.0);
376      }
# Line 260 | Line 379 | EPNODE  *ep;
379   }
380  
381   static double
382 < ebotch(ep)
383 < EPNODE  *ep;
382 > ebotch(
383 >    EPNODE      *ep
384 > )
385   {
386      eputs("Bad expression!\n");
387      quit(1);
388 +        return 0.0; /* pro forma return */
389   }
390  
391  
392   EPNODE *
393 < ekid(ep, n)                     /* return pointer to a node's nth kid */
394 < register EPNODE  *ep;
395 < register int  n;
393 > ekid(                   /* return pointer to a node's nth kid */
394 >    EPNODE       *ep,
395 >    int  n
396 > )
397   {
398 <
399 <    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
400 <        if (--n < 0)
401 <            break;
402 <
398 >    if (ep->nkids < 0) {        /* allocated array? */
399 >        if (n >= -ep->nkids)
400 >            return(NULL);
401 >        return(ep->v.kid + n);
402 >    }
403 >    ep = ep->v.kid;             /* else get from list */
404 >    while (n-- > 0)
405 >        if ((ep = ep->sibling) == NULL)
406 >                break;
407      return(ep);
408   }
409  
410  
411 < int
412 < nekids(ep)                      /* return # of kids for node ep */
413 < register EPNODE  *ep;
411 > void
412 > initfile(               /* prepare input file */
413 >    FILE  *fp,
414 >    char  *fn,
415 >    int  ln
416 > )
417   {
418 <    register int  n = 0;
418 >    static char  inpbuf[MAXLINE];
419  
291    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
292        n++;
293
294    return(n);
295 }
296
297
298 initfile(fp, fn, ln)            /* prepare input file */
299 FILE  *fp;
300 char  *fn;
301 int  ln;
302 {
303    static char  inpbuf[MAXLINE];
304
420      infp = fp;
421      linbuf = inpbuf;
422      infile = fn;
# Line 312 | Line 427 | int  ln;
427   }
428  
429  
430 < initstr(s, fn, ln)              /* prepare input string */
431 < char  *s;
432 < char  *fn;
433 < int  ln;
430 > void
431 > initstr(                /* prepare input string */
432 >    char  *s,
433 >    char  *fn,
434 >    int  ln
435 > )
436   {
437      infp = NULL;
438      infile = fn;
# Line 326 | Line 443 | int  ln;
443   }
444  
445  
446 < getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
447 < char  **fnp;
448 < int  *lnp;
449 < char  **spp;
450 < FILE  **fpp;
446 > void
447 > getscanpos(     /* return current scan position */
448 >    char  **fnp,
449 >    int  *lnp,
450 >    char  **spp,
451 >    FILE  **fpp
452 > )
453   {
454      if (fnp != NULL) *fnp = infile;
455      if (lnp != NULL) *lnp = lineno;
# Line 340 | Line 459 | FILE  **fpp;
459  
460  
461   int
462 < scan()                          /* scan next character, return literal next */
462 > scan(void)              /* scan next character, return literal next */
463   {
464 <    register int  lnext = 0;
464 >    int  lnext = 0;
465  
466      do {
467          if (linbuf[linepos] == '\0')
# Line 357 | Line 476 | scan()                         /* scan next character, return literal next
476              nextc = linbuf[linepos++];
477          if (!lnext)
478                  lnext = nextc;
479 +        if (nextc == eofc) {
480 +                nextc = EOF;
481 +                break;
482 +        }
483          if (nextc == '{') {
484              scan();
485              while (nextc != '}')
# Line 372 | Line 495 | scan()                         /* scan next character, return literal next
495  
496  
497   char *
498 < ltoa(l)                         /* convert long to ascii */
499 < long  l;
498 > long2ascii(                           /* convert long to ascii */
499 >    long  l
500 > )
501   {
502 <    static char  buf[16];
503 <    register char  *cp;
504 <    int  neg = 0;
502 >    static char  buf[16];
503 >    char  *cp;
504 >    int  neg = 0;
505  
506      if (l == 0)
507          return("0");
# Line 397 | Line 521 | long  l;
521   }
522  
523  
524 < syntax(err)                     /* report syntax error and quit */
525 < char  *err;
524 > void
525 > syntax(                 /* report syntax error and quit */
526 >    char  *err
527 > )
528   {
529 <    register int  i;
529 >    int  i;
530  
531 <    if (infile != NULL || lineno != 0) {
531 >    if ((infile != NULL) | (lineno != 0)) {
532          if (infile != NULL) eputs(infile);
533          if (lineno != 0) {
534              eputs(infile != NULL ? ", line " : "line ");
535 <            eputs(ltoa((long)lineno));
535 >            eputs(long2ascii((long)lineno));
536          }
537 <        eputs(": syntax error:\n");
537 >        eputs(":\n");
538      }
539      eputs(linbuf);
540      if (linbuf[strlen(linbuf)-1] != '\n')
# Line 422 | Line 548 | char  *err;
548   }
549  
550  
551 < addekid(ep, ekid)                       /* add a child to ep */
552 < register EPNODE  *ep;
553 < EPNODE  *ekid;
551 > void
552 > addekid(                        /* add a child to ep */
553 >    EPNODE       *ep,
554 >    EPNODE      *ek
555 > )
556   {
557 +    if (ep->nkids < 0) {
558 +        eputs("Cannot add kid to EPNODE array\n");
559 +        quit(1);
560 +    }
561 +    ep->nkids++;
562      if (ep->v.kid == NULL)
563 <        ep->v.kid = ekid;
563 >        ep->v.kid = ek;
564      else {
565          for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
566              ;
567 <        ep->sibling = ekid;
567 >        ep->sibling = ek;
568      }
569 <    ekid->sibling = NULL;
569 >    ek->sibling = NULL;         /* shouldn't be necessary */
570   }
571  
572  
573   char *
574 < getname()                       /* scan an identifier */
574 > getname(void)                   /* scan an identifier */
575   {
576 <    static char  str[MAXWORD+1];
577 <    register int  i, lnext;
576 >    static char  str[RMAXWORD+1];
577 >    int  i, lnext;
578  
579      lnext = nextc;
580 <    for (i = 0; i < MAXWORD && isid(lnext); i++, lnext = scan())
580 >    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
581          str[i] = lnext;
582      str[i] = '\0';
583      while (isid(lnext))         /* skip rest of name */
# Line 455 | Line 588 | getname()                      /* scan an identifier */
588  
589  
590   int
591 < getinum()                       /* scan a positive integer */
591 > getinum(void)                   /* scan a positive integer */
592   {
593 <    register int  n, lnext;
593 >    int  n, lnext;
594  
595      n = 0;
596      lnext = nextc;
# Line 470 | Line 603 | getinum()                      /* scan a positive integer */
603  
604  
605   double
606 < getnum()                        /* scan a positive float */
606 > getnum(void)                    /* scan a positive float */
607   {
608 <    register int  i, lnext;
609 <    char  str[MAXWORD+1];
608 >    int  i, lnext;
609 >    char  str[RMAXWORD+1];
610  
611      i = 0;
612      lnext = nextc;
613 <    while (isdigit(lnext) && i < MAXWORD) {
613 >    while (isdigit(lnext) && i < RMAXWORD) {
614          str[i++] = lnext;
615          lnext = scan();
616      }
617 <    if (lnext == '.' && i < MAXWORD) {
618 <        str[i++] = lnext;
619 <        lnext = scan();
620 <        while (isdigit(lnext) && i < MAXWORD) {
617 >    if ((lnext == '.') & (i < RMAXWORD)) {
618 >        str[i++] = lnext;
619 >        lnext = scan();
620 >        if (i == 1 && !isdigit(lnext))
621 >            syntax("badly formed number");
622 >        while (isdigit(lnext) && i < RMAXWORD) {
623              str[i++] = lnext;
624              lnext = scan();
625          }
626      }
627 <    if ((lnext == 'e' || lnext == 'E') && i < MAXWORD) {
628 <        str[i++] = lnext;
629 <        lnext = scan();
630 <        if ((lnext == '-' || lnext == '+') && i < MAXWORD) {
627 >    if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
628 >        str[i++] = lnext;
629 >        lnext = scan();
630 >        if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
631              str[i++] = lnext;
632              lnext = scan();
633          }
634 <        while (isdigit(lnext) && i < MAXWORD) {
634 >        if (!isdigit(lnext))
635 >            syntax("missing exponent");
636 >        while (isdigit(lnext) && i < RMAXWORD) {
637              str[i++] = lnext;
638              lnext = scan();
639          }
# Line 508 | Line 645 | getnum()                       /* scan a positive float */
645  
646  
647   EPNODE *
648 < getE1()                         /* E1 -> E1 ADDOP E2 */
649 <                                /*       E2 */
648 > getE1(void)                     /* E1 -> E1 ADDOP E2 */
649 >                                /*       E2 */
650   {
651 <    register EPNODE  *ep1, *ep2;
651 >    EPNODE  *ep1, *ep2;
652  
653      ep1 = getE2();
654 <    while (nextc == '+' || nextc == '-') {
654 >    while ((nextc == '+') | (nextc == '-')) {
655          ep2 = newnode();
656          ep2->type = nextc;
657          scan();
658          addekid(ep2, ep1);
659          addekid(ep2, getE2());
660 < #ifdef  RCONST
661 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
660 >        if (esupport&E_RCONST &&
661 >                        (ep1->type == NUM) & (ep1->sibling->type == NUM))
662                  ep2 = rconst(ep2);
526 #endif
663          ep1 = ep2;
664      }
665      return(ep1);
# Line 531 | Line 667 | getE1()                                /* E1 -> E1 ADDOP E2 */
667  
668  
669   EPNODE *
670 < getE2()                         /* E2 -> E2 MULOP E3 */
671 <                                /*       E3 */
670 > getE2(void)                     /* E2 -> E2 MULOP E3 */
671 >                                /*       E3 */
672   {
673 <    register EPNODE  *ep1, *ep2;
673 >    EPNODE  *ep1, *ep2;
674  
675      ep1 = getE3();
676 <    while (nextc == '*' || nextc == '/') {
676 >    while ((nextc == '*') | (nextc == '/')) {
677          ep2 = newnode();
678          ep2->type = nextc;
679          scan();
680          addekid(ep2, ep1);
681          addekid(ep2, getE3());
682 < #ifdef  RCONST
683 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
684 <                ep2 = rconst(ep2);
685 < #endif
682 >        if (esupport&E_RCONST) {
683 >                EPNODE  *ep3 = ep1->sibling;
684 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
685 >                        ep2 = rconst(ep2);
686 >                } else if (ep3->type == NUM) {
687 >                        if (ep2->type == '/') {
688 >                                if (ep3->v.num == 0)
689 >                                        syntax("divide by zero constant");
690 >                                ep2->type = '*';        /* for speed */
691 >                                ep3->v.num = 1./ep3->v.num;
692 >                        } else if (ep3->v.num == 0) {
693 >                                ep1->sibling = NULL;    /* (E2 * 0) */
694 >                                epfree(ep2,1);
695 >                                ep2 = ep3;
696 >                        }
697 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
698 >                        epfree(ep3,1);          /* (0 * E3) or (0 / E3) */
699 >                        ep1->sibling = NULL;
700 >                        efree(ep2);
701 >                        ep2 = ep1;
702 >                }
703 >        }
704          ep1 = ep2;
705      }
706      return(ep1);
# Line 554 | Line 708 | getE2()                                /* E2 -> E2 MULOP E3 */
708  
709  
710   EPNODE *
711 < getE3()                         /* E3 -> E4 ^ E3 */
712 <                                /*       E4 */
711 > getE3(void)                     /* E3 -> E4 ^ E3 */
712 >                                /*       E4 */
713   {
714 <    register EPNODE  *ep1, *ep2;
714 >        EPNODE  *ep1, *ep2;
715  
716 <    ep1 = getE4();
717 <    if (nextc == '^') {
716 >        ep1 = getE4();
717 >        if (nextc != '^')
718 >                return(ep1);
719          ep2 = newnode();
720          ep2->type = nextc;
721          scan();
722          addekid(ep2, ep1);
723          addekid(ep2, getE3());
724 < #ifdef  RCONST
725 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
726 <                ep2 = rconst(ep2);
727 < #endif
724 >        if (esupport&E_RCONST) {
725 >                EPNODE  *ep3 = ep1->sibling;
726 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
727 >                        ep2 = rconst(ep2);
728 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
729 >                        epfree(ep3,1);          /* (0 ^ E3) */
730 >                        ep1->sibling = NULL;
731 >                        efree(ep2);
732 >                        ep2 = ep1;
733 >                } else if ((ep3->type == NUM && ep3->v.num == 0) |
734 >                                (ep1->type == NUM && ep1->v.num == 1)) {
735 >                        epfree(ep2,0);          /* (E4 ^ 0) or (1 ^ E3) */
736 >                        ep2->type = NUM;
737 >                        ep2->v.num = 1;
738 >                } else if (ep3->type == NUM && ep3->v.num == 1) {
739 >                        efree(ep3);     /* (E4 ^ 1) */
740 >                        ep1->sibling = NULL;
741 >                        efree(ep2);
742 >                        ep2 = ep1;
743 >                }
744 >        }
745          return(ep2);
574    }
575    return(ep1);
746   }
747  
748  
749   EPNODE *
750 < getE4()                         /* E4 -> ADDOP E5 */
751 <                                /*       E5 */
750 > getE4(void)                     /* E4 -> ADDOP E5 */
751 >                                /*       E5 */
752   {
753 <    register EPNODE  *ep1, *ep2;
753 >    EPNODE  *ep1, *ep2;
754  
755      if (nextc == '-') {
756          scan();
# Line 590 | Line 760 | getE4()                                /* E4 -> ADDOP E5 */
760                  return(ep2);
761          }
762          if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
763 <            efree((char *)ep2);
764 <            return(ep2->v.kid);
763 >            ep1 = ep2->v.kid;
764 >            efree(ep2);
765 >            return(ep1);
766          }
767          ep1 = newnode();
768          ep1->type = UMINUS;
# Line 605 | Line 776 | getE4()                                /* E4 -> ADDOP E5 */
776  
777  
778   EPNODE *
779 < getE5()                         /* E5 -> (E1) */
780 <                                /*       VAR */
781 <                                /*       NUM */
782 <                                /*       $N */
783 <                                /*       FUNC(E1,..) */
784 <                                /*       ARG */
779 > getE5(void)                     /* E5 -> (E1) */
780 >                                /*       VAR */
781 >                                /*       NUM */
782 >                                /*       $N */
783 >                                /*       FUNC(E1,..) */
784 >                                /*       ARG */
785   {
786 <    int  i;
787 <    char  *nam;
788 <    register EPNODE  *ep1, *ep2;
786 >        int      i;
787 >        char  *nam;
788 >        EPNODE  *ep1, *ep2;
789  
619    if (nextc == '(') {
620        scan();
621        ep1 = getE1();
622        if (nextc != ')')
623            syntax("')' expected");
624        scan();
625        return(ep1);
626    }
627
628 #ifdef  INCHAN
629    if (nextc == '$') {
630        scan();
631        ep1 = newnode();
632        ep1->type = CHAN;
633        ep1->v.chan = getinum();
634        return(ep1);
635    }
636 #endif
637
638 #if  defined(VARIABLE) || defined(FUNCTION)
639    if (isalpha(nextc) || nextc == CNTXMARK) {
640        nam = getname();
641 #if  defined(VARIABLE) && defined(FUNCTION)
642        ep1 = NULL;
643        if (curfunc != NULL)
644            for (i = 1, ep2 = curfunc->v.kid->sibling;
645                                ep2 != NULL; i++, ep2 = ep2->sibling)
646                if (!strcmp(ep2->v.name, nam)) {
647                    ep1 = newnode();
648                    ep1->type = ARG;
649                    ep1->v.chan = i;
650                    break;
651                }
652        if (ep1 == NULL)
653 #endif
654        {
655            ep1 = newnode();
656            ep1->type = VAR;
657            ep1->v.ln = varinsert(nam);
658        }
659 #ifdef  FUNCTION
790          if (nextc == '(') {
661            ep2 = newnode();
662            ep2->type = FUNC;
663            addekid(ep2, ep1);
664            ep1 = ep2;
665            do {
791                  scan();
792 <                addekid(ep1, getE1());
793 <            } while (nextc == ',');
794 <            if (nextc != ')')
795 <                syntax("')' expected");
796 <            scan();
792 >                ep1 = getE1();
793 >                if (nextc != ')')
794 >                        syntax("')' expected");
795 >                scan();
796 >                return(ep1);
797          }
798 < #ifndef  VARIABLE
799 <        else
800 <            syntax("'(' expected");
801 < #endif
802 < #endif
803 < #ifdef  RCONST
804 <        if (isconstvar(ep1))
805 <            ep1 = rconst(ep1);
806 < #endif
807 <        return(ep1);
808 <    }
809 < #endif
810 <
811 <    if (isdecimal(nextc)) {
812 <        ep1 = newnode();
813 <        ep1->type = NUM;
814 <        ep1->v.num = getnum();
815 <        return(ep1);
816 <    }
817 <    syntax("unexpected character");
798 >        if (esupport&E_INCHAN && nextc == '$') {
799 >                scan();
800 >                ep1 = newnode();
801 >                ep1->type = CHAN;
802 >                ep1->v.chan = getinum();
803 >                return(ep1);
804 >        }
805 >        if (esupport&(E_VARIABLE|E_FUNCTION) &&
806 >                        (isalpha(nextc) | (nextc == CNTXMARK))) {
807 >                nam = getname();
808 >                ep1 = NULL;
809 >                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
810 >                                && curfunc != NULL)
811 >                        for (i = 1, ep2 = curfunc->v.kid->sibling;
812 >                                        ep2 != NULL; i++, ep2 = ep2->sibling)
813 >                                if (!strcmp(ep2->v.name, nam)) {
814 >                                        ep1 = newnode();
815 >                                        ep1->type = ARG;
816 >                                        ep1->v.chan = i;
817 >                                        break;
818 >                                }
819 >                if (ep1 == NULL) {
820 >                        ep1 = newnode();
821 >                        ep1->type = VAR;
822 >                        ep1->v.ln = varinsert(nam);
823 >                }
824 >                if (esupport&E_FUNCTION && nextc == '(') {
825 >                        ep2 = newnode();
826 >                        ep2->type = FUNC;
827 >                        addekid(ep2, ep1);
828 >                        ep1 = ep2;
829 >                        do {
830 >                                scan();
831 >                                addekid(ep1, getE1());
832 >                        } while (nextc == ',');
833 >                        if (nextc != ')')
834 >                                syntax("')' expected");
835 >                        scan();
836 >                } else if (!(esupport&E_VARIABLE))
837 >                        syntax("'(' expected");
838 >                if (esupport&E_RCONST && isconstvar(ep1))
839 >                        ep1 = rconst(ep1);
840 >                return(ep1);
841 >        }
842 >        if (isdecimal(nextc)) {
843 >                ep1 = newnode();
844 >                ep1->type = NUM;
845 >                ep1->v.num = getnum();
846 >                return(ep1);
847 >        }
848 >        syntax("unexpected character");
849 >        return NULL; /* pro forma return */
850   }
851  
852  
696 #ifdef  RCONST
853   EPNODE *
854 < rconst(epar)                    /* reduce a constant expression */
855 < register EPNODE  *epar;
854 > rconst(                 /* reduce a constant expression */
855 >    EPNODE       *epar
856 > )
857   {
858 <    register EPNODE  *ep;
858 >    EPNODE  *ep;
859  
860      ep = newnode();
861      ep->type = NUM;
862      errno = 0;
863      ep->v.num = evalue(epar);
864 <    if (errno)
865 <        syntax("bad constant expression");
866 <    epfree(epar);
864 >    if ((errno == EDOM) | (errno == ERANGE))
865 >        syntax("bad constant expression");
866 >    epfree(epar,1);
867  
868      return(ep);
869   }
870  
871  
872 < isconstvar(ep)                  /* is ep linked to a constant expression? */
873 < register EPNODE  *ep;
872 > int
873 > isconstvar(                     /* is ep linked to a constant expression? */
874 >    EPNODE       *ep
875 > )
876   {
877 < #ifdef  VARIABLE
719 <    register EPNODE  *ep1;
720 < #ifdef  FUNCTION
877 >    EPNODE  *ep1;
878  
879 <    if (ep->type == FUNC) {
879 >    if (esupport&E_FUNCTION && ep->type == FUNC) {
880          if (!isconstfun(ep->v.kid))
881                  return(0);
882          for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
# Line 727 | Line 884 | register EPNODE  *ep;
884                  return(0);
885          return(1);
886      }
730 #endif
887      if (ep->type != VAR)
888          return(0);
889      ep1 = ep->v.ln->def;
890      if (ep1 == NULL || ep1->type != ':')
891          return(0);
892 < #ifdef  FUNCTION
737 <    if (ep1->v.kid->type != SYM)
892 >    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
893          return(0);
739 #endif
894      return(1);
741 #else
742    return(ep->type == FUNC);
743 #endif
895   }
896  
897  
898 < #if  defined(FUNCTION) && defined(VARIABLE)
899 < isconstfun(ep)                  /* is ep linked to a constant function? */
900 < register EPNODE  *ep;
898 > int
899 > isconstfun(                     /* is ep linked to a constant function? */
900 >    EPNODE       *ep
901 > )
902   {
903 <    register EPNODE  *dp;
904 <    register LIBR  *lp;
903 >    EPNODE  *dp;
904 >    LIBR  *lp;
905  
906      if (ep->type != VAR)
907          return(0);
908 <    if ((dp = ep->v.ln->def) != NULL && dp->v.kid->type == FUNC)
909 <        return(dp->type == ':');
910 <    if ((lp = liblookup(ep->v.ln->name)) != NULL)
908 >    if ((dp = ep->v.ln->def) != NULL) {
909 >        if (dp->v.kid->type == FUNC)
910 >            return(dp->type == ':');
911 >        else
912 >            return(0);          /* don't identify masked library functions */
913 >    }
914 >    if ((lp = ep->v.ln->lib) != NULL)
915          return(lp->atyp == ':');
916      return(0);
917   }
762 #endif
763 #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines