ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/caldefn.c
Revision: 1.4
Committed: Thu Jul 19 11:06:37 1990 UTC (33 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.3: +5 -4 lines
Log Message:
added line numbers to error reports

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