ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/calexpr.c
Revision: 2.46
Committed: Sat Feb 24 19:26:44 2024 UTC (2 months, 3 weeks ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.45: +2 -2 lines
Log Message:
perf: Minor optimization

File Contents

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