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.25 by schorsch, Mon Jul 21 22:30:17 2003 UTC vs.
Revision 2.53 by greg, Sat Dec 6 02:32:21 2025 UTC

# Line 19 | Line 19 | static const char      RCSid[] = "$Id$";
19  
20   #include "copyright.h"
21  
22 #include  <stdio.h>
23 #include  <string.h>
22   #include  <ctype.h>
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  
# Line 33 | Line 33 | static const char      RCSid[] = "$Id$";
33  
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 < static double  euminus(EPNODE *), eargument(EPNODE *), enumber(EPNODE *);
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 *),
# Line 45 | Line 47 | static double  ebotch(EPNODE *);
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,
55          evariable,
56          enumber,
# Line 82 | 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 <    curfunc = NULL;
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   int
122 < epcmp(ep1, ep2)                 /* compare two expressions for equivalence */
123 < register EPNODE  *ep1, *ep2;
122 > epcmp(                  /* compare two expressions for equivalence */
123 >    EPNODE  *ep1,
124 >    EPNODE  *ep2
125 > )
126   {
127          double  d;
128  
# Line 128 | Line 138 | register EPNODE  *ep1, *ep2;
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);
141 >                return((d > 1.000000000001) | (d < 0.999999999999));
142  
143          case CHAN:
144          case ARG:
# Line 138 | Line 148 | register EPNODE  *ep1, *ep2;
148          case ':':
149                  return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling));
150  
151 <        case TICK:
151 >        case CLKT:
152          case SYM:                       /* should never get this one */
153                  return(0);
154  
# Line 159 | Line 169 | register EPNODE  *ep1, *ep2;
169  
170  
171   void
172 < epfree(epar)                    /* free a parse tree */
173 < register EPNODE  *epar;
172 > epfree(                 /* free a parse tree */
173 >    EPNODE       *epar,
174 >    int         frep
175 > )
176   {
177 <    register EPNODE  *ep;
177 >    EPNODE      *ep;
178  
179      switch (epar->type) {
180  
# Line 177 | 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 <            while ((ep = epar->v.kid) != NULL) {
197 <                epar->v.kid = ep->sibling;
198 <                epfree(ep);
199 <            }
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, *ep2;
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 ((epar->nkids <= 2) | !(esupport & E_RCONST))
239 >        return;
240 >    ep1 = NULL;                 /* combine numbers 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 combined *= ep->v.num;
246 >        }
247 >    if (ep1 == NULL)
248 >        return;
249 >    ep1->v.num = combined;      /* elide others */
250 >    while (ep1->sibling != NULL)
251 >        if (ep1->sibling->type == NUM) {
252 >            ep2 = ep1->sibling;
253 >            ep1->sibling = ep2->sibling;
254 >            efree(ep2);
255 >            if (--epar->nkids <= 2)
256 >                break;
257 >        } else
258 >                ep1 = ep1->sibling;
259   }
260  
261 <                                /* the following used to be a switch */
262 < static double
263 < eargument(ep)
264 < EPNODE  *ep;
261 >
262 > void
263 > epoptimize(                     /* flatten operations, lists -> arrays */
264 >        EPNODE  *epar
265 > )
266   {
267 <    return(argument(ep->v.chan));
267 >    EPNODE      *ep;
268 >
269 >    if ((epar->type == '+') | (epar->type == '*'))
270 >        epflatten(epar);        /* flatten associative operations */
271 >
272 >    if (epar->nkids)            /* do children if any */
273 >        for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
274 >            epoptimize(ep);
275 >
276 >    if (epar->nkids > 4) {      /* make list into array if > 4 kids */
277 >        int     n = 1;
278 >        epar->v.kid = (EPNODE *)erealloc(epar->v.kid,
279 >                                        sizeof(EPNODE)*epar->nkids);
280 >        while (n < epar->nkids) {
281 >            ep = epar->v.kid[n-1].sibling;
282 >            epar->v.kid[n] = *ep;
283 >            efree(ep);          /* not epfree()! */
284 >            epar->v.kid[n-1].sibling = epar->v.kid + n;
285 >            n++;
286 >        }
287 >        epar->nkids = -n;
288 >    }
289   }
290  
291 +                                /* the following used to be a switch */
292   static double
293 < enumber(ep)
294 < EPNODE  *ep;
293 > enumber(
294 >    EPNODE      *ep
295 > )
296   {
297      return(ep->v.num);
298   }
299  
300   static double
301 < euminus(ep)
302 < EPNODE  *ep;
301 > euminus(
302 >    EPNODE      *ep
303 > )
304   {
305 <    register EPNODE  *ep1 = ep->v.kid;
305 >    EPNODE  *ep1 = ep->v.kid;
306  
307      return(-evalue(ep1));
308   }
309  
310   static double
311 < echannel(ep)
312 < EPNODE  *ep;
311 > echannel(
312 >    EPNODE      *ep
313 > )
314   {
315      return(chanvalue(ep->v.chan));
316   }
317  
318   static double
319 < eadd(ep)
320 < EPNODE  *ep;
319 > eadd(
320 >    EPNODE      *ep
321 > )
322   {
323 <    register EPNODE  *ep1 = ep->v.kid;
323 >    double  sum = 0;
324 >    EPNODE  *ep1 = ep->v.kid;
325  
326 <    return(evalue(ep1) + evalue(ep1->sibling));
326 >    do
327 >        sum += envalue(ep1);
328 >    while ((ep1 = ep1->sibling) != NULL);
329 >
330 >    return(sum);
331   }
332  
333   static double
334 < esubtr(ep)
335 < EPNODE  *ep;
334 > esubtr(
335 >    EPNODE      *ep
336 > )
337   {
338 <    register EPNODE  *ep1 = ep->v.kid;
338 >    EPNODE  *ep1 = ep->v.kid;
339 >    EPNODE  *ep2 = ep1->sibling;
340  
341 <    return(evalue(ep1) - evalue(ep1->sibling));
341 >    return(envalue(ep1) - envalue(ep2));
342   }
343  
344   static double
345 < emult(ep)
346 < EPNODE  *ep;
345 > emult(
346 >    EPNODE      *ep
347 > )
348   {
349 <    register EPNODE  *ep1 = ep->v.kid;
349 >    double  prod = 1;
350 >    EPNODE  *ep1 = ep->v.kid;
351  
352 <    return(evalue(ep1) * evalue(ep1->sibling));
352 >    do
353 >        prod *= envalue(ep1);
354 >    while ((ep1 = ep1->sibling) != NULL);
355 >
356 >    return(prod);
357   }
358  
359   static double
360 < edivi(ep)
361 < EPNODE  *ep;
360 > edivi(
361 >    EPNODE      *ep
362 > )
363   {
364 <    register EPNODE  *ep1 = ep->v.kid;
365 <    double  d;
364 >    EPNODE  *ep1 = ep->v.kid;
365 >    double  den = evalue(ep1->sibling);
366  
367 <    d = evalue(ep1->sibling);
261 <    if (d == 0.0) {
367 >    if (den == 0.0) {
368          wputs("Division by zero\n");
369          errno = ERANGE;
370          return(0.0);
371      }
372 <    return(evalue(ep1) / d);
372 >    return(envalue(ep1) / den);
373   }
374  
375   static double
376 < epow(ep)
377 < EPNODE  *ep;
376 > epow(
377 >    EPNODE      *ep
378 > )
379   {
380 <    register EPNODE  *ep1 = ep->v.kid;
380 >    EPNODE  *ep1 = ep->v.kid;
381      double  d;
382      int  lasterrno;
383  
384      lasterrno = errno;
385      errno = 0;
386      d = pow(evalue(ep1), evalue(ep1->sibling));
387 < #ifdef  IEEE
388 <    if (!finite(d))
389 <        errno = EDOM;
387 > #ifdef  isnan
388 >    if (errno == 0) {
389 >        if (isnan(d))
390 >            errno = EDOM;
391 >        else if (isinf(d))
392 >            errno = ERANGE;
393 >    }
394   #endif
395 <    if (errno == EDOM || errno == ERANGE) {
395 >    if ((errno == EDOM) | (errno == ERANGE)) {
396          wputs("Illegal power\n");
397          return(0.0);
398      }
# Line 290 | Line 401 | EPNODE *ep;
401   }
402  
403   static double
404 < ebotch(ep)
405 < EPNODE  *ep;
404 > ebotch(
405 >    EPNODE      *ep
406 > )
407   {
408      eputs("Bad expression!\n");
409      quit(1);
# Line 300 | Line 412 | EPNODE *ep;
412  
413  
414   EPNODE *
415 < ekid(ep, n)                     /* return pointer to a node's nth kid */
416 < register EPNODE  *ep;
417 < register int  n;
415 > ekid(                   /* return pointer to a node's nth kid */
416 >    EPNODE       *ep,
417 >    int  n
418 > )
419   {
420 <
421 <    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
422 <        if (--n < 0)
423 <            break;
424 <
420 >    if (ep->nkids < 0) {        /* allocated array? */
421 >        if (n >= -ep->nkids)
422 >            return(NULL);
423 >        return(ep->v.kid + n);
424 >    }
425 >    ep = ep->v.kid;             /* else get from list */
426 >    while (n-- > 0)
427 >        if ((ep = ep->sibling) == NULL)
428 >                break;
429      return(ep);
430   }
431  
432  
316 int
317 nekids(ep)                      /* return # of kids for node ep */
318 register EPNODE  *ep;
319 {
320    register int  n = 0;
321
322    for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
323        n++;
324
325    return(n);
326 }
327
328
433   void
434 < initfile(fp, fn, ln)            /* prepare input file */
435 < FILE  *fp;
436 < char  *fn;
437 < int  ln;
434 > initfile(               /* prepare input file */
435 >    FILE  *fp,
436 >    char  *fn,
437 >    int  ln
438 > )
439   {
440      static char  inpbuf[MAXLINE];
441  
# Line 340 | Line 445 | int  ln;
445      lineno = ln;
446      linepos = 0;
447      inpbuf[0] = '\0';
448 <    scan();
448 >    escan();
449   }
450  
451  
452   void
453 < initstr(s, fn, ln)              /* prepare input string */
454 < char  *s;
455 < char  *fn;
456 < int  ln;
453 > initstr(                /* prepare input string */
454 >    char  *s,
455 >    char  *fn,
456 >    int  ln
457 > )
458   {
459      infp = NULL;
460      infile = fn;
461      lineno = ln;
462      linbuf = s;
463      linepos = 0;
464 <    scan();
464 >    escan();
465   }
466  
467  
468   void
469 < getscanpos(fnp, lnp, spp, fpp)  /* return current scan position */
470 < char  **fnp;
471 < int  *lnp;
472 < char  **spp;
473 < FILE  **fpp;
469 > getscanpos(     /* return current scan position */
470 >    char  **fnp,
471 >    int  *lnp,
472 >    char  **spp,
473 >    FILE  **fpp
474 > )
475   {
476      if (fnp != NULL) *fnp = infile;
477      if (lnp != NULL) *lnp = lineno;
# Line 374 | Line 481 | FILE  **fpp;
481  
482  
483   int
484 < scan()                          /* scan next character, return literal next */
484 > escan(void)             /* scan next character, return literal next */
485   {
486 <    register int  lnext = 0;
486 >    int  lnext = 0;
487  
488      do {
489          if (linbuf[linepos] == '\0')
# Line 391 | Line 498 | scan()                         /* scan next character, return literal next
498              nextc = linbuf[linepos++];
499          if (!lnext)
500                  lnext = nextc;
501 +        if (nextc == eofc) {
502 +                nextc = EOF;
503 +                break;
504 +        }
505          if (nextc == '{') {
506 <            scan();
506 >            escan();
507              while (nextc != '}')
508                  if (nextc == EOF)
509 <                    syntax("'}' expected");
509 >                    esyntax("'}' expected");
510                  else
511 <                    scan();
512 <            scan();
511 >                    escan();
512 >            escan();
513          }
514      } while (isspace(nextc));
515      return(lnext);
# Line 406 | Line 517 | scan()                         /* scan next character, return literal next
517  
518  
519   char *
520 < long2ascii(l)                         /* convert long to ascii */
521 < long  l;
520 > long2ascii(                           /* convert long to ascii */
521 >    long  l
522 > )
523   {
524      static char  buf[16];
525 <    register char  *cp;
525 >    char  *cp;
526      int  neg = 0;
527  
528      if (l == 0)
# Line 432 | Line 544 | long  l;
544  
545  
546   void
547 < syntax(err)                     /* report syntax error and quit */
548 < char  *err;
547 > esyntax(                        /* report syntax error and quit */
548 >    char  *err
549 > )
550   {
551 <    register int  i;
551 >    int  i;
552  
553 <    if (infile != NULL || lineno != 0) {
553 >    if ((infile != NULL) | (lineno != 0)) {
554          if (infile != NULL) eputs(infile);
555          if (lineno != 0) {
556              eputs(infile != NULL ? ", line " : "line ");
# Line 458 | Line 571 | char  *err;
571  
572  
573   void
574 < addekid(ep, ekid)                       /* add a child to ep */
575 < register EPNODE  *ep;
576 < EPNODE  *ekid;
574 > addekid(                        /* add a child to ep */
575 >    EPNODE       *ep,
576 >    EPNODE      *ek
577 > )
578   {
579 +    if (ep->nkids < 0) {
580 +        eputs("Cannot add kid to EPNODE array\n");
581 +        quit(1);
582 +    }
583 +    ep->nkids++;
584      if (ep->v.kid == NULL)
585 <        ep->v.kid = ekid;
585 >        ep->v.kid = ek;
586      else {
587          for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
588              ;
589 <        ep->sibling = ekid;
589 >        ep->sibling = ek;
590      }
591 <    ekid->sibling = NULL;
591 >    ek->sibling = NULL;         /* shouldn't be necessary */
592   }
593  
594  
595   char *
596 < getname()                       /* scan an identifier */
596 > getname(void)                   /* scan an identifier */
597   {
598      static char  str[RMAXWORD+1];
599 <    register int  i, lnext;
599 >    int  i, lnext;
600  
601      lnext = nextc;
602 <    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
602 >    for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = escan())
603          str[i] = lnext;
604      str[i] = '\0';
605      while (isid(lnext))         /* skip rest of name */
606 <        lnext = scan();
606 >        lnext = escan();
607  
608      return(str);
609   }
610  
611  
612   int
613 < getinum()                       /* scan a positive integer */
613 > getinum(void)                   /* scan a positive integer */
614   {
615 <    register int  n, lnext;
615 >    int  n, lnext;
616  
617      n = 0;
618      lnext = nextc;
619      while (isdigit(lnext)) {
620          n = n * 10 + lnext - '0';
621 <        lnext = scan();
621 >        lnext = escan();
622      }
623      return(n);
624   }
625  
626  
627   double
628 < getnum()                        /* scan a positive float */
628 > getnum(void)                    /* scan a positive float */
629   {
630 <    register int  i, lnext;
630 >    int  i, lnext;
631      char  str[RMAXWORD+1];
632  
633      i = 0;
634      lnext = nextc;
635      while (isdigit(lnext) && i < RMAXWORD) {
636          str[i++] = lnext;
637 <        lnext = scan();
637 >        lnext = escan();
638      }
639 <    if (lnext == '.' && i < RMAXWORD) {
639 >    if ((lnext == '.') & (i < RMAXWORD)) {
640          str[i++] = lnext;
641 <        lnext = scan();
641 >        lnext = escan();
642          if (i == 1 && !isdigit(lnext))
643 <            syntax("badly formed number");
643 >            esyntax("badly formed number");
644          while (isdigit(lnext) && i < RMAXWORD) {
645              str[i++] = lnext;
646 <            lnext = scan();
646 >            lnext = escan();
647          }
648      }
649 <    if ((lnext == 'e' | lnext == 'E') && i < RMAXWORD) {
649 >    if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
650          str[i++] = lnext;
651 <        lnext = scan();
652 <        if ((lnext == '-' | lnext == '+') && i < RMAXWORD) {
651 >        lnext = escan();
652 >        if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
653              str[i++] = lnext;
654 <            lnext = scan();
654 >            lnext = escan();
655          }
656          if (!isdigit(lnext))
657 <            syntax("missing exponent");
657 >            esyntax("missing exponent");
658          while (isdigit(lnext) && i < RMAXWORD) {
659              str[i++] = lnext;
660 <            lnext = scan();
660 >            lnext = escan();
661          }
662      }
663      str[i] = '\0';
# Line 548 | Line 667 | getnum()                       /* scan a positive float */
667  
668  
669   EPNODE *
670 < getE1()                         /* E1 -> E1 ADDOP E2 */
670 > getE1(void)                     /* E1 -> E1 ADDOP E2 */
671                                  /*       E2 */
672   {
673 <    register EPNODE  *ep1, *ep2;
673 >    EPNODE  *ep1, *ep2;
674  
675      ep1 = getE2();
676 <    while (nextc == '+' || nextc == '-') {
676 >    while ((nextc == '+') | (nextc == '-')) {
677          ep2 = newnode();
678          ep2->type = nextc;
679 <        scan();
679 >        escan();
680          addekid(ep2, ep1);
681          addekid(ep2, getE2());
682          if (esupport&E_RCONST &&
683 <                        ep1->type == NUM && ep1->sibling->type == NUM)
683 >                        (ep1->type == NUM) & (ep1->sibling->type == NUM))
684                  ep2 = rconst(ep2);
685          ep1 = ep2;
686      }
# Line 570 | Line 689 | getE1()                                /* E1 -> E1 ADDOP E2 */
689  
690  
691   EPNODE *
692 < getE2()                         /* E2 -> E2 MULOP E3 */
692 > getE2(void)                     /* E2 -> E2 MULOP E3 */
693                                  /*       E3 */
694   {
695 <    register EPNODE  *ep1, *ep2;
695 >    EPNODE  *ep1, *ep2;
696  
697      ep1 = getE3();
698 <    while (nextc == '*' || nextc == '/') {
698 >    while ((nextc == '*') | (nextc == '/')) {
699          ep2 = newnode();
700          ep2->type = nextc;
701 <        scan();
701 >        escan();
702          addekid(ep2, ep1);
703          addekid(ep2, getE3());
704 <        if (esupport&E_RCONST &&
705 <                        ep1->type == NUM && ep1->sibling->type == NUM)
704 >        if (esupport&E_RCONST) {
705 >            EPNODE      *ep3 = ep1->sibling;
706 >            if ((ep1->type == NUM) & (ep3->type == NUM)) {
707                  ep2 = rconst(ep2);
708 +            } else if (ep3->type == NUM) {
709 +                if (ep2->type == '/') {
710 +                    if (ep3->v.num == 0)
711 +                        esyntax("divide by zero constant");
712 +                    ep2->type = '*';            /* for speed */
713 +                    ep3->v.num = 1./ep3->v.num;
714 +                } else if (ep3->v.num == 0) {
715 +                    ep1->sibling = NULL;        /* (E2 * 0) */
716 +                    epfree(ep2,1);
717 +                    ep2 = ep3;
718 +                }
719 +            } else if (ep1->type == NUM && ep1->v.num == 0) {
720 +                epfree(ep3,1);                  /* (0 * E3) or (0 / E3) */
721 +                ep1->sibling = NULL;
722 +                efree(ep2);
723 +                ep2 = ep1;
724 +            }
725 +        }
726          ep1 = ep2;
727      }
728      return(ep1);
# Line 592 | Line 730 | getE2()                                /* E2 -> E2 MULOP E3 */
730  
731  
732   EPNODE *
733 < getE3()                         /* E3 -> E4 ^ E3 */
733 > getE3(void)                     /* E3 -> E4 ^ E3 */
734                                  /*       E4 */
735   {
736 <    register EPNODE  *ep1, *ep2;
736 >        EPNODE  *ep1, *ep2;
737  
738 <    ep1 = getE4();
739 <    if (nextc == '^') {
738 >        ep1 = getE4();
739 >        if (nextc != '^')
740 >                return(ep1);
741          ep2 = newnode();
742          ep2->type = nextc;
743 <        scan();
743 >        escan();
744          addekid(ep2, ep1);
745          addekid(ep2, getE3());
746 <        if (esupport&E_RCONST &&
747 <                        ep1->type == NUM && ep1->sibling->type == NUM)
746 >        if (esupport&E_RCONST) {
747 >            EPNODE      *ep3 = ep1->sibling;
748 >            if ((ep1->type == NUM) & (ep3->type == NUM)) {
749                  ep2 = rconst(ep2);
750 +            } else if (ep1->type == NUM && ep1->v.num == 0) {
751 +                epfree(ep3,1);          /* (0 ^ E3) */
752 +                ep1->sibling = NULL;
753 +                efree(ep2);
754 +                ep2 = ep1;
755 +            } else if ((ep3->type == NUM && ep3->v.num == 0) |
756 +                                (ep1->type == NUM && ep1->v.num == 1)) {
757 +                epfree(ep2,0);          /* (E4 ^ 0) or (1 ^ E3) */
758 +                ep2->type = NUM;
759 +                ep2->v.num = 1;
760 +            } else if (ep3->type == NUM && ep3->v.num == 1) {
761 +                efree(ep3);             /* (E4 ^ 1) */
762 +                ep1->sibling = NULL;
763 +                efree(ep2);
764 +                ep2 = ep1;
765 +            }
766 +        }
767          return(ep2);
611    }
612    return(ep1);
768   }
769  
770  
771   EPNODE *
772 < getE4()                         /* E4 -> ADDOP E5 */
772 > getE4(void)                     /* E4 -> ADDOP E5 */
773                                  /*       E5 */
774   {
775 <    register EPNODE  *ep1, *ep2;
775 >    EPNODE  *ep1, *ep2;
776  
777      if (nextc == '-') {
778 <        scan();
778 >        escan();
779          ep2 = getE5();
780          if (ep2->type == NUM) {
781 <                ep2->v.num = -ep2->v.num;
782 <                return(ep2);
781 >            ep2->v.num = -ep2->v.num;
782 >            return(ep2);
783          }
784          if (ep2->type == UMINUS) {      /* don't generate -(-E5) */
785 <            efree((char *)ep2);
786 <            return(ep2->v.kid);
785 >            ep1 = ep2->v.kid;
786 >            efree(ep2);
787 >            return(ep1);
788          }
789          ep1 = newnode();
790          ep1->type = UMINUS;
# Line 636 | Line 792 | getE4()                                /* E4 -> ADDOP E5 */
792          return(ep1);
793      }
794      if (nextc == '+')
795 <        scan();
795 >        escan();
796      return(getE5());
797   }
798  
799  
800   EPNODE *
801 < getE5()                         /* E5 -> (E1) */
801 > getE5(void)                     /* E5 -> (E1) */
802                                  /*       VAR */
803                                  /*       NUM */
804                                  /*       $N */
# Line 651 | Line 807 | getE5()                                /* E5 -> (E1) */
807   {
808          int      i;
809          char  *nam;
810 <        register EPNODE  *ep1, *ep2;
810 >        EPNODE  *ep1, *ep2;
811  
812          if (nextc == '(') {
813 <                scan();
814 <                ep1 = getE1();
815 <                if (nextc != ')')
816 <                        syntax("')' expected");
817 <                scan();
818 <                return(ep1);
813 >            escan();
814 >            ep1 = getE1();
815 >            if (nextc != ')')
816 >                esyntax("')' expected");
817 >            escan();
818 >            return(ep1);
819          }
664
820          if (esupport&E_INCHAN && nextc == '$') {
821 <                scan();
822 <                ep1 = newnode();
823 <                ep1->type = CHAN;
824 <                ep1->v.chan = getinum();
825 <                return(ep1);
821 >            escan();
822 >            ep1 = newnode();
823 >            ep1->type = CHAN;
824 >            ep1->v.chan = getinum();
825 >            return(ep1);
826          }
672
827          if (esupport&(E_VARIABLE|E_FUNCTION) &&
828 <                        (isalpha(nextc) || nextc == CNTXMARK)) {
829 <                nam = getname();
830 <                ep1 = NULL;
831 <                if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
832 <                                && curfunc != NULL)
833 <                        for (i = 1, ep2 = curfunc->v.kid->sibling;
834 <                                        ep2 != NULL; i++, ep2 = ep2->sibling)
835 <                                if (!strcmp(ep2->v.name, nam)) {
682 <                                        ep1 = newnode();
683 <                                        ep1->type = ARG;
684 <                                        ep1->v.chan = i;
685 <                                        break;
686 <                                }
687 <                if (ep1 == NULL) {
828 >                        (isalpha(nextc) | (nextc == CNTXMARK))) {
829 >            nam = getname();
830 >            ep1 = NULL;
831 >            if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
832 >                                && ecurfunc != NULL)
833 >                for (i = 1, ep2 = ecurfunc->v.kid->sibling;
834 >                                ep2 != NULL; i++, ep2 = ep2->sibling)
835 >                    if (!strcmp(ep2->v.name, nam)) {
836                          ep1 = newnode();
837 <                        ep1->type = VAR;
838 <                        ep1->v.ln = varinsert(nam);
839 <                }
840 <                if (esupport&E_FUNCTION && nextc == '(') {
841 <                        ep2 = newnode();
842 <                        ep2->type = FUNC;
843 <                        addekid(ep2, ep1);
844 <                        ep1 = ep2;
845 <                        do {
846 <                                scan();
847 <                                addekid(ep1, getE1());
848 <                        } while (nextc == ',');
849 <                        if (nextc != ')')
850 <                                syntax("')' expected");
851 <                        scan();
852 <                } else if (!(esupport&E_VARIABLE))
853 <                        syntax("'(' expected");
854 <                if (esupport&E_RCONST && isconstvar(ep1))
855 <                        ep1 = rconst(ep1);
856 <                return(ep1);
837 >                        ep1->type = ARG;
838 >                        ep1->v.chan = i;
839 >                        break;
840 >                    }
841 >            if (ep1 == NULL) {
842 >                ep1 = newnode();
843 >                ep1->type = VAR;
844 >                ep1->v.ln = varinsert(nam);
845 >            }
846 >            if (esupport&E_FUNCTION && nextc == '(') {
847 >                ep2 = newnode();
848 >                ep2->type = FUNC;
849 >                addekid(ep2, ep1);
850 >                ep1 = ep2;
851 >                do {
852 >                    escan();
853 >                    addekid(ep1, getE1());
854 >                } while (nextc == ',');
855 >                if (nextc != ')')
856 >                    esyntax("')' expected");
857 >                escan();
858 >            } else if (!(esupport&E_VARIABLE))
859 >                esyntax("'(' expected");
860 >            if (esupport&E_RCONST && isconstvar(ep1))
861 >                ep1 = rconst(ep1);
862 >            return(ep1);
863          }
710
864          if (isdecimal(nextc)) {
865 <                ep1 = newnode();
866 <                ep1->type = NUM;
867 <                ep1->v.num = getnum();
868 <                return(ep1);
865 >            ep1 = newnode();
866 >            ep1->type = NUM;
867 >            ep1->v.num = getnum();
868 >            return(ep1);
869          }
870 <        syntax("unexpected character");
870 >        esyntax("unexpected character");
871          return NULL; /* pro forma return */
872   }
873  
874  
875   EPNODE *
876 < rconst(epar)                    /* reduce a constant expression */
877 < register EPNODE  *epar;
876 > rconst(                 /* reduce a constant expression */
877 >    EPNODE       *epar
878 > )
879   {
880 <    register EPNODE  *ep;
880 >    EPNODE  *ep;
881  
882      ep = newnode();
883      ep->type = NUM;
884      errno = 0;
885      ep->v.num = evalue(epar);
886 <    if (errno == EDOM || errno == ERANGE)
887 <        syntax("bad constant expression");
888 <    epfree(epar);
886 >    if ((errno == EDOM) | (errno == ERANGE))
887 >        esyntax("bad constant expression");
888 >    epfree(epar,1);
889  
890      return(ep);
891   }
892  
893  
894   int
895 < isconstvar(ep)                  /* is ep linked to a constant expression? */
896 < register EPNODE  *ep;
895 > isconstvar(                     /* is ep linked to a constant expression? */
896 >    EPNODE       *ep
897 > )
898   {
899 <    register EPNODE  *ep1;
899 >    EPNODE  *ep1;
900  
901      if (esupport&E_FUNCTION && ep->type == FUNC) {
902          if (!isconstfun(ep->v.kid))
# Line 763 | Line 918 | register EPNODE         *ep;
918  
919  
920   int
921 < isconstfun(ep)                  /* is ep linked to a constant function? */
922 < register EPNODE  *ep;
921 > isconstfun(                     /* is ep linked to a constant function? */
922 >    EPNODE       *ep
923 > )
924   {
925 <    register EPNODE  *dp;
926 <    register LIBR  *lp;
925 >    EPNODE  *dp;
926 >    ELIBR  *lp;
927  
928      if (ep->type != VAR)
929          return(0);

Diff Legend

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