mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 04:24:43 +00:00
After the last commit there were still a couple of calls to
m_stream->emit_style_escape in the pager_file class. As discussed in
the last commit, these are likely wrong, but I'd not been able to
produce any bugs because of them.
The reason why there are no bugs is that these calls are, I think,
entirely redundant. Consider this block:
if (m_wrap_column)
{
/* We are about to insert a newline at an historic
location in the WRAP_BUFFER. Before we do we want to
restore the default style. To know if we actually
need to insert an escape sequence we must restore the
current applied style to how it was at the WRAP_COLUMN
location. */
m_applied_style = m_wrap_style;
m_stream->emit_style_escape (ui_file_style ());
/* If we aren't actually wrapping, don't output
newline -- if chars_per_line is right, we
probably just overflowed anyway; if it's wrong,
let us keep going. */
m_stream->puts ("\n");
}
What we know (see previous commit) is that the call:
m_stream->emit_style_escape (ui_file_style ());
is dangerous as m_stream->m_applied_style is going to be out of sync
with its current state. Actually, m_stream->m_applied_style is likely
to be the default style as it is not updated elsewhere. So why does
this not cause problems?
Well, GDB's style output is always done in tightly scoped regions.
That means if we want to print some styled output, and then apply a
wrap point the code might look like this:
fprintf_styled (gdb_stdout, file_name_style, "some text");
gdb_stdout->wrap_here (4);
But, after printing 'some text', the style of gdb_stdout will have
returned to the default style.
My claim is that, whenever we encounter a wrap_here call, the stream
in question will _always_ have been returned to the default style.
This means that, in the block above, the call:
m_stream->emit_style_escape (ui_file_style ());
will never emit anything because it depends on a check against
m_stream->m_applied_style, which will always mean that the above call
does nothing. But that's OK. By chance, we'll have always placed the
stream into a default style state anyway, so no harm done.
Similarly, the other call:
/* Having finished inserting the wrapping we should
restore the style as it was at the WRAP_COLUMN. */
m_stream->emit_style_escape (m_wrap_style);
Tries to return m_stream to the state it was in at the point of the
wrap_here call. But, as described above, this will always be the
default style, so the above call will do nothing, but that just
happens to be exactly what we want!
So what does this commit do?
Well, I "fix" the above code by removing the
m_stream->emit_style_escape calls and replacing them with calls to
puts, passing in the escape sequence for the required style, but only
if the m_stream style as tracked by pager_file::m_stream_style
indicates this is needed.
Got the reasons given above, this should mean there is no change after
this patch. We still shouldn't be emitting any extra escape
sequences. But, should we ever manage to get into a state where we
call wrap_here with a stream in a style other than the default, then
this should mean things work as expected.
There should be no user visible changes after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
107 lines
2.9 KiB
C++
107 lines
2.9 KiB
C++
/* Output pager for gdb
|
|
Copyright (C) 2021-2025 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
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/>. */
|
|
|
|
#ifndef GDB_PAGER_H
|
|
#define GDB_PAGER_H
|
|
|
|
#include "ui-file.h"
|
|
|
|
/* A ui_file that implements output paging and unfiltered output. */
|
|
|
|
class pager_file : public wrapped_file
|
|
{
|
|
public:
|
|
/* Create a new pager_file. The new object takes ownership of
|
|
STREAM. */
|
|
explicit pager_file (ui_file *stream)
|
|
: wrapped_file (stream)
|
|
{
|
|
}
|
|
|
|
~pager_file ()
|
|
{
|
|
delete m_stream;
|
|
}
|
|
|
|
DISABLE_COPY_AND_ASSIGN (pager_file);
|
|
|
|
void write (const char *buf, long length_buf) override;
|
|
|
|
void puts (const char *str) override;
|
|
|
|
void write_async_safe (const char *buf, long length_buf) override
|
|
{
|
|
m_stream->write_async_safe (buf, length_buf);
|
|
}
|
|
|
|
void emit_style_escape (const ui_file_style &style) override;
|
|
|
|
void flush () override;
|
|
|
|
void wrap_here (int indent) override;
|
|
|
|
void puts_unfiltered (const char *str) override
|
|
{
|
|
flush_wrap_buffer ();
|
|
m_stream->puts_unfiltered (str);
|
|
}
|
|
|
|
private:
|
|
|
|
void prompt_for_continue ();
|
|
|
|
/* Flush the wrap buffer to STREAM, if necessary. */
|
|
void flush_wrap_buffer ();
|
|
|
|
/* Set the style of m_stream to STYLE. */
|
|
void set_stream_style (const ui_file_style &style)
|
|
{
|
|
if (m_stream->can_emit_style_escape () && m_stream_style != style)
|
|
{
|
|
m_stream->puts (style.to_ansi ().c_str ());
|
|
m_stream_style = style;
|
|
}
|
|
}
|
|
|
|
/* Contains characters which are waiting to be output (they have
|
|
already been counted in chars_printed). */
|
|
std::string m_wrap_buffer;
|
|
|
|
/* Amount to indent by if the wrap occurs. */
|
|
int m_wrap_indent = 0;
|
|
|
|
/* Column number on the screen where wrap_buffer begins, or 0 if
|
|
wrapping is not in effect. */
|
|
int m_wrap_column = 0;
|
|
|
|
/* The style applied at the time that wrap_here was called. */
|
|
ui_file_style m_wrap_style;
|
|
|
|
/* The style currently applied to m_stream. While m_applied_style is the
|
|
style that is applied to new content added to m_wrap_buffer, the
|
|
m_stream_style reflects changes that have been flushed to the managed
|
|
stream. */
|
|
ui_file_style m_stream_style;
|
|
|
|
/* This is temporarily set when paging. This will cause some
|
|
methods to change their behavior to ignore the wrap buffer. */
|
|
bool m_paging = false;
|
|
};
|
|
|
|
#endif /* GDB_PAGER_H */
|