ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/caldefn.c
Revision: 1.3
Committed: Tue Jun 26 09:15:08 1990 UTC (33 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.2: +1 -1 lines
Log Message:
nit-picking for Stardent compiler

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