ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/calexpr.c
Revision: 2.36
Committed: Sat Aug 1 23:27:04 2015 UTC (8 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2, rad5R0, rad5R1
Changes since 2.35: +3 -2 lines
Log Message:
Fixed various compiler warnings (mostly harmless)

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: calexpr.c,v 2.35 2010/09/04 19:04:35 greg Exp $";
3 #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 *
17 * 2/19/03 Eliminated conditional compiles in favor of esupport extern.
18 */
19
20 #include "copyright.h"
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <math.h>
27 #include <stdlib.h>
28
29 #include "rtmisc.h"
30 #include "rtio.h"
31 #include "rterror.h"
32 #include "calcomp.h"
33
34 #define MAXLINE 256 /* maximum line length */
35
36 #define newnode() (EPNODE *)ecalloc(1, sizeof(EPNODE))
37
38 #define isdecimal(c) (isdigit(c) || (c) == '.')
39
40 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
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[])(EPNODE *) = { /* expression operations */
54 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 0,0,0,0,0,0,0,0,0,0,
72 ebotch,
73 0,0,
74 ebotch,
75 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 static char *infile; /* input file name */
83 static int lineno; /* input line number */
84 static int linepos; /* position in buffer */
85
86
87 EPNODE *
88 eparse( /* parse an expression string */
89 char *expr
90 )
91 {
92 EPNODE *ep;
93
94 initstr(expr, NULL, 0);
95 curfunc = NULL;
96 ep = getE1();
97 if (nextc != EOF)
98 syntax("unexpected character");
99 return(ep);
100 }
101
102
103 double
104 eval( /* evaluate an expression string */
105 char *expr
106 )
107 {
108 register EPNODE *ep;
109 double rval;
110
111 ep = eparse(expr);
112 rval = evalue(ep);
113 epfree(ep);
114 return(rval);
115 }
116
117
118 int
119 epcmp( /* compare two expressions for equivalence */
120 register EPNODE *ep1,
121 register EPNODE *ep2
122 )
123 {
124 double d;
125
126 if (ep1->type != ep2->type)
127 return(1);
128
129 switch (ep1->type) {
130
131 case VAR:
132 return(ep1->v.ln != ep2->v.ln);
133
134 case NUM:
135 if (ep2->v.num == 0)
136 return(ep1->v.num != 0);
137 d = ep1->v.num / ep2->v.num;
138 return((d > 1.000000000001) | (d < 0.999999999999));
139
140 case CHAN:
141 case ARG:
142 return(ep1->v.chan != ep2->v.chan);
143
144 case '=':
145 case ':':
146 return(epcmp(ep1->v.kid->sibling, ep2->v.kid->sibling));
147
148 case CLKT:
149 case SYM: /* should never get this one */
150 return(0);
151
152 default:
153 ep1 = ep1->v.kid;
154 ep2 = ep2->v.kid;
155 while (ep1 != NULL) {
156 if (ep2 == NULL)
157 return(1);
158 if (epcmp(ep1, ep2))
159 return(1);
160 ep1 = ep1->sibling;
161 ep2 = ep2->sibling;
162 }
163 return(ep2 != NULL);
164 }
165 }
166
167
168 void
169 epfree( /* free a parse tree */
170 register EPNODE *epar
171 )
172 {
173 register EPNODE *ep;
174
175 switch (epar->type) {
176
177 case VAR:
178 varfree(epar->v.ln);
179 break;
180
181 case SYM:
182 freestr(epar->v.name);
183 break;
184
185 case NUM:
186 case CHAN:
187 case ARG:
188 case CLKT:
189 break;
190
191 default:
192 while ((ep = epar->v.kid) != NULL) {
193 epar->v.kid = ep->sibling;
194 epfree(ep);
195 }
196 break;
197
198 }
199
200 efree((char *)epar);
201 }
202
203 /* the following used to be a switch */
204 static double
205 eargument(
206 EPNODE *ep
207 )
208 {
209 return(argument(ep->v.chan));
210 }
211
212 static double
213 enumber(
214 EPNODE *ep
215 )
216 {
217 return(ep->v.num);
218 }
219
220 static double
221 euminus(
222 EPNODE *ep
223 )
224 {
225 register EPNODE *ep1 = ep->v.kid;
226
227 return(-evalue(ep1));
228 }
229
230 static double
231 echannel(
232 EPNODE *ep
233 )
234 {
235 return(chanvalue(ep->v.chan));
236 }
237
238 static double
239 eadd(
240 EPNODE *ep
241 )
242 {
243 register EPNODE *ep1 = ep->v.kid;
244
245 return(evalue(ep1) + evalue(ep1->sibling));
246 }
247
248 static double
249 esubtr(
250 EPNODE *ep
251 )
252 {
253 register EPNODE *ep1 = ep->v.kid;
254
255 return(evalue(ep1) - evalue(ep1->sibling));
256 }
257
258 static double
259 emult(
260 EPNODE *ep
261 )
262 {
263 register EPNODE *ep1 = ep->v.kid;
264
265 return(evalue(ep1) * evalue(ep1->sibling));
266 }
267
268 static double
269 edivi(
270 EPNODE *ep
271 )
272 {
273 register EPNODE *ep1 = ep->v.kid;
274 double d;
275
276 d = evalue(ep1->sibling);
277 if (d == 0.0) {
278 wputs("Division by zero\n");
279 errno = ERANGE;
280 return(0.0);
281 }
282 return(evalue(ep1) / d);
283 }
284
285 static double
286 epow(
287 EPNODE *ep
288 )
289 {
290 register EPNODE *ep1 = ep->v.kid;
291 double d;
292 int lasterrno;
293
294 lasterrno = errno;
295 errno = 0;
296 d = pow(evalue(ep1), evalue(ep1->sibling));
297 #ifdef isnan
298 if (errno == 0) {
299 if (isnan(d))
300 errno = EDOM;
301 else if (isinf(d))
302 errno = ERANGE;
303 }
304 #endif
305 if (errno == EDOM || errno == ERANGE) {
306 wputs("Illegal power\n");
307 return(0.0);
308 }
309 errno = lasterrno;
310 return(d);
311 }
312
313 static double
314 ebotch(
315 EPNODE *ep
316 )
317 {
318 eputs("Bad expression!\n");
319 quit(1);
320 return 0.0; /* pro forma return */
321 }
322
323
324 EPNODE *
325 ekid( /* return pointer to a node's nth kid */
326 register EPNODE *ep,
327 register int n
328 )
329 {
330
331 for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
332 if (--n < 0)
333 break;
334
335 return(ep);
336 }
337
338
339 int
340 nekids( /* return # of kids for node ep */
341 register EPNODE *ep
342 )
343 {
344 register int n = 0;
345
346 for (ep = ep->v.kid; ep != NULL; ep = ep->sibling)
347 n++;
348
349 return(n);
350 }
351
352
353 void
354 initfile( /* prepare input file */
355 FILE *fp,
356 char *fn,
357 int ln
358 )
359 {
360 static char inpbuf[MAXLINE];
361
362 infp = fp;
363 linbuf = inpbuf;
364 infile = fn;
365 lineno = ln;
366 linepos = 0;
367 inpbuf[0] = '\0';
368 scan();
369 }
370
371
372 void
373 initstr( /* prepare input string */
374 char *s,
375 char *fn,
376 int ln
377 )
378 {
379 infp = NULL;
380 infile = fn;
381 lineno = ln;
382 linbuf = s;
383 linepos = 0;
384 scan();
385 }
386
387
388 void
389 getscanpos( /* return current scan position */
390 char **fnp,
391 int *lnp,
392 char **spp,
393 FILE **fpp
394 )
395 {
396 if (fnp != NULL) *fnp = infile;
397 if (lnp != NULL) *lnp = lineno;
398 if (spp != NULL) *spp = linbuf+linepos;
399 if (fpp != NULL) *fpp = infp;
400 }
401
402
403 int
404 scan(void) /* scan next character, return literal next */
405 {
406 register int lnext = 0;
407
408 do {
409 if (linbuf[linepos] == '\0')
410 if (infp == NULL || fgets(linbuf, MAXLINE, infp) == NULL)
411 nextc = EOF;
412 else {
413 nextc = linbuf[0];
414 lineno++;
415 linepos = 1;
416 }
417 else
418 nextc = linbuf[linepos++];
419 if (!lnext)
420 lnext = nextc;
421 if (nextc == eofc) {
422 nextc = EOF;
423 break;
424 }
425 if (nextc == '{') {
426 scan();
427 while (nextc != '}')
428 if (nextc == EOF)
429 syntax("'}' expected");
430 else
431 scan();
432 scan();
433 }
434 } while (isspace(nextc));
435 return(lnext);
436 }
437
438
439 char *
440 long2ascii( /* convert long to ascii */
441 long l
442 )
443 {
444 static char buf[16];
445 register char *cp;
446 int neg = 0;
447
448 if (l == 0)
449 return("0");
450 if (l < 0) {
451 l = -l;
452 neg++;
453 }
454 cp = buf + sizeof(buf);
455 *--cp = '\0';
456 while (l) {
457 *--cp = l % 10 + '0';
458 l /= 10;
459 }
460 if (neg)
461 *--cp = '-';
462 return(cp);
463 }
464
465
466 void
467 syntax( /* report syntax error and quit */
468 char *err
469 )
470 {
471 register int i;
472
473 if (infile != NULL || lineno != 0) {
474 if (infile != NULL) eputs(infile);
475 if (lineno != 0) {
476 eputs(infile != NULL ? ", line " : "line ");
477 eputs(long2ascii((long)lineno));
478 }
479 eputs(":\n");
480 }
481 eputs(linbuf);
482 if (linbuf[strlen(linbuf)-1] != '\n')
483 eputs("\n");
484 for (i = 0; i < linepos-1; i++)
485 eputs(linbuf[i] == '\t' ? "\t" : " ");
486 eputs("^ ");
487 eputs(err);
488 eputs("\n");
489 quit(1);
490 }
491
492
493 void
494 addekid( /* add a child to ep */
495 register EPNODE *ep,
496 EPNODE *ekid
497 )
498 {
499 if (ep->v.kid == NULL)
500 ep->v.kid = ekid;
501 else {
502 for (ep = ep->v.kid; ep->sibling != NULL; ep = ep->sibling)
503 ;
504 ep->sibling = ekid;
505 }
506 ekid->sibling = NULL;
507 }
508
509
510 char *
511 getname(void) /* scan an identifier */
512 {
513 static char str[RMAXWORD+1];
514 register int i, lnext;
515
516 lnext = nextc;
517 for (i = 0; i < RMAXWORD && isid(lnext); i++, lnext = scan())
518 str[i] = lnext;
519 str[i] = '\0';
520 while (isid(lnext)) /* skip rest of name */
521 lnext = scan();
522
523 return(str);
524 }
525
526
527 int
528 getinum(void) /* scan a positive integer */
529 {
530 register int n, lnext;
531
532 n = 0;
533 lnext = nextc;
534 while (isdigit(lnext)) {
535 n = n * 10 + lnext - '0';
536 lnext = scan();
537 }
538 return(n);
539 }
540
541
542 double
543 getnum(void) /* scan a positive float */
544 {
545 register int i, lnext;
546 char str[RMAXWORD+1];
547
548 i = 0;
549 lnext = nextc;
550 while (isdigit(lnext) && i < RMAXWORD) {
551 str[i++] = lnext;
552 lnext = scan();
553 }
554 if (lnext == '.' && i < RMAXWORD) {
555 str[i++] = lnext;
556 lnext = scan();
557 if (i == 1 && !isdigit(lnext))
558 syntax("badly formed number");
559 while (isdigit(lnext) && i < RMAXWORD) {
560 str[i++] = lnext;
561 lnext = scan();
562 }
563 }
564 if ((lnext == 'e') | (lnext == 'E') && i < RMAXWORD) {
565 str[i++] = lnext;
566 lnext = scan();
567 if ((lnext == '-') | (lnext == '+') && i < RMAXWORD) {
568 str[i++] = lnext;
569 lnext = scan();
570 }
571 if (!isdigit(lnext))
572 syntax("missing exponent");
573 while (isdigit(lnext) && i < RMAXWORD) {
574 str[i++] = lnext;
575 lnext = scan();
576 }
577 }
578 str[i] = '\0';
579
580 return(atof(str));
581 }
582
583
584 EPNODE *
585 getE1(void) /* E1 -> E1 ADDOP E2 */
586 /* E2 */
587 {
588 register EPNODE *ep1, *ep2;
589
590 ep1 = getE2();
591 while (nextc == '+' || nextc == '-') {
592 ep2 = newnode();
593 ep2->type = nextc;
594 scan();
595 addekid(ep2, ep1);
596 addekid(ep2, getE2());
597 if (esupport&E_RCONST &&
598 ep1->type == NUM && ep1->sibling->type == NUM)
599 ep2 = rconst(ep2);
600 ep1 = ep2;
601 }
602 return(ep1);
603 }
604
605
606 EPNODE *
607 getE2(void) /* E2 -> E2 MULOP E3 */
608 /* E3 */
609 {
610 register EPNODE *ep1, *ep2;
611
612 ep1 = getE3();
613 while (nextc == '*' || nextc == '/') {
614 ep2 = newnode();
615 ep2->type = nextc;
616 scan();
617 addekid(ep2, ep1);
618 addekid(ep2, getE3());
619 if (esupport&E_RCONST) {
620 EPNODE *ep3 = ep1->sibling;
621 if (ep1->type == NUM && ep3->type == NUM) {
622 ep2 = rconst(ep2);
623 } else if (ep3->type == NUM) {
624 if (ep2->type == '/') {
625 if (ep3->v.num == 0)
626 syntax("divide by zero constant");
627 ep2->type = '*'; /* for speed */
628 ep3->v.num = 1./ep3->v.num;
629 } else if (ep3->v.num == 0) {
630 ep1->sibling = NULL; /* (E2 * 0) */
631 epfree(ep2);
632 ep2 = ep3;
633 }
634 } else if (ep1->type == NUM && ep1->v.num == 0) {
635 epfree(ep3); /* (0 * E3) or (0 / E3) */
636 ep1->sibling = NULL;
637 efree((char *)ep2);
638 ep2 = ep1;
639 }
640 }
641 ep1 = ep2;
642 }
643 return(ep1);
644 }
645
646
647 EPNODE *
648 getE3(void) /* E3 -> E4 ^ E3 */
649 /* E4 */
650 {
651 register EPNODE *ep1, *ep2;
652
653 ep1 = getE4();
654 if (nextc != '^')
655 return(ep1);
656 ep2 = newnode();
657 ep2->type = nextc;
658 scan();
659 addekid(ep2, ep1);
660 addekid(ep2, getE3());
661 if (esupport&E_RCONST) {
662 EPNODE *ep3 = ep1->sibling;
663 if (ep1->type == NUM && ep3->type == NUM) {
664 ep2 = rconst(ep2);
665 } else if (ep1->type == NUM && ep1->v.num == 0) {
666 epfree(ep3); /* (0 ^ E3) */
667 ep1->sibling = NULL;
668 efree((char *)ep2);
669 ep2 = ep1;
670 } else if ((ep3->type == NUM && ep3->v.num == 0) ||
671 (ep1->type == NUM && ep1->v.num == 1)) {
672 epfree(ep2); /* (E4 ^ 0) or (1 ^ E3) */
673 ep2 = newnode();
674 ep2->type = NUM;
675 ep2->v.num = 1;
676 }
677 }
678 return(ep2);
679 }
680
681
682 EPNODE *
683 getE4(void) /* E4 -> ADDOP E5 */
684 /* E5 */
685 {
686 register EPNODE *ep1, *ep2;
687
688 if (nextc == '-') {
689 scan();
690 ep2 = getE5();
691 if (ep2->type == NUM) {
692 ep2->v.num = -ep2->v.num;
693 return(ep2);
694 }
695 if (ep2->type == UMINUS) { /* don't generate -(-E5) */
696 ep1 = ep2->v.kid;
697 efree((char *)ep2);
698 return(ep1);
699 }
700 ep1 = newnode();
701 ep1->type = UMINUS;
702 addekid(ep1, ep2);
703 return(ep1);
704 }
705 if (nextc == '+')
706 scan();
707 return(getE5());
708 }
709
710
711 EPNODE *
712 getE5(void) /* E5 -> (E1) */
713 /* VAR */
714 /* NUM */
715 /* $N */
716 /* FUNC(E1,..) */
717 /* ARG */
718 {
719 int i;
720 char *nam;
721 register EPNODE *ep1, *ep2;
722
723 if (nextc == '(') {
724 scan();
725 ep1 = getE1();
726 if (nextc != ')')
727 syntax("')' expected");
728 scan();
729 return(ep1);
730 }
731
732 if (esupport&E_INCHAN && nextc == '$') {
733 scan();
734 ep1 = newnode();
735 ep1->type = CHAN;
736 ep1->v.chan = getinum();
737 return(ep1);
738 }
739
740 if (esupport&(E_VARIABLE|E_FUNCTION) &&
741 (isalpha(nextc) || nextc == CNTXMARK)) {
742 nam = getname();
743 ep1 = NULL;
744 if ((esupport&(E_VARIABLE|E_FUNCTION)) == (E_VARIABLE|E_FUNCTION)
745 && curfunc != NULL)
746 for (i = 1, ep2 = curfunc->v.kid->sibling;
747 ep2 != NULL; i++, ep2 = ep2->sibling)
748 if (!strcmp(ep2->v.name, nam)) {
749 ep1 = newnode();
750 ep1->type = ARG;
751 ep1->v.chan = i;
752 break;
753 }
754 if (ep1 == NULL) {
755 ep1 = newnode();
756 ep1->type = VAR;
757 ep1->v.ln = varinsert(nam);
758 }
759 if (esupport&E_FUNCTION && nextc == '(') {
760 ep2 = newnode();
761 ep2->type = FUNC;
762 addekid(ep2, ep1);
763 ep1 = ep2;
764 do {
765 scan();
766 addekid(ep1, getE1());
767 } while (nextc == ',');
768 if (nextc != ')')
769 syntax("')' expected");
770 scan();
771 } else if (!(esupport&E_VARIABLE))
772 syntax("'(' expected");
773 if (esupport&E_RCONST && isconstvar(ep1))
774 ep1 = rconst(ep1);
775 return(ep1);
776 }
777
778 if (isdecimal(nextc)) {
779 ep1 = newnode();
780 ep1->type = NUM;
781 ep1->v.num = getnum();
782 return(ep1);
783 }
784 syntax("unexpected character");
785 return NULL; /* pro forma return */
786 }
787
788
789 EPNODE *
790 rconst( /* reduce a constant expression */
791 register EPNODE *epar
792 )
793 {
794 register EPNODE *ep;
795
796 ep = newnode();
797 ep->type = NUM;
798 errno = 0;
799 ep->v.num = evalue(epar);
800 if (errno == EDOM || errno == ERANGE)
801 syntax("bad constant expression");
802 epfree(epar);
803
804 return(ep);
805 }
806
807
808 int
809 isconstvar( /* is ep linked to a constant expression? */
810 register EPNODE *ep
811 )
812 {
813 register EPNODE *ep1;
814
815 if (esupport&E_FUNCTION && ep->type == FUNC) {
816 if (!isconstfun(ep->v.kid))
817 return(0);
818 for (ep1 = ep->v.kid->sibling; ep1 != NULL; ep1 = ep1->sibling)
819 if (ep1->type != NUM && !isconstfun(ep1))
820 return(0);
821 return(1);
822 }
823 if (ep->type != VAR)
824 return(0);
825 ep1 = ep->v.ln->def;
826 if (ep1 == NULL || ep1->type != ':')
827 return(0);
828 if (esupport&E_FUNCTION && ep1->v.kid->type != SYM)
829 return(0);
830 return(1);
831 }
832
833
834 int
835 isconstfun( /* is ep linked to a constant function? */
836 register EPNODE *ep
837 )
838 {
839 register EPNODE *dp;
840 register LIBR *lp;
841
842 if (ep->type != VAR)
843 return(0);
844 if ((dp = ep->v.ln->def) != NULL) {
845 if (dp->v.kid->type == FUNC)
846 return(dp->type == ':');
847 else
848 return(0); /* don't identify masked library functions */
849 }
850 if ((lp = ep->v.ln->lib) != NULL)
851 return(lp->atyp == ':');
852 return(0);
853 }