mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
887ae0cf2b
This patch adds separate styling for line numbers. That is, whenever gdb prints a source line number, it uses this style. v2 includes a change to ensure that %ps works in query. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Reviewed-by: Keith Seitz <keiths@redhat.com>
372 lines
12 KiB
C++
372 lines
12 KiB
C++
/* TUI display source/assembly window.
|
|
|
|
Copyright (C) 1998-2024 Free Software Foundation, Inc.
|
|
|
|
Contributed by Hewlett-Packard Company.
|
|
|
|
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 TUI_TUI_WINSOURCE_H
|
|
#define TUI_TUI_WINSOURCE_H
|
|
|
|
#include "gdbsupport/observable.h"
|
|
#include "tui/tui-data.h"
|
|
#include "symtab.h"
|
|
|
|
enum tui_line_or_address_kind
|
|
{
|
|
LOA_LINE,
|
|
LOA_ADDRESS
|
|
};
|
|
|
|
/* Structure describing source line or line address. */
|
|
struct tui_line_or_address
|
|
{
|
|
enum tui_line_or_address_kind loa;
|
|
union
|
|
{
|
|
int line_no;
|
|
CORE_ADDR addr;
|
|
} u;
|
|
};
|
|
|
|
/* Flags to tell what kind of breakpoint is at current line. */
|
|
enum tui_bp_flag
|
|
{
|
|
TUI_BP_ENABLED = 0x01,
|
|
TUI_BP_DISABLED = 0x02,
|
|
TUI_BP_HIT = 0x04,
|
|
TUI_BP_CONDITIONAL = 0x08,
|
|
TUI_BP_HARDWARE = 0x10
|
|
};
|
|
|
|
DEF_ENUM_FLAGS_TYPE (enum tui_bp_flag, tui_bp_flags);
|
|
|
|
/* Position of breakpoint markers in the exec info string. */
|
|
#define TUI_BP_HIT_POS 0
|
|
#define TUI_BP_BREAK_POS 1
|
|
#define TUI_EXEC_POS 2
|
|
#define TUI_EXECINFO_SIZE 3
|
|
|
|
/* Elements in the Source/Disassembly Window. */
|
|
struct tui_source_element
|
|
{
|
|
tui_source_element ()
|
|
{
|
|
line_or_addr.loa = LOA_LINE;
|
|
line_or_addr.u.line_no = 0;
|
|
}
|
|
|
|
DISABLE_COPY_AND_ASSIGN (tui_source_element);
|
|
|
|
tui_source_element (tui_source_element &&other)
|
|
: line (std::move (other.line)),
|
|
line_or_addr (other.line_or_addr),
|
|
is_exec_point (other.is_exec_point),
|
|
break_mode (other.break_mode)
|
|
{
|
|
}
|
|
|
|
std::string line;
|
|
struct tui_line_or_address line_or_addr;
|
|
bool is_exec_point = false;
|
|
tui_bp_flags break_mode = 0;
|
|
};
|
|
|
|
|
|
/* The base class for all source-like windows, namely the source and
|
|
disassembly windows. */
|
|
|
|
struct tui_source_window_base : public tui_win_info
|
|
{
|
|
protected:
|
|
tui_source_window_base ();
|
|
~tui_source_window_base ();
|
|
|
|
DISABLE_COPY_AND_ASSIGN (tui_source_window_base);
|
|
|
|
void do_scroll_horizontal (int num_to_scroll) override;
|
|
|
|
/* Erase the content and display STRING. */
|
|
void do_erase_source_content (const char *string);
|
|
|
|
void rerender () override;
|
|
|
|
virtual bool set_contents (struct gdbarch *gdbarch,
|
|
const struct symtab_and_line &sal) = 0;
|
|
|
|
/* Return the number of extra margin characters needed by this
|
|
instance. */
|
|
virtual int extra_margin () const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* Display the line number in the window margin. OFFSET indicates
|
|
which line to display; it is 0-based, with 0 meaning the line at
|
|
the top of the window. */
|
|
virtual void show_line_number (int offset) const
|
|
{
|
|
}
|
|
|
|
/* Redraw the complete line of a source or disassembly window. */
|
|
void show_source_line (int lineno);
|
|
|
|
/* Where to start generating content from. */
|
|
struct tui_line_or_address m_start_line_or_addr;
|
|
|
|
/* Architecture associated with code at this location. */
|
|
struct gdbarch *m_gdbarch = nullptr;
|
|
|
|
std::vector<tui_source_element> m_content;
|
|
|
|
/* Length of longest line to be displayed. */
|
|
int m_max_length;
|
|
|
|
public:
|
|
|
|
/* Refill the source window's source cache and update it. If this
|
|
is a disassembly window, then just update it. */
|
|
void refill ();
|
|
|
|
/* Set the location of the execution point. */
|
|
void set_is_exec_point_at (struct tui_line_or_address l);
|
|
|
|
void update_tab_width () override;
|
|
|
|
virtual bool location_matches_p (struct bp_location *loc, int line_no) = 0;
|
|
|
|
/* Fill in the left margin of the current window with execution indicator
|
|
information, e.g. breakpoint indicators, and line numbers. When
|
|
REFRESH_P is true this function will call refresh_window to ensure
|
|
updates are written to the screen, otherwise the refresh is skipped,
|
|
which will leave the on screen contents out of date. When passing
|
|
false for REFRESH_P you should be planning to call refresh_window
|
|
yourself. */
|
|
void update_exec_info (bool refresh_p = true);
|
|
|
|
/* Update the window to display the given location. Does nothing if
|
|
the location is already displayed. */
|
|
virtual void maybe_update (const frame_info_ptr &fi, symtab_and_line sal) = 0;
|
|
|
|
void update_source_window_as_is (struct gdbarch *gdbarch,
|
|
const struct symtab_and_line &sal);
|
|
void update_source_window (struct gdbarch *gdbarch,
|
|
const struct symtab_and_line &sal);
|
|
|
|
/* Scan the source window and the breakpoints to update the
|
|
break_mode information for each line. Returns true if something
|
|
changed and the execution window must be refreshed. See
|
|
tui_update_all_breakpoint_info for a description of
|
|
BEING_DELETED. */
|
|
bool update_breakpoint_info (struct breakpoint *being_deleted,
|
|
bool current_only);
|
|
|
|
/* Erase the source content. */
|
|
virtual void erase_source_content () = 0;
|
|
|
|
void refresh_window () override;
|
|
|
|
/* Return the start address and gdbarch. */
|
|
virtual void display_start_addr (struct gdbarch **gdbarch_p,
|
|
CORE_ADDR *addr_p) = 0;
|
|
|
|
/* Function to ensure that the source or disassembly window
|
|
reflects the input address. Single window variant of
|
|
update_source_windows_with_addr. */
|
|
void update_source_window_with_addr (struct gdbarch *, CORE_ADDR);
|
|
|
|
protected:
|
|
|
|
/* Called when a user style setting is changed. */
|
|
void style_changed ();
|
|
|
|
private:
|
|
|
|
/* Used for horizontal scroll. */
|
|
int m_horizontal_offset = 0;
|
|
|
|
/* Check that the current values of M_HORIZONTAL_OFFSET and M_PAD_OFFSET
|
|
make sense given the current M_MAX_LENGTH (content width), WIDTH
|
|
(window size), and window margins. After calling this function
|
|
M_HORIZONTAL_OFFSET and M_PAD_OFFSET might have been adjusted to
|
|
reduce unnecessary whitespace on the right side of the window.
|
|
|
|
If M_PAD_OFFSET is adjusted then this function returns true
|
|
indicating that the pad contents need to be reloaded by calling
|
|
show_source_content. If M_PAD_OFFSET is not adjusted then this
|
|
function returns false, the window contents might still need
|
|
redrawing if M_HORIZONTAL_OFFSET was adjusted, but right now, this
|
|
function is only called in contexts where the window is going to be
|
|
redrawn anyway. */
|
|
bool validate_scroll_offsets ();
|
|
|
|
/* Return the size of the left margin space, this is the space used to
|
|
display things like breakpoint markers. */
|
|
int left_margin () const
|
|
{ return TUI_EXECINFO_SIZE + extra_margin (); }
|
|
|
|
/* Return the width of the area that is available for window content.
|
|
This is the window width minus the borders and the left margin, which
|
|
is used for displaying things like breakpoint markers. */
|
|
int view_width () const
|
|
{ return width - left_margin () - box_size (); }
|
|
|
|
void show_source_content ();
|
|
|
|
/* Write STRING to the window M_PAD, but skip the first SKIP printable
|
|
characters. Any escape sequences within the first SKIP characters are
|
|
still processed though. This means if we have this string:
|
|
|
|
"\033[31mABCDEFGHIJKLM\033[0m"
|
|
|
|
and call this function with a skip value of 3, then we effectively
|
|
write this string to M_PAD:
|
|
|
|
"\033[31mDEFGHIJKLM\033[0m"
|
|
|
|
the initial escape that sets the color will still be applied. */
|
|
void puts_to_pad_with_skip (const char *string, int skip);
|
|
|
|
/* A token used to register and unregister an observer. */
|
|
gdb::observers::token m_observable;
|
|
|
|
/* Pad to hold some, or all, of the window contents. Content is then
|
|
copied from this pad to the screen as the user scrolls horizontally,
|
|
this avoids the need to recalculate the screen contents each time the
|
|
user does a horizontal scroll. */
|
|
std::unique_ptr<WINDOW, curses_deleter> m_pad;
|
|
|
|
/* When M_PAD was allocated, this holds the width that was initially
|
|
asked for. If we ask for a very large pad then the allocation may
|
|
fail, and we might instead allocate a narrower pad. */
|
|
int m_pad_requested_width = 0;
|
|
|
|
/* If M_PAD is not as wide as the content (so less than M_MAX_LENGTH)
|
|
then this value indicates the offset at which the pad contents begin. */
|
|
int m_pad_offset = 0;
|
|
};
|
|
|
|
|
|
/* A wrapper for a TUI window iterator that only iterates over source
|
|
windows. */
|
|
|
|
struct tui_source_window_iterator
|
|
{
|
|
public:
|
|
|
|
typedef std::vector<tui_win_info *>::iterator inner_iterator;
|
|
|
|
typedef tui_source_window_iterator self_type;
|
|
typedef struct tui_source_window_base *value_type;
|
|
typedef struct tui_source_window_base *&reference;
|
|
typedef struct tui_source_window_base **pointer;
|
|
typedef std::forward_iterator_tag iterator_category;
|
|
typedef int difference_type;
|
|
|
|
explicit tui_source_window_iterator (const inner_iterator &it,
|
|
const inner_iterator &end)
|
|
: m_iter (it),
|
|
m_end (end)
|
|
{
|
|
advance ();
|
|
}
|
|
|
|
explicit tui_source_window_iterator (const inner_iterator &it)
|
|
: m_iter (it)
|
|
{
|
|
}
|
|
|
|
bool operator!= (const self_type &other) const
|
|
{
|
|
return m_iter != other.m_iter;
|
|
}
|
|
|
|
value_type operator* () const
|
|
{
|
|
return dynamic_cast<tui_source_window_base *> (*m_iter);
|
|
}
|
|
|
|
self_type &operator++ ()
|
|
{
|
|
++m_iter;
|
|
advance ();
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
|
|
void advance ()
|
|
{
|
|
while (m_iter != m_end
|
|
&& dynamic_cast<tui_source_window_base *> (*m_iter) == nullptr)
|
|
++m_iter;
|
|
}
|
|
|
|
inner_iterator m_iter;
|
|
inner_iterator m_end;
|
|
};
|
|
|
|
/* A range adapter for source windows. */
|
|
|
|
struct tui_source_windows
|
|
{
|
|
/* Work around Wmaybe-uninitialized warning with g++ 11.0.0, see also
|
|
PR gcc/96295. Note that "tui_source_windows () = default" doesn't work
|
|
around the warning. */
|
|
tui_source_windows () {}
|
|
|
|
tui_source_window_iterator begin () const
|
|
{
|
|
return tui_source_window_iterator (tui_windows.begin (),
|
|
tui_windows.end ());
|
|
}
|
|
|
|
tui_source_window_iterator end () const
|
|
{
|
|
return tui_source_window_iterator (tui_windows.end ());
|
|
}
|
|
};
|
|
|
|
/* Update the execution windows to show the active breakpoints. This
|
|
is called whenever a breakpoint is inserted, removed or has its
|
|
state changed. Normally BEING_DELETED is nullptr; if not nullptr,
|
|
it indicates a breakpoint that is in the process of being deleted,
|
|
and which should therefore be ignored by the update. This is done
|
|
because the relevant observer is notified before the breakpoint is
|
|
removed from the list of breakpoints. */
|
|
extern void tui_update_all_breakpoint_info (struct breakpoint *being_deleted);
|
|
|
|
/* Function to display the "main" routine. */
|
|
extern void tui_display_main (void);
|
|
extern void tui_update_source_windows_with_addr (struct gdbarch *, CORE_ADDR);
|
|
extern void tui_update_source_windows_with_line (struct symtab_and_line sal);
|
|
|
|
/* Extract some source text from PTR. Returns a string holding the
|
|
desired text. PTR is updated to point to the start of the next
|
|
line. If LENGTH is non-NULL, then the length of the line is stored
|
|
there. Escape sequences are not counted against the length.
|
|
Actually an approximation is used -- each byte of a multi-byte
|
|
sequence counts as a character here. */
|
|
|
|
extern std::string tui_copy_source_line (const char **ptr,
|
|
int *length = nullptr);
|
|
|
|
/* Constant definitions. */
|
|
#define SCROLL_THRESHOLD 2 /* Threshold for lazy scroll. */
|
|
|
|
#endif /* TUI_TUI_WINSOURCE_H */
|