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

Re: [PATCH] out of memory error after "edit-command-line"



> 2022/08/13 9:10, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> 
> The following patch fixes this example, but might only be a partial
> fix for problems with locally flipping the state of various options
> (MONITOR, BANGHIST, SHINSTDIN come to mind).  I think really we should
> be looping over the options and calling dosetopt() for each one
> instead of just memcpy'ing the saved set back on top of the original
> ... or at least we need a mapping of the subset of options that have
> extra code associated with a change via setopt.

In dosetopt(), only MONITOR, EMACSMODE/VIMODE and SUNKEYBOARDHACK have
extra code other than new_opts[optno] = value.

MONITOR:
  dosetopt() has the extra code only when setting MONITOR to ON.
This suggests that just restoring opts[] is enough in doshfunc() when
finishing a function, because:
  If MONITOR was initially off and was set to on locally in a function,
no other code will be run even if we call dosetopt() to set it back to off.
  If MONITOR was initially on, then the extra code had been already run,
and when it was set to off locally in a function nothing extra was done;
so again just opts[MONITOR]=on is enough in doshfunc().... Is this correct?

EMACS/VI:
% bindkey -v
% () { setopt localoptions emacs; }
% (still using emacs binding)
We need to restore the keymap in doshfunc() as in dosetopt().
The problem is that the options EMACS and VI can both be off.
In doshfunc() we can't tell to which keymap we should link the 'main'
keymap because both EMACS and VI may be off in the saved opts[].
The patch below forces 'bindkey -e/-v' to set the option EMACS or VI.
Is this OK?

SUNKEYBOARDHACK: this is simple.

For inittyptab():
dosetopt() calls inittyptab() if BANGHIST or SHINSTDIN changes.
With the patch below doshfunc() calls inittyptab() if BANGHIST,
SHINSTDIN or MULTIBYTE changes (This should solve the original problem
as Bart's patch).
In addition, I think dosetopt() should call inittyptab() also
when MULTIBYTE option changes. Otherwise, we will get troubles
if MULTIBYTE option is changed not by the setopt builtin but
by directly assigning to $options[multibyte].
(bin_setopt() always calls inittyptab(), but this may be redundant)

I _hope_ there is no other option that require extra code in doshfunc().


diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index d90838f03..c0a12f71a 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -799,8 +799,11 @@ bin_bindkey(char *name, char **argv, Options ops, UNUSED(int func))
 	    zwarnnam(name, "no such keymap `%s'", kmname);
 	    return 1;
 	}
-	if(OPT_ISSET(ops,'e') || OPT_ISSET(ops,'v'))
+	if(OPT_ISSET(ops,'e') || OPT_ISSET(ops,'v')) {
 	    linkkeymap(km, "main", 0);
+	    opts[OPT_ISSET(ops,'e') ? EMACSMODE : VIMODE] = 1;
+	    opts[OPT_ISSET(ops,'e') ? VIMODE : EMACSMODE] = 0;
+	}
     } else {
 	kmname = NULL;
 	km = NULL;
diff --git a/Src/exec.c b/Src/exec.c
index f2911807c..6b70e8be9 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -5961,11 +5961,27 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
 	    emulation = funcsave->emulation;
 	    sticky = funcsave->sticky;
 	} else if (isset(LOCALOPTIONS)) {
+	    /* we need to call inittyptab() if these options change */
+	    int init_typtab =
+#ifdef MULTIBYTE_SUPPORT
+			funcsave->opts[MULTIBYTE] != opts[MULTIBYTE] ||
+#endif
+			funcsave->opts[BANGHIST] != opts[BANGHIST] ||
+			funcsave->opts[SHINSTDIN] != opts[SHINSTDIN];
+	    /* just restoring opts[] is not sufficient for these options */
+	    if (funcsave->opts[EMACSMODE] != opts[EMACSMODE] ||
+		funcsave->opts[VIMODE] != opts[VIMODE])
+		zleentry(ZLE_CMD_SET_KEYMAP,
+			funcsave->opts[VIMODE] ? VIMODE : EMACSMODE);
+	    if (funcsave->opts[SUNKEYBOARDHACK] != opts[SUNKEYBOARDHACK])
+		keyboardhackchar = funcsave->opts[SUNKEYBOARDHACK] ? '`' : '\0';
 	    /* restore all shell options except PRIVILEGED and RESTRICTED */
 	    funcsave->opts[PRIVILEGED] = opts[PRIVILEGED];
 	    funcsave->opts[RESTRICTED] = opts[RESTRICTED];
 	    memcpy(opts, funcsave->opts, sizeof(opts));
 	    emulation = funcsave->emulation;
+	    if (init_typtab)
+		inittyptab();
 	} else {
 	    /* just restore a couple. */
 	    opts[XTRACE] = funcsave->opts[XTRACE];
diff --git a/Src/options.c b/Src/options.c
index a1fe918fc..a994b563e 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -904,7 +904,11 @@ dosetopt(int optno, int value, int force, char *new_opts)
 	keyboardhackchar = (value ? '`' : '\0');
     }
     new_opts[optno] = value;
-    if (optno == BANGHIST || optno == SHINSTDIN)
+    if (
+#ifdef MULTIBYTE_SUPPORT
+	optno == MULTIBYTE ||
+#endif
+	optno == BANGHIST || optno == SHINSTDIN)
 	inittyptab();
     return 0;
 }







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