ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/Development/ray/src/common/calexpr.c
(Generate patch)

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

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)