ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/caldefn.c
Revision: 1.7
Committed: Fri Jul 20 08:30:23 1990 UTC (33 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +3 -2 lines
Log Message:
forgot addition for elimination of TICK for numeric def'ns

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