ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/Development/ray/src/common/calexpr.c
Revision: 2.55
Committed: Sat Dec 6 04:07:05 2025 UTC (3 weeks, 5 days ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.54: +11 -4 lines
Log Message:
fix: Bug in last change and corner case of reduction to constant

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.55 static const char RCSid[] = "$Id: calexpr.c,v 2.54 2025/12/06 02:58:05 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * Compute data values using expression parser
6     *
7     * 7/1/85 Greg Ward
8     *
9     * 11/11/85 Made channel input conditional with (INCHAN) compiles.
10     *
11     * 4/2/86 Added conditional compiles for function definitions (FUNCTION).
12     *
13     * 1/29/87 Made variables conditional (VARIABLE)
14     *
15     * 5/19/88 Added constant subexpression elimination (RCONST)
16 greg 2.18 *
17     * 2/19/03 Eliminated conditional compiles in favor of esupport extern.
18     */
19    
20 greg 2.19 #include "copyright.h"
21 greg 1.1
22     #include <ctype.h>
23     #include <errno.h>
24 greg 2.8 #include <math.h>
25 greg 2.18 #include <stdlib.h>
26    
27 schorsch 2.29 #include "rtmisc.h"
28     #include "rtio.h"
29 schorsch 2.24 #include "rterror.h"
30 greg 1.1 #include "calcomp.h"
31    
32 greg 2.6 #define MAXLINE 256 /* maximum line length */
33 greg 1.1
34 greg 2.6 #define newnode() (EPNODE *)ecalloc(1, sizeof(EPNODE))
35 greg 1.1
36 greg 2.42 #define isdecimal(c) (isdigit(c) | ((c) == '.'))
37 greg 1.1
38 greg 2.44 #define envalue(ep) ((ep)->type==NUM ? (ep)->v.num : evalue(ep))
39    
40 greg 2.49 static double euminus(EPNODE *), enumber(EPNODE *);
41 schorsch 2.24 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 greg 1.1
47 greg 2.18 unsigned int esupport = /* what to support */
48 greg 2.21 E_VARIABLE | E_FUNCTION ;
49 greg 2.15
50 greg 2.30 int eofc = 0; /* optional end-of-file character */
51 greg 1.1 int nextc; /* lookahead character */
52    
53 greg 2.27 double (*eoper[])(EPNODE *) = { /* expression operations */
54 greg 1.1 ebotch,
55     evariable,
56     enumber,
57     euminus,
58     echannel,
59     efunc,
60     eargument,
61     ebotch,
62     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,
66     eadd,
67     0,
68     esubtr,
69     0,
70     edivi,
71 greg 1.9 0,0,0,0,0,0,0,0,0,0,
72 greg 1.1 ebotch,
73 greg 1.9 0,0,
74     ebotch,
75 greg 1.1 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    
80     static FILE *infp; /* input file pointer */
81     static char *linbuf; /* line buffer */
82 greg 1.6 static char *infile; /* input file name */
83     static int lineno; /* input line number */
84 greg 1.1 static int linepos; /* position in buffer */
85    
86    
87     EPNODE *
88 schorsch 2.28 eparse( /* parse an expression string */
89     char *expr
90     )
91 greg 1.1 {
92     EPNODE *ep;
93    
94 greg 1.6 initstr(expr, NULL, 0);
95 greg 2.51 ecurfunc = NULL;
96 greg 1.1 ep = getE1();
97     if (nextc != EOF)
98 greg 2.51 esyntax("unexpected character");
99 greg 1.1 return(ep);
100     }
101    
102    
103     double
104 schorsch 2.28 eval( /* evaluate an expression string */
105     char *expr
106     )
107 greg 1.1 {
108 greg 2.38 int prev_support = esupport;
109 greg 2.37 EPNODE *ep;
110 greg 1.1 double rval;
111    
112 greg 2.38 esupport &= ~E_RCONST; /* don't bother reducing constant expr */
113 greg 1.1 ep = eparse(expr);
114 greg 2.38 esupport = prev_support; /* as you were */
115 greg 1.1 rval = evalue(ep);
116 greg 2.43 epfree(ep,1);
117 greg 1.1 return(rval);
118     }
119    
120    
121 greg 2.18 int
122 schorsch 2.28 epcmp( /* compare two expressions for equivalence */
123 greg 2.37 EPNODE *ep1,
124     EPNODE *ep2
125 schorsch 2.28 )
126 greg 2.16 {
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 schorsch 2.26 return((d > 1.000000000001) | (d < 0.999999999999));
142 greg 2.16
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 greg 2.32 case CLKT:
152 greg 2.16 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 greg 2.18 void
172 schorsch 2.28 epfree( /* free a parse tree */
173 greg 2.43 EPNODE *epar,
174     int frep
175 schorsch 2.28 )
176 greg 1.1 {
177 greg 2.43 EPNODE *ep;
178 greg 1.1
179     switch (epar->type) {
180    
181     case VAR:
182     varfree(epar->v.ln);
183     break;
184    
185     case SYM:
186     freestr(epar->v.name);
187     break;
188    
189     case NUM:
190     case CHAN:
191     case ARG:
192 greg 2.32 case CLKT:
193 greg 1.1 break;
194    
195     default:
196 greg 2.43 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 greg 1.1 break;
207    
208     }
209 greg 2.43 if (frep)
210     efree(epar);
211 greg 2.50 else
212     memset(epar, 0, sizeof(EPNODE));
213 greg 2.43 }
214    
215 greg 1.1
216 greg 2.45 static void
217 greg 2.44 epflatten( /* flatten hierarchies for '+', '*' */
218     EPNODE *epar
219     )
220     {
221 greg 2.54 EPNODE *ep, *ep1;
222 greg 2.53 double combined;
223 greg 2.44
224 greg 2.53 if (epar->nkids <= 0) /* can't handle array allocations */
225 greg 2.48 return;
226    
227 greg 2.44 for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
228 greg 2.53 while ((ep->type == epar->type) & (ep->nkids > 0)) {
229     ep1 = ep->v.kid;
230 greg 2.44 while (ep1->sibling != NULL)
231     ep1 = ep1->sibling;
232     ep1->sibling = ep->sibling;
233 greg 2.48 epar->nkids += ep->nkids - 1;
234 greg 2.44 ep1 = ep->v.kid;
235     *ep = *ep1;
236     efree(ep1); /* not epfree()! */
237     }
238 greg 2.55 if (!(esupport & E_RCONST))
239 greg 2.53 return;
240 greg 2.54 ep1 = NULL; /* combine constants in sum/product */
241 greg 2.53 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 greg 2.54 else /* epar->type=='*' */ combined *= ep->v.num;
246 greg 2.53 }
247     if (ep1 == NULL)
248     return;
249 greg 2.55 ep1->v.num = combined; /* assumes commutative property, also */
250 greg 2.53 while (ep1->sibling != NULL)
251     if (ep1->sibling->type == NUM) {
252 greg 2.54 ep = ep1->sibling;
253     ep1->sibling = ep->sibling;
254 greg 2.55 epar->nkids--;
255     efree(ep); /* drop subsumed constant */
256 greg 2.53 } else
257 greg 2.54 ep1 = ep1->sibling;
258 greg 2.55
259     if (epar->nkids == 1) { /* late constant expression? */
260     ep = epar->v.kid;
261     *epar = *ep;
262     efree(ep);
263     }
264 greg 2.44 }
265    
266    
267     void
268 greg 2.47 epoptimize( /* flatten operations, lists -> arrays */
269 greg 2.43 EPNODE *epar
270     )
271     {
272     EPNODE *ep;
273    
274 greg 2.45 if ((epar->type == '+') | (epar->type == '*'))
275 greg 2.47 epflatten(epar); /* flatten associative operations */
276 greg 2.44
277 greg 2.45 if (epar->nkids) /* do children if any */
278 greg 2.44 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 greg 2.43 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 greg 2.44 epar->nkids = -n;
293 greg 2.43 }
294 greg 1.1 }
295    
296     /* the following used to be a switch */
297     static double
298 schorsch 2.28 enumber(
299     EPNODE *ep
300     )
301 greg 1.1 {
302     return(ep->v.num);
303     }
304    
305     static double
306 schorsch 2.28 euminus(
307     EPNODE *ep
308     )
309 greg 1.1 {
310 greg 2.37 EPNODE *ep1 = ep->v.kid;
311 greg 1.1
312     return(-evalue(ep1));
313     }
314    
315     static double
316 schorsch 2.28 echannel(
317     EPNODE *ep
318     )
319 greg 1.1 {
320     return(chanvalue(ep->v.chan));
321     }
322    
323     static double
324 schorsch 2.28 eadd(
325     EPNODE *ep
326     )
327 greg 1.1 {
328 greg 2.44 double sum = 0;
329 greg 2.37 EPNODE *ep1 = ep->v.kid;
330 greg 1.1
331 greg 2.44 do
332     sum += envalue(ep1);
333     while ((ep1 = ep1->sibling) != NULL);
334    
335     return(sum);
336 greg 1.1 }
337    
338     static double
339 schorsch 2.28 esubtr(
340     EPNODE *ep
341     )
342 greg 1.1 {
343 greg 2.37 EPNODE *ep1 = ep->v.kid;
344 greg 2.44 EPNODE *ep2 = ep1->sibling;
345 greg 1.1
346 greg 2.44 return(envalue(ep1) - envalue(ep2));
347 greg 1.1 }
348    
349     static double
350 schorsch 2.28 emult(
351     EPNODE *ep
352     )
353 greg 1.1 {
354 greg 2.44 double prod = 1;
355 greg 2.37 EPNODE *ep1 = ep->v.kid;
356 greg 1.1
357 greg 2.44 do
358     prod *= envalue(ep1);
359     while ((ep1 = ep1->sibling) != NULL);
360    
361     return(prod);
362 greg 1.1 }
363    
364     static double
365 schorsch 2.28 edivi(
366     EPNODE *ep
367     )
368 greg 1.1 {
369 greg 2.37 EPNODE *ep1 = ep->v.kid;
370 greg 2.48 double den = evalue(ep1->sibling);
371 greg 1.1
372 greg 2.48 if (den == 0.0) {
373 greg 1.1 wputs("Division by zero\n");
374     errno = ERANGE;
375     return(0.0);
376     }
377 greg 2.48 return(envalue(ep1) / den);
378 greg 1.1 }
379    
380     static double
381 schorsch 2.28 epow(
382     EPNODE *ep
383     )
384 greg 1.1 {
385 greg 2.37 EPNODE *ep1 = ep->v.kid;
386 greg 1.1 double d;
387 greg 2.6 int lasterrno;
388 greg 1.1
389     lasterrno = errno;
390     errno = 0;
391     d = pow(evalue(ep1), evalue(ep1->sibling));
392 greg 2.31 #ifdef isnan
393 greg 2.36 if (errno == 0) {
394 greg 2.31 if (isnan(d))
395     errno = EDOM;
396     else if (isinf(d))
397     errno = ERANGE;
398 greg 2.36 }
399 greg 1.1 #endif
400 greg 2.42 if ((errno == EDOM) | (errno == ERANGE)) {
401 greg 1.1 wputs("Illegal power\n");
402     return(0.0);
403     }
404     errno = lasterrno;
405     return(d);
406     }
407    
408     static double
409 schorsch 2.28 ebotch(
410     EPNODE *ep
411     )
412 greg 1.1 {
413     eputs("Bad expression!\n");
414     quit(1);
415 schorsch 2.22 return 0.0; /* pro forma return */
416 greg 1.1 }
417    
418    
419     EPNODE *
420 schorsch 2.28 ekid( /* return pointer to a node's nth kid */
421 greg 2.37 EPNODE *ep,
422     int n
423 schorsch 2.28 )
424 greg 1.1 {
425 greg 2.43 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 greg 1.1 return(ep);
435     }
436    
437    
438 greg 2.18 void
439 schorsch 2.28 initfile( /* prepare input file */
440     FILE *fp,
441     char *fn,
442     int ln
443     )
444 greg 1.1 {
445 greg 2.6 static char inpbuf[MAXLINE];
446 greg 1.1
447     infp = fp;
448     linbuf = inpbuf;
449 greg 1.6 infile = fn;
450     lineno = ln;
451 greg 1.1 linepos = 0;
452     inpbuf[0] = '\0';
453 greg 2.51 escan();
454 greg 1.1 }
455    
456    
457 greg 2.18 void
458 schorsch 2.28 initstr( /* prepare input string */
459     char *s,
460     char *fn,
461     int ln
462     )
463 greg 1.1 {
464     infp = NULL;
465 greg 1.6 infile = fn;
466     lineno = ln;
467 greg 1.1 linbuf = s;
468     linepos = 0;
469 greg 2.51 escan();
470 greg 1.1 }
471    
472    
473 greg 2.18 void
474 schorsch 2.28 getscanpos( /* return current scan position */
475     char **fnp,
476     int *lnp,
477     char **spp,
478     FILE **fpp
479     )
480 greg 1.13 {
481     if (fnp != NULL) *fnp = infile;
482     if (lnp != NULL) *lnp = lineno;
483     if (spp != NULL) *spp = linbuf+linepos;
484     if (fpp != NULL) *fpp = infp;
485     }
486    
487    
488 greg 1.12 int
489 greg 2.51 escan(void) /* scan next character, return literal next */
490 greg 1.1 {
491 greg 2.37 int lnext = 0;
492 greg 1.12
493 greg 1.1 do {
494     if (linbuf[linepos] == '\0')
495     if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
496     nextc = EOF;
497     else {
498     nextc = linbuf[0];
499 greg 1.6 lineno++;
500 greg 1.1 linepos = 1;
501     }
502     else
503     nextc = linbuf[linepos++];
504 greg 1.12 if (!lnext)
505     lnext = nextc;
506 greg 2.30 if (nextc == eofc) {
507     nextc = EOF;
508     break;
509     }
510 greg 1.1 if (nextc == '{') {
511 greg 2.51 escan();
512 greg 1.1 while (nextc != '}')
513     if (nextc == EOF)
514 greg 2.51 esyntax("'}' expected");
515 greg 1.1 else
516 greg 2.51 escan();
517     escan();
518 greg 1.1 }
519     } while (isspace(nextc));
520 greg 1.12 return(lnext);
521 greg 1.1 }
522    
523    
524 greg 1.6 char *
525 schorsch 2.28 long2ascii( /* convert long to ascii */
526     long l
527     )
528 greg 1.6 {
529 greg 2.6 static char buf[16];
530 greg 2.37 char *cp;
531 greg 2.6 int neg = 0;
532 greg 1.6
533     if (l == 0)
534     return("0");
535     if (l < 0) {
536     l = -l;
537     neg++;
538     }
539     cp = buf + sizeof(buf);
540     *--cp = '\0';
541     while (l) {
542     *--cp = l % 10 + '0';
543     l /= 10;
544     }
545     if (neg)
546     *--cp = '-';
547     return(cp);
548     }
549    
550    
551 greg 2.18 void
552 greg 2.51 esyntax( /* report syntax error and quit */
553 schorsch 2.28 char *err
554     )
555 greg 1.1 {
556 greg 2.37 int i;
557 greg 1.1
558 greg 2.42 if ((infile != NULL) | (lineno != 0)) {
559 greg 1.6 if (infile != NULL) eputs(infile);
560     if (lineno != 0) {
561     eputs(infile != NULL ? ", line " : "line ");
562 greg 2.9 eputs(long2ascii((long)lineno));
563 greg 1.6 }
564 greg 2.7 eputs(":\n");
565 greg 1.1 }
566 greg 1.7 eputs(linbuf);
567     if (linbuf[strlen(linbuf)-1] != '\n')
568     eputs("\n");
569     for (i = 0; i < linepos-1; i++)
570     eputs(linbuf[i] == '\t' ? "\t" : " ");
571     eputs("^ ");
572 greg 1.1 eputs(err);
573     eputs("\n");
574     quit(1);
575     }
576    
577    
578 greg 2.18 void
579 schorsch 2.28 addekid( /* add a child to ep */
580 greg 2.37 EPNODE *ep,
581 greg 2.43 EPNODE *ek
582 schorsch 2.28 )
583 greg 1.1 {
584 greg 2.47 if (ep->nkids < 0) {
585     eputs("Cannot add kid to EPNODE array\n");
586     quit(1);
587     }
588 greg 2.43 ep->nkids++;
589 greg 1.1 if (ep->v.kid == NULL)
590 greg 2.43 ep->v.kid = ek;
591 greg 1.1 else {
592     for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
593     ;
594 greg 2.43 ep->sibling = ek;
595 greg 1.1 }
596 greg 2.44 ek->sibling = NULL; /* shouldn't be necessary */
597 greg 1.1 }
598    
599    
600     char *
601 schorsch 2.28 getname(void) /* scan an identifier */
602 greg 1.1 {
603 schorsch 2.23 static char str[RMAXWORD+1];
604 greg 2.37 int i, lnext;
605 greg 1.1
606 greg 1.12 lnext = nextc;
607 greg 2.51 for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = escan())
608 greg 1.12 str[i] = lnext;
609 greg 1.1 str[i] = '\0';
610 greg 1.15 while (isid(lnext)) /* skip rest of name */
611 greg 2.51 lnext = escan();
612 greg 1.1
613     return(str);
614     }
615    
616    
617     int
618 schorsch 2.28 getinum(void) /* scan a positive integer */
619 greg 1.1 {
620 greg 2.37 int n, lnext;
621 greg 1.1
622     n = 0;
623 greg 1.12 lnext = nextc;
624     while (isdigit(lnext)) {
625     n = n * 10 + lnext - '0';
626 greg 2.51 lnext = escan();
627 greg 1.1 }
628     return(n);
629     }
630    
631    
632     double
633 schorsch 2.28 getnum(void) /* scan a positive float */
634 greg 1.1 {
635 greg 2.37 int i, lnext;
636 schorsch 2.23 char str[RMAXWORD+1];
637 greg 1.1
638     i = 0;
639 greg 1.12 lnext = nextc;
640 schorsch 2.23 while (isdigit(lnext) && i < RMAXWORD) {
641 greg 1.12 str[i++] = lnext;
642 greg 2.51 lnext = escan();
643 greg 1.1 }
644 greg 2.42 if ((lnext == '.') & (i < RMAXWORD)) {
645 greg 2.6 str[i++] = lnext;
646 greg 2.51 lnext = escan();
647 gwlarson 2.17 if (i == 1 && !isdigit(lnext))
648 greg 2.51 esyntax("badly formed number");
649 schorsch 2.23 while (isdigit(lnext) && i < RMAXWORD) {
650 greg 1.12 str[i++] = lnext;
651 greg 2.51 lnext = escan();
652 greg 1.1 }
653     }
654 schorsch 2.26 if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
655 greg 2.6 str[i++] = lnext;
656 greg 2.51 lnext = escan();
657 schorsch 2.26 if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
658 greg 1.12 str[i++] = lnext;
659 greg 2.51 lnext = escan();
660 greg 1.1 }
661 gwlarson 2.17 if (!isdigit(lnext))
662 greg 2.51 esyntax("missing exponent");
663 schorsch 2.23 while (isdigit(lnext) && i < RMAXWORD) {
664 greg 1.12 str[i++] = lnext;
665 greg 2.51 lnext = escan();
666 greg 1.1 }
667     }
668     str[i] = '\0';
669    
670     return(atof(str));
671     }
672    
673    
674     EPNODE *
675 greg 2.34 getE1(void) /* E1 -> E1 ADDOP E2 */
676 greg 2.6 /* E2 */
677 greg 1.1 {
678 greg 2.37 EPNODE *ep1, *ep2;
679 greg 1.1
680     ep1 = getE2();
681 greg 2.42 while ((nextc == '+') | (nextc == '-')) {
682 greg 1.1 ep2 = newnode();
683     ep2->type = nextc;
684 greg 2.51 escan();
685 greg 1.1 addekid(ep2, ep1);
686     addekid(ep2, getE2());
687 greg 2.18 if (esupport&E_RCONST &&
688 greg 2.42 (ep1->type == NUM) & (ep1->sibling->type == NUM))
689 greg 1.1 ep2 = rconst(ep2);
690     ep1 = ep2;
691     }
692     return(ep1);
693     }
694    
695    
696     EPNODE *
697 greg 2.34 getE2(void) /* E2 -> E2 MULOP E3 */
698 greg 2.6 /* E3 */
699 greg 1.1 {
700 greg 2.37 EPNODE *ep1, *ep2;
701 greg 1.1
702     ep1 = getE3();
703 greg 2.42 while ((nextc == '*') | (nextc == '/')) {
704 greg 1.1 ep2 = newnode();
705     ep2->type = nextc;
706 greg 2.51 escan();
707 greg 1.1 addekid(ep2, ep1);
708     addekid(ep2, getE3());
709 greg 2.34 if (esupport&E_RCONST) {
710 greg 2.52 EPNODE *ep3 = ep1->sibling;
711     if ((ep1->type == NUM) & (ep3->type == NUM)) {
712     ep2 = rconst(ep2);
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 greg 2.34 }
724 greg 2.52 } 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 greg 2.34 }
731 greg 1.1 ep1 = ep2;
732     }
733     return(ep1);
734     }
735    
736    
737     EPNODE *
738 greg 2.34 getE3(void) /* E3 -> E4 ^ E3 */
739 greg 2.6 /* E4 */
740 greg 1.1 {
741 greg 2.37 EPNODE *ep1, *ep2;
742 greg 1.1
743 greg 2.34 ep1 = getE4();
744     if (nextc != '^')
745     return(ep1);
746 greg 1.1 ep2 = newnode();
747     ep2->type = nextc;
748 greg 2.51 escan();
749 greg 1.1 addekid(ep2, ep1);
750 greg 1.8 addekid(ep2, getE3());
751 greg 2.34 if (esupport&E_RCONST) {
752 greg 2.52 EPNODE *ep3 = ep1->sibling;
753     if ((ep1->type == NUM) & (ep3->type == NUM)) {
754     ep2 = rconst(ep2);
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 greg 2.34 (ep1->type == NUM && ep1->v.num == 1)) {
762 greg 2.52 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 greg 2.34 }
772 greg 1.8 return(ep2);
773 greg 1.1 }
774    
775    
776     EPNODE *
777 greg 2.34 getE4(void) /* E4 -> ADDOP E5 */
778 greg 2.6 /* E5 */
779 greg 1.1 {
780 greg 2.37 EPNODE *ep1, *ep2;
781 greg 1.1
782     if (nextc == '-') {
783 greg 2.51 escan();
784 greg 1.3 ep2 = getE5();
785     if (ep2->type == NUM) {
786 greg 2.52 ep2->v.num = -ep2->v.num;
787     return(ep2);
788 greg 1.3 }
789 greg 1.16 if (ep2->type == UMINUS) { /* don't generate -(-E5) */
790 greg 2.33 ep1 = ep2->v.kid;
791 greg 2.41 efree(ep2);
792 greg 2.33 return(ep1);
793 greg 1.16 }
794 greg 1.1 ep1 = newnode();
795     ep1->type = UMINUS;
796 greg 1.3 addekid(ep1, ep2);
797 greg 1.1 return(ep1);
798     }
799     if (nextc == '+')
800 greg 2.51 escan();
801 greg 1.1 return(getE5());
802     }
803    
804    
805     EPNODE *
806 schorsch 2.28 getE5(void) /* E5 -> (E1) */
807 greg 2.6 /* VAR */
808     /* NUM */
809     /* $N */
810     /* FUNC(E1,..) */
811     /* ARG */
812 greg 1.1 {
813 schorsch 2.22 int i;
814     char *nam;
815 greg 2.37 EPNODE *ep1, *ep2;
816 greg 1.1
817 schorsch 2.22 if (nextc == '(') {
818 greg 2.52 escan();
819     ep1 = getE1();
820     if (nextc != ')')
821     esyntax("')' expected");
822     escan();
823     return(ep1);
824 schorsch 2.22 }
825     if (esupport&E_INCHAN && nextc == '$') {
826 greg 2.52 escan();
827     ep1 = newnode();
828     ep1->type = CHAN;
829     ep1->v.chan = getinum();
830     return(ep1);
831 schorsch 2.22 }
832     if (esupport&(E_VARIABLE|E_FUNCTION) &&
833 greg 2.42 (isalpha(nextc) | (nextc == CNTXMARK))) {
834 greg 2.52 nam = getname();
835     ep1 = NULL;
836     if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
837 greg 2.51 && ecurfunc != NULL)
838 greg 2.52 for (i = 1, ep2 = ecurfunc->v.kid->sibling;
839     ep2 != NULL; i++, ep2 = ep2->sibling)
840     if (!strcmp(ep2->v.name, nam)) {
841 schorsch 2.22 ep1 = newnode();
842 greg 2.52 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 schorsch 2.22 }
869     if (isdecimal(nextc)) {
870 greg 2.52 ep1 = newnode();
871     ep1->type = NUM;
872     ep1->v.num = getnum();
873     return(ep1);
874 schorsch 2.22 }
875 greg 2.51 esyntax("unexpected character");
876 schorsch 2.22 return NULL; /* pro forma return */
877 greg 1.1 }
878    
879    
880     EPNODE *
881 schorsch 2.28 rconst( /* reduce a constant expression */
882 greg 2.37 EPNODE *epar
883 schorsch 2.28 )
884 greg 1.1 {
885 greg 2.37 EPNODE *ep;
886 greg 1.1
887     ep = newnode();
888     ep->type = NUM;
889     errno = 0;
890     ep->v.num = evalue(epar);
891 greg 2.42 if ((errno == EDOM) | (errno == ERANGE))
892 greg 2.51 esyntax("bad constant expression");
893 greg 2.43 epfree(epar,1);
894 greg 1.1
895     return(ep);
896 greg 1.9 }
897    
898    
899 greg 2.18 int
900 schorsch 2.28 isconstvar( /* is ep linked to a constant expression? */
901 greg 2.37 EPNODE *ep
902 schorsch 2.28 )
903 greg 1.9 {
904 greg 2.37 EPNODE *ep1;
905 greg 1.10
906 greg 2.18 if (esupport&E_FUNCTION && ep->type == FUNC) {
907 greg 1.11 if (!isconstfun(ep->v.kid))
908     return(0);
909 greg 1.9 for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
910 greg 1.11 if (ep1->type != NUM && !isconstfun(ep1))
911 greg 1.9 return(0);
912     return(1);
913     }
914     if (ep->type != VAR)
915     return(0);
916     ep1 = ep->v.ln->def;
917     if (ep1 == NULL || ep1->type != ':')
918     return(0);
919 greg 2.18 if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
920 greg 1.9 return(0);
921     return(1);
922 greg 1.1 }
923 greg 1.11
924    
925 greg 2.18 int
926 schorsch 2.28 isconstfun( /* is ep linked to a constant function? */
927 greg 2.37 EPNODE *ep
928 schorsch 2.28 )
929 greg 1.11 {
930 greg 2.37 EPNODE *dp;
931 greg 2.51 ELIBR *lp;
932 greg 1.11
933     if (ep->type != VAR)
934     return(0);
935 schorsch 2.25 if ((dp = ep->v.ln->def) != NULL) {
936 greg 2.18 if (dp->v.kid->type == FUNC)
937     return(dp->type == ':');
938     else
939     return(0); /* don't identify masked library functions */
940 schorsch 2.25 }
941 greg 2.4 if ((lp = ep->v.ln->lib) != NULL)
942 greg 2.3 return(lp->atyp == ':');
943     return(0);
944 greg 1.11 }