diff options
author | Ilia K <ki.stfu@gmail.com> | 2015-02-26 18:14:30 +0000 |
---|---|---|
committer | Ilia K <ki.stfu@gmail.com> | 2015-02-26 18:14:30 +0000 |
commit | da86749a92f60e63aadd25a3cfed173a1cb189e4 (patch) | |
tree | a93a25d62a8fd6ecb4df95f8f39c69e6a73ee4f6 | |
parent | 28a3b86b069c05418234bd16890843ca400b8639 (diff) | |
download | bcm5719-llvm-da86749a92f60e63aadd25a3cfed173a1cb189e4.tar.gz bcm5719-llvm-da86749a92f60e63aadd25a3cfed173a1cb189e4.zip |
Fix process's output to stdout/stderr (MI)
Summary:
* Add CMIUtilString::Escape/Unescape methods (MI)
* Fix process's output to stdout/stderr (MI):
lldb-mi escapes process's output to show it in the following format:
```
~"..."
```
But previously not all characters were escaped by CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString and output of
```
printf("'\n` - it's \\n\x12\"\\\"")
```
looked like:
```
~"'\r\n` - it's \n"\""
```
This patch fixes it by using CMIUtilString::Escape method and now it looks like:
```
~"'\r\n` - it's \\n\x12\"\\\""
```
Reviewers: abidh, emaste, clayborg
Reviewed By: clayborg
Subscribers: zturner, lldb-commits, emaste, clayborg, abidh
Differential Revision: http://reviews.llvm.org/D7858
llvm-svn: 230652
-rw-r--r-- | lldb/test/tools/lldb-mi/syntax/Makefile | 5 | ||||
-rw-r--r-- | lldb/test/tools/lldb-mi/syntax/TestMiSyntax.py (renamed from lldb/test/tools/lldb-mi/TestMiSyntax.py) | 23 | ||||
-rw-r--r-- | lldb/test/tools/lldb-mi/syntax/main.cpp | 17 | ||||
-rw-r--r-- | lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp | 100 | ||||
-rw-r--r-- | lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h | 1 | ||||
-rw-r--r-- | lldb/tools/lldb-mi/MIUtilString.cpp | 78 | ||||
-rw-r--r-- | lldb/tools/lldb-mi/MIUtilString.h | 1 |
7 files changed, 144 insertions, 81 deletions
diff --git a/lldb/test/tools/lldb-mi/syntax/Makefile b/lldb/test/tools/lldb-mi/syntax/Makefile new file mode 100644 index 00000000000..314f1cb2f07 --- /dev/null +++ b/lldb/test/tools/lldb-mi/syntax/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/tools/lldb-mi/TestMiSyntax.py b/lldb/test/tools/lldb-mi/syntax/TestMiSyntax.py index 9f3e32c84c0..90211a7ef21 100644 --- a/lldb/test/tools/lldb-mi/TestMiSyntax.py +++ b/lldb/test/tools/lldb-mi/syntax/TestMiSyntax.py @@ -2,6 +2,10 @@ Test that the lldb-mi driver understands MI command syntax. """ +# adjust path for lldbmi_testcase.py +import sys, os.path +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) + import lldbmi_testcase from lldbtest import * import unittest2 @@ -63,5 +67,24 @@ class MiSyntaxTestCase(lldbmi_testcase.MiTestCaseBase): # Clean up os.unlink(complicated_myexe) + @lldbmi_test + @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races + def test_lldbmi_process_output(self): + """Test that 'lldb-mi --interpreter' wraps process output correctly.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run + self.runCmd("-exec-run") + self.expect("\^running") + + # Test that a process output is wrapped correctly + self.expect("\~\"'\\\\r\\\\n` - it's \\\\\\\\n\\\\x12\\\\\"\\\\\\\\\\\\\"") + if __name__ == '__main__': unittest2.main() diff --git a/lldb/test/tools/lldb-mi/syntax/main.cpp b/lldb/test/tools/lldb-mi/syntax/main.cpp new file mode 100644 index 00000000000..d2935b08f87 --- /dev/null +++ b/lldb/test/tools/lldb-mi/syntax/main.cpp @@ -0,0 +1,17 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <cstdio> + +int +main(int argc, char const *argv[]) +{ + printf("'\n` - it's \\n\x12\"\\\""); + return 0; +} diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp index 650856f34d5..829d60a7fe3 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp @@ -1379,26 +1379,24 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void) bool CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void) { - bool bOk = MIstatus::success; - - char c; - size_t nBytes = 0; CMIUtilString text; + std::unique_ptr<char[]> apStdoutBuffer(new char[1024]); lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess(); - while (process.GetSTDOUT(&c, 1) > 0) + while (1) { - CMIUtilString str; - if (ConvertPrintfCtrlCodeToString(c, str)) - text += str; - nBytes++; - } - if (nBytes > 0) - { - const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str())); - bOk = TextToStdout(t); + const size_t nBytes = process.GetSTDOUT(apStdoutBuffer.get(), 1024); + if (nBytes == 0) + break; + + text.append(apStdoutBuffer.get(), nBytes); } - return bOk; + if (text.empty()) + return MIstatus::success; + + const bool bEscapeQuotes(true); + const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.Escape(bEscapeQuotes).c_str())); + return TextToStdout(t); } //++ ------------------------------------------------------------------------------------ @@ -1414,72 +1412,24 @@ CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void) bool CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void) { - bool bOk = MIstatus::success; - - char c; - size_t nBytes = 0; CMIUtilString text; + std::unique_ptr<char[]> apStderrBuffer(new char[1024]); lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess(); - while (process.GetSTDERR(&c, 1) > 0) - { - CMIUtilString str; - if (ConvertPrintfCtrlCodeToString(c, str)) - text += str; - nBytes++; - } - if (nBytes > 0) - { - const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str())); - bOk = TextToStdout(t); - } - - return bOk; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Convert text stream control codes to text equivalent. -// Type: Method. -// Args: vCtrl - (R) The control code. -// vwrStrEquivalent - (W) The text equivalent. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool -CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent) -{ - switch (vCtrl) + while (1) { - case '\033': - vwrStrEquivalent = "\\e"; - break; - case '\a': - vwrStrEquivalent = "\\a"; - break; - case '\b': - vwrStrEquivalent = "\\b"; - break; - case '\f': - vwrStrEquivalent = "\\f"; - break; - case '\n': - vwrStrEquivalent = "\\n"; - break; - case '\r': - vwrStrEquivalent = "\\r"; - break; - case '\t': - vwrStrEquivalent = "\\t"; - break; - case '\v': - vwrStrEquivalent = "\\v"; - break; - default: - vwrStrEquivalent = CMIUtilString::Format("%c", vCtrl); + const size_t nBytes = process.GetSTDERR(apStderrBuffer.get(), 1024); + if (nBytes == 0) break; + + text.append(apStderrBuffer.get(), nBytes); } - return MIstatus::success; + if (text.empty()) + return MIstatus::success; + + const bool bEscapeQuotes(true); + const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.Escape(bEscapeQuotes).c_str())); + return TextToStdout(t); } //++ ------------------------------------------------------------------------------------ diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h index 5fe9af1a39c..01b394fcdca 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h +++ b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h @@ -86,7 +86,6 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton< bool TextToStdout(const CMIUtilString &vrTxt); bool TextToStderr(const CMIUtilString &vrTxt); bool UpdateSelectedThread(void); - bool ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent); // Overridden: private: diff --git a/lldb/tools/lldb-mi/MIUtilString.cpp b/lldb/tools/lldb-mi/MIUtilString.cpp index 599b18b0397..b9d1d7d4f02 100644 --- a/lldb/tools/lldb-mi/MIUtilString.cpp +++ b/lldb/tools/lldb-mi/MIUtilString.cpp @@ -20,11 +20,12 @@ //-- // Third party headers -#include <memory> // std::unique_ptr -#include <stdarg.h> // va_list, va_start, var_end -#include <sstream> // std::stringstream -#include <string.h> // for strncmp -#include <limits.h> // for ULONG_MAX +#include <inttypes.h> // for PRIx8 +#include <limits.h> // for ULONG_MAX +#include <memory> // std::unique_ptr +#include <sstream> // std::stringstream +#include <stdarg.h> // va_list, va_start, var_end +#include <string.h> // for strncmp // In-house headers: #include "MIUtilString.h" @@ -797,3 +798,70 @@ CMIUtilString::FindFirstQuote(const MIuint vnPos) const return (MIuint)std::string::npos; } + +//++ ------------------------------------------------------------------------------------ +// Details: Get escaped string from *this string. +// Type: Method. +// Args: None. +// Return: CMIUtilString - The escaped version of the initial string. +// Throws: None. +//-- +CMIUtilString +CMIUtilString::Escape(const bool vbEscapeQuotes /* = false */) const +{ + const MIuint nLen(length()); + CMIUtilString strNew; + strNew.reserve(nLen); + for (MIuint nIndex(0); nIndex < nLen; ++nIndex) + { + const MIchar cUnescapedChar((*this)[nIndex]); + switch (cUnescapedChar) + { + case '\a': + strNew.append("\\a"); + break; + case '\b': + strNew.append("\\b"); + break; + case '\t': + strNew.append("\\t"); + break; + case '\n': + strNew.append("\\n"); + break; + case '\v': + strNew.append("\\v"); + break; + case '\f': + strNew.append("\\f"); + break; + case '\r': + strNew.append("\\r"); + break; + case '\033': + strNew.append("\\e"); + break; + case '\\': + strNew.append("\\\\"); + break; + case '\"': + if (vbEscapeQuotes) + { + strNew.append("\\\""); + break; + } + // FALLTHROUGH + default: + if (::isprint(cUnescapedChar)) + strNew.push_back(cUnescapedChar); + else + { + char strEscapedChar[sizeof("\\xXX")]; + ::sprintf(strEscapedChar, "\\x%02" PRIx8, cUnescapedChar); + strNew.append(strEscapedChar); + } + break; + } + } + return strNew; +} diff --git a/lldb/tools/lldb-mi/MIUtilString.h b/lldb/tools/lldb-mi/MIUtilString.h index 37f3092441b..54a0f7704c0 100644 --- a/lldb/tools/lldb-mi/MIUtilString.h +++ b/lldb/tools/lldb-mi/MIUtilString.h @@ -72,6 +72,7 @@ class CMIUtilString : public std::string MIuint FindFirst(const CMIUtilString &vrPattern, const bool vbSkipQuotedText, bool &vrwbNotFoundClosedQuote, const MIuint vnPos = 0) const; MIuint FindFirstNot(const CMIUtilString &vrPattern, const MIuint vnPos = 0) const; + CMIUtilString Escape(const bool vbEscapeQuotes = false) const; // CMIUtilString &operator=(const MIchar *vpRhs); CMIUtilString &operator=(const std::string &vrRhs); |