aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Core/IOHandlerCursesGUI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core/IOHandlerCursesGUI.cpp')
-rw-r--r--lldb/source/Core/IOHandlerCursesGUI.cpp246
1 files changed, 117 insertions, 129 deletions
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
index b37e84a13c5e..0151255631bf 100644
--- a/lldb/source/Core/IOHandlerCursesGUI.cpp
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -28,6 +28,7 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObjectUpdater.h"
#include "lldb/Host/File.h"
+#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
@@ -341,7 +342,7 @@ public:
protected:
StringList m_text;
- int m_first_visible_line;
+ int m_first_visible_line = 0;
};
// A surface is an abstraction for something than can be drawn on. The surface
@@ -352,7 +353,7 @@ class Surface {
public:
enum class Type { Window, Pad };
- Surface(Surface::Type type) : m_type(type), m_window(nullptr) {}
+ Surface(Surface::Type type) : m_type(type) {}
WINDOW *get() { return m_window; }
@@ -495,7 +496,7 @@ public:
if (use_blue_background)
::wattron(m_window, COLOR_PAIR(WhiteOnBlue));
while (!string.empty()) {
- size_t esc_pos = string.find('\x1b');
+ size_t esc_pos = string.find(ANSI_ESC_START);
if (esc_pos == StringRef::npos) {
string = string.substr(skip_first_count);
if (!string.empty()) {
@@ -517,36 +518,36 @@ public:
string = string.drop_front(esc_pos);
}
}
- bool consumed = string.consume_front("\x1b");
+ bool consumed = string.consume_front(ANSI_ESC_START);
assert(consumed);
UNUSED_IF_ASSERT_DISABLED(consumed);
// This is written to match our Highlighter classes, which seem to
// generate only foreground color escape sequences. If necessary, this
// will need to be extended.
- if (!string.consume_front("[")) {
- llvm::errs() << "Missing '[' in color escape sequence.\n";
- continue;
- }
- // Only 8 basic foreground colors and reset, our Highlighter doesn't use
- // anything else.
+ // Only 8 basic foreground colors, underline and reset, our Highlighter
+ // doesn't use anything else.
int value;
if (!!string.consumeInteger(10, value) || // Returns false on success.
- !(value == 0 || (value >= 30 && value <= 37))) {
+ !(value == 0 || value == ANSI_CTRL_UNDERLINE ||
+ (value >= ANSI_FG_COLOR_BLACK && value <= ANSI_FG_COLOR_WHITE))) {
llvm::errs() << "No valid color code in color escape sequence.\n";
continue;
}
- if (!string.consume_front("m")) {
- llvm::errs() << "Missing 'm' in color escape sequence.\n";
+ if (!string.consume_front(ANSI_ESC_END)) {
+ llvm::errs() << "Missing '" << ANSI_ESC_END
+ << "' in color escape sequence.\n";
continue;
}
if (value == 0) { // Reset.
wattr_set(m_window, saved_attr, saved_pair, nullptr);
if (use_blue_background)
::wattron(m_window, COLOR_PAIR(WhiteOnBlue));
+ } else if (value == ANSI_CTRL_UNDERLINE) {
+ ::wattron(m_window, A_UNDERLINE);
} else {
// Mapped directly to first 16 color pairs (black/blue background).
- ::wattron(m_window,
- COLOR_PAIR(value - 30 + 1 + (use_blue_background ? 8 : 0)));
+ ::wattron(m_window, COLOR_PAIR(value - ANSI_FG_COLOR_BLACK + 1 +
+ (use_blue_background ? 8 : 0)));
}
}
wattr_set(m_window, saved_attr, saved_pair, nullptr);
@@ -555,7 +556,7 @@ public:
protected:
Type m_type;
- WINDOW *m_window;
+ WINDOW *m_window = nullptr;
};
class Pad : public Surface {
@@ -1076,8 +1077,7 @@ typedef std::unique_ptr<FieldDelegate> FieldDelegateUP;
class TextFieldDelegate : public FieldDelegate {
public:
TextFieldDelegate(const char *label, const char *content, bool required)
- : m_label(label), m_required(required), m_cursor_position(0),
- m_first_visibile_char(0) {
+ : m_label(label), m_required(required) {
if (content)
m_content = content;
}
@@ -1325,9 +1325,9 @@ protected:
std::string m_content;
// The cursor position in the content string itself. Can be in the range
// [0, GetContentLength()].
- int m_cursor_position;
+ int m_cursor_position = 0;
// The index of the first visible character in the content.
- int m_first_visibile_char;
+ int m_first_visibile_char = 0;
// Optional error message. If empty, field is considered to have no error.
std::string m_error;
};
@@ -1515,7 +1515,7 @@ public:
ChoicesFieldDelegate(const char *label, int number_of_visible_choices,
std::vector<std::string> choices)
: m_label(label), m_number_of_visible_choices(number_of_visible_choices),
- m_choices(choices), m_choice(0), m_first_visibile_choice(0) {}
+ m_choices(choices) {}
// Choices fields are drawn as titles boxses of a number of visible choices.
// The rest of the choices become visible as the user scroll. The selected
@@ -1609,7 +1609,7 @@ public:
// Returns the index of the choice.
int GetChoice() { return m_choice; }
- void SetChoice(const std::string &choice) {
+ void SetChoice(llvm::StringRef choice) {
for (int i = 0; i < GetNumberOfChoices(); i++) {
if (choice == m_choices[i]) {
m_choice = i;
@@ -1623,9 +1623,9 @@ protected:
int m_number_of_visible_choices;
std::vector<std::string> m_choices;
// The index of the selected choice.
- int m_choice;
+ int m_choice = 0;
// The index of the first visible choice in the field.
- int m_first_visibile_choice;
+ int m_first_visibile_choice = 0;
};
class PlatformPluginFieldDelegate : public ChoicesFieldDelegate {
@@ -1634,7 +1634,7 @@ public:
: ChoicesFieldDelegate("Platform Plugin", 3, GetPossiblePluginNames()) {
PlatformSP platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
if (platform_sp)
- SetChoice(platform_sp->GetName().AsCString());
+ SetChoice(platform_sp->GetPluginName());
}
std::vector<std::string> GetPossiblePluginNames() {
@@ -1707,7 +1707,7 @@ public:
template <class T> class ListFieldDelegate : public FieldDelegate {
public:
ListFieldDelegate(const char *label, T default_field)
- : m_label(label), m_default_field(default_field), m_selection_index(0),
+ : m_label(label), m_default_field(default_field),
m_selection_type(SelectionType::NewButton) {}
// Signify which element is selected. If a field or a remove button is
@@ -2011,7 +2011,7 @@ protected:
// created though a copy.
T m_default_field;
std::vector<T> m_fields;
- int m_selection_index;
+ int m_selection_index = 0;
// See SelectionType class enum.
SelectionType m_selection_type;
};
@@ -2283,7 +2283,7 @@ protected:
class FormDelegate {
public:
- FormDelegate() {}
+ FormDelegate() = default;
virtual ~FormDelegate() = default;
@@ -2465,9 +2465,7 @@ typedef std::shared_ptr<FormDelegate> FormDelegateSP;
class FormWindowDelegate : public WindowDelegate {
public:
- FormWindowDelegate(FormDelegateSP &delegate_sp)
- : m_delegate_sp(delegate_sp), m_selection_index(0),
- m_first_visible_line(0) {
+ FormWindowDelegate(FormDelegateSP &delegate_sp) : m_delegate_sp(delegate_sp) {
assert(m_delegate_sp->GetNumberOfActions() > 0);
if (m_delegate_sp->GetNumberOfFields() > 0)
m_selection_type = SelectionType::Field;
@@ -2856,11 +2854,11 @@ public:
protected:
FormDelegateSP m_delegate_sp;
// The index of the currently selected SelectionType.
- int m_selection_index;
+ int m_selection_index = 0;
// See SelectionType class enum.
SelectionType m_selection_type;
// The first visible line from the pad.
- int m_first_visible_line;
+ int m_first_visible_line = 0;
};
///////////////////////////
@@ -3647,7 +3645,7 @@ protected:
class SearcherDelegate {
public:
- SearcherDelegate() {}
+ SearcherDelegate() = default;
virtual ~SearcherDelegate() = default;
@@ -3670,8 +3668,7 @@ typedef std::shared_ptr<SearcherDelegate> SearcherDelegateSP;
class SearcherWindowDelegate : public WindowDelegate {
public:
SearcherWindowDelegate(SearcherDelegateSP &delegate_sp)
- : m_delegate_sp(delegate_sp), m_text_field("Search", "", false),
- m_selected_match(0), m_first_visible_match(0) {
+ : m_delegate_sp(delegate_sp), m_text_field("Search", "", false) {
;
}
@@ -3811,9 +3808,9 @@ protected:
SearcherDelegateSP m_delegate_sp;
TextFieldDelegate m_text_field;
// The index of the currently selected match.
- int m_selected_match;
+ int m_selected_match = 0;
// The index of the first visible match.
- int m_first_visible_match;
+ int m_first_visible_match = 0;
};
//////////////////////////////
@@ -4266,8 +4263,7 @@ HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) {
class Application {
public:
- Application(FILE *in, FILE *out)
- : m_window_sp(), m_screen(nullptr), m_in(in), m_out(out) {}
+ Application(FILE *in, FILE *out) : m_window_sp(), m_in(in), m_out(out) {}
~Application() {
m_window_delegates.clear();
@@ -4475,7 +4471,7 @@ public:
protected:
WindowSP m_window_sp;
WindowDelegates m_window_delegates;
- SCREEN *m_screen;
+ SCREEN *m_screen = nullptr;
FILE *m_in;
FILE *m_out;
bool m_update_screen = false;
@@ -4541,7 +4537,8 @@ struct Row {
if (parent)
parent->DrawTreeForChild(window, this, 0);
- if (might_have_children) {
+ if (might_have_children &&
+ (!calculated_children || !GetChildren().empty())) {
// It we can get UTF8 characters to work we should try to use the
// "symbol" UTF8 string below
// const char *symbol = "";
@@ -4619,9 +4616,8 @@ typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;
class TreeItem {
public:
TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children)
- : m_parent(parent), m_delegate(delegate), m_user_data(nullptr),
- m_identifier(0), m_row_idx(-1), m_children(),
- m_might_have_children(might_have_children), m_is_expanded(false) {
+ : m_parent(parent), m_delegate(delegate), m_children(),
+ m_might_have_children(might_have_children) {
if (m_parent == nullptr)
m_is_expanded = m_delegate.TreeDelegateExpandRootByDefault();
}
@@ -4816,23 +4812,21 @@ public:
protected:
TreeItem *m_parent;
TreeDelegate &m_delegate;
- void *m_user_data;
- uint64_t m_identifier;
+ void *m_user_data = nullptr;
+ uint64_t m_identifier = 0;
std::string m_text;
- int m_row_idx; // Zero based visible row index, -1 if not visible or for the
- // root item
+ int m_row_idx = -1; // Zero based visible row index, -1 if not visible or for
+ // the root item
std::vector<TreeItem> m_children;
bool m_might_have_children;
- bool m_is_expanded;
+ bool m_is_expanded = false;
};
class TreeWindowDelegate : public WindowDelegate {
public:
TreeWindowDelegate(Debugger &debugger, const TreeDelegateSP &delegate_sp)
: m_debugger(debugger), m_delegate_sp(delegate_sp),
- m_root(nullptr, *delegate_sp, true), m_selected_item(nullptr),
- m_num_rows(0), m_selected_row_idx(0), m_first_visible_row(0),
- m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {}
+ m_root(nullptr, *delegate_sp, true) {}
int NumVisibleRows() const { return m_max_y - m_min_y; }
@@ -4992,14 +4986,14 @@ protected:
Debugger &m_debugger;
TreeDelegateSP m_delegate_sp;
TreeItem m_root;
- TreeItem *m_selected_item;
- int m_num_rows;
- int m_selected_row_idx;
- int m_first_visible_row;
- int m_min_x;
- int m_min_y;
- int m_max_x;
- int m_max_y;
+ TreeItem *m_selected_item = nullptr;
+ int m_num_rows = 0;
+ int m_selected_row_idx = 0;
+ int m_first_visible_row = 0;
+ int m_min_x = 0;
+ int m_min_y = 0;
+ int m_max_x = 0;
+ int m_max_y = 0;
};
// A tree delegate that just draws the text member of the tree item, it doesn't
@@ -5023,8 +5017,7 @@ class FrameTreeDelegate : public TreeDelegate {
public:
FrameTreeDelegate() : TreeDelegate() {
FormatEntity::Parse(
- "frame #${frame.index}: {${function.name}${function.pc-offset}}}",
- m_format);
+ "#${frame.index}: {${function.name}${function.pc-offset}}}", m_format);
}
~FrameTreeDelegate() override = default;
@@ -5071,8 +5064,7 @@ protected:
class ThreadTreeDelegate : public TreeDelegate {
public:
ThreadTreeDelegate(Debugger &debugger)
- : TreeDelegate(), m_debugger(debugger), m_tid(LLDB_INVALID_THREAD_ID),
- m_stop_id(UINT32_MAX) {
+ : TreeDelegate(), m_debugger(debugger) {
FormatEntity::Parse("thread #${thread.index}: tid = ${thread.id}{, stop "
"reason = ${thread.stop-reason}}",
m_format);
@@ -5161,16 +5153,15 @@ public:
protected:
Debugger &m_debugger;
std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp;
- lldb::user_id_t m_tid;
- uint32_t m_stop_id;
+ lldb::user_id_t m_tid = LLDB_INVALID_THREAD_ID;
+ uint32_t m_stop_id = UINT32_MAX;
FormatEntity::Entry m_format;
};
class ThreadsTreeDelegate : public TreeDelegate {
public:
ThreadsTreeDelegate(Debugger &debugger)
- : TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger),
- m_stop_id(UINT32_MAX), m_update_selection(false) {
+ : TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger) {
FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
m_format);
}
@@ -5280,8 +5271,8 @@ public:
protected:
std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
Debugger &m_debugger;
- uint32_t m_stop_id;
- bool m_update_selection;
+ uint32_t m_stop_id = UINT32_MAX;
+ bool m_update_selection = false;
FormatEntity::Entry m_format;
};
@@ -5523,9 +5514,7 @@ class ValueObjectListDelegate : public WindowDelegate {
public:
ValueObjectListDelegate() : m_rows() {}
- ValueObjectListDelegate(ValueObjectList &valobj_list)
- : m_rows(), m_selected_row(nullptr), m_selected_row_idx(0),
- m_first_visible_row(0), m_num_rows(0), m_max_x(0), m_max_y(0) {
+ ValueObjectListDelegate(ValueObjectList &valobj_list) : m_rows() {
SetValues(valobj_list);
}
@@ -5836,9 +5825,11 @@ protected:
++m_num_rows;
}
- auto &children = row.GetChildren();
- if (row.expanded && !children.empty()) {
- DisplayRows(window, children, options);
+ if (row.expanded) {
+ auto &children = row.GetChildren();
+ if (!children.empty()) {
+ DisplayRows(window, children, options);
+ }
}
}
}
@@ -5859,11 +5850,13 @@ protected:
return &row;
else {
--row_index;
- auto &children = row.GetChildren();
- if (row.expanded && !children.empty()) {
- Row *result = GetRowForRowIndexImpl(children, row_index);
- if (result)
- return result;
+ if (row.expanded) {
+ auto &children = row.GetChildren();
+ if (!children.empty()) {
+ Row *result = GetRowForRowIndexImpl(children, row_index);
+ if (result)
+ return result;
+ }
}
}
}
@@ -5882,8 +5875,7 @@ protected:
class FrameVariablesWindowDelegate : public ValueObjectListDelegate {
public:
FrameVariablesWindowDelegate(Debugger &debugger)
- : ValueObjectListDelegate(), m_debugger(debugger),
- m_frame_block(nullptr) {}
+ : ValueObjectListDelegate(), m_debugger(debugger) {}
~FrameVariablesWindowDelegate() override = default;
@@ -5944,7 +5936,7 @@ public:
protected:
Debugger &m_debugger;
- Block *m_frame_block;
+ Block *m_frame_block = nullptr;
};
class RegistersWindowDelegate : public ValueObjectListDelegate {
@@ -6198,7 +6190,7 @@ static const char *CursesKeyToCString(int ch) {
HelpDialogDelegate::HelpDialogDelegate(const char *text,
KeyHelp *key_help_array)
- : m_text(), m_first_visible_line(0) {
+ : m_text() {
if (text && text[0]) {
m_text.SplitIntoLines(text);
m_text.AppendString("");
@@ -6415,8 +6407,11 @@ public:
if (exe_ctx.HasThreadScope()) {
Process *process = exe_ctx.GetProcessPtr();
if (process && process->IsAlive() &&
- StateIsStoppedState(process->GetState(), true))
- exe_ctx.GetThreadRef().StepOut();
+ StateIsStoppedState(process->GetState(), true)) {
+ Thread *thread = exe_ctx.GetThreadPtr();
+ uint32_t frame_idx = thread->GetSelectedFrameIndex();
+ exe_ctx.GetThreadRef().StepOut(frame_idx);
+ }
}
}
return MenuActionResult::Handled;
@@ -6762,11 +6757,7 @@ class SourceFileWindowDelegate : public WindowDelegate {
public:
SourceFileWindowDelegate(Debugger &debugger)
: WindowDelegate(), m_debugger(debugger), m_sc(), m_file_sp(),
- m_disassembly_scope(nullptr), m_disassembly_sp(), m_disassembly_range(),
- m_title(), m_tid(LLDB_INVALID_THREAD_ID), m_line_width(4),
- m_selected_line(0), m_pc_line(0), m_stop_id(0), m_frame_idx(UINT32_MAX),
- m_first_visible_line(0), m_first_visible_column(0), m_min_x(0),
- m_min_y(0), m_max_x(0), m_max_y(0) {}
+ m_disassembly_sp(), m_disassembly_range(), m_title() {}
~SourceFileWindowDelegate() override = default;
@@ -6994,9 +6985,6 @@ public:
}
}
- const attr_t selected_highlight_attr = A_REVERSE;
- const attr_t pc_highlight_attr = COLOR_PAIR(BlackOnBlue);
-
for (size_t i = 0; i < num_visible_lines; ++i) {
const uint32_t curr_line = m_first_visible_line + i;
if (curr_line < num_source_lines) {
@@ -7004,14 +6992,13 @@ public:
window.MoveCursor(1, line_y);
const bool is_pc_line = curr_line == m_pc_line;
const bool line_is_selected = m_selected_line == curr_line;
- // Highlight the line as the PC line first, then if the selected
- // line isn't the same as the PC line, highlight it differently
+ // Highlight the line as the PC line first (done by passing
+ // argument to OutputColoredStringTruncated()), then if the selected
+ // line isn't the same as the PC line, highlight it differently.
attr_t highlight_attr = 0;
attr_t bp_attr = 0;
- if (is_pc_line)
- highlight_attr = pc_highlight_attr;
- else if (line_is_selected)
- highlight_attr = selected_highlight_attr;
+ if (line_is_selected && !is_pc_line)
+ highlight_attr = A_REVERSE;
if (bp_lines.find(curr_line + 1) != bp_lines.end())
bp_attr = COLOR_PAIR(BlackOnWhite);
@@ -7035,14 +7022,19 @@ public:
window.AttributeOn(highlight_attr);
StreamString lineStream;
- m_file_sp->DisplaySourceLines(curr_line + 1, {}, 0, 0, &lineStream);
+
+ llvm::Optional<size_t> column;
+ if (is_pc_line && m_sc.line_entry.IsValid() && m_sc.line_entry.column)
+ column = m_sc.line_entry.column - 1;
+ m_file_sp->DisplaySourceLines(curr_line + 1, column, 0, 0,
+ &lineStream);
StringRef line = lineStream.GetString();
if (line.endswith("\n"))
line = line.drop_back();
bool wasWritten = window.OutputColoredStringTruncated(
- 1, line, m_first_visible_column, line_is_selected);
- if (line_is_selected && !wasWritten) {
- // Draw an empty space to show the selected line if empty,
+ 1, line, m_first_visible_column, is_pc_line);
+ if (!wasWritten && (line_is_selected || is_pc_line)) {
+ // Draw an empty space to show the selected/PC line if empty,
// or draw '<' if nothing is visible because of scrolling too much
// to the right.
window.PutCStringTruncated(
@@ -7377,7 +7369,9 @@ public:
m_debugger.GetCommandInterpreter().GetExecutionContext();
if (exe_ctx.HasThreadScope() &&
StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
- exe_ctx.GetThreadRef().StepOut();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ uint32_t frame_idx = thread->GetSelectedFrameIndex();
+ exe_ctx.GetThreadRef().StepOut(frame_idx);
}
}
return eKeyHandled;
@@ -7524,22 +7518,22 @@ protected:
Debugger &m_debugger;
SymbolContext m_sc;
SourceManager::FileSP m_file_sp;
- SymbolContextScope *m_disassembly_scope;
+ SymbolContextScope *m_disassembly_scope = nullptr;
lldb::DisassemblerSP m_disassembly_sp;
AddressRange m_disassembly_range;
StreamString m_title;
- lldb::user_id_t m_tid;
- int m_line_width;
- uint32_t m_selected_line; // The selected line
- uint32_t m_pc_line; // The line with the PC
- uint32_t m_stop_id;
- uint32_t m_frame_idx;
- int m_first_visible_line;
- int m_first_visible_column;
- int m_min_x;
- int m_min_y;
- int m_max_x;
- int m_max_y;
+ lldb::user_id_t m_tid = LLDB_INVALID_THREAD_ID;
+ int m_line_width = 4;
+ uint32_t m_selected_line = 0; // The selected line
+ uint32_t m_pc_line = 0; // The line with the PC
+ uint32_t m_stop_id = 0;
+ uint32_t m_frame_idx = UINT32_MAX;
+ int m_first_visible_line = 0;
+ int m_first_visible_column = 0;
+ int m_min_x = 0;
+ int m_min_y = 0;
+ int m_max_x = 0;
+ int m_max_y = 0;
};
DisplayOptions ValueObjectListDelegate::g_options = {true};
@@ -7682,14 +7676,6 @@ void IOHandlerCursesGUI::Activate() {
status_window_sp->SetDelegate(
WindowDelegateSP(new StatusBarWindowDelegate(m_debugger)));
- // Show the main help window once the first time the curses GUI is
- // launched
- static bool g_showed_help = false;
- if (!g_showed_help) {
- g_showed_help = true;
- main_window_sp->CreateHelpSubwindow();
- }
-
// All colors with black background.
init_pair(1, COLOR_BLACK, COLOR_BLACK);
init_pair(2, COLOR_RED, COLOR_BLACK);
@@ -7729,7 +7715,9 @@ IOHandlerCursesGUI::~IOHandlerCursesGUI() = default;
void IOHandlerCursesGUI::Cancel() {}
-bool IOHandlerCursesGUI::Interrupt() { return false; }
+bool IOHandlerCursesGUI::Interrupt() {
+ return m_debugger.GetCommandInterpreter().IOHandlerInterrupt(*this);
+}
void IOHandlerCursesGUI::GotEOF() {}