1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-12-07 18:11:20 +01:00

27951: Add $ZSH_EVAL_CONTEXT and $zsh_eval_contxt

This commit is contained in:
Peter Stephenson 2010-05-12 10:06:59 +00:00
parent cb8ddf171e
commit 09960dc5b9
12 changed files with 188 additions and 38 deletions

View file

@ -1,3 +1,11 @@
2010-05-12 Peter Stephenson <pws@csr.com>
* 27951: Doc/Zsh/expn.yo, Doc/Zsh/params.yo, Src/builtin.c,
Src/exec.c, Src/glob.c, Src/init.c, Src/params.c, Src/signals.c,
Src/Builtins/sched.c, Src/Modules/zpty.c, Src/Modules/zutil.c:
Add $ZSH_EVAL_CONTEXT and $zsh_eval_context to provide context
stack.
2010-05-10 Peter Stephenson <pws@csr.com>
* c.f. 27950: Test/C03traps.ztst some bogus whitespace got added
@ -13122,5 +13130,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
* $Revision: 1.4975 $
* $Revision: 1.4976 $
*****************************************************

View file

@ -2149,12 +2149,17 @@ xitem(tt(e)var(string))
item(tt(PLUS())var(cmd))(
The var(string) will be executed as shell code. The filename will be
included in the list if and only if the code returns a zero status (usually
the status of the last command). The first character after the `tt(e)'
the status of the last command).
In the first form, the first character after the `tt(e)'
will be used as a separator and anything up to the next matching separator
will be taken as the var(string); `tt([)', `tt({)', and `tt(<)' match
`tt(])', `tt(})', and `tt(>)', respectively, while any other character
matches itself. Note that expansions must be quoted in the var(string)
to prevent them from being expanded before globbing is done.
var(string) is then executed as shell code. The string tt(globqual)
is appended to the array tt(zsh_eval_context) the duration of
execution.
vindex(REPLY, use of)
vindex(reply, use of)
@ -2288,12 +2293,13 @@ specifiers may occur to resolve ties.
tt(oe) and tt(o+) are special cases; they are each followed by shell code,
delimited as for the tt(e) glob qualifier and the tt(+) glob qualifier
respectively (see above). The code is executed for each matched file with
the parameter tt(REPLY) set to the name of the file on entry. The code
should modify the parameter tt(REPLY) in some fashion. On return, the value
of the parameter is used instead of the file name as the string on which to
sort. Unlike other sort operators, tt(oe) and tt(o+) may be repeated, but
note that the maximum number of sort operators of any kind that may appear
in any glob expression is 12.
the parameter tt(REPLY) set to the name of the file on entry and
tt(globsort) appended to tt(zsh_eval_context). The code
should modify the parameter tt(REPLY) in some fashion. On return, the
value of the parameter is used instead of the file name as the string on
which to sort. Unlike other sort operators, tt(oe) and tt(o+) may be
repeated, but note that the maximum number of sort operators of any kind
that may appear in any glob expression is 12.
)
item(tt(O)var(c))(
like `tt(o)', but sorts in descending order; i.e. `tt(*(^oc))' is the

View file

@ -722,6 +722,100 @@ vindex(VENDOR)
item(tt(VENDOR))(
The vendor, as determined at compile time.
)
vindex(zsh_eval_context)
vindex(ZSH_EVAL_CONTEXT)
item(tt(zsh_eval_context) <S> <Z> (tt(ZSH_EVAL_CONTEXT) <S>))(
An array (colon-separated list) indicating the context of shell
code that is being run. Each time a piece of shell code that
is stored within the shell is executed a string is temporarily appended to
the array to indicate the type of operation that is being performed.
Read in order the array gives an indication of the stack of
operations being performed with the most immediate context last.
The context is one of the following:
startitem()
item(tt(cmdarg))(
Code specified by the tt(-c) option to the command line that invoked
the shell.
)
item(tt(cmdsubst))(
Command substitution using the tt(`)var(...)tt(`) or
tt($+LPAR())var(...)tt(RPAR()) construct.
)
item(tt(equalsubst))(
File substitution using the tt(=+LPAR())var(...)tt(RPAR()) construct.
)
item(tt(eval))(
Code executed by the tt(eval) builtin.
)
item(tt(evalautofunc))(
Code executed with the tt(KSH_AUTOLOAD) mechanism in order to define
an autoloaded function.
)
item(tt(fc))(
Code from the shell history executed by the tt(-e) option to the tt(fc)
builtin.
)
item(tt(file))(
Lines of code being read directly from a file, for example by
the tt(source) builtin.
)
item(tt(filecode))(
Lines of code being read from a tt(.zwc) file instead of directly
from the source file.
)
item(tt(globqual))(
Code executed by the tt(e) or tt(+) glob qualifier.
)
item(tt(globsort))(
Code executed to order files by the tt(o) glob qualifier.
)
item(tt(insubst))(
File substitution using the tt(<LPAR())var(...)tt(RPAR()) construct.
)
item(tt(loadautofunc))(
Code read directly from a file to define an autoloaded function.
)
item(tt(outsubst))(
File substitution using the tt(>LPAR())var(...)tt(RPAR()) construct.
)
item(tt(sched))(
Code executed by the tt(sched) builtin.
)
item(tt(shfunc))(
A shell function.
)
item(tt(stty))(
Code passed to tt(stty) by the tt(STTY) environment variable.
Normally this is passed directly to the system's tt(stty) command,
so this value is unlikely to be seen in practice.
)
item(tt(style))(
Code executed as part of a style retrieved by the tt(zstyle) builtin
from the tt(zsh/zutil) module.
)
item(tt(toplevel))(
The highest execution level of a script or interactive shell.
)
item(tt(trap))(
Code executed as a trap defined by the tt(trap) builtin. Traps
defined as functions have the context tt(shfunc). As traps are
asynchronous they may have a different hierarchy from other
code.
)
item(tt(zpty))(
Code executed by the tt(zpty) builtin from the tt(zsh/zpty) module.
)
item(tt(zregesparse-guard))(
Code executed as a guard by the tt(zregexparse) command from the
tt(zsh/zutil) module.
)
item(tt(zregexparse-action))(
Code executed as an action by the tt(zregexparse) command from the
tt(zsh/zutil) module.
)
enditem()
)
vindex(ZSH_NAME)
item(tt(ZSH_NAME))(
Expands to the basename of the command used to invoke this instance

View file

@ -119,7 +119,7 @@ checksched(void)
if ((sch->flags & SCHEDFLAG_TRASH_ZLE) && zleactive)
zleentry(ZLE_CMD_TRASH);
execstring(sch->cmd, 0, 0);
execstring(sch->cmd, 0, 0, "sched");
zsfree(sch->cmd);
zfree(sch, sizeof(struct schedcmd));

View file

@ -396,7 +396,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
setsparam("TTY", ztrdup(ttystrname));
opts[INTERACTIVE] = 0;
execode(prog, 1, 0);
execode(prog, 1, 0, "zpty");
stopmsg = 2;
zexit(lastval, 0);
}

View file

@ -343,7 +343,7 @@ evalstyle(Stypat p)
char **ret, *str;
unsetparam("reply");
execode(p->eval, 1, 0);
execode(p->eval, 1, 0, "style");
if (errflag) {
errflag = ef;
return NULL;
@ -1253,7 +1253,7 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
char *action = getdata(ln);
if (action)
execstring(action, 1, 0);
execstring(action, 1, 0, "zregexparse-action");
}
return 0;
}
@ -1278,7 +1278,8 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
return 3;
}
if (next->pattern && pattry(next->patprog, subj) &&
(!next->guard || (execstring(next->guard, 1, 0), !lastval))) {
(!next->guard || (execstring(next->guard, 1, 0,
"zregesparse-guard"), !lastval))) {
LinkNode aln;
char **mend;
int len;
@ -1299,7 +1300,7 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
char *action = getdata(aln);
if (action)
execstring(action, 1, 0);
execstring(action, 1, 0, "zregexparse-action");
}
restorematch(&match2);
@ -1328,7 +1329,7 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
char *action = getdata(ln);
if (action)
execstring(action, 1, 0);
execstring(action, 1, 0, "zregexparse-action");
}
return 0;
}
@ -1339,7 +1340,7 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
for (ln = firstnode(nexts); ln; ln = nextnode(ln)) {
br = getdata(ln);
if (br->state->action)
execstring(br->state->action, 1, 0);
execstring(br->state->action, 1, 0, "zregexparse-action");
}
}
return empty(nexts) ? 2 : 1;

View file

@ -1755,7 +1755,7 @@ fcedit(char *ename, char *fn)
return 1;
s = tricat(ename, " ", fn);
execstring(s, 1, 0);
execstring(s, 1, 0, "fc");
zsfree(s);
return !lastval;
@ -4883,7 +4883,7 @@ eval(char **argv)
/* No code to execute */
lastval = 0;
} else {
execode(prog, 1, 0);
execode(prog, 1, 0, "eval");
if (errflag && !lastval)
lastval = errflag;

View file

@ -564,7 +564,7 @@ execute(LinkList args, int flags, int defpath)
STTYval = 0; /* this prevents infinite recursion */
zsfree(s);
execstring(t, 1, 0);
execstring(t, 1, 0, "stty");
zsfree(t);
} else if (s) {
STTYval = 0;
@ -970,21 +970,40 @@ entersubsh(int flags)
/**/
mod_export void
execstring(char *s, int dont_change_job, int exiting)
execstring(char *s, int dont_change_job, int exiting, char *context)
{
Eprog prog;
pushheap();
if ((prog = parse_string(s, 0)))
execode(prog, dont_change_job, exiting);
execode(prog, dont_change_job, exiting, context);
popheap();
}
/**/
mod_export void
execode(Eprog p, int dont_change_job, int exiting)
execode(Eprog p, int dont_change_job, int exiting, char *context)
{
struct estate s;
static int zsh_eval_context_len;
int alen;
if (!zsh_eval_context_len) {
zsh_eval_context_len = 16;
alen = 0;
zsh_eval_context = (char **)zalloc(zsh_eval_context_len *
sizeof(*zsh_eval_context));
} else {
alen = arrlen(zsh_eval_context);
if (zsh_eval_context_len == alen + 1) {
zsh_eval_context_len *= 2;
zsh_eval_context = zrealloc(zsh_eval_context,
zsh_eval_context_len *
sizeof(*zsh_eval_context));
}
}
zsh_eval_context[alen] = context;
zsh_eval_context[alen+1] = NULL;
s.prog = p;
s.pc = p->prog;
@ -994,6 +1013,12 @@ execode(Eprog p, int dont_change_job, int exiting)
execlist(&s, dont_change_job, exiting);
freeeprog(p); /* Free if now unused */
/*
* zsh_eval_context may have been altered by a recursive
* call, but that's OK since we're using the global value.
*/
zsh_eval_context[alen] = NULL;
}
/* Execute a simplified command. This is used to execute things that
@ -3571,7 +3596,7 @@ getoutput(char *cmd, int qt)
redup(pipes[1], 1);
entersubsh(ESUB_PGRP|ESUB_NOMONITOR);
cmdpush(CS_CMDSUBST);
execode(prog, 0, 1);
execode(prog, 0, 1, "cmdsubst");
cmdpop();
close(1);
_exit(lastval);
@ -3725,7 +3750,7 @@ getoutputfile(char *cmd, char **eptr)
redup(fd, 1);
entersubsh(ESUB_PGRP|ESUB_NOMONITOR);
cmdpush(CS_CMDSUBST);
execode(prog, 0, 1);
execode(prog, 0, 1, "equalsubst");
cmdpop();
close(1);
_exit(lastval);
@ -3827,7 +3852,7 @@ getproc(char *cmd, char **eptr)
#endif /* PATH_DEV_FD */
cmdpush(CS_CMDSUBST);
execode(prog, 0, 1);
execode(prog, 0, 1, out ? "outsubst" : "insubst");
cmdpop();
zclose(out);
_exit(lastval);
@ -3875,7 +3900,7 @@ getpipe(char *cmd, int nullexec)
redup(pipes[out], out);
closem(FDT_UNUSED); /* this closes pipes[!out] as well */
cmdpush(CS_CMDSUBST);
execode(prog, 0, 1);
execode(prog, 0, 1, out ? "outsubst" : "insubst");
cmdpop();
_exit(lastval);
return 0;
@ -4196,7 +4221,7 @@ execautofn(Estate state, UNUSED(int do_exec))
oldscriptname = scriptname;
oldscriptfilename = scriptfilename;
scriptname = scriptfilename = dupstring(shf->node.nam);
execode(shf->funcdef, 1, 0);
execode(shf->funcdef, 1, 0, "loadautofunc");
scriptname = oldscriptname;
scriptfilename = oldscriptfilename;
@ -4250,7 +4275,7 @@ loadautofn(Shfunc shf, int fksh, int autol)
} else {
VARARR(char, n, strlen(shf->node.nam) + 1);
strcpy(n, shf->node.nam);
execode(prog, 1, 0);
execode(prog, 1, 0, "evalautofunc");
shf = (Shfunc) shfunctab->getnode(shfunctab, n);
if (!shf || (shf->node.flags & PM_UNDEFINED)) {
/* We're not actually in the function; decrement locallevel */
@ -4538,7 +4563,7 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
wrap = wrap->next;
}
startparamscope();
execode(prog, 1, 0);
execode(prog, 1, 0, "shfunc");
if (ou) {
setunderscore(ou);
zfree(ou, ouu);

View file

@ -1806,7 +1806,7 @@ zglob(LinkList list, LinkNode np, int nountok)
/* Parsed OK, execute for each name */
for (tmpptr = matchbuf; tmpptr < matchptr; tmpptr++) {
setsparam("REPLY", ztrdup(tmpptr->name));
execode(prog, 1, 0);
execode(prog, 1, 0, "globsort");
if (!errflag)
tmpptr->sortstrs[iexec] =
dupstring(getsparam("REPLY"));
@ -3497,7 +3497,7 @@ qualsheval(char *name, UNUSED(struct stat *buf), UNUSED(off_t days), char *str)
unsetparam("reply");
setsparam("REPLY", ztrdup(name));
execode(prog, 1, 0);
execode(prog, 1, 0, "globqual");
ret = lastval;
errflag = ef;
@ -3516,6 +3516,7 @@ qualsheval(char *name, UNUSED(struct stat *buf), UNUSED(off_t days), char *str)
inserts = tmparr;
}
}
return !ret;
}
return 0;

View file

@ -182,7 +182,7 @@ loop(int toplevel, int justonce)
}
if (stopmsg) /* unset 'you have stopped jobs' flag */
stopmsg--;
execode(prog, 0, 0);
execode(prog, 0, 0, toplevel ? "toplevel" : "file");
tok = toksav;
if (toplevel)
noexitct = 0;
@ -1125,7 +1125,7 @@ init_misc(void)
fclose(bshin);
SHIN = movefd(open("/dev/null", O_RDONLY | O_NOCTTY));
bshin = fdopen(SHIN, "r");
execstring(cmd, 0, 1);
execstring(cmd, 0, 1, "cmdarg");
stopmsg = 1;
zexit(lastval, 0);
}
@ -1213,7 +1213,7 @@ source(char *s)
if (prog) {
pushheap();
errflag = 0;
execode(prog, 1, 0);
execode(prog, 1, 0, "filecode");
popheap();
if (errflag)
ret = SOURCE_ERROR;

View file

@ -57,7 +57,8 @@ char **pparams, /* $argv */
**mailpath, /* $mailpath */
**manpath, /* $manpath */
**psvar, /* $psvar */
**watch; /* $watch */
**watch, /* $watch */
**zsh_eval_context; /* $zsh_eval_context */
/**/
mod_export
char **path, /* $path */
@ -341,6 +342,7 @@ IPDEF8("MAILPATH", &mailpath, "mailpath", 0),
IPDEF8("WATCH", &watch, "watch", 0),
IPDEF8("PATH", &path, "path", PM_RESTRICTED),
IPDEF8("PSVAR", &psvar, "psvar", 0),
IPDEF8("ZSH_EVAL_CONTEXT", &zsh_eval_context, "zsh_eval_context", PM_READONLY),
/* MODULE_PATH is not imported for security reasons */
IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED),
@ -349,12 +351,21 @@ IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED),
#define IPDEF9(A,B,C) IPDEF9F(A,B,C,0)
IPDEF9F("*", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY),
IPDEF9F("@", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY),
/*
* This empty row indicates the end of parameters available in
* all emulations.
*/
{{NULL,NULL,0},BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0},
#define IPDEF10(A,B) {{NULL,A,PM_ARRAY|PM_SPECIAL},BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0}
/* The following parameters are not available in sh/ksh compatibility *
* mode. All of these have sh compatible equivalents. */
/*
* The following parameters are not available in sh/ksh compatibility *
* mode.
*/
/* All of these have sh compatible equivalents. */
IPDEF1("ARGC", argc_gsu, PM_READONLY),
IPDEF2("HISTCHARS", histchars_gsu, PM_DONTIMPORT),
IPDEF4("status", &lastval),
@ -373,9 +384,13 @@ IPDEF9("manpath", &manpath, "MANPATH"),
IPDEF9("psvar", &psvar, "PSVAR"),
IPDEF9("watch", &watch, "WATCH"),
IPDEF9F("zsh_eval_context", &zsh_eval_context, "ZSH_EVAL_CONTEXT", PM_READONLY),
IPDEF9F("module_path", &module_path, "MODULE_PATH", PM_RESTRICTED),
IPDEF9F("path", &path, "PATH", PM_RESTRICTED),
/* These are known to zsh alone. */
IPDEF10("pipestatus", pipestatus_gsu),
{{NULL,NULL,0},BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0},

View file

@ -1198,7 +1198,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
trap_state = TRAP_STATE_PRIMED;
trapisfunc = isfunc = 0;
execode((Eprog)sigfn, 1, 0);
execode((Eprog)sigfn, 1, 0, "trap");
}
runhookdef(AFTERTRAPHOOK, NULL);