summaryrefslogtreecommitdiff
path: root/source/Core/IOHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Core/IOHandler.cpp')
-rw-r--r--source/Core/IOHandler.cpp148
1 files changed, 79 insertions, 69 deletions
diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp
index 5c0eea5ea1a3..b30308490cca 100644
--- a/source/Core/IOHandler.cpp
+++ b/source/Core/IOHandler.cpp
@@ -1,9 +1,8 @@
//===-- IOHandler.cpp -------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -77,16 +76,19 @@ IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type)
StreamFileSP(), // Adopt STDIN from top input reader
StreamFileSP(), // Adopt STDOUT from top input reader
StreamFileSP(), // Adopt STDERR from top input reader
- 0) // Flags
-{}
+ 0, // Flags
+ nullptr // Shadow file recorder
+ ) {}
IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type,
const lldb::StreamFileSP &input_sp,
const lldb::StreamFileSP &output_sp,
- const lldb::StreamFileSP &error_sp, uint32_t flags)
+ const lldb::StreamFileSP &error_sp, uint32_t flags,
+ repro::DataRecorder *data_recorder)
: m_debugger(debugger), m_input_sp(input_sp), m_output_sp(output_sp),
- m_error_sp(error_sp), m_popped(false), m_flags(flags), m_type(type),
- m_user_data(nullptr), m_done(false), m_active(false) {
+ m_error_sp(error_sp), m_data_recorder(data_recorder), m_popped(false),
+ m_flags(flags), m_type(type), m_user_data(nullptr), m_done(false),
+ m_active(false) {
// If any files are not specified, then adopt them from the top input reader.
if (!m_input_sp || !m_output_sp || !m_error_sp)
debugger.AdoptTopIOHandlerFilesIfInvalid(m_input_sp, m_output_sp,
@@ -154,7 +156,7 @@ IOHandlerConfirm::IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt,
llvm::StringRef(), // No continuation prompt
false, // Multi-line
false, // Don't colorize the prompt (i.e. the confirm message.)
- 0, *this),
+ 0, *this, nullptr),
m_default_response(default_response), m_user_response(default_response) {
StreamString prompt_stream;
prompt_stream.PutCString(prompt);
@@ -265,7 +267,7 @@ IOHandlerEditline::IOHandlerEditline(
const char *editline_name, // Used for saving history files
llvm::StringRef prompt, llvm::StringRef continuation_prompt,
bool multi_line, bool color_prompts, uint32_t line_number_start,
- IOHandlerDelegate &delegate)
+ IOHandlerDelegate &delegate, repro::DataRecorder *data_recorder)
: IOHandlerEditline(debugger, type,
StreamFileSP(), // Inherit input from top input reader
StreamFileSP(), // Inherit output from top input reader
@@ -273,7 +275,7 @@ IOHandlerEditline::IOHandlerEditline(
0, // Flags
editline_name, // Used for saving history files
prompt, continuation_prompt, multi_line, color_prompts,
- line_number_start, delegate) {}
+ line_number_start, delegate, data_recorder) {}
IOHandlerEditline::IOHandlerEditline(
Debugger &debugger, IOHandler::Type type,
@@ -282,10 +284,11 @@ IOHandlerEditline::IOHandlerEditline(
const char *editline_name, // Used for saving history files
llvm::StringRef prompt, llvm::StringRef continuation_prompt,
bool multi_line, bool color_prompts, uint32_t line_number_start,
- IOHandlerDelegate &delegate)
- : IOHandler(debugger, type, input_sp, output_sp, error_sp, flags),
+ IOHandlerDelegate &delegate, repro::DataRecorder *data_recorder)
+ : IOHandler(debugger, type, input_sp, output_sp, error_sp, flags,
+ data_recorder),
#ifndef LLDB_DISABLE_LIBEDIT
- m_editline_ap(),
+ m_editline_up(),
#endif
m_delegate(delegate), m_prompt(), m_continuation_prompt(),
m_current_lines_ptr(nullptr), m_base_line_number(line_number_start),
@@ -300,17 +303,17 @@ IOHandlerEditline::IOHandlerEditline(
use_editline = m_input_sp->GetFile().GetIsRealTerminal();
if (use_editline) {
- m_editline_ap.reset(new Editline(editline_name, GetInputFILE(),
+ m_editline_up.reset(new Editline(editline_name, GetInputFILE(),
GetOutputFILE(), GetErrorFILE(),
m_color_prompts));
- m_editline_ap->SetIsInputCompleteCallback(IsInputCompleteCallback, this);
- m_editline_ap->SetAutoCompleteCallback(AutoCompleteCallback, this);
+ m_editline_up->SetIsInputCompleteCallback(IsInputCompleteCallback, this);
+ m_editline_up->SetAutoCompleteCallback(AutoCompleteCallback, this);
// See if the delegate supports fixing indentation
const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters();
if (indent_chars) {
// The delegate does support indentation, hook it up so when any
// indentation character is typed, the delegate gets a chance to fix it
- m_editline_ap->SetFixIndentationCallback(FixIndentationCallback, this,
+ m_editline_up->SetFixIndentationCallback(FixIndentationCallback, this,
indent_chars);
}
}
@@ -322,13 +325,13 @@ IOHandlerEditline::IOHandlerEditline(
IOHandlerEditline::~IOHandlerEditline() {
#ifndef LLDB_DISABLE_LIBEDIT
- m_editline_ap.reset();
+ m_editline_up.reset();
#endif
}
void IOHandlerEditline::Activate() {
IOHandler::Activate();
- m_delegate.IOHandlerActivated(*this);
+ m_delegate.IOHandlerActivated(*this, GetIsInteractive());
}
void IOHandlerEditline::Deactivate() {
@@ -338,8 +341,11 @@ void IOHandlerEditline::Deactivate() {
bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap) {
- return m_editline_ap->GetLine(line, interrupted);
+ if (m_editline_up) {
+ bool b = m_editline_up->GetLine(line, interrupted);
+ if (m_data_recorder)
+ m_data_recorder->Record(line, true);
+ return b;
} else {
#endif
line.clear();
@@ -368,7 +374,18 @@ bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
bool got_line = false;
m_editing = true;
while (!done) {
+#ifdef _WIN32
+ // ReadFile on Windows is supposed to set ERROR_OPERATION_ABORTED
+ // according to the docs on MSDN. However, this has evidently been a
+ // known bug since Windows 8. Therefore, we can't detect if a signal
+ // interrupted in the fgets. So pressing ctrl-c causes the repl to end
+ // and the process to exit. A temporary workaround is just to attempt to
+ // fgets twice until this bug is fixed.
+ if (fgets(buffer, sizeof(buffer), in) == nullptr &&
+ fgets(buffer, sizeof(buffer), in) == nullptr) {
+#else
if (fgets(buffer, sizeof(buffer), in) == nullptr) {
+#endif
const int saved_errno = errno;
if (feof(in))
done = true;
@@ -395,6 +412,8 @@ bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) {
}
}
m_editing = false;
+ if (m_data_recorder && got_line)
+ m_data_recorder->Record(line, true);
// We might have gotten a newline on a line by itself make sure to return
// true in this case.
return got_line;
@@ -441,8 +460,8 @@ int IOHandlerEditline::AutoCompleteCallback(
const char *IOHandlerEditline::GetPrompt() {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap) {
- return m_editline_ap->GetPrompt();
+ if (m_editline_up) {
+ return m_editline_up->GetPrompt();
} else {
#endif
if (m_prompt.empty())
@@ -457,8 +476,8 @@ bool IOHandlerEditline::SetPrompt(llvm::StringRef prompt) {
m_prompt = prompt;
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str());
+ if (m_editline_up)
+ m_editline_up->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str());
#endif
return true;
}
@@ -472,8 +491,8 @@ void IOHandlerEditline::SetContinuationPrompt(llvm::StringRef prompt) {
m_continuation_prompt = prompt;
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->SetContinuationPrompt(m_continuation_prompt.empty()
+ if (m_editline_up)
+ m_editline_up->SetContinuationPrompt(m_continuation_prompt.empty()
? nullptr
: m_continuation_prompt.c_str());
#endif
@@ -485,8 +504,8 @@ void IOHandlerEditline::SetBaseLineNumber(uint32_t line) {
uint32_t IOHandlerEditline::GetCurrentLineIndex() const {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- return m_editline_ap->GetCurrentLine();
+ if (m_editline_up)
+ return m_editline_up->GetCurrentLine();
#endif
return m_curr_line_idx;
}
@@ -496,8 +515,8 @@ bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) {
bool success = false;
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap) {
- return m_editline_ap->GetLines(m_base_line_number, lines, interrupted);
+ if (m_editline_up) {
+ return m_editline_up->GetLines(m_base_line_number, lines, interrupted);
} else {
#endif
bool done = false;
@@ -565,8 +584,8 @@ void IOHandlerEditline::Run() {
void IOHandlerEditline::Cancel() {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->Cancel();
+ if (m_editline_up)
+ m_editline_up->Cancel();
#endif
}
@@ -576,23 +595,23 @@ bool IOHandlerEditline::Interrupt() {
return true;
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- return m_editline_ap->Interrupt();
+ if (m_editline_up)
+ return m_editline_up->Interrupt();
#endif
return false;
}
void IOHandlerEditline::GotEOF() {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->Interrupt();
+ if (m_editline_up)
+ m_editline_up->Interrupt();
#endif
}
void IOHandlerEditline::PrintAsync(Stream *stream, const char *s, size_t len) {
#ifndef LLDB_DISABLE_LIBEDIT
- if (m_editline_ap)
- m_editline_ap->PrintAsync(stream, s, len);
+ if (m_editline_up)
+ m_editline_up->PrintAsync(stream, s, len);
else
#endif
{
@@ -994,20 +1013,15 @@ public:
WindowSP CreateSubWindow(const char *name, const Rect &bounds,
bool make_active) {
- WindowSP subwindow_sp;
- if (m_window) {
- subwindow_sp.reset(new Window(
- name, ::subwin(m_window, bounds.size.height, bounds.size.width,
- bounds.origin.y, bounds.origin.x),
- true));
- subwindow_sp->m_is_subwin = true;
- } else {
- subwindow_sp.reset(
- new Window(name, ::newwin(bounds.size.height, bounds.size.width,
- bounds.origin.y, bounds.origin.x),
- true));
- subwindow_sp->m_is_subwin = false;
- }
+ auto get_window = [this, &bounds]() {
+ return m_window
+ ? ::subwin(m_window, bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x)
+ : ::newwin(bounds.size.height, bounds.size.width,
+ bounds.origin.y, bounds.origin.x);
+ };
+ WindowSP subwindow_sp = std::make_shared<Window>(name, get_window(), true);
+ subwindow_sp->m_is_subwin = subwindow_sp.operator bool();
subwindow_sp->m_parent = this;
if (make_active) {
m_prev_active_window_idx = m_curr_active_window_idx;
@@ -1075,9 +1089,7 @@ public:
operator WINDOW *() { return m_window; }
- //----------------------------------------------------------------------
// Window drawing utilities
- //----------------------------------------------------------------------
void DrawTitleBox(const char *title, const char *bottom_message = nullptr) {
attr_t attr = 0;
if (IsActive())
@@ -1128,10 +1140,10 @@ public:
const char *text = m_delegate_sp->WindowDelegateGetHelpText();
KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp();
if ((text && text[0]) || key_help) {
- std::unique_ptr<HelpDialogDelegate> help_delegate_ap(
+ std::unique_ptr<HelpDialogDelegate> help_delegate_up(
new HelpDialogDelegate(text, key_help));
- const size_t num_lines = help_delegate_ap->GetNumLines();
- const size_t max_length = help_delegate_ap->GetMaxLineLength();
+ const size_t num_lines = help_delegate_up->GetNumLines();
+ const size_t max_length = help_delegate_up->GetMaxLineLength();
Rect bounds = GetBounds();
bounds.Inset(1, 1);
if (max_length + 4 < static_cast<size_t>(bounds.size.width)) {
@@ -1162,7 +1174,7 @@ public:
else
help_window_sp = CreateSubWindow("Help", bounds, true);
help_window_sp->SetDelegate(
- WindowDelegateSP(help_delegate_ap.release()));
+ WindowDelegateSP(help_delegate_up.release()));
return true;
}
}
@@ -1882,7 +1894,7 @@ public:
WindowSP &GetMainWindow() {
if (!m_window_sp)
- m_window_sp.reset(new Window("main", stdscr, false));
+ m_window_sp = std::make_shared<Window>("main", stdscr, false);
return m_window_sp;
}
@@ -2509,7 +2521,7 @@ public:
return; // Children are already up to date
if (!m_frame_delegate_sp) {
// Always expand the thread item the first time we show it
- m_frame_delegate_sp.reset(new FrameTreeDelegate());
+ m_frame_delegate_sp = std::make_shared<FrameTreeDelegate>();
}
m_stop_id = process_sp->GetStopID();
@@ -2601,7 +2613,8 @@ public:
if (!m_thread_delegate_sp) {
// Always expand the thread item the first time we show it
// item.Expand();
- m_thread_delegate_sp.reset(new ThreadTreeDelegate(m_debugger));
+ m_thread_delegate_sp =
+ std::make_shared<ThreadTreeDelegate>(m_debugger);
}
TreeItem t(&item, *m_thread_delegate_sp, false);
@@ -3934,12 +3947,10 @@ public:
m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file);
if (m_file_sp) {
const size_t num_lines = m_file_sp->GetNumLines();
- int m_line_width = 1;
+ m_line_width = 1;
for (size_t n = num_lines; n >= 10; n = n / 10)
++m_line_width;
- snprintf(m_line_format, sizeof(m_line_format), " %%%iu ",
- m_line_width);
if (num_lines < num_visible_lines ||
m_selected_line < num_visible_lines)
m_first_visible_line = 0;
@@ -4056,7 +4067,7 @@ public:
if (bp_attr)
window.AttributeOn(bp_attr);
- window.Printf(m_line_format, curr_line + 1);
+ window.Printf(" %*u ", m_line_width, curr_line + 1);
if (bp_attr)
window.AttributeOff(bp_attr);
@@ -4482,7 +4493,6 @@ protected:
AddressRange m_disassembly_range;
StreamString m_title;
lldb::user_id_t m_tid;
- char m_line_format[8];
int m_line_width;
uint32_t m_selected_line; // The selected line
uint32_t m_pc_line; // The line with the PC