--- ray/src/common/caldefn.c 1991/04/24 08:17:22 1.9 +++ ray/src/common/caldefn.c 1991/08/09 08:27:56 1.17 @@ -19,7 +19,9 @@ static char SCCSid[] = "$SunId$ LBL"; * * 5/31/90 Added conditional compile (REDEFW) for redefinition warning. * - * 4/23/91 Added ':' defines for constant expressions (RCONST) + * 4/23/91 Added ':' assignment for constant expressions + * + * 8/7/91 Added optional context path to append to variable names */ #include @@ -34,12 +36,14 @@ static char SCCSid[] = "$SunId$ LBL"; #define newnode() (EPNODE *)ecalloc(1, sizeof(EPNODE)) -extern char *ecalloc(), *savestr(); +extern char *ecalloc(), *savestr(), *strcpy(); static double dvalue(); long eclock = -1; /* value storage timer */ +static char context[MAXWORD]; /* current context path */ + static VARDEF *hashtbl[NHASH]; /* definition list */ static int htndx; /* index for */ static VARDEF *htpos; /* ...dfirst() and */ @@ -72,7 +76,7 @@ char *fname; } initfile(fp, fname, 0); while (nextc != EOF) - loaddefn(); + getstatement(); if (fname != NULL) fclose(fp); } @@ -85,7 +89,7 @@ int ln; { initstr(str, fn, ln); while (nextc != EOF) - loaddefn(); + getstatement(); } @@ -112,9 +116,12 @@ char *vname; int assign; double val; { + char *qname; register EPNODE *ep1, *ep2; + /* get qualified name */ + qname = qualname(vname, 0); /* check for quick set */ - if ((ep1 = dlookup(vname)) != NULL && ep1->v.kid->type == SYM) { + if ((ep1 = dlookup(qname)) != NULL && ep1->v.kid->type == SYM) { ep2 = ep1->v.kid->sibling; if (ep2->type == NUM) { ep2->v.num = val; @@ -133,8 +140,8 @@ double val; ep2->type = NUM; ep2->v.num = val; addekid(ep1, ep2); - dremove(vname); - dpush(ep1); + dremove(qname); + dpush(qname, ep1); } @@ -145,7 +152,7 @@ char *name; while ((ep = dpop(name)) != NULL) { if (ep->type == ':') { - dpush(ep); /* don't clear constants */ + dpush(name, ep); /* don't clear constants */ return; } epfree(ep); @@ -172,6 +179,98 @@ char *name; } +char * +setcontext(ctx) /* set a new context path */ +register char *ctx; +{ + register char *cpp; + + if (ctx == NULL) + return(context); /* just asking */ + if (!*ctx) { + context[0] = '\0'; /* 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-1) { + *cpp = '\0'; + wputs(context); + wputs(": context path too long\n"); + return(NULL); + } + if (isid(*ctx)) + *cpp++ = *ctx++; + else { + *cpp++ = '_'; ctx++; + } + } while (*ctx); + *cpp = '\0'; + return(context); +} + + +char * +qualname(nam, lvl) /* get qualified name */ +register char *nam; +int lvl; +{ + static char nambuf[MAXWORD]; + register char *cp = nambuf, *cpp; + /* check for explicit local */ + if (*nam == CNTXMARK) + if (lvl > 0) /* only action is to refuse search */ + return(NULL); + else + 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-1) + goto toolong; + *cp++ = *nam++; + } + /* check for explicit global */ + if (cp > nambuf && cp[-1] == CNTXMARK) { + if (lvl > 0) + return(NULL); + *--cp = '\0'; + return(nambuf); /* already qualified */ + } + cpp = context; /* else skip the requested levels */ + while (lvl-- > 0) { + if (!*cpp) + return(NULL); /* return NULL if past global level */ + while (*++cpp && *cpp != CNTXMARK) + ; + } + while (*cpp) { /* copy context to static buffer */ + if (cp >= nambuf+MAXWORD-1) + goto toolong; + *cp++ = *cpp++; + } + *cp = '\0'; + return(nambuf); /* return qualified name */ +toolong: + *cp = '\0'; + eputs(nambuf); + eputs(": name too long\n"); + quit(1); +} + + +incontext(qn) /* is qualified name in current context? */ +register char *qn; +{ + while (*qn && *qn != CNTXMARK) /* find context mark */ + ; + return(!strcmp(qn, context)); +} + + #ifdef OUTCHAN chanout(cs) /* set output channels */ int (*cs)(); @@ -185,21 +284,22 @@ int (*cs)(); #endif -dcleanup(cons, ochans) /* clear definitions */ -int cons, ochans; +dcleanup(lvl) /* clear definitions (0->vars,1->output,2->consts) */ +int lvl; { register int i; register VARDEF *vp; register EPNODE *ep; - + /* if context is global, clear all */ for (i = 0; i < NHASH; i++) for (vp = hashtbl[i]; vp != NULL; vp = vp->next) - if (cons) - dremove(vp->name); - else - dclear(vp->name); + if (!context[0] || incontext(vp->name)) + if (lvl >= 2) + dremove(vp->name); + else + dclear(vp->name); #ifdef OUTCHAN - if (ochans) { + if (lvl >= 1) { for (ep = outchan; ep != NULL; ep = ep->sibling) epfree(ep); outchan = NULL; @@ -224,11 +324,14 @@ VARDEF * varlookup(name) /* look up a variable */ char *name; { + int lvl = 0; + register char *qname; register VARDEF *vp; - - for (vp = hashtbl[hash(name)]; vp != NULL; vp = vp->next) - if (!strcmp(vp->name, name)) - return(vp); + /* 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)) + return(vp); return(NULL); } @@ -238,19 +341,26 @@ varinsert(name) /* get a link to a variable */ char *name; { register VARDEF *vp; + LIBR *libp; 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 */ + name = qualname(name, 0); /* use fully qualified version */ hv = hash(name); - for (vp = hashtbl[hv]; vp != NULL; vp = vp->next) - if (!strcmp(vp->name, name)) { - vp->nlinks++; - return(vp); - } vp = (VARDEF *)emalloc(sizeof(VARDEF)); vp->name = savestr(name); vp->nlinks = 1; vp->def = NULL; - vp->lib = NULL; + vp->lib = libp; vp->next = hashtbl[hv]; hashtbl[hv] = vp; return(vp); @@ -333,12 +443,13 @@ char *name; } -dpush(ep) /* push on a definition */ +dpush(nm, ep) /* push on a definition */ +char *nm; register EPNODE *ep; { register VARDEF *vp; - vp = varinsert(dname(ep)); + vp = varinsert(nm); ep->sibling = vp->def; vp->def = ep; } @@ -375,9 +486,11 @@ EPNODE *sp; #endif -loaddefn() /* load next definition */ +getstatement() /* get next statement */ { register EPNODE *ep; + char *qname; + register VARDEF *vdef; if (nextc == ';') { /* empty statement */ scan(); @@ -391,26 +504,28 @@ loaddefn() /* load next definition */ #endif { /* ordinary definition */ ep = getdefn(); + qname = qualname(dname(ep), 0); #ifdef REDEFW - if (dlookup(dname(ep)) != NULL) { - dclear(dname(ep)); - wputs(dname(ep)); - if (dlookup(dname(ep)) == NULL) - wputs(": redefined\n"); - else - wputs(": redefined constant expression\n"); - } + if ((vdef = varlookup(qname)) != NULL) + if (vdef->def != NULL) { + wputs(qname); + if (vdef->def->type == ':') + wputs(": redefined constant expression\n"); + else + wputs(": redefined\n"); + } #ifdef FUNCTION - else if (ep->v.kid->type == FUNC && - liblookup(ep->v.kid->v.kid->v.name) != NULL) { - wputs(ep->v.kid->v.kid->v.name); - wputs(": redefined library function\n"); - } + else if (ep->v.kid->type == FUNC && vdef->lib != NULL) { + wputs(qname); + wputs(": definition hides library function\n"); + } #endif -#else - dclear(dname(ep)); #endif - dpush(ep); + if (ep->type == ':') + dremove(qname); + else + dclear(qname); + dpush(qname, ep); } if (nextc != EOF) { if (nextc != ';') @@ -465,15 +580,6 @@ getdefn() /* A -> SYM = E1 */ ep2->type = nextc; scan(); addekid(ep2, ep1); -#ifdef RCONST - if ( -#ifdef FUNCTION - ep1->type == SYM && -#endif - ep2->type == ':') - addekid(ep2, rconst(getE1())); - else -#endif addekid(ep2, getE1()); if (