about summary refs log tree commit diff
path: root/Src/options.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2012-10-07 19:46:46 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2012-10-07 19:46:46 +0000
commit4e2cdd795677e655f89b76b57611a196ce578432 (patch)
tree8fde8d99741f84cecb14f46f705ca1500d159af7 /Src/options.c
parent321471891e259c7b406f3cfaf1c076b28ae16a5f (diff)
downloadzsh-4e2cdd795677e655f89b76b57611a196ce578432.tar.gz
zsh-4e2cdd795677e655f89b76b57611a196ce578432.tar.xz
zsh-4e2cdd795677e655f89b76b57611a196ce578432.zip
30722: fix some cases where emulations or options were not propagated properly
from the emulate command
Diffstat (limited to 'Src/options.c')
-rw-r--r--Src/options.c72
1 files changed, 46 insertions, 26 deletions
diff --git a/Src/options.c b/Src/options.c
index 6075a7fcb..87e9abe2d 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -44,6 +44,14 @@ mod_export int sticky_emulation;
  
 /**/
 mod_export char opts[OPT_SIZE];
+
+/*
+ * the options that need setting for current sticky emulation, if any:
+ * same format as opts.
+ */
+
+/**/
+mod_export char sticky_opts[OPT_SIZE];
  
 /* Option name hash table */
 
@@ -70,7 +78,7 @@ mod_export HashTable optiontab;
 /* option is an alias to an other option */
 #define OPT_ALIAS	(EMULATE_UNUSED<<2)
 
-#define defset(X) (!!((X)->node.flags & emulation))
+#define defset(X, my_emulation) (!!((X)->node.flags & my_emulation))
 
 /*
  * Note that option names should usually be fewer than 20 characters long
@@ -439,11 +447,11 @@ printoptionnode(HashNode hn, int set)
     if (optno < 0)
 	optno = -optno;
     if (isset(KSHOPTIONPRINT)) {
-	if (defset(on))
+	if (defset(on, emulation))
 	    printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
 	else
 	    printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");
-    } else if (set == (isset(optno) ^ defset(on))) {
+    } else if (set == (isset(optno) ^ defset(on, emulation))) {
 	if (set ^ isset(optno))
 	    fputs("no", stdout);
 	puts(on->node.nam);
@@ -475,6 +483,15 @@ createoptiontable(void)
 	optiontab->addnode(optiontab, on->node.nam, on);
 }
 
+/* Emulation appropriate to the setemulate function */
+
+static int setemulate_emulation;
+
+/* Option array manipulated within the setemulate function */
+
+/**/
+static char *setemulate_opts;
+
 /* Setting of default options */
 
 /**/
@@ -490,20 +507,22 @@ setemulate(HashNode hn, int fully)
     if (!(on->node.flags & OPT_ALIAS) &&
 	((fully && !(on->node.flags & OPT_SPECIAL)) ||
 	 (on->node.flags & OPT_EMULATE)))
-	opts[on->optno] = defset(on);
+	setemulate_opts[on->optno] = defset(on, setemulate_emulation);
 }
 
 /**/
 void
-installemulation(void)
+installemulation(int new_emulation, char *new_opts)
 {
+    setemulate_emulation = new_emulation;
+    setemulate_opts = new_opts;
     scanhashtable(optiontab, 0, 0, 0, setemulate,
-		  !!(emulation & EMULATE_FULLY));
+		  !!(new_emulation & EMULATE_FULLY));
 }
 
 /**/
 void
-emulate(const char *zsh_name, int fully)
+emulate(const char *zsh_name, int fully, int *new_emulation, char *new_opts)
 {
     char ch = *zsh_name;
 
@@ -512,17 +531,17 @@ emulate(const char *zsh_name, int fully)
 
     /* Work out the new emulation mode */
     if (ch == 'c')
-	emulation = EMULATE_CSH;
+	*new_emulation = EMULATE_CSH;
     else if (ch == 'k')
-	emulation = EMULATE_KSH;
+	*new_emulation = EMULATE_KSH;
     else if (ch == 's' || ch == 'b')
-	emulation = EMULATE_SH;
+	*new_emulation = EMULATE_SH;
     else
-	emulation = EMULATE_ZSH;
+	*new_emulation = EMULATE_ZSH;
 
     if (fully)
-	emulation |= EMULATE_FULLY;
-    installemulation();
+	*new_emulation |= EMULATE_FULLY;
+    installemulation(*new_emulation, new_opts);
 
     if (funcstack && funcstack->tp == FS_FUNC) {
 	/*
@@ -534,7 +553,7 @@ emulate(const char *zsh_name, int fully)
 	Shfunc shf = (Shfunc)shfunctab->getnode(shfunctab, funcstack->name);
 	if (shf && (shf->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL))) {
 	    /* Tracing is on, so set xtrace */
-	    opts[XTRACE] = 1;
+	    new_opts[XTRACE] = 1;
 	}
     }
 }
@@ -545,7 +564,7 @@ emulate(const char *zsh_name, int fully)
 static void
 setoption(HashNode hn, int value)
 {
-    dosetopt(((Optname) hn)->optno, value, 0);
+    dosetopt(((Optname) hn)->optno, value, 0, opts);
 }
 
 /**/
@@ -582,7 +601,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
 		}
 		if(!(optno = optlookup(*args)))
 		    zwarnnam(nam, "no such option: %s", *args);
-		else if(dosetopt(optno, action, 0))
+		else if(dosetopt(optno, action, 0, opts))
 		    zwarnnam(nam, "can't change option: %s", *args);
 		break;
 	    } else if(**args == 'm') {
@@ -590,7 +609,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
 	    } else {
 	    	if (!(optno = optlookupc(**args)))
 		    zwarnnam(nam, "bad option: -%c", **args);
-		else if(dosetopt(optno, action, 0))
+		else if(dosetopt(optno, action, 0, opts))
 		    zwarnnam(nam, "can't change option: -%c", **args);
 	    }
 	}
@@ -603,7 +622,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun)
 	while (*args) {
 	    if(!(optno = optlookup(*args++)))
 		zwarnnam(nam, "no such option: %s", args[-1]);
-	    else if(dosetopt(optno, !isun, 0))
+	    else if(dosetopt(optno, !isun, 0, opts))
 		zwarnnam(nam, "can't change option: %s", args[-1]);
 	}
     } else {
@@ -713,7 +732,7 @@ static char *rparams[] = {
 
 /**/
 mod_export int
-dosetopt(int optno, int value, int force)
+dosetopt(int optno, int value, int force, char *new_opts)
 {
     if(!optno)
 	return -1;
@@ -735,7 +754,7 @@ dosetopt(int optno, int value, int force)
 	return -1;
     } else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN ||
 	    optno == SINGLECOMMAND)) {
-	if (opts[optno] == value)
+	if (new_opts[optno] == value)
 	    return 0;
 	/* it is not permitted to change the value of these options */
 	return -1;
@@ -751,7 +770,7 @@ dosetopt(int optno, int value, int force)
 #endif /* HAVE_SETUID */
 #ifdef JOB_CONTROL
     } else if (!force && optno == MONITOR && value) {
-	if (opts[optno] == value)
+	if (new_opts[optno] == value)
 	    return 0;
 	if (SHTTY != -1) {
 	    origpgrp = GETPGRP();
@@ -770,12 +789,12 @@ dosetopt(int optno, int value, int force)
 	if (sticky_emulation)
 	    return -1;
 	zleentry(ZLE_CMD_SET_KEYMAP, optno);
-	opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0;
+	new_opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0;
     } else if (optno == SUNKEYBOARDHACK) {
 	/* for backward compatibility */
 	keyboardhackchar = (value ? '`' : '\0');
     }
-    opts[optno] = value;
+    new_opts[optno] = value;
     if (optno == BANGHIST || optno == SHINSTDIN)
 	inittyptab();
     return 0;
@@ -817,10 +836,11 @@ printoptionnodestate(HashNode hn, int hadplus)
     int optno = on->optno;
 
     if (hadplus) {
-        if (defset(on) != isset(optno))
-	    printf("set -o %s%s\n", defset(on) ? "no" : "", on->node.nam);
+        if (defset(on, emulation) != isset(optno))
+	    printf("set -o %s%s\n", defset(on, emulation) ?
+		   "no" : "", on->node.nam);
     } else {
-	if (defset(on))
+	if (defset(on, emulation))
 	    printf("no%-19s %s\n", on->node.nam, isset(optno) ? "off" : "on");
 	else
 	    printf("%-21s %s\n", on->node.nam, isset(optno) ? "on" : "off");