1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-11-28 03:10:56 +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 static int
ex_wrapper(List list, FuncWrap w, char *name) ex_wrapper(Eprog prog, FuncWrap w, char *name)
{ {
if (strncmp(name, "example", 7)) if (strncmp(name, "example", 7))
return 1; return 1;
@ -151,7 +151,7 @@ ex_wrapper(List list, FuncWrap w, char *name)
int ogd = opts[GLOBDOTS]; int ogd = opts[GLOBDOTS];
opts[GLOBDOTS] = 1; opts[GLOBDOTS] = 1;
runshfunc(list, w, name); runshfunc(prog, w, name);
opts[GLOBDOTS] = ogd; opts[GLOBDOTS] = ogd;
return 0; return 0;

View file

@ -339,23 +339,23 @@ setfunction(char *name, char *val, int dis)
{ {
char *value = dupstring(val); char *value = dupstring(val);
Shfunc shf; Shfunc shf;
List list; Eprog prog;
int sn; int sn;
val = metafy(val, strlen(val), META_REALLOC); val = metafy(val, strlen(val), META_REALLOC);
HEAPALLOC { HEAPALLOC {
list = parse_string(val, 1); prog = parse_string(val, 1);
} LASTALLOC; } LASTALLOC;
if (!list || list == &dummy_list) { if (!prog || prog == &dummy_eprog) {
zwarn("invalid function definition", value, 0); zwarn("invalid function definition", value, 0);
zsfree(val); zsfree(val);
return; return;
} }
PERMALLOC { PERMALLOC {
shf = (Shfunc) zalloc(sizeof(*shf)); shf = (Shfunc) zalloc(sizeof(*shf));
shf->funcdef = (List) dupstruct(list); shf->funcdef = dupeprog(prog);
shf->flags = dis; shf->flags = dis;
if (!strncmp(name, "TRAP", 4) && 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) ? "Ut" : "U") :
((shf->flags & PM_TAGGED) ? "t" : ""))); ((shf->flags & PM_TAGGED) ? "t" : "")));
} else { } else {
char *t = getpermtext((void *) dupstruct((void *) char *t = getpermtext(shf->funcdef, NULL), *h;
shf->funcdef)), *h;
h = dupstring(t); h = dupstring(t);
zsfree(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) ? "Ut" : "U") :
((shf->flags & PM_TAGGED) ? "t" : ""))); ((shf->flags & PM_TAGGED) ? "t" : "")));
} else { } else {
char *t = getpermtext((void *) char *t = getpermtext(((Shfunc) hn)->funcdef, NULL);
dupstruct((void *) ((Shfunc) hn)->funcdef));
pm.u.str = dupstring(t); pm.u.str = dupstring(t);
unmetafy(pm.u.str, NULL); unmetafy(pm.u.str, NULL);
@ -577,13 +575,13 @@ funcstackgetfn(Param pm)
/**/ /**/
static int static int
func_wrapper(List list, FuncWrap w, char *name) func_wrapper(Eprog prog, FuncWrap w, char *name)
{ {
PERMALLOC { PERMALLOC {
pushnode(funcstack, ztrdup(name)); pushnode(funcstack, ztrdup(name));
} LASTALLOC; } LASTALLOC;
runshfunc(list, w, name); runshfunc(prog, w, name);
DPUTS(strcmp(name, (char *) getdata(firstnode(funcstack))), DPUTS(strcmp(name, (char *) getdata(firstnode(funcstack))),
"funcstack wrapper with wrong function"); "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; char lsbuf[ZF_BUFSIZE], *ascbuf = NULL, *optr;
off_t sofar = 0, last_sofar = 0; off_t sofar = 0, last_sofar = 0;
readwrite_t read_ptr = zfread, write_ptr = zfwrite; 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. * progress to set up: ZFTP_COUNT is zero.
* We do this here in case we needed to wait for a RETR * 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; int osc = sfcontext;
sfcontext = SFC_HOOK; sfcontext = SFC_HOOK;
doshfunc("zftp_progress", l, NULL, 0, 1); doshfunc("zftp_progress", prog, NULL, 0, 1);
sfcontext = osc; sfcontext = osc;
/* Now add in the bit of the file we've got/sent already */ /* Now add in the bit of the file we've got/sent already */
sofar = last_sofar = startat; sofar = last_sofar = startat;
@ -1739,12 +1739,12 @@ zfsenddata(char *name, int recv, int progress, off_t startat)
} else } else
break; break;
if (!ret && sofar != last_sofar && progress && if (!ret && sofar != last_sofar && progress &&
(l = getshfunc("zftp_progress")) != &dummy_list) { (prog = getshfunc("zftp_progress")) != &dummy_eprog) {
int osc = sfcontext; int osc = sfcontext;
zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER); zfsetparam("ZFTP_COUNT", &sofar, ZFPM_READONLY|ZFPM_INTEGER);
sfcontext = SFC_HOOK; sfcontext = SFC_HOOK;
doshfunc("zftp_progress", l, NULL, 0, 1); doshfunc("zftp_progress", prog, NULL, 0, 1);
sfcontext = osc; sfcontext = osc;
last_sofar = sofar; last_sofar = sofar;
} }
@ -2444,7 +2444,7 @@ zfgetcwd(void)
{ {
char *ptr, *eptr; char *ptr, *eptr;
int endc; int endc;
List l; Eprog prog;
if (zfprefs & ZFPF_DUMB) if (zfprefs & ZFPF_DUMB)
return 1; return 1;
@ -2471,11 +2471,11 @@ zfgetcwd(void)
* front end. By putting it here, and in close when ZFTP_PWD is unset, * front end. By putting it here, and in close when ZFTP_PWD is unset,
* we at least cover the bases. * we at least cover the bases.
*/ */
if ((l = getshfunc("zftp_chpwd")) != &dummy_list) { if ((prog = getshfunc("zftp_chpwd")) != &dummy_eprog) {
int osc = sfcontext; int osc = sfcontext;
sfcontext = SFC_HOOK; sfcontext = SFC_HOOK;
doshfunc("zftp_chpwd", l, NULL, 0, 1); doshfunc("zftp_chpwd", prog, NULL, 0, 1);
sfcontext = osc; sfcontext = osc;
} }
return 0; 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; int ret = 0, recv = (flags & ZFTP_RECV), getsize = 0, progress = 1;
char *cmd = recv ? "RETR " : (flags & ZFTP_APPE) ? "APPE " : "STOR "; 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 * 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++) { for (; *args; args++) {
char *ln, *rest = NULL; char *ln, *rest = NULL;
off_t startat = 0; off_t startat = 0;
if (progress && (l = getshfunc("zftp_progress")) != &dummy_list) { if (progress && (prog = getshfunc("zftp_progress")) != &dummy_eprog) {
off_t sz; off_t sz;
/* /*
* This calls the SIZE command to get the size for remote * 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 and only if we called zfsenddata();
*/ */
if (progress && ret != 2 && 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 */ /* progress to finish: ZFTP_TRANSFER set to GF or PF */
int osc = sfcontext; int osc = sfcontext;
zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"), zfsetparam("ZFTP_TRANSFER", ztrdup(recv ? "GF" : "PF"),
ZFPM_READONLY); ZFPM_READONLY);
sfcontext = SFC_HOOK; sfcontext = SFC_HOOK;
doshfunc("zftp_progress", l, NULL, 0, 1); doshfunc("zftp_progress", prog, NULL, 0, 1);
sfcontext = osc; sfcontext = osc;
} }
if (rest) { if (rest) {
@ -2795,7 +2795,7 @@ static void
zfclose(int leaveparams) zfclose(int leaveparams)
{ {
char **aptr; char **aptr;
List l; Eprog prog;
if (zfsess->cfd == -1) if (zfsess->cfd == -1)
return; return;
@ -2837,11 +2837,11 @@ zfclose(int leaveparams)
zfunsetparam(*aptr); zfunsetparam(*aptr);
/* Now ZFTP_PWD is unset. It's up to zftp_chpwd to notice. */ /* 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; int osc = sfcontext;
sfcontext = SFC_HOOK; sfcontext = SFC_HOOK;
doshfunc("zftp_chpwd", l, NULL, 0, 1); doshfunc("zftp_chpwd", prog, NULL, 0, 1);
sfcontext = osc; sfcontext = osc;
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -47,15 +47,20 @@ mod_export int breaks;
/**/ /**/
int int
execfor(Cmd cmd, LinkList args, int flags) execfor(Estate state, int do_exec)
{ {
Forcmd node; Wordcode end, loop;
char *str; wordcode code = state->pc[-1];
int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND);
char *name, *str, *cond, *advance;
zlong val = 0; zlong val = 0;
LinkList args;
node = cmd->u.forcmd; name = ecgetstr(state, 0);
if (node->condition) { end = state->pc + WC_FOR_SKIP(code);
str = dupstring(node->name);
if (iscond) {
str = dupstring(name);
singsub(&str); singsub(&str);
if (isset(XTRACE)) { if (isset(XTRACE)) {
char *str2 = dupstring(str); char *str2 = dupstring(str);
@ -66,9 +71,19 @@ execfor(Cmd cmd, LinkList args, int flags)
} }
if (!errflag) if (!errflag)
matheval(str); matheval(str);
if (errflag) if (errflag) {
state->pc = end;
return lastval = errflag; 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; char **x;
args = newlinklist(); args = newlinklist();
@ -79,9 +94,10 @@ execfor(Cmd cmd, LinkList args, int flags)
loops++; loops++;
pushheap(); pushheap();
cmdpush(CS_FOR); cmdpush(CS_FOR);
loop = state->pc;
for (;;) { for (;;) {
if (node->condition) { if (iscond) {
str = dupstring(node->condition); str = dupstring(cond);
singsub(&str); singsub(&str);
if (!errflag) { if (!errflag) {
while (iblank(*str)) while (iblank(*str))
@ -109,21 +125,21 @@ execfor(Cmd cmd, LinkList args, int flags)
break; break;
if (isset(XTRACE)) { if (isset(XTRACE)) {
printprompt4(); printprompt4();
fprintf(stderr, "%s=%s\n", node->name, str); fprintf(stderr, "%s=%s\n", name, str);
fflush(stderr); fflush(stderr);
} }
setsparam(node->name, ztrdup(str)); setsparam(name, ztrdup(str));
} }
execlist(node->list, 1, state->pc = loop;
(flags & CFLAG_EXEC) && args && empty(args)); execlist(state, 1, do_exec && args && empty(args));
if (breaks) { if (breaks) {
breaks--; breaks--;
if (breaks || !contflag) if (breaks || !contflag)
break; break;
contflag = 0; contflag = 0;
} }
if (node->condition && !errflag) { if (iscond && !errflag) {
str = dupstring(node->advance); str = dupstring(advance);
if (isset(XTRACE)) { if (isset(XTRACE)) {
printprompt4(); printprompt4();
fprintf(stderr, "%s\n", str); fprintf(stderr, "%s\n", str);
@ -149,25 +165,37 @@ execfor(Cmd cmd, LinkList args, int flags)
/**/ /**/
int int
execselect(Cmd cmd, LinkList args, int flags) execselect(Estate state, int do_exec)
{ {
Forcmd node; Wordcode end, loop;
char *str, *s; wordcode code = state->pc[-1];
char *str, *s, *name;
LinkNode n; LinkNode n;
int i, usezle; int i, usezle;
FILE *inp; FILE *inp;
size_t more; size_t more;
LinkList args;
node = cmd->u.forcmd; end = state->pc + WC_FOR_SKIP(code);
if (!node->inflag) { name = ecgetstr(state, 0);
if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) {
char **x; char **x;
args = newlinklist(); args = newlinklist();
for (x = pparams; *x; x++) for (x = pparams; *x; x++)
addlinknode(args, dupstring(*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; return 1;
}
loops++; loops++;
lastval = 0; lastval = 0;
pushheap(); pushheap();
@ -175,6 +203,7 @@ execselect(Cmd cmd, LinkList args, int flags)
usezle = interact && SHTTY != -1 && isset(USEZLE); usezle = interact && SHTTY != -1 && isset(USEZLE);
inp = fdopen(dup(usezle ? SHTTY : 0), "r"); inp = fdopen(dup(usezle ? SHTTY : 0), "r");
more = selectlist(args, 0); more = selectlist(args, 0);
loop = state->pc;
for (;;) { for (;;) {
for (;;) { for (;;) {
if (empty(bufstack)) { if (empty(bufstack)) {
@ -219,8 +248,9 @@ execselect(Cmd cmd, LinkList args, int flags)
else else
str = ""; str = "";
} }
setsparam(node->name, ztrdup(str)); setsparam(name, ztrdup(str));
execlist(node->list, 1, 0); state->pc = loop;
execlist(state, 1, 0);
freeheap(); freeheap();
if (breaks) { if (breaks) {
breaks--; breaks--;
@ -236,6 +266,7 @@ execselect(Cmd cmd, LinkList args, int flags)
popheap(); popheap();
fclose(inp); fclose(inp);
loops--; loops--;
state->pc = end;
return lastval; return lastval;
} }
@ -302,28 +333,31 @@ selectlist(LinkList l, size_t start)
/**/ /**/
int int
execwhile(Cmd cmd, LinkList args, int flags) execwhile(Estate state, int do_exec)
{ {
struct whilecmd *node; Wordcode end, loop;
int olderrexit, oldval; 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; olderrexit = noerrexit;
node = cmd->u.whilecmd;
oldval = 0; oldval = 0;
pushheap(); pushheap();
cmdpush(node->cond ? CS_UNTIL : CS_WHILE); cmdpush(isuntil ? CS_UNTIL : CS_WHILE);
loops++; loops++;
loop = state->pc;
for (;;) { for (;;) {
state->pc = loop;
noerrexit = 1; noerrexit = 1;
execlist(node->cont, 1, 0); execlist(state, 1, 0);
noerrexit = olderrexit; noerrexit = olderrexit;
if (!((lastval == 0) ^ node->cond)) { if (!((lastval == 0) ^ isuntil)) {
if (breaks) if (breaks)
breaks--; breaks--;
lastval = oldval; lastval = oldval;
break; break;
} }
execlist(node->loop, 1, 0); execlist(state, 1, 0);
if (breaks) { if (breaks) {
breaks--; breaks--;
if (breaks || !contflag) if (breaks || !contflag)
@ -345,21 +379,26 @@ execwhile(Cmd cmd, LinkList args, int flags)
/**/ /**/
int int
execrepeat(Cmd cmd, LinkList args, int flags) execrepeat(Estate state, int do_exec)
{ {
Wordcode end, loop;
wordcode code = state->pc[-1];
int count; int count;
char *tmp;
end = state->pc + WC_REPEAT_SKIP(code);
lastval = 0; lastval = 0;
if (!args || empty(args) || nextnode(firstnode(args))) { tmp = ecgetstr(state, 1);
zerr("bad argument for repeat", NULL, 0); singsub(&tmp);
return 1; count = atoi(tmp);
}
count = atoi(peekfirst(args));
pushheap(); pushheap();
cmdpush(CS_REPEAT); cmdpush(CS_REPEAT);
loops++; loops++;
loop = state->pc;
while (count-- > 0) { while (count-- > 0) {
execlist(cmd->u.list, 1, 0); state->pc = loop;
execlist(state, 1, 0);
freeheap(); freeheap();
if (breaks) { if (breaks) {
breaks--; breaks--;
@ -375,114 +414,140 @@ execrepeat(Cmd cmd, LinkList args, int flags)
cmdpop(); cmdpop();
popheap(); popheap();
loops--; loops--;
state->pc = end;
return lastval; return lastval;
} }
/**/ /**/
int int
execif(Cmd cmd, LinkList args, int flags) execif(Estate state, int do_exec)
{ {
struct ifcmd *node; Wordcode end, next;
int olderrexit, s = 0; wordcode code = state->pc[-1];
List *i, *t; int olderrexit, s = 0, run = 0;
olderrexit = noerrexit; olderrexit = noerrexit;
node = cmd->u.ifcmd; end = state->pc + WC_IF_SKIP(code);
i = node->ifls;
t = node->thenls;
if (!noerrexit) if (!noerrexit)
noerrexit = 1; noerrexit = 1;
while (*i) { while (state->pc < end) {
cmdpush(s ? CS_ELIF : CS_IF); code = *state->pc++;
execlist(*i, 1, 0); if (wc_code(code) != WC_IF ||
cmdpop(); (run = (WC_IF_TYPE(code) == WC_IF_ELSE))) {
if (!lastval) if (run)
run = 2;
break; 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; s = 1;
i++; state->pc = next;
t++;
} }
noerrexit = olderrexit; noerrexit = olderrexit;
if (*t) { if (run) {
cmdpush(*i ? (s ? CS_ELIFTHEN : CS_IFTHEN) : CS_ELSE); cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN));
execlist(*t, 1, flags & CFLAG_EXEC); execlist(state, 1, do_exec);
cmdpop(); cmdpop();
} else } else
lastval = 0; lastval = 0;
state->pc = end;
return lastval; return lastval;
} }
/**/ /**/
int int
execcase(Cmd cmd, LinkList args, int flags) execcase(Estate state, int do_exec)
{ {
struct casecmd *node; Wordcode end, next;
char *word; wordcode code = state->pc[-1];
List *l; char *word, *pat;
char **p; int npat, save;
Patprog *pp, pprog; Patprog *spprog, pprog;
int save;
node = cmd->u.casecmd; end = state->pc + WC_CASE_SKIP(code);
l = node->lists;
p = node->pats;
pp = node->progs;
word = dupstring(*p++); word = ecgetstr(state, 1);
singsub(&word); singsub(&word);
untokenize(word); untokenize(word);
lastval = 0; lastval = 0;
if (node) { cmdpush(CS_CASE);
cmdpush(CS_CASE); while (state->pc < end) {
while (*p) { code = *state->pc++;
char *pat = NULL, *opat; if (wc_code(code) != WC_CASE)
break;
pprog = NULL; pat = NULL;
save = 0; pprog = NULL;
save = 0;
npat = state->pc[1];
spprog = state->prog->pats + npat;
if (isset(XTRACE)) { next = state->pc + WC_CASE_SKIP(code);
char *pat2;
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); singsub(&pat);
save = (!strcmp(pat, opat) && *pp != dummy_patprog2); 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);
} }
if (*pp != dummy_patprog1 && *pp != dummy_patprog2) if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
pprog = *pp; NULL)))
zerr("bad pattern: %s", pat, 0);
if (!pprog) { else if (save)
if (!pat) { *spprog = pprog;
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++;
} }
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; 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 */ /* trap functions for each signal */
/**/ /**/
mod_export List sigfuncs[VSIGCOUNT]; mod_export Eprog sigfuncs[VSIGCOUNT];
/* Variables used by signal queueing */ /* Variables used by signal queueing */
@ -674,7 +674,7 @@ dosavetrap(int sig, int level)
/**/ /**/
mod_export int mod_export int
settrap(int sig, List l) settrap(int sig, Eprog l)
{ {
if (sig == -1) if (sig == -1)
return 1; return 1;
@ -773,7 +773,7 @@ unsettrap(int sig)
if ((hn = removehashnode(shfunctab, func))) if ((hn = removehashnode(shfunctab, func)))
shfunctab->freenode(hn); shfunctab->freenode(hn);
} else if (sigfuncs[sig]) { } else if (sigfuncs[sig]) {
freestruct(sigfuncs[sig]); freeeprog(sigfuncs[sig]);
sigfuncs[sig] = NULL; sigfuncs[sig] = NULL;
} }
} }
@ -834,12 +834,12 @@ endtrapscope(void)
unsettrap(sig); unsettrap(sig);
sigtrapped[sig] = st->flags; sigtrapped[sig] = st->flags;
if (st->flags) { if (st->flags) {
List list = (st->flags & ZSIG_FUNC) ? Eprog prog = (st->flags & ZSIG_FUNC) ?
((Shfunc) st->list)->funcdef : (List) st->list; ((Shfunc) st->list)->funcdef : (Eprog) st->list;
/* prevent settrap from saving this */ /* prevent settrap from saving this */
int oldlt = opts[LOCALTRAPS]; int oldlt = opts[LOCALTRAPS];
opts[LOCALTRAPS] = 0; opts[LOCALTRAPS] = 0;
settrap(sig, list); settrap(sig, prog);
opts[LOCALTRAPS] = oldlt; opts[LOCALTRAPS] = oldlt;
if ((sigtrapped[sig] = st->flags) & ZSIG_FUNC) if ((sigtrapped[sig] = st->flags) & ZSIG_FUNC)
shfunctab->addnode(shfunctab, ((Shfunc)st->list)->nam, shfunctab->addnode(shfunctab, ((Shfunc)st->list)->nam,
@ -851,11 +851,11 @@ endtrapscope(void)
if (exittr) { if (exittr) {
dotrapargs(SIGEXIT, &exittr, (exittr & ZSIG_FUNC) ? dotrapargs(SIGEXIT, &exittr, (exittr & ZSIG_FUNC) ?
((Shfunc)exitfn)->funcdef : (List) exitfn); ((Shfunc)exitfn)->funcdef : (Eprog) exitfn);
if (exittr & ZSIG_FUNC) if (exittr & ZSIG_FUNC)
shfunctab->freenode((HashNode)exitfn); shfunctab->freenode((HashNode)exitfn);
else else
freestruct(exitfn); freeeprog(exitfn);
} }
} }

View file

@ -31,7 +31,7 @@
#include "text.pro" #include "text.pro"
static char *tptr, *tbuf, *tlim; static char *tptr, *tbuf, *tlim;
static int tsiz, tindent, tnewlins; static int tsiz, tindent, tnewlins, tjob;
/* add a character to the text buffer */ /* add a character to the text buffer */
@ -72,18 +72,18 @@ taddstr(char *s)
tptr += sl; tptr += sl;
} }
/* add an integer to the text buffer */ /**/
static void
#if 0 /**/ taddlist(Estate state, int num)
void
taddint(int x)
{ {
char buf[DIGBUFSIZE]; if (num) {
while (num--) {
sprintf(buf, "%d", x); taddstr(ecgetstr(state, 0));
taddstr(buf); taddchr(' ');
}
tptr--;
}
} }
#endif
/* add a newline, or something equivalent, to the text buffer */ /* add a newline, or something equivalent, to the text buffer */
@ -105,14 +105,24 @@ taddnl(void)
/**/ /**/
mod_export char * 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; tnewlins = 1;
tbuf = (char *)zalloc(tsiz = 32); tbuf = (char *)zalloc(tsiz = 32);
tptr = tbuf; tptr = tbuf;
tlim = tbuf + tsiz; tlim = tbuf + tsiz;
tindent = 1; tindent = 1;
gettext2(n); tjob = 0;
gettext2(&s);
*tptr = '\0'; *tptr = '\0';
untokenize(tbuf); untokenize(tbuf);
return tbuf; return tbuf;
@ -122,366 +132,566 @@ getpermtext(struct node *n)
/**/ /**/
char * char *
getjobtext(struct node *n) getjobtext(Eprog prog, Wordcode c)
{ {
static char jbuf[JOBTEXTSIZE]; static char jbuf[JOBTEXTSIZE];
struct estate s;
if (!c)
c = prog->prog;
s.prog = prog;
s.pc = c;
s.strs = prog->strs;
tnewlins = 0; tnewlins = 0;
tbuf = NULL; tbuf = NULL;
tptr = jbuf; tptr = jbuf;
tlim = tptr + JOBTEXTSIZE - 1; tlim = tptr + JOBTEXTSIZE - 1;
tindent = 1; tindent = 1;
gettext2(n); tjob = 1;
gettext2(&s);
*tptr = '\0'; *tptr = '\0';
untokenize(jbuf); untokenize(jbuf);
return jbuf; return jbuf;
} }
#define gt2(X) gettext2((struct node *) (X))
/* /*
"gettext2" or "type checking and how to avoid it" * gettext2() shows one way to walk through the word code without
an epic function by Paul Falstad * 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)) typedef struct tstack *Tstack;
#define _Cmd(X) ((Cmd) (X))
#define _Pline(X) ((Pline) (X)) struct tstack {
#define _Sublist(X) ((Sublist) (X)) Tstack prev;
#define _List(X) ((List) (X)) wordcode code;
#define _casecmd(X) ((struct casecmd *) (X)) int pop;
#define _ifcmd(X) ((struct ifcmd *) (X)) union {
#define _whilecmd(X) ((struct whilecmd *) (X)) 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 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) while (1) {
return; if (stack) {
switch (NT_TYPE(n->ntype)) { if (!(s = tstack))
case N_LIST: return;
gt2(_List(n)->left); if (s->pop) {
if (_List(n)->type & Z_ASYNC) { tstack = s->prev;
taddstr(" &"); s->prev = tfree;
if (_List(n)->type & Z_DISOWN) tfree = s;
taddstr("|"); }
code = s->code;
stack = 0;
} else {
s = NULL;
code = *state->pc++;
} }
if (_List(n)->right) { switch (wc_code(code)) {
if (tnewlins) case WC_LIST:
taddnl(); if (!s) {
else tpush(code, (WC_LIST_TYPE(code) & Z_END));
taddstr((_List(n)->type & Z_ASYNC) ? " " : "; "); stack = 0;
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");
} else { } else {
taddstr(nn->u.forcmd->name); if (WC_LIST_TYPE(code) & Z_ASYNC) {
if (nn->u.forcmd->inflag) { taddstr(" &");
taddstr(" in "); if (WC_LIST_TYPE(code) & Z_DISOWN)
taddlist(nn->args); 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(); taddnl();
taddstr("do"); 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; break;
case CIF: case WC_REPEAT:
gt2(nn->u.ifcmd); if (!s) {
taddstr("fi"); taddstr("repeat ");
taddstr(ecgetstr(state, 0));
taddnl();
taddstr("do");
tindent++;
taddnl();
tpush(code, 1);
} else {
tindent--;
taddnl();
taddstr("done");
stack = 1;
}
break; break;
case CCASE: case WC_CASE:
gt2(nn->u.casecmd); if (!s) {
break; Wordcode end = state->pc + WC_CASE_SKIP(code);
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;
l = _casecmd(n)->lists; taddstr("case ");
p = _casecmd(n)->pats; taddstr(ecgetstr(state, 0));
taddstr(" in");
taddstr("case "); if (state->pc >= end) {
taddstr(*p++); if (tnewlins)
taddstr(" in"); taddnl();
tindent++; else
for (; l && *l; p++, l++) { 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) if (tnewlins)
taddnl(); taddnl();
else else
taddchr(' '); taddchr(' ');
taddstr(*p + 1); code = *state->pc++;
taddstr(ecgetstr(state, 0));
state->pc++;
taddstr(") "); taddstr(") ");
tindent++; tindent++;
gt2(*l); s->code = code;
s->pop = ((state->pc - 2 + WC_CASE_SKIP(code)) >=
s->u._case.end);
} else {
tindent--; tindent--;
taddstr(" ;"); taddstr(WC_CASE_TYPE(code) == WC_CASE_OR ? " ;;" : ";&");
taddchr(**p); tindent--;
if (tnewlins)
taddnl();
else
taddchr(' ');
taddstr("esac");
stack = 1;
} }
tindent--;
if (tnewlins)
taddnl();
else
taddchr(' ');
taddstr("esac");
break; break;
} case WC_IF:
case N_IF: if (!s) {
{ Wordcode end = state->pc + WC_IF_SKIP(code);
List *i, *t;
taddstr("if "); taddstr("if ");
for (i = _ifcmd(n)->ifls, t = _ifcmd(n)->thenls; *i; i++, t++) {
tindent++; 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--; tindent--;
taddnl(); taddnl();
taddstr("then"); taddstr("then");
tindent++; tindent++;
taddnl(); taddnl();
gt2(*t); s->u._if.cond = 0;
} else if (state->pc < s->u._if.end) {
tindent--; tindent--;
taddnl(); taddnl();
if (i[1]) { code = *state->pc++;
if (WC_IF_TYPE(code) == WC_IF_ELIF) {
taddstr("elif "); taddstr("elif ");
tindent++;
s->u._if.cond = 1;
} else {
taddstr("else");
tindent++;
taddnl();
} }
} } else {
if (*t) { s->pop = 1;
taddstr("else");
tindent++;
taddnl();
gt2(*t);
tindent--; tindent--;
taddnl(); taddnl();
taddstr("fi");
stack = 1;
} }
break; break;
} case WC_COND:
case N_WHILE: {
taddstr((_whilecmd(n)->cond) ? "until " : "while "); static char *c1[] = {
tindent++; "=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
gt2(_whilecmd(n)->cont); "-ne", "-lt", "-gt", "-le", "-ge"
tindent--; };
taddnl();
taddstr("do");
tindent++;
taddnl();
gt2(_whilecmd(n)->loop);
tindent--;
taddnl();
taddstr("done");
break;
}
}
/* Print a condition bracketed by [[ ... ]]. * int ctype;
* With addpar non-zero, parenthesise the subexpression. */
/**/ if (!s) {
static void taddstr("[[ ");
getcond(Cond nm, int addpar) n = tpush(code, 1);
{ n->u._cond.par = 2;
static char *c1[] = } else if (s->u._cond.par == 2) {
{ taddstr(" ]]");
"=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq", stack = 1;
"-ne", "-lt", "-gt", "-le", "-ge" 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(ecgetstr(state, 0));
taddstr("( "); taddchr(' ');
switch (nm->type) { taddstr(name);
case COND_NOT: taddchr(' ');
taddstr("! "); taddstr(ecgetstr(state, 0));
getcond(nm->left, _Cond(nm->left)->type <= COND_OR); stack = 1;
break; }
case COND_AND: break;
getcond(nm->left, _Cond(nm->left)->type == COND_OR); default:
taddstr(" && "); if (ctype <= COND_GE) {
getcond(nm->right, _Cond(nm->right)->type == COND_OR); /* Binary test: `a = b' etc. */
break; taddstr(ecgetstr(state, 0));
case COND_OR: taddstr(" ");
/* This is deliberately over-generous with parentheses: * taddstr(c1[ctype - COND_STREQ]);
* in fact omitting them gives correct precedence. */ taddstr(" ");
getcond(nm->left, _Cond(nm->left)->type == COND_AND); taddstr(ecgetstr(state, 0));
taddstr(" || "); if (ctype == COND_STREQ ||
getcond(nm->right, _Cond(nm->right)->type == COND_AND); ctype == COND_STRNEQ)
break; state->pc++;
case COND_MOD: } else {
{ /* Unary test: `-f foo' etc. */
/* Module defined prefix condition. */ char c2[4];
char **p = (char **) nm->right;
taddstr(nm->left); c2[0] = '-';
for (; *p; p++) { c2[1] = ctype;
taddstr(" "); c2[2] = ' ';
taddstr(*p); 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 void
getredirs(Cmd cmd) getredirs(LinkList redirs)
{ {
LinkNode n; LinkNode n;
static char *fstr[] = static char *fstr[] =
@ -489,12 +699,9 @@ getredirs(Cmd cmd)
">", ">|", ">>", ">>|", "&>", "&>|", "&>>", "&>>|", "<>", "<", ">", ">|", ">>", ">>|", "&>", "&>|", "&>>", "&>>|", "<>", "<",
"<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">" "<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">"
}; };
if (!cmd->redir)
return;
taddchr(' '); taddchr(' ');
for (n = firstnode(cmd->redir); n; incnode(n)) { for (n = firstnode(redirs); n; incnode(n)) {
struct redir *f = (struct redir *)getdata(n); Redir f = (Redir) getdata(n);
switch (f->type) { switch (f->type) {
case WRITE: case WRITE:
@ -532,18 +739,3 @@ getredirs(Cmd cmd)
} }
tptr--; 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; static time_t lastperiodic;
LinkNode ln; LinkNode ln;
List list; Eprog prog;
int period = getiparam("PERIOD"); int period = getiparam("PERIOD");
int mailcheck = getiparam("MAILCHECK"); int mailcheck = getiparam("MAILCHECK");
@ -643,11 +643,11 @@ preprompt(void)
/* If a shell function named "precmd" exists, * /* If a shell function named "precmd" exists, *
* then execute it. */ * then execute it. */
if ((list = getshfunc("precmd")) != &dummy_list) { if ((prog = getshfunc("precmd")) != &dummy_eprog) {
int osc = sfcontext; int osc = sfcontext;
sfcontext = SFC_HOOK; sfcontext = SFC_HOOK;
doshfunc("precmd", list, NULL, 0, 1); doshfunc("precmd", prog, NULL, 0, 1);
sfcontext = osc; sfcontext = osc;
} }
if (errflag) if (errflag)
@ -657,11 +657,11 @@ preprompt(void)
* "periodic" exists, 3) it's been greater than PERIOD since we * * "periodic" exists, 3) it's been greater than PERIOD since we *
* executed "periodic", then execute it now. */ * executed "periodic", then execute it now. */
if (period && (time(NULL) > lastperiodic + period) && if (period && (time(NULL) > lastperiodic + period) &&
(list = getshfunc("periodic")) != &dummy_list) { (prog = getshfunc("periodic")) != &dummy_eprog) {
int osc = sfcontext; int osc = sfcontext;
sfcontext = SFC_HOOK; sfcontext = SFC_HOOK;
doshfunc("periodic", list, NULL, 0, 1); doshfunc("periodic", prog, NULL, 0, 1);
sfcontext = osc; sfcontext = osc;
lastperiodic = time(NULL); lastperiodic = time(NULL);
} }
@ -1890,275 +1890,17 @@ sepsplit(char *s, char *sep, int allownull)
/* Get the definition of a shell function */ /* Get the definition of a shell function */
/**/ /**/
mod_export List mod_export Eprog
getshfunc(char *nam) getshfunc(char *nam)
{ {
Shfunc shf; Shfunc shf;
if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, nam))) if (!(shf = (Shfunc) shfunctab->getnode(shfunctab, nam)))
return &dummy_list; return &dummy_eprog;
return shf->funcdef; 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 ** char **
mkarray(char *s) mkarray(char *s)

354
Src/zsh.h
View file

@ -306,20 +306,12 @@ typedef struct patprog *Patprog;
typedef struct process *Process; typedef struct process *Process;
typedef struct job *Job; typedef struct job *Job;
typedef struct value *Value; typedef struct value *Value;
typedef struct varasg *Varasg;
typedef struct cond *Cond;
typedef struct conddef *Conddef; 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 redir *Redir;
typedef struct complist *Complist; typedef struct complist *Complist;
typedef struct heap *Heap; typedef struct heap *Heap;
typedef struct heapstack *Heapstack; typedef struct heapstack *Heapstack;
typedef struct histent *Histent; typedef struct histent *Histent;
typedef struct forcmd *Forcmd;
typedef struct autofn *AutoFn;
typedef struct hookdef *Hookdef; typedef struct hookdef *Hookdef;
typedef struct asgment *Asgment; typedef struct asgment *Asgment;
@ -365,148 +357,16 @@ struct linklist {
/* Definitions for syntax trees */ /* 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 * /* These are control flags that are passed *
* down the execution pipeline. */ * down the execution pipeline. */
#define Z_TIMED (1<<0) /* pipeline is being timed */ #define Z_TIMED (1<<0) /* pipeline is being timed */
#define Z_SYNC (1<<1) /* run this sublist synchronously (;) */ #define Z_SYNC (1<<1) /* run this sublist synchronously (;) */
#define Z_ASYNC (1<<2) /* run this sublist asynchronously (&) */ #define Z_ASYNC (1<<2) /* run this sublist asynchronously (&) */
#define Z_DISOWN (1<<3) /* run this sublist without job control (&|) */ #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 */ /* flags for command modifiers */
#define CFLAG_EXEC (1<<0) /* exec ... */ #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_NOT 0
#define COND_AND 1 #define COND_AND 1
#define COND_OR 2 #define COND_OR 2
@ -545,42 +405,12 @@ struct conddef {
#define CONDDEF(name, flags, handler, min, max, condid) \ #define CONDDEF(name, flags, handler, min, max, condid) \
{ NULL, name, flags, handler, min, max, condid, NULL } { NULL, name, flags, handler, min, max, condid, NULL }
struct forcmd { /* for/select */ /* tree element for redirection lists */
/* 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 */
};
struct casecmd { struct redir {
/* Cmd->args contains word to test */ int type;
int ntype; /* node type */ int fd1, fd2;
char **pats; /* pattern strings */ char *name;
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 */
}; };
/* The number of fds space is allocated for * /* 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 */ int fds[MULTIOUNIT]; /* list of src/dests redirected to/from this fd */
}; };
/* variable assignment tree element */ /* structure for foo=bar assignments */
struct varasg { struct asgment {
int ntype; /* node type */ struct asgment *next;
int type; /* nonzero means array */
char *name; char *name;
char *str; /* should've been a union here. oh well */ char *value;
LinkList arr;
}; };
/* lvalue for variable assignment/expansion */ /* lvalue for variable assignment/expansion */
@ -623,16 +451,152 @@ struct value {
char **arr; /* cache for hash turned into array */ 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 #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 */ /* Defintions for job table and job control */
@ -845,7 +809,7 @@ struct shfunc {
HashNode next; /* next in hash chain */ HashNode next; /* next in hash chain */
char *nam; /* name of shell function */ char *nam; /* name of shell function */
int flags; /* various flags */ int flags; /* various flags */
List funcdef; /* function definition */ Eprog funcdef; /* function definition */
}; };
/* Shell function context types. */ /* Shell function context types. */
@ -860,7 +824,7 @@ struct shfunc {
/* node in list of function call wrappers */ /* node in list of function call wrappers */
typedef int (*WrapFunc) _((List, FuncWrap, char *)); typedef int (*WrapFunc) _((Eprog, FuncWrap, char *));
struct funcwrap { struct funcwrap {
FuncWrap next; FuncWrap next;
@ -996,7 +960,7 @@ struct patprog {
#define GF_MATCHREF 0x0800 #define GF_MATCHREF 0x0800
/* Dummy Patprog pointers. Used mainly in executions trees, but the /* 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_patprog1 ((Patprog) 1)
#define dummy_patprog2 ((Patprog) 2) #define dummy_patprog2 ((Patprog) 2)