Skip to content

Commit

Permalink
Support escapes and quotes in string and character values.
Browse files Browse the repository at this point in the history
Summary:
Escape characters in strings and strings containing quotes were not appearing correctly in expression values.

Patch from paulmay@microsoft.com

Reviewers: abidh, ChuckR, paulmaybee

Subscribers: greggm, lldb-commits

Differential Revision: http://reviews.llvm.org/D11371

llvm-svn: 243383
  • Loading branch information
k15tfu committed Jul 28, 2015
1 parent 0a67440 commit b56c50f
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 57 deletions.
46 changes: 23 additions & 23 deletions lldb/test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py
Expand Up @@ -37,27 +37,27 @@ def test_lldbmi_gdb_set_show_print_char_array_as_string(self):

# Test that an char* is expanded to string when print char-array-as-string is "off"
self.runCmd("-var-create - * cp")
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ \\\\\\\"hello\\\\\\\"\",type=\"const char \*\",thread-id=\"1\",has_more=\"0\"")
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ \\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char \*\",thread-id=\"1\",has_more=\"0\"")

# Test that an char[] isn't expanded to string when print char-array-as-string is "off"
self.runCmd("-var-create - * ca")
self.expect("\^done,name=\"var\d+\",numchild=\"6\",value=\"\[6\]\",type=\"const char \[6\]\",thread-id=\"1\",has_more=\"0\"")
self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"\[10\]\",type=\"const char \[10\]\",thread-id=\"1\",has_more=\"0\"")

# Test that an char16_t* is expanded to string when print char-array-as-string is "off"
self.runCmd("-var-create - * u16p")
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ u\\\\\\\"hello\\\\\\\"\",type=\"const char16_t \*\",thread-id=\"1\",has_more=\"0\"")
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ u\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char16_t \*\",thread-id=\"1\",has_more=\"0\"")

# Test that an char16_t[] isn't expanded to string when print char-array-as-string is "off"
self.runCmd("-var-create - * u16a")
self.expect("\^done,name=\"var\d+\",numchild=\"6\",value=\"\[6\]\",type=\"const char16_t \[6\]\",thread-id=\"1\",has_more=\"0\"")
self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"\[10\]\",type=\"const char16_t \[10\]\",thread-id=\"1\",has_more=\"0\"")

# Test that an char32_t* is expanded to string when print char-array-as-string is "off"
self.runCmd("-var-create - * u32p")
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ U\\\\\\\"hello\\\\\\\"\",type=\"const char32_t \*\",thread-id=\"1\",has_more=\"0\"")
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ U\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char32_t \*\",thread-id=\"1\",has_more=\"0\"")

# Test that an char32_t[] isn't expanded to string when print char-array-as-string is "off"
self.runCmd("-var-create - * u32a")
self.expect("\^done,name=\"var\d+\",numchild=\"6\",value=\"\[6\]\",type=\"const char32_t \[6\]\",thread-id=\"1\",has_more=\"0\"")
self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"\[10\]\",type=\"const char32_t \[10\]\",thread-id=\"1\",has_more=\"0\"")

# Test that -gdb-set can set print char-array-as-string flag
self.runCmd("-gdb-set print char-array-as-string on")
Expand All @@ -67,29 +67,29 @@ def test_lldbmi_gdb_set_show_print_char_array_as_string(self):
self.runCmd("-gdb-show print char-array-as-string")
self.expect("\^done,value=\"on\"")

# Test that an char* is expanded to string when print char-array-as-string is "on"
# Test that an char* with escape chars is expanded to string when print char-array-as-string is "on"
self.runCmd("-var-create - * cp")
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ \\\\\\\"hello\\\\\\\"\",type=\"const char \*\",thread-id=\"1\",has_more=\"0\"")

# Test that an char[] isn't expanded to string when print char-array-as-string is "on"
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ \\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char \*\",thread-id=\"1\",has_more=\"0\"")
# Test that an char[] with escape chars is expanded to string when print char-array-as-string is "on"
self.runCmd("-var-create - * ca")
self.expect("\^done,name=\"var\d+\",numchild=\"6\",value=\"\\\\\\\"hello\\\\\\\"\",type=\"const char \[6\]\",thread-id=\"1\",has_more=\"0\"")

# Test that an char16_t* is expanded to string when print char-array-as-string is "on"
self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char \[10\]\",thread-id=\"1\",has_more=\"0\"")
# Test that an char16_t* with esc1ape chars is expanded to string when print char-array-as-string is "on"
self.runCmd("-var-create - * u16p")
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ u\\\\\\\"hello\\\\\\\"\",type=\"const char16_t \*\",thread-id=\"1\",has_more=\"0\"")

# Test that an char16_t[] isn't expanded to string when print char-array-as-string is "on"
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ u\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char16_t \*\",thread-id=\"1\",has_more=\"0\"")
# Test that an char16_t[] with escape chars is expanded to string when print char-array-as-string is "on"
self.runCmd("-var-create - * u16a")
self.expect("\^done,name=\"var\d+\",numchild=\"6\",value=\"u\\\\\\\"hello\\\\\\\"\",type=\"const char16_t \[6\]\",thread-id=\"1\",has_more=\"0\"")

# Test that an char32_t* is expanded to string when print char-array-as-string is "on"
self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"u\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char16_t \[10\]\",thread-id=\"1\",has_more=\"0\"")
# Test that an char32_t* with escape chars is expanded to string when print char-array-as-string is "on"
self.runCmd("-var-create - * u32p")
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ U\\\\\\\"hello\\\\\\\"\",type=\"const char32_t \*\",thread-id=\"1\",has_more=\"0\"")

# Test that an char32_t[] isn't expanded to string when print char-array-as-string is "on"
self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ U\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char32_t \*\",thread-id=\"1\",has_more=\"0\"")
# Test that an char32_t[] with escape chars is expanded to string when print char-array-as-string is "on"
self.runCmd("-var-create - * u32a")
self.expect("\^done,name=\"var\d+\",numchild=\"6\",value=\"U\\\\\\\"hello\\\\\\\"\",type=\"const char32_t \[6\]\",thread-id=\"1\",has_more=\"0\"")
self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"U\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char32_t \[10\]\",thread-id=\"1\",has_more=\"0\"")

# Test that -gdb-set print char-array-as-string fails if "on"/"off" isn't specified
self.runCmd("-gdb-set print char-array-as-string")
Expand Down
12 changes: 6 additions & 6 deletions lldb/test/tools/lldb-mi/variable/main.cpp
Expand Up @@ -57,12 +57,12 @@ var_list_children_test(void)
void
gdb_set_show_print_char_array_as_string_test(void)
{
const char *cp = "hello";
const char ca[] = "hello";
const char16_t *u16p = u"hello";
const char16_t u16a[] = u"hello";
const char32_t *u32p = U"hello";
const char32_t u32a[] = U"hello";
const char *cp = "\t\"hello\"\n";
const char ca[] = "\t\"hello\"\n";
const char16_t *u16p = u"\t\"hello\"\n";
const char16_t u16a[] = u"\t\"hello\"\n";
const char32_t *u32p = U"\t\"hello\"\n";
const char32_t u32a[] = U"\t\"hello\"\n";

// BP_gdb_set_show_print_char_array_as_string_test
}
Expand Down
2 changes: 1 addition & 1 deletion lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp
Expand Up @@ -285,7 +285,7 @@ CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(const lldb::SBValue &v
}
}

return utilValue.GetValue().Escape().AddSlashes();
return utilValue.GetValue().AddSlashes();
}

//++ ------------------------------------------------------------------------------------
Expand Down
20 changes: 7 additions & 13 deletions lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
Expand Up @@ -237,23 +237,20 @@ CMICmnLLDBUtilSBValue::GetSimpleValueCStringPointer(void) const
case lldb::eBasicTypeSignedChar:
case lldb::eBasicTypeUnsignedChar:
{
// FIXME Add slashes before double quotes
const CMIUtilString prefix(ReadCStringFromHostMemory<char>(child).AddSlashes());
const CMIUtilString prefix(ReadCStringFromHostMemory<char>(child));
// Note code that has const in will not show the text suffix to the string pointer
// i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this
// but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this
return CMIUtilString::Format("%s \"%s\"", value, prefix.c_str());
}
case lldb::eBasicTypeChar16:
{
// FIXME Add slashes before double quotes
const CMIUtilString prefix(ReadCStringFromHostMemory<char16_t>(child).AddSlashes());
const CMIUtilString prefix(ReadCStringFromHostMemory<char16_t>(child));
return CMIUtilString::Format("%s u\"%s\"", value, prefix.c_str());
}
case lldb::eBasicTypeChar32:
{
// FIXME Add slashes before double quotes
const CMIUtilString prefix(ReadCStringFromHostMemory<char32_t>(child).AddSlashes());
const CMIUtilString prefix(ReadCStringFromHostMemory<char32_t>(child));
return CMIUtilString::Format("%s U\"%s\"", value, prefix.c_str());
}
}
Expand All @@ -280,22 +277,19 @@ CMICmnLLDBUtilSBValue::GetSimpleValueCStringArray(void) const
case lldb::eBasicTypeSignedChar:
case lldb::eBasicTypeUnsignedChar:
{
// FIXME Add slashes before double quotes
const CMIUtilString prefix(ReadCStringFromHostMemory<char>(m_rValue, nChildren).AddSlashes());
const CMIUtilString prefix(ReadCStringFromHostMemory<char>(m_rValue, nChildren));
// TODO: to match char* it should be the following
// return CMIUtilString::Format("[%u] \"%s\"", nChildren, prefix.c_str());
return CMIUtilString::Format("\"%s\"", prefix.c_str());
}
case lldb::eBasicTypeChar16:
{
// FIXME Add slashes before double quotes
const CMIUtilString prefix(ReadCStringFromHostMemory<char16_t>(m_rValue, nChildren).AddSlashes());
const CMIUtilString prefix(ReadCStringFromHostMemory<char16_t>(m_rValue, nChildren));
return CMIUtilString::Format("u\"%s\"", prefix.c_str());
}
case lldb::eBasicTypeChar32:
{
// FIXME Add slashes before double quotes
const CMIUtilString prefix(ReadCStringFromHostMemory<char32_t>(m_rValue, nChildren).AddSlashes());
const CMIUtilString prefix(ReadCStringFromHostMemory<char32_t>(m_rValue, nChildren));
return CMIUtilString::Format("U\"%s\"", prefix.c_str());
}
}
Expand Down Expand Up @@ -472,7 +466,7 @@ CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(lldb::SBValue &vrValue, const M
return m_pUnkwn;
else if (ch == 0)
break;
result.append(CMIUtilString::ConvertToPrintableASCII(ch));
result.append(CMIUtilString::ConvertToPrintableASCII(ch, true /* bEscapeQuotes */));
addr += sizeof(ch);
}

Expand Down
67 changes: 56 additions & 11 deletions lldb/tools/lldb-mi/MIUtilString.cpp
Expand Up @@ -895,7 +895,7 @@ CMIUtilString::StripSlashes(void) const
}

CMIUtilString
CMIUtilString::ConvertToPrintableASCII(const char vChar)
CMIUtilString::ConvertToPrintableASCII(const char vChar, bool bEscapeQuotes)
{
switch (vChar)
{
Expand All @@ -917,6 +917,10 @@ CMIUtilString::ConvertToPrintableASCII(const char vChar)
return "\\e";
case '\\':
return "\\\\";
case '"':
if (bEscapeQuotes)
return "\\\"";
// fall thru
default:
if (::isprint(vChar))
return Format("%c", vChar);
Expand All @@ -926,24 +930,65 @@ CMIUtilString::ConvertToPrintableASCII(const char vChar)
}

CMIUtilString
CMIUtilString::ConvertToPrintableASCII(const char16_t vChar16)
CMIUtilString::ConvertCharValueToPrintableASCII(char vChar, bool bEscapeQuotes)
{
if (vChar16 == (char16_t)(char)vChar16 && ::isprint(vChar16))
switch (vChar)
{
case '\a':
return "\\a";
case '\b':
return "\\b";
case '\t':
return "\\t";
case '\n':
return "\\n";
case '\v':
return "\\v";
case '\f':
return "\\f";
case '\r':
return "\\r";
case '\033':
return "\\e";
case '\\':
return "\\\\";
case '"':
if (bEscapeQuotes)
return "\\\"";
// fall thru
default:
if (::isprint(vChar))
return Format("%c", vChar);
else
return CMIUtilString();
}
}

CMIUtilString
CMIUtilString::ConvertToPrintableASCII(const char16_t vChar16, bool bEscapeQuotes)
{
if (vChar16 == (char16_t)(char)vChar16)
{
// Convert char16_t to char (if possible)
return Format("%c", vChar16);
else
return Format("\\u%02" PRIx8 "%02" PRIx8,
CMIUtilString str = ConvertCharValueToPrintableASCII((char)vChar16, bEscapeQuotes);
if (str.length() > 0)
return str;
}
return Format("\\u%02" PRIx8 "%02" PRIx8,
(vChar16 >> 8) & 0xff, vChar16 & 0xff);
}

CMIUtilString
CMIUtilString::ConvertToPrintableASCII(const char32_t vChar32)
CMIUtilString::ConvertToPrintableASCII(const char32_t vChar32, bool bEscapeQuotes)
{
if (vChar32 == (char32_t)(char)vChar32 && ::isprint(vChar32))
if (vChar32 == (char32_t)(char)vChar32)
{
// Convert char32_t to char (if possible)
return Format("%c", vChar32);
else
return Format("\\U%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8,
CMIUtilString str = ConvertCharValueToPrintableASCII((char)vChar32, bEscapeQuotes);
if (str.length() > 0)
return str;
}
return Format("\\U%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8,
(vChar32 >> 24) & 0xff, (vChar32 >> 16) & 0xff,
(vChar32 >> 8) & 0xff, vChar32 & 0xff);
}
7 changes: 4 additions & 3 deletions lldb/tools/lldb-mi/MIUtilString.h
Expand Up @@ -34,9 +34,9 @@ class CMIUtilString : public std::string
static CMIUtilString FormatValist(const CMIUtilString &vrFormating, va_list vArgs);
static bool IsAllValidAlphaAndNumeric(const char *vpText);
static bool Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs);
static CMIUtilString ConvertToPrintableASCII(const char vChar);
static CMIUtilString ConvertToPrintableASCII(const char16_t vChar16);
static CMIUtilString ConvertToPrintableASCII(const char32_t vChar32);
static CMIUtilString ConvertToPrintableASCII(const char vChar, bool bEscapeQuotes = false);
static CMIUtilString ConvertToPrintableASCII(const char16_t vChar16, bool bEscapeQuotes = false);
static CMIUtilString ConvertToPrintableASCII(const char32_t vChar32, bool bEscapeQuotes = false);

// Methods:
public:
Expand Down Expand Up @@ -75,6 +75,7 @@ class CMIUtilString : public std::string
// Static method:
private:
static CMIUtilString FormatPriv(const CMIUtilString &vrFormat, va_list vArgs);
static CMIUtilString ConvertCharValueToPrintableASCII(char vChar, bool bEscapeQuotes);

// Methods:
private:
Expand Down

0 comments on commit b56c50f

Please sign in to comment.