lawrence_danna created this revision. lawrence_danna added reviewers: JDevlieghere, jasonmolenda, labath, lanza. Herald added a project: LLDB.
IOHandler needs to read lines of input from a lldb::File. The way it currently does this using, FILE*, which is something we want to avoid now. I'd prefer to just replace the FILE* code with calls to File::Read, but it contains an awkward and delicate workaround specific to ctrl-C handling on windows, and it's not clear if or how that workaround would translate to lldb::File. So in this patch, we use use the FILE* if it's available, and only fall back on File::Read if that's the only option. I think this is a reasonable approach here for two reasons. First is that interactive terminal support is the one area where FILE* can't be avoided. We need them for libedit and curses anyway, and using them here as well is consistent with that pattern. The second reason is that the comments express a hope that the underlying windows bug that's being worked around will be fixed one day, so hopefully when that happens, that whole path can be deleted. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D68622 Files: lldb/include/lldb/Core/IOHandler.h lldb/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py lldb/source/Core/IOHandler.cpp
Index: lldb/source/Core/IOHandler.cpp =================================================================== --- lldb/source/Core/IOHandler.cpp +++ lldb/source/Core/IOHandler.cpp @@ -316,27 +316,71 @@ #endif line.clear(); + if (GetIsInteractive()) { + const char *prompt = nullptr; + + if (m_multi_line && m_curr_line_idx > 0) + prompt = GetContinuationPrompt(); + + if (prompt == nullptr) + prompt = GetPrompt(); + + if (prompt && prompt[0]) { + if (m_output_sp) { + m_output_sp->Printf("%s", prompt); + m_output_sp->Flush(); + } + } + } + FILE *in = GetInputFILE(); - if (in) { - if (GetIsInteractive()) { - const char *prompt = nullptr; + char buffer[256]; + bool done = false; + bool got_line = false; - if (m_multi_line && m_curr_line_idx > 0) - prompt = GetContinuationPrompt(); + if (!in && m_input_sp) { + // there is no FILE*, fall back on just reading bytes from the stream. - if (prompt == nullptr) - prompt = GetPrompt(); + size_t pos = m_line_buffer.find('\n'); + if (pos != std::string::npos) { + size_t end = pos; + while (end > 0 && + (m_line_buffer[end] == '\n' || m_line_buffer[end] == '\r')) + end--; + line = m_line_buffer.substr(0, end + 1); + m_line_buffer = m_line_buffer.substr(pos + 1); + done = true; + got_line = true; + } - if (prompt && prompt[0]) { - if (m_output_sp) { - m_output_sp->Printf("%s", prompt); - m_output_sp->Flush(); + while (!done) { + size_t bytes_read = sizeof(buffer); + m_input_sp->Read((void *)buffer, bytes_read); + if (bytes_read) { + auto bytes = llvm::StringRef(buffer, bytes_read); + size_t pos = bytes.find('\n'); + if (pos != llvm::StringRef::npos) { + size_t end = pos; + while (end > 0 && (bytes[end] == '\n' || bytes[end] == '\r')) + end--; + line = m_line_buffer; + line.append(bytes.substr(0, end + 1)); + m_line_buffer = bytes.substr(pos + 1); + done = true; + got_line = true; + } else { + m_line_buffer.append(bytes); } + } else { + // No more input file, we are done... + SetIsDone(true); + done = true; } } - char buffer[256]; - bool done = false; - bool got_line = false; + return got_line; + } + + if (in) { m_editing = true; while (!done) { #ifdef _WIN32 Index: lldb/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py =================================================================== --- lldb/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py +++ lldb/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py @@ -400,9 +400,9 @@ @add_test_categories(['pyapi']) - @expectedFailure # FIXME IOHandler still using FILE* + @skipIf(py_version=['<', (3,)]) def test_string_inout(self): - inf = io.StringIO("help help\n") + inf = io.StringIO("help help\np/x ~0\n") outf = io.StringIO() status = self.debugger.SetOutputFile(lldb.SBFile(outf)) self.assertTrue(status.Success()) @@ -413,10 +413,11 @@ self.debugger.GetOutputFile().Flush() output = outf.getvalue() self.assertIn('Show a list of all debugger commands', output) + self.assertIn('0xfff', output) @add_test_categories(['pyapi']) - @expectedFailure # FIXME IOHandler still using FILE* + @skipIf(py_version=['<', (3,)]) def test_bytes_inout(self): inf = io.BytesIO(b"help help\nhelp b\n") outf = io.BytesIO() Index: lldb/include/lldb/Core/IOHandler.h =================================================================== --- lldb/include/lldb/Core/IOHandler.h +++ lldb/include/lldb/Core/IOHandler.h @@ -431,6 +431,7 @@ bool m_interrupt_exits; bool m_editing; // Set to true when fetching a line manually (not using // libedit) + std::string m_line_buffer; }; // The order of base classes is important. Look at the constructor of
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits