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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits