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:
parent
cf10e60524
commit
63acd10601
21 changed files with 2472 additions and 1356 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
123
Src/cond.c
123
Src/cond.c
|
|
@ -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) {
|
||||
|
|
|
|||
664
Src/exec.c
664
Src/exec.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
16
Src/init.c
16
Src/init.c
|
|
@ -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;
|
||||
|
|
|
|||
283
Src/loop.c
283
Src/loop.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
1064
Src/parse.c
1064
Src/parse.c
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
848
Src/text.c
848
Src/text.c
|
|
@ -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--;
|
||||
}
|
||||
|
|
|
|||
272
Src/utils.c
272
Src/utils.c
|
|
@ -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
354
Src/zsh.h
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue