V9/cmd/sh/name.c
/* @(#)name.c 1.5 */
/*
* UNIX shell
*
* Bell Telephone Laboratories
*
*/
#include "defs.h"
#include "sym.h"
extern BOOL chkid();
extern char *simple();
static int namwalk();
struct namnod ps2nod =
{
(struct namnod *)NIL,
&acctnod,
ps2name
};
struct namnod cdpnod =
{
(struct namnod *)NIL,
(struct namnod *)NIL,
cdpname
};
struct namnod ifsnod =
{
(struct namnod *)NIL,
(struct namnod *)NIL,
ifsname
};
struct namnod ps1nod =
{
&pathnod,
&ps2nod,
ps1name
};
struct namnod histnod =
{
&cdpnod,
(struct namnod *)NIL,
histname
};
struct namnod homenod =
{
&histnod,
&ifsnod,
homename
};
struct namnod pathnod =
{
(struct namnod *)NIL,
(struct namnod *)NIL,
pathname
};
struct namnod mailnod =
{
&homenod,
&ps1nod,
mailname
};
struct namnod acctnod =
{
(struct namnod *)NIL,
(struct namnod *)NIL,
acctname
};
struct namnod *namep = &mailnod;
/* ======== variable and string handling ======== */
syslook(w, syswds, n)
register char *w;
register struct sysnod syswds[];
int n;
{
int low;
int high;
int mid;
register int cond;
if (w == 0 || *w == 0)
return(0);
low = 0;
high = n - 1;
while (low <= high)
{
mid = (low + high) / 2;
if ((cond = cf(w, syswds[mid].sysnam)) < 0)
high = mid - 1;
else if (cond > 0)
low = mid + 1;
else
return(syswds[mid].sysval);
}
return(0);
}
setlist(arg, xp)
register struct argnod *arg;
int xp;
{
if (flags & exportflg)
xp |= N_EXPORT;
while (arg)
{
register char *s = mactrim(arg->argval);
setname(s, xp);
arg = arg->argnxt;
if (flags & execpr)
{
prs(s);
if (arg)
blank();
else
newline();
}
}
}
setname(argi, xp) /* does parameter assignments */
char *argi;
int xp;
{
register char *argscan = argi;
register struct namnod *n;
while(!ctrlchar(*argscan))
{
if (*argscan == '=')
{
*argscan = 0; /* make name a cohesive string */
n = lookup(argi);
*argscan++ = '=';
attrib(n, xp);
if (xp & N_ENVNAM)
n->namenv.val = n->namval.val = argscan;
else
assign(n, argscan);
return;
}
if ((xp & N_ENVNAM) && *argscan == '(')
{
/*
* flags==0 when we are called, so flags&ttyflg==0, so
* if there's an error we will exit
*/
execexp(argi, 0);
*argscan = 0;
n = lookup(argi);
attrib(n, xp);
return;
}
argscan++;
}
failed(argi, notid);
}
replace(a, v)
register char **a;
char *v;
{
shfree(*a);
*a = make(v);
}
dfault(n, v)
struct namnod *n;
char *v;
{
if (n->namval.val == 0)
assign(n, v);
}
assign(n, v)
struct namnod *n;
char *v;
{
if (!(n->namflg & N_ENVNAM))
free_val(&n->namval);
else
n->namflg &= ~N_ENVNAM;
n->namval.val = make(v);
n->namval.flg = N_VAR;
if (flags & prompt)
if (n == &mailnod)
setmail(n->namval.val);
}
readvar(names)
char **names;
{
struct fileblk fb;
register struct fileblk *f = &fb;
register char c;
register int rc = 0;
struct namnod *n = lookup(*names++); /* done now to avoid storage mess */
char *rel = (char *)relstak();
push(f);
initf(dup(0));
if (lseek(0, 0L, 1) == -1)
f->fsiz = 1;
/*
* strip leading IFS characters
*/
while ((any((c = nextc(0)), ifsnod.namval.val)) && !(eolchar(c)))
;
for (;;)
{
if ((*names && any(c, ifsnod.namval.val)) || eolchar(c))
{
zerostak();
assign(n, absstak(rel));
setstak(rel);
if (*names)
n = lookup(*names++);
else
n = 0;
if (eolchar(c))
{
break;
}
else /* strip imbedded IFS characters */
{
while ((any((c = nextc(0)), ifsnod.namval.val)) &&
!(eolchar(c)))
;
}
}
else
{
pushstak(c);
c = nextc(0);
if (eolchar(c))
{
char *top = staktop;
while (any(*(--top), ifsnod.namval.val))
;
staktop = top + 1;
}
}
}
while (n)
{
assign(n, nullstr);
if (*names)
n = lookup(*names++);
else
n = 0;
}
if (eof)
rc = 1;
lseek(0, (long)(f->fnxt - f->fend), 1);
pop();
return(rc);
}
assnum(p, i)
char **p;
int i;
{
itos(i);
replace(p, numbuf);
}
char *
make(v)
char *v;
{
register char *p;
if (v)
{
movstr(v, p = shalloc(length(v)));
return(p);
}
else
return(0);
}
struct namnod *
lookup(nam)
register char *nam;
{
register struct namnod *nscan = namep;
register struct namnod **prev;
int LR;
if (!chkid(nam))
failed(nam, notid);
while (nscan)
{
if ((LR = cf(nam, nscan->namid)) == 0)
return(nscan);
else if (LR < 0)
prev = &(nscan->namlft);
else
prev = &(nscan->namrgt);
nscan = *prev;
}
/*
* add name node
*/
nscan = (struct namnod *)shalloc(sizeof *nscan);
nscan->namlft = nscan->namrgt = (struct namnod *)NIL;
nscan->namid = make(nam);
nscan->namval.val = 0;
nscan->namval.flg = N_VAR;
nscan->namenv.val = 0;
nscan->namenv.flg = N_VAR;
nscan->namflg = N_DEFAULT;
return(*prev = nscan);
}
BOOL
chkid(nam)
register char *nam;
{
if(!nam) return 0;
while(!ctrlchar(*nam) && (*nam"E)==0 && *nam!='(' && *nam!='=')
nam++;
return *nam==0;
}
static int (*namfn)();
namscan(fn)
int (*fn)();
{
namfn = fn;
namwalk(namep);
}
static int
namwalk(np)
register struct namnod *np;
{
if (np)
{
namwalk(np->namlft);
(*namfn)(np);
namwalk(np->namrgt);
}
}
printnam(n)
struct namnod *n;
{
register char *s;
sigchk();
if (n->namval.flg & N_FUNCTN) {
prs_buff(strf(n));
prc_buff(NL);
}
else if (s = n->namval.val)
{
prs_buff(n->namid);
prc_buff('=');
prs_buff(quotedstring(s));
prc_buff(NL);
}
}
pushstr(s)
register char *s;
{
do
pushstak(*s);
while(*s++);
--staktop;
}
char *
staknam(n)
register struct namnod *n;
{
register char *p;
register char *q;
if (n->namval.flg & N_FUNCTN)
pushstr(strf(n));
else
{
pushstr(n->namid);
pushstak('=');
pushstr(n->namval.val);
}
return(getstak(staktop + 1 - (char *)(stakbot)));
}
static int namec;
exname(n)
register struct namnod *n;
{
register int flg = n->namflg;
if (!(flg & N_ENVNAM))
{
n->namflg |= N_ENVNAM;
if (flg & N_EXPORT)
{
free_val(&n->namenv);
n->namenv = n->namval;
}
else
{
free_val(&n->namval);
n->namval = n->namenv;
}
}
n->namflg &= N_ENVNAM;
if (n->namval.val)
namec++;
}
printexp(n)
register struct namnod *n;
{
if (n->namflg & N_EXPORT)
{
prs_buff(export);
prc_buff(SP);
prs_buff(n->namid);
prc_buff(NL);
}
}
setup_env()
{
register char **e = environ;
while (*e)
setname(*e++, N_ENVNAM);
}
killenvfn(n)
struct namnod *n;
{
if ((n->namflg & N_ENVNAM) && (n->namval.flg & N_FUNCTN))
{
freefunc(n->namval.val);
n->namval.val = N_VAR;
n->namval.flg = 0;
}
}
prot_env()
{
register struct namnod *n;
namscan(killenvfn);
if (ifsnod.namval.val)
shfree(ifsnod.namval.val);
ifsnod.namval.val = 0;
dfault(&ifsnod, sptbnl);
}
static char **argnam;
pushnam(n)
struct namnod *n;
{
if (n->namval.val || (n->namval.flg & N_FUNCTN))
*argnam++ = staknam(n);
}
char **
setenv()
{
register char **er;
namec = 0;
namscan(exname);
argnam = er = (char **)getstak(namec * BYTESPERWORD + BYTESPERWORD);
namscan(pushnam);
*argnam++ = 0;
return(er);
}
struct namnod *
findnam(nam)
register char *nam;
{
register struct namnod *nscan = namep;
int LR;
if (!chkid(nam))
return(0);
while (nscan)
{
if ((LR = cf(nam, nscan->namid)) == 0)
return(nscan);
else if (LR < 0)
nscan = nscan->namlft;
else
nscan = nscan->namrgt;
}
return(0);
}
special(s)
char *s;
{
return !cf(s, "builtin") || !cf(s, ifsname) || !cf(s, pathname) || !cf(s, ps1name) || !cf(s, ps2name);
}
unset_name(name)
register char *name;
{
register struct namnod *n;
if (n = findnam(name))
{
if (special(name))
failed(name, badunset);
if (!(n->namflg & N_ENVNAM))
{
if (n->namval.flg & N_FUNCTN)
freefunc(n->namval.val);
else
shfree(n->namval.val);
}
if (n->namenv.flg & N_FUNCTN)
freefunc(n->namenv.val);
else
shfree(n->namenv.val);
n->namval.val = N_VAR;
n->namval.flg = 0;
n->namenv = n->namval;
n->namflg = N_DEFAULT;
if (flags & prompt)
{
if (n == &mailnod)
setmail(0);
}
}
}
free_val(nx)
struct namx *nx;
{
if (nx->flg & N_FUNCTN)
freefunc(nx->val);
else
shfree(nx->val);
}