ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/caldefn.c
(Generate patch)

Comparing ray/src/common/caldefn.c (file contents):
Revision 1.3 by greg, Tue Jun 26 09:15:08 1990 UTC vs.
Revision 2.5 by greg, Sat Nov 21 21:42:42 1992 UTC

# Line 1 | Line 1
1 < /* Copyright (c) 1986 Regents of the University of California */
1 > /* Copyright (c) 1992 Regents of the University of California */
2  
3   #ifndef lint
4   static char SCCSid[] = "$SunId$ LBL";
# Line 18 | Line 18 | static char SCCSid[] = "$SunId$ LBL";
18   *  11/16/88  Added VARDEF structure for hard linking.
19   *
20   *  5/31/90  Added conditional compile (REDEFW) for redefinition warning.
21 + *
22 + *  4/23/91  Added ':' assignment for constant expressions
23 + *
24 + *  8/7/91  Added optional context path to append to variable names
25   */
26  
27   #include  <stdio.h>
# Line 26 | Line 30 | static char SCCSid[] = "$SunId$ LBL";
30  
31   #include  "calcomp.h"
32  
33 < #ifndef  NHASH
34 < #define  NHASH          521             /* hash size (a prime!) */
33 > #ifndef  NHASH
34 > #define  NHASH          521             /* hash size (a prime!) */
35   #endif
36  
37 < #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
37 > #define  hash(s)        (shash(s)%NHASH)
38  
39 < extern char  *ecalloc(), *savestr();
39 > #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
40  
41 + extern char  *ecalloc(), *emalloc(), *savestr(), *strcpy();
42 +
43   static double  dvalue();
44  
45   long  eclock = -1;                      /* value storage timer */
46  
47 + static char  context[MAXWORD+1];        /* current context path */
48 +
49   static VARDEF  *hashtbl[NHASH];         /* definition list */
50   static int  htndx;                      /* index for */        
51   static VARDEF  *htpos;                  /* ...dfirst() and */
52 < #ifdef  OUTCHAN
52 > #ifdef  OUTCHAN
53   static EPNODE  *ochpos;                 /* ...dnext */
54   static EPNODE  *outchan;
55   #endif
56  
57 < #ifdef  FUNCTION
58 < EPNODE  *curfunc;
59 < #define  dname(ep)      ((ep)->v.kid->type == SYM ? \
57 > #ifdef  FUNCTION
58 > EPNODE  *curfunc;
59 > #define  dname(ep)      ((ep)->v.kid->type == SYM ? \
60                          (ep)->v.kid->v.name : \
61                          (ep)->v.kid->v.kid->v.name)
62   #else
63 < #define  dname(ep)      ((ep)->v.kid->v.name)
63 > #define  dname(ep)      ((ep)->v.kid->v.name)
64   #endif
65  
66  
# Line 68 | Line 76 | char  *fname;
76          eputs(": cannot open\n");
77          quit(1);
78      }
79 <    initfile(fname, fp);
79 >    initfile(fp, fname, 0);
80      while (nextc != EOF)
81 <        loaddefn();
81 >        getstatement();
82      if (fname != NULL)
83          fclose(fp);
84   }
85  
86  
87 < scompile(file, str)             /* get definitions from a string */
80 < char  *file;
87 > scompile(str, fn, ln)           /* get definitions from a string */
88   char  *str;
89 + char  *fn;
90 + int  ln;
91   {
92 <    initstr(file, str);
92 >    initstr(str, fn, ln);
93      while (nextc != EOF)
94 <        loaddefn();
94 >        getstatement();
95   }
96  
97  
# Line 96 | Line 105 | char  *vname;
105  
106   double
107   evariable(ep)                   /* evaluate a variable */
108 < EPNODE  *ep;
108 > EPNODE  *ep;
109   {
110      register VARDEF  *dp = ep->v.ln;
111  
# Line 104 | Line 113 | EPNODE  *ep;
113   }
114  
115  
116 < varset(vname, val)              /* set a variable's value */
116 > varset(vname, assign, val)      /* set a variable's value */
117   char  *vname;
118 < double  val;
118 > int  assign;
119 > double  val;
120   {
121 +    char  *qname;
122      register EPNODE  *ep1, *ep2;
123 +                                        /* get qualified name */
124 +    qname = qualname(vname, 0);
125                                          /* check for quick set */
126 <    if ((ep1 = dlookup(vname)) != NULL && ep1->v.kid->type == SYM) {
126 >    if ((ep1 = dlookup(qname)) != NULL && ep1->v.kid->type == SYM) {
127          ep2 = ep1->v.kid->sibling;
128          if (ep2->type == NUM) {
129              ep2->v.num = val;
130 <            ep2->sibling->v.tick = -1;
130 >            ep1->type = assign;
131              return;
132          }
133      }
134                                          /* hand build definition */
135      ep1 = newnode();
136 <    ep1->type = '=';
136 >    ep1->type = assign;
137      ep2 = newnode();
138      ep2->type = SYM;
139      ep2->v.name = savestr(vname);
# Line 129 | Line 142 | double  val;
142      ep2->type = NUM;
143      ep2->v.num = val;
144      addekid(ep1, ep2);
145 <    ep2 = newnode();
146 <    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);
145 >    dremove(qname);
146 >    dpush(qname, ep1);
147   }
148  
149  
150 < dclear(name)                    /* delete all definitions of name */
150 > dclear(name)                    /* delete variable definitions of name */
151   char  *name;
152   {
153      register EPNODE  *ep;
154  
155 +    while ((ep = dpop(name)) != NULL) {
156 +        if (ep->type == ':') {
157 +            dpush(name, ep);            /* don't clear constants */
158 +            return;
159 +        }
160 +        epfree(ep);
161 +    }
162 + }
163 +
164 +
165 + dremove(name)                   /* delete all definitions of name */
166 + char  *name;
167 + {
168 +    register EPNODE  *ep;
169 +
170      while ((ep = dpop(name)) != NULL)
171          epfree(ep);
172   }
# Line 160 | Line 181 | char  *name;
181   }
182  
183  
184 < #ifdef  OUTCHAN
185 < chanout()                       /* set output channels */
184 > char *
185 > setcontext(ctx)                 /* set a new context path */
186 > register char  *ctx;
187   {
188 +    register char  *cpp;
189 +
190 +    if (ctx == NULL)
191 +        return(context);                /* just asking */
192 +    if (!*ctx) {
193 +        context[0] = '\0';              /* clear context */
194 +        return(context);
195 +    }
196 +    cpp = context;                      /* else copy it (carefully!) */
197 +    if (*ctx != CNTXMARK)
198 +        *cpp++ = CNTXMARK;              /* make sure there's a mark */
199 +    do {
200 +        if (cpp >= context+MAXWORD)
201 +            break;                      /* just copy what we can */
202 +        if (isid(*ctx))
203 +            *cpp++ = *ctx++;
204 +        else {
205 +            *cpp++ = '_'; ctx++;
206 +        }
207 +    } while (*ctx);
208 +    *cpp = '\0';
209 +    return(context);
210 + }
211 +
212 +
213 + char *
214 + qualname(nam, lvl)              /* get qualified name */
215 + register char  *nam;
216 + int  lvl;
217 + {
218 +    static char  nambuf[MAXWORD+1];
219 +    register char  *cp = nambuf, *cpp;
220 +                                /* check for explicit local */
221 +    if (*nam == CNTXMARK)
222 +        if (lvl > 0)            /* only action is to refuse search */
223 +            return(NULL);
224 +        else
225 +            nam++;
226 +    else if (nam == nambuf)     /* check for repeat call */
227 +        return(lvl > 0 ? NULL : nam);
228 +                                /* copy name to static buffer */
229 +    while (*nam) {
230 +        if (cp >= nambuf+MAXWORD)
231 +                goto toolong;
232 +        *cp++ = *nam++;
233 +    }
234 +                                /* check for explicit global */
235 +    if (cp > nambuf && cp[-1] == CNTXMARK) {
236 +        if (lvl > 0)
237 +            return(NULL);
238 +        *--cp = '\0';
239 +        return(nambuf);         /* already qualified */
240 +    }
241 +    cpp = context;              /* else skip the requested levels */
242 +    while (lvl-- > 0) {
243 +        if (!*cpp)
244 +            return(NULL);       /* return NULL if past global level */
245 +        while (*++cpp && *cpp != CNTXMARK)
246 +            ;
247 +    }
248 +    while (*cpp) {              /* copy context to static buffer */
249 +        if (cp >= nambuf+MAXWORD)
250 +            goto toolong;
251 +        *cp++ = *cpp++;
252 +    }
253 + toolong:
254 +    *cp = '\0';
255 +    return(nambuf);             /* return qualified name */
256 + }
257 +
258 +
259 + incontext(qn)                   /* is qualified name in current context? */
260 + register char  *qn;
261 + {
262 +    while (*qn && *qn != CNTXMARK)      /* find context mark */
263 +        qn++;
264 +    return(!strcmp(qn, context));
265 + }
266 +
267 +
268 + #ifdef  OUTCHAN
269 + chanout(cs)                     /* set output channels */
270 + int  (*cs)();
271 + {
272      register EPNODE  *ep;
273  
274      for (ep = outchan; ep != NULL; ep = ep->sibling)
275 <        chanset(ep->v.kid->v.chan, evalue(ep->v.kid->sibling));
275 >        (*cs)(ep->v.kid->v.chan, evalue(ep->v.kid->sibling));
276  
277   }
278   #endif
279  
280  
281 < dclearall()                     /* clear all definitions */
281 > dcleanup(lvl)           /* clear definitions (0->vars,1->output,2->consts) */
282 > int  lvl;
283   {
284      register int  i;
285      register VARDEF  *vp;
286      register EPNODE  *ep;
287 <
287 >                                /* if context is global, clear all */
288      for (i = 0; i < NHASH; i++)
289          for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
290 <            dclear(vp->name);
291 < #ifdef  OUTCHAN
292 <    for (ep = outchan; ep != NULL; ep = ep->sibling)
293 <        epfree(ep);
294 <    outchan = NULL;
290 >            if (!context[0] || incontext(vp->name))
291 >                if (lvl >= 2)
292 >                    dremove(vp->name);
293 >                else
294 >                    dclear(vp->name);
295 > #ifdef  OUTCHAN
296 >    if (lvl >= 1) {
297 >        for (ep = outchan; ep != NULL; ep = ep->sibling)
298 >            epfree(ep);
299 >        outchan = NULL;
300 >    }
301   #endif
302   }
303  
# Line 196 | Line 309 | char  *name;
309      register VARDEF  *vp;
310      
311      if ((vp = varlookup(name)) == NULL)
312 <        return(NULL);
312 >        return(NULL);
313      return(vp->def);
314   }
315  
# Line 205 | Line 318 | VARDEF *
318   varlookup(name)                 /* look up a variable */
319   char  *name;
320   {
321 +    int  lvl = 0;
322 +    register char  *qname;
323      register VARDEF  *vp;
324 <    
325 <    for (vp = hashtbl[hash(name)]; vp != NULL; vp = vp->next)
326 <        if (!strcmp(vp->name, name))
327 <            return(vp);
324 >                                /* find most qualified match */
325 >    while ((qname = qualname(name, lvl++)) != NULL)
326 >        for (vp = hashtbl[hash(qname)]; vp != NULL; vp = vp->next)
327 >            if (!strcmp(vp->name, qname))
328 >                return(vp);
329      return(NULL);
330   }
331  
# Line 219 | Line 335 | varinsert(name)                        /* get a link to a variable */
335   char  *name;
336   {
337      register VARDEF  *vp;
338 <    int  hv;
338 >    int  hv;
339      
340 <    hv = hash(name);
341 <    for (vp = hashtbl[hv]; vp != NULL; vp = vp->next)
342 <        if (!strcmp(vp->name, name)) {
343 <            vp->nlinks++;
228 <            return(vp);
229 <        }
340 >    if ((vp = varlookup(name)) != NULL) {
341 >        vp->nlinks++;
342 >        return(vp);
343 >    }
344      vp = (VARDEF *)emalloc(sizeof(VARDEF));
345 + #ifdef  FUNCTION
346 +    vp->lib = liblookup(name);
347 + #else
348 +    vp->lib = NULL;
349 + #endif
350 +    if (vp->lib == NULL)                /* if name not in library */
351 +        name = qualname(name, 0);       /* use fully qualified version */
352 +    hv = hash(name);
353      vp->name = savestr(name);
354      vp->nlinks = 1;
355      vp->def = NULL;
234    vp->lib = NULL;
356      vp->next = hashtbl[hv];
357      hashtbl[hv] = vp;
358      return(vp);
359   }
360  
361  
362 + #ifdef  FUNCTION
363 + libupdate(fn)                   /* update library links */
364 + char  *fn;
365 + {
366 +    register int  i;
367 +    register VARDEF  *vp;
368 +                                        /* if fn is NULL then relink all */
369 +    for (i = 0; i < NHASH; i++)
370 +        for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
371 +            if (vp->lib != NULL || fn == NULL || !strcmp(fn, vp->name))
372 +                vp->lib = liblookup(vp->name);
373 + }
374 + #endif
375 +
376 +
377   varfree(ln)                             /* release link to variable */
378 < register VARDEF  *ln;
378 > register VARDEF  *ln;
379   {
380      register VARDEF  *vp;
381 <    int  hv;
381 >    int  hv;
382  
383      if (--ln->nlinks > 0)
384 <        return;                         /* still active */
384 >        return;                         /* still active */
385  
386      hv = hash(ln->name);
387      vp = hashtbl[hv];
388      if (vp == ln)
389 <        hashtbl[hv] = vp->next;
389 >        hashtbl[hv] = vp->next;
390      else {
391 <        while (vp->next != ln)          /* must be in list */
392 <                vp = vp->next;
393 <        vp->next = ln->next;
391 >        while (vp->next != ln)          /* must be in list */
392 >                vp = vp->next;
393 >        vp->next = ln->next;
394      }
395      freestr(ln->name);
396      efree((char *)ln);
# Line 266 | Line 402 | dfirst()                       /* return pointer to first definition */
402   {
403      htndx = 0;
404      htpos = NULL;
405 < #ifdef  OUTCHAN
405 > #ifdef  OUTCHAN
406      ochpos = outchan;
407   #endif
408      return(dnext());
# Line 277 | Line 413 | EPNODE *
413   dnext()                         /* return pointer to next definition */
414   {
415      register EPNODE  *ep;
416 +    register char  *nm;
417  
418      while (htndx < NHASH) {
419 <        if (htpos == NULL)
420 <                htpos = hashtbl[htndx++];
421 <        while (htpos != NULL) {
422 <            ep = htpos->def;
423 <            htpos = htpos->next;
424 <            if (ep != NULL)
425 <                return(ep);
426 <        }
419 >        if (htpos == NULL)
420 >                htpos = hashtbl[htndx++];
421 >        while (htpos != NULL) {
422 >            ep = htpos->def;
423 >            nm = htpos->name;
424 >            htpos = htpos->next;
425 >            if (ep != NULL && incontext(nm))
426 >                return(ep);
427 >        }
428      }
429 < #ifdef  OUTCHAN
429 > #ifdef  OUTCHAN
430      if ((ep = ochpos) != NULL)
431 <        ochpos = ep->sibling;
431 >        ochpos = ep->sibling;
432      return(ep);
433   #else
434      return(NULL);
# Line 306 | Line 444 | char  *name;
444      register EPNODE  *dp;
445      
446      if ((vp = varlookup(name)) == NULL || vp->def == NULL)
447 <        return(NULL);
447 >        return(NULL);
448      dp = vp->def;
449      vp->def = dp->sibling;
450      varfree(vp);
# Line 314 | Line 452 | char  *name;
452   }
453  
454  
455 < dpush(ep)                       /* push on a definition */
456 < register EPNODE  *ep;
455 > dpush(nm, ep)                   /* push on a definition */
456 > char  *nm;
457 > register EPNODE  *ep;
458   {
459      register VARDEF  *vp;
460  
461 <    vp = varinsert(dname(ep));
461 >    vp = varinsert(nm);
462      ep->sibling = vp->def;
463      vp->def = ep;
464   }
465  
466  
467 < #ifdef  OUTCHAN
467 > #ifdef  OUTCHAN
468   addchan(sp)                     /* add an output channel assignment */
469 < EPNODE  *sp;
469 > EPNODE  *sp;
470   {
471 <    int  ch = sp->v.kid->v.chan;
471 >    int  ch = sp->v.kid->v.chan;
472      register EPNODE  *ep, *epl;
473  
474      for (epl = NULL, ep = outchan; ep != NULL; epl = ep, ep = ep->sibling)
# Line 356 | Line 495 | EPNODE  *sp;
495   #endif
496  
497  
498 < loaddefn()                      /* load next definition */
498 > getstatement()                  /* get next statement */
499   {
500      register EPNODE  *ep;
501 +    char  *qname;
502 +    register VARDEF  *vdef;
503  
504      if (nextc == ';') {         /* empty statement */
505          scan();
506          return;
507      }
508 < #ifdef  OUTCHAN
508 > #ifdef  OUTCHAN
509      if (nextc == '$') {         /* channel assignment */
510          ep = getchan();
511          addchan(ep);
# Line 372 | Line 513 | loaddefn()                     /* load next definition */
513   #endif
514      {                           /* ordinary definition */
515          ep = getdefn();
516 < #ifdef  REDEFW
517 <        if (dlookup(dname(ep)) != NULL) {
518 <                dclear(dname(ep));
519 <                wputs(dname(ep));
520 <                wputs(": redefined\n");
521 <        }
522 < #else
523 <        dclear(dname(ep));
516 >        qname = qualname(dname(ep), 0);
517 > #ifdef  REDEFW
518 >        if ((vdef = varlookup(qname)) != NULL)
519 >            if (vdef->def != NULL) {
520 >                wputs(qname);
521 >                if (vdef->def->type == ':')
522 >                    wputs(": redefined constant expression\n");
523 >                else
524 >                    wputs(": redefined\n");
525 >            }
526 > #ifdef  FUNCTION
527 >            else if (ep->v.kid->type == FUNC && vdef->lib != NULL) {
528 >                wputs(qname);
529 >                wputs(": definition hides library function\n");
530 >            }
531   #endif
532 <        dpush(ep);
532 > #endif
533 >        if (ep->type == ':')
534 >            dremove(qname);
535 >        else
536 >            dclear(qname);
537 >        dpush(qname, ep);
538      }
539      if (nextc != EOF) {
540          if (nextc != ';')
# Line 393 | Line 546 | loaddefn()                     /* load next definition */
546  
547   EPNODE *
548   getdefn()                       /* A -> SYM = E1 */
549 <                                /*      FUNC(SYM,..) = E1 */
549 >                                /*      SYM : E1 */
550 >                                /*      FUNC(SYM,..) = E1 */
551 >                                /*      FUNC(SYM,..) : E1 */
552   {
553      register EPNODE  *ep1, *ep2;
554  
555 <    if (!isalpha(nextc))
555 >    if (!isalpha(nextc) && nextc != CNTXMARK)
556          syntax("illegal variable name");
557  
558      ep1 = newnode();
559      ep1->type = SYM;
560      ep1->v.name = savestr(getname());
561  
562 < #ifdef  FUNCTION
562 > #ifdef  FUNCTION
563      if (nextc == '(') {
564          ep2 = newnode();
565          ep2->type = FUNC;
# Line 427 | Line 582 | getdefn()                      /* A -> SYM = E1 */
582          curfunc = NULL;
583   #endif
584  
585 <    if (nextc != '=')
586 <        syntax("'=' expected");
432 <    scan();
585 >    if (nextc != '=' && nextc != ':')
586 >        syntax("'=' or ':' expected");
587  
588      ep2 = newnode();
589 <    ep2->type = '=';
589 >    ep2->type = nextc;
590 >    scan();
591      addekid(ep2, ep1);
592      addekid(ep2, getE1());
593  
594 < #ifdef  FUNCTION
595 <    if (ep1->type == SYM)
594 >    if (
595 > #ifdef  FUNCTION
596 >            ep1->type == SYM &&
597   #endif
598 <    {
598 >            ep1->sibling->type != NUM) {
599          ep1 = newnode();
600          ep1->type = TICK;
601          ep1->v.tick = -1;
# Line 453 | Line 609 | getdefn()                      /* A -> SYM = E1 */
609   }
610  
611  
612 < #ifdef  OUTCHAN
612 > #ifdef  OUTCHAN
613   EPNODE *
614   getchan()                       /* A -> $N = E1 */
615   {
# Line 490 | Line 646 | getchan()                      /* A -> $N = E1 */
646   static double
647   dvalue(name, d)                 /* evaluate a variable */
648   char  *name;
649 < EPNODE  *d;
649 > EPNODE  *d;
650   {
651      register EPNODE  *ep1, *ep2;
652      
# Line 500 | Line 656 | EPNODE  *d;
656          quit(1);
657      }
658      ep1 = d->v.kid->sibling;                    /* get expression */
659 +    if (ep1->type == NUM)
660 +        return(ep1->v.num);                     /* return if number */
661      ep2 = ep1->sibling;                         /* check time */
662      if (ep2->v.tick < 0 || ep2->v.tick < eclock) {
663 <        ep2->v.tick = eclock;
663 >        ep2->v.tick = d->type == ':' ? 1L<<30 : eclock;
664          ep2 = ep2->sibling;
665 <        ep2->v.num = evalue(ep1);               /* compute new value */
665 >        ep2->v.num = evalue(ep1);               /* needs new value */
666      } else
667 <        ep2 = ep2->sibling;                     /* reuse old value */
667 >        ep2 = ep2->sibling;                     /* else reuse old value */
668  
669      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);
670   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines