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.6 by greg, Thu Jul 19 13:09:22 1990 UTC vs.
Revision 2.14 by greg, Mon Mar 10 17:13:29 2003 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1986 Regents of the University of California */
2
1   #ifndef lint
2 < static char SCCSid[] = "$SunId$ LBL";
2 > static const char       RCSid[] = "$Id$";
3   #endif
6
4   /*
5   *  Store variable definitions.
6   *
# Line 18 | Line 15 | static char SCCSid[] = "$SunId$ LBL";
15   *  11/16/88  Added VARDEF structure for hard linking.
16   *
17   *  5/31/90  Added conditional compile (REDEFW) for redefinition warning.
18 + *
19 + *  4/23/91  Added ':' assignment for constant expressions
20 + *
21 + *  8/7/91  Added optional context path to append to variable names
22 + *
23 + *  5/17/2001  Fixed clock counter wrapping behavior
24 + *
25 + *  2/19/03     Eliminated conditional compiles in favor of esupport extern.
26   */
27  
28 + #include "copyright.h"
29 +
30   #include  <stdio.h>
31  
32 + #include  <string.h>
33 +
34   #include  <ctype.h>
35  
36   #include  "calcomp.h"
37  
38 < #ifndef  NHASH
39 < #define  NHASH          521             /* hash size (a prime!) */
38 > #ifndef  NHASH
39 > #define  NHASH          521             /* hash size (a prime!) */
40   #endif
41  
42 < #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
42 > #define  hash(s)        (shash(s)%NHASH)
43  
44 < extern char  *ecalloc(), *savestr();
44 > #define  newnode()      (EPNODE *)ecalloc(1, sizeof(EPNODE))
45  
46   static double  dvalue();
47  
48 < long  eclock = -1;                      /* value storage timer */
48 > #define  MAXCLOCK       (1L<<31)        /* clock wrap value */
49  
50 + unsigned long  eclock = 0;              /* value storage timer */
51 +
52 + #define  MAXCNTX        1023            /* maximum context length */
53 +
54 + static char  context[MAXCNTX+1];        /* current context path */
55 +
56   static VARDEF  *hashtbl[NHASH];         /* definition list */
57   static int  htndx;                      /* index for */        
58   static VARDEF  *htpos;                  /* ...dfirst() and */
44 #ifdef  OUTCHAN
59   static EPNODE  *ochpos;                 /* ...dnext */
60   static EPNODE  *outchan;
47 #endif
61  
62 < #ifdef  FUNCTION
63 < EPNODE  *curfunc;
51 < #define  dname(ep)      ((ep)->v.kid->type == SYM ? \
62 > EPNODE  *curfunc = NULL;
63 > #define  dname(ep)      ((ep)->v.kid->type == SYM ? \
64                          (ep)->v.kid->v.name : \
65                          (ep)->v.kid->v.kid->v.name)
54 #else
55 #define  dname(ep)      ((ep)->v.kid->v.name)
56 #endif
66  
67  
68 + void
69   fcompile(fname)                 /* get definitions from a file */
70   char  *fname;
71   {
# Line 70 | Line 80 | char  *fname;
80      }
81      initfile(fp, fname, 0);
82      while (nextc != EOF)
83 <        loaddefn();
83 >        getstatement();
84      if (fname != NULL)
85          fclose(fp);
86   }
87  
88  
89 + void
90   scompile(str, fn, ln)           /* get definitions from a string */
91   char  *str;
92   char  *fn;
# Line 83 | Line 94 | int  ln;
94   {
95      initstr(str, fn, ln);
96      while (nextc != EOF)
97 <        loaddefn();
97 >        getstatement();
98   }
99  
100  
# Line 97 | Line 108 | char  *vname;
108  
109   double
110   evariable(ep)                   /* evaluate a variable */
111 < EPNODE  *ep;
111 > EPNODE  *ep;
112   {
113      register VARDEF  *dp = ep->v.ln;
114  
# Line 105 | Line 116 | EPNODE  *ep;
116   }
117  
118  
119 < varset(vname, val)              /* set a variable's value */
119 > void
120 > varset(vname, assign, val)      /* set a variable's value */
121   char  *vname;
122 < double  val;
122 > int  assign;
123 > double  val;
124   {
125 +    char  *qname;
126      register EPNODE  *ep1, *ep2;
127 +                                        /* get qualified name */
128 +    qname = qualname(vname, 0);
129                                          /* check for quick set */
130 <    if ((ep1 = dlookup(vname)) != NULL && ep1->v.kid->type == SYM) {
130 >    if ((ep1 = dlookup(qname)) != NULL && ep1->v.kid->type == SYM) {
131          ep2 = ep1->v.kid->sibling;
132          if (ep2->type == NUM) {
133              ep2->v.num = val;
134 +            ep1->type = assign;
135              return;
136          }
137      }
138                                          /* hand build definition */
139      ep1 = newnode();
140 <    ep1->type = '=';
140 >    ep1->type = assign;
141      ep2 = newnode();
142      ep2->type = SYM;
143      ep2->v.name = savestr(vname);
# Line 129 | Line 146 | double  val;
146      ep2->type = NUM;
147      ep2->v.num = val;
148      addekid(ep1, ep2);
149 <    dclear(vname);
150 <    dpush(ep1);
149 >    dremove(qname);
150 >    dpush(qname, ep1);
151   }
152  
153  
154 < dclear(name)                    /* delete all definitions of name */
154 > void
155 > dclear(name)                    /* delete variable definitions of name */
156   char  *name;
157   {
158      register EPNODE  *ep;
159  
160 +    while ((ep = dpop(name)) != NULL) {
161 +        if (ep->type == ':') {
162 +            dpush(name, ep);            /* don't clear constants */
163 +            return;
164 +        }
165 +        epfree(ep);
166 +    }
167 + }
168 +
169 +
170 + void
171 + dremove(name)                   /* delete all definitions of name */
172 + char  *name;
173 + {
174 +    register EPNODE  *ep;
175 +
176      while ((ep = dpop(name)) != NULL)
177          epfree(ep);
178   }
179  
180  
181 + int
182   vardefined(name)        /* return non-zero if variable defined */
183   char  *name;
184   {
# Line 153 | Line 188 | char  *name;
188   }
189  
190  
191 < #ifdef  OUTCHAN
191 > char *
192 > setcontext(ctx)                 /* set a new context path */
193 > register char  *ctx;
194 > {
195 >    register char  *cpp;
196 >
197 >    if (ctx == NULL)
198 >        return(context);                /* just asking */
199 >    while (*ctx == CNTXMARK)
200 >        ctx++;                          /* skip past marks */
201 >    if (!*ctx) {
202 >        context[0] = '\0';              /* empty means clear context */
203 >        return(context);
204 >    }
205 >    cpp = context;                      /* start context with mark */
206 >    *cpp++ = CNTXMARK;
207 >    do {                                /* carefully copy new context */
208 >        if (cpp >= context+MAXCNTX)
209 >            break;                      /* just copy what we can */
210 >        if (isid(*ctx))
211 >            *cpp++ = *ctx++;
212 >        else {
213 >            *cpp++ = '_'; ctx++;
214 >        }
215 >    } while (*ctx);
216 >    while (cpp[-1] == CNTXMARK)         /* cannot end in context mark */
217 >        cpp--;
218 >    *cpp = '\0';
219 >    return(context);
220 > }
221 >
222 >
223 > char *
224 > pushcontext(ctx)                /* push on another context */
225 > char  *ctx;
226 > {
227 >    char  oldcontext[MAXCNTX+1];
228 >    register int  n;
229 >
230 >    strcpy(oldcontext, context);        /* save old context */
231 >    setcontext(ctx);                    /* set new context */
232 >    n = strlen(context);                /* tack on old */
233 >    if (n+strlen(oldcontext) > MAXCNTX) {
234 >        strncpy(context+n, oldcontext, MAXCNTX-n);
235 >        context[MAXCNTX] = '\0';
236 >    } else
237 >        strcpy(context+n, oldcontext);
238 >    return(context);
239 > }
240 >
241 >
242 > char *
243 > popcontext()                    /* pop off top context */
244 > {
245 >    register char  *cp1, *cp2;
246 >
247 >    if (!context[0])                    /* nothing left to pop */
248 >        return(context);
249 >    cp2 = context;                      /* find mark */
250 >    while (*++cp2 && *cp2 != CNTXMARK)
251 >        ;
252 >    cp1 = context;                      /* copy tail to front */
253 >    while (*cp1++ = *cp2++)
254 >        ;
255 >    return(context);
256 > }
257 >
258 >
259 > char *
260 > qualname(nam, lvl)              /* get qualified name */
261 > register char  *nam;
262 > int  lvl;
263 > {
264 >    static char  nambuf[MAXWORD+1];
265 >    register char  *cp = nambuf, *cpp;
266 >                                /* check for explicit local */
267 >    if (*nam == CNTXMARK)
268 >        if (lvl > 0)            /* only action is to refuse search */
269 >            return(NULL);
270 >        else
271 >            nam++;
272 >    else if (nam == nambuf)     /* check for repeat call */
273 >        return(lvl > 0 ? NULL : nam);
274 >                                /* copy name to static buffer */
275 >    while (*nam) {
276 >        if (cp >= nambuf+MAXWORD)
277 >                goto toolong;
278 >        *cp++ = *nam++;
279 >    }
280 >                                /* check for explicit global */
281 >    if (cp > nambuf && cp[-1] == CNTXMARK) {
282 >        if (lvl > 0)
283 >            return(NULL);
284 >        *--cp = '\0';
285 >        return(nambuf);         /* already qualified */
286 >    }
287 >    cpp = context;              /* else skip the requested levels */
288 >    while (lvl-- > 0) {
289 >        if (!*cpp)
290 >            return(NULL);       /* return NULL if past global level */
291 >        while (*++cpp && *cpp != CNTXMARK)
292 >            ;
293 >    }
294 >    while (*cpp) {              /* copy context to static buffer */
295 >        if (cp >= nambuf+MAXWORD)
296 >            goto toolong;
297 >        *cp++ = *cpp++;
298 >    }
299 > toolong:
300 >    *cp = '\0';
301 >    return(nambuf);             /* return qualified name */
302 > }
303 >
304 >
305 > int
306 > incontext(qn)                   /* is qualified name in current context? */
307 > register char  *qn;
308 > {
309 >    if (!context[0])                    /* global context accepts all */
310 >        return(1);
311 >    while (*qn && *qn != CNTXMARK)      /* find context mark */
312 >        qn++;
313 >    return(!strcmp(qn, context));
314 > }
315 >
316 >
317 > void
318   chanout(cs)                     /* set output channels */
319   int  (*cs)();
320   {
# Line 163 | Line 324 | int  (*cs)();
324          (*cs)(ep->v.kid->v.chan, evalue(ep->v.kid->sibling));
325  
326   }
166 #endif
327  
328  
329 < dclearall()                     /* clear all definitions */
329 > void
330 > dcleanup(lvl)           /* clear definitions (0->vars,1->output,2->consts) */
331 > int  lvl;
332   {
333      register int  i;
334      register VARDEF  *vp;
335      register EPNODE  *ep;
336 <
336 >                                /* if context is global, clear all */
337      for (i = 0; i < NHASH; i++)
338          for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
339 <            dclear(vp->name);
340 < #ifdef  OUTCHAN
341 <    for (ep = outchan; ep != NULL; ep = ep->sibling)
342 <        epfree(ep);
343 <    outchan = NULL;
344 < #endif
339 >            if (incontext(vp->name))
340 >                if (lvl >= 2)
341 >                    dremove(vp->name);
342 >                else
343 >                    dclear(vp->name);
344 >    if (lvl >= 1) {
345 >        for (ep = outchan; ep != NULL; ep = ep->sibling)
346 >            epfree(ep);
347 >        outchan = NULL;
348 >    }
349   }
350  
351  
# Line 190 | Line 356 | char  *name;
356      register VARDEF  *vp;
357      
358      if ((vp = varlookup(name)) == NULL)
359 <        return(NULL);
359 >        return(NULL);
360      return(vp->def);
361   }
362  
# Line 199 | Line 365 | VARDEF *
365   varlookup(name)                 /* look up a variable */
366   char  *name;
367   {
368 +    int  lvl = 0;
369 +    register char  *qname;
370      register VARDEF  *vp;
371 <    
372 <    for (vp = hashtbl[hash(name)]; vp != NULL; vp = vp->next)
373 <        if (!strcmp(vp->name, name))
374 <            return(vp);
371 >                                /* find most qualified match */
372 >    while ((qname = qualname(name, lvl++)) != NULL)
373 >        for (vp = hashtbl[hash(qname)]; vp != NULL; vp = vp->next)
374 >            if (!strcmp(vp->name, qname))
375 >                return(vp);
376      return(NULL);
377   }
378  
# Line 213 | Line 382 | varinsert(name)                        /* get a link to a variable */
382   char  *name;
383   {
384      register VARDEF  *vp;
385 <    int  hv;
385 >    int  hv;
386      
387 <    hv = hash(name);
388 <    for (vp = hashtbl[hv]; vp != NULL; vp = vp->next)
389 <        if (!strcmp(vp->name, name)) {
390 <            vp->nlinks++;
222 <            return(vp);
223 <        }
387 >    if ((vp = varlookup(name)) != NULL) {
388 >        vp->nlinks++;
389 >        return(vp);
390 >    }
391      vp = (VARDEF *)emalloc(sizeof(VARDEF));
392 +    vp->lib = liblookup(name);
393 +    if (vp->lib == NULL)                /* if name not in library */
394 +        name = qualname(name, 0);       /* use fully qualified version */
395 +    hv = hash(name);
396      vp->name = savestr(name);
397      vp->nlinks = 1;
398      vp->def = NULL;
228    vp->lib = NULL;
399      vp->next = hashtbl[hv];
400      hashtbl[hv] = vp;
401      return(vp);
402   }
403  
404  
405 + void
406 + libupdate(fn)                   /* update library links */
407 + char  *fn;
408 + {
409 +    register int  i;
410 +    register VARDEF  *vp;
411 +                                        /* if fn is NULL then relink all */
412 +    for (i = 0; i < NHASH; i++)
413 +        for (vp = hashtbl[i]; vp != NULL; vp = vp->next)
414 +            if (vp->lib != NULL || fn == NULL || !strcmp(fn, vp->name))
415 +                vp->lib = liblookup(vp->name);
416 + }
417 +
418 +
419 + void
420   varfree(ln)                             /* release link to variable */
421 < register VARDEF  *ln;
421 > register VARDEF  *ln;
422   {
423      register VARDEF  *vp;
424 <    int  hv;
424 >    int  hv;
425  
426      if (--ln->nlinks > 0)
427 <        return;                         /* still active */
427 >        return;                         /* still active */
428  
429      hv = hash(ln->name);
430      vp = hashtbl[hv];
431      if (vp == ln)
432 <        hashtbl[hv] = vp->next;
432 >        hashtbl[hv] = vp->next;
433      else {
434 <        while (vp->next != ln)          /* must be in list */
435 <                vp = vp->next;
436 <        vp->next = ln->next;
434 >        while (vp->next != ln)          /* must be in list */
435 >                vp = vp->next;
436 >        vp->next = ln->next;
437      }
438      freestr(ln->name);
439      efree((char *)ln);
# Line 260 | Line 445 | dfirst()                       /* return pointer to first definition */
445   {
446      htndx = 0;
447      htpos = NULL;
263 #ifdef  OUTCHAN
448      ochpos = outchan;
265 #endif
449      return(dnext());
450   }
451  
# Line 271 | Line 454 | EPNODE *
454   dnext()                         /* return pointer to next definition */
455   {
456      register EPNODE  *ep;
457 +    register char  *nm;
458  
459      while (htndx < NHASH) {
460 <        if (htpos == NULL)
461 <                htpos = hashtbl[htndx++];
462 <        while (htpos != NULL) {
463 <            ep = htpos->def;
464 <            htpos = htpos->next;
465 <            if (ep != NULL)
466 <                return(ep);
467 <        }
460 >        if (htpos == NULL)
461 >                htpos = hashtbl[htndx++];
462 >        while (htpos != NULL) {
463 >            ep = htpos->def;
464 >            nm = htpos->name;
465 >            htpos = htpos->next;
466 >            if (ep != NULL && incontext(nm))
467 >                return(ep);
468 >        }
469      }
285 #ifdef  OUTCHAN
470      if ((ep = ochpos) != NULL)
471 <        ochpos = ep->sibling;
471 >        ochpos = ep->sibling;
472      return(ep);
289 #else
290    return(NULL);
291 #endif
473   }
474  
475  
# Line 300 | Line 481 | char  *name;
481      register EPNODE  *dp;
482      
483      if ((vp = varlookup(name)) == NULL || vp->def == NULL)
484 <        return(NULL);
484 >        return(NULL);
485      dp = vp->def;
486      vp->def = dp->sibling;
487      varfree(vp);
# Line 308 | Line 489 | char  *name;
489   }
490  
491  
492 < dpush(ep)                       /* push on a definition */
493 < register EPNODE  *ep;
492 > void
493 > dpush(nm, ep)                   /* push on a definition */
494 > char  *nm;
495 > register EPNODE  *ep;
496   {
497      register VARDEF  *vp;
498  
499 <    vp = varinsert(dname(ep));
499 >    vp = varinsert(nm);
500      ep->sibling = vp->def;
501      vp->def = ep;
502   }
503  
504  
505 < #ifdef  OUTCHAN
505 > void
506   addchan(sp)                     /* add an output channel assignment */
507 < EPNODE  *sp;
507 > EPNODE  *sp;
508   {
509 <    int  ch = sp->v.kid->v.chan;
509 >    int  ch = sp->v.kid->v.chan;
510      register EPNODE  *ep, *epl;
511  
512      for (epl = NULL, ep = outchan; ep != NULL; epl = ep, ep = ep->sibling)
# Line 347 | Line 530 | EPNODE  *sp;
530      sp->sibling = NULL;
531  
532   }
350 #endif
533  
534  
535 < loaddefn()                      /* load next definition */
535 > void
536 > getstatement()                  /* get next statement */
537   {
538      register EPNODE  *ep;
539 +    char  *qname;
540 +    register VARDEF  *vdef;
541  
542      if (nextc == ';') {         /* empty statement */
543          scan();
544          return;
545      }
546 < #ifdef  OUTCHAN
547 <    if (nextc == '$') {         /* channel assignment */
546 >    if (esupport&E_OUTCHAN &&
547 >                nextc == '$') {         /* channel assignment */
548          ep = getchan();
549          addchan(ep);
550 <    } else
366 < #endif
367 <    {                           /* ordinary definition */
550 >    } else {                            /* ordinary definition */
551          ep = getdefn();
552 < #ifdef  REDEFW
553 <        if (dlookup(dname(ep)) != NULL) {
554 <                dclear(dname(ep));
555 <                wputs(dname(ep));
556 <                wputs(": redefined\n");
557 <        }
558 < #else
559 <        dclear(dname(ep));
560 < #endif
561 <        dpush(ep);
552 >        qname = qualname(dname(ep), 0);
553 >        if (esupport&E_REDEFW && (vdef = varlookup(qname)) != NULL)
554 >            if (vdef->def != NULL && epcmp(ep, vdef->def)) {
555 >                wputs(qname);
556 >                if (vdef->def->type == ':')
557 >                    wputs(": redefined constant expression\n");
558 >                else
559 >                    wputs(": redefined\n");
560 >            } else if (ep->v.kid->type == FUNC && vdef->lib != NULL) {
561 >                wputs(qname);
562 >                wputs(": definition hides library function\n");
563 >            }
564 >        if (ep->type == ':')
565 >            dremove(qname);
566 >        else
567 >            dclear(qname);
568 >        dpush(qname, ep);
569      }
570      if (nextc != EOF) {
571          if (nextc != ';')
# Line 387 | Line 577 | loaddefn()                     /* load next definition */
577  
578   EPNODE *
579   getdefn()                       /* A -> SYM = E1 */
580 <                                /*      FUNC(SYM,..) = E1 */
580 >                                /*      SYM : E1 */
581 >                                /*      FUNC(SYM,..) = E1 */
582 >                                /*      FUNC(SYM,..) : E1 */
583   {
584      register EPNODE  *ep1, *ep2;
585  
586 <    if (!isalpha(nextc))
586 >    if (!isalpha(nextc) && nextc != CNTXMARK)
587          syntax("illegal variable name");
588  
589      ep1 = newnode();
590      ep1->type = SYM;
591      ep1->v.name = savestr(getname());
592  
593 < #ifdef  FUNCTION
402 <    if (nextc == '(') {
593 >    if (esupport&E_FUNCTION && nextc == '(') {
594          ep2 = newnode();
595          ep2->type = FUNC;
596          addekid(ep2, ep1);
# Line 417 | Line 608 | getdefn()                      /* A -> SYM = E1 */
608              syntax("')' expected");
609          scan();
610          curfunc = ep1;
611 <    } else
421 <        curfunc = NULL;
422 < #endif
611 >    }
612  
613 <    if (nextc != '=')
614 <        syntax("'=' expected");
426 <    scan();
613 >    if (nextc != '=' && nextc != ':')
614 >        syntax("'=' or ':' expected");
615  
616      ep2 = newnode();
617 <    ep2->type = '=';
617 >    ep2->type = nextc;
618 >    scan();
619      addekid(ep2, ep1);
620      addekid(ep2, getE1());
621  
622 < #ifdef  FUNCTION
434 <    if (ep1->type == SYM)
435 < #endif
436 <    {
622 >    if (ep1->type == SYM && ep1->sibling->type != NUM) {
623          ep1 = newnode();
624          ep1->type = TICK;
625 <        ep1->v.tick = -1;
625 >        ep1->v.tick = 0;
626          addekid(ep2, ep1);
627          ep1 = newnode();
628          ep1->type = NUM;
629          addekid(ep2, ep1);
630      }
631 +    curfunc = NULL;
632  
633      return(ep2);
634   }
635  
636  
450 #ifdef  OUTCHAN
637   EPNODE *
638   getchan()                       /* A -> $N = E1 */
639   {
# Line 472 | Line 658 | getchan()                      /* A -> $N = E1 */
658  
659      return(ep2);
660   }
475 #endif
661  
662  
663  
# Line 484 | Line 669 | getchan()                      /* A -> $N = E1 */
669   static double
670   dvalue(name, d)                 /* evaluate a variable */
671   char  *name;
672 < EPNODE  *d;
672 > EPNODE  *d;
673   {
674      register EPNODE  *ep1, *ep2;
675      
# Line 497 | Line 682 | EPNODE  *d;
682      if (ep1->type == NUM)
683          return(ep1->v.num);                     /* return if number */
684      ep2 = ep1->sibling;                         /* check time */
685 <    if (ep2->v.tick < 0 || ep2->v.tick < eclock) {
686 <        ep2->v.tick = eclock;
685 >    if (eclock >= MAXCLOCK)
686 >        eclock = 1;                             /* wrap clock counter */
687 >    if (ep2->v.tick < MAXCLOCK &&
688 >                ep2->v.tick == 0 | ep2->v.tick != eclock) {
689 >        ep2->v.tick = d->type == ':' ? MAXCLOCK : eclock;
690          ep2 = ep2->sibling;
691          ep2->v.num = evalue(ep1);               /* needs new value */
692      } else
693          ep2 = ep2->sibling;                     /* else reuse old value */
694  
695      return(ep2->v.num);
508 }
509
510
511 static int
512 hash(s)                         /* hash a string */
513 register char  *s;
514 {
515    register int  rval = 0;
516
517    while (*s)
518        rval += *s++;
519    
520    return(rval % NHASH);
696   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines