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.9 by greg, Wed Apr 24 08:17:22 1991 UTC vs.
Revision 2.5 by greg, Sat Nov 21 21:42:42 1992 UTC

# Line 1 | Line 1
1 < /* Copyright (c) 1991 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 19 | Line 19 | static char SCCSid[] = "$SunId$ LBL";
19   *
20   *  5/31/90  Added conditional compile (REDEFW) for redefinition warning.
21   *
22 < *  4/23/91  Added ':' defines for constant expressions (RCONST)
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 28 | 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 72 | 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 85 | Line 91 | int  ln;
91   {
92      initstr(str, fn, ln);
93      while (nextc != EOF)
94 <        loaddefn();
94 >        getstatement();
95   }
96  
97  
# Line 99 | 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 110 | Line 116 | EPNODE  *ep;
116   varset(vname, assign, val)      /* set a variable's value */
117   char  *vname;
118   int  assign;
119 < double  val;
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;
# Line 133 | Line 142 | double  val;
142      ep2->type = NUM;
143      ep2->v.num = val;
144      addekid(ep1, ep2);
145 <    dremove(vname);
146 <    dpush(ep1);
145 >    dremove(qname);
146 >    dpush(qname, ep1);
147   }
148  
149  
# Line 145 | Line 154 | char  *name;
154  
155      while ((ep = dpop(name)) != NULL) {
156          if (ep->type == ':') {
157 <            dpush(ep);          /* don't clear constants */
157 >            dpush(name, ep);            /* don't clear constants */
158              return;
159          }
160          epfree(ep);
# Line 172 | Line 181 | char  *name;
181   }
182  
183  
184 < #ifdef  OUTCHAN
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   {
# Line 185 | Line 278 | int  (*cs)();
278   #endif
279  
280  
281 < dcleanup(cons, ochans)          /* clear definitions */
282 < int  cons, ochans;
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 <            if (cons)
291 <                dremove(vp->name);
292 <            else
293 <                dclear(vp->name);
294 < #ifdef  OUTCHAN
295 <    if (ochans) {
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;
# Line 215 | 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 224 | 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 238 | 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++;
247 <            return(vp);
248 <        }
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;
253    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 285 | 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 296 | 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 325 | 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 333 | 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 375 | 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 391 | 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 <            if (dlookup(dname(ep)) == NULL)
521 <                wputs(": redefined\n");
522 <            else
523 <                wputs(": redefined constant expression\n");
524 <        }
525 < #ifdef  FUNCTION
526 <        else if (ep->v.kid->type == FUNC &&
527 <                        liblookup(ep->v.kid->v.kid->v.name) != NULL) {
528 <            wputs(ep->v.kid->v.kid->v.name);
529 <            wputs(": redefined library function\n");
530 <        }
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
410 #else
411        dclear(dname(ep));
532   #endif
533 <        dpush(ep);
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 423 | Line 547 | loaddefn()                     /* load next definition */
547   EPNODE *
548   getdefn()                       /* A -> SYM = E1 */
549                                  /*      SYM : E1 */
550 <                                /*      FUNC(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 465 | Line 589 | getdefn()                      /* A -> SYM = E1 */
589      ep2->type = nextc;
590      scan();
591      addekid(ep2, ep1);
468 #ifdef  RCONST
469    if (
470 #ifdef  FUNCTION
471            ep1->type == SYM &&
472 #endif
473            ep2->type == ':')
474        addekid(ep2, rconst(getE1()));
475    else
476 #endif
592      addekid(ep2, getE1());
593  
594      if (
595 < #ifdef  FUNCTION
596 <            ep1->type == SYM &&
595 > #ifdef  FUNCTION
596 >            ep1->type == SYM &&
597   #endif
598              ep1->sibling->type != NUM) {
599          ep1 = newnode();
# Line 494 | Line 609 | getdefn()                      /* A -> SYM = E1 */
609   }
610  
611  
612 < #ifdef  OUTCHAN
612 > #ifdef  OUTCHAN
613   EPNODE *
614   getchan()                       /* A -> $N = E1 */
615   {
# Line 531 | 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 552 | Line 667 | EPNODE  *d;
667          ep2 = ep2->sibling;                     /* else reuse old value */
668  
669      return(ep2->v.num);
555 }
556
557
558 static int
559 hash(s)                         /* hash a string */
560 register char  *s;
561 {
562    register int  rval = 0;
563
564    while (*s)
565        rval += *s++;
566    
567    return(rval % NHASH);
670   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines