ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/caldefn.c
Revision: 1.8
Committed: Tue Apr 23 12:59:33 1991 UTC (33 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +52 -12 lines
Log Message:
added ':' definitions for constant expressions

File Contents

# Content
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 * Store variable definitions.
9 *
10 * 7/1/85 Greg Ward
11 *
12 * 11/11/85 Added conditional compiles (OUTCHAN) for control output.
13 *
14 * 4/2/86 Added conditional compiles for function definitions (FUNCTION).
15 *
16 * 1/15/88 Added clock for caching of variable values.
17 *
18 * 11/16/88 Added VARDEF structure for hard linking.
19 *
20 * 5/31/90 Added conditional compile (REDEFW) for redefinition warning.
21 *
22 * 4/23/91 Added ':' defines for constant expressions (RCONST)
23 */
24
25 #include <stdio.h>
26
27 #include <ctype.h>
28
29 #include "calcomp.h"
30
31 #ifndef NHASH
32 #define NHASH 521 /* hash size (a prime!) */
33 #endif
34
35 #define newnode() (EPNODE *)ecalloc(1, sizeof(EPNODE))
36
37 extern char *ecalloc(), *savestr();
38
39 static double dvalue();
40
41 long eclock = -1; /* value storage timer */
42
43 static VARDEF *hashtbl[NHASH]; /* definition list */
44 static int htndx; /* index for */
45 static VARDEF *htpos; /* ...dfirst() and */
46 #ifdef OUTCHAN
47 static EPNODE *ochpos; /* ...dnext */
48 static EPNODE *outchan;
49 #endif
50
51 #ifdef FUNCTION
52 EPNODE *curfunc;
53 #define dname(ep) ((ep)->v.kid->type == SYM ? \
54 (ep)->v.kid->v.name : \
55 (ep)->v.kid->v.kid->v.name)
56 #else
57 #define dname(ep) ((ep)->v.kid->v.name)
58 #endif
59
60
61 fcompile(fname) /* get definitions from a file */
62 char *fname;
63 {
64 FILE *fp;
65
66 if (fname == NULL)
67 fp = stdin;
68 else if ((fp = fopen(fname, "r")) == NULL) {
69 eputs(fname);
70 eputs(": cannot open\n");
71 quit(1);
72 }
73 initfile(fp, fname, 0);
74 while (nextc != EOF)
75 loaddefn();
76 if (fname != NULL)
77 fclose(fp);
78 }
79
80
81 scompile(str, fn, ln) /* get definitions from a string */
82 char *str;
83 char *fn;
84 int ln;
85 {
86 initstr(str, fn, ln);
87 while (nextc != EOF)
88 loaddefn();
89 }
90
91
92 double
93 varvalue(vname) /* return a variable's value */
94 char *vname;
95 {
96 return(dvalue(vname, dlookup(vname)));
97 }
98
99
100 double
101 evariable(ep) /* evaluate a variable */
102 EPNODE *ep;
103 {
104 register VARDEF *dp = ep->v.ln;
105
106 return(dvalue(dp->name, dp->def));
107 }
108
109
110 varset(vname, assign, val) /* set a variable's value */
111 char *vname;
112 int assign;
113 double val;
114 {
115 register EPNODE *ep1, *ep2;
116 /* check for quick set */
117 if ((ep1 = dlookup(vname)) != NULL && ep1->v.kid->type == SYM) {
118 ep2 = ep1->v.kid->sibling;
119 if (ep2->type == NUM) {
120 ep2->v.num = val;
121 ep1->type = assign;
122 return;
123 }
124 }
125 /* hand build definition */
126 ep1 = newnode();
127 ep1->type = assign;
128 ep2 = newnode();
129 ep2->type = SYM;
130 ep2->v.name = savestr(vname);
131 addekid(ep1, ep2);
132 ep2 = newnode();
133 ep2->type = NUM;
134 ep2->v.num = val;
135 addekid(ep1, ep2);
136 dremove(vname);
137 dpush(ep1);
138 }
139
140
141 dclear(name) /* delete variable definitions of name */
142 char *name;
143 {
144 register EPNODE *ep;
145
146 while ((ep = dpop(name)) != NULL) {
147 if (ep->type == ':') {
148 dpush(ep); /* don't clear constants */
149 return;
150 }
151 epfree(ep);
152 }
153 }
154
155
156 dremove(name) /* delete all definitions of name */
157 char *name;
158 {
159 register EPNODE *ep;
160
161 while ((ep = dpop(name)) != NULL)
162 epfree(ep);
163 }
164
165
166 vardefined(name) /* return non-zero if variable defined */
167 char *name;
168 {
169 register EPNODE *dp;
170
171 return((dp = dlookup(name)) != NULL && dp->v.kid->type == SYM);
172 }
173
174
175 #ifdef OUTCHAN
176 chanout(cs) /* set output channels */
177 int (*cs)();
178 {
179 register EPNODE *ep;
180
181 for (ep = outchan; ep != NULL; ep = ep->sibling)
182 (*cs)(ep->v.kid->v.chan, evalue(ep->v.kid->sibling));
183
184 }
185 #endif
186
187
188 dclearall() /* clear all definitions */
189 {
190 register int i;
191 register VARDEF *vp;
192 register EPNODE *ep;
193
194 for (i = 0; i < NHASH; i++)
195 for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
196 dremove(vp->name);
197 #ifdef OUTCHAN
198 for (ep = outchan; ep != NULL; ep = ep->sibling)
199 epfree(ep);
200 outchan = NULL;
201 #endif
202 }
203
204
205 EPNODE *
206 dlookup(name) /* look up a definition */
207 char *name;
208 {
209 register VARDEF *vp;
210
211 if ((vp = varlookup(name)) == NULL)
212 return(NULL);
213 return(vp->def);
214 }
215
216
217 VARDEF *
218 varlookup(name) /* look up a variable */
219 char *name;
220 {
221 register VARDEF *vp;
222
223 for (vp = hashtbl[hash(name)]; vp != NULL; vp = vp->next)
224 if (!strcmp(vp->name, name))
225 return(vp);
226 return(NULL);
227 }
228
229
230 VARDEF *
231 varinsert(name) /* get a link to a variable */
232 char *name;
233 {
234 register VARDEF *vp;
235 int hv;
236
237 hv = hash(name);
238 for (vp = hashtbl[hv]; vp != NULL; vp = vp->next)
239 if (!strcmp(vp->name, name)) {
240 vp->nlinks++;
241 return(vp);
242 }
243 vp = (VARDEF *)emalloc(sizeof(VARDEF));
244 vp->name = savestr(name);
245 vp->nlinks = 1;
246 vp->def = NULL;
247 vp->lib = NULL;
248 vp->next = hashtbl[hv];
249 hashtbl[hv] = vp;
250 return(vp);
251 }
252
253
254 varfree(ln) /* release link to variable */
255 register VARDEF *ln;
256 {
257 register VARDEF *vp;
258 int hv;
259
260 if (--ln->nlinks > 0)
261 return; /* still active */
262
263 hv = hash(ln->name);
264 vp = hashtbl[hv];
265 if (vp == ln)
266 hashtbl[hv] = vp->next;
267 else {
268 while (vp->next != ln) /* must be in list */
269 vp = vp->next;
270 vp->next = ln->next;
271 }
272 freestr(ln->name);
273 efree((char *)ln);
274 }
275
276
277 EPNODE *
278 dfirst() /* return pointer to first definition */
279 {
280 htndx = 0;
281 htpos = NULL;
282 #ifdef OUTCHAN
283 ochpos = outchan;
284 #endif
285 return(dnext());
286 }
287
288
289 EPNODE *
290 dnext() /* return pointer to next definition */
291 {
292 register EPNODE *ep;
293
294 while (htndx < NHASH) {
295 if (htpos == NULL)
296 htpos = hashtbl[htndx++];
297 while (htpos != NULL) {
298 ep = htpos->def;
299 htpos = htpos->next;
300 if (ep != NULL)
301 return(ep);
302 }
303 }
304 #ifdef OUTCHAN
305 if ((ep = ochpos) != NULL)
306 ochpos = ep->sibling;
307 return(ep);
308 #else
309 return(NULL);
310 #endif
311 }
312
313
314 EPNODE *
315 dpop(name) /* pop a definition */
316 char *name;
317 {
318 register VARDEF *vp;
319 register EPNODE *dp;
320
321 if ((vp = varlookup(name)) == NULL || vp->def == NULL)
322 return(NULL);
323 dp = vp->def;
324 vp->def = dp->sibling;
325 varfree(vp);
326 return(dp);
327 }
328
329
330 dpush(ep) /* push on a definition */
331 register EPNODE *ep;
332 {
333 register VARDEF *vp;
334
335 vp = varinsert(dname(ep));
336 ep->sibling = vp->def;
337 vp->def = ep;
338 }
339
340
341 #ifdef OUTCHAN
342 addchan(sp) /* add an output channel assignment */
343 EPNODE *sp;
344 {
345 int ch = sp->v.kid->v.chan;
346 register EPNODE *ep, *epl;
347
348 for (epl = NULL, ep = outchan; ep != NULL; epl = ep, ep = ep->sibling)
349 if (ep->v.kid->v.chan >= ch) {
350 if (epl != NULL)
351 epl->sibling = sp;
352 else
353 outchan = sp;
354 if (ep->v.kid->v.chan > ch)
355 sp->sibling = ep;
356 else {
357 sp->sibling = ep->sibling;
358 epfree(ep);
359 }
360 return;
361 }
362 if (epl != NULL)
363 epl->sibling = sp;
364 else
365 outchan = sp;
366 sp->sibling = NULL;
367
368 }
369 #endif
370
371
372 loaddefn() /* load next definition */
373 {
374 register EPNODE *ep;
375
376 if (nextc == ';') { /* empty statement */
377 scan();
378 return;
379 }
380 #ifdef OUTCHAN
381 if (nextc == '$') { /* channel assignment */
382 ep = getchan();
383 addchan(ep);
384 } else
385 #endif
386 { /* ordinary definition */
387 ep = getdefn();
388 #ifdef REDEFW
389 if (dlookup(dname(ep)) != NULL) {
390 dclear(dname(ep));
391 wputs(dname(ep));
392 if (dlookup(dname(ep)) == NULL)
393 wputs(": redefined\n");
394 else
395 wputs(": redefined constant expression\n");
396 }
397 #ifdef FUNCTION
398 else if (ep->v.kid->type == FUNC &&
399 liblookup(ep->v.kid->v.kid->v.name) != NULL) {
400 wputs(ep->v.kid->v.kid->v.name);
401 wputs(": redefined library function\n");
402 }
403 #endif
404 #else
405 dclear(dname(ep));
406 #endif
407 dpush(ep);
408 }
409 if (nextc != EOF) {
410 if (nextc != ';')
411 syntax("';' expected");
412 scan();
413 }
414 }
415
416
417 EPNODE *
418 getdefn() /* A -> SYM = E1 */
419 /* SYM : E1 */
420 /* FUNC(SYM,..) = E1 */
421 /* FUNC(SYM,..) : E1 */
422 {
423 register EPNODE *ep1, *ep2;
424
425 if (!isalpha(nextc))
426 syntax("illegal variable name");
427
428 ep1 = newnode();
429 ep1->type = SYM;
430 ep1->v.name = savestr(getname());
431
432 #ifdef FUNCTION
433 if (nextc == '(') {
434 ep2 = newnode();
435 ep2->type = FUNC;
436 addekid(ep2, ep1);
437 ep1 = ep2;
438 do {
439 scan();
440 if (!isalpha(nextc))
441 syntax("illegal variable name");
442 ep2 = newnode();
443 ep2->type = SYM;
444 ep2->v.name = savestr(getname());
445 addekid(ep1, ep2);
446 } while (nextc == ',');
447 if (nextc != ')')
448 syntax("')' expected");
449 scan();
450 curfunc = ep1;
451 } else
452 curfunc = NULL;
453 #endif
454
455 if (nextc != '=' && nextc != ':')
456 syntax("'=' or ':' expected");
457
458 ep2 = newnode();
459 ep2->type = nextc;
460 scan();
461 addekid(ep2, ep1);
462 #ifdef RCONST
463 if (
464 #ifdef FUNCTION
465 ep1->type == SYM &&
466 #endif
467 ep2->type == ':')
468 addekid(ep2, rconst(getE1()));
469 else
470 #endif
471 addekid(ep2, getE1());
472
473 if (
474 #ifdef FUNCTION
475 ep1->type == SYM &&
476 #endif
477 ep1->sibling->type != NUM) {
478 ep1 = newnode();
479 ep1->type = TICK;
480 ep1->v.tick = -1;
481 addekid(ep2, ep1);
482 ep1 = newnode();
483 ep1->type = NUM;
484 addekid(ep2, ep1);
485 }
486
487 return(ep2);
488 }
489
490
491 #ifdef OUTCHAN
492 EPNODE *
493 getchan() /* A -> $N = E1 */
494 {
495 register EPNODE *ep1, *ep2;
496
497 if (nextc != '$')
498 syntax("missing '$'");
499 scan();
500
501 ep1 = newnode();
502 ep1->type = CHAN;
503 ep1->v.chan = getinum();
504
505 if (nextc != '=')
506 syntax("'=' expected");
507 scan();
508
509 ep2 = newnode();
510 ep2->type = '=';
511 addekid(ep2, ep1);
512 addekid(ep2, getE1());
513
514 return(ep2);
515 }
516 #endif
517
518
519
520 /*
521 * The following routines are for internal use only:
522 */
523
524
525 static double
526 dvalue(name, d) /* evaluate a variable */
527 char *name;
528 EPNODE *d;
529 {
530 register EPNODE *ep1, *ep2;
531
532 if (d == NULL || d->v.kid->type != SYM) {
533 eputs(name);
534 eputs(": undefined variable\n");
535 quit(1);
536 }
537 ep1 = d->v.kid->sibling; /* get expression */
538 if (ep1->type == NUM)
539 return(ep1->v.num); /* return if number */
540 ep2 = ep1->sibling; /* check time */
541 if (ep2->v.tick < 0 || ep2->v.tick < eclock) {
542 ep2->v.tick = d->type == ':' ? 1L<<30 : eclock;
543 ep2 = ep2->sibling;
544 ep2->v.num = evalue(ep1); /* needs new value */
545 } else
546 ep2 = ep2->sibling; /* else reuse old value */
547
548 return(ep2->v.num);
549 }
550
551
552 static int
553 hash(s) /* hash a string */
554 register char *s;
555 {
556 register int rval = 0;
557
558 while (*s)
559 rval += *s++;
560
561 return(rval % NHASH);
562 }