diff options
| author | Andrew Burgess <aburgess@redhat.com> | 2025-06-18 15:02:29 +0100 |
|---|---|---|
| committer | Andrew Burgess <aburgess@redhat.com> | 2025-08-24 16:57:32 +0100 |
| commit | 3825c972a636852600b47c242826313f4b9963b8 (patch) | |
| tree | 7742ba11e2abd3f4f062bc8e37a5c11aedb26d9a /gdb/python/python.c | |
| parent | 356fff4944574b40d58146b3d09fa0c980aa0a70 (diff) | |
| download | binutils-3825c972a636852600b47c242826313f4b9963b8.zip binutils-3825c972a636852600b47c242826313f4b9963b8.tar.gz binutils-3825c972a636852600b47c242826313f4b9963b8.tar.bz2 | |
gdb: allow gdb.Color to work correctly with pagination
This commit allows gdb.Color objects to be used to style output from
GDB commands written in Python, and the styled output should work
correctly with pagination.
There are two parts to fixing this:
First, GDB needs to be able to track the currently applied style
within the page_file class. This means that style changes need to be
achieved with calls to pager_file::emit_style_escape.
Now usually, GDB does this by calling something like fprintf_styled,
which takes care to apply the style for us. However, that's not
really an option here as a gdb.Color isn't a full style, and as the
gdb.Color object is designed to be converted directly into escape
sequences that can then be printed, we really need a solution that
works with this approach.
However pager_file::puts already has code in place to handle escape
sequences. Right now all this code does is spot the escape sequence
and append it to the m_wrap_buffer. But in this commit I propose that
we go one step further, parse the escape sequence back into a
ui_file_style object in pager_file::puts, and then we can call
pager_file::emit_style_escape.
If the parsing doesn't work then we can just add the escape sequence
to m_wrap_buffer as we did before.
But wait, how can this work if a gdb.Color isn't a full style? Turns
out that's not a problem. We only ever emit the escape sequence for
those parts of a style that need changing, so a full style that sets
the foreground color will emit the same escape sequence as a gdb.Color
for the foreground. When we convert the escape sequence back into a
ui_file_style, then we get a style with everything set to default,
except the foreground color.
I had hoped that this would be all that was needed. But unfortunately
this doesn't work because of the second problem...
... the implementation of the Python function gdb.write() calls
gdb_printf(), which calls gdb_vprintf(), which calls ui_file::vprintf,
which calls ui_out::vmessage, which calls ui_out::call_do_message, and
finally we reach cli_ui_out::do_message. This final do_message
function does this:
ui_file *stream = m_streams.back ();
stream->emit_style_escape (style);
stream->puts (str.c_str ());
stream->emit_style_escape (ui_file_style ());
If we imagine the case where we are emitting a style, triggered from
Python like this:
gdb.write(gdb.Color('red').escape_sequence(True))
the STYLE in this case will be the default ui_file_style(), and STR
will hold the escape sequence we are writing.
After the first change, where pager_file::puts now calls
pager_file::emit_style_escape, the current style of STREAM will have
been updated. But this means that the final emit_style_escape will
now restore the default style.
The fix for this is to avoid using the high level gdb_printf from
gdb.write(), and instead use gdb_puts instead. The gdb_puts function
doesn't restore the default style, which means our style modification
survives.
There's a new test included. This test includes what appears like a
pointless extra loop (looping over a single value), but this makes
sense given the origin of this patch. I've pulled this commit from a
longer series:
https://inbox.sourceware.org/gdb-patches/cover.1755080429.git.aburgess@redhat.com
I want to get this bug fix merged before GDB 17 branches, but the
longer series is not getting reviews, so for now I'm just merging this
one fix. Once the rest of the series gets merged, I'll be extending
the test, and the loop (mentioned above) will now loop over more
values.
Diffstat (limited to 'gdb/python/python.c')
| -rw-r--r-- | gdb/python/python.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/gdb/python/python.c b/gdb/python/python.c index cb0d642..1af7896 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1570,21 +1570,21 @@ gdbpy_write (PyObject *self, PyObject *args, PyObject *kw) try { + ui_file *stream; switch (stream_type) { case 1: - { - gdb_printf (gdb_stderr, "%s", arg); - break; - } + stream = gdb_stderr; + break; case 2: - { - gdb_printf (gdb_stdlog, "%s", arg); - break; - } + stream = gdb_stdlog; + break; default: - gdb_printf (gdb_stdout, "%s", arg); + stream = gdb_stdout; + break; } + + gdb_puts (arg, stream); } catch (const gdb_exception &except) { |
