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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines