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.45 by greg, Sat Feb 24 19:11:45 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 *), eargument(EPNODE *), enumber(EPNODE *);
41 + static double  echannel(EPNODE *);
42 + static double  eadd(EPNODE *), esubtr(EPNODE *),
43 +               emult(EPNODE *), edivi(EPNODE *),
44 +               epow(EPNODE *);
45 + static double  ebotch(EPNODE *);
46 +
47 + 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 + }
212  
213 <    efree((char *)epar);
213 >
214 > static void
215 > epflatten(                      /* flatten hierarchies for '+', '*' */
216 >        EPNODE *epar
217 > )
218 > {
219 >    EPNODE      *ep;
220 >
221 >    if (epar->nkids < 0)        /* we don't really handle this properly */
222 >        epar->nkids *= -1;
223 >
224 >    for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
225 >        while (ep->type == epar->type) {
226 >            EPNODE      *ep1 = ep->v.kid;
227 >            while (ep1->sibling != NULL)
228 >                ep1 = ep1->sibling;
229 >            ep1->sibling = ep->sibling;
230 >            epar->nkids += nekids(ep) - 1;
231 >            ep1 = ep->v.kid;
232 >            *ep = *ep1;
233 >            efree(ep1);         /* not epfree()! */
234 >        }
235   }
236  
237 +
238 + void
239 + epoptimize(                     /* flatten operations and lists -> arrays */
240 +        EPNODE  *epar
241 + )
242 + {
243 +    EPNODE      *ep;
244 +
245 +    if ((epar->type == '+') | (epar->type == '*'))
246 +        epflatten(epar);        /* commutative & associative */
247 +
248 +    if (epar->nkids)            /* do children if any */
249 +        for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
250 +            epoptimize(ep);
251 +
252 +    if (epar->nkids > 4) {      /* make list into array if > 4 kids */
253 +        int     n = 1;
254 +        epar->v.kid = (EPNODE *)erealloc(epar->v.kid,
255 +                                        sizeof(EPNODE)*epar->nkids);
256 +        while (n < epar->nkids) {
257 +            ep = epar->v.kid[n-1].sibling;
258 +            epar->v.kid[n] = *ep;
259 +            efree(ep);          /* not epfree()! */
260 +            epar->v.kid[n-1].sibling = epar->v.kid + n;
261 +            n++;
262 +        }
263 +        epar->nkids = -n;
264 +    }
265 + }
266 +
267                                  /* the following used to be a switch */
162 #ifdef  FUNCTION
268   static double
269 < eargument(ep)
270 < EPNODE  *ep;
269 > eargument(
270 >    EPNODE      *ep
271 > )
272   {
273      return(argument(ep->v.chan));
274   }
169 #endif
275  
276   static double
277 < enumber(ep)
278 < EPNODE  *ep;
277 > enumber(
278 >    EPNODE      *ep
279 > )
280   {
281      return(ep->v.num);
282   }
283  
284   static double
285 < euminus(ep)
286 < EPNODE  *ep;
285 > euminus(
286 >    EPNODE      *ep
287 > )
288   {
289 <    register EPNODE  *ep1 = ep->v.kid;
289 >    EPNODE  *ep1 = ep->v.kid;
290  
291      return(-evalue(ep1));
292   }
293  
187 #ifdef  INCHAN
294   static double
295 < echannel(ep)
296 < EPNODE  *ep;
295 > echannel(
296 >    EPNODE      *ep
297 > )
298   {
299      return(chanvalue(ep->v.chan));
300   }
194 #endif
301  
302   static double
303 < eadd(ep)
304 < EPNODE  *ep;
303 > eadd(
304 >    EPNODE      *ep
305 > )
306   {
307 <    register EPNODE  *ep1 = ep->v.kid;
307 >    double  sum = 0;
308 >    EPNODE  *ep1 = ep->v.kid;
309  
310 <    return(evalue(ep1) + evalue(ep1->sibling));
310 >    do
311 >        sum += envalue(ep1);
312 >    while ((ep1 = ep1->sibling) != NULL);
313 >
314 >    return(sum);
315   }
316  
317   static double
318 < esubtr(ep)
319 < EPNODE  *ep;
318 > esubtr(
319 >    EPNODE      *ep
320 > )
321   {
322 <    register EPNODE  *ep1 = ep->v.kid;
322 >    EPNODE  *ep1 = ep->v.kid;
323 >    EPNODE  *ep2 = ep1->sibling;
324  
325 <    return(evalue(ep1) - evalue(ep1->sibling));
325 >    return(envalue(ep1) - envalue(ep2));
326   }
327  
328   static double
329 < emult(ep)
330 < EPNODE  *ep;
329 > emult(
330 >    EPNODE      *ep
331 > )
332   {
333 <    register EPNODE  *ep1 = ep->v.kid;
333 >    double  prod = 1;
334 >    EPNODE  *ep1 = ep->v.kid;
335  
336 <    return(evalue(ep1) * evalue(ep1->sibling));
336 >    do
337 >        prod *= envalue(ep1);
338 >    while ((ep1 = ep1->sibling) != NULL);
339 >
340 >    return(prod);
341   }
342  
343   static double
344 < edivi(ep)
345 < EPNODE  *ep;
344 > edivi(
345 >    EPNODE      *ep
346 > )
347   {
348 <    register EPNODE  *ep1 = ep->v.kid;
348 >    EPNODE  *ep1 = ep->v.kid;
349 >    EPNODE  *ep2 = ep1->sibling;
350      double  d;
351  
352 <    d = evalue(ep1->sibling);
352 >    d = envalue(ep2);
353      if (d == 0.0) {
354          wputs("Division by zero\n");
355          errno = ERANGE;
356          return(0.0);
357      }
358 <    return(evalue(ep1) / d);
358 >    return(envalue(ep1) / d);
359   }
360  
361   static double
362 < epow(ep)
363 < EPNODE  *ep;
362 > epow(
363 >    EPNODE      *ep
364 > )
365   {
366 <    register EPNODE  *ep1 = ep->v.kid;
366 >    EPNODE  *ep1 = ep->v.kid;
367      double  d;
368 <    int  lasterrno;
368 >    int  lasterrno;
369  
370      lasterrno = errno;
371      errno = 0;
372      d = pow(evalue(ep1), evalue(ep1->sibling));
373 < #ifdef  IEEE
374 <    if (!finite(d))
375 <        errno = EDOM;
373 > #ifdef  isnan
374 >    if (errno == 0) {
375 >        if (isnan(d))
376 >            errno = EDOM;
377 >        else if (isinf(d))
378 >            errno = ERANGE;
379 >    }
380   #endif
381 <    if (errno) {
381 >    if ((errno == EDOM) | (errno == ERANGE)) {
382          wputs("Illegal power\n");
383          return(0.0);
384      }
# Line 260 | Line 387 | EPNODE  *ep;
387   }
388  
389   static double
390 < ebotch(ep)
391 < EPNODE  *ep;
390 > ebotch(
391 >    EPNODE      *ep
392 > )
393   {
394      eputs("Bad expression!\n");
395      quit(1);
396 +        return 0.0; /* pro forma return */
397   }
398  
399  
400   EPNODE *
401 < ekid(ep, n)                     /* return pointer to a node's nth kid */
402 < register EPNODE  *ep;
403 < register int  n;
401 > ekid(                   /* return pointer to a node's nth kid */
402 >    EPNODE       *ep,
403 >    int  n
404 > )
405   {
406 <
407 <    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
408 <        if (--n < 0)
409 <            break;
410 <
406 >    if (ep->nkids < 0) {        /* allocated array? */
407 >        if (n >= -ep->nkids)
408 >            return(NULL);
409 >        return(ep->v.kid + n);
410 >    }
411 >    ep = ep->v.kid;             /* else get from list */
412 >    while (n-- > 0)
413 >        if ((ep = ep->sibling) == NULL)
414 >                break;
415      return(ep);
416   }
417  
418  
419 < int
420 < nekids(ep)                      /* return # of kids for node ep */
421 < register EPNODE  *ep;
419 > void
420 > initfile(               /* prepare input file */
421 >    FILE  *fp,
422 >    char  *fn,
423 >    int  ln
424 > )
425   {
426 <    register int  n = 0;
426 >    static char  inpbuf[MAXLINE];
427  
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
428      infp = fp;
429      linbuf = inpbuf;
430      infile = fn;
# Line 312 | Line 435 | int  ln;
435   }
436  
437  
438 < initstr(s, fn, ln)              /* prepare input string */
439 < char  *s;
440 < char  *fn;
441 < int  ln;
438 > void
439 > initstr(                /* prepare input string */
440 >    char  *s,
441 >    char  *fn,
442 >    int  ln
443 > )
444   {
445      infp = NULL;
446      infile = fn;
# Line 326 | Line 451 | int  ln;
451   }
452  
453  
454 < getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
455 < char  **fnp;
456 < int  *lnp;
457 < char  **spp;
458 < FILE  **fpp;
454 > void
455 > getscanpos(     /* return current scan position */
456 >    char  **fnp,
457 >    int  *lnp,
458 >    char  **spp,
459 >    FILE  **fpp
460 > )
461   {
462      if (fnp != NULL) *fnp = infile;
463      if (lnp != NULL) *lnp = lineno;
# Line 340 | Line 467 | FILE  **fpp;
467  
468  
469   int
470 < scan()                          /* scan next character, return literal next */
470 > scan(void)              /* scan next character, return literal next */
471   {
472 <    register int  lnext = 0;
472 >    int  lnext = 0;
473  
474      do {
475          if (linbuf[linepos] == '\0')
# Line 357 | Line 484 | scan()                         /* scan next character, return literal next
484              nextc = linbuf[linepos++];
485          if (!lnext)
486                  lnext = nextc;
487 +        if (nextc == eofc) {
488 +                nextc = EOF;
489 +                break;
490 +        }
491          if (nextc == '{') {
492              scan();
493              while (nextc != '}')
# Line 372 | Line 503 | scan()                         /* scan next character, return literal next
503  
504  
505   char *
506 < ltoa(l)                         /* convert long to ascii */
507 < long  l;
506 > long2ascii(                           /* convert long to ascii */
507 >    long  l
508 > )
509   {
510 <    static char  buf[16];
511 <    register char  *cp;
512 <    int  neg = 0;
510 >    static char  buf[16];
511 >    char  *cp;
512 >    int  neg = 0;
513  
514      if (l == 0)
515          return("0");
# Line 397 | Line 529 | long  l;
529   }
530  
531  
532 < syntax(err)                     /* report syntax error and quit */
533 < char  *err;
532 > void
533 > syntax(                 /* report syntax error and quit */
534 >    char  *err
535 > )
536   {
537 <    register int  i;
537 >    int  i;
538  
539 <    if (infile != NULL || lineno != 0) {
539 >    if ((infile != NULL) | (lineno != 0)) {
540          if (infile != NULL) eputs(infile);
541          if (lineno != 0) {
542              eputs(infile != NULL ? ", line " : "line ");
543 <            eputs(ltoa((long)lineno));
543 >            eputs(long2ascii((long)lineno));
544          }
545 <        eputs(": syntax error:\n");
545 >        eputs(":\n");
546      }
547      eputs(linbuf);
548      if (linbuf[strlen(linbuf)-1] != '\n')
# Line 422 | Line 556 | char  *err;
556   }
557  
558  
559 < addekid(ep, ekid)                       /* add a child to ep */
560 < register EPNODE  *ep;
561 < EPNODE  *ekid;
559 > void
560 > addekid(                        /* add a child to ep */
561 >    EPNODE       *ep,
562 >    EPNODE      *ek
563 > )
564   {
565 +    if (ep->nkids < 0)          /* we don't really handle this properly */
566 +        ep->nkids *= -1;
567 +    ep->nkids++;
568      if (ep->v.kid == NULL)
569 <        ep->v.kid = ekid;
569 >        ep->v.kid = ek;
570      else {
571          for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
572              ;
573 <        ep->sibling = ekid;
573 >        ep->sibling = ek;
574      }
575 <    ekid->sibling = NULL;
575 >    ek->sibling = NULL;         /* shouldn't be necessary */
576   }
577  
578  
579   char *
580 < getname()                       /* scan an identifier */
580 > getname(void)                   /* scan an identifier */
581   {
582 <    static char  str[MAXWORD+1];
583 <    register int  i, lnext;
582 >    static char  str[RMAXWORD+1];
583 >    int  i, lnext;
584  
585      lnext = nextc;
586 <    for (i = 0; i < MAXWORD && isid(lnext); i++, lnext = scan())
586 >    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
587          str[i] = lnext;
588      str[i] = '\0';
589      while (isid(lnext))         /* skip rest of name */
# Line 455 | Line 594 | getname()                      /* scan an identifier */
594  
595  
596   int
597 < getinum()                       /* scan a positive integer */
597 > getinum(void)                   /* scan a positive integer */
598   {
599 <    register int  n, lnext;
599 >    int  n, lnext;
600  
601      n = 0;
602      lnext = nextc;
# Line 470 | Line 609 | getinum()                      /* scan a positive integer */
609  
610  
611   double
612 < getnum()                        /* scan a positive float */
612 > getnum(void)                    /* scan a positive float */
613   {
614 <    register int  i, lnext;
615 <    char  str[MAXWORD+1];
614 >    int  i, lnext;
615 >    char  str[RMAXWORD+1];
616  
617      i = 0;
618      lnext = nextc;
619 <    while (isdigit(lnext) && i < MAXWORD) {
619 >    while (isdigit(lnext) && i < RMAXWORD) {
620          str[i++] = lnext;
621          lnext = scan();
622      }
623 <    if (lnext == '.' && i < MAXWORD) {
624 <        str[i++] = lnext;
625 <        lnext = scan();
626 <        while (isdigit(lnext) && i < MAXWORD) {
623 >    if ((lnext == '.') & (i < RMAXWORD)) {
624 >        str[i++] = lnext;
625 >        lnext = scan();
626 >        if (i == 1 && !isdigit(lnext))
627 >            syntax("badly formed number");
628 >        while (isdigit(lnext) && i < RMAXWORD) {
629              str[i++] = lnext;
630              lnext = scan();
631          }
632      }
633 <    if ((lnext == 'e' || lnext == 'E') && i < MAXWORD) {
634 <        str[i++] = lnext;
635 <        lnext = scan();
636 <        if ((lnext == '-' || lnext == '+') && i < MAXWORD) {
633 >    if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
634 >        str[i++] = lnext;
635 >        lnext = scan();
636 >        if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
637              str[i++] = lnext;
638              lnext = scan();
639          }
640 <        while (isdigit(lnext) && i < MAXWORD) {
640 >        if (!isdigit(lnext))
641 >            syntax("missing exponent");
642 >        while (isdigit(lnext) && i < RMAXWORD) {
643              str[i++] = lnext;
644              lnext = scan();
645          }
# Line 508 | Line 651 | getnum()                       /* scan a positive float */
651  
652  
653   EPNODE *
654 < getE1()                         /* E1 -> E1 ADDOP E2 */
655 <                                /*       E2 */
654 > getE1(void)                     /* E1 -> E1 ADDOP E2 */
655 >                                /*       E2 */
656   {
657 <    register EPNODE  *ep1, *ep2;
657 >    EPNODE  *ep1, *ep2;
658  
659      ep1 = getE2();
660 <    while (nextc == '+' || nextc == '-') {
660 >    while ((nextc == '+') | (nextc == '-')) {
661          ep2 = newnode();
662          ep2->type = nextc;
663          scan();
664          addekid(ep2, ep1);
665          addekid(ep2, getE2());
666 < #ifdef  RCONST
667 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
666 >        if (esupport&E_RCONST &&
667 >                        (ep1->type == NUM) & (ep1->sibling->type == NUM))
668                  ep2 = rconst(ep2);
526 #endif
669          ep1 = ep2;
670      }
671      return(ep1);
# Line 531 | Line 673 | getE1()                                /* E1 -> E1 ADDOP E2 */
673  
674  
675   EPNODE *
676 < getE2()                         /* E2 -> E2 MULOP E3 */
677 <                                /*       E3 */
676 > getE2(void)                     /* E2 -> E2 MULOP E3 */
677 >                                /*       E3 */
678   {
679 <    register EPNODE  *ep1, *ep2;
679 >    EPNODE  *ep1, *ep2;
680  
681      ep1 = getE3();
682 <    while (nextc == '*' || nextc == '/') {
682 >    while ((nextc == '*') | (nextc == '/')) {
683          ep2 = newnode();
684          ep2->type = nextc;
685          scan();
686          addekid(ep2, ep1);
687          addekid(ep2, getE3());
688 < #ifdef  RCONST
689 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
690 <                ep2 = rconst(ep2);
691 < #endif
688 >        if (esupport&E_RCONST) {
689 >                EPNODE  *ep3 = ep1->sibling;
690 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
691 >                        ep2 = rconst(ep2);
692 >                } else if (ep3->type == NUM) {
693 >                        if (ep2->type == '/') {
694 >                                if (ep3->v.num == 0)
695 >                                        syntax("divide by zero constant");
696 >                                ep2->type = '*';        /* for speed */
697 >                                ep3->v.num = 1./ep3->v.num;
698 >                        } else if (ep3->v.num == 0) {
699 >                                ep1->sibling = NULL;    /* (E2 * 0) */
700 >                                epfree(ep2,1);
701 >                                ep2 = ep3;
702 >                        }
703 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
704 >                        epfree(ep3,1);          /* (0 * E3) or (0 / E3) */
705 >                        ep1->sibling = NULL;
706 >                        efree(ep2);
707 >                        ep2 = ep1;
708 >                }
709 >        }
710          ep1 = ep2;
711      }
712      return(ep1);
# Line 554 | Line 714 | getE2()                                /* E2 -> E2 MULOP E3 */
714  
715  
716   EPNODE *
717 < getE3()                         /* E3 -> E4 ^ E3 */
718 <                                /*       E4 */
717 > getE3(void)                     /* E3 -> E4 ^ E3 */
718 >                                /*       E4 */
719   {
720 <    register EPNODE  *ep1, *ep2;
720 >        EPNODE  *ep1, *ep2;
721  
722 <    ep1 = getE4();
723 <    if (nextc == '^') {
722 >        ep1 = getE4();
723 >        if (nextc != '^')
724 >                return(ep1);
725          ep2 = newnode();
726          ep2->type = nextc;
727          scan();
728          addekid(ep2, ep1);
729          addekid(ep2, getE3());
730 < #ifdef  RCONST
731 <        if (ep1->type == NUM && ep1->sibling->type == NUM)
732 <                ep2 = rconst(ep2);
733 < #endif
730 >        if (esupport&E_RCONST) {
731 >                EPNODE  *ep3 = ep1->sibling;
732 >                if ((ep1->type == NUM) & (ep3->type == NUM)) {
733 >                        ep2 = rconst(ep2);
734 >                } else if (ep1->type == NUM && ep1->v.num == 0) {
735 >                        epfree(ep3,1);          /* (0 ^ E3) */
736 >                        ep1->sibling = NULL;
737 >                        efree(ep2);
738 >                        ep2 = ep1;
739 >                } else if ((ep3->type == NUM && ep3->v.num == 0) |
740 >                                (ep1->type == NUM && ep1->v.num == 1)) {
741 >                        epfree(ep2,1);          /* (E4 ^ 0) or (1 ^ E3) */
742 >                        ep2 = newnode();
743 >                        ep2->type = NUM;
744 >                        ep2->v.num = 1;
745 >                } else if (ep3->type == NUM && ep3->v.num == 1) {
746 >                        efree(ep3);     /* (E4 ^ 1) */
747 >                        ep1->sibling = NULL;
748 >                        efree(ep2);
749 >                        ep2 = ep1;
750 >                }
751 >        }
752          return(ep2);
574    }
575    return(ep1);
753   }
754  
755  
756   EPNODE *
757 < getE4()                         /* E4 -> ADDOP E5 */
758 <                                /*       E5 */
757 > getE4(void)                     /* E4 -> ADDOP E5 */
758 >                                /*       E5 */
759   {
760 <    register EPNODE  *ep1, *ep2;
760 >    EPNODE  *ep1, *ep2;
761  
762      if (nextc == '-') {
763          scan();
# Line 590 | Line 767 | getE4()                                /* E4 -> ADDOP E5 */
767                  return(ep2);
768          }
769          if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
770 <            efree((char *)ep2);
771 <            return(ep2->v.kid);
770 >            ep1 = ep2->v.kid;
771 >            efree(ep2);
772 >            return(ep1);
773          }
774          ep1 = newnode();
775          ep1->type = UMINUS;
# Line 605 | Line 783 | getE4()                                /* E4 -> ADDOP E5 */
783  
784  
785   EPNODE *
786 < getE5()                         /* E5 -> (E1) */
787 <                                /*       VAR */
788 <                                /*       NUM */
789 <                                /*       $N */
790 <                                /*       FUNC(E1,..) */
791 <                                /*       ARG */
786 > getE5(void)                     /* E5 -> (E1) */
787 >                                /*       VAR */
788 >                                /*       NUM */
789 >                                /*       $N */
790 >                                /*       FUNC(E1,..) */
791 >                                /*       ARG */
792   {
793 <    int  i;
794 <    char  *nam;
795 <    register EPNODE  *ep1, *ep2;
793 >        int      i;
794 >        char  *nam;
795 >        EPNODE  *ep1, *ep2;
796  
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
797          if (nextc == '(') {
661            ep2 = newnode();
662            ep2->type = FUNC;
663            addekid(ep2, ep1);
664            ep1 = ep2;
665            do {
798                  scan();
799 <                addekid(ep1, getE1());
800 <            } while (nextc == ',');
801 <            if (nextc != ')')
802 <                syntax("')' expected");
803 <            scan();
799 >                ep1 = getE1();
800 >                if (nextc != ')')
801 >                        syntax("')' expected");
802 >                scan();
803 >                return(ep1);
804          }
805 < #ifndef  VARIABLE
806 <        else
807 <            syntax("'(' expected");
808 < #endif
809 < #endif
810 < #ifdef  RCONST
811 <        if (isconstvar(ep1))
812 <            ep1 = rconst(ep1);
813 < #endif
814 <        return(ep1);
815 <    }
816 < #endif
817 <
818 <    if (isdecimal(nextc)) {
819 <        ep1 = newnode();
820 <        ep1->type = NUM;
821 <        ep1->v.num = getnum();
822 <        return(ep1);
823 <    }
824 <    syntax("unexpected character");
805 >        if (esupport&E_INCHAN && nextc == '$') {
806 >                scan();
807 >                ep1 = newnode();
808 >                ep1->type = CHAN;
809 >                ep1->v.chan = getinum();
810 >                return(ep1);
811 >        }
812 >        if (esupport&(E_VARIABLE|E_FUNCTION) &&
813 >                        (isalpha(nextc) | (nextc == CNTXMARK))) {
814 >                nam = getname();
815 >                ep1 = NULL;
816 >                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
817 >                                && curfunc != NULL)
818 >                        for (i = 1, ep2 = curfunc->v.kid->sibling;
819 >                                        ep2 != NULL; i++, ep2 = ep2->sibling)
820 >                                if (!strcmp(ep2->v.name, nam)) {
821 >                                        ep1 = newnode();
822 >                                        ep1->type = ARG;
823 >                                        ep1->v.chan = i;
824 >                                        break;
825 >                                }
826 >                if (ep1 == NULL) {
827 >                        ep1 = newnode();
828 >                        ep1->type = VAR;
829 >                        ep1->v.ln = varinsert(nam);
830 >                }
831 >                if (esupport&E_FUNCTION && nextc == '(') {
832 >                        ep2 = newnode();
833 >                        ep2->type = FUNC;
834 >                        addekid(ep2, ep1);
835 >                        ep1 = ep2;
836 >                        do {
837 >                                scan();
838 >                                addekid(ep1, getE1());
839 >                        } while (nextc == ',');
840 >                        if (nextc != ')')
841 >                                syntax("')' expected");
842 >                        scan();
843 >                } else if (!(esupport&E_VARIABLE))
844 >                        syntax("'(' expected");
845 >                if (esupport&E_RCONST && isconstvar(ep1))
846 >                        ep1 = rconst(ep1);
847 >                return(ep1);
848 >        }
849 >        if (isdecimal(nextc)) {
850 >                ep1 = newnode();
851 >                ep1->type = NUM;
852 >                ep1->v.num = getnum();
853 >                return(ep1);
854 >        }
855 >        syntax("unexpected character");
856 >        return NULL; /* pro forma return */
857   }
858  
859  
696 #ifdef  RCONST
860   EPNODE *
861 < rconst(epar)                    /* reduce a constant expression */
862 < register EPNODE  *epar;
861 > rconst(                 /* reduce a constant expression */
862 >    EPNODE       *epar
863 > )
864   {
865 <    register EPNODE  *ep;
865 >    EPNODE  *ep;
866  
867      ep = newnode();
868      ep->type = NUM;
869      errno = 0;
870      ep->v.num = evalue(epar);
871 <    if (errno)
872 <        syntax("bad constant expression");
873 <    epfree(epar);
871 >    if ((errno == EDOM) | (errno == ERANGE))
872 >        syntax("bad constant expression");
873 >    epfree(epar,1);
874  
875      return(ep);
876   }
877  
878  
879 < isconstvar(ep)                  /* is ep linked to a constant expression? */
880 < register EPNODE  *ep;
879 > int
880 > isconstvar(                     /* is ep linked to a constant expression? */
881 >    EPNODE       *ep
882 > )
883   {
884 < #ifdef  VARIABLE
719 <    register EPNODE  *ep1;
720 < #ifdef  FUNCTION
884 >    EPNODE  *ep1;
885  
886 <    if (ep->type == FUNC) {
886 >    if (esupport&E_FUNCTION && ep->type == FUNC) {
887          if (!isconstfun(ep->v.kid))
888                  return(0);
889          for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
# Line 727 | Line 891 | register EPNODE  *ep;
891                  return(0);
892          return(1);
893      }
730 #endif
894      if (ep->type != VAR)
895          return(0);
896      ep1 = ep->v.ln->def;
897      if (ep1 == NULL || ep1->type != ':')
898          return(0);
899 < #ifdef  FUNCTION
737 <    if (ep1->v.kid->type != SYM)
899 >    if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
900          return(0);
739 #endif
901      return(1);
741 #else
742    return(ep->type == FUNC);
743 #endif
902   }
903  
904  
905 < #if  defined(FUNCTION) && defined(VARIABLE)
906 < isconstfun(ep)                  /* is ep linked to a constant function? */
907 < register EPNODE  *ep;
905 > int
906 > isconstfun(                     /* is ep linked to a constant function? */
907 >    EPNODE       *ep
908 > )
909   {
910 <    register EPNODE  *dp;
911 <    register LIBR  *lp;
910 >    EPNODE  *dp;
911 >    LIBR  *lp;
912  
913      if (ep->type != VAR)
914          return(0);
915 <    if ((dp = ep->v.ln->def) != NULL && dp->v.kid->type == FUNC)
916 <        return(dp->type == ':');
917 <    if ((lp = liblookup(ep->v.ln->name)) != NULL)
915 >    if ((dp = ep->v.ln->def) != NULL) {
916 >        if (dp->v.kid->type == FUNC)
917 >            return(dp->type == ':');
918 >        else
919 >            return(0);          /* don't identify masked library functions */
920 >    }
921 >    if ((lp = ep->v.ln->lib) != NULL)
922          return(lp->atyp == ':');
923      return(0);
924   }
762 #endif
763 #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines