ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/caldefn.c
Revision: 1.5
Committed: Thu Jul 19 11:15:31 1990 UTC (33 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.4: +4 -10 lines
Log Message:
eliminated cache for numeric definitions

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