ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/Development/ray/src/common/calexpr.c
Revision: 2.54
Committed: Sat Dec 6 02:58:05 2025 UTC (3 weeks, 5 days ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.53: +9 -11 lines
Log Message:
perf: Minor optimization tweaks to previous change

File Contents

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