ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/calexpr.c
Revision: 1.2
Committed: Mon Apr 10 22:06:37 1989 UTC (35 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +2 -0 lines
Log Message:
Fixed conditional compile error in epfree()

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1986 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Compute data values using expression parser
9     *
10     * 7/1/85 Greg Ward
11     *
12     * 11/11/85 Made channel input conditional with (INCHAN) compiles.
13     *
14     * 4/2/86 Added conditional compiles for function definitions (FUNCTION).
15     *
16     * 1/29/87 Made variables conditional (VARIABLE)
17     *
18     * 5/19/88 Added constant subexpression elimination (RCONST)
19     */
20    
21     #include <stdio.h>
22    
23     #include <ctype.h>
24    
25     #include <errno.h>
26    
27     #include "calcomp.h"
28    
29     #define MAXLINE 256 /* maximum line length */
30     #define MAXWORD 64 /* maximum word length */
31    
32     #define newnode() (EPNODE *)ecalloc(1, sizeof(EPNODE))
33    
34     #define isid(c) (isalnum(c) || (c) == '_' || (c) == '.')
35    
36     #define isdecimal(c) (isdigit(c) || (c) == '.')
37    
38     extern double atof(), pow();
39     extern char *fgets(), *savestr();
40     extern char *emalloc(), *ecalloc();
41     extern EPNODE *curfunc;
42     extern double efunc(), evariable(), enumber(), euminus(), echannel();
43     extern double eargument(), eadd(), esubtr(), emult(), edivi(), epow();
44     extern double ebotch();
45     extern int errno;
46    
47     int nextc; /* lookahead character */
48    
49     double (*eoper[])() = { /* expression operations */
50     ebotch,
51     #ifdef VARIABLE
52     evariable,
53     #else
54     ebotch,
55     #endif
56     enumber,
57     euminus,
58     #ifdef INCHAN
59     echannel,
60     #else
61     ebotch,
62     #endif
63     #ifdef FUNCTION
64     efunc,
65     eargument,
66     #else
67     ebotch,
68     ebotch,
69     #endif
70     ebotch,
71     ebotch,
72     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74     emult,
75     eadd,
76     0,
77     esubtr,
78     0,
79     edivi,
80     0,0,0,0,0,0,0,0,0,0,0,0,0,
81     ebotch,
82     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
83     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
84     epow,
85     };
86    
87     static char *infile; /* input file name */
88     static FILE *infp; /* input file pointer */
89     static char *linbuf; /* line buffer */
90     static int linepos; /* position in buffer */
91    
92    
93     EPNODE *
94     eparse(expr) /* parse an expression string */
95     char *expr;
96     {
97     EPNODE *ep;
98    
99     initstr(NULL, expr);
100     #if defined(VARIABLE) && defined(FUNCTION)
101     curfunc = NULL;
102     #endif
103     ep = getE1();
104     if (nextc != EOF)
105     syntax("unexpected character");
106     return(ep);
107     }
108    
109    
110     double
111     eval(expr) /* evaluate an expression string */
112     char *expr;
113     {
114     register EPNODE *ep;
115     double rval;
116    
117     ep = eparse(expr);
118     rval = evalue(ep);
119     epfree(ep);
120     return(rval);
121     }
122    
123    
124     epfree(epar) /* free a parse tree */
125     register EPNODE *epar;
126     {
127     register EPNODE *ep;
128    
129     switch (epar->type) {
130    
131 greg 1.2 #if defined(VARIABLE) || defined(FUNCTION)
132 greg 1.1 case VAR:
133     varfree(epar->v.ln);
134     break;
135 greg 1.2 #endif
136 greg 1.1
137     case SYM:
138     freestr(epar->v.name);
139     break;
140    
141     case NUM:
142     case CHAN:
143     case ARG:
144     case TICK:
145     break;
146    
147     default:
148     for (ep = epar->v.kid; ep != NULL; ep = ep->sibling)
149     epfree(ep);
150     break;
151    
152     }
153    
154     efree((char *)epar);
155     }
156    
157     /* the following used to be a switch */
158     #ifdef FUNCTION
159     static double
160     eargument(ep)
161     EPNODE *ep;
162     {
163     return(argument(ep->v.chan));
164     }
165     #endif
166    
167     static double
168     enumber(ep)
169     EPNODE *ep;
170     {
171     return(ep->v.num);
172     }
173    
174     static double
175     euminus(ep)
176     EPNODE *ep;
177     {
178     register EPNODE *ep1 = ep->v.kid;
179    
180     return(-evalue(ep1));
181     }
182    
183     #ifdef INCHAN
184     static double
185     echannel(ep)
186     EPNODE *ep;
187     {
188     return(chanvalue(ep->v.chan));
189     }
190     #endif
191    
192     static double
193     eadd(ep)
194     EPNODE *ep;
195     {
196     register EPNODE *ep1 = ep->v.kid;
197    
198     return(evalue(ep1) + evalue(ep1->sibling));
199     }
200    
201     static double
202     esubtr(ep)
203     EPNODE *ep;
204     {
205     register EPNODE *ep1 = ep->v.kid;
206    
207     return(evalue(ep1) - evalue(ep1->sibling));
208     }
209    
210     static double
211     emult(ep)
212     EPNODE *ep;
213     {
214     register EPNODE *ep1 = ep->v.kid;
215    
216     return(evalue(ep1) * evalue(ep1->sibling));
217     }
218    
219     static double
220     edivi(ep)
221     EPNODE *ep;
222     {
223     register EPNODE *ep1 = ep->v.kid;
224     double d;
225    
226     d = evalue(ep1->sibling);
227     if (d == 0.0) {
228     wputs("Division by zero\n");
229     errno = ERANGE;
230     return(0.0);
231     }
232     return(evalue(ep1) / d);
233     }
234    
235     static double
236     epow(ep)
237     EPNODE *ep;
238     {
239     register EPNODE *ep1 = ep->v.kid;
240     double d;
241     int lasterrno;
242    
243     lasterrno = errno;
244     errno = 0;
245     d = pow(evalue(ep1), evalue(ep1->sibling));
246     #ifdef IEEE
247     if (!finite(d))
248     errno = EDOM;
249     #endif
250     if (errno) {
251     wputs("Illegal power\n");
252     return(0.0);
253     }
254     errno = lasterrno;
255     return(d);
256     }
257    
258     static double
259     ebotch(ep)
260     EPNODE *ep;
261     {
262     eputs("Bad expression!\n");
263     quit(1);
264     }
265    
266    
267     EPNODE *
268     ekid(ep, n) /* return pointer to a node's nth kid */
269     register EPNODE *ep;
270     register int n;
271     {
272    
273     for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
274     if (--n < 0)
275     break;
276    
277     return(ep);
278     }
279    
280    
281     int
282     nekids(ep) /* return # of kids for node ep */
283     register EPNODE *ep;
284     {
285     register int n = 0;
286    
287     for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
288     n++;
289    
290     return(n);
291     }
292    
293    
294     initfile(file, fp) /* prepare input file */
295     char *file;
296     FILE *fp;
297     {
298     static char inpbuf[MAXLINE];
299    
300     infile = file;
301     infp = fp;
302     linbuf = inpbuf;
303     linepos = 0;
304     inpbuf[0] = '\0';
305     scan();
306     }
307    
308    
309     initstr(file, s) /* prepare input string */
310     char *file;
311     char *s;
312     {
313     infile = file;
314     infp = NULL;
315     linbuf = s;
316     linepos = 0;
317     scan();
318     }
319    
320    
321     scan() /* scan next character */
322     {
323     do {
324     if (linbuf[linepos] == '\0')
325     if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
326     nextc = EOF;
327     else {
328     nextc = linbuf[0];
329     linepos = 1;
330     }
331     else
332     nextc = linbuf[linepos++];
333     if (nextc == '{') {
334     scan();
335     while (nextc != '}')
336     if (nextc == EOF)
337     syntax("'}' expected");
338     else
339     scan();
340     scan();
341     }
342     } while (isspace(nextc));
343     }
344    
345    
346     syntax(err) /* report syntax error and quit */
347     char *err;
348     {
349     register int i;
350    
351     eputs(linbuf);
352     if (linbuf[0] == '\0' || linbuf[strlen(linbuf)-1] != '\n')
353     eputs("\n");
354     for (i = 0; i < linepos-1; i++)
355     eputs(linbuf[i] == '\t' ? "\t" : " ");
356     eputs("^ ");
357     if (infile != NULL) {
358     eputs(infile);
359     eputs(": ");
360     }
361     eputs(err);
362     eputs("\n");
363     quit(1);
364     }
365    
366    
367     addekid(ep, ekid) /* add a child to ep */
368     register EPNODE *ep;
369     EPNODE *ekid;
370     {
371     if (ep->v.kid == NULL)
372     ep->v.kid = ekid;
373     else {
374     for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
375     ;
376     ep->sibling = ekid;
377     }
378     ekid->sibling = NULL;
379     }
380    
381    
382     char *
383     getname() /* scan an identifier */
384     {
385     static char str[MAXWORD+1];
386     register int i;
387    
388     for (i = 0; i < MAXWORD && isid(nextc); i++, scan())
389     str[i] = nextc;
390     str[i] = '\0';
391    
392     return(str);
393     }
394    
395    
396     int
397     getinum() /* scan a positive integer */
398     {
399     register int n;
400    
401     n = 0;
402     while (isdigit(nextc)) {
403     n = n * 10 + nextc - '0';
404     scan();
405     }
406     return(n);
407     }
408    
409    
410     double
411     getnum() /* scan a positive float */
412     {
413     register int i;
414     char str[MAXWORD+1];
415    
416     i = 0;
417     while (isdigit(nextc) && i < MAXWORD) {
418     str[i++] = nextc;
419     scan();
420     }
421     if (nextc == '.' && i < MAXWORD) {
422     str[i++] = nextc;
423     scan();
424     while (isdigit(nextc) && i < MAXWORD) {
425     str[i++] = nextc;
426     scan();
427     }
428     }
429     if ((nextc == 'e' || nextc == 'E') && i < MAXWORD) {
430     str[i++] = nextc;
431     scan();
432     if ((nextc == '-' || nextc == '+') && i < MAXWORD) {
433     str[i++] = nextc;
434     scan();
435     }
436     while (isdigit(nextc) && i < MAXWORD) {
437     str[i++] = nextc;
438     scan();
439     }
440     }
441     str[i] = '\0';
442    
443     return(atof(str));
444     }
445    
446    
447     EPNODE *
448     getE1() /* E1 -> E1 ADDOP E2 */
449     /* E2 */
450     {
451     register EPNODE *ep1, *ep2;
452    
453     ep1 = getE2();
454     while (nextc == '+' || nextc == '-') {
455     ep2 = newnode();
456     ep2->type = nextc;
457     scan();
458     addekid(ep2, ep1);
459     addekid(ep2, getE2());
460     #ifdef RCONST
461     if (ep1->type == NUM && ep1->sibling->type == NUM)
462     ep2 = rconst(ep2);
463     #endif
464     ep1 = ep2;
465     }
466     return(ep1);
467     }
468    
469    
470     EPNODE *
471     getE2() /* E2 -> E2 MULOP E3 */
472     /* E3 */
473     {
474     register EPNODE *ep1, *ep2;
475    
476     ep1 = getE3();
477     while (nextc == '*' || nextc == '/') {
478     ep2 = newnode();
479     ep2->type = nextc;
480     scan();
481     addekid(ep2, ep1);
482     addekid(ep2, getE3());
483     #ifdef RCONST
484     if (ep1->type == NUM && ep1->sibling->type == NUM)
485     ep2 = rconst(ep2);
486     #endif
487     ep1 = ep2;
488     }
489     return(ep1);
490     }
491    
492    
493     EPNODE *
494     getE3() /* E3 -> E3 ^ E4 */
495     /* E4 */
496     {
497     register EPNODE *ep1, *ep2;
498    
499     ep1 = getE4();
500     while (nextc == '^') {
501     ep2 = newnode();
502     ep2->type = nextc;
503     scan();
504     addekid(ep2, ep1);
505     addekid(ep2, getE4());
506     #ifdef RCONST
507     if (ep1->type == NUM && ep1->sibling->type == NUM)
508     ep2 = rconst(ep2);
509     #endif
510     ep1 = ep2;
511     }
512     return(ep1);
513     }
514    
515    
516     EPNODE *
517     getE4() /* E4 -> ADDOP E5 */
518     /* E5 */
519     {
520     register EPNODE *ep1;
521    
522     if (nextc == '-') {
523     scan();
524     ep1 = newnode();
525     #ifndef RCONST
526     if (isdecimal(nextc)) {
527     ep1->type = NUM;
528     ep1->v.num = -getnum();
529     return(ep1);
530     }
531     #endif
532     ep1->type = UMINUS;
533     addekid(ep1, getE5());
534     #ifdef RCONST
535     if (ep1->v.kid->type == NUM)
536     ep1 = rconst(ep1);
537     #endif
538     return(ep1);
539     }
540     if (nextc == '+')
541     scan();
542     return(getE5());
543     }
544    
545    
546     EPNODE *
547     getE5() /* E5 -> (E1) */
548     /* VAR */
549     /* NUM */
550     /* $N */
551     /* FUNC(E1,..) */
552     /* ARG */
553     {
554     int i;
555     register EPNODE *ep1, *ep2;
556    
557     if (nextc == '(') {
558     scan();
559     ep1 = getE1();
560     if (nextc != ')')
561     syntax("')' expected");
562     scan();
563     return(ep1);
564     }
565    
566     #ifdef INCHAN
567     if (nextc == '$') {
568     scan();
569     ep1 = newnode();
570     ep1->type = CHAN;
571     ep1->v.chan = getinum();
572     return(ep1);
573     }
574     #endif
575    
576     #if defined(VARIABLE) || defined(FUNCTION)
577     if (isalpha(nextc)) {
578     ep1 = newnode();
579     ep1->type = VAR;
580     ep1->v.ln = varinsert(getname());
581    
582     #if defined(VARIABLE) && defined(FUNCTION)
583     if (curfunc != NULL)
584     for (i = 1, ep2 = curfunc->v.kid->sibling;
585     ep2 != NULL; i++, ep2 = ep2->sibling)
586     if (!strcmp(ep2->v.name, ep1->v.ln->name)) {
587     epfree(ep1);
588     ep1 = newnode();
589     ep1->type = ARG;
590     ep1->v.chan = i;
591     break;
592     }
593     #endif
594     #ifdef FUNCTION
595     if (nextc == '(') {
596     ep2 = newnode();
597     ep2->type = FUNC;
598     addekid(ep2, ep1);
599     ep1 = ep2;
600     do {
601     scan();
602     addekid(ep1, getE1());
603     } while (nextc == ',');
604     if (nextc != ')')
605     syntax("')' expected");
606     scan();
607     }
608     #ifndef VARIABLE
609     else
610     syntax("'(' expected");
611     #endif
612     #endif
613     return(ep1);
614     }
615     #endif
616    
617     if (isdecimal(nextc)) {
618     ep1 = newnode();
619     ep1->type = NUM;
620     ep1->v.num = getnum();
621     return(ep1);
622     }
623     syntax("unexpected character");
624     }
625    
626    
627     #ifdef RCONST
628     EPNODE *
629     rconst(epar) /* reduce a constant expression */
630     register EPNODE *epar;
631     {
632     register EPNODE *ep;
633    
634     ep = newnode();
635     ep->type = NUM;
636     errno = 0;
637     ep->v.num = evalue(epar);
638     if (errno)
639     syntax("bad constant expression");
640     epfree(epar);
641    
642     return(ep);
643     }
644     #endif