[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-11 Thread Lawrence D'Anna via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb3faa01ff962: IOHandler: fall back on File::Read if a FILE* 
isnt available. (authored by lawrence_danna).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68622/new/

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
@@ -70,6 +70,10 @@
 
 using namespace lldb;
 using namespace lldb_private;
+using llvm::None;
+using llvm::Optional;
+using llvm::StringRef;
+
 
 IOHandler::IOHandler(Debugger , IOHandler::Type type)
 : IOHandler(debugger, type,
@@ -306,94 +310,119 @@
   m_delegate.IOHandlerDeactivated(*this);
 }
 
+// Split out a line from the buffer, if there is a full one to get.
+static Optional SplitLine(std::string _buffer) {
+  size_t pos = line_buffer.find('\n');
+  if (pos == std::string::npos)
+return None;
+  std::string line = StringRef(line_buffer.c_str(), pos).rtrim("\n\r");
+  line_buffer = line_buffer.substr(pos + 1);
+  return line;
+}
+
+// If the final line of the file ends without a end-of-line, return
+// it as a line anyway.
+static Optional SplitLineEOF(std::string _buffer) {
+  if (llvm::all_of(line_buffer, isspace))
+return None;
+  std::string line = std::move(line_buffer);
+  line_buffer.clear();
+  return line;
+}
+
 bool IOHandlerEditline::GetLine(std::string , bool ) {
 #ifndef LLDB_DISABLE_LIBEDIT
   if (m_editline_up) {
 bool b = m_editline_up->GetLine(line, interrupted);
-if (m_data_recorder)
+if (b && m_data_recorder)
   m_data_recorder->Record(line, true);
 return b;
-  } else {
+  }
 #endif
-line.clear();
 
-FILE *in = GetInputFILE();
-if (in) {
-  if (GetIsInteractive()) {
-const char *prompt = nullptr;
+  line.clear();
 
-if (m_multi_line && m_curr_line_idx > 0)
-  prompt = GetContinuationPrompt();
+  if (GetIsInteractive()) {
+const char *prompt = nullptr;
 
-if (prompt == nullptr)
-  prompt = GetPrompt();
+if (m_multi_line && m_curr_line_idx > 0)
+  prompt = GetContinuationPrompt();
 
-if (prompt && prompt[0]) {
-  if (m_output_sp) {
-m_output_sp->Printf("%s", prompt);
-m_output_sp->Flush();
-  }
-}
+if (prompt == nullptr)
+  prompt = GetPrompt();
+
+if (prompt && prompt[0]) {
+  if (m_output_sp) {
+m_output_sp->Printf("%s", prompt);
+m_output_sp->Flush();
+  }
+}
+  }
+
+  Optional got_line = SplitLine(m_line_buffer);
+
+  if (!got_line && !m_input_sp) {
+// No more input file, we are done...
+SetIsDone(true);
+return false;
+  }
+
+  FILE *in = GetInputFILE();
+  char buffer[256];
+
+  if (!got_line && !in && m_input_sp) {
+// there is no FILE*, fall back on just reading bytes from the stream.
+while (!got_line) {
+  size_t bytes_read = sizeof(buffer);
+  Status error = m_input_sp->Read((void *)buffer, bytes_read);
+  if (error.Success() && !bytes_read) {
+got_line = SplitLineEOF(m_line_buffer);
+break;
   }
-  char buffer[256];
-  bool done = false;
-  bool got_line = false;
-  m_editing = true;
-  while (!done) {
+  if (error.Fail())
+break;
+  m_line_buffer += StringRef(buffer, bytes_read);
+  got_line = SplitLine(m_line_buffer);
+}
+  }
+
+  if (!got_line && in) {
+m_editing = true;
+while (!got_line) {
+  char *r = fgets(buffer, sizeof(buffer), in);
 #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) {
-  // this is the equivalent of EINTR for Windows
-  if (GetLastError() == ERROR_OPERATION_ABORTED)
-continue;
-#else
-  if (fgets(buffer, sizeof(buffer), in) == nullptr) {
+  // 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 

[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-11 Thread Lawrence D'Anna via Phabricator via lldb-commits
lawrence_danna updated this revision to Diff 224630.
lawrence_danna added a comment.

move using declarations


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68622/new/

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
@@ -70,6 +70,10 @@
 
 using namespace lldb;
 using namespace lldb_private;
+using llvm::None;
+using llvm::Optional;
+using llvm::StringRef;
+
 
 IOHandler::IOHandler(Debugger , IOHandler::Type type)
 : IOHandler(debugger, type,
@@ -306,94 +310,119 @@
   m_delegate.IOHandlerDeactivated(*this);
 }
 
+// Split out a line from the buffer, if there is a full one to get.
+static Optional SplitLine(std::string _buffer) {
+  size_t pos = line_buffer.find('\n');
+  if (pos == std::string::npos)
+return None;
+  std::string line = StringRef(line_buffer.c_str(), pos).rtrim("\n\r");
+  line_buffer = line_buffer.substr(pos + 1);
+  return line;
+}
+
+// If the final line of the file ends without a end-of-line, return
+// it as a line anyway.
+static Optional SplitLineEOF(std::string _buffer) {
+  if (llvm::all_of(line_buffer, isspace))
+return None;
+  std::string line = std::move(line_buffer);
+  line_buffer.clear();
+  return line;
+}
+
 bool IOHandlerEditline::GetLine(std::string , bool ) {
 #ifndef LLDB_DISABLE_LIBEDIT
   if (m_editline_up) {
 bool b = m_editline_up->GetLine(line, interrupted);
-if (m_data_recorder)
+if (b && m_data_recorder)
   m_data_recorder->Record(line, true);
 return b;
-  } else {
+  }
 #endif
-line.clear();
 
-FILE *in = GetInputFILE();
-if (in) {
-  if (GetIsInteractive()) {
-const char *prompt = nullptr;
+  line.clear();
 
-if (m_multi_line && m_curr_line_idx > 0)
-  prompt = GetContinuationPrompt();
+  if (GetIsInteractive()) {
+const char *prompt = nullptr;
 
-if (prompt == nullptr)
-  prompt = GetPrompt();
+if (m_multi_line && m_curr_line_idx > 0)
+  prompt = GetContinuationPrompt();
 
-if (prompt && prompt[0]) {
-  if (m_output_sp) {
-m_output_sp->Printf("%s", prompt);
-m_output_sp->Flush();
-  }
-}
+if (prompt == nullptr)
+  prompt = GetPrompt();
+
+if (prompt && prompt[0]) {
+  if (m_output_sp) {
+m_output_sp->Printf("%s", prompt);
+m_output_sp->Flush();
+  }
+}
+  }
+
+  Optional got_line = SplitLine(m_line_buffer);
+
+  if (!got_line && !m_input_sp) {
+// No more input file, we are done...
+SetIsDone(true);
+return false;
+  }
+
+  FILE *in = GetInputFILE();
+  char buffer[256];
+
+  if (!got_line && !in && m_input_sp) {
+// there is no FILE*, fall back on just reading bytes from the stream.
+while (!got_line) {
+  size_t bytes_read = sizeof(buffer);
+  Status error = m_input_sp->Read((void *)buffer, bytes_read);
+  if (error.Success() && !bytes_read) {
+got_line = SplitLineEOF(m_line_buffer);
+break;
   }
-  char buffer[256];
-  bool done = false;
-  bool got_line = false;
-  m_editing = true;
-  while (!done) {
+  if (error.Fail())
+break;
+  m_line_buffer += StringRef(buffer, bytes_read);
+  got_line = SplitLine(m_line_buffer);
+}
+  }
+
+  if (!got_line && in) {
+m_editing = true;
+while (!got_line) {
+  char *r = fgets(buffer, sizeof(buffer), in);
 #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) {
-  // this is the equivalent of EINTR for Windows
-  if (GetLastError() == ERROR_OPERATION_ABORTED)
-continue;
-#else
-  if (fgets(buffer, sizeof(buffer), in) == nullptr) {
+  // 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 (r == nullptr)
+r = fgets(buffer, sizeof(buffer), 

[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-11 Thread Pavel Labath via Phabricator via lldb-commits
labath accepted this revision.
labath added inline comments.
This revision is now accepted and ready to land.



Comment at: lldb/source/Core/IOHandler.cpp:308-310
+using llvm::None;
+using llvm::Optional;
+using llvm::StringRef;

Please move these to the beginning of the file, next to all the "using 
namespace" stuff.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68622/new/

https://reviews.llvm.org/D68622



___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-09 Thread Lawrence D'Anna via Phabricator via lldb-commits
lawrence_danna added a comment.

fixed


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68622/new/

https://reviews.llvm.org/D68622



___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-09 Thread Lawrence D'Anna via Phabricator via lldb-commits
lawrence_danna updated this revision to Diff 224119.
lawrence_danna marked 4 inline comments as done.
lawrence_danna added a comment.

review fixes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68622/new/

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
@@ -305,94 +305,123 @@
   m_delegate.IOHandlerDeactivated(*this);
 }
 
+using llvm::None;
+using llvm::Optional;
+using llvm::StringRef;
+
+// Split out a line from the buffer, if there is a full one to get.
+static Optional SplitLine(std::string _buffer) {
+  size_t pos = line_buffer.find('\n');
+  if (pos == std::string::npos)
+return None;
+  std::string line = StringRef(line_buffer.c_str(), pos).rtrim("\n\r");
+  line_buffer = line_buffer.substr(pos + 1);
+  return line;
+}
+
+// If the final line of the file ends without a end-of-line, return
+// it as a line anyway.
+static Optional SplitLineEOF(std::string _buffer) {
+  if (llvm::all_of(line_buffer, isspace))
+return None;
+  std::string line = std::move(line_buffer);
+  line_buffer.clear();
+  return line;
+}
+
 bool IOHandlerEditline::GetLine(std::string , bool ) {
 #ifndef LLDB_DISABLE_LIBEDIT
   if (m_editline_up) {
 bool b = m_editline_up->GetLine(line, interrupted);
-if (m_data_recorder)
+if (b && m_data_recorder)
   m_data_recorder->Record(line, true);
 return b;
-  } else {
+  }
 #endif
-line.clear();
 
-FILE *in = GetInputFILE();
-if (in) {
-  if (GetIsInteractive()) {
-const char *prompt = nullptr;
+  line.clear();
 
-if (m_multi_line && m_curr_line_idx > 0)
-  prompt = GetContinuationPrompt();
+  if (GetIsInteractive()) {
+const char *prompt = nullptr;
 
-if (prompt == nullptr)
-  prompt = GetPrompt();
+if (m_multi_line && m_curr_line_idx > 0)
+  prompt = GetContinuationPrompt();
 
-if (prompt && prompt[0]) {
-  if (m_output_sp) {
-m_output_sp->Printf("%s", prompt);
-m_output_sp->Flush();
-  }
-}
+if (prompt == nullptr)
+  prompt = GetPrompt();
+
+if (prompt && prompt[0]) {
+  if (m_output_sp) {
+m_output_sp->Printf("%s", prompt);
+m_output_sp->Flush();
+  }
+}
+  }
+
+  Optional got_line = SplitLine(m_line_buffer);
+
+  if (!got_line && !m_input_sp) {
+// No more input file, we are done...
+SetIsDone(true);
+return false;
+  }
+
+  FILE *in = GetInputFILE();
+  char buffer[256];
+
+  if (!got_line && !in && m_input_sp) {
+// there is no FILE*, fall back on just reading bytes from the stream.
+while (!got_line) {
+  size_t bytes_read = sizeof(buffer);
+  Status error = m_input_sp->Read((void *)buffer, bytes_read);
+  if (error.Success() && !bytes_read) {
+got_line = SplitLineEOF(m_line_buffer);
+break;
   }
-  char buffer[256];
-  bool done = false;
-  bool got_line = false;
-  m_editing = true;
-  while (!done) {
+  if (error.Fail())
+break;
+  m_line_buffer += StringRef(buffer, bytes_read);
+  got_line = SplitLine(m_line_buffer);
+}
+  }
+
+  if (!got_line && in) {
+m_editing = true;
+while (!got_line) {
+  char *r = fgets(buffer, sizeof(buffer), in);
 #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) {
-  // this is the equivalent of EINTR for Windows
-  if (GetLastError() == ERROR_OPERATION_ABORTED)
-continue;
-#else
-  if (fgets(buffer, sizeof(buffer), in) == nullptr) {
+  // 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 (r == nullptr)
+r = fgets(buffer, sizeof(buffer), in);
+  // this is the equivalent of EINTR for Windows
+  if (r == nullptr && GetLastError() == 

[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-09 Thread Pavel Labath via Phabricator via lldb-commits
labath added inline comments.



Comment at: lldb/source/Core/IOHandler.cpp:317-321
+  size_t end = pos + 1;
+  while (end > 0 &&
+ (line_buffer[end - 1] == '\n' || line_buffer[end - 1] == '\r'))
+end--;
+  std::string line = line_buffer.substr(0, end);

`line = StringRef(line_buffer.begin(), pos).rtrim("\n\r")` ?



Comment at: lldb/source/Core/IOHandler.cpp:326-341
+// Append newchars to the buffer and split out a line.
+static Optional AppendAndSplitLine(std::string _buffer,
+StringRef newchars) {
+  size_t pos = newchars.find('\n');
+  if (pos == StringRef::npos) {
+line_buffer.append(newchars);
+return None;

This looks like too much optimization. Why not just append the new stuff and 
then call `SplitLine` ?



Comment at: lldb/source/Core/IOHandler.cpp:346-347
+static Optional SplitLineEOF(std::string _buffer) {
+  if (line_buffer.empty())
+return None;
+  if (std::all_of(line_buffer.begin(), line_buffer.end(), isspace))

Technically, this check is subsumed by the next one.



Comment at: lldb/source/Core/IOHandler.cpp:348
+return None;
+  if (std::all_of(line_buffer.begin(), line_buffer.end(), isspace))
+return None;

`llvm::all_of(line_buffer, ::isspace)`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68622/new/

https://reviews.llvm.org/D68622



___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-08 Thread Lawrence D'Anna via Phabricator via lldb-commits
lawrence_danna updated this revision to Diff 223983.
lawrence_danna added a comment.

rebased


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68622/new/

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
@@ -305,94 +305,145 @@
   m_delegate.IOHandlerDeactivated(*this);
 }
 
+using llvm::None;
+using llvm::Optional;
+using llvm::StringRef;
+
+// Split out a line from the buffer, if there is a full one to get.
+static Optional SplitLine(std::string _buffer) {
+  size_t pos = line_buffer.find('\n');
+  if (pos == std::string::npos)
+return None;
+  size_t end = pos + 1;
+  while (end > 0 &&
+ (line_buffer[end - 1] == '\n' || line_buffer[end - 1] == '\r'))
+end--;
+  std::string line = line_buffer.substr(0, end);
+  line_buffer = line_buffer.substr(pos + 1);
+  return line;
+}
+
+// Append newchars to the buffer and split out a line.
+static Optional AppendAndSplitLine(std::string _buffer,
+StringRef newchars) {
+  size_t pos = newchars.find('\n');
+  if (pos == StringRef::npos) {
+line_buffer.append(newchars);
+return None;
+  }
+  size_t end = pos + 1;
+  while (end > 0 && (newchars[end - 1] == '\n' || newchars[end - 1] == '\r'))
+end--;
+  std::string line = std::move(line_buffer);
+  line.append(newchars.substr(0, end));
+  line_buffer = newchars.substr(pos + 1);
+  return line;
+}
+
+// If the final line of the file ends without a end-of-line, return
+// it as a line anyway.
+static Optional SplitLineEOF(std::string _buffer) {
+  if (line_buffer.empty())
+return None;
+  if (std::all_of(line_buffer.begin(), line_buffer.end(), isspace))
+return None;
+  std::string line = std::move(line_buffer);
+  line_buffer.clear();
+  return line;
+}
+
 bool IOHandlerEditline::GetLine(std::string , bool ) {
 #ifndef LLDB_DISABLE_LIBEDIT
   if (m_editline_up) {
 bool b = m_editline_up->GetLine(line, interrupted);
-if (m_data_recorder)
+if (b && m_data_recorder)
   m_data_recorder->Record(line, true);
 return b;
-  } else {
+  }
 #endif
-line.clear();
 
-FILE *in = GetInputFILE();
-if (in) {
-  if (GetIsInteractive()) {
-const char *prompt = nullptr;
+  line.clear();
 
-if (m_multi_line && m_curr_line_idx > 0)
-  prompt = GetContinuationPrompt();
+  if (GetIsInteractive()) {
+const char *prompt = nullptr;
 
-if (prompt == nullptr)
-  prompt = GetPrompt();
+if (m_multi_line && m_curr_line_idx > 0)
+  prompt = GetContinuationPrompt();
 
-if (prompt && prompt[0]) {
-  if (m_output_sp) {
-m_output_sp->Printf("%s", prompt);
-m_output_sp->Flush();
-  }
-}
+if (prompt == nullptr)
+  prompt = GetPrompt();
+
+if (prompt && prompt[0]) {
+  if (m_output_sp) {
+m_output_sp->Printf("%s", prompt);
+m_output_sp->Flush();
+  }
+}
+  }
+
+  Optional got_line = SplitLine(m_line_buffer);
+
+  if (!got_line && !m_input_sp) {
+// No more input file, we are done...
+SetIsDone(true);
+return false;
+  }
+
+  FILE *in = GetInputFILE();
+  char buffer[256];
+
+  if (!got_line && !in && m_input_sp) {
+// there is no FILE*, fall back on just reading bytes from the stream.
+while (!got_line) {
+  size_t bytes_read = sizeof(buffer);
+  Status error = m_input_sp->Read((void *)buffer, bytes_read);
+  if (error.Success() && !bytes_read) {
+got_line = SplitLineEOF(m_line_buffer);
+break;
   }
-  char buffer[256];
-  bool done = false;
-  bool got_line = false;
-  m_editing = true;
-  while (!done) {
+  if (error.Fail())
+break;
+  got_line =
+  AppendAndSplitLine(m_line_buffer, StringRef(buffer, bytes_read));
+}
+  }
+
+  if (!got_line && in) {
+m_editing = true;
+while (!got_line) {
+  char *r = fgets(buffer, sizeof(buffer), in);
 #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) {
-  // this is the equivalent of EINTR for Windows
-  if (GetLastError() == ERROR_OPERATION_ABORTED)
-   

[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-08 Thread Lawrence D'Anna via Phabricator via lldb-commits
lawrence_danna updated this revision to Diff 223958.
lawrence_danna added a comment.

factor out string splitting stuff


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68622/new/

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
@@ -305,94 +305,145 @@
   m_delegate.IOHandlerDeactivated(*this);
 }
 
+using llvm::None;
+using llvm::Optional;
+using llvm::StringRef;
+
+// Split out a line from the buffer, if there is a full one to get.
+static Optional SplitLine(std::string _buffer) {
+  size_t pos = line_buffer.find('\n');
+  if (pos == std::string::npos)
+return None;
+  size_t end = pos + 1;
+  while (end > 0 &&
+ (line_buffer[end - 1] == '\n' || line_buffer[end - 1] == '\r'))
+end--;
+  std::string line = line_buffer.substr(0, end);
+  line_buffer = line_buffer.substr(pos + 1);
+  return line;
+}
+
+// Append newchars to the buffer and split out a line.
+static Optional AppendAndSplitLine(std::string _buffer,
+StringRef newchars) {
+  size_t pos = newchars.find('\n');
+  if (pos == StringRef::npos) {
+line_buffer.append(newchars);
+return None;
+  }
+  size_t end = pos + 1;
+  while (end > 0 && (newchars[end - 1] == '\n' || newchars[end - 1] == '\r'))
+end--;
+  std::string line = std::move(line_buffer);
+  line.append(newchars.substr(0, end));
+  line_buffer = newchars.substr(pos + 1);
+  return line;
+}
+
+// If the final line of the file ends without a end-of-line, return
+// it as a line anyway.
+static Optional SplitLineEOF(std::string _buffer) {
+  if (line_buffer.empty())
+return None;
+  if (std::all_of(line_buffer.begin(), line_buffer.end(), isspace))
+return None;
+  std::string line = std::move(line_buffer);
+  line_buffer.clear();
+  return line;
+}
+
 bool IOHandlerEditline::GetLine(std::string , bool ) {
 #ifndef LLDB_DISABLE_LIBEDIT
   if (m_editline_up) {
 bool b = m_editline_up->GetLine(line, interrupted);
-if (m_data_recorder)
+if (b && m_data_recorder)
   m_data_recorder->Record(line, true);
 return b;
-  } else {
+  }
 #endif
-line.clear();
 
-FILE *in = GetInputFILE();
-if (in) {
-  if (GetIsInteractive()) {
-const char *prompt = nullptr;
+  line.clear();
 
-if (m_multi_line && m_curr_line_idx > 0)
-  prompt = GetContinuationPrompt();
+  if (GetIsInteractive()) {
+const char *prompt = nullptr;
 
-if (prompt == nullptr)
-  prompt = GetPrompt();
+if (m_multi_line && m_curr_line_idx > 0)
+  prompt = GetContinuationPrompt();
 
-if (prompt && prompt[0]) {
-  if (m_output_sp) {
-m_output_sp->Printf("%s", prompt);
-m_output_sp->Flush();
-  }
-}
+if (prompt == nullptr)
+  prompt = GetPrompt();
+
+if (prompt && prompt[0]) {
+  if (m_output_sp) {
+m_output_sp->Printf("%s", prompt);
+m_output_sp->Flush();
+  }
+}
+  }
+
+  Optional got_line = SplitLine(m_line_buffer);
+
+  if (!got_line && !m_input_sp) {
+// No more input file, we are done...
+SetIsDone(true);
+return false;
+  }
+
+  FILE *in = GetInputFILE();
+  char buffer[256];
+
+  if (!got_line && !in && m_input_sp) {
+// there is no FILE*, fall back on just reading bytes from the stream.
+while (!got_line) {
+  size_t bytes_read = sizeof(buffer);
+  Status error = m_input_sp->Read((void *)buffer, bytes_read);
+  if (error.Success() && !bytes_read) {
+got_line = SplitLineEOF(m_line_buffer);
+break;
   }
-  char buffer[256];
-  bool done = false;
-  bool got_line = false;
-  m_editing = true;
-  while (!done) {
+  if (error.Fail())
+break;
+  got_line =
+  AppendAndSplitLine(m_line_buffer, StringRef(buffer, bytes_read));
+}
+  }
+
+  if (!got_line && in) {
+m_editing = true;
+while (!got_line) {
+  char *r = fgets(buffer, sizeof(buffer), in);
 #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) {
-  // this is the equivalent of EINTR for Windows
-  if (GetLastError() == 

[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-08 Thread Pavel Labath via Phabricator via lldb-commits
labath added a comment.

Even if we ignore the windows parts, there's still a lot of duplication here. 
The bits that extract a "complete" line from the buffer look like they could be 
factored into a separate function (`Optional 
GetCompleteLineFromCache(...)` ?). It would not hurt to split the parts that 
read from a FILE and the parts reading from the lldb_private::File into 
separate functions too...
Other than that, the functionality seems fine to me...


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68622/new/

https://reviews.llvm.org/D68622



___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D68622: IOHandler: fall back on File::Read if a FILE* isn't available.

2019-10-07 Thread Lawrence D'Anna via Phabricator via lldb-commits
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'])
-