From 9ee9f4709c53bbf1240a8f4169674172dd458030 Mon Sep 17 00:00:00 2001
From: Eli Zaretskii <eliz@gnu.org>
Date: Fri, 20 Apr 2012 13:09:40 +0300
Subject: [PATCH] Fix bug #11279 with sending command blocks to GDB.

 lisp/progmodes/gdb-mi.el (gdb-control-level): New variable.
 (gdb): Make it buffer-local and init to zero.
 (gdb-control-commands-regexp): New variable.
 (gdb-send): Don't wrap in "-interpreter-exec console" if
 gdb-control-level is positive.  Increment gdb-control-level
 whenever the command matches gdb-control-commands-regexp, and
 decrement it each time the command is "end".  (Bug#11279)
---
 lisp/ChangeLog           | 10 ++++++++++
 lisp/progmodes/gdb-mi.el | 30 ++++++++++++++++++++++++++----
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index e139a7b2bba..c5c4d2573b1 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,13 @@
+2012-04-20  Eli Zaretskii  <eliz@gnu.org>
+
+	* progmodes/gdb-mi.el (gdb-control-level): New variable.
+	(gdb): Make it buffer-local and init to zero.
+	(gdb-control-commands-regexp): New variable.
+	(gdb-send): Don't wrap in "-interpreter-exec console" if
+	gdb-control-level is positive.  Increment gdb-control-level
+	whenever the command matches gdb-control-commands-regexp, and
+	decrement it each time the command is "end".  (Bug#11279)
+
 2012-04-20  Martin Rudalics  <rudalics@gmx.at>
 
 	* window.el (adjust-window-trailing-edge, enlarge-window)
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index f2d8f1f75b7..b19c828d171 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -603,6 +603,8 @@ NOARG must be t when this macro is used outside `gud-def'"
         (set (make-local-variable 'gud-marker-filter) #'gud-gdb-marker-filter))
       (funcall filter proc string))))
 
+(defvar gdb-control-level 0)
+
 ;;;###autoload
 (defun gdb (command-line)
   "Run gdb on program FILE in buffer *gud-FILE*.
@@ -677,6 +679,7 @@ detailed description of this mode.
     (set-process-filter proc #'gdb--check-interpreter))
 
   (set (make-local-variable 'gud-minor-mode) 'gdbmi)
+  (set (make-local-variable 'gdb-control-level) 0)
   (setq comint-input-sender 'gdb-send)
   (when (ring-empty-p comint-input-ring) ; cf shell-mode
     (let ((hfile (expand-file-name (or (getenv "GDBHISTFILE")
@@ -1700,6 +1703,16 @@ static char *magick[] = {
   :group 'gdb)
 
 
+(defvar gdb-control-commands-regexp
+  (concat
+   "^\\("
+   "commands\\|if\\|while\\|define\\|document\\|python\\|"
+   "while-stepping\\|stepping\\|ws\\|actions"
+   "\\)\\([[:blank:]]+.*\\)?$")
+  "Regexp matching GDB commands that enter a recursive reading loop.
+As long as GDB is in the recursive reading loop, it does not expect
+commands to be prefixed by \"-interpreter-exec console\".")
+
 (defun gdb-send (proc string)
   "A comint send filter for gdb."
   (with-current-buffer gud-comint-buffer
@@ -1709,11 +1722,15 @@ static char *magick[] = {
   (if (not (string= "" string))
       (setq gdb-last-command string)
     (if gdb-last-command (setq string gdb-last-command)))
-  (if (string-match "^-" string)
-      ;; MI command
+  (if (or (string-match "^-" string)
+	  (> gdb-control-level 0))
+      ;; Either MI command or we are feeding GDB's recursive reading loop.
       (progn
 	(setq gdb-first-done-or-error t)
-	(process-send-string proc (concat string "\n")))
+	(process-send-string proc (concat string "\n"))
+	(if (and (string-match "^end$" string)
+		 (> gdb-control-level 0))
+	    (setq gdb-control-level (1- gdb-control-level))))
     ;; CLI command
     (if (string-match "\\\\$" string)
 	(setq gdb-continuation (concat gdb-continuation string "\n"))
@@ -1724,7 +1741,12 @@ static char *magick[] = {
         (if gdb-enable-debug
             (push (cons 'mi-send to-send) gdb-debug-log))
         (process-send-string proc to-send))
-      (setq gdb-continuation nil))))
+      (if (and (string-match "^end$" string)
+	       (> gdb-control-level 0))
+	  (setq gdb-control-level (1- gdb-control-level)))
+      (setq gdb-continuation nil)))
+  (if (string-match gdb-control-commands-regexp string)
+      (setq gdb-control-level (1+ gdb-control-level))))
 
 (defun gdb-mi-quote (string)
   "Return STRING quoted properly as an MI argument.
-- 
2.39.5