1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-11-27 15:01:00 +01:00

zsh-workers/9332

This commit is contained in:
Tanaka Akira 2000-01-17 18:25:25 +00:00
parent cf10e60524
commit 63acd10601
21 changed files with 2472 additions and 1356 deletions

View file

@ -143,7 +143,7 @@ math_length(char *name, char *arg, int id)
/**/
static int
ex_wrapper(List list, FuncWrap w, char *name)
ex_wrapper(Eprog prog, FuncWrap w, char *name)
{
if (strncmp(name, "example", 7))
return 1;
@ -151,7 +151,7 @@ ex_wrapper(List list, FuncWrap w, char *name)
int ogd = opts[GLOBDOTS];
opts[GLOBDOTS] = 1;
runshfunc(list, w, name);
runshfunc(prog, w, name);
opts[GLOBDOTS] = ogd;
return 0;

View file

@ -339,23 +339,23 @@ setfunction(char *name, char *val, int dis)
{
char *value = dupstring(val);
Shfunc shf;
List list;
Eprog prog;
int sn;
val = metafy(val, strlen(val), META_REALLOC);
HEAPALLOC {
list = parse_string(val, 1);
prog = parse_string(val, 1);
} LASTALLOC;
if (!list || list == &dummy_list) {
if (!prog || prog == &dummy_eprog) {
zwarn("invalid function definition", value, 0);
zsfree(val);
return;
}
PERMALLOC {
shf = (Shfunc) zalloc(sizeof(*shf));
shf->funcdef = (List) dupstruct(list);
shf->funcdef = dupeprog(prog);
shf->flags = dis;
if (!strncmp(name, "TRAP", 4) &&
@ -463,8 +463,7 @@ getfunction(HashTable ht, char *name, int dis)
((shf->flags & PM_TAGGED) ? "Ut" : "U") :
((shf->flags & PM_TAGGED) ? "t" : "")));
} else {
char *t = getpermtext((void *) dupstruct((void *)
shf->funcdef)), *h;
char *t = getpermtext(shf->funcdef, NULL), *h;
h = dupstring(t);
zsfree(t);
@ -528,8 +527,7 @@ scanfunctions(HashTable ht, ScanFunc func, int flags, int dis)
((shf->flags & PM_TAGGED) ? "Ut" : "U") :
((shf->flags & PM_TAGGED) ? "t" : "")));
} else {
char *t = getpermtext((void *)
dupstruct((void *) ((Shfunc) hn)->funcdef));
char *t = getpermtext(((Shfunc) hn)->funcdef, NULL);
pm.u.str = dupstring(t);
unmetafy(pm.u.str, NULL);
@ -577,13 +575,13 @@ funcstackgetfn(Param pm)
/**/
static int
func_wrapper(List list, FuncWrap w, char *name)
func_wrapper(Eprog prog, FuncWrap w, char *name)
{
PERMALLOC {
pushnode(funcstack, ztrdup(name));
} LASTALLOC;
runshfunc(list, w, name);
runshfunc(prog, w, name);
DPUTS(strcmp(name, (char *) getdata(firstnode(funcstack))),
"funcstack wrapper with wrong function");

View file

@ -1600,9 +1600,9 @@ zfsenddata(char *name, int recv, int progress, off_t startat)
char lsbuf[ZF_BUFSIZE], *ascbuf = NULL, *optr;
off_t sofar = 0, last_sofar = 0;
readwrite_t read_ptr = zfread, write_ptr = zfwrite;
List l;
Eprog prog;
if (progress && (l = getshfunc("zftp_progress")) != &dummy_list) {
if (progress && (prog = getshfunc("zftp_progress")) != &dummy_eprog) {
/*
* progress to set up: ZFTP_COUNT is zero.
* We do this here in case we needed to wait for a RETR
@ -1611,7 +1611,7 @@ zfsenddata(char *name, int recv, int progress, off_t startat)
int osc = sfcontext;
sfcontext = SFC_HOOK;
doshfunc("zftp_progress", l, NULL, 0, 1);
doshfunc("zftp_progress", prog, NULL, 0, 1);
sfcontext = osc;
/* Now add in the bit of the file we've got/sent already */
sofar = last_sofar = startat;
@ -1739,12 +1739,12 @@ zfsenddata(char *name, int recv, int progress, off_t startat)
} else
break;
if (!ret && sofar != last_sofar && progress &&
(l = getshfunc("zftp_progress")) != &dummy_list) {
(prog = getshfunc("zftp_progress")) != &dummy_eprog) {
int osc = sfcontext;
zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER);
sfcontext = SFC_HOOK;
doshfunc("zftp_progress", l, NULL, 0, 1);
doshfunc("zftp_progress", prog, NULL, 0, 1);
sfcontext = osc;
last_sofar = sofar;
}
@ -2444,7 +2444,7 @@ zfgetcwd(void)
{
char *ptr, *eptr;
int endc;
List l;
Eprog prog;
if (zfprefs & ZFPF_DUMB)
return 1;
@ -2471,11 +2471,11 @@ zfgetcwd(void)
* front end. By putting it here, and in close when ZFTP_PWD is unset,
* we at least cover the bases.
*/
if ((l = getshfunc("zftp_chpwd")) != &dummy_list) {
if ((prog = getshfunc("zftp_chpwd")) != &dummy_eprog) {
int osc = sfcontext;
sfcontext = SFC_HOOK;
doshfunc("zftp_chpwd", l, NULL, 0, 1);
doshfunc("zftp_chpwd", prog, NULL, 0, 1);
sfcontext = osc;
}
return 0;
@ -2629,7 +2629,7 @@ zftp_getput(char *name, char **args, int flags)
{
int ret = 0, recv = (flags & ZFTP_RECV), getsize = 0, progress = 1;
char *cmd = recv ? "RETR " : (flags & ZFTP_APPE) ? "APPE " : "STOR ";
List l;
Eprog prog;
/*
* At this point I'd like to set progress to 0 if we're
@ -2647,7 +2647,7 @@ zftp_getput(char *name, char **args, int flags)
for (; *args; args++) {
char *ln, *rest = NULL;
off_t startat = 0;
if (progress && (l = getshfunc("zftp_progress")) != &dummy_list) {
if (progress && (prog = getshfunc("zftp_progress")) != &dummy_eprog) {
off_t sz;
/*
* This calls the SIZE command to get the size for remote
@ -2688,14 +2688,14 @@ zftp_getput(char *name, char **args, int flags)
* if and only if we called zfsenddata();
*/
if (progress && ret != 2 &&
(l = getshfunc("zftp_progress")) != &dummy_list) {
(prog = getshfunc("zftp_progress")) != &dummy_eprog) {
/* progress to finish: ZFTP_TRANSFER set to GF or PF */
int osc = sfcontext;
zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"),
ZFPM_READONLY);
sfcontext = SFC_HOOK;
doshfunc("zftp_progress", l, NULL, 0, 1);
doshfunc("zftp_progress", prog, NULL, 0, 1);
sfcontext = osc;
}
if (rest) {
@ -2795,7 +2795,7 @@ static void
zfclose(int leaveparams)
{
char **aptr;
List l;
Eprog prog;
if (zfsess->cfd == -1)
return;
@ -2837,11 +2837,11 @@ zfclose(int leaveparams)
zfunsetparam(*aptr);
/* Now ZFTP_PWD is unset. It's up to zftp_chpwd to notice. */
if ((l = getshfunc("zftp_chpwd")) != &dummy_list) {
if ((prog = getshfunc("zftp_chpwd")) != &dummy_eprog) {
int osc = sfcontext;
sfcontext = SFC_HOOK;
doshfunc("zftp_chpwd", l, NULL, 0, 1);
doshfunc("zftp_chpwd", prog, NULL, 0, 1);
sfcontext = osc;
}
}

View file

@ -214,7 +214,7 @@ bin_zprof(char *nam, char **args, char *ops, int func)
/**/
static int
zprof_wrapper(List list, FuncWrap w, char *name)
zprof_wrapper(Eprog prog, FuncWrap w, char *name)
{
struct sfunc sf, *sp;
Pfunc f;
@ -257,7 +257,7 @@ zprof_wrapper(List list, FuncWrap w, char *name)
gettimeofday(&tv, &dummy);
sf.beg = prev = ((((double) tv.tv_sec) * 1000.0) +
(((double) tv.tv_usec) / 1000.0));
runshfunc(list, w, name);
runshfunc(prog, w, name);
tv.tv_sec = tv.tv_usec = 0;
gettimeofday(&tv, &dummy);

View file

@ -491,11 +491,11 @@ after_complete(Hookdef dummy, Compldat dat)
static void
callcompfunc(char *s, char *fn)
{
List list;
Eprog prog;
int lv = lastval;
char buf[20];
if ((list = getshfunc(fn)) != &dummy_list) {
if ((prog = getshfunc(fn)) != &dummy_eprog) {
char **p, *tmp;
int aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext;
unsigned int rset, kset;
@ -724,7 +724,7 @@ callcompfunc(char *s, char *fn)
while (*p)
addlinknode(largs, dupstring(*p++));
}
doshfunc(fn, list, largs, 0, 0);
doshfunc(fn, prog, largs, 0, 0);
cfret = lastval;
lastval = olv;
} OLDHEAPS;

View file

@ -3431,12 +3431,12 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
}
if (cc->func) {
/* This handles the compctl -K flag. */
List list;
Eprog prog;
char **r;
int lv = lastval;
/* Get the function. */
if ((list = getshfunc(cc->func)) != &dummy_list) {
if ((prog = getshfunc(cc->func)) != &dummy_eprog) {
/* We have it, so build a argument list. */
LinkList args = newlinklist();
int osc = sfcontext;
@ -3460,7 +3460,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
incompctlfunc = 1;
sfcontext = SFC_COMPLETE;
/* Call the function. */
doshfunc(cc->func, list, args, 0, 1);
doshfunc(cc->func, prog, args, 0, 1);
sfcontext = osc;
incompctlfunc = 0;
/* And get the result from the reply parameter. */
@ -3601,12 +3601,12 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
/* generate the user-defined display list: if anything fails, *
* we silently allow the normal completion list to be used. */
char **yaptr = NULL, *uv = NULL;
List list;
Eprog prog;
if (cc->ylist[0] == '$' || cc->ylist[0] == '(') {
/* from variable */
uv = cc->ylist + (cc->ylist[0] == '$');
} else if ((list = getshfunc(cc->ylist)) != &dummy_list) {
} else if ((prog = getshfunc(cc->ylist)) != &dummy_eprog) {
/* from function: pass completions as arg list */
LinkList args = newlinklist();
LinkNode ln;
@ -3630,7 +3630,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
if (incompfunc != 1)
incompctlfunc = 1;
sfcontext = SFC_COMPLETE;
doshfunc(cc->ylist, list, args, 0, 1);
doshfunc(cc->ylist, prog, args, 0, 1);
sfcontext = osc;
incompctlfunc = 0;
uv = "reply";

View file

@ -1177,7 +1177,7 @@ comp_setunset(int rset, int runset, int kset, int kunset)
/**/
static int
comp_wrapper(List list, FuncWrap w, char *name)
comp_wrapper(Eprog prog, FuncWrap w, char *name)
{
if (incompfunc != 1)
return 1;
@ -1214,7 +1214,7 @@ comp_wrapper(List list, FuncWrap w, char *name)
owords = arrdup(compwords);
} LASTALLOC;
runshfunc(list, w, name);
runshfunc(prog, w, name);
if (comprestore && !strcmp(comprestore, "auto")) {
compcurrent = ocur;

View file

@ -649,9 +649,9 @@ execzlefunc(Thingy func, char **args)
lastcmd = wflags;
r = 1;
} else {
List l = getshfunc(w->u.fnnam);
Eprog prog = getshfunc(w->u.fnnam);
if(l == &dummy_list) {
if(prog == &dummy_eprog) {
/* the shell function doesn't exist */
char *nm = niceztrdup(w->u.fnnam);
char *msg = tricat("No such shell function `", nm, "'");
@ -673,7 +673,7 @@ execzlefunc(Thingy func, char **args)
startparamscope();
makezleparams(0);
sfcontext = SFC_WIDGET;
doshfunc(w->u.fnnam, l, largs, 0, 0);
doshfunc(w->u.fnnam, prog, largs, 0, 0);
ret = lastval;
lastval = olv;
sfcontext = osc;

View file

@ -925,9 +925,9 @@ mod_export void
iremovesuffix(int c, int keep)
{
if (suffixfunc) {
List l = getshfunc(suffixfunc);
Eprog prog = getshfunc(suffixfunc);
if (l != &dummy_list) {
if (prog != &dummy_eprog) {
LinkList args = newlinklist();
char buf[20];
int osc = sfcontext;
@ -939,7 +939,7 @@ iremovesuffix(int c, int keep)
startparamscope();
makezleparams(0);
sfcontext = SFC_COMPLETE;
doshfunc(suffixfunc, l, args, 0, 1);
doshfunc(suffixfunc, prog, args, 0, 1);
sfcontext = osc;
endparamscope();
}

View file

@ -971,7 +971,7 @@ cd_try_chdir(char *pfix, char *dest, int hard)
static void
cd_new_pwd(int func, LinkNode dir)
{
List l;
Eprog prog;
char *new_pwd, *s;
int dirstacksize;
@ -1015,13 +1015,13 @@ cd_new_pwd(int func, LinkNode dir)
}
/* execute the chpwd function */
if ((l = getshfunc("chpwd")) != &dummy_list) {
if ((prog = getshfunc("chpwd")) != &dummy_eprog) {
int osc = sfcontext;
fflush(stdout);
fflush(stderr);
sfcontext = SFC_HOOK;
doshfunc("chpwd", l, NULL, 0, 1);
doshfunc("chpwd", prog, NULL, 0, 1);
sfcontext = osc;
}
@ -2003,7 +2003,7 @@ eval_autoload(Shfunc shf, char *name, char *ops, int func)
return 1;
if (shf->funcdef)
freestruct(shf->funcdef);
freeeprog(shf->funcdef);
if (ops['X'] == 1) {
char *fargv[3];
@ -2140,30 +2140,27 @@ bin_functions(char *name, char **argv, char *ops, int func)
}
/**/
static List
static Eprog
mkautofn(Shfunc shf)
{
List l;
Sublist s;
Pline p;
Cmd c;
AutoFn a;
PERMALLOC {
a = (AutoFn)allocnode(N_AUTOFN);
a->shf = shf;
c = (Cmd)allocnode(N_CMD);
c->type = AUTOFN;
c->u.autofn = a;
p = (Pline)allocnode(N_PLINE);
p->left = c;
p->type = END;
s = (Sublist)allocnode(N_SUBLIST);
s->left = p;
l = (List)allocnode(N_LIST);
l->left = s;
l->type = Z_SYNC;
} LASTALLOC;
return l;
Eprog p;
p = (Eprog) zalloc(sizeof(*p));
p->len = 5 * sizeof(wordcode);
p->prog = (Wordcode) zalloc(p->len);
p->strs = NULL;
p->shf = shf;
p->npats = 0;
p->pats = NULL;
p->heap = 0;
p->prog[0] = WCB_LIST(Z_SYNC | Z_END);
p->prog[1] = WCB_SUBLIST(WC_SUBLIST_END, 0, 3);
p->prog[2] = WCB_PIPE(WC_PIPE_END, 0);
p->prog[3] = WCB_AUTOFN();
p->prog[4] = WCB_END();
return p;
}
/* unset: unset parameters */
@ -3328,14 +3325,14 @@ bin_emulate(char *nam, char **argv, char *ops, int func)
int
bin_eval(char *nam, char **argv, char *ops, int func)
{
List list;
Eprog prog;
list = parse_string(zjoin(argv, ' '), 0);
if (!list) {
prog = parse_string(zjoin(argv, ' '), 0);
if (!prog) {
errflag = 0;
return 1;
}
execlist(list, 1, 0);
execode(prog, 1, 0);
if (errflag) {
lastval = errflag;
errflag = 0;
@ -3761,7 +3758,8 @@ int
bin_test(char *name, char **argv, char *ops, int func)
{
char **s;
Cond c;
Eprog prog;
struct estate state;
/* if "test" was invoked as "[", it needs a matching "]" *
* which is subsequently ignored */
@ -3781,7 +3779,7 @@ bin_test(char *name, char **argv, char *ops, int func)
tok = NULLTOK;
condlex = testlex;
testlex();
c = par_cond();
prog = parse_cond();
condlex = yylex;
if (errflag) {
@ -3789,13 +3787,19 @@ bin_test(char *name, char **argv, char *ops, int func)
return 1;
}
if (!c || tok == LEXERR) {
if (!prog || tok == LEXERR) {
zwarnnam(name, tokstr ? "parse error" : "argument expected", NULL, 0);
return 1;
}
/* syntax is OK, so evaluate */
return !evalcond(c);
state.prog = prog;
state.pc = prog->prog;
state.strs = prog->strs;
return !evalcond(&state);
}
/* display a time, provided in units of 1/60s, as minutes and seconds */
@ -3830,7 +3834,7 @@ bin_times(char *name, char **argv, char *ops, int func)
int
bin_trap(char *name, char **argv, char *ops, int func)
{
List l;
Eprog prog;
char *arg, *s;
int sig;
@ -3852,7 +3856,7 @@ bin_trap(char *name, char **argv, char *ops, int func)
if (!sigfuncs[sig])
printf("trap -- '' %s\n", sigs[sig]);
else {
s = getpermtext((void *) sigfuncs[sig]);
s = getpermtext(sigfuncs[sig], NULL);
printf("trap -- ");
quotedzputs(s, stdout);
printf(" %s\n", sigs[sig]);
@ -3878,15 +3882,15 @@ bin_trap(char *name, char **argv, char *ops, int func)
/* Sort out the command to execute on trap */
arg = *argv++;
if (!*arg)
l = NULL;
else if (!(l = parse_string(arg, 0))) {
prog = NULL;
else if (!(prog = parse_string(arg, 0))) {
zwarnnam(name, "couldn't parse trap command", NULL, 0);
return 1;
}
/* set traps */
for (; *argv; argv++) {
List t;
Eprog t;
sig = getsignum(*argv);
if (sig == -1) {
@ -3894,10 +3898,10 @@ bin_trap(char *name, char **argv, char *ops, int func)
break;
}
PERMALLOC {
t = (List) dupstruct(l);
t = dupeprog(prog);
} LASTALLOC;
if (settrap(sig, t))
freestruct(t);
freeeprog(t);
}
return *argv != NULL;
}

View file

@ -39,95 +39,108 @@ static char *condstr[COND_MOD] = {
/**/
int
evalcond(Cond c)
evalcond(Estate state)
{
struct stat *st;
char *left, *right = NULL;
wordcode code = *state->pc++;
int ctype = WC_COND_TYPE(code);
switch (c->type) {
switch (ctype) {
case COND_NOT:
if (tracingcond)
fprintf(stderr, " %s", condstr[c->type]);
return !evalcond(c->left);
fprintf(stderr, " %s", condstr[ctype]);
return !evalcond(state);
case COND_AND:
if (evalcond(c->left)) {
if (evalcond(state)) {
if (tracingcond)
fprintf(stderr, " %s", condstr[c->type]);
return evalcond(c->right);
} else
fprintf(stderr, " %s", condstr[ctype]);
return evalcond(state);
} else {
state->pc += WC_COND_SKIP(code) - 1;
return 0;
}
case COND_OR:
if (!evalcond(c->left)) {
if (!evalcond(state)) {
if (tracingcond)
fprintf(stderr, " %s", condstr[c->type]);
return evalcond(c->right);
} else
fprintf(stderr, " %s", condstr[ctype]);
return evalcond(state);
} else {
state->pc += WC_COND_SKIP(code) - 1;
return 1;
}
case COND_MOD:
case COND_MODI:
{
Conddef cd;
char *name = ecgetstr(state, 0), **strs;
int l = WC_COND_SKIP(code);
if ((cd = getconddef((c->type == COND_MODI),
((char *) c->left) + 1, 1))) {
if (c->type == COND_MOD) {
int l = arrlen((char **) c->right);
if (ctype == COND_MOD)
strs = ecgetarr(state, l, 1);
else {
char *sbuf[3];
if (l < cd->min || (cd->max >= 0 && l > cd->max)) {
zerr("unrecognized condition: `%s'", (char *) c->left, 0);
return 0;
}
sbuf[0] = ecgetstr(state, 0);
sbuf[1] = ecgetstr(state, 0);
sbuf[2] = NULL;
strs = arrdup(sbuf);
l = 2;
}
if ((cd = getconddef((ctype == COND_MODI), name + 1, 1))) {
if (ctype == COND_MOD &&
(l < cd->min || (cd->max >= 0 && l > cd->max))) {
zerr("unrecognized condition: `%s'", name, 0);
return 0;
}
if (tracingcond)
tracemodcond((char *)c->left, (char **)c->right,
c->type == COND_MODI);
return cd->handler((char **) c->right, cd->condid);
tracemodcond(name, strs, ctype == COND_MODI);
return cd->handler(strs, cd->condid);
}
else {
char **a = (char **) c->right, *s = a[0];
char *s = strs[0];
if (s && s[0] == '-' &&
(cd = getconddef(0, s + 1, 1))) {
int l = arrlen(a);
strs[0] = dupstring(name);
name = s;
if (name && name[0] == '-' &&
(cd = getconddef(0, name + 1, 1))) {
if (l < cd->min || (cd->max >= 0 && l > cd->max)) {
zerr("unrecognized condition: `%s'", (char *) c->left, 0);
zerr("unrecognized condition: `%s'", name, 0);
return 0;
}
if (tracingcond)
tracemodcond((char *)c->left, a, c->type == COND_MODI);
a[0] = (char *) c->left;
return cd->handler(a, cd->condid);
tracemodcond(name, strs, ctype == COND_MODI);
return cd->handler(strs, cd->condid);
} else
zerr("unrecognized condition: `%s'", (char *) c->left, 0);
zerr("unrecognized condition: `%s'", name, 0);
}
return 0;
}
}
left = dupstring((char *) c->left);
left = ecgetstr(state, 1);
singsub(&left);
untokenize(left);
if (c->right && c->type != COND_STREQ && c->type != COND_STRNEQ) {
right = dupstring((char *) c->right);
if (ctype <= COND_GE && ctype != COND_STREQ && ctype != COND_STRNEQ) {
right = ecgetstr(state, 1);
singsub(&right);
untokenize(right);
}
if (tracingcond) {
if (c->type < COND_MOD) {
if (ctype < COND_MOD) {
char *rt = (char *) right;
if (c->type == COND_STREQ || c->type == COND_STRNEQ) {
rt = dupstring(c->right);
if (ctype == COND_STREQ || ctype == COND_STRNEQ) {
rt = dupstring(ecrawstr(state->prog, state->pc));
singsub(&rt);
untokenize(rt);
}
fprintf(stderr, " %s %s %s", (char *)left, condstr[c->type],
rt);
fprintf(stderr, " %s %s %s", left, condstr[ctype], rt);
} else
fprintf(stderr, " -%c %s", c->type, (char *)left);
fprintf(stderr, " -%c %s", ctype, left);
}
if (c->type >= COND_EQ && c->type <= COND_GE) {
if (ctype >= COND_EQ && ctype <= COND_GE) {
mnumber mn1, mn2;
mn1 = matheval(left);
mn2 = matheval(right);
@ -144,7 +157,7 @@ evalcond(Cond c)
mn2.u.d = (double)mn2.u.l;
}
}
switch(c->type) {
switch(ctype) {
case COND_EQ:
return (mn1.type & MN_FLOAT) ? (mn1.u.d == mn2.u.d) :
(mn1.u.l == mn2.u.l);
@ -166,30 +179,32 @@ evalcond(Cond c)
}
}
switch (c->type) {
switch (ctype) {
case COND_STREQ:
case COND_STRNEQ:
{
Patprog pprog = c->prog;
int test;
int test, npat = state->pc[1];
Patprog pprog = state->prog->pats[npat];
if (pprog == dummy_patprog1 || pprog == dummy_patprog2) {
char *opat;
int save;
right = opat = dupstring((char *) c->right);
right = opat = dupstring(ecrawstr(state->prog, state->pc));
singsub(&right);
save = (!strcmp(opat, right) && pprog != dummy_patprog2);
save = (!state->prog->heap &&
!strcmp(opat, right) && pprog != dummy_patprog2);
if (!(pprog = patcompile(right, (save ? PAT_ZDUP : PAT_STATIC),
NULL)))
zerr("bad pattern: %s", right, 0);
else if (save)
c->prog = pprog;
state->prog->pats[npat] = pprog;
}
state->pc += 2;
test = (pprog && pattry(pprog, left));
return (c->type == COND_STREQ ? test : !test);
return (ctype == COND_STREQ ? test : !test);
}
case COND_STRLT:
return strcmp(left, right) < 0;
@ -255,7 +270,7 @@ evalcond(Cond c)
a = st->st_mtime;
if (!(st = getstat(right)))
return 0;
return (c->type == COND_NT) ? a > st->st_mtime : a < st->st_mtime;
return (ctype == COND_NT) ? a > st->st_mtime : a < st->st_mtime;
}
case COND_EF:
{
@ -271,7 +286,7 @@ evalcond(Cond c)
return d == st->st_dev && i == st->st_ino;
}
default:
zerr("bad cond structure", NULL, 0);
zerr("bad cond code", NULL, 0);
}
return 0;
}
@ -390,7 +405,7 @@ tracemodcond(char *name, char **args, int inf)
{
char **aptr;
MUSTUSEHEAP("tracemodcond");
args = duparray(args, (VFunc) dupstring);
args = arrdup(args);
for (aptr = args; *aptr; aptr++)
untokenize(*aptr);
if (inf) {

File diff suppressed because it is too large Load diff

View file

@ -2551,15 +2551,15 @@ qualtime(char *name, struct stat *buf, off_t days, char *dummy)
static int
qualsheval(char *name, struct stat *buf, off_t days, char *str)
{
List list;
Eprog prog;
if ((list = parse_string(str, 0))) {
if ((prog = parse_string(str, 0))) {
int ef = errflag, lv = lastval, ret;
unsetparam("reply");
setsparam("REPLY", ztrdup(name));
execlist(list, 1, 0);
execode(prog, 1, 0);
ret = lastval;
errflag = ef;

View file

@ -842,7 +842,7 @@ freeshfuncnode(HashNode hn)
zsfree(shf->nam);
if (shf->funcdef)
freestruct(shf->funcdef);
freeeprog(shf->funcdef);
zfree(shf, sizeof(struct shfunc));
}
@ -879,7 +879,7 @@ printshfuncnode(HashNode hn, int printflags)
if (!f->funcdef)
t = 0;
else
t = getpermtext((void *) f->funcdef);
t = getpermtext(f->funcdef, NULL);
}
quotedzputs(f->nam, stdout);

View file

@ -95,7 +95,7 @@ mod_export int alloc_stackp;
void
loop(int toplevel, int justonce)
{
List list;
Eprog prog;
#ifdef DEBUG
int oasp = toplevel ? 0 : alloc_stackp;
#endif
@ -112,7 +112,7 @@ loop(int toplevel, int justonce)
hbegin(1); /* init history mech */
intr(); /* interrupts on */
lexinit(); /* initialize lexical state */
if (!(list = parse_event())) { /* if we couldn't parse a list */
if (!(prog = parse_event())) { /* if we couldn't parse a list */
hend();
if ((tok == ENDINPUT && !errflag) ||
(tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) ||
@ -122,9 +122,9 @@ loop(int toplevel, int justonce)
}
if (hend()) {
int toksav = tok;
List prelist;
Eprog preprog;
if (toplevel && (prelist = getshfunc("preexec")) != &dummy_list) {
if (toplevel && (preprog = getshfunc("preexec")) != &dummy_eprog) {
LinkList args;
int osc = sfcontext;
@ -135,16 +135,16 @@ loop(int toplevel, int justonce)
addlinknode(args, hist_ring->text);
} LASTALLOC;
sfcontext = SFC_HOOK;
doshfunc("preexec", prelist, args, 0, 1);
doshfunc("preexec", preprog, args, 0, 1);
sfcontext = osc;
freelinklist(args, (FreeFunc) NULL);
errflag = 0;
}
if (stopmsg) /* unset 'you have stopped jobs' flag */
stopmsg--;
execlist(list, 0, 0);
execode(prog, 0, 0);
if (toplevel)
freestructs();
freeeprogs();
tok = toksav;
if (toplevel)
noexitct = 0;
@ -560,6 +560,8 @@ setupvals(void)
# endif
#endif
init_eprog();
getkeyptr = NULL;
lineno = 1;

View file

@ -47,15 +47,20 @@ mod_export int breaks;
/**/
int
execfor(Cmd cmd, LinkList args, int flags)
execfor(Estate state, int do_exec)
{
Forcmd node;
char *str;
Wordcode end, loop;
wordcode code = state->pc[-1];
int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND);
char *name, *str, *cond, *advance;
zlong val = 0;
LinkList args;
node = cmd->u.forcmd;
if (node->condition) {
str = dupstring(node->name);
name = ecgetstr(state, 0);
end = state->pc + WC_FOR_SKIP(code);
if (iscond) {
str = dupstring(name);
singsub(&str);
if (isset(XTRACE)) {
char *str2 = dupstring(str);
@ -66,9 +71,19 @@ execfor(Cmd cmd, LinkList args, int flags)
}
if (!errflag)
matheval(str);
if (errflag)
if (errflag) {
state->pc = end;
return lastval = errflag;
} else if (!node->inflag) {
}
cond = ecgetstr(state, 0);
advance = ecgetstr(state, 0);
} else if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
if (!(args = ecgetlist(state, *state->pc++, 1))) {
state->pc = end;
return 0;
}
execsubst(args);
} else {
char **x;
args = newlinklist();
@ -79,9 +94,10 @@ execfor(Cmd cmd, LinkList args, int flags)
loops++;
pushheap();
cmdpush(CS_FOR);
loop = state->pc;
for (;;) {
if (node->condition) {
str = dupstring(node->condition);
if (iscond) {
str = dupstring(cond);
singsub(&str);
if (!errflag) {
while (iblank(*str))
@ -109,21 +125,21 @@ execfor(Cmd cmd, LinkList args, int flags)
break;
if (isset(XTRACE)) {
printprompt4();
fprintf(stderr, "%s=%s\n", node->name, str);
fprintf(stderr, "%s=%s\n", name, str);
fflush(stderr);
}
setsparam(node->name, ztrdup(str));
setsparam(name, ztrdup(str));
}
execlist(node->list, 1,
(flags & CFLAG_EXEC) && args && empty(args));
state->pc = loop;
execlist(state, 1, do_exec && args && empty(args));
if (breaks) {
breaks--;
if (breaks || !contflag)
break;
contflag = 0;
}
if (node->condition && !errflag) {
str = dupstring(node->advance);
if (iscond && !errflag) {
str = dupstring(advance);
if (isset(XTRACE)) {
printprompt4();
fprintf(stderr, "%s\n", str);
@ -149,25 +165,37 @@ execfor(Cmd cmd, LinkList args, int flags)
/**/
int
execselect(Cmd cmd, LinkList args, int flags)
execselect(Estate state, int do_exec)
{
Forcmd node;
char *str, *s;
Wordcode end, loop;
wordcode code = state->pc[-1];
char *str, *s, *name;
LinkNode n;
int i, usezle;
FILE *inp;
size_t more;
LinkList args;
node = cmd->u.forcmd;
if (!node->inflag) {
end = state->pc + WC_FOR_SKIP(code);
name = ecgetstr(state, 0);
if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) {
char **x;
args = newlinklist();
for (x = pparams; *x; x++)
addlinknode(args, dupstring(*x));
} else {
if (!(args = ecgetlist(state, *state->pc++, 1))) {
state->pc = end;
return 0;
}
execsubst(args);
}
if (!args || empty(args))
if (!args || empty(args)) {
state->pc = end;
return 1;
}
loops++;
lastval = 0;
pushheap();
@ -175,6 +203,7 @@ execselect(Cmd cmd, LinkList args, int flags)
usezle = interact && SHTTY != -1 && isset(USEZLE);
inp = fdopen(dup(usezle ? SHTTY : 0), "r");
more = selectlist(args, 0);
loop = state->pc;
for (;;) {
for (;;) {
if (empty(bufstack)) {
@ -219,8 +248,9 @@ execselect(Cmd cmd, LinkList args, int flags)
else
str = "";
}
setsparam(node->name, ztrdup(str));
execlist(node->list, 1, 0);
setsparam(name, ztrdup(str));
state->pc = loop;
execlist(state, 1, 0);
freeheap();
if (breaks) {
breaks--;
@ -236,6 +266,7 @@ execselect(Cmd cmd, LinkList args, int flags)
popheap();
fclose(inp);
loops--;
state->pc = end;
return lastval;
}
@ -302,28 +333,31 @@ selectlist(LinkList l, size_t start)
/**/
int
execwhile(Cmd cmd, LinkList args, int flags)
execwhile(Estate state, int do_exec)
{
struct whilecmd *node;
int olderrexit, oldval;
Wordcode end, loop;
wordcode code = state->pc[-1];
int olderrexit, oldval, isuntil = (WC_WHILE_TYPE(code) == WC_WHILE_UNTIL);
end = state->pc + WC_WHILE_SKIP(code);
olderrexit = noerrexit;
node = cmd->u.whilecmd;
oldval = 0;
pushheap();
cmdpush(node->cond ? CS_UNTIL : CS_WHILE);
cmdpush(isuntil ? CS_UNTIL : CS_WHILE);
loops++;
loop = state->pc;
for (;;) {
state->pc = loop;
noerrexit = 1;
execlist(node->cont, 1, 0);
execlist(state, 1, 0);
noerrexit = olderrexit;
if (!((lastval == 0) ^ node->cond)) {
if (!((lastval == 0) ^ isuntil)) {
if (breaks)
breaks--;
lastval = oldval;
break;
}
execlist(node->loop, 1, 0);
execlist(state, 1, 0);
if (breaks) {
breaks--;
if (breaks || !contflag)
@ -345,21 +379,26 @@ execwhile(Cmd cmd, LinkList args, int flags)
/**/
int
execrepeat(Cmd cmd, LinkList args, int flags)
execrepeat(Estate state, int do_exec)
{
Wordcode end, loop;
wordcode code = state->pc[-1];
int count;
char *tmp;
end = state->pc + WC_REPEAT_SKIP(code);
lastval = 0;
if (!args || empty(args) || nextnode(firstnode(args))) {
zerr("bad argument for repeat", NULL, 0);
return 1;
}
count = atoi(peekfirst(args));
tmp = ecgetstr(state, 1);
singsub(&tmp);
count = atoi(tmp);
pushheap();
cmdpush(CS_REPEAT);
loops++;
loop = state->pc;
while (count-- > 0) {
execlist(cmd->u.list, 1, 0);
state->pc = loop;
execlist(state, 1, 0);
freeheap();
if (breaks) {
breaks--;
@ -375,114 +414,140 @@ execrepeat(Cmd cmd, LinkList args, int flags)
cmdpop();
popheap();
loops--;
state->pc = end;
return lastval;
}
/**/
int
execif(Cmd cmd, LinkList args, int flags)
execif(Estate state, int do_exec)
{
struct ifcmd *node;
int olderrexit, s = 0;
List *i, *t;
Wordcode end, next;
wordcode code = state->pc[-1];
int olderrexit, s = 0, run = 0;
olderrexit = noerrexit;
node = cmd->u.ifcmd;
i = node->ifls;
t = node->thenls;
end = state->pc + WC_IF_SKIP(code);
if (!noerrexit)
noerrexit = 1;
while (*i) {
cmdpush(s ? CS_ELIF : CS_IF);
execlist(*i, 1, 0);
cmdpop();
if (!lastval)
while (state->pc < end) {
code = *state->pc++;
if (wc_code(code) != WC_IF ||
(run = (WC_IF_TYPE(code) == WC_IF_ELSE))) {
if (run)
run = 2;
break;
}
next = state->pc + WC_IF_SKIP(code);
cmdpush(s ? CS_ELIF : CS_IF);
execlist(state, 1, 0);
cmdpop();
if (!lastval) {
run = 1;
break;
}
s = 1;
i++;
t++;
state->pc = next;
}
noerrexit = olderrexit;
if (*t) {
cmdpush(*i ? (s ? CS_ELIFTHEN : CS_IFTHEN) : CS_ELSE);
execlist(*t, 1, flags & CFLAG_EXEC);
if (run) {
cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN));
execlist(state, 1, do_exec);
cmdpop();
} else
lastval = 0;
state->pc = end;
return lastval;
}
/**/
int
execcase(Cmd cmd, LinkList args, int flags)
execcase(Estate state, int do_exec)
{
struct casecmd *node;
char *word;
List *l;
char **p;
Patprog *pp, pprog;
int save;
Wordcode end, next;
wordcode code = state->pc[-1];
char *word, *pat;
int npat, save;
Patprog *spprog, pprog;
node = cmd->u.casecmd;
l = node->lists;
p = node->pats;
pp = node->progs;
end = state->pc + WC_CASE_SKIP(code);
word = dupstring(*p++);
word = ecgetstr(state, 1);
singsub(&word);
untokenize(word);
lastval = 0;
if (node) {
cmdpush(CS_CASE);
while (*p) {
char *pat = NULL, *opat;
cmdpush(CS_CASE);
while (state->pc < end) {
code = *state->pc++;
if (wc_code(code) != WC_CASE)
break;
pprog = NULL;
save = 0;
pat = NULL;
pprog = NULL;
save = 0;
npat = state->pc[1];
spprog = state->prog->pats + npat;
if (isset(XTRACE)) {
char *pat2;
next = state->pc + WC_CASE_SKIP(code);
opat = pat = dupstring(*p + 1);
if (isset(XTRACE)) {
char *pat2, *opat;
opat = pat = ecgetstr(state, 1);
singsub(&pat);
save = (!state->prog->heap &&
!strcmp(pat, opat) && *spprog != dummy_patprog2);
pat2 = dupstring(pat);
untokenize(pat2);
printprompt4();
fprintf(stderr, "case %s (%s)\n", word, pat2);
fflush(stderr);
state->pc++;
} else
state->pc += 2;
if (*spprog != dummy_patprog1 && *spprog != dummy_patprog2)
pprog = *spprog;
if (!pprog) {
if (!pat) {
char *opat;
opat = pat = dupstring(ecrawstr(state->prog, state->pc - 2));
singsub(&pat);
save = (!strcmp(pat, opat) && *pp != dummy_patprog2);
pat2 = dupstring(pat);
untokenize(pat2);
printprompt4();
fprintf(stderr, "case %s (%s)\n", word, pat2);
fflush(stderr);
save = (!state->prog->heap &&
!strcmp(pat, opat) && *spprog != dummy_patprog2);
}
if (*pp != dummy_patprog1 && *pp != dummy_patprog2)
pprog = *pp;
if (!pprog) {
if (!pat) {
opat = pat = dupstring(*p + 1);
singsub(&pat);
save = (!strcmp(pat, opat) && *pp != dummy_patprog2);
}
if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
NULL)))
zerr("bad pattern: %s", pat, 0);
else if (save)
*pp = pprog;
}
if (pprog && pattry(pprog, word)) {
do {
execlist(*l++, 1, **p == ';' && (flags & CFLAG_EXEC));
} while(**p++ == '&' && *p);
break;
}
p++;
pp++;
l++;
if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
NULL)))
zerr("bad pattern: %s", pat, 0);
else if (save)
*spprog = pprog;
}
cmdpop();
if (pprog && pattry(pprog, word)) {
execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
do_exec));
while (wc_code(code) == WC_CASE &&
WC_CASE_TYPE(code) == WC_CASE_AND) {
state->pc = next;
code = *state->pc;
state->pc += 3;
next = state->pc + WC_CASE_SKIP(code) - 1;
execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
do_exec));
}
break;
} else
state->pc = next;
}
cmdpop();
state->pc = end;
return lastval;
}

File diff suppressed because it is too large Load diff

View file

@ -39,7 +39,7 @@ mod_export int sigtrapped[VSIGCOUNT];
/* trap functions for each signal */
/**/
mod_export List sigfuncs[VSIGCOUNT];
mod_export Eprog sigfuncs[VSIGCOUNT];
/* Variables used by signal queueing */
@ -674,7 +674,7 @@ dosavetrap(int sig, int level)
/**/
mod_export int
settrap(int sig, List l)
settrap(int sig, Eprog l)
{
if (sig == -1)
return 1;
@ -773,7 +773,7 @@ unsettrap(int sig)
if ((hn = removehashnode(shfunctab, func)))
shfunctab->freenode(hn);
} else if (sigfuncs[sig]) {
freestruct(sigfuncs[sig]);
freeeprog(sigfuncs[sig]);
sigfuncs[sig] = NULL;
}
}
@ -834,12 +834,12 @@ endtrapscope(void)
unsettrap(sig);
sigtrapped[sig] = st->flags;
if (st->flags) {
List list = (st->flags & ZSIG_FUNC) ?
((Shfunc) st->list)->funcdef : (List) st->list;
Eprog prog = (st->flags & ZSIG_FUNC) ?
((Shfunc) st->list)->funcdef : (Eprog) st->list;
/* prevent settrap from saving this */
int oldlt = opts[LOCALTRAPS];
opts[LOCALTRAPS] = 0;
settrap(sig, list);
settrap(sig, prog);
opts[LOCALTRAPS] = oldlt;
if ((sigtrapped[sig] = st->flags) & ZSIG_FUNC)
shfunctab->addnode(shfunctab, ((Shfunc)st->list)->nam,
@ -851,11 +851,11 @@ endtrapscope(void)
if (exittr) {
dotrapargs(SIGEXIT, &exittr, (exittr & ZSIG_FUNC) ?
((Shfunc)exitfn)->funcdef : (List) exitfn);
((Shfunc)exitfn)->funcdef : (Eprog) exitfn);
if (exittr & ZSIG_FUNC)
shfunctab->freenode((HashNode)exitfn);
else
freestruct(exitfn);
freeeprog(exitfn);
}
}

View file

@ -31,7 +31,7 @@
#include "text.pro"
static char *tptr, *tbuf, *tlim;
static int tsiz, tindent, tnewlins;
static int tsiz, tindent, tnewlins, tjob;
/* add a character to the text buffer */
@ -72,18 +72,18 @@ taddstr(char *s)
tptr += sl;
}
/* add an integer to the text buffer */
#if 0 /**/
void
taddint(int x)
/**/
static void
taddlist(Estate state, int num)
{
char buf[DIGBUFSIZE];
sprintf(buf, "%d", x);
taddstr(buf);
if (num) {
while (num--) {
taddstr(ecgetstr(state, 0));
taddchr(' ');
}
tptr--;
}
}
#endif
/* add a newline, or something equivalent, to the text buffer */
@ -105,14 +105,24 @@ taddnl(void)
/**/
mod_export char *
getpermtext(struct node *n)
getpermtext(Eprog prog, Wordcode c)
{
struct estate s;
if (!c)
c = prog->prog;
s.prog = prog;
s.pc = c;
s.strs = prog->strs;
tnewlins = 1;
tbuf = (char *)zalloc(tsiz = 32);
tptr = tbuf;
tlim = tbuf + tsiz;
tindent = 1;
gettext2(n);
tjob = 0;
gettext2(&s);
*tptr = '\0';
untokenize(tbuf);
return tbuf;
@ -122,366 +132,566 @@ getpermtext(struct node *n)
/**/
char *
getjobtext(struct node *n)
getjobtext(Eprog prog, Wordcode c)
{
static char jbuf[JOBTEXTSIZE];
struct estate s;
if (!c)
c = prog->prog;
s.prog = prog;
s.pc = c;
s.strs = prog->strs;
tnewlins = 0;
tbuf = NULL;
tptr = jbuf;
tlim = tptr + JOBTEXTSIZE - 1;
tindent = 1;
gettext2(n);
tjob = 1;
gettext2(&s);
*tptr = '\0';
untokenize(jbuf);
return jbuf;
}
#define gt2(X) gettext2((struct node *) (X))
/*
"gettext2" or "type checking and how to avoid it"
an epic function by Paul Falstad
*/
* gettext2() shows one way to walk through the word code without
* recursion. We start by reading a word code and executing the
* action for it. Some codes have sub-structures (like, e.g. WC_FOR)
* and require something to be done after the sub-structure has been
* handled. For these codes a tstack structure which describes what
* has to be done is pushed onto a stack. Codes without sub-structures
* arrange for the next structure being taken from the stack so that
* the action for it is executed instead of the one for the next
* word code. If the stack is empty at this point, we have handled
* the whole structure we were called for.
*/
#define _Cond(X) ((Cond) (X))
#define _Cmd(X) ((Cmd) (X))
#define _Pline(X) ((Pline) (X))
#define _Sublist(X) ((Sublist) (X))
#define _List(X) ((List) (X))
#define _casecmd(X) ((struct casecmd *) (X))
#define _ifcmd(X) ((struct ifcmd *) (X))
#define _whilecmd(X) ((struct whilecmd *) (X))
typedef struct tstack *Tstack;
struct tstack {
Tstack prev;
wordcode code;
int pop;
union {
struct {
LinkList list;
} _redir;
struct {
char *strs;
} _funcdef;
struct {
Wordcode end;
} _case;
struct {
int cond;
Wordcode end;
} _if;
struct {
int par;
} _cond;
} u;
};
static Tstack tstack, tfree;
static Tstack
tpush(wordcode code, int pop)
{
Tstack s;
if ((s = tfree))
tfree = s->prev;
else
s = (Tstack) zalloc(sizeof(*s));
s->prev = tstack;
tstack = s;
s->code = code;
s->pop = pop;
return s;
}
/**/
static void
gettext2(struct node *n)
gettext2(Estate state)
{
Cmd nn;
Tstack s, n;
int stack = 0;
wordcode code;
if (!n || ((List) n) == &dummy_list)
return;
switch (NT_TYPE(n->ntype)) {
case N_LIST:
gt2(_List(n)->left);
if (_List(n)->type & Z_ASYNC) {
taddstr(" &");
if (_List(n)->type & Z_DISOWN)
taddstr("|");
while (1) {
if (stack) {
if (!(s = tstack))
return;
if (s->pop) {
tstack = s->prev;
s->prev = tfree;
tfree = s;
}
code = s->code;
stack = 0;
} else {
s = NULL;
code = *state->pc++;
}
if (_List(n)->right) {
if (tnewlins)
taddnl();
else
taddstr((_List(n)->type & Z_ASYNC) ? " " : "; ");
gt2(_List(n)->right);
}
break;
case N_SUBLIST:
if (_Sublist(n)->flags & PFLAG_NOT)
taddstr("! ");
if (_Sublist(n)->flags & PFLAG_COPROC)
taddstr("coproc ");
gt2(_Sublist(n)->left);
if (_Sublist(n)->right) {
taddstr((_Sublist(n)->type == ORNEXT) ? " || " : " && ");
gt2(_Sublist(n)->right);
}
break;
case N_PLINE:
gt2(_Pline(n)->left);
if (_Pline(n)->type == PIPE) {
taddstr(" | ");
gt2(_Pline(n)->right);
}
break;
case N_CMD:
nn = _Cmd(n);
switch (nn->type) {
case SIMPLE:
getsimptext(nn);
break;
case SUBSH:
taddstr("( ");
tindent++;
gt2(nn->u.list);
tindent--;
taddstr(" )");
break;
case ZCTIME:
taddstr("time ");
tindent++;
gt2(nn->u.pline);
tindent--;
break;
case FUNCDEF:
taddlist(nn->args);
taddstr(" () {");
tindent++;
taddnl();
gt2(nn->u.list);
tindent--;
taddnl();
taddstr("}");
break;
case CURSH:
taddstr("{ ");
tindent++;
gt2(nn->u.list);
tindent--;
taddstr(" }");
break;
case CFOR:
case CSELECT:
taddstr((nn->type == CFOR) ? "for " : "select ");
if (nn->u.forcmd->condition) {
taddstr("((");
taddstr(nn->u.forcmd->name);
taddstr("; ");
taddstr(nn->u.forcmd->condition);
taddstr("; ");
taddstr(nn->u.forcmd->advance);
taddstr(")) do");
switch (wc_code(code)) {
case WC_LIST:
if (!s) {
tpush(code, (WC_LIST_TYPE(code) & Z_END));
stack = 0;
} else {
taddstr(nn->u.forcmd->name);
if (nn->u.forcmd->inflag) {
taddstr(" in ");
taddlist(nn->args);
if (WC_LIST_TYPE(code) & Z_ASYNC) {
taddstr(" &");
if (WC_LIST_TYPE(code) & Z_DISOWN)
taddstr("|");
}
if (!(stack = (WC_LIST_TYPE(code) & Z_END))) {
if (tnewlins)
taddnl();
else
taddstr((WC_LIST_TYPE(code) & Z_ASYNC) ? " " : "; ");
s->code = *state->pc++;
s->pop = (WC_LIST_TYPE(s->code) & Z_END);
}
}
break;
case WC_SUBLIST:
if (!s) {
if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT)
taddstr("! ");
if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_COPROC)
taddstr("coproc ");
tpush(code, (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END));
} else {
if (!(stack = (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END))) {
taddstr((WC_SUBLIST_TYPE(code) == WC_SUBLIST_OR) ?
" || " : " && ");
s->code = *state->pc++;
s->pop = (WC_SUBLIST_TYPE(s->code) == WC_SUBLIST_END);
if (WC_SUBLIST_FLAGS(s->code) & WC_SUBLIST_NOT)
taddstr("! ");
if (WC_SUBLIST_FLAGS(s->code) & WC_SUBLIST_COPROC)
taddstr("coproc ");
}
}
break;
case WC_PIPE:
if (!s) {
tpush(code, (WC_PIPE_TYPE(code) == WC_PIPE_END));
if (WC_PIPE_TYPE(code) == WC_PIPE_MID)
state->pc++;
} else {
if (!(stack = (WC_PIPE_TYPE(code) == WC_PIPE_END))) {
taddstr(" | ");
s->code = *state->pc++;
if (!(s->pop = (WC_PIPE_TYPE(s->code) == WC_PIPE_END)))
state->pc++;
}
}
break;
case WC_REDIR:
if (!s) {
state->pc--;
n = tpush(code, 1);
n->u._redir.list = ecgetredirs(state);
} else {
getredirs(s->u._redir.list);
stack = 1;
}
break;
case WC_ASSIGN:
taddstr(ecgetstr(state, 0));
taddchr('=');
if (WC_ASSIGN_TYPE(code) == WC_ASSIGN_ARRAY) {
taddchr('(');
taddlist(state, WC_ASSIGN_NUM(code));
taddstr(") ");
} else {
taddstr(ecgetstr(state, 0));
taddchr(' ');
}
break;
case WC_SIMPLE:
taddlist(state, WC_SIMPLE_ARGC(code));
stack = 1;
break;
case WC_SUBSH:
if (!s) {
taddstr("( ");
tindent++;
tpush(code, 1);
} else {
tindent--;
taddstr(" )");
stack = 1;
}
break;
case WC_CURSH:
if (!s) {
taddstr("{ ");
tindent++;
tpush(code, 1);
} else {
tindent--;
taddstr(" }");
stack = 1;
}
break;
case WC_TIMED:
if (!s) {
taddstr("time");
if (WC_TIMED_TYPE(code) == WC_TIMED_PIPE) {
taddchr(' ');
tindent++;
tpush(code, 1);
} else
stack = 1;
} else {
tindent--;
stack = 1;
}
break;
case WC_FUNCDEF:
if (!s) {
Wordcode p = state->pc;
Wordcode end = p + WC_FUNCDEF_SKIP(code);
taddlist(state, *state->pc++);
if (tjob) {
taddstr(" () { ... }");
state->pc = end;
stack = 1;
} else {
taddstr(" () {");
tindent++;
taddnl();
n = tpush(code, 1);
n->u._funcdef.strs = state->strs;
state->strs = (char *) (p + (*state->pc));
state->pc += 2;
}
} else {
state->strs = s->u._funcdef.strs;
tindent--;
taddnl();
taddstr("}");
stack = 1;
}
break;
case WC_FOR:
if (!s) {
taddstr("for ");
if (WC_FOR_TYPE(code) == WC_FOR_COND) {
taddstr("((");
taddstr(ecgetstr(state, 0));
taddstr("; ");
taddstr(ecgetstr(state, 0));
taddstr("; ");
taddstr(ecgetstr(state, 0));
taddstr(")) do");
} else {
taddstr(ecgetstr(state, 0));
if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
taddstr(" in ");
taddlist(state, *state->pc++);
}
taddnl();
taddstr("do");
}
tindent++;
taddnl();
tpush(code, 1);
} else {
tindent--;
taddnl();
taddstr("done");
stack = 1;
}
break;
case WC_SELECT:
if (!s) {
taddstr("select ");
taddstr(ecgetstr(state, 0));
if (WC_SELECT_TYPE(code) == WC_SELECT_LIST) {
taddstr(" in ");
taddlist(state, *state->pc++);
}
tindent++;
taddnl();
tpush(code, 1);
} else {
tindent--;
taddnl();
taddstr("done");
stack = 1;
}
break;
case WC_WHILE:
if (!s) {
taddstr(WC_WHILE_TYPE(code) == WC_WHILE_UNTIL ?
"until " : "while ");
tindent++;
tpush(code, 0);
} else if (!s->pop) {
tindent--;
taddnl();
taddstr("do");
tindent++;
taddnl();
s->pop = 1;
} else {
tindent--;
taddnl();
taddstr("done");
stack = 1;
}
tindent++;
taddnl();
gt2(nn->u.forcmd->list);
tindent--;
taddnl();
taddstr("done");
break;
case CIF:
gt2(nn->u.ifcmd);
taddstr("fi");
case WC_REPEAT:
if (!s) {
taddstr("repeat ");
taddstr(ecgetstr(state, 0));
taddnl();
taddstr("do");
tindent++;
taddnl();
tpush(code, 1);
} else {
tindent--;
taddnl();
taddstr("done");
stack = 1;
}
break;
case CCASE:
gt2(nn->u.casecmd);
break;
case COND:
taddstr("[[ ");
gt2(nn->u.cond);
taddstr(" ]]");
break;
case CARITH:
taddstr("((");
taddlist(nn->args);
taddstr("))");
break;
case CREPEAT:
taddstr("repeat ");
taddlist(nn->args);
taddnl();
taddstr("do");
tindent++;
taddnl();
gt2(nn->u.list);
tindent--;
taddnl();
taddstr("done");
break;
case CWHILE:
gt2(nn->u.whilecmd);
break;
}
getredirs(nn);
break;
case N_COND:
getcond(_Cond(n), 0);
break;
case N_CASE:
{
List *l;
char **p;
case WC_CASE:
if (!s) {
Wordcode end = state->pc + WC_CASE_SKIP(code);
l = _casecmd(n)->lists;
p = _casecmd(n)->pats;
taddstr("case ");
taddstr(ecgetstr(state, 0));
taddstr(" in");
taddstr("case ");
taddstr(*p++);
taddstr(" in");
tindent++;
for (; l && *l; p++, l++) {
if (state->pc >= end) {
if (tnewlins)
taddnl();
else
taddchr(' ');
taddstr("esac");
stack = 1;
} else {
tindent++;
if (tnewlins)
taddnl();
else
taddchr(' ');
code = *state->pc++;
taddstr(ecgetstr(state, 0));
state->pc++;
taddstr(") ");
tindent++;
n = tpush(code, 0);
n->u._case.end = end;
n->pop = (state->pc - 2 + WC_CASE_SKIP(code) >= end);
}
} else if (state->pc < s->u._case.end) {
tindent--;
taddstr(WC_CASE_TYPE(code) == WC_CASE_OR ? " ;;" : ";&");
if (tnewlins)
taddnl();
else
taddchr(' ');
taddstr(*p + 1);
code = *state->pc++;
taddstr(ecgetstr(state, 0));
state->pc++;
taddstr(") ");
tindent++;
gt2(*l);
s->code = code;
s->pop = ((state->pc - 2 + WC_CASE_SKIP(code)) >=
s->u._case.end);
} else {
tindent--;
taddstr(" ;");
taddchr(**p);
taddstr(WC_CASE_TYPE(code) == WC_CASE_OR ? " ;;" : ";&");
tindent--;
if (tnewlins)
taddnl();
else
taddchr(' ');
taddstr("esac");
stack = 1;
}
tindent--;
if (tnewlins)
taddnl();
else
taddchr(' ');
taddstr("esac");
break;
}
case N_IF:
{
List *i, *t;
case WC_IF:
if (!s) {
Wordcode end = state->pc + WC_IF_SKIP(code);
taddstr("if ");
for (i = _ifcmd(n)->ifls, t = _ifcmd(n)->thenls; *i; i++, t++) {
taddstr("if ");
tindent++;
gt2(*i);
state->pc++;
n = tpush(code, 0);
n->u._if.end = end;
n->u._if.cond = 1;
} else if (s->pop) {
stack = 1;
} else if (s->u._if.cond) {
tindent--;
taddnl();
taddstr("then");
tindent++;
taddnl();
gt2(*t);
s->u._if.cond = 0;
} else if (state->pc < s->u._if.end) {
tindent--;
taddnl();
if (i[1]) {
code = *state->pc++;
if (WC_IF_TYPE(code) == WC_IF_ELIF) {
taddstr("elif ");
tindent++;
s->u._if.cond = 1;
} else {
taddstr("else");
tindent++;
taddnl();
}
}
if (*t) {
taddstr("else");
tindent++;
taddnl();
gt2(*t);
} else {
s->pop = 1;
tindent--;
taddnl();
taddstr("fi");
stack = 1;
}
break;
}
case N_WHILE:
taddstr((_whilecmd(n)->cond) ? "until " : "while ");
tindent++;
gt2(_whilecmd(n)->cont);
tindent--;
taddnl();
taddstr("do");
tindent++;
taddnl();
gt2(_whilecmd(n)->loop);
tindent--;
taddnl();
taddstr("done");
break;
}
}
case WC_COND:
{
static char *c1[] = {
"=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
"-ne", "-lt", "-gt", "-le", "-ge"
};
/* Print a condition bracketed by [[ ... ]]. *
* With addpar non-zero, parenthesise the subexpression. */
int ctype;
/**/
static void
getcond(Cond nm, int addpar)
{
static char *c1[] =
{
"=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
"-ne", "-lt", "-gt", "-le", "-ge"
};
if (!s) {
taddstr("[[ ");
n = tpush(code, 1);
n->u._cond.par = 2;
} else if (s->u._cond.par == 2) {
taddstr(" ]]");
stack = 1;
break;
} else if (s->u._cond.par == 1) {
taddstr(" )");
stack = 1;
break;
} else if (WC_COND_TYPE(s->code) == COND_AND) {
taddstr(" && ");
code = *state->pc++;
if (WC_COND_TYPE(code) == COND_OR) {
taddstr("( ");
n = tpush(code, 1);
n->u._cond.par = 1;
}
} else if (WC_COND_TYPE(s->code) == COND_OR) {
taddstr(" || ");
code = *state->pc++;
if (WC_COND_TYPE(code) == COND_AND) {
taddstr("( ");
n = tpush(code, 1);
n->u._cond.par = 1;
}
}
while (!stack) {
switch ((ctype = WC_COND_TYPE(code))) {
case COND_NOT:
taddstr("! ");
code = *state->pc++;
if (WC_COND_TYPE(code) <= COND_OR) {
taddstr("( ");
n = tpush(code, 1);
n->u._cond.par = 1;
}
break;
case COND_AND:
tpush(code, 1);
code = *state->pc++;
if (WC_COND_TYPE(code) == COND_OR) {
taddstr("( ");
n = tpush(code, 1);
n->u._cond.par = 1;
}
break;
case COND_OR:
tpush(code, 1);
code = *state->pc++;
if (WC_COND_TYPE(code) == COND_AND) {
taddstr("( ");
n = tpush(code, 1);
n->u._cond.par = 1;
}
break;
case COND_MOD:
taddstr(ecgetstr(state, 0));
taddlist(state, WC_COND_SKIP(code));
stack = 1;
break;
case COND_MODI:
{
char *name = ecgetstr(state, 0);
if (addpar)
taddstr("( ");
switch (nm->type) {
case COND_NOT:
taddstr("! ");
getcond(nm->left, _Cond(nm->left)->type <= COND_OR);
break;
case COND_AND:
getcond(nm->left, _Cond(nm->left)->type == COND_OR);
taddstr(" && ");
getcond(nm->right, _Cond(nm->right)->type == COND_OR);
break;
case COND_OR:
/* This is deliberately over-generous with parentheses: *
* in fact omitting them gives correct precedence. */
getcond(nm->left, _Cond(nm->left)->type == COND_AND);
taddstr(" || ");
getcond(nm->right, _Cond(nm->right)->type == COND_AND);
break;
case COND_MOD:
{
/* Module defined prefix condition. */
char **p = (char **) nm->right;
taddstr(ecgetstr(state, 0));
taddchr(' ');
taddstr(name);
taddchr(' ');
taddstr(ecgetstr(state, 0));
stack = 1;
}
break;
default:
if (ctype <= COND_GE) {
/* Binary test: `a = b' etc. */
taddstr(ecgetstr(state, 0));
taddstr(" ");
taddstr(c1[ctype - COND_STREQ]);
taddstr(" ");
taddstr(ecgetstr(state, 0));
if (ctype == COND_STREQ ||
ctype == COND_STRNEQ)
state->pc++;
} else {
/* Unary test: `-f foo' etc. */
char c2[4];
taddstr(nm->left);
for (; *p; p++) {
taddstr(" ");
taddstr(*p);
c2[0] = '-';
c2[1] = ctype;
c2[2] = ' ';
c2[3] = '\0';
taddstr(c2);
taddstr(ecgetstr(state, 0));
}
stack = 1;
break;
}
}
}
break;
case WC_ARITH:
taddstr("((");
taddstr(ecgetstr(state, 0));
taddstr("))");
stack = 1;
break;
default:
return;
}
break;
case COND_MODI:
/* Module defined infix condition. */
taddstr(((char **) nm->right)[0]);
taddstr(" ");
taddstr(nm->left);
taddstr(" ");
taddstr(((char **) nm->right)[1]);
break;
default:
if (nm->type <= COND_GE) {
/* Binary test: `a = b' etc. */
taddstr(nm->left);
taddstr(" ");
taddstr(c1[nm->type - COND_STREQ]);
taddstr(" ");
taddstr(nm->right);
} else {
/* Unary test: `-f foo' etc. */
char c2[4];
c2[0] = '-';
c2[1] = nm->type;
c2[2] = ' ';
c2[3] = '\0';
taddstr(c2);
taddstr(nm->left);
}
break;
}
if (addpar)
taddstr(" )");
}
/**/
static void
getsimptext(Cmd cmd)
{
LinkNode n;
if (cmd->vars)
for (n = firstnode(cmd->vars); n; incnode(n)) {
struct varasg *v = (struct varasg *)getdata(n);
taddstr(v->name);
taddchr('=');
if (PM_TYPE(v->type) == PM_ARRAY) {
taddchr('(');
taddlist(v->arr);
taddstr(") ");
} else if (PM_TYPE(v->type) == PM_HASHED) {
/* XXX */
} else {
taddstr(v->str);
taddchr(' ');
}
}
taddlist(cmd->args);
}
/**/
void
getredirs(Cmd cmd)
getredirs(LinkList redirs)
{
LinkNode n;
static char *fstr[] =
@ -489,12 +699,9 @@ getredirs(Cmd cmd)
">", ">|", ">>", ">>|", "&>", "&>|", "&>>", "&>>|", "<>", "<",
"<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">"
};
if (!cmd->redir)
return;
taddchr(' ');
for (n = firstnode(cmd->redir); n; incnode(n)) {
struct redir *f = (struct redir *)getdata(n);
for (n = firstnode(redirs); n; incnode(n)) {
Redir f = (Redir) getdata(n);
switch (f->type) {
case WRITE:
@ -532,18 +739,3 @@ getredirs(Cmd cmd)
}
tptr--;
}
/**/
static void
taddlist(LinkList l)
{
LinkNode n;
if (!l || !(n = firstnode(l)))
return;
for (; n; incnode(n)) {
taddstr(getdata(n));
taddchr(' ');
}
tptr--;
}

View file

@ -630,7 +630,7 @@ preprompt(void)
{
static time_t lastperiodic;
LinkNode ln;
List list;
Eprog prog;
int period = getiparam("PERIOD");
int mailcheck = getiparam("MAILCHECK");
@ -643,11 +643,11 @@ preprompt(void)
/* If a shell function named "precmd" exists, *
* then execute it. */
if ((list = getshfunc("precmd")) != &dummy_list) {
if ((prog = getshfunc("precmd")) != &dummy_eprog) {
int osc = sfcontext;
sfcontext = SFC_HOOK;
doshfunc("precmd", list, NULL, 0, 1);
doshfunc("precmd", prog, NULL, 0, 1);
sfcontext = osc;
}
if (errflag)
@ -657,11 +657,11 @@ preprompt(void)
* "periodic" exists, 3) it's been greater than PERIOD since we *
* executed "periodic", then execute it now. */
if (period && (time(NULL) > lastperiodic + period) &&
(list = getshfunc("periodic")) != &dummy_list) {
(prog = getshfunc("periodic")) != &dummy_eprog) {
int osc = sfcontext;
sfcontext = SFC_HOOK;
doshfunc("periodic", list, NULL, 0, 1);
doshfunc("periodic", prog, NULL, 0, 1);
sfcontext = osc;
lastperiodic = time(NULL);
}
@ -1890,275 +1890,17 @@ sepsplit(char *s, char *sep, int allownull)
/* Get the definition of a shell function */
/**/
mod_export List
mod_export Eprog
getshfunc(char *nam)
{
Shfunc shf;
if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, nam)))
return &dummy_list;
return &dummy_eprog;
return shf->funcdef;
}
/* allocate a tree element */
static int sizetab[N_COUNT] = {
sizeof(struct list),
sizeof(struct sublist),
sizeof(struct pline),
sizeof(struct cmd),
sizeof(struct redir),
sizeof(struct cond),
sizeof(struct forcmd),
sizeof(struct casecmd),
sizeof(struct ifcmd),
sizeof(struct whilecmd),
sizeof(struct varasg),
sizeof(struct autofn),
};
static int offstab[N_COUNT] = {
offsetof(struct list, left),
offsetof(struct sublist, left),
offsetof(struct pline, left),
offsetof(struct cmd, u),
offsetof(struct redir, name),
offsetof(struct cond, left),
offsetof(struct forcmd, name),
offsetof(struct casecmd, pats),
offsetof(struct ifcmd, ifls),
offsetof(struct whilecmd, cont),
offsetof(struct varasg, name),
sizeof(struct autofn),
};
static int flagtab[N_COUNT] = {
NT_SET(N_LIST, NT_NODE, NT_NODE, 0, 0),
NT_SET(N_SUBLIST, NT_NODE, NT_NODE, 0, 0),
NT_SET(N_PLINE, NT_NODE, NT_NODE, 0, 0),
NT_SET(N_CMD, NT_NODE, NT_STR | NT_LIST, NT_NODE | NT_LIST, NT_NODE | NT_LIST),
NT_SET(N_REDIR, NT_STR, 0, 0, 0),
NT_SET(N_COND, NT_NODE, NT_NODE, NT_PAT, 0),
NT_SET(N_FOR, NT_STR, NT_STR, NT_STR, NT_NODE),
NT_SET(N_CASE, NT_STR | NT_ARR, NT_PAT | NT_ARR, NT_NODE | NT_ARR, 0),
NT_SET(N_IF, NT_NODE | NT_ARR, NT_NODE | NT_ARR, 0, 0),
NT_SET(N_WHILE, NT_NODE, NT_NODE, 0, 0),
NT_SET(N_VARASG, NT_STR, NT_STR, NT_STR | NT_LIST, 0),
NT_SET(N_AUTOFN, 0, 0, 0, 0),
};
/**/
void *
allocnode(int type)
{
struct node *n;
n = (struct node *) ncalloc(sizetab[type]);
memset((void *) n, 0, sizetab[type]);
n->ntype = flagtab[type];
return (void *) n;
}
/* duplicate a syntax tree */
/**/
mod_export void *
dupstruct(void *a)
{
void **onodes, **nnodes, *ret, *n, *on;
int type;
size_t nodeoffs;
if (!a || ((List) a) == &dummy_list)
return a;
type = *(int *)a;
ret = alloc(sizetab[NT_TYPE(type)]);
memcpy(ret, a, nodeoffs = offstab[NT_TYPE(type)]);
onodes = (void **) ((char *)a + nodeoffs);
nnodes = (void **) ((char *)ret + nodeoffs);
for (type = (type & 0xffff00) >> 4; (type >>= 4); *nnodes++ = n) {
if (!(on = *onodes++))
n = NULL;
else {
switch (type & 0xf) {
case NT_NODE:
n = dupstruct(on);
break;
case NT_STR:
n = dupstring(on);
break;
case NT_PAT:
n = duppatprog(on);
break;
case NT_LIST | NT_NODE:
n = duplist(on, (VFunc) dupstruct);
break;
case NT_LIST | NT_STR:
n = duplist(on, (VFunc) (useheap ? dupstring : ztrdup));
break;
case NT_LIST | NT_PAT:
n = duplist(on, (VFunc) duppatprog);
break;
case NT_NODE | NT_ARR:
n = duparray(on, (VFunc) dupstruct);
break;
case NT_STR | NT_ARR:
n = duparray(on, (VFunc) (useheap ? dupstring : ztrdup));
break;
case NT_PAT | NT_ARR:
n = duparray(on, (VFunc) duppatprog);
break;
default:
DPUTS(1, "BUG: bad node type in dupstruct()");
abort();
}
}
}
return ret;
}
/* Free a syntax tree. Now, freestruct() only registers everything that
* has to be freed. Later, freestructs() will be called to do the real
* work. This is to avoid having functions that are currently executed
* free themselves by re-defining themselves. */
static LinkList freeslist = NULL;
/**/
mod_export void
freestruct(void *a)
{
if (!a || ((List) a) == &dummy_list)
return;
PERMALLOC {
if (!freeslist)
freeslist = newlinklist();
addlinknode(freeslist, a);
} LASTALLOC;
}
/**/
void
freestructs(void)
{
void *a;
if (freeslist)
while ((a = getlinknode(freeslist)))
ifreestruct(a);
}
/**/
static void
ifreestruct(void *a)
{
void **nodes, *n;
int type, size;
type = *(int *) a;
nodes = (void **) ((char *)a + offstab[NT_TYPE(type)]);
size = sizetab[NT_TYPE(type)];
for (type = (type & 0xffff00) >> 4; (type >>= 4);) {
if ((n = *nodes++)) {
switch (type & 0xf) {
case NT_NODE:
freestruct(n);
break;
case NT_STR:
zsfree((char *) n);
break;
case NT_PAT:
freepatprog((Patprog) n);
break;
case NT_LIST | NT_NODE:
freelinklist((LinkList) n, (FreeFunc) freestruct);
break;
case NT_LIST | NT_STR:
freelinklist((LinkList) n, (FreeFunc) zsfree);
break;
case NT_LIST | NT_PAT:
freelinklist((LinkList) n, (FreeFunc) freepatprog);
break;
case NT_NODE | NT_ARR:
{
void **p = (void **) n;
while (*p)
freestruct(*p++);
zfree(n, sizeof(void *) * (p + 1 - (void **) n));
break;
}
case NT_STR | NT_ARR:
freearray((char **) n);
break;
case NT_PAT | NT_ARR:
{
Patprog *p = (Patprog *) n;
while (*p)
freepatprog(*p++);
zfree(n, sizeof(void *) * ((void **) p + 1 - (void **) n));
break;
}
default:
DPUTS(1, "BUG: bad node type in freenode()");
abort();
}
}
}
#if 0
DPUTS(size != ((char *) nodes) - ((char *) a),
"BUG: size wrong in freenode()");
#endif
zfree(a, size);
}
/**/
LinkList
dupheaplist(LinkList l)
{
if (!l)
return NULL;
return duplist(l, (VFunc) dupstruct);
}
/**/
static LinkList
duplist(LinkList l, VFunc func)
{
if (l && nonempty(l)) {
LinkList ret;
LinkNode node;
ret = newlinklist();
for (node = firstnode(l); node; incnode(node))
addlinknode(ret, func(getdata(node)));
return ret;
}
return NULL;
}
/**/
mod_export char **
duparray(char **arr, VFunc func)
{
if (arr && *arr) {
char **ret, **rr, *p;
ret = (char **) alloc((arrlen(arr) + 1) * sizeof(char *));
for (rr = ret; (p = *arr++);)
*rr++ = (char *)func(p);
*rr = NULL;
return ret;
}
return NULL;
}
/**/
char **
mkarray(char *s)

354
Src/zsh.h
View file

@ -306,20 +306,12 @@ typedef struct patprog *Patprog;
typedef struct process *Process;
typedef struct job *Job;
typedef struct value *Value;
typedef struct varasg *Varasg;
typedef struct cond *Cond;
typedef struct conddef *Conddef;
typedef struct cmd *Cmd;
typedef struct pline *Pline;
typedef struct sublist *Sublist;
typedef struct list *List;
typedef struct redir *Redir;
typedef struct complist *Complist;
typedef struct heap *Heap;
typedef struct heapstack *Heapstack;
typedef struct histent *Histent;
typedef struct forcmd *Forcmd;
typedef struct autofn *AutoFn;
typedef struct hookdef *Hookdef;
typedef struct asgment *Asgment;
@ -365,148 +357,16 @@ struct linklist {
/* Definitions for syntax trees */
/********************************/
/* struct list, struct sublist, struct pline, etc. all fit the form *
* of this structure and are used interchangably. The ptrs may hold *
* integers or pointers, depending on the type of the node. */
/* Generic node structure for syntax trees */
struct node {
int ntype; /* node type */
};
#define N_LIST 0
#define N_SUBLIST 1
#define N_PLINE 2
#define N_CMD 3
#define N_REDIR 4
#define N_COND 5
#define N_FOR 6
#define N_CASE 7
#define N_IF 8
#define N_WHILE 9
#define N_VARASG 10
#define N_AUTOFN 11
#define N_COUNT 12
/* values for types[4] */
#define NT_EMPTY 0
#define NT_NODE 1
#define NT_STR 2
#define NT_PAT 3
#define NT_LIST 4
#define NT_ARR 8
#define NT_TYPE(T) ((T) & 0xff)
#define NT_N(T, N) (((T) >> (8 + (N) * 4)) & 0xf)
#define NT_SET(T0, T1, T2, T3, T4) \
((T0) | ((T1) << 8) | ((T2) << 12) | ((T3) << 16) | ((T4) << 20))
/* tree element for lists */
struct list {
int ntype; /* node type */
int type;
Sublist left;
List right;
};
/* These are control flags that are passed *
* down the execution pipeline. */
#define Z_TIMED (1<<0) /* pipeline is being timed */
#define Z_SYNC (1<<1) /* run this sublist synchronously (;) */
#define Z_ASYNC (1<<2) /* run this sublist asynchronously (&) */
#define Z_TIMED (1<<0) /* pipeline is being timed */
#define Z_SYNC (1<<1) /* run this sublist synchronously (;) */
#define Z_ASYNC (1<<2) /* run this sublist asynchronously (&) */
#define Z_DISOWN (1<<3) /* run this sublist without job control (&|) */
/* tree element for sublists */
struct sublist {
int ntype; /* node type */
int type;
int flags; /* see PFLAGs below */
Pline left;
Sublist right;
};
#define ORNEXT 10 /* || */
#define ANDNEXT 11 /* && */
#define PFLAG_NOT 1 /* ! ... */
#define PFLAG_COPROC 32 /* coproc ... */
/* tree element for pipes */
struct pline {
int ntype; /* node type */
int type;
Cmd left;
Pline right;
};
#define END 0 /* pnode *right is null */
#define PIPE 1 /* pnode *right is the rest of the pipeline */
/* tree element for commands */
struct cmd {
int ntype; /* node type */
int type;
int flags; /* see CFLAGs below */
int lineno; /* lineno of script for command */
union {
List list; /* for SUBSH/CURSH/SHFUNC */
Forcmd forcmd;
struct casecmd *casecmd;
struct ifcmd *ifcmd;
struct whilecmd *whilecmd;
Sublist pline;
Cond cond;
AutoFn autofn;
void *generic;
} u;
LinkList args; /* command & argmument List (char *'s) */
LinkList redir; /* i/o redirections (struct redir *'s) */
LinkList vars; /* param assignments (struct varasg *'s) */
};
/* cmd types */
#define SIMPLE 0
#define SUBSH 1
#define CURSH 2
#define ZCTIME 3
#define FUNCDEF 4
#define CFOR 5
#define CWHILE 6
#define CREPEAT 7
#define CIF 8
#define CCASE 9
#define CSELECT 10
#define COND 11
#define CARITH 12
#define AUTOFN 13
/* flags for command modifiers */
#define CFLAG_EXEC (1<<0) /* exec ... */
/* tree element for redirection lists */
struct redir {
int ntype; /* node type */
int type;
int fd1, fd2;
char *name;
};
/* tree element for conditionals */
struct cond {
int ntype; /* node type */
int type; /* can be cond_type, or a single */
/* letter (-a, -b, ...) */
void *left, *right;
Patprog prog; /* compiled pattern for `==' and `!=' */
};
#define COND_NOT 0
#define COND_AND 1
#define COND_OR 2
@ -545,42 +405,12 @@ struct conddef {
#define CONDDEF(name, flags, handler, min, max, condid) \
{ NULL, name, flags, handler, min, max, condid, NULL }
struct forcmd { /* for/select */
/* Cmd->args contains list of words to loop thru */
int ntype; /* node type */
int inflag; /* if there is an in ... clause */
char *name; /* initializer or parameter name */
char *condition; /* arithmetic terminating condition */
char *advance; /* evaluated after each loop */
List list; /* list to look through for each name */
};
/* tree element for redirection lists */
struct casecmd {
/* Cmd->args contains word to test */
int ntype; /* node type */
char **pats; /* pattern strings */
Patprog *progs; /* compiled patterns (on demand) */
List *lists; /* list to execute */
};
struct ifcmd {
int ntype; /* node type */
List *ifls;
List *thenls;
};
struct whilecmd {
int ntype; /* node type */
int cond; /* 0 for while, 1 for until */
List cont; /* condition */
List loop; /* list to execute until condition met */
};
/* node for autoloading functions */
struct autofn {
int ntype; /* node type */
Shfunc shf; /* the shell function to define */
struct redir {
int type;
int fd1, fd2;
char *name;
};
/* The number of fds space is allocated for *
@ -602,14 +432,12 @@ struct multio {
int fds[MULTIOUNIT]; /* list of src/dests redirected to/from this fd */
};
/* variable assignment tree element */
/* structure for foo=bar assignments */
struct varasg {
int ntype; /* node type */
int type; /* nonzero means array */
struct asgment {
struct asgment *next;
char *name;
char *str; /* should've been a union here. oh well */
LinkList arr;
char *value;
};
/* lvalue for variable assignment/expansion */
@ -623,16 +451,152 @@ struct value {
char **arr; /* cache for hash turned into array */
};
/* structure for foo=bar assignments */
struct asgment {
struct asgment *next;
char *name;
char *value;
};
#define MAX_ARRLEN 262144
/********************************************/
/* Defintions for byte code */
/********************************************/
typedef unsigned int wordcode;
typedef wordcode *Wordcode;
typedef struct eprog *Eprog;
struct eprog {
int heap; /* != 0 if this is in heap memory */
int len; /* total block length */
int npats; /* Patprog cache size */
Patprog *pats; /* the memory block, the patterns */
Wordcode prog; /* memory block ctd, the code */
char *strs; /* memory block ctd, the strings */
Shfunc shf; /* shell function for autoload */
};
typedef struct estate *Estate;
struct estate {
Eprog prog; /* the eprog executed */
Wordcode pc; /* program counter, current pos */
char *strs; /* strings from prog */
};
#define WC_CODEBITS 5
#define wc_code(C) ((C) & ((wordcode) ((1 << WC_CODEBITS) - 1)))
#define wc_data(C) ((C) >> WC_CODEBITS)
#define wc_bld(C, D) (((wordcode) (C)) | (((wordcode) (D)) << WC_CODEBITS))
#define WC_END 0
#define WC_LIST 1
#define WC_SUBLIST 2
#define WC_PIPE 3
#define WC_REDIR 4
#define WC_ASSIGN 5
#define WC_SIMPLE 6
#define WC_SUBSH 7
#define WC_CURSH 8
#define WC_TIMED 9
#define WC_FUNCDEF 10
#define WC_FOR 11
#define WC_SELECT 12
#define WC_WHILE 13
#define WC_REPEAT 14
#define WC_CASE 15
#define WC_IF 16
#define WC_COND 17
#define WC_ARITH 18
#define WC_AUTOFN 19
#define WCB_END() wc_bld(WC_END, 0)
#define WC_LIST_TYPE(C) wc_data(C)
#define Z_END (1<<4)
#define WCB_LIST(T) wc_bld(WC_LIST, (T))
#define WC_SUBLIST_TYPE(C) (wc_data(C) & ((wordcode) 3))
#define WC_SUBLIST_END 0
#define WC_SUBLIST_AND 1
#define WC_SUBLIST_OR 2
#define WC_SUBLIST_FLAGS(C) (wc_data(C) & ((wordcode) 12))
#define WC_SUBLIST_COPROC 4
#define WC_SUBLIST_NOT 8
#define WC_SUBLIST_SKIP(C) (wc_data(C) >> 4)
#define WCB_SUBLIST(T,F,O) wc_bld(WC_SUBLIST, ((T) | (F) | ((O) << 4)))
#define WC_PIPE_TYPE(C) (wc_data(C) & ((wordcode) 1))
#define WC_PIPE_END 0
#define WC_PIPE_MID 1
#define WC_PIPE_LINENO(C) (wc_data(C) >> 1)
#define WCB_PIPE(T,L) wc_bld(WC_PIPE, ((T) | ((L) << 1)))
#define WC_REDIR_TYPE(C) wc_data(C)
#define WCB_REDIR(T) wc_bld(WC_REDIR, (T))
#define WC_ASSIGN_TYPE(C) (wc_data(C) & ((wordcode) 1))
#define WC_ASSIGN_SCALAR 0
#define WC_ASSIGN_ARRAY 1
#define WC_ASSIGN_NUM(C) (wc_data(C) >> 1)
#define WCB_ASSIGN(T,N) wc_bld(WC_ASSIGN, ((T) | ((N) << 1)))
#define WC_SIMPLE_ARGC(C) wc_data(C)
#define WCB_SIMPLE(N) wc_bld(WC_SIMPLE, (N))
#define WCB_SUBSH() wc_bld(WC_SUBSH, 0)
#define WCB_CURSH() wc_bld(WC_CURSH, 0)
#define WC_TIMED_TYPE(C) wc_data(C)
#define WC_TIMED_EMPTY 0
#define WC_TIMED_PIPE 1
#define WCB_TIMED(T) wc_bld(WC_TIMED, (T))
#define WC_FUNCDEF_SKIP(C) wc_data(C)
#define WCB_FUNCDEF(O) wc_bld(WC_FUNCDEF, (O))
#define WC_FOR_TYPE(C) (wc_data(C) & 3)
#define WC_FOR_PPARAM 0
#define WC_FOR_LIST 1
#define WC_FOR_COND 2
#define WC_FOR_SKIP(C) (wc_data(C) >> 2)
#define WCB_FOR(T,O) wc_bld(WC_FOR, ((T) | ((O) << 2)))
#define WC_SELECT_TYPE(C) (wc_data(C) & 1)
#define WC_SELECT_PPARAM 0
#define WC_SELECT_LIST 1
#define WC_SELECT_SKIP(C) (wc_data(C) >> 1)
#define WCB_SELECT(T,O) wc_bld(WC_SELECT, ((T) | ((O) << 1)))
#define WC_WHILE_TYPE(C) (wc_data(C) & 1)
#define WC_WHILE_WHILE 0
#define WC_WHILE_UNTIL 1
#define WC_WHILE_SKIP(C) (wc_data(C) >> 1)
#define WCB_WHILE(T,O) wc_bld(WC_WHILE, ((T) | ((O) << 1)))
#define WC_REPEAT_SKIP(C) wc_data(C)
#define WCB_REPEAT(O) wc_bld(WC_REPEAT, (O))
#define WC_CASE_TYPE(C) (wc_data(C) & 3)
#define WC_CASE_HEAD 0
#define WC_CASE_OR 1
#define WC_CASE_AND 2
#define WC_CASE_SKIP(C) (wc_data(C) >> 2)
#define WCB_CASE(T,O) wc_bld(WC_CASE, ((T) | ((O) << 2)))
#define WC_IF_TYPE(C) (wc_data(C) & 3)
#define WC_IF_HEAD 0
#define WC_IF_IF 1
#define WC_IF_ELIF 2
#define WC_IF_ELSE 3
#define WC_IF_SKIP(C) (wc_data(C) >> 2)
#define WCB_IF(T,O) wc_bld(WC_IF, ((T) | ((O) << 2)))
#define WC_COND_TYPE(C) (wc_data(C) & 127)
#define WC_COND_SKIP(C) (wc_data(C) >> 7)
#define WCB_COND(T,O) wc_bld(WC_COND, ((T) | ((O) << 7)))
#define WCB_ARITH() wc_bld(WC_ARITH, 0)
#define WCB_AUTOFN() wc_bld(WC_AUTOFN, 0)
/********************************************/
/* Defintions for job table and job control */
@ -845,7 +809,7 @@ struct shfunc {
HashNode next; /* next in hash chain */
char *nam; /* name of shell function */
int flags; /* various flags */
List funcdef; /* function definition */
Eprog funcdef; /* function definition */
};
/* Shell function context types. */
@ -860,7 +824,7 @@ struct shfunc {
/* node in list of function call wrappers */
typedef int (*WrapFunc) _((List, FuncWrap, char *));
typedef int (*WrapFunc) _((Eprog, FuncWrap, char *));
struct funcwrap {
FuncWrap next;
@ -996,7 +960,7 @@ struct patprog {
#define GF_MATCHREF 0x0800
/* Dummy Patprog pointers. Used mainly in executions trees, but the
* pattern code needs to knwo about it, too. */
* pattern code needs to know about it, too. */
#define dummy_patprog1 ((Patprog) 1)
#define dummy_patprog2 ((Patprog) 2)