summaryrefslogtreecommitdiffstats
path: root/lldb/source/Host/common/Editline.cpp
diff options
context:
space:
mode:
authorPavel Labath <labath@google.com>2017-01-06 09:27:38 +0000
committerPavel Labath <labath@google.com>2017-01-06 09:27:38 +0000
commit927ec4b5ace874af77dd0ff9b7580fe5f29884ee (patch)
treed9652d87334045fcf3a403eb0bf8b0f06b967764 /lldb/source/Host/common/Editline.cpp
parent214a8976817a7290a3d11806e19f38e2fd71d99d (diff)
downloadbcm5719-llvm-927ec4b5ace874af77dd0ff9b7580fe5f29884ee.tar.gz
bcm5719-llvm-927ec4b5ace874af77dd0ff9b7580fe5f29884ee.zip
Consolidate file handle usage in Editline.cpp
Summary: To implement wide character reading, editline was mixing FILE*-based access with a Connection-based one (plus it did some selects on the raw FD), which is very fragile. Here, I replace it with one which uses only a Connection-based reads. The code is somewhat longer as I had to read characters one by one to detect the end of the multibyte sequence. I've verified that international characters still work in lldb command line on OSX. Reviewers: clayborg, zturner Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D28356 llvm-svn: 291220
Diffstat (limited to 'lldb/source/Host/common/Editline.cpp')
-rw-r--r--lldb/source/Host/common/Editline.cpp47
1 files changed, 37 insertions, 10 deletions
diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp
index a600c61c8e6..1c5c0ffe902 100644
--- a/lldb/source/Host/common/Editline.cpp
+++ b/lldb/source/Host/common/Editline.cpp
@@ -526,17 +526,8 @@ int Editline::GetCharacter(EditLineCharType *c) {
}
if (read_count) {
-#if LLDB_EDITLINE_USE_WCHAR
- // After the initial interruptible read, this is guaranteed not to block
- ungetc(ch, m_input_file);
- *c = fgetwc(m_input_file);
- if (*c != WEOF)
- return 1;
-#else
- *c = ch;
- if (ch != (char)EOF)
+ if (CompleteCharacter(ch, *c))
return 1;
-#endif
} else {
switch (status) {
case lldb::eConnectionStatusSuccess: // Success
@@ -1367,3 +1358,39 @@ void Editline::PrintAsync(Stream *stream, const char *s, size_t len) {
MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
}
}
+
+bool Editline::CompleteCharacter(char ch, EditLineCharType &out) {
+#if !LLDB_EDITLINE_USE_WCHAR
+ if (ch == (char)EOF)
+ return false;
+
+ out = ch;
+ return true;
+#else
+ std::codecvt_utf8<wchar_t> cvt;
+ llvm::SmallString<4> input;
+ for (;;) {
+ const char *from_next;
+ wchar_t *to_next;
+ std::mbstate_t state = std::mbstate_t();
+ input.push_back(ch);
+ switch (cvt.in(state, input.begin(), input.end(), from_next, &out, &out + 1,
+ to_next)) {
+ case std::codecvt_base::ok:
+ return out != WEOF;
+
+ case std::codecvt_base::error:
+ case std::codecvt_base::noconv:
+ return false;
+
+ case std::codecvt_base::partial:
+ lldb::ConnectionStatus status;
+ size_t read_count = m_input_connection.Read(
+ &ch, 1, std::chrono::seconds(0), status, nullptr);
+ if (read_count == 0)
+ return false;
+ break;
+ }
+ }
+#endif
+}
OpenPOWER on IntegriCloud