ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/caldefn.c
Revision: 1.2
Committed: Thu May 31 10:24:28 1990 UTC (33 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +10 -0 lines
Log Message:
added conditional compiles for redefinition warning (REDEFW)

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     extern 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 greg 1.2 #ifdef REDEFW
376     if (dlookup(dname(ep)) != NULL) {
377     dclear(dname(ep));
378     wputs(dname(ep));
379     wputs(": redefined\n");
380     }
381     #else
382 greg 1.1 dclear(dname(ep));
383 greg 1.2 #endif
384 greg 1.1 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     }