Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: oltolm <oleg.tolmatcev@gmail.com>
To: gdb-patches@sourceware.org
Cc: oltolm <oleg.tolmatcev@gmail.com>
Subject: [PATCH v4] gdb/dap: add option commandEscapePrefix
Date: Sun, 16 Nov 2025 15:26:14 +0100	[thread overview]
Message-ID: <20251116142613.1736-2-oleg.tolmatcev@gmail.com> (raw)

The escape prefix to use for executing regular GDB commands in the Debug
Console, instead of printing variables. Defaults to an empty string. If it's
an empty string, then all expressions in the Debug Console are treated as
regular GDB commands.

Signed-off-by: oltolm <oleg.tolmatcev@gmail.com>
---
 gdb/doc/gdb.texinfo                   |  6 ++++++
 gdb/python/lib/gdb/dap/completions.py | 15 ++++++++++++---
 gdb/python/lib/gdb/dap/evaluate.py    | 15 ++++++++++++---
 gdb/python/lib/gdb/dap/launch.py      |  5 +++++
 gdb/python/lib/gdb/dap/server.py      | 14 ++++++++++++++
 5 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b52fd7f880d..bad8eede578 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -40155,6 +40155,12 @@ the same approach as the @code{start} command.  @xref{Starting}.
 If provided, this must be a boolean.  When @samp{True}, @value{GDBN}
 will set a temporary breakpoint at the program's first instruction, using
 the same approach as the @code{starti} command.  @xref{Starting}.
+
+@item commandEscapePrefix
+The escape prefix to use for executing regular @value{GDBN} commands in the
+Debug Console, instead of printing variables.  Defaults to an empty string.  If it's
+an empty string, then all expressions in the Debug Console are treated as
+regular @value{GDBN} commands.
 @end table
 
 @value{GDBN} defines some parameters that can be passed to the
diff --git a/gdb/python/lib/gdb/dap/completions.py b/gdb/python/lib/gdb/dap/completions.py
index e5003fff96d..a9c4d12bbdb 100644
--- a/gdb/python/lib/gdb/dap/completions.py
+++ b/gdb/python/lib/gdb/dap/completions.py
@@ -16,7 +16,13 @@
 from typing import Optional
 
 from .frames import select_frame
-from .server import capability, import_column, import_line, request
+from .server import (
+    capability,
+    get_command_escape_prefix,
+    import_column,
+    import_line,
+    request,
+)
 from .startup import exec_mi_and_log
 
 
@@ -44,12 +50,15 @@ def completions(
         text = text[: column - 1]
     else:
         text = ""
+    if not text.startswith(get_command_escape_prefix()):
+        return {"targets": []}
+    text = text[len(get_command_escape_prefix()):]
     mi_result = exec_mi_and_log("-complete", text)
     result = []
     completion = None
     if "completion" in mi_result:
         completion = mi_result["completion"]
-        result.append({"label": completion, "length": len(completion)})
+        result.append({"label": get_command_escape_prefix() + completion, "length": len(completion)})
     # If `-complete' finds one match then `completion' and `matches'
     # will contain the same one match.
     if (
@@ -59,5 +68,5 @@ def completions(
     ):
         return {"targets": result}
     for match in mi_result["matches"]:
-        result.append({"label": match, "length": len(match)})
+        result.append({"label": get_command_escape_prefix() + match, "length": len(match)})
     return {"targets": result}
diff --git a/gdb/python/lib/gdb/dap/evaluate.py b/gdb/python/lib/gdb/dap/evaluate.py
index fcbcc99acfc..985cad88db7 100644
--- a/gdb/python/lib/gdb/dap/evaluate.py
+++ b/gdb/python/lib/gdb/dap/evaluate.py
@@ -19,7 +19,12 @@ from typing import Optional
 import gdb
 
 from .frames import select_frame
-from .server import capability, client_bool_capability, request
+from .server import (
+    capability,
+    client_bool_capability,
+    get_command_escape_prefix,
+    request,
+)
 from .startup import DAPException, in_gdb_thread, parse_and_eval
 from .varref import VariableReference, apply_format, find_variable
 
@@ -86,8 +91,12 @@ def eval_request(
     elif context == "hover":
         return _eval_for_hover(expression, frameId, format)
     elif context == "repl":
-        # Ignore the format for repl evaluation.
-        return _repl(expression, frameId)
+        if expression.startswith(get_command_escape_prefix()):
+            expression = expression[len(get_command_escape_prefix()):]
+            # Ignore the format for repl evaluation.
+            return _repl(expression, frameId)
+        else:
+            return _evaluate(expression, frameId, format)
     else:
         raise DAPException('unknown evaluate context "' + context + '"')
 
diff --git a/gdb/python/lib/gdb/dap/launch.py b/gdb/python/lib/gdb/dap/launch.py
index 8ac4c7750c6..00676c3d75c 100644
--- a/gdb/python/lib/gdb/dap/launch.py
+++ b/gdb/python/lib/gdb/dap/launch.py
@@ -28,6 +28,7 @@ from .server import (
     request,
     send_gdb,
     send_gdb_with_response,
+    set_command_escape_prefix,
 )
 from .startup import DAPException, exec_and_log, in_dap_thread, in_gdb_thread
 
@@ -80,6 +81,7 @@ def launch(
     env: Optional[Mapping[str, str]] = None,
     stopAtBeginningOfMainSubprogram: bool = False,
     stopOnEntry: bool = False,
+    commandEscapePrefix: str = "",
     **extra,
 ):
     # Launch setup is handled here.  This is done synchronously so
@@ -123,6 +125,7 @@ def launch(
 
     # The launch itself is deferred until the configurationDone
     # request.
+    set_command_escape_prefix(commandEscapePrefix)
     return _LaunchOrAttachDeferredRequest(_launch_impl)
 
 
@@ -132,6 +135,7 @@ def attach(
     program: Optional[str] = None,
     pid: Optional[int] = None,
     target: Optional[str] = None,
+    commandEscapePrefix: str = "",
     **args,
 ):
     # The actual attach is handled by this function.
@@ -157,6 +161,7 @@ def attach(
 
     # The attach itself is deferred until the configurationDone
     # request.
+    set_command_escape_prefix(commandEscapePrefix)
     return _LaunchOrAttachDeferredRequest(_attach_impl)
 
 
diff --git a/gdb/python/lib/gdb/dap/server.py b/gdb/python/lib/gdb/dap/server.py
index 98a80842633..b983a0a38d0 100644
--- a/gdb/python/lib/gdb/dap/server.py
+++ b/gdb/python/lib/gdb/dap/server.py
@@ -51,6 +51,20 @@ _server = None
 _lines_start_at_1 = False
 _columns_start_at_1 = False
 
+# The escape prefix to use for executing regular GDB commands in the
+# Debug Console.
+_command_escape_prefix: str = ""
+
+def get_command_escape_prefix() -> str:
+    """Return the command escape prefix.
+    """
+    return _command_escape_prefix
+
+def set_command_escape_prefix(command_escape_prefix: str) -> None:
+    """Set the command escape prefix to COMMAND_ESCAPE_PREFIX.
+    """
+    global _command_escape_prefix
+    _command_escape_prefix = command_escape_prefix
 
 class DeferredRequest:
     """If a DAP request function returns a deferred request, no
-- 
2.51.2.windows.1


             reply	other threads:[~2025-11-16 14:27 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-16 14:26 oltolm [this message]
2025-11-16 14:31 ` Eli Zaretskii
2025-11-16 14:33   ` Oleg Tolmatcev
2025-11-16 15:03     ` Eli Zaretskii
2025-11-19 18:52       ` Tom Tromey
2025-11-19 18:54 ` Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251116142613.1736-2-oleg.tolmatcev@gmail.com \
    --to=oleg.tolmatcev@gmail.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox