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.14 by greg, Thu Aug 8 12:12:16 1991 UTC vs.
Revision 2.11 by greg, Wed Feb 12 17:38:03 1997 UTC

# Line 1 | Line 1
1 < /* Copyright (c) 1991 Regents of the University of California */
1 > /* Copyright (c) 1997 Regents of the University of California */
2  
3   #ifndef lint
4   static char SCCSid[] = "$SunId$ LBL";
# Line 30 | 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(), *strcpy();
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];          /* current context path */
47 > #define  MAXCNTX        1023            /* maximum context length */
48  
49 + static char  context[MAXCNTX+1];        /* current context path */
50 +
51   static VARDEF  *hashtbl[NHASH];         /* definition list */
52   static int  htndx;                      /* index for */        
53   static VARDEF  *htpos;                  /* ...dfirst() and */
54 < #ifdef  OUTCHAN
54 > #ifdef  OUTCHAN
55   static EPNODE  *ochpos;                 /* ...dnext */
56   static EPNODE  *outchan;
57   #endif
58  
59 < #ifdef  FUNCTION
60 < EPNODE  *curfunc;
61 < #define  dname(ep)      ((ep)->v.kid->type == SYM ? \
59 > #ifdef  FUNCTION
60 > EPNODE  *curfunc = NULL;
61 > #define  dname(ep)      ((ep)->v.kid->type == SYM ? \
62                          (ep)->v.kid->v.name : \
63                          (ep)->v.kid->v.kid->v.name)
64   #else
65 < #define  dname(ep)      ((ep)->v.kid->v.name)
65 > #define  dname(ep)      ((ep)->v.kid->v.name)
66   #endif
67  
68  
# Line 103 | Line 107 | char  *vname;
107  
108   double
109   evariable(ep)                   /* evaluate a variable */
110 < EPNODE  *ep;
110 > EPNODE  *ep;
111   {
112      register VARDEF  *dp = ep->v.ln;
113  
# Line 114 | Line 118 | EPNODE  *ep;
118   varset(vname, assign, val)      /* set a variable's value */
119   char  *vname;
120   int  assign;
121 < double  val;
121 > double  val;
122   {
123      char  *qname;
124      register EPNODE  *ep1, *ep2;
# Line 187 | Line 191 | register char  *ctx;
191  
192      if (ctx == NULL)
193          return(context);                /* just asking */
194 +    while (*ctx == CNTXMARK)
195 +        ctx++;                          /* skip past marks */
196      if (!*ctx) {
197 <        context[0] = '\0';              /* clear context */
197 >        context[0] = '\0';              /* empty means clear context */
198          return(context);
199      }
200 <    cpp = context;                      /* else copy it (carefully!) */
201 <    if (*ctx != CNTXMARK)
202 <        *cpp++ = CNTXMARK;              /* make sure there's a mark */
203 <    do {
204 <        if (cpp >= context+MAXWORD-1) {
199 <            *cpp = '\0';
200 <            wputs(context);
201 <            wputs(": context path too long\n");
202 <            return(NULL);
203 <        }
200 >    cpp = context;                      /* start context with mark */
201 >    *cpp++ = CNTXMARK;
202 >    do {                                /* carefully copy new context */
203 >        if (cpp >= context+MAXCNTX)
204 >            break;                      /* just copy what we can */
205          if (isid(*ctx))
206              *cpp++ = *ctx++;
207          else {
208              *cpp++ = '_'; ctx++;
209          }
210      } while (*ctx);
211 +    while (cpp[-1] == CNTXMARK)         /* cannot end in context mark */
212 +        cpp--;
213      *cpp = '\0';
214      return(context);
215   }
216  
217  
218   char *
219 + pushcontext(ctx)                /* push on another context */
220 + char  *ctx;
221 + {
222 +    extern char  *strncpy(), *strcpy();
223 +    char  oldcontext[MAXCNTX+1];
224 +    register int  n;
225 +
226 +    strcpy(oldcontext, context);        /* save old context */
227 +    setcontext(ctx);                    /* set new context */
228 +    n = strlen(context);                /* tack on old */
229 +    if (n+strlen(oldcontext) > MAXCNTX) {
230 +        strncpy(context+n, oldcontext, MAXCNTX-n);
231 +        context[MAXCNTX] = '\0';
232 +    } else
233 +        strcpy(context+n, oldcontext);
234 +    return(context);
235 + }
236 +
237 +
238 + char *
239 + popcontext()                    /* pop off top context */
240 + {
241 +    register char  *cp1, *cp2;
242 +
243 +    if (!context[0])                    /* nothing left to pop */
244 +        return(context);
245 +    cp2 = context;                      /* find mark */
246 +    while (*++cp2 && *cp2 != CNTXMARK)
247 +        ;
248 +    cp1 = context;                      /* copy tail to front */
249 +    while (*cp1++ = *cp2++)
250 +        ;
251 +    return(context);
252 + }
253 +
254 +
255 + char *
256   qualname(nam, lvl)              /* get qualified name */
257   register char  *nam;
258   int  lvl;
259   {
260 <    static char  nambuf[MAXWORD];
261 <    register char  *cp = nambuf, *cpp = context;
262 <                                /* check for repeat call */
263 <    if (nam == nambuf)
264 <        return(lvl > 0 ? NULL : nambuf);
260 >    static char  nambuf[MAXWORD+1];
261 >    register char  *cp = nambuf, *cpp;
262 >                                /* check for explicit local */
263 >    if (*nam == CNTXMARK)
264 >        if (lvl > 0)            /* only action is to refuse search */
265 >            return(NULL);
266 >        else
267 >            nam++;
268 >    else if (nam == nambuf)     /* check for repeat call */
269 >        return(lvl > 0 ? NULL : nam);
270                                  /* copy name to static buffer */
271      while (*nam) {
272 <        if (cp >= nambuf+MAXWORD-1)
272 >        if (cp >= nambuf+MAXWORD)
273                  goto toolong;
274 <        if ((*cp++ = *nam++) == CNTXMARK)
230 <            cpp = NULL;         /* flag a qualified name */
274 >        *cp++ = *nam++;
275      }
276 <    if (cpp == NULL) {
276 >                                /* check for explicit global */
277 >    if (cp > nambuf && cp[-1] == CNTXMARK) {
278          if (lvl > 0)
279 <            return(NULL);               /* no higher level */
280 <        if (cp[-1] == CNTXMARK) {
281 <            cp--; cpp = context;        /* current context explicitly */
282 <        } else
283 <            cpp = "";                   /* else fully qualified */
284 <    } else                      /* else skip the requested levels */
285 <        while (lvl-- > 0) {
286 <            if (!*cpp)
287 <                return(NULL);   /* return NULL if past global level */
288 <            while (*++cpp && *cpp != CNTXMARK)
289 <                ;
245 <        }
279 >            return(NULL);
280 >        *--cp = '\0';
281 >        return(nambuf);         /* already qualified */
282 >    }
283 >    cpp = context;              /* else skip the requested levels */
284 >    while (lvl-- > 0) {
285 >        if (!*cpp)
286 >            return(NULL);       /* return NULL if past global level */
287 >        while (*++cpp && *cpp != CNTXMARK)
288 >            ;
289 >    }
290      while (*cpp) {              /* copy context to static buffer */
291 <        if (cp >= nambuf+MAXWORD-1)
291 >        if (cp >= nambuf+MAXWORD)
292              goto toolong;
293          *cp++ = *cpp++;
294      }
251    *cp = '\0';
252    return(nambuf);             /* return qualified name */
295   toolong:
296      *cp = '\0';
297 <    eputs(nambuf);
256 <    eputs(": name too long\n");
257 <    quit(1);
297 >    return(nambuf);             /* return qualified name */
298   }
299  
300  
301   incontext(qn)                   /* is qualified name in current context? */
302   register char  *qn;
303   {
304 +    if (!context[0])                    /* global context accepts all */
305 +        return(1);
306      while (*qn && *qn != CNTXMARK)      /* find context mark */
307 <        ;
307 >        qn++;
308      return(!strcmp(qn, context));
309   }
310  
311  
312 < #ifdef  OUTCHAN
312 > #ifdef  OUTCHAN
313   chanout(cs)                     /* set output channels */
314   int  (*cs)();
315   {
# Line 289 | Line 331 | int  lvl;
331                                  /* if context is global, clear all */
332      for (i = 0; i < NHASH; i++)
333          for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
334 <            if (!context[0] || incontext(vp->name))
334 >            if (incontext(vp->name))
335                  if (lvl >= 2)
336                      dremove(vp->name);
337                  else
338                      dclear(vp->name);
339 < #ifdef  OUTCHAN
339 > #ifdef  OUTCHAN
340      if (lvl >= 1) {
341          for (ep = outchan; ep != NULL; ep = ep->sibling)
342              epfree(ep);
# Line 311 | Line 353 | char  *name;
353      register VARDEF  *vp;
354      
355      if ((vp = varlookup(name)) == NULL)
356 <        return(NULL);
356 >        return(NULL);
357      return(vp->def);
358   }
359  
# Line 320 | Line 362 | VARDEF *
362   varlookup(name)                 /* look up a variable */
363   char  *name;
364   {
365 <    int  lvl = 0;
365 >    int  lvl = 0;
366      register char  *qname;
367      register VARDEF  *vp;
368 <                                /* find most qualified match */
368 >                                /* find most qualified match */
369      while ((qname = qualname(name, lvl++)) != NULL)
370          for (vp = hashtbl[hash(qname)]; vp != NULL; vp = vp->next)
371              if (!strcmp(vp->name, qname))
# Line 337 | Line 379 | varinsert(name)                        /* get a link to a variable */
379   char  *name;
380   {
381      register VARDEF  *vp;
382 <    int  hv;
382 >    int  hv;
383      
384      if ((vp = varlookup(name)) != NULL) {
385          vp->nlinks++;
386          return(vp);
387      }
346    name = qualname(name, 0);           /* use fully qualified name */
347    hv = hash(name);
388      vp = (VARDEF *)emalloc(sizeof(VARDEF));
389 + #ifdef  FUNCTION
390 +    vp->lib = liblookup(name);
391 + #else
392 +    vp->lib = NULL;
393 + #endif
394 +    if (vp->lib == NULL)                /* if name not in library */
395 +        name = qualname(name, 0);       /* use fully qualified version */
396 +    hv = hash(name);
397      vp->name = savestr(name);
398      vp->nlinks = 1;
399      vp->def = NULL;
352    vp->lib = NULL;
400      vp->next = hashtbl[hv];
401      hashtbl[hv] = vp;
402      return(vp);
403   }
404  
405  
406 + #ifdef  FUNCTION
407 + libupdate(fn)                   /* update library links */
408 + char  *fn;
409 + {
410 +    register int  i;
411 +    register VARDEF  *vp;
412 +                                        /* if fn is NULL then relink all */
413 +    for (i = 0; i < NHASH; i++)
414 +        for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
415 +            if (vp->lib != NULL || fn == NULL || !strcmp(fn, vp->name))
416 +                vp->lib = liblookup(vp->name);
417 + }
418 + #endif
419 +
420 +
421   varfree(ln)                             /* release link to variable */
422 < register VARDEF  *ln;
422 > register VARDEF  *ln;
423   {
424      register VARDEF  *vp;
425 <    int  hv;
425 >    int  hv;
426  
427      if (--ln->nlinks > 0)
428 <        return;                         /* still active */
428 >        return;                         /* still active */
429  
430      hv = hash(ln->name);
431      vp = hashtbl[hv];
432      if (vp == ln)
433 <        hashtbl[hv] = vp->next;
433 >        hashtbl[hv] = vp->next;
434      else {
435 <        while (vp->next != ln)          /* must be in list */
436 <                vp = vp->next;
437 <        vp->next = ln->next;
435 >        while (vp->next != ln)          /* must be in list */
436 >                vp = vp->next;
437 >        vp->next = ln->next;
438      }
439      freestr(ln->name);
440      efree((char *)ln);
# Line 384 | Line 446 | dfirst()                       /* return pointer to first definition */
446   {
447      htndx = 0;
448      htpos = NULL;
449 < #ifdef  OUTCHAN
449 > #ifdef  OUTCHAN
450      ochpos = outchan;
451   #endif
452      return(dnext());
# Line 395 | Line 457 | EPNODE *
457   dnext()                         /* return pointer to next definition */
458   {
459      register EPNODE  *ep;
460 +    register char  *nm;
461  
462      while (htndx < NHASH) {
463 <        if (htpos == NULL)
464 <                htpos = hashtbl[htndx++];
465 <        while (htpos != NULL) {
466 <            ep = htpos->def;
467 <            htpos = htpos->next;
468 <            if (ep != NULL)
469 <                return(ep);
470 <        }
463 >        if (htpos == NULL)
464 >                htpos = hashtbl[htndx++];
465 >        while (htpos != NULL) {
466 >            ep = htpos->def;
467 >            nm = htpos->name;
468 >            htpos = htpos->next;
469 >            if (ep != NULL && incontext(nm))
470 >                return(ep);
471 >        }
472      }
473 < #ifdef  OUTCHAN
473 > #ifdef  OUTCHAN
474      if ((ep = ochpos) != NULL)
475 <        ochpos = ep->sibling;
475 >        ochpos = ep->sibling;
476      return(ep);
477   #else
478      return(NULL);
# Line 424 | Line 488 | char  *name;
488      register EPNODE  *dp;
489      
490      if ((vp = varlookup(name)) == NULL || vp->def == NULL)
491 <        return(NULL);
491 >        return(NULL);
492      dp = vp->def;
493      vp->def = dp->sibling;
494      varfree(vp);
# Line 434 | Line 498 | char  *name;
498  
499   dpush(nm, ep)                   /* push on a definition */
500   char  *nm;
501 < register EPNODE  *ep;
501 > register EPNODE  *ep;
502   {
503      register VARDEF  *vp;
504  
# Line 444 | Line 508 | register EPNODE  *ep;
508   }
509  
510  
511 < #ifdef  OUTCHAN
511 > #ifdef  OUTCHAN
512   addchan(sp)                     /* add an output channel assignment */
513 < EPNODE  *sp;
513 > EPNODE  *sp;
514   {
515 <    int  ch = sp->v.kid->v.chan;
515 >    int  ch = sp->v.kid->v.chan;
516      register EPNODE  *ep, *epl;
517  
518      for (epl = NULL, ep = outchan; ep != NULL; epl = ep, ep = ep->sibling)
# Line 479 | Line 543 | getstatement()                 /* get next statement */
543   {
544      register EPNODE  *ep;
545      char  *qname;
546 <    EPNODE  *lastdef;
546 >    register VARDEF  *vdef;
547  
548      if (nextc == ';') {         /* empty statement */
549          scan();
550          return;
551      }
552 < #ifdef  OUTCHAN
552 > #ifdef  OUTCHAN
553      if (nextc == '$') {         /* channel assignment */
554          ep = getchan();
555          addchan(ep);
# Line 494 | Line 558 | getstatement()                 /* get next statement */
558      {                           /* ordinary definition */
559          ep = getdefn();
560          qname = qualname(dname(ep), 0);
561 < #ifdef  REDEFW
562 <        if ((lastdef = dlookup(qname)) != NULL) {
563 <            wputs(qname);
564 <            if (lastdef->type == ':')
565 <                wputs(": redefined constant expression\n");
566 <            else
567 <                wputs(": redefined\n");
568 <        }
569 < #ifdef  FUNCTION
570 <        else if (ep->v.kid->type == FUNC && liblookup(qname) != NULL) {
571 <            wputs(qname);
572 <            wputs(": definition hides library function\n");
573 <        }
561 > #ifdef  REDEFW
562 >        if ((vdef = varlookup(qname)) != NULL)
563 >            if (vdef->def != NULL && epcmp(ep, vdef->def)) {
564 >                wputs(qname);
565 >                if (vdef->def->type == ':')
566 >                    wputs(": redefined constant expression\n");
567 >                else
568 >                    wputs(": redefined\n");
569 >            }
570 > #ifdef  FUNCTION
571 >            else if (ep->v.kid->type == FUNC && vdef->lib != NULL) {
572 >                wputs(qname);
573 >                wputs(": definition hides library function\n");
574 >            }
575   #endif
576   #endif
577          if (ep->type == ':')
# Line 526 | Line 591 | getstatement()                 /* get next statement */
591   EPNODE *
592   getdefn()                       /* A -> SYM = E1 */
593                                  /*      SYM : E1 */
594 <                                /*      FUNC(SYM,..) = E1 */
594 >                                /*      FUNC(SYM,..) = E1 */
595                                  /*      FUNC(SYM,..) : E1 */
596   {
597      register EPNODE  *ep1, *ep2;
598  
599 <    if (!isalpha(nextc))
599 >    if (!isalpha(nextc) && nextc != CNTXMARK)
600          syntax("illegal variable name");
601  
602      ep1 = newnode();
603      ep1->type = SYM;
604      ep1->v.name = savestr(getname());
605  
606 < #ifdef  FUNCTION
606 > #ifdef  FUNCTION
607      if (nextc == '(') {
608          ep2 = newnode();
609          ep2->type = FUNC;
# Line 557 | Line 622 | getdefn()                      /* A -> SYM = E1 */
622              syntax("')' expected");
623          scan();
624          curfunc = ep1;
625 <    } else
561 <        curfunc = NULL;
625 >    }
626   #endif
627  
628      if (nextc != '=' && nextc != ':')
# Line 571 | Line 635 | getdefn()                      /* A -> SYM = E1 */
635      addekid(ep2, getE1());
636  
637      if (
638 < #ifdef  FUNCTION
639 <            ep1->type == SYM &&
638 > #ifdef  FUNCTION
639 >            ep1->type == SYM &&
640   #endif
641              ep1->sibling->type != NUM) {
642          ep1 = newnode();
643          ep1->type = TICK;
644 <        ep1->v.tick = -1;
644 >        ep1->v.tick = 0;
645          addekid(ep2, ep1);
646          ep1 = newnode();
647          ep1->type = NUM;
648          addekid(ep2, ep1);
649      }
650  
651 + #ifdef  FUNCTION
652 +    curfunc = NULL;
653 + #endif
654 +
655      return(ep2);
656   }
657  
658  
659 < #ifdef  OUTCHAN
659 > #ifdef  OUTCHAN
660   EPNODE *
661   getchan()                       /* A -> $N = E1 */
662   {
# Line 625 | Line 693 | getchan()                      /* A -> $N = E1 */
693   static double
694   dvalue(name, d)                 /* evaluate a variable */
695   char  *name;
696 < EPNODE  *d;
696 > EPNODE  *d;
697   {
698      register EPNODE  *ep1, *ep2;
699      
# Line 638 | Line 706 | EPNODE  *d;
706      if (ep1->type == NUM)
707          return(ep1->v.num);                     /* return if number */
708      ep2 = ep1->sibling;                         /* check time */
709 <    if (ep2->v.tick < 0 || ep2->v.tick < eclock) {
710 <        ep2->v.tick = d->type == ':' ? 1L<<30 : eclock;
709 >    if (ep2->v.tick == 0 || ep2->v.tick < eclock) {
710 >        ep2->v.tick = d->type == ':' ? ~0L : eclock;
711          ep2 = ep2->sibling;
712          ep2->v.num = evalue(ep1);               /* needs new value */
713      } else
714          ep2 = ep2->sibling;                     /* else reuse old value */
715  
716      return(ep2->v.num);
649 }
650
651
652 static int
653 hash(s)                         /* hash a string */
654 register char  *s;
655 {
656    register int  rval = 0;
657
658    while (*s)
659        rval += *s++;
660    
661    return(rval % NHASH);
717   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines