aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/NEWS5
-rw-r--r--gdb/cli/cli-script.c4
-rw-r--r--gdb/cli/cli-script.h6
-rw-r--r--gdb/cli/cli-style.c21
-rw-r--r--gdb/cli/cli-style.h19
-rw-r--r--gdb/doc/python.texi10
-rw-r--r--gdb/python/python.c39
-rw-r--r--gdb/testsuite/gdb.python/py-styled-execute.exp109
8 files changed, 201 insertions, 12 deletions
diff --git a/gdb/NEWS b/gdb/NEWS
index 42e6de6..2fdb849 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -65,6 +65,11 @@ info sharedlibrary
was never documented in the GDB manual, so users should not have
been using it.
+ ** gdb.execute has an additional 'styling' argument. When True, then
+ output will be styled. The default for this argument is True
+ when output is going to standard output, and False when output is
+ going to a string.
+
* Guile API
** New type <gdb:color> for dealing with colors.
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 9131768..5decf3b 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -422,14 +422,14 @@ execute_control_commands (struct command_line *cmdlines, int from_tty)
std::string
execute_control_commands_to_string (struct command_line *commands,
- int from_tty)
+ int from_tty, bool term_out)
{
std::string result;
execute_fn_to_string (result, [&] ()
{
execute_control_commands (commands, from_tty);
- }, false);
+ }, term_out);
return result;
}
diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h
index 23bd83e..df7316e 100644
--- a/gdb/cli/cli-script.h
+++ b/gdb/cli/cli-script.h
@@ -143,10 +143,12 @@ extern void execute_control_commands (struct command_line *cmdlines,
/* Run execute_control_commands for COMMANDS. Capture its output into
the returned string, do not display it to the screen. BATCH_FLAG
- will be temporarily set to true. */
+ will be temporarily set to true. When TERM_OUT is true the output is
+ collected with terminal behavior (e.g. with styling). When TERM_OUT is
+ false raw output will be collected (e.g. no styling). */
extern std::string execute_control_commands_to_string
- (struct command_line *commands, int from_tty);
+ (struct command_line *commands, int from_tty, bool term_out);
/* Exported to gdb/breakpoint.c */
diff --git a/gdb/cli/cli-style.c b/gdb/cli/cli-style.c
index 3ca30a4..b436275 100644
--- a/gdb/cli/cli-style.c
+++ b/gdb/cli/cli-style.c
@@ -51,6 +51,25 @@ static const char * const cli_intensities[] = {
nullptr
};
+/* When true styling is being temporarily suppressed. */
+
+static bool scoped_disable_styling_p = false;
+
+/* See cli/cli-style.h. */
+
+scoped_disable_styling::scoped_disable_styling ()
+{
+ m_old_value = scoped_disable_styling_p;
+ scoped_disable_styling_p = true;
+}
+
+/* See cli/cli-style.h. */
+
+scoped_disable_styling::~scoped_disable_styling ()
+{
+ scoped_disable_styling_p = m_old_value;
+}
+
/* Return true if GDB's output terminal should support styling, otherwise,
return false. This function really checks for things that indicate
styling might not be supported, so a return value of false indicates
@@ -91,7 +110,7 @@ disable_cli_styling ()
bool
term_cli_styling ()
{
- return cli_styling;
+ return cli_styling && !scoped_disable_styling_p;
}
/* See cli/cli-style.h. */
diff --git a/gdb/cli/cli-style.h b/gdb/cli/cli-style.h
index 18827ce..e94b48d 100644
--- a/gdb/cli/cli-style.h
+++ b/gdb/cli/cli-style.h
@@ -171,4 +171,23 @@ extern void disable_cli_styling ();
/* Return true styled output is currently enabled. */
extern bool term_cli_styling ();
+/* Allow styling to be temporarily suppressed without changing the value of
+ 'set style enabled' user setting. This is useful in, for example, the
+ Python gdb.execute() call which can produce unstyled output. */
+struct scoped_disable_styling
+{
+ /* Temporarily suppress styling without changing the value of 'set
+ style enabled' user setting. */
+ scoped_disable_styling ();
+
+ /* If the constructor started suppressing styling, then styling is
+ resumed after this destructor call. */
+ ~scoped_disable_styling ();
+
+private:
+
+ /* The value to restore in the destructor. */
+ bool m_old_value;
+};
+
#endif /* GDB_CLI_CLI_STYLE_H */
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 0dbb37b..50342bb 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -285,7 +285,7 @@ offered for debugging purposes only, expect them to change over time.
A string containing the python directory (@pxref{Python}).
@end defvar
-@defun gdb.execute (command @r{[}, from_tty @r{[}, to_string@r{]]})
+@defun gdb.execute (command @r{[}, from_tty @r{[}, to_string @w{@r{[}, styling @r{]]]}})
Evaluate @var{command}, a string, as a @value{GDBN} CLI command.
If a GDB exception happens while @var{command} runs, it is
translated as described in @ref{Exception Handling,,Exception Handling}.
@@ -302,6 +302,14 @@ returned as a string. The default is @code{False}, in which case the
return value is @code{None}. If @var{to_string} is @code{True}, the
@value{GDBN} virtual terminal will be temporarily set to unlimited width
and height, and its pagination will be disabled; @pxref{Screen Size}.
+
+When @var{styling} is @code{True}, the output, whether sent to
+standard output, or to a string, will have styling applied, if
+@value{GDBN}'s standard output supports styling, and @kbd{show style
+enabled} is @kbd{on}. When @var{styling} is @code{False} then no
+styling is applied. The default for @var{styling} is @code{True} when
+@var{to_string} is @code{False}, and @code{False} when @var{to_string}
+is @code{True}.
@end defun
@defun gdb.breakpoints ()
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 8f8030c..2aaa30c 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -36,6 +36,7 @@
#include "run-on-main-thread.h"
#include "observable.h"
#include "build-id.h"
+#include "cli/cli-style.h"
#if GDB_SELF_TEST
#include "gdbsupport/selftest.h"
@@ -660,12 +661,14 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
const char *arg;
PyObject *from_tty_obj = nullptr;
PyObject *to_string_obj = nullptr;
- static const char *keywords[] = { "command", "from_tty", "to_string",
- nullptr };
+ PyObject *styling = nullptr;
+ static const char *keywords[]
+ = { "command", "from_tty", "to_string", "styling", nullptr };
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!O!", keywords, &arg,
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!O!O!", keywords, &arg,
&PyBool_Type, &from_tty_obj,
- &PyBool_Type, &to_string_obj))
+ &PyBool_Type, &to_string_obj,
+ &PyBool_Type, &styling))
return nullptr;
bool from_tty = false;
@@ -686,6 +689,15 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
to_string = (cmp != 0);
}
+ bool styling_p = !to_string;
+ if (styling != nullptr)
+ {
+ int cmp = PyObject_IsTrue (styling);
+ if (cmp < 0)
+ return nullptr;
+ styling_p = (cmp != 0);
+ }
+
std::string to_string_res;
scoped_restore preventer = prevent_dont_repeat ();
@@ -745,14 +757,29 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw)
scoped_restore save_uiout = make_scoped_restore (&current_uiout);
+ /* If the Python 'styling' argument was False then temporarily
+ disable styling. Otherwise, don't do anything, styling could
+ already be disabled for some other reason, we shouldn't override
+ that and force styling on. */
+ std::optional<scoped_disable_styling> disable_styling;
+ if (!styling_p)
+ disable_styling.emplace ();
+
/* Use the console interpreter uiout to have the same print format
for console or MI. */
interp = interp_lookup (current_ui, "console");
current_uiout = interp->interp_ui_out ();
if (to_string)
- to_string_res = execute_control_commands_to_string (lines.get (),
- from_tty);
+ {
+ /* Pass 'true' here to always request styling, however, if
+ the scoped_disable_styling disabled styling, or the user
+ has globally disabled styling, then the output will not be
+ styled. */
+ to_string_res
+ = execute_control_commands_to_string (lines.get (), from_tty,
+ true);
+ }
else
execute_control_commands (lines.get (), from_tty);
}
diff --git a/gdb/testsuite/gdb.python/py-styled-execute.exp b/gdb/testsuite/gdb.python/py-styled-execute.exp
new file mode 100644
index 0000000..0b27c63
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-styled-execute.exp
@@ -0,0 +1,109 @@
+# Copyright (C) 2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Check the the output of gdb.execute can be styled or not depending
+# on the value of the third argument passed to gdb.execute.
+
+require allow_python_tests
+
+load_lib gdb-python.exp
+
+# Use gdb.execute() to run CMD passing different argument values. The
+# output should match either STYLED_RE or UNSTYLED_RE depending on
+# whether the 'styling' argument is True or False.
+proc do_gdb_execute { cmd styled_re unstyled_re } {
+ gdb_test "python gdb.execute('$cmd')" $styled_re
+
+ foreach from_tty { True False } {
+ gdb_test \
+ "python gdb.execute('$cmd', $from_tty)" \
+ $styled_re
+ gdb_test \
+ "python gdb.execute('$cmd', $from_tty, False)" \
+ $styled_re
+ gdb_test \
+ "python gdb.execute('$cmd', $from_tty, False, True)" \
+ $styled_re
+ gdb_test \
+ "python gdb.execute('$cmd', $from_tty, False, False)" \
+ $unstyled_re
+ gdb_test \
+ "python print(gdb.execute('$cmd', $from_tty, True), end='')" \
+ $unstyled_re
+ gdb_test \
+ "python print(gdb.execute('$cmd', $from_tty, True, False), end='')" \
+ $unstyled_re
+ gdb_test \
+ "python print(gdb.execute('$cmd', $from_tty, True, True), end='')" \
+ $styled_re
+ }
+}
+
+# Test that the output from gdb.execute is styled or not based on the
+# arguments passed in.
+proc test_gdb_execute_styling {} {
+ clean_restart
+
+ # Two possible outputs, BASIC_RE, the unstyled output text, or
+ # STYLED_RE, the same things, but with styling applied.
+ set text "\"version\" style"
+ set styled_text \
+ [style "\"" version][style "version" version][style "\" style" version]
+ set basic_re "The $text foreground color is: \[^\r\n\]+"
+ set styled_re "The $styled_text foreground color is: \[^\r\n\]+"
+
+ # The command we'll run. It's output matches the above regexp.
+ set show_style_version_cmd "show style version foreground"
+
+ # Another command we'll run. The output of this command is never
+ # styled, but we run this to check that the output doesn't change
+ # even when gdb.execute() asks for styled, or unstyled output.
+ set show_style_enabled_cmd "show style enabled"
+
+ with_test_prefix "with style enabled on" {
+ do_gdb_execute $show_style_version_cmd $styled_re $basic_re
+
+ # This time, print the value of 'show style enabled'. This
+ # output is unstyled, so there's only one regexp. The
+ # interesting thing here is that we don't expect the output to
+ # change, even when gdb.execute() is printing unstyled output.
+ # The "styling=False" argument to gdb.execute() is separate to
+ # the 'set style enabled on|off' setting.
+ set re "CLI output styling is enabled\\."
+ do_gdb_execute $show_style_enabled_cmd $re $re
+ }
+
+ gdb_test_no_output "set style enabled off"
+
+ with_test_prefix "with style enabled off" {
+ # With 'set style enabled off' in use, even a request to
+ # gdb.execute() to produce styled output should produce
+ # unstyled output. The assumption is that 'set style enabled
+ # off' is done by the user, while the gdb.execute() is likely
+ # from some Python extension. The users request for no
+ # styling overrules the extensions request for styled output.
+ do_gdb_execute $show_style_version_cmd $basic_re $basic_re
+
+ # Now check that even when we request styled output, the 'show
+ # style enabled' value is always reported as disabled.
+ set re "CLI output styling is disabled\\."
+ do_gdb_execute $show_style_enabled_cmd $re $re
+ }
+}
+
+# Run the tests.
+with_ansi_styling_terminal {
+ test_gdb_execute_styling
+}