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 1.17 by greg, Fri Aug 9 08:27:56 1991 UTC

# Line 1 | Line 1
1 < /* Copyright (c) 1986 Regents of the University of California */
1 > /* Copyright (c) 1991 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 32 | Line 36 | static char SCCSid[] = "$SunId$ LBL";
36  
37   #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
38  
39 < extern char  *ecalloc(), *savestr();
39 > extern char  *ecalloc(), *savestr(), *strcpy();
40  
41   static double  dvalue();
42  
43   long  eclock = -1;                      /* value storage timer */
44  
45 + static char  context[MAXWORD];          /* current context path */
46 +
47   static VARDEF  *hashtbl[NHASH];         /* definition list */
48   static int  htndx;                      /* index for */        
49   static VARDEF  *htpos;                  /* ...dfirst() and */
# Line 68 | Line 74 | char  *fname;
74          eputs(": cannot open\n");
75          quit(1);
76      }
77 <    initfile(fname, fp);
77 >    initfile(fp, fname, 0);
78      while (nextc != EOF)
79 <        loaddefn();
79 >        getstatement();
80      if (fname != NULL)
81          fclose(fp);
82   }
83  
84  
85 < scompile(file, str)             /* get definitions from a string */
80 < char  *file;
85 > scompile(str, fn, ln)           /* get definitions from a string */
86   char  *str;
87 + char  *fn;
88 + int  ln;
89   {
90 <    initstr(file, str);
90 >    initstr(str, fn, ln);
91      while (nextc != EOF)
92 <        loaddefn();
92 >        getstatement();
93   }
94  
95  
# Line 104 | Line 111 | EPNODE  *ep;
111   }
112  
113  
114 < varset(vname, val)              /* set a variable's value */
114 > varset(vname, assign, val)      /* set a variable's value */
115   char  *vname;
116 + int  assign;
117   double  val;
118   {
119 +    char  *qname;
120      register EPNODE  *ep1, *ep2;
121 +                                        /* get qualified name */
122 +    qname = qualname(vname, 0);
123                                          /* check for quick set */
124 <    if ((ep1 = dlookup(vname)) != NULL && ep1->v.kid->type == SYM) {
124 >    if ((ep1 = dlookup(qname)) != NULL && ep1->v.kid->type == SYM) {
125          ep2 = ep1->v.kid->sibling;
126          if (ep2->type == NUM) {
127              ep2->v.num = val;
128 <            ep2->sibling->v.tick = -1;
128 >            ep1->type = assign;
129              return;
130          }
131      }
132                                          /* hand build definition */
133      ep1 = newnode();
134 <    ep1->type = '=';
134 >    ep1->type = assign;
135      ep2 = newnode();
136      ep2->type = SYM;
137      ep2->v.name = savestr(vname);
# Line 129 | Line 140 | double  val;
140      ep2->type = NUM;
141      ep2->v.num = val;
142      addekid(ep1, ep2);
143 <    ep2 = newnode();
144 <    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);
143 >    dremove(qname);
144 >    dpush(qname, ep1);
145   }
146  
147  
148 < dclear(name)                    /* delete all definitions of name */
148 > dclear(name)                    /* delete variable definitions of name */
149   char  *name;
150   {
151      register EPNODE  *ep;
152  
153 +    while ((ep = dpop(name)) != NULL) {
154 +        if (ep->type == ':') {
155 +            dpush(name, ep);            /* don't clear constants */
156 +            return;
157 +        }
158 +        epfree(ep);
159 +    }
160 + }
161 +
162 +
163 + dremove(name)                   /* delete all definitions of name */
164 + char  *name;
165 + {
166 +    register EPNODE  *ep;
167 +
168      while ((ep = dpop(name)) != NULL)
169          epfree(ep);
170   }
# Line 160 | Line 179 | char  *name;
179   }
180  
181  
182 + char *
183 + setcontext(ctx)                 /* set a new context path */
184 + register char  *ctx;
185 + {
186 +    register char  *cpp;
187 +
188 +    if (ctx == NULL)
189 +        return(context);                /* just asking */
190 +    if (!*ctx) {
191 +        context[0] = '\0';              /* clear context */
192 +        return(context);
193 +    }
194 +    cpp = context;                      /* else copy it (carefully!) */
195 +    if (*ctx != CNTXMARK)
196 +        *cpp++ = CNTXMARK;              /* make sure there's a mark */
197 +    do {
198 +        if (cpp >= context+MAXWORD-1) {
199 +            *cpp = '\0';
200 +            wputs(context);
201 +            wputs(": context path too long\n");
202 +            return(NULL);
203 +        }
204 +        if (isid(*ctx))
205 +            *cpp++ = *ctx++;
206 +        else {
207 +            *cpp++ = '_'; ctx++;
208 +        }
209 +    } while (*ctx);
210 +    *cpp = '\0';
211 +    return(context);
212 + }
213 +
214 +
215 + char *
216 + qualname(nam, lvl)              /* get qualified name */
217 + register char  *nam;
218 + int  lvl;
219 + {
220 +    static char  nambuf[MAXWORD];
221 +    register char  *cp = nambuf, *cpp;
222 +                                /* check for explicit local */
223 +    if (*nam == CNTXMARK)
224 +        if (lvl > 0)            /* only action is to refuse search */
225 +            return(NULL);
226 +        else
227 +            nam++;
228 +    else if (nam == nambuf)     /* check for repeat call */
229 +        return(lvl > 0 ? NULL : nam);
230 +                                /* copy name to static buffer */
231 +    while (*nam) {
232 +        if (cp >= nambuf+MAXWORD-1)
233 +                goto toolong;
234 +        *cp++ = *nam++;
235 +    }
236 +                                /* check for explicit global */
237 +    if (cp > nambuf && cp[-1] == CNTXMARK) {
238 +        if (lvl > 0)
239 +            return(NULL);
240 +        *--cp = '\0';
241 +        return(nambuf);         /* already qualified */
242 +    }
243 +    cpp = context;              /* else skip the requested levels */
244 +    while (lvl-- > 0) {
245 +        if (!*cpp)
246 +            return(NULL);       /* return NULL if past global level */
247 +        while (*++cpp && *cpp != CNTXMARK)
248 +            ;
249 +    }
250 +    while (*cpp) {              /* copy context to static buffer */
251 +        if (cp >= nambuf+MAXWORD-1)
252 +            goto toolong;
253 +        *cp++ = *cpp++;
254 +    }
255 +    *cp = '\0';
256 +    return(nambuf);             /* return qualified name */
257 + toolong:
258 +    *cp = '\0';
259 +    eputs(nambuf);
260 +    eputs(": name too long\n");
261 +    quit(1);
262 + }
263 +
264 +
265 + incontext(qn)                   /* is qualified name in current context? */
266 + register char  *qn;
267 + {
268 +    while (*qn && *qn != CNTXMARK)      /* find context mark */
269 +        ;
270 +    return(!strcmp(qn, context));
271 + }
272 +
273 +
274   #ifdef  OUTCHAN
275 < chanout()                       /* set output channels */
275 > chanout(cs)                     /* set output channels */
276 > int  (*cs)();
277   {
278      register EPNODE  *ep;
279  
280      for (ep = outchan; ep != NULL; ep = ep->sibling)
281 <        chanset(ep->v.kid->v.chan, evalue(ep->v.kid->sibling));
281 >        (*cs)(ep->v.kid->v.chan, evalue(ep->v.kid->sibling));
282  
283   }
284   #endif
285  
286  
287 < dclearall()                     /* clear all definitions */
287 > dcleanup(lvl)           /* clear definitions (0->vars,1->output,2->consts) */
288 > int  lvl;
289   {
290      register int  i;
291      register VARDEF  *vp;
292      register EPNODE  *ep;
293 <
293 >                                /* if context is global, clear all */
294      for (i = 0; i < NHASH; i++)
295          for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
296 <            dclear(vp->name);
296 >            if (!context[0] || incontext(vp->name))
297 >                if (lvl >= 2)
298 >                    dremove(vp->name);
299 >                else
300 >                    dclear(vp->name);
301   #ifdef  OUTCHAN
302 <    for (ep = outchan; ep != NULL; ep = ep->sibling)
303 <        epfree(ep);
304 <    outchan = NULL;
302 >    if (lvl >= 1) {
303 >        for (ep = outchan; ep != NULL; ep = ep->sibling)
304 >            epfree(ep);
305 >        outchan = NULL;
306 >    }
307   #endif
308   }
309  
# Line 205 | Line 324 | VARDEF *
324   varlookup(name)                 /* look up a variable */
325   char  *name;
326   {
327 +    int  lvl = 0;
328 +    register char  *qname;
329      register VARDEF  *vp;
330 <    
331 <    for (vp = hashtbl[hash(name)]; vp != NULL; vp = vp->next)
332 <        if (!strcmp(vp->name, name))
333 <            return(vp);
330 >                                /* find most qualified match */
331 >    while ((qname = qualname(name, lvl++)) != NULL)
332 >        for (vp = hashtbl[hash(qname)]; vp != NULL; vp = vp->next)
333 >            if (!strcmp(vp->name, qname))
334 >                return(vp);
335      return(NULL);
336   }
337  
# Line 219 | Line 341 | varinsert(name)                        /* get a link to a variable */
341   char  *name;
342   {
343      register VARDEF  *vp;
344 +    LIBR  *libp;
345      int  hv;
346      
347 +    if ((vp = varlookup(name)) != NULL) {
348 +        vp->nlinks++;
349 +        return(vp);
350 +    }
351 + #ifdef  FUNCTION
352 +    libp = liblookup(name);
353 + #else
354 +    libp = NULL;
355 + #endif
356 +    if (libp == NULL)                   /* if name not in library */
357 +        name = qualname(name, 0);       /* use fully qualified version */
358      hv = hash(name);
225    for (vp = hashtbl[hv]; vp != NULL; vp = vp->next)
226        if (!strcmp(vp->name, name)) {
227            vp->nlinks++;
228            return(vp);
229        }
359      vp = (VARDEF *)emalloc(sizeof(VARDEF));
360      vp->name = savestr(name);
361      vp->nlinks = 1;
362      vp->def = NULL;
363 <    vp->lib = NULL;
363 >    vp->lib = libp;
364      vp->next = hashtbl[hv];
365      hashtbl[hv] = vp;
366      return(vp);
# Line 314 | Line 443 | char  *name;
443   }
444  
445  
446 < dpush(ep)                       /* push on a definition */
446 > dpush(nm, ep)                   /* push on a definition */
447 > char  *nm;
448   register EPNODE  *ep;
449   {
450      register VARDEF  *vp;
451  
452 <    vp = varinsert(dname(ep));
452 >    vp = varinsert(nm);
453      ep->sibling = vp->def;
454      vp->def = ep;
455   }
# Line 356 | Line 486 | EPNODE  *sp;
486   #endif
487  
488  
489 < loaddefn()                      /* load next definition */
489 > getstatement()                  /* get next statement */
490   {
491      register EPNODE  *ep;
492 +    char  *qname;
493 +    register VARDEF  *vdef;
494  
495      if (nextc == ';') {         /* empty statement */
496          scan();
# Line 372 | Line 504 | loaddefn()                     /* load next definition */
504   #endif
505      {                           /* ordinary definition */
506          ep = getdefn();
507 +        qname = qualname(dname(ep), 0);
508   #ifdef  REDEFW
509 <        if (dlookup(dname(ep)) != NULL) {
510 <                dclear(dname(ep));
511 <                wputs(dname(ep));
512 <                wputs(": redefined\n");
513 <        }
514 < #else
515 <        dclear(dname(ep));
509 >        if ((vdef = varlookup(qname)) != NULL)
510 >            if (vdef->def != NULL) {
511 >                wputs(qname);
512 >                if (vdef->def->type == ':')
513 >                    wputs(": redefined constant expression\n");
514 >                else
515 >                    wputs(": redefined\n");
516 >            }
517 > #ifdef  FUNCTION
518 >            else if (ep->v.kid->type == FUNC && vdef->lib != NULL) {
519 >                wputs(qname);
520 >                wputs(": definition hides library function\n");
521 >            }
522   #endif
523 <        dpush(ep);
523 > #endif
524 >        if (ep->type == ':')
525 >            dremove(qname);
526 >        else
527 >            dclear(qname);
528 >        dpush(qname, ep);
529      }
530      if (nextc != EOF) {
531          if (nextc != ';')
# Line 393 | Line 537 | loaddefn()                     /* load next definition */
537  
538   EPNODE *
539   getdefn()                       /* A -> SYM = E1 */
540 +                                /*      SYM : E1 */
541                                  /*      FUNC(SYM,..) = E1 */
542 +                                /*      FUNC(SYM,..) : E1 */
543   {
544      register EPNODE  *ep1, *ep2;
545  
# Line 427 | Line 573 | getdefn()                      /* A -> SYM = E1 */
573          curfunc = NULL;
574   #endif
575  
576 <    if (nextc != '=')
577 <        syntax("'=' expected");
432 <    scan();
576 >    if (nextc != '=' && nextc != ':')
577 >        syntax("'=' or ':' expected");
578  
579      ep2 = newnode();
580 <    ep2->type = '=';
580 >    ep2->type = nextc;
581 >    scan();
582      addekid(ep2, ep1);
583      addekid(ep2, getE1());
584  
585 +    if (
586   #ifdef  FUNCTION
587 <    if (ep1->type == SYM)
587 >            ep1->type == SYM &&
588   #endif
589 <    {
589 >            ep1->sibling->type != NUM) {
590          ep1 = newnode();
591          ep1->type = TICK;
592          ep1->v.tick = -1;
# Line 500 | Line 647 | EPNODE  *d;
647          quit(1);
648      }
649      ep1 = d->v.kid->sibling;                    /* get expression */
650 +    if (ep1->type == NUM)
651 +        return(ep1->v.num);                     /* return if number */
652      ep2 = ep1->sibling;                         /* check time */
653      if (ep2->v.tick < 0 || ep2->v.tick < eclock) {
654 <        ep2->v.tick = eclock;
654 >        ep2->v.tick = d->type == ':' ? 1L<<30 : eclock;
655          ep2 = ep2->sibling;
656 <        ep2->v.num = evalue(ep1);               /* compute new value */
656 >        ep2->v.num = evalue(ep1);               /* needs new value */
657      } else
658 <        ep2 = ep2->sibling;                     /* reuse old value */
658 >        ep2 = ep2->sibling;                     /* else reuse old value */
659  
660      return(ep2->v.num);
661   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines