--- ray/src/common/caldefn.c 1992/05/15 16:38:49 2.2 +++ ray/src/common/caldefn.c 2003/07/17 09:21:29 2.18 @@ -1,9 +1,6 @@ -/* Copyright (c) 1991 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: caldefn.c,v 2.18 2003/07/17 09:21:29 schorsch Exp $"; #endif - /* * Store variable definitions. * @@ -22,50 +19,55 @@ static char SCCSid[] = "$SunId$ LBL"; * 4/23/91 Added ':' assignment for constant expressions * * 8/7/91 Added optional context path to append to variable names + * + * 5/17/2001 Fixed clock counter wrapping behavior + * + * 2/19/03 Eliminated conditional compiles in favor of esupport extern. */ -#include +#include "copyright.h" +#include +#include #include +#include "rterror.h" #include "calcomp.h" -#ifndef NHASH -#define NHASH 521 /* hash size (a prime!) */ +#ifndef NHASH +#define NHASH 521 /* hash size (a prime!) */ #endif -#define newnode() (EPNODE *)ecalloc(1, sizeof(EPNODE)) +#define hash(s) (shash(s)%NHASH) -extern char *ecalloc(), *savestr(), *strcpy(); +#define newnode() (EPNODE *)ecalloc(1, sizeof(EPNODE)) -static int hash(); +static double dvalue(char *name, EPNODE *d); -static double dvalue(); +#define MAXCLOCK (1L<<31) /* clock wrap value */ -long eclock = -1; /* value storage timer */ +unsigned long eclock = 0; /* value storage timer */ -static char context[MAXWORD+1]; /* current context path */ +#define MAXCNTX 1023 /* maximum context length */ +static char context[MAXCNTX+1]; /* current context path */ + static VARDEF *hashtbl[NHASH]; /* definition list */ static int htndx; /* index for */ static VARDEF *htpos; /* ...dfirst() and */ -#ifdef OUTCHAN static EPNODE *ochpos; /* ...dnext */ static EPNODE *outchan; -#endif -#ifdef FUNCTION -EPNODE *curfunc; -#define dname(ep) ((ep)->v.kid->type == SYM ? \ +EPNODE *curfunc = NULL; +#define dname(ep) ((ep)->v.kid->type == SYM ? \ (ep)->v.kid->v.name : \ (ep)->v.kid->v.kid->v.name) -#else -#define dname(ep) ((ep)->v.kid->v.name) -#endif -fcompile(fname) /* get definitions from a file */ -char *fname; +void +fcompile( /* get definitions from a file */ + char *fname +) { FILE *fp; @@ -84,10 +86,12 @@ char *fname; } -scompile(str, fn, ln) /* get definitions from a string */ -char *str; -char *fn; -int ln; +void +scompile( /* get definitions from a string */ + char *str, + char *fn, + int ln +) { initstr(str, fn, ln); while (nextc != EOF) @@ -96,16 +100,18 @@ int ln; double -varvalue(vname) /* return a variable's value */ -char *vname; +varvalue( /* return a variable's value */ + char *vname +) { return(dvalue(vname, dlookup(vname))); } double -evariable(ep) /* evaluate a variable */ -EPNODE *ep; +evariable( /* evaluate a variable */ + EPNODE *ep +) { register VARDEF *dp = ep->v.ln; @@ -113,10 +119,12 @@ EPNODE *ep; } -varset(vname, assign, val) /* set a variable's value */ -char *vname; -int assign; -double val; +void +varset( /* set a variable's value */ + char *vname, + int assign, + double val +) { char *qname; register EPNODE *ep1, *ep2; @@ -147,8 +155,10 @@ double val; } -dclear(name) /* delete variable definitions of name */ -char *name; +void +dclear( /* delete variable definitions of name */ + char *name +) { register EPNODE *ep; @@ -162,8 +172,10 @@ char *name; } -dremove(name) /* delete all definitions of name */ -char *name; +void +dremove( /* delete all definitions of name */ + char *name +) { register EPNODE *ep; @@ -172,8 +184,10 @@ char *name; } -vardefined(name) /* return non-zero if variable defined */ -char *name; +int +vardefined( /* return non-zero if variable defined */ + char *name +) { register EPNODE *dp; @@ -182,22 +196,24 @@ char *name; char * -setcontext(ctx) /* set a new context path */ -register char *ctx; +setcontext( /* set a new context path */ + register char *ctx +) { register char *cpp; if (ctx == NULL) return(context); /* just asking */ + while (*ctx == CNTXMARK) + ctx++; /* skip past marks */ if (!*ctx) { - context[0] = '\0'; /* clear context */ + context[0] = '\0'; /* empty means clear context */ return(context); } - cpp = context; /* else copy it (carefully!) */ - if (*ctx != CNTXMARK) - *cpp++ = CNTXMARK; /* make sure there's a mark */ - do { - if (cpp >= context+MAXWORD) + cpp = context; /* start context with mark */ + *cpp++ = CNTXMARK; + do { /* carefully copy new context */ + if (cpp >= context+MAXCNTX) break; /* just copy what we can */ if (isid(*ctx)) *cpp++ = *ctx++; @@ -205,17 +221,57 @@ register char *ctx; *cpp++ = '_'; ctx++; } } while (*ctx); + while (cpp[-1] == CNTXMARK) /* cannot end in context mark */ + cpp--; *cpp = '\0'; return(context); } char * -qualname(nam, lvl) /* get qualified name */ -register char *nam; -int lvl; +pushcontext( /* push on another context */ + char *ctx +) { - static char nambuf[MAXWORD+1]; + char oldcontext[MAXCNTX+1]; + register int n; + + strcpy(oldcontext, context); /* save old context */ + setcontext(ctx); /* set new context */ + n = strlen(context); /* tack on old */ + if (n+strlen(oldcontext) > MAXCNTX) { + strncpy(context+n, oldcontext, MAXCNTX-n); + context[MAXCNTX] = '\0'; + } else + strcpy(context+n, oldcontext); + return(context); +} + + +char * +popcontext(void) /* pop off top context */ +{ + register char *cp1, *cp2; + + if (!context[0]) /* nothing left to pop */ + return(context); + cp2 = context; /* find mark */ + while (*++cp2 && *cp2 != CNTXMARK) + ; + cp1 = context; /* copy tail to front */ + while (*cp1++ = *cp2++) + ; + return(context); +} + + +char * +qualname( /* get qualified name */ + register char *nam, + int lvl +) +{ + static char nambuf[RMAXWORD+1]; register char *cp = nambuf, *cpp; /* check for explicit local */ if (*nam == CNTXMARK) @@ -227,7 +283,7 @@ int lvl; return(lvl > 0 ? NULL : nam); /* copy name to static buffer */ while (*nam) { - if (cp >= nambuf+MAXWORD) + if (cp >= nambuf+RMAXWORD) goto toolong; *cp++ = *nam++; } @@ -246,7 +302,7 @@ int lvl; ; } while (*cpp) { /* copy context to static buffer */ - if (cp >= nambuf+MAXWORD) + if (cp >= nambuf+RMAXWORD) goto toolong; *cp++ = *cpp++; } @@ -256,18 +312,23 @@ toolong: } -incontext(qn) /* is qualified name in current context? */ -register char *qn; +int +incontext( /* is qualified name in current context? */ + register char *qn +) { + if (!context[0]) /* global context accepts all */ + return(1); while (*qn && *qn != CNTXMARK) /* find context mark */ qn++; return(!strcmp(qn, context)); } -#ifdef OUTCHAN -chanout(cs) /* set output channels */ -int (*cs)(); +void +chanout( /* set output channels */ + void (*cs)(int n, double v) +) { register EPNODE *ep; @@ -275,11 +336,12 @@ int (*cs)(); (*cs)(ep->v.kid->v.chan, evalue(ep->v.kid->sibling)); } -#endif -dcleanup(lvl) /* clear definitions (0->vars,1->output,2->consts) */ -int lvl; +void +dcleanup( /* clear definitions (0->vars,1->output,2->consts) */ + int lvl +) { register int i; register VARDEF *vp; @@ -287,41 +349,41 @@ int lvl; /* if context is global, clear all */ for (i = 0; i < NHASH; i++) for (vp = hashtbl[i]; vp != NULL; vp = vp->next) - if (!context[0] || incontext(vp->name)) + if (incontext(vp->name)) if (lvl >= 2) dremove(vp->name); else dclear(vp->name); -#ifdef OUTCHAN if (lvl >= 1) { for (ep = outchan; ep != NULL; ep = ep->sibling) epfree(ep); outchan = NULL; } -#endif } EPNODE * -dlookup(name) /* look up a definition */ -char *name; +dlookup( /* look up a definition */ + char *name +) { register VARDEF *vp; if ((vp = varlookup(name)) == NULL) - return(NULL); + return(NULL); return(vp->def); } VARDEF * -varlookup(name) /* look up a variable */ -char *name; +varlookup( /* look up a variable */ + char *name +) { - int lvl = 0; + int lvl = 0; register char *qname; register VARDEF *vp; - /* find most qualified match */ + /* find most qualified match */ while ((qname = qualname(name, lvl++)) != NULL) for (vp = hashtbl[hash(qname)]; vp != NULL; vp = vp->next) if (!strcmp(vp->name, qname)) @@ -331,39 +393,35 @@ char *name; VARDEF * -varinsert(name) /* get a link to a variable */ -char *name; +varinsert( /* get a link to a variable */ + char *name +) { register VARDEF *vp; - register LIBR *libp; - int hv; + int hv; if ((vp = varlookup(name)) != NULL) { vp->nlinks++; return(vp); } -#ifdef FUNCTION - libp = liblookup(name); -#else - libp = NULL; -#endif - if (libp == NULL) /* if name not in library */ + vp = (VARDEF *)emalloc(sizeof(VARDEF)); + vp->lib = liblookup(name); + if (vp->lib == NULL) /* if name not in library */ name = qualname(name, 0); /* use fully qualified version */ hv = hash(name); - vp = (VARDEF *)emalloc(sizeof(VARDEF)); vp->name = savestr(name); vp->nlinks = 1; vp->def = NULL; - vp->lib = libp; vp->next = hashtbl[hv]; hashtbl[hv] = vp; return(vp); } -#ifdef FUNCTION -libupdate(fn) /* update library links */ -char *fn; +void +libupdate( /* update library links */ + char *fn +) { register int i; register VARDEF *vp; @@ -373,26 +431,27 @@ char *fn; if (vp->lib != NULL || fn == NULL || !strcmp(fn, vp->name)) vp->lib = liblookup(vp->name); } -#endif -varfree(ln) /* release link to variable */ -register VARDEF *ln; +void +varfree( /* release link to variable */ + register VARDEF *ln +) { register VARDEF *vp; - int hv; + int hv; if (--ln->nlinks > 0) - return; /* still active */ + return; /* still active */ hv = hash(ln->name); vp = hashtbl[hv]; if (vp == ln) - hashtbl[hv] = vp->next; + hashtbl[hv] = vp->next; else { - while (vp->next != ln) /* must be in list */ - vp = vp->next; - vp->next = ln->next; + while (vp->next != ln) /* must be in list */ + vp = vp->next; + vp->next = ln->next; } freestr(ln->name); efree((char *)ln); @@ -400,53 +459,48 @@ register VARDEF *ln; EPNODE * -dfirst() /* return pointer to first definition */ +dfirst(void) /* return pointer to first definition */ { htndx = 0; htpos = NULL; -#ifdef OUTCHAN ochpos = outchan; -#endif return(dnext()); } EPNODE * -dnext() /* return pointer to next definition */ +dnext(void) /* return pointer to next definition */ { register EPNODE *ep; register char *nm; while (htndx < NHASH) { - if (htpos == NULL) - htpos = hashtbl[htndx++]; - while (htpos != NULL) { - ep = htpos->def; + if (htpos == NULL) + htpos = hashtbl[htndx++]; + while (htpos != NULL) { + ep = htpos->def; nm = htpos->name; - htpos = htpos->next; - if (ep != NULL && incontext(nm)) - return(ep); - } + htpos = htpos->next; + if (ep != NULL && incontext(nm)) + return(ep); + } } -#ifdef OUTCHAN if ((ep = ochpos) != NULL) - ochpos = ep->sibling; + ochpos = ep->sibling; return(ep); -#else - return(NULL); -#endif } EPNODE * -dpop(name) /* pop a definition */ -char *name; +dpop( /* pop a definition */ + char *name +) { register VARDEF *vp; register EPNODE *dp; if ((vp = varlookup(name)) == NULL || vp->def == NULL) - return(NULL); + return(NULL); dp = vp->def; vp->def = dp->sibling; varfree(vp); @@ -454,9 +508,11 @@ char *name; } -dpush(nm, ep) /* push on a definition */ -char *nm; -register EPNODE *ep; +void +dpush( /* push on a definition */ + char *nm, + register EPNODE *ep +) { register VARDEF *vp; @@ -466,11 +522,12 @@ register EPNODE *ep; } -#ifdef OUTCHAN -addchan(sp) /* add an output channel assignment */ -EPNODE *sp; +void +addchan( /* add an output channel assignment */ + EPNODE *sp +) { - int ch = sp->v.kid->v.chan; + int ch = sp->v.kid->v.chan; register EPNODE *ep, *epl; for (epl = NULL, ep = outchan; ep != NULL; epl = ep, ep = ep->sibling) @@ -494,10 +551,10 @@ EPNODE *sp; sp->sibling = NULL; } -#endif -getstatement() /* get next statement */ +void +getstatement(void) /* get next statement */ { register EPNODE *ep; char *qname; @@ -507,31 +564,24 @@ getstatement() /* get next statement */ scan(); return; } -#ifdef OUTCHAN - if (nextc == '$') { /* channel assignment */ + if (esupport&E_OUTCHAN && + nextc == '$') { /* channel assignment */ ep = getchan(); addchan(ep); - } else -#endif - { /* ordinary definition */ + } else { /* ordinary definition */ ep = getdefn(); qname = qualname(dname(ep), 0); -#ifdef REDEFW - if ((vdef = varlookup(qname)) != NULL) - if (vdef->def != NULL) { + if (esupport&E_REDEFW && (vdef = varlookup(qname)) != NULL) + if (vdef->def != NULL && epcmp(ep, vdef->def)) { wputs(qname); if (vdef->def->type == ':') wputs(": redefined constant expression\n"); else wputs(": redefined\n"); - } -#ifdef FUNCTION - else if (ep->v.kid->type == FUNC && vdef->lib != NULL) { + } else if (ep->v.kid->type == FUNC && vdef->lib != NULL) { wputs(qname); wputs(": definition hides library function\n"); } -#endif -#endif if (ep->type == ':') dremove(qname); else @@ -547,10 +597,11 @@ getstatement() /* get next statement */ EPNODE * -getdefn() /* A -> SYM = E1 */ - /* SYM : E1 */ - /* FUNC(SYM,..) = E1 */ - /* FUNC(SYM,..) : E1 */ +getdefn(void) + /* A -> SYM = E1 */ + /* SYM : E1 */ + /* FUNC(SYM,..) = E1 */ + /* FUNC(SYM,..) : E1 */ { register EPNODE *ep1, *ep2; @@ -561,8 +612,7 @@ getdefn() /* A -> SYM = E1 */ ep1->type = SYM; ep1->v.name = savestr(getname()); -#ifdef FUNCTION - if (nextc == '(') { + if (esupport&E_FUNCTION && nextc == '(') { ep2 = newnode(); ep2->type = FUNC; addekid(ep2, ep1); @@ -580,9 +630,7 @@ getdefn() /* A -> SYM = E1 */ syntax("')' expected"); scan(); curfunc = ep1; - } else - curfunc = NULL; -#endif + } if (nextc != '=' && nextc != ':') syntax("'=' or ':' expected"); @@ -593,27 +641,23 @@ getdefn() /* A -> SYM = E1 */ addekid(ep2, ep1); addekid(ep2, getE1()); - if ( -#ifdef FUNCTION - ep1->type == SYM && -#endif - ep1->sibling->type != NUM) { + if (ep1->type == SYM && ep1->sibling->type != NUM) { ep1 = newnode(); ep1->type = TICK; - ep1->v.tick = -1; + ep1->v.tick = 0; addekid(ep2, ep1); ep1 = newnode(); ep1->type = NUM; addekid(ep2, ep1); } + curfunc = NULL; return(ep2); } -#ifdef OUTCHAN EPNODE * -getchan() /* A -> $N = E1 */ +getchan(void) /* A -> $N = E1 */ { register EPNODE *ep1, *ep2; @@ -636,7 +680,6 @@ getchan() /* A -> $N = E1 */ return(ep2); } -#endif @@ -645,10 +688,8 @@ getchan() /* A -> $N = E1 */ */ -static double -dvalue(name, d) /* evaluate a variable */ -char *name; -EPNODE *d; +static double /* evaluate a variable */ +dvalue(char *name, EPNODE *d) { register EPNODE *ep1, *ep2; @@ -661,25 +702,15 @@ EPNODE *d; if (ep1->type == NUM) return(ep1->v.num); /* return if number */ ep2 = ep1->sibling; /* check time */ - if (ep2->v.tick < 0 || ep2->v.tick < eclock) { - ep2->v.tick = d->type == ':' ? 1L<<30 : eclock; + if (eclock >= MAXCLOCK) + eclock = 1; /* wrap clock counter */ + if (ep2->v.tick < MAXCLOCK && + ep2->v.tick == 0 | ep2->v.tick != eclock) { + ep2->v.tick = d->type == ':' ? MAXCLOCK : eclock; ep2 = ep2->sibling; ep2->v.num = evalue(ep1); /* needs new value */ } else ep2 = ep2->sibling; /* else reuse old value */ return(ep2->v.num); -} - - -static int -hash(s) /* hash a string */ -register char *s; -{ - register int rval = 0; - - while (*s) - rval += *s++; - - return(rval % NHASH); }