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.5 by greg, Thu Jul 19 11:15:31 1990 UTC vs.
Revision 2.10 by greg, Wed Jan 8 17:10:24 1997 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 */
45 > unsigned long  eclock = 0;              /* 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 = NULL;
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 70 | Line 78 | char  *fname;
78      }
79      initfile(fp, fname, 0);
80      while (nextc != EOF)
81 <        loaddefn();
81 >        getstatement();
82      if (fname != NULL)
83          fclose(fp);
84   }
# Line 83 | Line 91 | int  ln;
91   {
92      initstr(str, fn, ln);
93      while (nextc != EOF)
94 <        loaddefn();
94 >        getstatement();
95   }
96  
97  
# Line 97 | 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 105 | 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 +            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 <    dclear(vname);
146 <    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 153 | 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 +    while (*ctx == CNTXMARK)
193 +        ctx++;                          /* skip past marks */
194 +    if (!*ctx) {
195 +        context[0] = '\0';              /* empty means clear context */
196 +        return(context);
197 +    }
198 +    cpp = context;                      /* start context with mark */
199 +    *cpp++ = CNTXMARK;
200 +    do {                                /* carefully copy new context */
201 +        if (cpp >= context+MAXWORD)
202 +            break;                      /* just copy what we can */
203 +        if (isid(*ctx))
204 +            *cpp++ = *ctx++;
205 +        else {
206 +            *cpp++ = '_'; ctx++;
207 +        }
208 +    } while (*ctx);
209 +    while (cpp[-1] == CNTXMARK)         /* cannot end in context mark */
210 +        cpp--;
211 +    *cpp = '\0';
212 +    return(context);
213 + }
214 +
215 +
216 + char *
217 + pushcontext(ctx)                /* push on another context */
218 + char  *ctx;
219 + {
220 +    extern char  *strncpy(), *strcpy();
221 +    char  oldcontext[MAXWORD+1];
222 +    register int  n;
223 +
224 +    strcpy(oldcontext, context);        /* save old context */
225 +    setcontext(ctx);                    /* set new context */
226 +    n = strlen(context);                /* tack on old */
227 +    if (n+strlen(oldcontext) > MAXWORD) {
228 +        strncpy(context+n, oldcontext, MAXWORD-n);
229 +        context[MAXWORD] = '\0';
230 +    } else
231 +        strcpy(context+n, oldcontext);
232 +    return(context);
233 + }
234 +
235 +
236 + char *
237 + popcontext()                    /* pop off top context */
238 + {
239 +    register char  *cp1, *cp2;
240 +
241 +    if (!context[0])                    /* nothing left to pop */
242 +        return(context);
243 +    cp2 = context;                      /* find mark */
244 +    while (*++cp2 && *cp2 != CNTXMARK)
245 +        ;
246 +    cp1 = context;                      /* copy tail to front */
247 +    while (*cp1++ = *cp2++)
248 +        ;
249 +    return(context);
250 + }
251 +
252 +
253 + char *
254 + qualname(nam, lvl)              /* get qualified name */
255 + register char  *nam;
256 + int  lvl;
257 + {
258 +    static char  nambuf[MAXWORD+1];
259 +    register char  *cp = nambuf, *cpp;
260 +                                /* check for explicit local */
261 +    if (*nam == CNTXMARK)
262 +        if (lvl > 0)            /* only action is to refuse search */
263 +            return(NULL);
264 +        else
265 +            nam++;
266 +    else if (nam == nambuf)     /* check for repeat call */
267 +        return(lvl > 0 ? NULL : nam);
268 +                                /* copy name to static buffer */
269 +    while (*nam) {
270 +        if (cp >= nambuf+MAXWORD)
271 +                goto toolong;
272 +        *cp++ = *nam++;
273 +    }
274 +                                /* check for explicit global */
275 +    if (cp > nambuf && cp[-1] == CNTXMARK) {
276 +        if (lvl > 0)
277 +            return(NULL);
278 +        *--cp = '\0';
279 +        return(nambuf);         /* already qualified */
280 +    }
281 +    cpp = context;              /* else skip the requested levels */
282 +    while (lvl-- > 0) {
283 +        if (!*cpp)
284 +            return(NULL);       /* return NULL if past global level */
285 +        while (*++cpp && *cpp != CNTXMARK)
286 +            ;
287 +    }
288 +    while (*cpp) {              /* copy context to static buffer */
289 +        if (cp >= nambuf+MAXWORD)
290 +            goto toolong;
291 +        *cp++ = *cpp++;
292 +    }
293 + toolong:
294 +    *cp = '\0';
295 +    return(nambuf);             /* return qualified name */
296 + }
297 +
298 +
299 + incontext(qn)                   /* is qualified name in current context? */
300 + register char  *qn;
301 + {
302 +    if (!context[0])                    /* global context accepts all */
303 +        return(1);
304 +    while (*qn && *qn != CNTXMARK)      /* find context mark */
305 +        qn++;
306 +    return(!strcmp(qn, context));
307 + }
308 +
309 +
310 + #ifdef  OUTCHAN
311 + chanout(cs)                     /* set output channels */
312 + int  (*cs)();
313 + {
314      register EPNODE  *ep;
315  
316      for (ep = outchan; ep != NULL; ep = ep->sibling)
317 <        chanset(ep->v.kid->v.chan, evalue(ep->v.kid->sibling));
317 >        (*cs)(ep->v.kid->v.chan, evalue(ep->v.kid->sibling));
318  
319   }
320   #endif
321  
322  
323 < dclearall()                     /* clear all definitions */
323 > dcleanup(lvl)           /* clear definitions (0->vars,1->output,2->consts) */
324 > int  lvl;
325   {
326      register int  i;
327      register VARDEF  *vp;
328      register EPNODE  *ep;
329 <
329 >                                /* if context is global, clear all */
330      for (i = 0; i < NHASH; i++)
331          for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
332 <            dclear(vp->name);
333 < #ifdef  OUTCHAN
334 <    for (ep = outchan; ep != NULL; ep = ep->sibling)
335 <        epfree(ep);
336 <    outchan = NULL;
332 >            if (incontext(vp->name))
333 >                if (lvl >= 2)
334 >                    dremove(vp->name);
335 >                else
336 >                    dclear(vp->name);
337 > #ifdef  OUTCHAN
338 >    if (lvl >= 1) {
339 >        for (ep = outchan; ep != NULL; ep = ep->sibling)
340 >            epfree(ep);
341 >        outchan = NULL;
342 >    }
343   #endif
344   }
345  
# Line 189 | Line 351 | char  *name;
351      register VARDEF  *vp;
352      
353      if ((vp = varlookup(name)) == NULL)
354 <        return(NULL);
354 >        return(NULL);
355      return(vp->def);
356   }
357  
# Line 198 | Line 360 | VARDEF *
360   varlookup(name)                 /* look up a variable */
361   char  *name;
362   {
363 +    int  lvl = 0;
364 +    register char  *qname;
365      register VARDEF  *vp;
366 <    
367 <    for (vp = hashtbl[hash(name)]; vp != NULL; vp = vp->next)
368 <        if (!strcmp(vp->name, name))
369 <            return(vp);
366 >                                /* find most qualified match */
367 >    while ((qname = qualname(name, lvl++)) != NULL)
368 >        for (vp = hashtbl[hash(qname)]; vp != NULL; vp = vp->next)
369 >            if (!strcmp(vp->name, qname))
370 >                return(vp);
371      return(NULL);
372   }
373  
# Line 212 | Line 377 | varinsert(name)                        /* get a link to a variable */
377   char  *name;
378   {
379      register VARDEF  *vp;
380 <    int  hv;
380 >    int  hv;
381      
382 <    hv = hash(name);
383 <    for (vp = hashtbl[hv]; vp != NULL; vp = vp->next)
384 <        if (!strcmp(vp->name, name)) {
385 <            vp->nlinks++;
221 <            return(vp);
222 <        }
382 >    if ((vp = varlookup(name)) != NULL) {
383 >        vp->nlinks++;
384 >        return(vp);
385 >    }
386      vp = (VARDEF *)emalloc(sizeof(VARDEF));
387 + #ifdef  FUNCTION
388 +    vp->lib = liblookup(name);
389 + #else
390 +    vp->lib = NULL;
391 + #endif
392 +    if (vp->lib == NULL)                /* if name not in library */
393 +        name = qualname(name, 0);       /* use fully qualified version */
394 +    hv = hash(name);
395      vp->name = savestr(name);
396      vp->nlinks = 1;
397      vp->def = NULL;
227    vp->lib = NULL;
398      vp->next = hashtbl[hv];
399      hashtbl[hv] = vp;
400      return(vp);
401   }
402  
403  
404 + #ifdef  FUNCTION
405 + libupdate(fn)                   /* update library links */
406 + char  *fn;
407 + {
408 +    register int  i;
409 +    register VARDEF  *vp;
410 +                                        /* if fn is NULL then relink all */
411 +    for (i = 0; i < NHASH; i++)
412 +        for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
413 +            if (vp->lib != NULL || fn == NULL || !strcmp(fn, vp->name))
414 +                vp->lib = liblookup(vp->name);
415 + }
416 + #endif
417 +
418 +
419   varfree(ln)                             /* release link to variable */
420 < register VARDEF  *ln;
420 > register VARDEF  *ln;
421   {
422      register VARDEF  *vp;
423 <    int  hv;
423 >    int  hv;
424  
425      if (--ln->nlinks > 0)
426 <        return;                         /* still active */
426 >        return;                         /* still active */
427  
428      hv = hash(ln->name);
429      vp = hashtbl[hv];
430      if (vp == ln)
431 <        hashtbl[hv] = vp->next;
431 >        hashtbl[hv] = vp->next;
432      else {
433 <        while (vp->next != ln)          /* must be in list */
434 <                vp = vp->next;
435 <        vp->next = ln->next;
433 >        while (vp->next != ln)          /* must be in list */
434 >                vp = vp->next;
435 >        vp->next = ln->next;
436      }
437      freestr(ln->name);
438      efree((char *)ln);
# Line 259 | Line 444 | dfirst()                       /* return pointer to first definition */
444   {
445      htndx = 0;
446      htpos = NULL;
447 < #ifdef  OUTCHAN
447 > #ifdef  OUTCHAN
448      ochpos = outchan;
449   #endif
450      return(dnext());
# Line 270 | Line 455 | EPNODE *
455   dnext()                         /* return pointer to next definition */
456   {
457      register EPNODE  *ep;
458 +    register char  *nm;
459  
460      while (htndx < NHASH) {
461 <        if (htpos == NULL)
462 <                htpos = hashtbl[htndx++];
463 <        while (htpos != NULL) {
464 <            ep = htpos->def;
465 <            htpos = htpos->next;
466 <            if (ep != NULL)
467 <                return(ep);
468 <        }
461 >        if (htpos == NULL)
462 >                htpos = hashtbl[htndx++];
463 >        while (htpos != NULL) {
464 >            ep = htpos->def;
465 >            nm = htpos->name;
466 >            htpos = htpos->next;
467 >            if (ep != NULL && incontext(nm))
468 >                return(ep);
469 >        }
470      }
471 < #ifdef  OUTCHAN
471 > #ifdef  OUTCHAN
472      if ((ep = ochpos) != NULL)
473 <        ochpos = ep->sibling;
473 >        ochpos = ep->sibling;
474      return(ep);
475   #else
476      return(NULL);
# Line 299 | Line 486 | char  *name;
486      register EPNODE  *dp;
487      
488      if ((vp = varlookup(name)) == NULL || vp->def == NULL)
489 <        return(NULL);
489 >        return(NULL);
490      dp = vp->def;
491      vp->def = dp->sibling;
492      varfree(vp);
# Line 307 | Line 494 | char  *name;
494   }
495  
496  
497 < dpush(ep)                       /* push on a definition */
498 < register EPNODE  *ep;
497 > dpush(nm, ep)                   /* push on a definition */
498 > char  *nm;
499 > register EPNODE  *ep;
500   {
501      register VARDEF  *vp;
502  
503 <    vp = varinsert(dname(ep));
503 >    vp = varinsert(nm);
504      ep->sibling = vp->def;
505      vp->def = ep;
506   }
507  
508  
509 < #ifdef  OUTCHAN
509 > #ifdef  OUTCHAN
510   addchan(sp)                     /* add an output channel assignment */
511 < EPNODE  *sp;
511 > EPNODE  *sp;
512   {
513 <    int  ch = sp->v.kid->v.chan;
513 >    int  ch = sp->v.kid->v.chan;
514      register EPNODE  *ep, *epl;
515  
516      for (epl = NULL, ep = outchan; ep != NULL; epl = ep, ep = ep->sibling)
# Line 349 | Line 537 | EPNODE  *sp;
537   #endif
538  
539  
540 < loaddefn()                      /* load next definition */
540 > getstatement()                  /* get next statement */
541   {
542      register EPNODE  *ep;
543 +    char  *qname;
544 +    register VARDEF  *vdef;
545  
546      if (nextc == ';') {         /* empty statement */
547          scan();
548          return;
549      }
550 < #ifdef  OUTCHAN
550 > #ifdef  OUTCHAN
551      if (nextc == '$') {         /* channel assignment */
552          ep = getchan();
553          addchan(ep);
# Line 365 | Line 555 | loaddefn()                     /* load next definition */
555   #endif
556      {                           /* ordinary definition */
557          ep = getdefn();
558 < #ifdef  REDEFW
559 <        if (dlookup(dname(ep)) != NULL) {
560 <                dclear(dname(ep));
561 <                wputs(dname(ep));
562 <                wputs(": redefined\n");
563 <        }
564 < #else
565 <        dclear(dname(ep));
558 >        qname = qualname(dname(ep), 0);
559 > #ifdef  REDEFW
560 >        if ((vdef = varlookup(qname)) != NULL)
561 >            if (vdef->def != NULL && epcmp(ep, vdef->def)) {
562 >                wputs(qname);
563 >                if (vdef->def->type == ':')
564 >                    wputs(": redefined constant expression\n");
565 >                else
566 >                    wputs(": redefined\n");
567 >            }
568 > #ifdef  FUNCTION
569 >            else if (ep->v.kid->type == FUNC && vdef->lib != NULL) {
570 >                wputs(qname);
571 >                wputs(": definition hides library function\n");
572 >            }
573   #endif
574 <        dpush(ep);
574 > #endif
575 >        if (ep->type == ':')
576 >            dremove(qname);
577 >        else
578 >            dclear(qname);
579 >        dpush(qname, ep);
580      }
581      if (nextc != EOF) {
582          if (nextc != ';')
# Line 386 | Line 588 | loaddefn()                     /* load next definition */
588  
589   EPNODE *
590   getdefn()                       /* A -> SYM = E1 */
591 <                                /*      FUNC(SYM,..) = E1 */
591 >                                /*      SYM : E1 */
592 >                                /*      FUNC(SYM,..) = E1 */
593 >                                /*      FUNC(SYM,..) : E1 */
594   {
595      register EPNODE  *ep1, *ep2;
596  
597 <    if (!isalpha(nextc))
597 >    if (!isalpha(nextc) && nextc != CNTXMARK)
598          syntax("illegal variable name");
599  
600      ep1 = newnode();
601      ep1->type = SYM;
602      ep1->v.name = savestr(getname());
603  
604 < #ifdef  FUNCTION
604 > #ifdef  FUNCTION
605      if (nextc == '(') {
606          ep2 = newnode();
607          ep2->type = FUNC;
# Line 416 | Line 620 | getdefn()                      /* A -> SYM = E1 */
620              syntax("')' expected");
621          scan();
622          curfunc = ep1;
623 <    } else
420 <        curfunc = NULL;
623 >    }
624   #endif
625  
626 <    if (nextc != '=')
627 <        syntax("'=' expected");
425 <    scan();
626 >    if (nextc != '=' && nextc != ':')
627 >        syntax("'=' or ':' expected");
628  
629      ep2 = newnode();
630 <    ep2->type = '=';
630 >    ep2->type = nextc;
631 >    scan();
632      addekid(ep2, ep1);
633      addekid(ep2, getE1());
634  
635 < #ifdef  FUNCTION
636 <    if (ep1->type == SYM)
635 >    if (
636 > #ifdef  FUNCTION
637 >            ep1->type == SYM &&
638   #endif
639 <    {
639 >            ep1->sibling->type != NUM) {
640          ep1 = newnode();
641          ep1->type = TICK;
642 <        ep1->v.tick = -1;
642 >        ep1->v.tick = 0;
643          addekid(ep2, ep1);
644          ep1 = newnode();
645          ep1->type = NUM;
646          addekid(ep2, ep1);
647      }
648  
649 + #ifdef  FUNCTION
650 +    curfunc = NULL;
651 + #endif
652 +
653      return(ep2);
654   }
655  
656  
657 < #ifdef  OUTCHAN
657 > #ifdef  OUTCHAN
658   EPNODE *
659   getchan()                       /* A -> $N = E1 */
660   {
# Line 483 | Line 691 | getchan()                      /* A -> $N = E1 */
691   static double
692   dvalue(name, d)                 /* evaluate a variable */
693   char  *name;
694 < EPNODE  *d;
694 > EPNODE  *d;
695   {
696      register EPNODE  *ep1, *ep2;
697      
# Line 496 | Line 704 | EPNODE  *d;
704      if (ep1->type == NUM)
705          return(ep1->v.num);                     /* return if number */
706      ep2 = ep1->sibling;                         /* check time */
707 <    if (ep2->v.tick < 0 || ep2->v.tick < eclock) {
708 <        ep2->v.tick = eclock;
707 >    if (ep2->v.tick == 0 || ep2->v.tick < eclock) {
708 >        ep2->v.tick = d->type == ':' ? ~0L : eclock;
709          ep2 = ep2->sibling;
710          ep2->v.num = evalue(ep1);               /* needs new value */
711      } else
712          ep2 = ep2->sibling;                     /* else reuse old value */
713  
714      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);
715   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines