Subject: bug#68272: [PATCH] Fix -1 leaking from C to lisp in 'read-event' etc.

From: Tim Ruffing <[email-masked]>
Date: Sat, 09 Mar 2024 13:33:53 +0100

Third revision.

 - Addressed Stefan's nit.
 - Extended the large comment.
 - Switched to Stefan's suggestion for calc.
 - Added a NEWS item that describes the suggestion
 - Added a commit that removes the Microsoft hack

> > It might be worth mentioning that the main difference is the
> > availability of `executing-kbd-macro` to let ELisp code behave
> > differently when called via a kmacro than via "live input".
> > Which also kind of justifies why `read-key-sequence` wants to
> > detect the end: if a kmacro ends in the middle of a key sequence,
> > then
> > it's triggered both my kmacro and by live input.
> > [ Of course, we could handle it in the command loop instead:
> >   check and compare the set of pending kmacro events before and
> > after
> > we
> >   call `read-key-sequence`.  ]

I didn't do this, because I couldn't follow exactly what you're saying.
Feel free to suggest a sentence.

Best,
Tim
From 22d890c88e721f15a591789d233bc943c9095593 Mon Sep 17 00:00:00 2001
From: Tim Ruffing <[email-masked]>
Date: Wed, 27 Dec 2023 14:26:26 +0100
Subject: [PATCH 1/7] Extract check for end of macro to function

* src/macros.h (at_end_of_macro_p):
* src/macros.c (at_end_of_macro_p):
New function.
* src/keyboard.c (read_char): Use the new function.
---
 src/keyboard.c |  3 +--
 src/macros.c   | 12 ++++++++++++
 src/macros.h   |  5 +++++
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/keyboard.c b/src/keyboard.c
index eb0de98bad1..b6fc568cde5 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2637,8 +2637,7 @@ read_char (int commandflag, Lisp_Object map,
       /* Exit the macro if we are at the end.
 	 Also, some things replace the macro with t
 	 to force an early exit.  */
-      if (EQ (Vexecuting_kbd_macro, Qt)
-	  || executing_kbd_macro_index >= XFIXNAT (Flength (Vexecuting_kbd_macro)))
+      if (at_end_of_macro_p ())
 	{
 	  XSETINT (c, -1);
 	  goto exit;
diff --git a/src/macros.c b/src/macros.c
index 5f71bcbd361..faec9dc646d 100644
--- a/src/macros.c
+++ b/src/macros.c
@@ -353,6 +353,18 @@ init_macros (void)
   executing_kbd_macro = Qnil;
 }
 
+/* Whether the execution of a macro has reached its end.
+   This should be called only while executing a macro.  */
+
+bool
+at_end_of_macro_p (void)
+{
+  eassume (!NILP (Vexecuting_kbd_macro));
+  /* Some things replace the macro with t to force an early exit.  */
+  return EQ (Vexecuting_kbd_macro, Qt)
+    || executing_kbd_macro_index >= XFIXNAT (Flength (Vexecuting_kbd_macro));
+}
+
 void
 syms_of_macros (void)
 {
diff --git a/src/macros.h b/src/macros.h
index 51599a29bcd..cb6ac8aa206 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -47,4 +47,9 @@ #define EMACS_MACROS_H
 
 extern void store_kbd_macro_char (Lisp_Object);
 
+/* Whether the execution of a macro has reached its end.
+   This should be called only while executing a macro.  */
+
+extern bool at_end_of_macro_p (void);
+
 #endif /* EMACS_MACROS_H */
-- 
2.44.0

From 929cbc6c6c4cd4a0d71ef37fc47ca7e9ee5b116b Mon Sep 17 00:00:00 2001
From: Tim Ruffing <[email-masked]>
Date: Wed, 27 Dec 2023 14:29:34 +0100
Subject: [PATCH 2/7] * src/keyboard.c (requeued_events_pending_p): Improve
 name and fix comment

* src/keyboard.c, src/keyboard.h (requeued_events_pending_p): Rename to
'requeued_command_events_pending_p' to clarify that the function covers
only command events. Fix wrong comment that claimed that the function
was unused.
* src/process.c (wait_reading_process_output): Update caller to use the
new name.
---
 src/keyboard.c | 8 ++------
 src/keyboard.h | 2 +-
 src/process.c  | 8 ++++----
 3 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/src/keyboard.c b/src/keyboard.c
index b6fc568cde5..e5efde4ef53 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -11565,14 +11565,10 @@ clear_input_pending (void)
   input_pending = false;
 }
 
-/* Return true if there are pending requeued events.
-   This isn't used yet.  The hope is to make wait_reading_process_output
-   call it, and return if it runs Lisp code that unreads something.
-   The problem is, kbd_buffer_get_event needs to be fixed to know what
-   to do in that case.  It isn't trivial.  */
+/* Return true if there are pending requeued command events.  */
 
 bool
-requeued_events_pending_p (void)
+requeued_command_events_pending_p (void)
 {
   return (CONSP (Vunread_command_events));
 }
diff --git a/src/keyboard.h b/src/keyboard.h
index 68e68bc2ae3..600aaf11517 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -483,7 +483,7 @@ #define EVENT_HEAD_KIND(event_head) \
 extern int gobble_input (void);
 extern bool input_polling_used (void);
 extern void clear_input_pending (void);
-extern bool requeued_events_pending_p (void);
+extern bool requeued_command_events_pending_p (void);
 extern void bind_polling_period (int);
 extern int make_ctrl_char (int) ATTRIBUTE_CONST;
 extern void stuff_buffered_input (Lisp_Object);
diff --git a/src/process.c b/src/process.c
index 48a2c0c8e53..6b8b483cdf7 100644
--- a/src/process.c
+++ b/src/process.c
@@ -5439,7 +5439,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
 	  /* If there is unread keyboard input, also return.  */
 	  if (read_kbd != 0
-	      && requeued_events_pending_p ())
+	      && requeued_command_events_pending_p ())
 	    break;
 
           /* This is so a breakpoint can be put here.  */
@@ -5849,7 +5849,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
       /* If there is unread keyboard input, also return.  */
       if (read_kbd != 0
-	  && requeued_events_pending_p ())
+	  && requeued_command_events_pending_p ())
 	break;
 
       /* If we are not checking for keyboard input now,
@@ -8036,7 +8036,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
 	  /* If there is unread keyboard input, also return.  */
 	  if (read_kbd != 0
-	      && requeued_events_pending_p ())
+	      && requeued_command_events_pending_p ())
 	    break;
 
 	  if (timespec_valid_p (timer_delay))
@@ -8109,7 +8109,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 
       /* If there is unread keyboard input, also return.  */
       if (read_kbd
-	  && requeued_events_pending_p ())
+	  && requeued_command_events_pending_p ())
 	break;
 
       /* If wait_for_cell. check for keyboard input
-- 
2.44.0

From 13a1547153c139897fd1e5652654eb6bad360390 Mon Sep 17 00:00:00 2001
From: Tim Ruffing <[email-masked]>
Date: Wed, 27 Dec 2023 14:29:34 +0100
Subject: [PATCH 3/7] * src/keyboard.c (requeued_events_pending_p): New
 function

* src/keyboard.c, src/keyboard.h (requeued_events_pending_p): Add
function 'requeued_events_pending_p' (whose name was made available in
the previous commit). As opposed to the previous function with the same
name, the new function covers both command and other events.
* src/keyboard.c (Finput_pending_p): Use the new function.
---
 src/keyboard.c | 16 +++++++++++++---
 src/keyboard.h |  1 +
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/keyboard.c b/src/keyboard.c
index e5efde4ef53..bd8d3aa7ecf 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -11573,6 +11573,18 @@ requeued_command_events_pending_p (void)
   return (CONSP (Vunread_command_events));
 }
 
+/* Return true if there are any pending requeued events (command events
+   or events to be processed by other levels of the input processing
+   stages).  */
+
+bool
+requeued_events_pending_p (void)
+{
+  return (requeued_command_events_pending_p ()
+	  || !NILP (Vunread_post_input_method_events)
+	  || !NILP (Vunread_input_method_events));
+}
+
 DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 1, 0,
        doc: /* Return t if command input is currently available with no wait.
 Actually, the value is nil only if we can be sure that no input is available;
@@ -11581,9 +11593,7 @@ DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 1, 0,
 If CHECK-TIMERS is non-nil, timers that are ready to run will do so.  */)
   (Lisp_Object check_timers)
 {
-  if (CONSP (Vunread_command_events)
-      || !NILP (Vunread_post_input_method_events)
-      || !NILP (Vunread_input_method_events))
+  if (requeued_events_pending_p ())
     return (Qt);
 
   /* Process non-user-visible events (Bug#10195).  */
diff --git a/src/keyboard.h b/src/keyboard.h
index 600aaf11517..2ce003fd444 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -484,6 +484,7 @@ #define EVENT_HEAD_KIND(event_head) \
 extern bool input_polling_used (void);
 extern void clear_input_pending (void);
 extern bool requeued_command_events_pending_p (void);
+extern bool requeued_events_pending_p (void);
 extern void bind_polling_period (int);
 extern int make_ctrl_char (int) ATTRIBUTE_CONST;
 extern void stuff_buffered_input (Lisp_Object);
-- 
2.44.0

From f8dfb4056bac10e1aa5b63407a7af5f78ad61147 Mon Sep 17 00:00:00 2001
From: Tim Ruffing <[email-masked]>
Date: Wed, 27 Dec 2023 14:32:09 +0100
Subject: [PATCH 4/7] Continue reading in 'read-event' etc. at the end of a
 keyboard macro

This fixes a bug that could make 'read-event', 'read-char', and
'read-char-exclusive' erroneously return -1, an internal magic return
value of 'read_char' leaked from C to lisp. Instead of returning -1, the
aforementioned lisp functions now transparently continue reading
available input (e.g., from the keyboard) when reaching the end of a
keyboard macro.

* src/keyboard.c (read_char, read_key_sequence): Move handling
of the end of a keyboard macro from 'read_char' to its caller
'read_key_sequence', which is the only caller that can
meaningfully deal with this case.
* src/macros.c (Fexecute_kbd_macro): Document how the end of keyboard
macro is processed.
* etc/NEWS: Announce this change.
---
 etc/NEWS       | 12 ++++++++++++
 src/keyboard.c | 39 +++++++++++++++------------------------
 src/macros.c   | 42 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 24 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 2aa669be344..bb57c7640d6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2131,6 +2131,18 @@ Like the variable with the same name, it adds menus from the list that
 is the value of the property to context menus shown when clicking on the
 text which as this property.
 
+---
+** Detecting the end of an iteration of a keyboard macro
+'read-event', 'read-char', and 'read-char-exclusive' no longer return -1
+when called at the end of an iteration of a the execution of a keyboard
+macro.  Instead, they will transparently continue reading available input
+(e.g., from the keyboard).  If you need to detect the end of a macro
+iteration, check the following condition before calling one of the
+aforementioned functions:
+
+    (and (arrayp executing-kbd-macro)
+         (>= executing-kbd-macro-index (length executing-kbd-macro))))
+
 
 * Changes in Emacs 30.1 on Non-Free Operating Systems
 
diff --git a/src/keyboard.c b/src/keyboard.c
index bd8d3aa7ecf..cadb376430e 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2620,7 +2620,8 @@ read_char (int commandflag, Lisp_Object map,
       goto reread_for_input_method;
     }
 
-  if (!NILP (Vexecuting_kbd_macro))
+  /* If we're executing a macro, process it unless we are at its end. */
+  if (!NILP (Vexecuting_kbd_macro) && !at_end_of_macro_p ())
     {
       /* We set this to Qmacro; since that's not a frame, nobody will
 	 try to switch frames on us, and the selected window will
@@ -2634,15 +2635,6 @@ read_char (int commandflag, Lisp_Object map,
 	 selected.  */
       Vlast_event_frame = internal_last_event_frame = Qmacro;
 
-      /* Exit the macro if we are at the end.
-	 Also, some things replace the macro with t
-	 to force an early exit.  */
-      if (at_end_of_macro_p ())
-	{
-	  XSETINT (c, -1);
-	  goto exit;
-	}
-
       c = Faref (Vexecuting_kbd_macro, make_int (executing_kbd_macro_index));
       if (STRINGP (Vexecuting_kbd_macro)
 	  && (XFIXNAT (c) & 0x80) && (XFIXNAT (c) <= 0xff))
@@ -10694,8 +10686,19 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
 	    }
 	  used_mouse_menu = used_mouse_menu_history[t];
 	}
-
-      /* If not, we should actually read a character.  */
+      /* If we're at the end of a macro, exit it by returning 0,
+	 unless there are unread events pending.  */
+      else if (!NILP (Vexecuting_kbd_macro)
+	  && at_end_of_macro_p ()
+	  && !requeued_events_pending_p ())
+	{
+	  t = 0;
+	  /* The Microsoft C compiler can't handle the goto that
+	     would go here.  */
+	  dummyflag = true;
+	  break;
+	}
+      /* Otherwise, we should actually read a character.  */
       else
 	{
 	  {
@@ -10787,18 +10790,6 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
 	      return -1;
 	    }
 
-	  /* read_char returns -1 at the end of a macro.
-	     Emacs 18 handles this by returning immediately with a
-	     zero, so that's what we'll do.  */
-	  if (FIXNUMP (key) && XFIXNUM (key) == -1)
-	    {
-	      t = 0;
-	      /* The Microsoft C compiler can't handle the goto that
-		 would go here.  */
-	      dummyflag = true;
-	      break;
-	    }
-
 	  /* If the current buffer has been changed from under us, the
 	     keymap may have changed, so replay the sequence.  */
 	  if (BUFFERP (key))
diff --git a/src/macros.c b/src/macros.c
index faec9dc646d..230195d9488 100644
--- a/src/macros.c
+++ b/src/macros.c
@@ -314,6 +314,48 @@ DEFUN ("execute-kbd-macro", Fexecute_kbd_macro, Sexecute_kbd_macro, 1, 3, 0,
 		      Vreal_this_command));
   record_unwind_protect (pop_kbd_macro, tem);
 
+  /* The following loop starts the execution of possibly multiple
+     iterations of the macro.
+
+     The state variables that control the execution of a single
+     iteration are Vexecuting_kbd_macro and executing_kbd_macro_index,
+     which can be accessed from lisp. The purpose of the variables
+     executing_kbd_macro and executing_kbd_macro_iteration is to
+     remember the most recently started macro and its iteration count.
+     This makes it possible to produce a meaningful message in case of
+     errors during the execution of the macro.
+
+     In a single iteration, individual characters from the macro are
+     read by read_char, which takes care of incrementing
+     executing_kbd_macro_index after each character.
+
+     The end of a macro iteration is handled as follows:
+      - read_key_sequence asks at_end_of_macro_p whether the end of the
+        iteration has been reached.  If so, it returns the magic value 0
+        to command_loop_1.
+      - command_loop_1 returns Qnil to command_loop_2.
+      - command_loop_2 returns Qnil to this function
+        (but only the returning is relevant, not the actual value).
+
+     Macro executions form a stack.  After the last iteration of the
+     execution of one stack item, or in case of an error during one of
+     the iterations, pop_kbd_macro (invoked via unwind-protect) will
+     restore Vexecuting_kbd_macro and executing_kbd_macro_index, and
+     run 'kbd-macro-termination-hook'.
+
+     If read_char happens to be called at the end of a macro interation,
+     but before read_key_sequence could handle the end (e.g., when lisp
+     code calls 'read-event', 'read-char', or 'read-char-exclusive'),
+     read_char will simply continue reading other available input
+     (Bug#68272).  Vexecuting_kbd_macro and executing_kbd_macro remain
+     untouched until the end of the iteration is handled.
+
+     This is similar (in observable behavior) to a posibly simpler
+     implementation of keyboard macros in which this function pushed all
+     characters of the macro into the incoming event queue and returned
+     immediately.  Maybe this is the implementation that we ideally
+     would like to have, but switching to it will require a larger code
+     change.  */
   do
     {
       Vexecuting_kbd_macro = final;
-- 
2.44.0

From 54e01b030b299049ff710f617082447828882b0c Mon Sep 17 00:00:00 2001
From: Tim Ruffing <[email-masked]>
Date: Wed, 27 Dec 2023 14:32:09 +0100
Subject: [PATCH 5/7] Remove workarounds for solved 'read-event' bug

* lisp/subr.el (read-char-choice-with-read-key):
* lisp/net/dbus.el (dbus-call-method):
Remove workarounds for the bug fixed in the previous commit
ac82baea1c41ec974ad49f2861ae6c06bda2b4ed, where 'read-event',
'read-char' and 'read-char-exclusively' could return wrongly -1.
In the case of lisp/dbus.el, this reverts commit
7177393826c73c87ffe9b428f0e5edae244d7a98.
---
 lisp/net/dbus.el | 6 +-----
 lisp/subr.el     | 5 -----
 2 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el
index 77b334e704e..46f85daba24 100644
--- a/lisp/net/dbus.el
+++ b/lisp/net/dbus.el
@@ -371,11 +371,7 @@ dbus-call-method
 	 (apply
           #'dbus-message-internal dbus-message-type-method-call
           bus service path interface method #'dbus-call-method-handler args))
-        (result (unless executing-kbd-macro (cons :pending nil))))
-
-    ;; While executing a keyboard macro, we run into an infinite loop,
-    ;; receiving the event -1.  So we don't try to get the result.
-    ;; (Bug#62018)
+        (result (cons :pending nil)))
 
     ;; Wait until `dbus-call-method-handler' has put the result into
     ;; `dbus-return-values-table'.  If no timeout is given, use the
diff --git a/lisp/subr.el b/lisp/subr.el
index d58f8ba3b27..ce933e3bfdc 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -3554,11 +3554,6 @@ read-char-choice-with-read-key
 		 (help-form-show)))
 	   ((memq char chars)
 	    (setq done t))
-	   ((and executing-kbd-macro (= char -1))
-	    ;; read-event returns -1 if we are in a kbd macro and
-	    ;; there are no more events in the macro.  Attempt to
-	    ;; get an event interactively.
-	    (setq executing-kbd-macro nil))
 	   ((not inhibit-keyboard-quit)
 	    (cond
 	     ((and (null esc-flag) (eq char ?\e))
-- 
2.44.0

From caa30fe9aa3cf75114d9db05cd0aed538444e957 Mon Sep 17 00:00:00 2001
From: Tim Ruffing <[email-masked]>
Date: Sat, 9 Mar 2024 12:29:39 +0100
Subject: [PATCH 6/7] * lisp/calc/calc-prog.el: Switch to new method of
 detecting end of kbd macro

'read-char' will no longer return -1 as of
ac82baea1c41ec974ad49f2861ae6c06bda2b4ed. This switches to a cleaner
method of detecting whether the end of a keyboard macro has been
reached.

* lisp/calc/calc-prog.el (calc--at-end-of-kmacro-p): New function.
(calc-kbd-skip-to-else-if): Use the function.

Co-authored-by: Stefan Monnier <[email-masked]>
---
 lisp/calc/calc-prog.el | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/lisp/calc/calc-prog.el b/lisp/calc/calc-prog.el
index 03210995eb3..8dff7f1f264 100644
--- a/lisp/calc/calc-prog.el
+++ b/lisp/calc/calc-prog.el
@@ -1225,13 +1225,17 @@ calc-kbd-else-if
   (interactive)
   (calc-kbd-if))
 
+(defun calc--at-end-of-kmacro-p ()
+  (and (arrayp executing-kbd-macro)
+       (>= executing-kbd-macro-index (length executing-kbd-macro))))
+
 (defun calc-kbd-skip-to-else-if (else-okay)
   (let ((count 0)
 	ch)
     (while (>= count 0)
-      (setq ch (read-char))
-      (if (= ch -1)
+      (if (calc--at-end-of-kmacro-p)
 	  (error "Unterminated Z[ in keyboard macro"))
+      (setq ch (read-char))
       (if (= ch ?Z)
 	  (progn
 	    (setq ch (read-char))
@@ -1299,9 +1303,9 @@ calc-kbd-loop
     (or executing-kbd-macro
 	(message "Reading loop body..."))
     (while (>= count 0)
-      (setq ch (read-event))
-      (if (eq ch -1)
+      (if (calc--at-end-of-kmacro-p)
 	  (error "Unterminated Z%c in keyboard macro" open))
+      (setq ch (read-event))
       (if (eq ch ?Z)
 	  (progn
 	    (setq ch (read-event)
@@ -1427,9 +1431,9 @@ calc-kbd-push
 	   (if defining-kbd-macro
 	       (message "Reading body..."))
 	   (while (>= count 0)
-	     (setq ch (read-char))
-	     (if (= ch -1)
+	     (if (calc--at-end-of-kmacro-p)
 		 (error "Unterminated Z` in keyboard macro"))
+	     (setq ch (read-char))
 	     (if (= ch ?Z)
 		 (progn
 		   (setq ch (read-char)
-- 
2.44.0

From a5cefe9ab516d2b062f3a0c68113e55f43e3085b Mon Sep 17 00:00:00 2001
From: Tim Ruffing <[email-masked]>
Date: Sat, 9 Mar 2024 12:15:22 +0100
Subject: [PATCH 7/7] * src/keyboard.c (read_key_sequence): Remove MSVC
 compatibility hack

---
 src/keyboard.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/src/keyboard.c b/src/keyboard.c
index cadb376430e..1ba74a59537 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -10442,9 +10442,6 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
   Lisp_Object original_uppercase UNINIT;
   int original_uppercase_position = -1;
 
-  /* Gets around Microsoft compiler limitations.  */
-  bool dummyflag = false;
-
 #ifdef HAVE_TEXT_CONVERSION
   bool disabled_conversion;
 
@@ -10693,10 +10690,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
 	  && !requeued_events_pending_p ())
 	{
 	  t = 0;
-	  /* The Microsoft C compiler can't handle the goto that
-	     would go here.  */
-	  dummyflag = true;
-	  break;
+	  goto done;
 	}
       /* Otherwise, we should actually read a character.  */
       else
@@ -11291,10 +11285,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
 	  && help_char_p (EVENT_HEAD (key)) && t > 1)
 	    {
 	      read_key_sequence_cmd = Vprefix_help_command;
-	      /* The Microsoft C compiler can't handle the goto that
-		 would go here.  */
-	      dummyflag = true;
-	      break;
+	      goto done;
 	    }
 
       /* If KEY is not defined in any of the keymaps,
@@ -11343,8 +11334,9 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
 	    }
 	}
     }
-  if (!dummyflag)
-    read_key_sequence_cmd = current_binding;
+  read_key_sequence_cmd = current_binding;
+
+  done:
   read_key_sequence_remapped
     /* Remap command through active keymaps.
        Do the remapping here, before the unbind_to so it uses the keymaps
-- 
2.44.0