summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--Doc/Zsh/builtins.yo60
-rw-r--r--Src/Modules/newuser.c2
-rw-r--r--Src/Modules/parameter.c1
-rw-r--r--Src/builtin.c34
-rw-r--r--Src/exec.c34
-rw-r--r--Src/hashtable.c2
-rw-r--r--Src/init.c15
-rw-r--r--Src/mkbltnmlst.sh2
-rw-r--r--Src/options.c26
-rw-r--r--Src/params.c8
-rw-r--r--Src/parse.c1
-rw-r--r--Src/signals.c3
-rw-r--r--Src/subst.c2
-rw-r--r--Src/zsh.h15
-rw-r--r--Test/B07emulate.ztst174
16 files changed, 322 insertions, 69 deletions
diff --git a/ChangeLog b/ChangeLog
index efef75d7f..20cf6ea4d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2009-02-11 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 26556: Doc/Zsh/builtins.yo: documentation for 26546.
+
+ * 26546: Src/builtin.c, Src/exec.c, Src/hashtable.c, Src/init.c,
+ Src/mkbltnmlst.sh, Src/options.c, Src/params.c, Src/parse.c,
+ Src/signals.c, Src/subst.c, Src/zsh.h, Src/Modules/newuser.c,
+ Src/Modules/parameter.c, Test/B07emulate.ztst: sticky emulation
+ for functions defined within emualate ... -c ... environments.
+
2009-02-11 Peter Stephenson <pws@csr.com>
* unposted: Functions/Calendar/age: accidentally committed a
@@ -11157,5 +11167,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.4562 $
+* $Revision: 1.4563 $
*****************************************************
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 4487ee175..1d74d7f49 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -356,10 +356,6 @@ noderef(Compatibility)
)\
.
-If tt(-c) tt(arg) is given, evaluate tt(arg) after temporary setting
-requested emulation. Emulation and all options will be restored to their
-original values before tt(emulate) returns.
-
If the tt(-R) option is given, all options
are reset to their default value corresponding to the specified emulation
mode, except for certain options describing the interactive
@@ -370,6 +366,62 @@ well, causing the effects of the tt(emulate) command and any tt(setopt) and
tt(trap) commands to be local to the immediately surrounding shell
function, if any; normally these options are turned off in all emulation
modes except tt(ksh). The tt(-L) and tt(-c) are mutually exclusive.
+
+If tt(-c) tt(arg) is given, evaluate tt(arg) while the requested
+emulation is temporarily in effect. The emulation and all options will
+be restored to their original values before tt(emulate) returns. The
+tt(-R) flag may be used.
+
+Use of tt(-c) enables `sticky' emulation mode for functions defined
+within the evaluated expression: the emulation mode is associated
+thereafter with the function so that whenever the function is executed
+the emulation (respecting the tt(-R) flag, if present) and all
+options are set before entry to the function, and restored after exit.
+If the function is called when the sticky emulation is already in
+effect, either within an `tt(emulate) var(shell) tt(-c)' expression or
+within another function with the same sticky emulation, entry and exit
+from the function do not cause options to be altered (except due to
+standard processing such as the tt(LOCAL_OPTIONS) option).
+
+For example:
+
+example(emulate sh -c 'fni+LPAR()RPAR() { setopt cshnullglob; }
+fno+LPAR()RPAR() { fni; }'
+fno
+)
+
+The two functions tt(fni) and tt(fno) are defined with sticky tt(sh)
+emulation. tt(fno) is then executed, causing options associated
+with emulations to be set to their values in tt(sh). tt(fni) then
+calls tt(fno); because tt(fno) is also marked for sticky tt(sh)
+emulation, no option changes take place on entry to or exit from it.
+Hence the option tt(cshnullglob), turned off by tt(sh) emulation, will
+be turned on within tt(fni) and remain on on return to tt(fno). On exit
+from tt(fno), the emulation mode and all options will be restored to the
+state they were in before entry to the temporary emulation.
+
+The documentation above is typically sufficient for the intended
+purpose of executing code designed for other shells in a suitable
+environment. More detailed rules follow.
+startsitem()
+sitem(1.)(The sticky emulation environment provided by `tt(emulate)
+var(shell) tt(-c)' is identical to that provided by entry to
+a function marked for sticky emulation as a consequence of being
+defined in such an environment. Hence, for example, the sticky
+emulation is inherited by subfunctions defined within functions
+with sticky emulation.)
+sitem(2.)(No change of options takes place on entry to or exit from
+functions that are not marked for sticky emulation, other than those
+that would normally take place, even if those functions are called
+within sticky emulation.)
+sitem(3.)(No special handling is provided for functions marked for
+tt(autoload) nor for functions present in wordcode created by
+the tt(zcompile) command.)
+sitem(4.)(The presence or absence of the tt(-R) flag to tt(emulate)
+corresponds to different sticky emulation modes, so for example
+`tt(emulate sh -c)', `tt(emulate -R sh -c)' and `tt(emulate csh -c)'
+are treated as three distinct sticky emulations.)
+endsitem()
)
findex(enable)
cindex(enabling commands)
diff --git a/Src/Modules/newuser.c b/Src/Modules/newuser.c
index e19c34df3..cc020d5bd 100644
--- a/Src/Modules/newuser.c
+++ b/Src/Modules/newuser.c
@@ -78,7 +78,7 @@ boot_(UNUSED(Module m))
0 };
const char **sp;
- if (emulation != EMULATE_ZSH)
+ if (!EMULATION(EMULATE_ZSH))
return 0;
if (!dotdir) {
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index e3fb909ea..38b462001 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -289,6 +289,7 @@ setfunction(char *name, char *val, int dis)
shf = (Shfunc) zshcalloc(sizeof(*shf));
shf->funcdef = dupeprog(prog, 0);
shf->node.flags = dis;
+ shf->emulation = sticky_emulation;
if (!strncmp(name, "TRAP", 4) &&
(sn = getsignum(name + 4)) != -1) {
diff --git a/Src/builtin.c b/Src/builtin.c
index 99af38e3a..b402d56e2 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -536,7 +536,7 @@ bin_set(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
/* Obsolescent sh compatibility: set - is the same as set +xv *
* and set - args is the same as set +xv -- args */
- if (emulation != EMULATE_ZSH && *args && **args == '-' && !args[0][1]) {
+ if (!EMULATION(EMULATE_ZSH) && *args && **args == '-' && !args[0][1]) {
dosetopt(VERBOSE, 0, 0);
dosetopt(XTRACE, 0, 0);
if (!args[1])
@@ -2861,6 +2861,8 @@ bin_functions(char *name, char **argv, Options ops, int func)
shf = (Shfunc) zshcalloc(sizeof *shf);
shf->node.flags = on;
shf->funcdef = mkautofn(shf);
+ /* No sticky emulation for autoloaded functions */
+ shf->emulation = 0;
shfunctab->addnode(shfunctab, ztrdup(*argv), shf);
if (signum != -1) {
@@ -4834,21 +4836,38 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
{
int opt_L = OPT_ISSET(ops, 'L');
int opt_R = OPT_ISSET(ops, 'R');
- int saveemulation ;
+ int saveemulation, savesticky_emulation;
int ret;
char saveopts[OPT_SIZE];
/* without arguments just print current emulation */
if (!*argv) {
+ const char *shname;
+
if (opt_L || opt_R) {
zwarnnam("emulate", "not enough arguments");
return 1;
}
- printf("%s\n", emulation == EMULATE_CSH ? "csh" :
- emulation == EMULATE_KSH ? "ksh" :
- emulation == EMULATE_SH ? "sh" :
- "zsh");
+ switch(SHELL_EMULATION()) {
+ case EMULATE_CSH:
+ shname = "csh";
+ break;
+
+ case EMULATE_KSH:
+ shname = "ksh";
+ break;
+
+ case EMULATE_SH:
+ shname = "sh";
+ break;
+
+ default:
+ shname = "zsh";
+ break;
+ }
+
+ printf("%s\n", shname);
return 0;
}
@@ -4880,9 +4899,12 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
memcpy(saveopts, opts, sizeof(opts));
saveemulation = emulation;
+ savesticky_emulation = sticky_emulation;
emulate(*argv, OPT_ISSET(ops,'R'));
+ sticky_emulation = emulation;
ret = eval(argv+2);
memcpy(opts, saveopts, sizeof(opts));
+ sticky_emulation = savesticky_emulation;
emulation = saveemulation;
return ret;
}
diff --git a/Src/exec.c b/Src/exec.c
index 5aec655a2..b86e5350c 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -3999,6 +3999,7 @@ execfuncdef(Estate state, UNUSED(int do_exec))
shf->node.flags = 0;
shf->filename = ztrdup(scriptfilename);
shf->lineno = lineno;
+ shf->emulation = sticky_emulation;
if (!names) {
/*
@@ -4221,7 +4222,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
char *name = shfunc->node.nam;
int flags = shfunc->node.flags;
char *fname = dupstring(name);
- int obreaks, saveemulation ;
+ int obreaks, saveemulation, savesticky_emulation, restore_sticky;
Eprog prog;
struct funcstack fstack;
#ifdef MAX_FUNCTION_DEPTH
@@ -4261,6 +4262,26 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
* function we need to restore the original options on exit. */
memcpy(saveopts, opts, sizeof(opts));
saveemulation = emulation;
+ savesticky_emulation = sticky_emulation;
+
+ if (shfunc->emulation && sticky_emulation != shfunc->emulation) {
+ /*
+ * Function is marked for sticky emulation.
+ * Enable it now.
+ *
+ * We deliberately do not do this if the sticky emulation
+ * in effect is the same as that requested. This enables
+ * option setting naturally within emulation environments.
+ * Note that a difference in EMULATE_FULLY (emulate with
+ * or without -R) counts as a different environment.
+ *
+ * This propagates the sticky emulation to subfunctions.
+ */
+ emulation = sticky_emulation = shfunc->emulation;
+ restore_sticky = 1;
+ installemulation();
+ } else
+ restore_sticky = 0;
if (flags & PM_TAGGED)
opts[XTRACE] = 1;
@@ -4349,7 +4370,16 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
zoptind = oldzoptind;
scriptname = oldscriptname;
- if (isset(LOCALOPTIONS)) {
+ if (restore_sticky) {
+ /*
+ * If we switched to an emulation environment just for
+ * this function, we interpret the option and emulation
+ * switch as being a firewall between environments.
+ */
+ memcpy(opts, saveopts, sizeof(opts));
+ emulation = saveemulation;
+ sticky_emulation = savesticky_emulation;
+ } else if (isset(LOCALOPTIONS)) {
/* restore all shell options except PRIVILEGED and RESTRICTED */
saveopts[PRIVILEGED] = opts[PRIVILEGED];
saveopts[RESTRICTED] = opts[RESTRICTED];
diff --git a/Src/hashtable.c b/Src/hashtable.c
index e12aca852..2eb70c3b0 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -588,7 +588,7 @@ mod_export HashTable cmdnamtab;
/**/
mod_export char **pathchecked;
-
+
/* Create a new command hash table */
/**/
diff --git a/Src/init.c b/Src/init.c
index 215514f6d..341446cb9 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -775,7 +775,7 @@ setupvals(void)
if(unset(INTERACTIVE)) {
prompt = ztrdup("");
prompt2 = ztrdup("");
- } else if (emulation == EMULATE_KSH || emulation == EMULATE_SH) {
+ } else if (EMULATION(EMULATE_KSH|EMULATE_SH)) {
prompt = ztrdup(privasserted() ? "# " : "$ ");
prompt2 = ztrdup("> ");
} else {
@@ -783,7 +783,7 @@ setupvals(void)
prompt2 = ztrdup("%_> ");
}
prompt3 = ztrdup("?# ");
- prompt4 = (emulation == EMULATE_KSH || emulation == EMULATE_SH)
+ prompt4 = EMULATION(EMULATE_KSH|EMULATE_SH)
? ztrdup("+ ") : ztrdup("+%N:%i> ");
sprompt = ztrdup("zsh: correct '%R' to '%r' [nyae]? ");
@@ -811,14 +811,14 @@ setupvals(void)
/* Get password entry and set info for `USERNAME' */
#ifdef USE_GETPWUID
if ((pswd = getpwuid(cached_uid))) {
- if (emulation == EMULATE_ZSH)
+ if (EMULATION(EMULATE_ZSH))
home = metafy(pswd->pw_dir, -1, META_DUP);
cached_username = ztrdup(pswd->pw_name);
}
else
#endif /* USE_GETPWUID */
{
- if (emulation == EMULATE_ZSH)
+ if (EMULATION(EMULATE_ZSH))
home = ztrdup("/");
cached_username = ztrdup("");
}
@@ -828,7 +828,7 @@ setupvals(void)
* In non-native emulations HOME must come from the environment;
* we're not allowed to set it locally.
*/
- if (emulation == EMULATE_ZSH)
+ if (EMULATION(EMULATE_ZSH))
ptr = home;
else
ptr = zgetenv("HOME");
@@ -954,7 +954,7 @@ run_init_scripts(void)
{
noerrexit = -1;
- if (emulation == EMULATE_KSH || emulation == EMULATE_SH) {
+ if (EMULATION(EMULATE_KSH|EMULATE_SH)) {
if (islogin)
source("/etc/profile");
if (unset(PRIVILEGED)) {
@@ -1160,8 +1160,7 @@ sourcehome(char *s)
char *h;
queue_signals();
- if (emulation == EMULATE_SH || emulation == EMULATE_KSH ||
- !(h = getsparam("ZDOTDIR"))) {
+ if (EMULATION(EMULATE_SH|EMULATE_KSH) || !(h = getsparam("ZDOTDIR"))) {
h = home;
if (!h)
return;
diff --git a/Src/mkbltnmlst.sh b/Src/mkbltnmlst.sh
index 005e2ef81..d9c5b13e9 100644
--- a/Src/mkbltnmlst.sh
+++ b/Src/mkbltnmlst.sh
@@ -40,7 +40,7 @@ for x_mod in $x_mods; do
unset moddeps autofeatures
. $srcdir/../$modfile
if test "x$autofeatures" != x; then
- echo " if (emulation == EMULATE_ZSH) {"
+ echo " if (EMULATION(EMULATE_ZSH)) {"
echo " char *features[] = { "
for feature in $autofeatures; do
echo " \"$feature\","
diff --git a/Src/options.c b/Src/options.c
index 3c7f88048..f852ec830 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -35,6 +35,11 @@
/**/
mod_export int emulation;
+/* current sticky emulation: 0 means none */
+
+/**/
+mod_export int sticky_emulation;
+
/* the options; e.g. if opts[SHGLOB] != 0, SH_GLOB is turned on */
/**/
@@ -58,9 +63,12 @@ mod_export HashTable optiontab;
#define OPT_NONBOURNE (OPT_ALL & ~OPT_BOURNE)
#define OPT_NONZSH (OPT_ALL & ~OPT_ZSH)
-#define OPT_EMULATE (1<<5) /* option is relevant to emulation */
-#define OPT_SPECIAL (1<<6) /* option should never be set by emulate() */
-#define OPT_ALIAS (1<<7) /* option is an alias to an other option */
+/* option is relevant to emulation */
+#define OPT_EMULATE (EMULATE_UNUSED)
+/* option should never be set by emulate() */
+#define OPT_SPECIAL (EMULATE_UNUSED<<1)
+/* option is an alias to an other option */
+#define OPT_ALIAS (EMULATE_UNUSED<<2)
#define defset(X) (!!((X)->node.flags & emulation))
@@ -477,6 +485,14 @@ setemulate(HashNode hn, int fully)
/**/
void
+installemulation(void)
+{
+ scanhashtable(optiontab, 0, 0, 0, setemulate,
+ !!(emulation & EMULATE_FULLY));
+}
+
+/**/
+void
emulate(const char *zsh_name, int fully)
{
char ch = *zsh_name;
@@ -494,7 +510,9 @@ emulate(const char *zsh_name, int fully)
else
emulation = EMULATE_ZSH;
- scanhashtable(optiontab, 0, 0, 0, setemulate, fully);
+ if (fully)
+ emulation |= EMULATE_FULLY;
+ installemulation();
}
/* setopt, unsetopt */
diff --git a/Src/params.c b/Src/params.c
index 1e902e871..6a7ab0fa6 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -642,7 +642,7 @@ createparamtable(void)
/* Add the special parameters to the hash table */
for (ip = special_params; ip->node.nam; ip++)
paramtab->addnode(paramtab, ztrdup(ip->node.nam), ip);
- if (emulation != EMULATE_SH && emulation != EMULATE_KSH)
+ if (!EMULATION(EMULATE_SH|EMULATE_KSH))
while ((++ip)->node.nam)
paramtab->addnode(paramtab, ztrdup(ip->node.nam), ip);
@@ -720,7 +720,7 @@ createparamtable(void)
#endif
opts[ALLEXPORT] = oae;
- if (emulation == EMULATE_ZSH)
+ if (EMULATION(EMULATE_ZSH))
{
/*
* For native emulation we always set the variable home
@@ -1881,7 +1881,7 @@ getstrvalue(Value v)
switch(PM_TYPE(v->pm->node.flags)) {
case PM_HASHED:
/* (!v->isarr) should be impossible unless emulating ksh */
- if (!v->isarr && emulation == EMULATE_KSH) {
+ if (!v->isarr && EMULATION(EMULATE_KSH)) {
s = dupstring("[0]");
if (getindex(&s, v, 0) == 0)
s = getstrvalue(v);
@@ -2164,7 +2164,7 @@ export_param(Param pm)
if (PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED)) {
#if 0 /* Requires changes elsewhere in params.c and builtin.c */
- if (emulation == EMULATE_KSH /* isset(KSHARRAYS) */) {
+ if (EMULATION(EMULATE_KSH) /* isset(KSHARRAYS) */) {
struct value v;
v.isarr = 1;
v.flags = 0;
diff --git a/Src/parse.c b/Src/parse.c
index 722809a78..59459870a 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -3415,6 +3415,7 @@ dump_autoload(char *nam, char *file, int on, Options ops, int func)
shf = (Shfunc) zshcalloc(sizeof *shf);
shf->node.flags = on;
shf->funcdef = mkautofn(shf);
+ shf->emulation = 0;
shfunctab->addnode(shfunctab, ztrdup(fdname(n) + fdhtail(n)), shf);
if (OPT_ISSET(ops,'X') && eval_autoload(shf, shf->node.nam, ops, func))
ret = 1;
diff --git a/Src/signals.c b/Src/signals.c
index ac5ffaa21..5d1797f2f 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -706,6 +706,7 @@ dosavetrap(int sig, int level)
newshf->node.flags = shf->node.flags;
newshf->funcdef = dupeprog(shf->funcdef, 0);
newshf->filename = ztrdup(shf->filename);
+ newshf->emulation = shf->emulation;
if (shf->node.flags & PM_UNDEFINED)
newshf->funcdef->shf = newshf;
}
@@ -1201,7 +1202,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
/* return triggered */
retflag = 1;
} else {
- if (traperr && emulation != EMULATE_SH)
+ if (traperr && !EMULATION(EMULATE_SH))
lastval = 1;
if (try_tryflag)
errflag = traperr;
diff --git a/Src/subst.c b/Src/subst.c
index 42f880965..89e9e46eb 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1534,7 +1534,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
* doesn't have parameter flags it might be neater to
* handle this with the ^, =, ~ stuff, below.
*/
- if ((c = *s) == '!' && s[1] != Outbrace && emulation == EMULATE_KSH) {
+ if ((c = *s) == '!' && s[1] != Outbrace && EMULATION(EMULATE_KSH)) {
hkeys = SCANPM_WANTKEYS;
s++;
} else if (c == '(' || c == Inpar) {
diff --git a/Src/zsh.h b/Src/zsh.h
index 36755c719..159806f2c 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1067,6 +1067,7 @@ struct shfunc {
char *filename; /* Name of file located in */
zlong lineno; /* line number in above file */
Eprog funcdef; /* function definition */
+ int emulation; /* sticky emulation for function */
};
/* Shell function context types. */
@@ -1790,6 +1791,20 @@ struct histent {
#define EMULATE_SH (1<<3) /* Bourne shell */
#define EMULATE_ZSH (1<<4) /* `native' mode */
+/* Test for a shell emulation. Use this rather than emulation directly. */
+#define EMULATION(X) (emulation & (X))
+
+/* Return only base shell emulation field. */
+#define SHELL_EMULATION() (emulation & ((1<<5)-1))
+
+/* Additional flags */
+
+#define EMULATE_FULLY (1<<5) /* "emulate -R" in effect */
+/*
+ * Higher bits are used in options.c, record lowest unused bit...
+ */
+#define EMULATE_UNUSED (1<<6)
+
/* option indices */
enum {
diff --git a/Test/B07emulate.ztst b/Test/B07emulate.ztst
index 57eea3806..dec809ea4 100644
--- a/Test/B07emulate.ztst
+++ b/Test/B07emulate.ztst
@@ -3,72 +3,176 @@
%prep
isset() {
+ print -n "${1}: "
if [[ -o $1 ]]; then print yes; else print no; fi
}
showopts() {
- # Set for Bourne shell emulation
- isset shwordsplit
- # Set in native mode and unless "emulate -R" is in use
- isset banghist
+ # Set for Bourne shell emulation
+ isset shwordsplit
+ # Set in native mode and unless "emulate -R" is in use
+ isset banghist
+ }
+ cshowopts() {
+ showopts
+ # Show a csh option, too
+ isset cshnullglob
}
%test
- (showopts
+ (print Before
+ showopts
fn() {
emulate sh
}
fn
+ print After
showopts)
0:Basic use of emulate
->no
->yes
->yes
->yes
+>Before
+>shwordsplit: no
+>banghist: yes
+>After
+>shwordsplit: yes
+>banghist: yes
fn() {
emulate -L sh
+ print During
showopts
}
+ print Before
showopts
fn
+ print After
showopts
0:Use of emulate -L
->no
->yes
->yes
->yes
->no
->yes
+>Before
+>shwordsplit: no
+>banghist: yes
+>During
+>shwordsplit: yes
+>banghist: yes
+>After
+>shwordsplit: no
+>banghist: yes
- (showopts
+ (print Before
+ showopts
emulate -R sh
+ print After
showopts)
0:Use of emulate -R
->no
->yes
->yes
->no
+>Before
+>shwordsplit: no
+>banghist: yes
+>After
+>shwordsplit: yes
+>banghist: no
+ print Before
showopts
- emulate sh -c 'showopts'
+ emulate sh -c 'print During; showopts'
+ print After
showopts
0:Use of emulate -c
->no
->yes
->yes
->yes
->no
->yes
-
+>Before
+>shwordsplit: no
+>banghist: yes
+>During
+>shwordsplit: yes
+>banghist: yes
+>After
+>shwordsplit: no
+>banghist: yes
+ print Before
showopts
- emulate -R sh -c 'showopts'
+ emulate -R sh -c 'print During; showopts'
+ print After
showopts
0:Use of emulate -R -c
->no
->yes
->yes
->no
->no
->yes
+>Before
+>shwordsplit: no
+>banghist: yes
+>During
+>shwordsplit: yes
+>banghist: no
+>After
+>shwordsplit: no
+>banghist: yes
+
+ print Before
+ showopts
+ emulate -R sh -c 'shshowopts() { showopts; }'
+ print After definition
+ showopts
+ print In sticky emulation
+ shshowopts
+ print After sticky emulation
+ showopts
+0:Basic sticky function emulation
+>Before
+>shwordsplit: no
+>banghist: yes
+>After definition
+>shwordsplit: no
+>banghist: yes
+>In sticky emulation
+>shwordsplit: yes
+>banghist: no
+>After sticky emulation
+>shwordsplit: no
+>banghist: yes
+
+ print Before
+ cshowopts
+ emulate -R sh -c 'shshowopts() { cshowopts; }'
+ emulate csh -c 'cshshowopts() {
+ cshowopts
+ print In nested sh emulation
+ shshowopts
+ }'
+ print After definition
+ cshowopts
+ print In sticky csh emulation
+ cshshowopts
+ print After sticky emulation
+ cshowopts
+0:Basic sticky function emulation
+>Before
+>shwordsplit: no
+>banghist: yes
+>cshnullglob: no
+>After definition
+>shwordsplit: no
+>banghist: yes
+>cshnullglob: no
+>In sticky csh emulation
+>shwordsplit: no
+>banghist: yes
+>cshnullglob: yes
+>In nested sh emulation
+>shwordsplit: yes
+>banghist: no
+>cshnullglob: no
+>After sticky emulation
+>shwordsplit: no
+>banghist: yes
+>cshnullglob: no
+
+ isalp() { if [[ -o alwayslastprompt ]]; then print on; else print off; fi; }
+ emulate sh -c 'shfunc_inner() { setopt alwayslastprompt; }'
+ emulate csh -c 'cshfunc_inner() { setopt alwayslastprompt; }'
+ emulate sh -c 'shfunc_outer() {
+ unsetopt alwayslastprompt;
+ shfunc_inner;
+ isalp
+ unsetopt alwayslastprompt
+ cshfunc_inner
+ isalp
+ }'
+ shfunc_outer
+0:Sticky emulation not triggered if sticky emulation unchanged
+>on
+>off