--- ray/src/common/caldefn.c 1997/02/12 17:38:03 2.11 +++ ray/src/common/caldefn.c 2023/10/01 18:02:23 2.37 @@ -1,9 +1,6 @@ -/* Copyright (c) 1997 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: caldefn.c,v 2.37 2023/10/01 18:02:23 greg Exp $"; #endif - /* * Store variable definitions. * @@ -22,12 +19,19 @@ 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 "rterror.h" +#include "rtio.h" +#include "rtmisc.h" #include "calcomp.h" #ifndef NHASH @@ -38,9 +42,9 @@ static char SCCSid[] = "$SunId$ LBL"; #define newnode() (EPNODE *)ecalloc(1, sizeof(EPNODE)) -extern char *ecalloc(), *emalloc(), *savestr(), *strcpy(); +static double dvalue(char *name, EPNODE *d); -static double dvalue(); +#define MAXCLOCK (1L<<31) /* clock wrap value */ unsigned long eclock = 0; /* value storage timer */ @@ -51,23 +55,16 @@ static char context[MAXCNTX+1]; /* current context pa 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 = 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; @@ -78,18 +75,27 @@ char *fname; eputs(": cannot open\n"); quit(1); } - initfile(fp, fname, 0); +#ifdef getc_unlocked /* avoid stupid semaphores */ + flockfile(fp); +#endif + initfile(fp, fname, 0); while (nextc != EOF) getstatement(); if (fname != NULL) fclose(fp); +#ifdef getc_unlocked + else + funlockfile(fp); +#endif } -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) @@ -98,34 +104,39 @@ 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; + VARDEF *dp = ep->v.ln; return(dvalue(dp->name, dp->def)); } -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; + EPNODE *ep1, *ep2; /* get qualified name */ qname = qualname(vname, 0); /* check for quick set */ - if ((ep1 = dlookup(qname)) != NULL && ep1->v.kid->type == SYM) { + if ((ep1 = dlookup(qname)) != NULL && ep1->v.kid->type == SYM && + (ep1->type == ':') <= (assign == ':')) { ep2 = ep1->v.kid->sibling; if (ep2->type == NUM) { ep2->v.num = val; @@ -133,6 +144,13 @@ double val; return; } } + if (ep1 != NULL && esupport&E_REDEFW) { + wputs(qname); + if (ep1->type == ':') + wputs(": reset constant expression\n"); + else + wputs(": reset expression\n"); + } /* hand build definition */ ep1 = newnode(); ep1->type = assign; @@ -144,50 +162,63 @@ double val; ep2->type = NUM; ep2->v.num = val; addekid(ep1, ep2); - dremove(qname); + if (assign == ':') + dremove(qname); + else + dclear(qname); dpush(qname, ep1); } -dclear(name) /* delete variable definitions of name */ -char *name; +void +dclear( /* delete variable definitions of name */ + char *name +) { - register EPNODE *ep; + VARDEF *vp; + EPNODE *dp; - while ((ep = dpop(name)) != NULL) { - if (ep->type == ':') { - dpush(name, ep); /* don't clear constants */ - return; - } - epfree(ep); + while ((vp = varlookup(name)) != NULL && + (dp = vp->def) != NULL && dp->type == '=') { + vp->def = dp->sibling; + epfree(dp); + varfree(vp); } } -dremove(name) /* delete all definitions of name */ -char *name; +void +dremove( /* delete all definitions of name */ + char *name +) { - register EPNODE *ep; + EPNODE *ep; while ((ep = dpop(name)) != NULL) epfree(ep); } -vardefined(name) /* return non-zero if variable defined */ -char *name; +int +vardefined( /* return '=' or ':' if variable/constant defined */ + char *name +) { - register EPNODE *dp; + EPNODE *dp = dlookup(name); - return((dp = dlookup(name)) != NULL && dp->v.kid->type == SYM); + if (dp == NULL || dp->v.kid->type != SYM) + return(0); + + return(dp->type); } char * -setcontext(ctx) /* set a new context path */ -register char *ctx; +calcontext( /* set a new context path */ + char *ctx +) { - register char *cpp; + char *cpp; if (ctx == NULL) return(context); /* just asking */ @@ -216,15 +247,15 @@ register char *ctx; char * -pushcontext(ctx) /* push on another context */ -char *ctx; +pushcontext( /* push on another context */ + char *ctx +) { - extern char *strncpy(), *strcpy(); char oldcontext[MAXCNTX+1]; - register int n; + int n; strcpy(oldcontext, context); /* save old context */ - setcontext(ctx); /* set new context */ + calcontext(ctx); /* set new context */ n = strlen(context); /* tack on old */ if (n+strlen(oldcontext) > MAXCNTX) { strncpy(context+n, oldcontext, MAXCNTX-n); @@ -236,9 +267,9 @@ char *ctx; char * -popcontext() /* pop off top context */ +popcontext(void) /* pop off top context */ { - register char *cp1, *cp2; + char *cp1, *cp2; if (!context[0]) /* nothing left to pop */ return(context); @@ -246,30 +277,30 @@ popcontext() /* pop off top context */ while (*++cp2 && *cp2 != CNTXMARK) ; cp1 = context; /* copy tail to front */ - while (*cp1++ = *cp2++) + while ( (*cp1++ = *cp2++) ) ; return(context); } char * -qualname(nam, lvl) /* get qualified name */ -register char *nam; -int lvl; +qualname( /* get qualified name */ + char *nam, + int lvl +) { - static char nambuf[MAXWORD+1]; - register char *cp = nambuf, *cpp; + static char nambuf[RMAXWORD+1]; + char *cp = nambuf, *cpp; /* check for explicit local */ - if (*nam == CNTXMARK) + if (*nam == CNTXMARK) { if (lvl > 0) /* only action is to refuse search */ return(NULL); - else - nam++; - else if (nam == nambuf) /* check for repeat call */ + nam++; + } else if (nam == nambuf) /* check for repeat call */ return(lvl > 0 ? NULL : nam); /* copy name to static buffer */ while (*nam) { - if (cp >= nambuf+MAXWORD) + if (cp >= nambuf+RMAXWORD) goto toolong; *cp++ = *nam++; } @@ -287,8 +318,8 @@ int lvl; while (*++cpp && *cpp != CNTXMARK) ; } - while (*cpp) { /* copy context to static buffer */ - if (cp >= nambuf+MAXWORD) + while (*cpp) { /* add remaining context to name */ + if (cp >= nambuf+RMAXWORD) goto toolong; *cp++ = *cpp++; } @@ -298,8 +329,10 @@ toolong: } -incontext(qn) /* is qualified name in current context? */ -register char *qn; +int +incontext( /* is qualified name in current context? */ + char *qn +) { if (!context[0]) /* global context accepts all */ return(1); @@ -309,48 +342,52 @@ register char *qn; } -#ifdef OUTCHAN -chanout(cs) /* set output channels */ -int (*cs)(); +void +chanout( /* set output channels */ + void (*cs)(int n, double v) +) { - register EPNODE *ep; + EPNODE *ep; for (ep = outchan; ep != NULL; ep = ep->sibling) (*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; - register EPNODE *ep; + int i; + VARDEF *vp; + EPNODE *ep; /* if context is global, clear all */ for (i = 0; i < NHASH; i++) for (vp = hashtbl[i]; vp != NULL; vp = vp->next) - if (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) + } + if (lvl >= 1) + while (outchan != NULL) { + ep = outchan; + outchan = ep->sibling; + ep->sibling = NULL; epfree(ep); - outchan = NULL; - } -#endif + } } EPNODE * -dlookup(name) /* look up a definition */ -char *name; +dlookup( /* look up a definition */ + char *name +) { - register VARDEF *vp; + VARDEF *vp; if ((vp = varlookup(name)) == NULL) return(NULL); @@ -359,12 +396,13 @@ char *name; VARDEF * -varlookup(name) /* look up a variable */ -char *name; +varlookup( /* look up a variable */ + char *name +) { int lvl = 0; - register char *qname; - register VARDEF *vp; + char *qname; + VARDEF *vp; /* find most qualified match */ while ((qname = qualname(name, lvl++)) != NULL) for (vp = hashtbl[hash(qname)]; vp != NULL; vp = vp->next) @@ -375,10 +413,11 @@ 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; + VARDEF *vp; int hv; if ((vp = varlookup(name)) != NULL) { @@ -386,11 +425,7 @@ char *name; return(vp); } vp = (VARDEF *)emalloc(sizeof(VARDEF)); -#ifdef FUNCTION vp->lib = liblookup(name); -#else - vp->lib = NULL; -#endif if (vp->lib == NULL) /* if name not in library */ name = qualname(name, 0); /* use fully qualified version */ hv = hash(name); @@ -403,25 +438,27 @@ char *name; } -#ifdef FUNCTION -libupdate(fn) /* update library links */ -char *fn; +void +libupdate( /* update library links */ + char *fn +) { - register int i; - register VARDEF *vp; + int i; + VARDEF *vp; /* if fn is NULL then relink all */ for (i = 0; i < NHASH; i++) for (vp = hashtbl[i]; vp != NULL; vp = vp->next) - if (vp->lib != NULL || fn == NULL || !strcmp(fn, vp->name)) + 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 */ + VARDEF *ln +) { - register VARDEF *vp; + VARDEF *vp; int hv; if (--ln->nlinks > 0) @@ -437,27 +474,25 @@ register VARDEF *ln; vp->next = ln->next; } freestr(ln->name); - efree((char *)ln); + efree(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; + EPNODE *ep; + char *nm; while (htndx < NHASH) { if (htpos == NULL) @@ -470,22 +505,19 @@ dnext() /* return pointer to next definition */ return(ep); } } -#ifdef OUTCHAN if ((ep = ochpos) != NULL) 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; + VARDEF *vp; + EPNODE *dp; if ((vp = varlookup(name)) == NULL || vp->def == NULL) return(NULL); @@ -496,11 +528,13 @@ char *name; } -dpush(nm, ep) /* push on a definition */ -char *nm; -register EPNODE *ep; +void +dpush( /* push on a definition */ + char *nm, + EPNODE *ep +) { - register VARDEF *vp; + VARDEF *vp; vp = varinsert(nm); ep->sibling = vp->def; @@ -508,12 +542,13 @@ 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; - register EPNODE *ep, *epl; + EPNODE *ep, *epl; for (epl = NULL, ep = outchan; ep != NULL; epl = ep, ep = ep->sibling) if (ep->v.kid->v.chan >= ch) { @@ -536,44 +571,38 @@ EPNODE *sp; sp->sibling = NULL; } -#endif -getstatement() /* get next statement */ +void +getstatement(void) /* get next statement */ { - register EPNODE *ep; + EPNODE *ep; char *qname; - register VARDEF *vdef; + VARDEF *vdef; if (nextc == ';') { /* empty 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) + qname = qualname(dfn_name(ep), 0); + 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 @@ -589,22 +618,22 @@ 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; + EPNODE *ep1, *ep2; - if (!isalpha(nextc) && nextc != CNTXMARK) + if (!isalpha(nextc) & (nextc != CNTXMARK)) syntax("illegal variable name"); ep1 = newnode(); 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); @@ -612,10 +641,12 @@ getdefn() /* A -> SYM = E1 */ do { scan(); if (!isalpha(nextc)) - syntax("illegal variable name"); + syntax("illegal parameter name"); ep2 = newnode(); ep2->type = SYM; ep2->v.name = savestr(getname()); + if (strchr(ep2->v.name, CNTXMARK) != NULL) + syntax("illegal parameter name"); addekid(ep1, ep2); } while (nextc == ','); if (nextc != ')') @@ -623,9 +654,8 @@ getdefn() /* A -> SYM = E1 */ scan(); curfunc = ep1; } -#endif - if (nextc != '=' && nextc != ':') + if ((nextc != '=') & (nextc != ':')) syntax("'=' or ':' expected"); ep2 = newnode(); @@ -634,33 +664,25 @@ 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->type = CLKT; ep1->v.tick = 0; addekid(ep2, ep1); ep1 = newnode(); ep1->type = NUM; addekid(ep2, ep1); } - -#ifdef FUNCTION curfunc = NULL; -#endif return(ep2); } -#ifdef OUTCHAN EPNODE * -getchan() /* A -> $N = E1 */ +getchan(void) /* A -> $N = E1 */ { - register EPNODE *ep1, *ep2; + EPNODE *ep1, *ep2; if (nextc != '$') syntax("missing '$'"); @@ -681,7 +703,6 @@ getchan() /* A -> $N = E1 */ return(ep2); } -#endif @@ -690,12 +711,10 @@ 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; + EPNODE *ep1, *ep2; if (d == NULL || d->v.kid->type != SYM) { eputs(name); @@ -705,9 +724,16 @@ EPNODE *d; ep1 = d->v.kid->sibling; /* get expression */ if (ep1->type == NUM) return(ep1->v.num); /* return if number */ + if (esupport&E_RCONST && d->type == ':') { + wputs(name); + wputs(": assigned non-constant value\n"); + } ep2 = ep1->sibling; /* check time */ - if (ep2->v.tick == 0 || ep2->v.tick < eclock) { - ep2->v.tick = d->type == ':' ? ~0L : 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