Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: sticky emulation



This is how I envision (and have already described, at least briefly)
sticky emulation for functions working.  This does not yet have
documentation, nor a way of setting or querying sticky emulation for
individual functions.  It will have at least the former if it gets
committed.

There's a certain amount of administrative reorganisation of emulation
flags here which isn't important; the key parts are in doshfunc() (the
hunks containing references to "restore_sticky").  Pretty much
everything else is straightforward---as discussed, "emulate ... -c"
always causes sticky emulation to be set.

Note that sticky emulation is not propagated to autoloaded functions,
neither when the autoload is set up nor when they are loaded, nor does
autoloading a function provide the same sort of firewall as sticky
emulation.  Defining a function with the special "functions" parameter
is treated the same as defining a function inline in the normal way.

Sticky emulation does propagate to functions defined within sticky
emulation functions---this is inevitable:  there should be no difference
between whether a function was defined within the initial "emulate" or
within a function defined there but called later.

From the previous discussions, I think the most controversial features
(though I'm happy these are reasonable, myself) are:

- Sticky emulation does not cause options to be saved and reset while
executing another function with the same sticky emulation.  This is to
provide consistent emulation environments --- something running in sh
emulation doesn't expect a complete set of options to be imposed and
later removed when it calls another function in the same emulation.

- Functions without sticky emulation are not specially handled, so are
entered with no option changes, and do not have options reset on
exit except as normal shell handling, e.g. LOCAL_OPTIONS.  Setting
LOCAL_OPTIONS is in any case the right thing for a native zsh function
to do to sanitise and protect its local environment, so I don't see any
point in limiting its behaviour in the new code.  You can of course
use "emulate zsh -c 'fn() { ... }'" if you so desire; that's not really
what this is intended for but it's supposed to work consistently.

Someone can probably tell me if I should be keeping the RESTRICTED
and PRIVILEGED options when restoring options after executing a sticky
function, as for LOCAL_OPTIONS handling but not as for "emulate"; my
brain hurts.  I think the answer is "no" because it looks more like the
latter case than the former, but it may not be that simple.

Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.219
diff -u -r1.219 builtin.c
--- Src/builtin.c	25 Jan 2009 18:19:29 -0000	1.219
+++ Src/builtin.c	10 Feb 2009 22:40:13 -0000
@@ -536,7 +536,7 @@
 
     /* 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 @@
 	    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 @@
 {
     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 @@
 
     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;
 }
Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.162
diff -u -r1.162 exec.c
--- Src/exec.c	17 Nov 2008 16:56:42 -0000	1.162
+++ Src/exec.c	10 Feb 2009 22:40:15 -0000
@@ -3999,6 +3999,7 @@
 	shf->node.flags = 0;
 	shf->filename = ztrdup(scriptfilename);
 	shf->lineno = lineno;
+	shf->emulation = sticky_emulation;
 
 	if (!names) {
 	    /*
@@ -4221,7 +4222,7 @@
     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 @@
      * 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 @@
     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];
Index: Src/hashtable.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/hashtable.c,v
retrieving revision 1.30
diff -u -r1.30 hashtable.c
--- Src/hashtable.c	1 Nov 2008 01:19:35 -0000	1.30
+++ Src/hashtable.c	10 Feb 2009 22:40:15 -0000
@@ -588,7 +588,7 @@
  
 /**/
 mod_export char **pathchecked;
- 
+
 /* Create a new command hash table */
  
 /**/
Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.97
diff -u -r1.97 init.c
--- Src/init.c	16 Sep 2008 15:07:08 -0000	1.97
+++ Src/init.c	10 Feb 2009 22:40:15 -0000
@@ -775,7 +775,7 @@
     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 @@
 	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 @@
     /* 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 @@
      * 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 @@
 {
     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 @@
     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;
Index: Src/mkbltnmlst.sh
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/mkbltnmlst.sh,v
retrieving revision 1.9
diff -u -r1.9 mkbltnmlst.sh
--- Src/mkbltnmlst.sh	6 Jul 2007 21:52:39 -0000	1.9
+++ Src/mkbltnmlst.sh	10 Feb 2009 22:40:15 -0000
@@ -40,7 +40,7 @@
     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\","
Index: Src/options.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/options.c,v
retrieving revision 1.46
diff -u -r1.46 options.c
--- Src/options.c	11 Sep 2008 12:49:20 -0000	1.46
+++ Src/options.c	10 Feb 2009 22:40:16 -0000
@@ -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 @@
 #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 @@
 
 /**/
 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 @@
     else
 	emulation = EMULATE_ZSH;
 
-    scanhashtable(optiontab, 0, 0, 0, setemulate, fully);
+    if (fully)
+	emulation |= EMULATE_FULLY;
+    installemulation();
 }
 
 /* setopt, unsetopt */
Index: Src/params.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/params.c,v
retrieving revision 1.154
diff -u -r1.154 params.c
--- Src/params.c	15 Jan 2009 19:47:20 -0000	1.154
+++ Src/params.c	10 Feb 2009 22:40:17 -0000
@@ -642,7 +642,7 @@
     /* 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 @@
 #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 @@
     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 @@
 
     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;
Index: Src/parse.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/parse.c,v
retrieving revision 1.77
diff -u -r1.77 parse.c
--- Src/parse.c	18 Nov 2008 10:07:31 -0000	1.77
+++ Src/parse.c	10 Feb 2009 22:40:17 -0000
@@ -3415,6 +3415,7 @@
 	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;
Index: Src/signals.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/signals.c,v
retrieving revision 1.53
diff -u -r1.53 signals.c
--- Src/signals.c	29 Sep 2008 21:46:58 -0000	1.53
+++ Src/signals.c	10 Feb 2009 22:40:18 -0000
@@ -706,6 +706,7 @@
 	    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 @@
 	/* return triggered */
 	retflag = 1;
     } else {
-	if (traperr && emulation != EMULATE_SH)
+	if (traperr && !EMULATION(EMULATE_SH))
 	    lastval = 1;
 	if (try_tryflag)
 	    errflag = traperr;
Index: Src/subst.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
retrieving revision 1.93
diff -u -r1.93 subst.c
--- Src/subst.c	18 Nov 2008 10:07:31 -0000	1.93
+++ Src/subst.c	10 Feb 2009 22:40:18 -0000
@@ -1534,7 +1534,7 @@
 	 * 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) {
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.151
diff -u -r1.151 zsh.h
--- Src/zsh.h	18 Nov 2008 10:07:31 -0000	1.151
+++ Src/zsh.h	10 Feb 2009 22:40:19 -0000
@@ -1067,6 +1067,7 @@
     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 @@
 #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 {
Index: Src/Modules/newuser.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/newuser.c,v
retrieving revision 1.6
diff -u -r1.6 newuser.c
--- Src/Modules/newuser.c	19 Jun 2007 20:37:40 -0000	1.6
+++ Src/Modules/newuser.c	10 Feb 2009 22:40:19 -0000
@@ -78,7 +78,7 @@
 	0 };
     const char **sp;
 
-    if (emulation != EMULATE_ZSH)
+    if (!EMULATION(EMULATE_ZSH))
 	return 0;
 
     if (!dotdir) {
Index: Src/Modules/parameter.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/parameter.c,v
retrieving revision 1.50
diff -u -r1.50 parameter.c
--- Src/Modules/parameter.c	29 Sep 2008 08:46:33 -0000	1.50
+++ Src/Modules/parameter.c	10 Feb 2009 22:40:19 -0000
@@ -289,6 +289,7 @@
     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) {
Index: Test/B07emulate.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/B07emulate.ztst,v
retrieving revision 1.1
diff -u -r1.1 B07emulate.ztst
--- Test/B07emulate.ztst	10 Feb 2009 20:30:11 -0000	1.1
+++ Test/B07emulate.ztst	10 Feb 2009 22:40:19 -0000
@@ -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


-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



Messages sorted by: Reverse Date, Date, Thread, Author