--- ray/src/common/caldefn.c 2012/07/29 22:10:45 2.25 +++ ray/src/common/caldefn.c 2024/02/23 03:47:57 2.38 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: caldefn.c,v 2.25 2012/07/29 22:10:45 greg Exp $"; +static const char RCSid[] = "$Id: caldefn.c,v 2.38 2024/02/23 03:47:57 greg Exp $"; #endif /* * Store variable definitions. @@ -27,8 +27,6 @@ static const char RCSid[] = "$Id: caldefn.c,v 2.25 201 #include "copyright.h" -#include -#include #include #include "rterror.h" @@ -60,10 +58,9 @@ static VARDEF *htpos; /* ...dfirst() and */ static EPNODE *ochpos; /* ...dnext */ static EPNODE *outchan; +static int optimized = 0; /* are we optimized? */ + EPNODE *curfunc = NULL; -#define dname(ep) ((ep)->v.kid->type == SYM ? \ - (ep)->v.kid->v.name : \ - (ep)->v.kid->v.kid->v.name) void @@ -80,11 +77,18 @@ fcompile( /* get definitions from a file */ 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 } @@ -142,6 +146,13 @@ varset( /* set a variable's value */ 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; @@ -166,14 +177,14 @@ dclear( /* delete variable definitions of name */ char *name ) { - 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,1); + varfree(vp); } } @@ -186,23 +197,26 @@ dremove( /* delete all definitions of name */ EPNODE *ep; while ((ep = dpop(name)) != NULL) - epfree(ep); + epfree(ep,1); } int -vardefined( /* return non-zero if variable defined */ +vardefined( /* return '=' or ':' if variable/constant defined */ char *name ) { - 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( /* set a new context path */ +calcontext( /* set a new context path */ char *ctx ) { @@ -243,7 +257,7 @@ pushcontext( /* push on another context */ 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); @@ -280,12 +294,11 @@ qualname( /* get qualified name */ 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) { @@ -307,7 +320,7 @@ qualname( /* get qualified name */ while (*++cpp && *cpp != CNTXMARK) ; } - while (*cpp) { /* copy context to static buffer */ + while (*cpp) { /* add remaining context to name */ if (cp >= nambuf+RMAXWORD) goto toolong; *cp++ = *cpp++; @@ -345,6 +358,22 @@ chanout( /* set output channels */ void +doptimize(int activate) /* optimize current and future definitions? */ +{ + EPNODE *ep; + + if (activate && optimized) + return; /* already going */ + + if (!(optimized = activate)) + return; /* switching off */ + + for (ep = dfirst(); ep != NULL; ep = dnext()) + epoptimize(ep); +} + + +void dcleanup( /* clear definitions (0->vars,1->output,2->consts) */ int lvl ) @@ -361,11 +390,12 @@ dcleanup( /* clear definitions (0->vars,1->output,2-> else dclear(vp->name); } - if (lvl >= 1) { - for (ep = outchan; ep != NULL; ep = ep->sibling) - epfree(ep); - outchan = NULL; - } + if (lvl >= 1) + while (outchan != NULL) { + ep = outchan; + outchan = ep->sibling; + epfree(ep,1); + } } @@ -435,7 +465,7 @@ libupdate( /* update library links */ /* 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); } @@ -461,7 +491,7 @@ varfree( /* release link to variable */ vp->next = ln->next; } freestr(ln->name); - efree((char *)ln); + efree(ln); } @@ -547,7 +577,7 @@ addchan( /* add an output channel assignment */ sp->sibling = ep; else { sp->sibling = ep->sibling; - epfree(ep); + epfree(ep,1); } return; } @@ -577,7 +607,7 @@ getstatement(void) /* get next statement */ addchan(ep); } else { /* ordinary definition */ ep = getdefn(); - qname = qualname(dname(ep), 0); + qname = qualname(dfn_name(ep), 0); if (esupport&E_REDEFW && (vdef = varlookup(qname)) != NULL) { if (vdef->def != NULL && epcmp(ep, vdef->def)) { wputs(qname); @@ -601,6 +631,8 @@ getstatement(void) /* get next statement */ syntax("';' expected"); scan(); } + if (optimized) + epoptimize(ep); /* optimize new statement */ } @@ -613,7 +645,7 @@ getdefn(void) { EPNODE *ep1, *ep2; - if (!isalpha(nextc) && nextc != CNTXMARK) + if (!isalpha(nextc) & (nextc != CNTXMARK)) syntax("illegal variable name"); ep1 = newnode(); @@ -632,6 +664,8 @@ getdefn(void) 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 != ')') @@ -640,7 +674,7 @@ getdefn(void) curfunc = ep1; } - if (nextc != '=' && nextc != ':') + if ((nextc != '=') & (nextc != ':')) syntax("'=' or ':' expected"); ep2 = newnode(); @@ -697,7 +731,7 @@ getchan(void) /* A -> $N = E1 */ static double /* evaluate a variable */ -dvalue(char *name, EPNODE *d) +dvalue(char *name, EPNODE *d) { EPNODE *ep1, *ep2; @@ -709,6 +743,10 @@ dvalue(char *name, 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 (eclock >= MAXCLOCK) eclock = 1; /* wrap clock counter */