diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | Doc/Zsh/builtins.yo | 60 | ||||
-rw-r--r-- | Src/Modules/newuser.c | 2 | ||||
-rw-r--r-- | Src/Modules/parameter.c | 1 | ||||
-rw-r--r-- | Src/builtin.c | 34 | ||||
-rw-r--r-- | Src/exec.c | 34 | ||||
-rw-r--r-- | Src/hashtable.c | 2 | ||||
-rw-r--r-- | Src/init.c | 15 | ||||
-rw-r--r-- | Src/mkbltnmlst.sh | 2 | ||||
-rw-r--r-- | Src/options.c | 26 | ||||
-rw-r--r-- | Src/params.c | 8 | ||||
-rw-r--r-- | Src/parse.c | 1 | ||||
-rw-r--r-- | Src/signals.c | 3 | ||||
-rw-r--r-- | Src/subst.c | 2 | ||||
-rw-r--r-- | Src/zsh.h | 15 | ||||
-rw-r--r-- | Test/B07emulate.ztst | 174 |
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 |