diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/NEWS | 5 | ||||
-rw-r--r-- | gdb/cli/cli-script.c | 4 | ||||
-rw-r--r-- | gdb/cli/cli-script.h | 6 | ||||
-rw-r--r-- | gdb/cli/cli-style.c | 21 | ||||
-rw-r--r-- | gdb/cli/cli-style.h | 19 | ||||
-rw-r--r-- | gdb/doc/python.texi | 10 | ||||
-rw-r--r-- | gdb/python/python.c | 39 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-styled-execute.exp | 109 |
8 files changed, 201 insertions, 12 deletions
@@ -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 (¤t_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 +} |