summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlia K <ki.stfu@gmail.com>2015-02-26 18:14:30 +0000
committerIlia K <ki.stfu@gmail.com>2015-02-26 18:14:30 +0000
commitda86749a92f60e63aadd25a3cfed173a1cb189e4 (patch)
treea93a25d62a8fd6ecb4df95f8f39c69e6a73ee4f6
parent28a3b86b069c05418234bd16890843ca400b8639 (diff)
downloadbcm5719-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/Makefile5
-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.cpp17
-rw-r--r--lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp100
-rw-r--r--lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h1
-rw-r--r--lldb/tools/lldb-mi/MIUtilString.cpp78
-rw-r--r--lldb/tools/lldb-mi/MIUtilString.h1
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);
OpenPOWER on IntegriCloud