[Lldb-commits] [lldb] r247899 - [lldb-mi] Fix the handling of files in -data-info-line and -symbol-list-lines.
Dawn Perchik via lldb-commits
lldb-commits at lists.llvm.org
Thu Sep 17 09:22:31 PDT 2015
Author: dperchik
Date: Thu Sep 17 11:22:30 2015
New Revision: 247899
URL: http://llvm.org/viewvc/llvm-project?rev=247899&view=rev
Log:
[lldb-mi] Fix the handling of files in -data-info-line and -symbol-list-lines.
This fixes -data-info-line and -symbol-list-lines to parse the filename
and line correctly when line entries don't have the optional column
number and the filename contains a Windows drive letter. It also fixes
-symbol-list-lines when code from header files is generated.
Reviewed by: abidh, ki.stfu
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D12115
Added:
lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.cpp
lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.h
lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test2.cpp
lldb/trunk/tools/lldb-mi/MIUtilParse.cpp
lldb/trunk/tools/lldb-mi/MIUtilParse.h
Modified:
lldb/trunk/test/tools/lldb-mi/symbol/Makefile
lldb/trunk/test/tools/lldb-mi/symbol/TestMiSymbol.py
lldb/trunk/test/tools/lldb-mi/symbol/main.cpp
lldb/trunk/tools/lldb-mi/CMakeLists.txt
lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp
lldb/trunk/tools/lldb-mi/MICmdCmdSymbol.cpp
lldb/trunk/tools/lldb-mi/MIUtilString.cpp
lldb/trunk/tools/lldb-mi/MIUtilString.h
Modified: lldb/trunk/test/tools/lldb-mi/symbol/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/symbol/Makefile?rev=247899&r1=247898&r2=247899&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/symbol/Makefile (original)
+++ lldb/trunk/test/tools/lldb-mi/symbol/Makefile Thu Sep 17 11:22:30 2015
@@ -1,5 +1,5 @@
LEVEL = ../../../make
-CXX_SOURCES := main.cpp
+CXX_SOURCES := main.cpp symbol_list_lines_inline_test.cpp symbol_list_lines_inline_test2.cpp
include $(LEVEL)/Makefile.rules
Modified: lldb/trunk/test/tools/lldb-mi/symbol/TestMiSymbol.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/symbol/TestMiSymbol.py?rev=247899&r1=247898&r2=247899&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/symbol/TestMiSymbol.py (original)
+++ lldb/trunk/test/tools/lldb-mi/symbol/TestMiSymbol.py Thu Sep 17 11:22:30 2015
@@ -39,6 +39,19 @@ class MiSymbolTestCase(lldbmi_testcase.M
self.runCmd("-symbol-list-lines main.cpp")
self.expect("\^done,lines=\[\{pc=\"0x0*%x\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"\d+\"\})+\]" % (addr, line))
+ # Test that -symbol-list-lines doesn't include lines from other sources
+ # by checking the first and last line, and making sure the other lines
+ # are between 30 and 39.
+ sline = line_number('symbol_list_lines_inline_test2.cpp', '// FUNC_gfunc2')
+ eline = line_number('symbol_list_lines_inline_test2.cpp', '// END_gfunc2')
+ self.runCmd("-symbol-list-lines symbol_list_lines_inline_test2.cpp")
+ self.expect("\^done,lines=\[\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"3\d\"\})*,\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}\]" % (sline, eline))
+ ##FIXME: This doesn't work for symbol_list_lines_inline_test.cpp due to clang bug llvm.org/pr24716
+ ##sline = line_number('symbol_list_lines_inline_test.cpp', '// FUNC_gfunc')
+ ##eline = line_number('symbol_list_lines_inline_test.cpp', '// STRUCT_s')
+ ##self.runCmd("-symbol-list-lines symbol_list_lines_inline_test.cpp")
+ ##self.expect("\^done,lines=\[\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"3\d\"\})*,\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}\]" % (sline, eline))
+
# Test that -symbol-list-lines fails when file doesn't exist
self.runCmd("-symbol-list-lines unknown_file")
self.expect("\^error,message=\"warning: No source filenames matched 'unknown_file'\. error: no source filenames matched any command arguments \"")
Modified: lldb/trunk/test/tools/lldb-mi/symbol/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/symbol/main.cpp?rev=247899&r1=247898&r2=247899&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/symbol/main.cpp (original)
+++ lldb/trunk/test/tools/lldb-mi/symbol/main.cpp Thu Sep 17 11:22:30 2015
@@ -7,8 +7,12 @@
//
//===----------------------------------------------------------------------===//
+extern int j;
+extern int gfunc(int i);
+extern int gfunc2(int i);
int
-main(int argc, char const *argv[])
+main()
{ // FUNC_main
- return 0;
+ int i = gfunc(j) + gfunc2(j);
+ return i == 0;
}
Added: lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.cpp?rev=247899&view=auto
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.cpp (added)
+++ lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.cpp Thu Sep 17 11:22:30 2015
@@ -0,0 +1,39 @@
+// Skip lines so we can make sure we're not seeing any lines from
+// symbol_list_lines_inline_test.h included in -symbol-list-lines
+// symbol_list_lines_inline_test.cpp, by checking that all the lines
+// are between 30 and 39.
+// line 5
+// line 6
+// line 7
+// line 8
+// line 9
+// line 10
+// line 11
+// line 12
+// line 13
+// line 14
+// line 15
+// line 16
+// line 17
+// line 18
+// line 19
+// line 20
+// line 21
+// line 22
+// line 23
+// line 24
+// line 25
+// line 26
+// line 27
+// line 28
+// line 29
+#include "symbol_list_lines_inline_test.h"
+int
+gfunc(int i)
+{ // FUNC_gfunc
+ return ns::ifunc(i);
+}
+namespace ns
+{
+S s; // STRUCT_s
+}
Added: lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.h?rev=247899&view=auto
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.h (added)
+++ lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.h Thu Sep 17 11:22:30 2015
@@ -0,0 +1,24 @@
+namespace ns
+{
+inline int
+ifunc(int i)
+{
+ return i;
+}
+struct S
+{
+ int a;
+ int b;
+ S()
+ : a(3)
+ , b(4)
+ {
+ }
+ int
+ mfunc()
+ {
+ return a + b;
+ }
+};
+extern S s;
+}
Added: lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test2.cpp?rev=247899&view=auto
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test2.cpp (added)
+++ lldb/trunk/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test2.cpp Thu Sep 17 11:22:30 2015
@@ -0,0 +1,38 @@
+// Skip lines so we can make sure we're not seeing any lines from
+// symbol_list_lines_inline_test.h included in -symbol-list-lines
+// symbol_list_lines_inline_test2.cpp, by checking that all the lines
+// are between 30 and 39.
+// line 5
+// line 6
+// line 7
+// line 8
+// line 9
+// line 10
+// line 11
+// line 12
+// line 13
+// line 14
+// line 15
+// line 16
+// line 17
+// line 18
+// line 19
+// line 20
+// line 21
+// line 22
+// line 23
+// line 24
+// line 25
+// line 26
+// line 27
+// line 28
+// line 29
+#include "symbol_list_lines_inline_test.h"
+int j = 2;
+int
+gfunc2(int i)
+{ // FUNC_gfunc2
+ i += ns::s.mfunc();
+ i += ns::ifunc(i);
+ return i == 0; // END_gfunc2
+}
Modified: lldb/trunk/tools/lldb-mi/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/CMakeLists.txt?rev=247899&r1=247898&r2=247899&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/CMakeLists.txt (original)
+++ lldb/trunk/tools/lldb-mi/CMakeLists.txt Thu Sep 17 11:22:30 2015
@@ -65,6 +65,7 @@ set(LLDB_MI_SOURCES
MIDriverBase.cpp
MIDriverMain.cpp
MIDriverMgr.cpp
+ MIUtilParse.cpp
MIUtilDateTimeStd.cpp
MIUtilDebug.cpp
MIUtilFileStd.cpp
Modified: lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp?rev=247899&r1=247898&r2=247899&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp Thu Sep 17 11:22:30 2015
@@ -42,6 +42,7 @@
#include "MICmdArgValConsume.h"
#include "MICmnLLDBDebugSessionInfoVarObj.h"
#include "MICmnLLDBUtilSBValue.h"
+#include "MIUtilParse.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdDataEvaluateExpression constructor.
@@ -1642,6 +1643,53 @@ CMICmdCmdDataInfoLine::Execute()
}
//++ ------------------------------------------------------------------------------------
+// Details: Helper function for parsing a line entry returned from lldb for the command:
+// target modules lookup -v <location>
+// where the line entry is of the format:
+// LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/file:3[:1]
+// start end file line column(opt)
+// Args: input - (R) Input string to parse.
+// start - (W) String representing the start address.
+// end - (W) String representing the end address.
+// file - (W) String representing the file.
+// line - (W) String representing the line.
+// Return: bool - True = input was parsed successfully, false = input could not be parsed.
+// Throws: None.
+//--
+static bool
+ParseLLDBLineEntry(const char *input, CMIUtilString &start, CMIUtilString &end,
+ CMIUtilString &file, CMIUtilString &line)
+{
+ // Note: Ambiguities arise because the column is optional, and
+ // because : can appear in filenames or as a byte in a multibyte
+ // UTF8 character. We keep those cases to a minimum by using regex
+ // to work on the string from both the left and right, so that what
+ // is remains is assumed to be the filename.
+
+ // Match LineEntry using regex.
+ static MIUtilParse::CRegexParser g_lineentry_nocol_regex(
+ "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$");
+ static MIUtilParse::CRegexParser g_lineentry_col_regex(
+ "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$");
+ // ^1=start ^2=end ^3=f ^4=line ^5=:col(opt)
+
+ MIUtilParse::CRegexParser::Match match(6);
+
+ // First try matching the LineEntry with the column,
+ // then try without the column.
+ const bool ok = g_lineentry_col_regex.Execute(input, match) ||
+ g_lineentry_nocol_regex.Execute(input, match);
+ if (ok)
+ {
+ start = match.GetMatchAtIndex(1);
+ end = match.GetMatchAtIndex(2);
+ file = match.GetMatchAtIndex(3);
+ line = match.GetMatchAtIndex(4);
+ }
+ return ok;
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
@@ -1672,58 +1720,25 @@ CMICmdCmdDataInfoLine::Acknowledge()
// String looks like:
// LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
const CMIUtilString &rLine(vecLines[i]);
+ CMIUtilString strStart;
+ CMIUtilString strEnd;
+ CMIUtilString strFile;
+ CMIUtilString strLine;
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^^^^^^^^^ -- property
- const size_t nPropertyStartPos = rLine.find_first_not_of(' ');
- const size_t nPropertyEndPos = rLine.find(':');
- const size_t nPropertyLen = nPropertyEndPos - nPropertyStartPos;
- const CMIUtilString strProperty(rLine.substr(nPropertyStartPos, nPropertyLen).c_str());
-
- // Skip all except LineEntry
- if (!CMIUtilString::Compare(strProperty, "LineEntry"))
+ if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile, strLine))
continue;
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^^^^^^^^^^^^^^^^^^ -- start address
- const size_t nStartAddressStartPos = rLine.find('[');
- const size_t nStartAddressEndPos = rLine.find('-');
- const size_t nStartAddressLen = nStartAddressEndPos - nStartAddressStartPos - 1;
- const CMIUtilString strStartAddress(rLine.substr(nStartAddressStartPos + 1, nStartAddressLen).c_str());
- const CMICmnMIValueConst miValueConst(strStartAddress);
+ const CMICmnMIValueConst miValueConst(strStart);
const CMICmnMIValueResult miValueResult("start", miValueConst);
- CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
-
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^^^^^^^^^^^^^^^^^^ -- end address
- const size_t nEndAddressEndPos = rLine.find(')');
- const size_t nEndAddressLen = nEndAddressEndPos - nStartAddressEndPos - 1;
- const CMIUtilString strEndAddress(rLine.substr(nStartAddressEndPos + 1, nEndAddressLen).c_str());
- const CMICmnMIValueConst miValueConst2(strEndAddress);
+ CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken,
+ CMICmnMIResultRecord::eResultClass_Done,
+ miValueResult);
+ const CMICmnMIValueConst miValueConst2(strEnd);
const CMICmnMIValueResult miValueResult2("end", miValueConst2);
miRecordResult.Add(miValueResult2);
-
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^^^^^^^^^^^^^ -- file
- // ^ -- line
- // ^ -- column (optional)
- const size_t nFileStartPos = rLine.find_first_not_of(' ', nEndAddressEndPos + 2);
- const size_t nFileOrLineEndPos = rLine.rfind(':');
- const size_t nFileOrLineStartPos = rLine.rfind(':', nFileOrLineEndPos - 1);
- const size_t nFileEndPos = nFileStartPos < nFileOrLineStartPos ? nFileOrLineStartPos : nFileOrLineEndPos;
- const size_t nFileLen = nFileEndPos - nFileStartPos;
- const CMIUtilString strFile(rLine.substr(nFileStartPos, nFileLen).c_str());
const CMICmnMIValueConst miValueConst3(strFile);
const CMICmnMIValueResult miValueResult3("file", miValueConst3);
miRecordResult.Add(miValueResult3);
-
- // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1]
- // ^ -- line
- const size_t nLineStartPos = nFileEndPos + 1;
- const size_t nLineEndPos = rLine.find(':', nLineStartPos);
- const size_t nLineLen = nLineEndPos != std::string::npos ? nLineEndPos - nLineStartPos
- : std::string::npos;
- const CMIUtilString strLine(rLine.substr(nLineStartPos, nLineLen).c_str());
const CMICmnMIValueConst miValueConst4(strLine);
const CMICmnMIValueResult miValueResult4("line", miValueConst4);
miRecordResult.Add(miValueResult4);
Modified: lldb/trunk/tools/lldb-mi/MICmdCmdSymbol.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmdCmdSymbol.cpp?rev=247899&r1=247898&r2=247899&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmdCmdSymbol.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MICmdCmdSymbol.cpp Thu Sep 17 11:22:30 2015
@@ -19,6 +19,7 @@
#include "MICmnMIResultRecord.h"
#include "MICmnMIValueList.h"
#include "MICmnMIValueTuple.h"
+#include "MIUtilParse.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdSymbolListLines constructor.
@@ -81,6 +82,10 @@ CMICmdCmdSymbolListLines::Execute()
CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile);
const CMIUtilString &strFilePath(pArgFile->GetValue());
+ // FIXME: this won't work for header files! To try and use existing
+ // commands to get this to work for header files would be too slow.
+ // Instead, this code should be rewritten to use APIs and/or support
+ // should be added to lldb which would work for header files.
const CMIUtilString strCmd(CMIUtilString::Format("target modules dump line-table \"%s\"", strFilePath.AddSlashes().c_str()));
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
@@ -91,6 +96,77 @@ CMICmdCmdSymbolListLines::Execute()
}
//++ ------------------------------------------------------------------------------------
+// Details: Helper function for parsing the header returned from lldb for the command:
+// target modules dump line-table <file>
+// where the header is of the format:
+// Line table for /path/to/file in `/path/to/module
+// Args: input - (R) Input string to parse.
+// file - (W) String representing the file.
+// Return: bool - True = input was parsed successfully, false = input could not be parsed.
+// Throws: None.
+//--
+static bool
+ParseLLDBLineAddressHeader(const char *input, CMIUtilString &file)
+{
+ // Match LineEntry using regex.
+ static MIUtilParse::CRegexParser g_lineentry_header_regex(
+ "^ *Line table for (.+) in `(.+)$");
+ // ^1=file ^2=module
+
+ MIUtilParse::CRegexParser::Match match(3);
+
+ const bool ok = g_lineentry_header_regex.Execute(input, match);
+ if (ok)
+ file = match.GetMatchAtIndex(1);
+ return ok;
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: Helper function for parsing a line entry returned from lldb for the command:
+// target modules dump line-table <file>
+// where the line entry is of the format:
+// 0x0000000100000e70: /path/to/file:3002[:4]
+// addr file line column(opt)
+// Args: input - (R) Input string to parse.
+// addr - (W) String representing the pc address.
+// file - (W) String representing the file.
+// line - (W) String representing the line.
+// Return: bool - True = input was parsed successfully, false = input could not be parsed.
+// Throws: None.
+//--
+static bool
+ParseLLDBLineAddressEntry(const char *input, CMIUtilString &addr,
+ CMIUtilString &file, CMIUtilString &line)
+{
+ // Note: Ambiguities arise because the column is optional, and
+ // because : can appear in filenames or as a byte in a multibyte
+ // UTF8 character. We keep those cases to a minimum by using regex
+ // to work on the string from both the left and right, so that what
+ // is remains is assumed to be the filename.
+
+ // Match LineEntry using regex.
+ static MIUtilParse::CRegexParser g_lineentry_nocol_regex(
+ "^ *(0x[0-9a-fA-F]+): (.+):([0-9]+)$");
+ static MIUtilParse::CRegexParser g_lineentry_col_regex(
+ "^ *(0x[0-9a-fA-F]+): (.+):([0-9]+):[0-9]+$");
+ // ^1=addr ^2=f ^3=line ^4=:col(opt)
+
+ MIUtilParse::CRegexParser::Match match(5);
+
+ // First try matching the LineEntry with the column,
+ // then try without the column.
+ const bool ok = g_lineentry_col_regex.Execute(input, match) ||
+ g_lineentry_nocol_regex.Execute(input, match);
+ if (ok)
+ {
+ addr = match.GetMatchAtIndex(1);
+ file = match.GetMatchAtIndex(2);
+ line = match.GetMatchAtIndex(3);
+ }
+ return ok;
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
@@ -117,29 +193,43 @@ CMICmdCmdSymbolListLines::Acknowledge()
const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
const MIuint nLines(strLldbMsg.SplitLines(vecLines));
+ // Parse the file from the header.
+ const CMIUtilString &rWantFile(vecLines[0]);
+ CMIUtilString strWantFile;
+ if (!ParseLLDBLineAddressHeader(rWantFile.c_str(), strWantFile))
+ {
+ // Unexpected error - parsing failed.
+ // MI print "%s^error,msg=\"Command '-symbol-list-lines'. Error: Line address header is absent or has an unknown format.\""
+ const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), "Line address header is absent or has an unknown format."));
+ const CMICmnMIValueResult miValueResult("msg", miValueConst);
+ const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
+ m_miResultRecord = miRecordResult;
+
+ return MIstatus::success;
+ }
+
+ // Parse the line address entries.
CMICmnMIValueList miValueList(true);
for (MIuint i = 1; i < nLines; ++i)
{
// String looks like:
// 0x0000000100000e70: /path/to/file:3[:4]
const CMIUtilString &rLine(vecLines[i]);
+ CMIUtilString strAddr;
+ CMIUtilString strFile;
+ CMIUtilString strLine;
+
+ if (!ParseLLDBLineAddressEntry(rLine.c_str(), strAddr, strFile, strLine))
+ continue;
+
+ // Skip entries which don't match the desired source.
+ if (strWantFile != strFile)
+ continue;
- // 0x0000000100000e70: /path/to/file:3[:4]
- // ^^^^^^^^^^^^^^^^^^ -- pc
- const size_t nAddrEndPos = rLine.find(':');
- const CMIUtilString strAddr(rLine.substr(0, nAddrEndPos).c_str());
const CMICmnMIValueConst miValueConst(strAddr);
const CMICmnMIValueResult miValueResult("pc", miValueConst);
CMICmnMIValueTuple miValueTuple(miValueResult);
- // 0x0000000100000e70: /path/to/file:3[:4]
- // ^ -- line
- const size_t nLineOrColumnStartPos = rLine.rfind(':');
- const CMIUtilString strLineOrColumn(rLine.substr(nLineOrColumnStartPos + 1).c_str());
- const size_t nPathOrLineStartPos = rLine.rfind(':', nLineOrColumnStartPos - 1);
- const size_t nPathOrLineLen = nLineOrColumnStartPos - nPathOrLineStartPos - 1;
- const CMIUtilString strPathOrLine(rLine.substr(nPathOrLineStartPos + 1, nPathOrLineLen).c_str());
- const CMIUtilString strLine(strPathOrLine.IsNumber() ? strPathOrLine : strLineOrColumn);
const CMICmnMIValueConst miValueConst2(strLine);
const CMICmnMIValueResult miValueResult2("line", miValueConst2);
miValueTuple.Add(miValueResult2);
Added: lldb/trunk/tools/lldb-mi/MIUtilParse.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIUtilParse.cpp?rev=247899&view=auto
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilParse.cpp (added)
+++ lldb/trunk/tools/lldb-mi/MIUtilParse.cpp Thu Sep 17 11:22:30 2015
@@ -0,0 +1,75 @@
+//===-- MIUtilParse.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Third party headers:
+#include <memory>
+
+// In-house headers:
+#include "MIUtilParse.h"
+
+//++ ------------------------------------------------------------------------------------
+// Details: CRegexParser constructor.
+// Type: Method.
+// Args: regexStr - Pointer to the regular expression to compile.
+// Return: None.
+// Throws: None.
+//--
+MIUtilParse::CRegexParser::CRegexParser(const char *regexStr)
+ : m_isValid(llvm_regcomp(&m_emma, regexStr, REG_EXTENDED) == 0)
+{
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CRegexParser destructor.
+// Type: Method.
+// Args: None.
+// Return: None.
+// Throws: None.
+//--
+MIUtilParse::CRegexParser::~CRegexParser()
+{
+ // Free up memory held within regex.
+ if (m_isValid)
+ llvm_regfree(&m_emma);
+}
+
+//++ ------------------------------------------------------------------------------------
+// Details: CRegexParser regex executer.
+// Match the input against the regular expression. Return an error
+// if the number of matches is less than minMatches. If the default
+// minMatches value of 0 is passed, an error will be returned if
+// the number of matches is less than the maxMatches value used to
+// initialize Match.
+// Type: Method.
+// Args: input (R) - Pointer to UTF8 text data to be parsed.
+// match (RW) - Reference to Match class.
+// minMatches (R) - Minimum number of regex matches expected.
+// Return: bool - True = minimum matches were met,
+// false = minimum matches were not met or regex failed.
+// Throws: None.
+//--
+bool
+MIUtilParse::CRegexParser::Execute(const char *input, Match& match, size_t minMatches)
+{
+ if (!m_isValid)
+ return false;
+
+ std::unique_ptr<llvm_regmatch_t[]> matches(new llvm_regmatch_t[match.m_maxMatches]); // Array of matches
+
+ if (llvm_regexec(&m_emma, input, match.m_maxMatches, matches.get(), 0) != 0)
+ return false;
+
+ size_t i;
+ for (i = 0; i < match.m_maxMatches && matches[i].rm_so >= 0; i++)
+ {
+ const int n = matches[i].rm_eo - matches[i].rm_so;
+ match.m_matchStrs[i].assign(input + matches[i].rm_so, n);
+ }
+ return i >= minMatches;
+}
Added: lldb/trunk/tools/lldb-mi/MIUtilParse.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIUtilParse.h?rev=247899&view=auto
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilParse.h (added)
+++ lldb/trunk/tools/lldb-mi/MIUtilParse.h Thu Sep 17 11:22:30 2015
@@ -0,0 +1,93 @@
+//===-- MIUtilParse.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+// Third party headers:
+#include "../lib/Support/regex_impl.h"
+
+// In-house headers:
+#include "MIUtilString.h"
+
+namespace MIUtilParse
+{
+
+//++ ============================================================================
+// Details: MI common code utility class. Used to parse the output
+// returned from lldb commands using regex.
+//--
+class CRegexParser
+{
+ public:
+ // Helper class for keeping track of regex matches.
+ class Match
+ {
+ friend CRegexParser;
+ public:
+ /* ctor */ explicit Match(size_t nmatches)
+ : m_matchStrs(nmatches), m_maxMatches(nmatches)
+ {
+ }
+ size_t
+ GetMatchCount() const
+ {
+ return m_matchStrs.size();
+ }
+ CMIUtilString
+ GetMatchAtIndex(size_t i) const
+ {
+ if (m_matchStrs.size() > i)
+ return m_matchStrs[i];
+ return CMIUtilString();
+ }
+ private:
+ CMIUtilString::VecString_t m_matchStrs;
+ const size_t m_maxMatches;
+ };
+
+ // Methods:
+ // Compile the regular expression.
+ /* ctor */ explicit CRegexParser(const char *regexStr);
+
+ // Free the memory used by the regular expression.
+ /* dtor */ ~CRegexParser();
+
+ // No copies
+ CRegexParser(const CRegexParser&) = delete;
+ void operator=(CRegexParser&) = delete;
+
+ // Return the match at the index.
+ int
+ GetMatchCount(const Match& match) const
+ {
+ if (m_isValid)
+ return match.GetMatchCount();
+ return 0;
+ }
+
+ bool
+ IsValid() const
+ {
+ return m_isValid;
+ }
+
+ // Match the input against the regular expression. Return an error
+ // if the number of matches is less than minMatches. If the default
+ // minMatches value of 0 is passed, an error will be returned if
+ // the number of matches is less than the maxMatches value used to
+ // initialize Match.
+ bool
+ Execute(const char *input, Match& match, size_t minMatches = 0);
+
+ private:
+ llvm_regex_t m_emma;
+ const bool m_isValid;
+};
+
+}
Modified: lldb/trunk/tools/lldb-mi/MIUtilString.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIUtilString.cpp?rev=247899&r1=247898&r2=247899&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilString.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MIUtilString.cpp Thu Sep 17 11:22:30 2015
@@ -55,6 +55,19 @@ CMIUtilString::CMIUtilString(const char
}
//++ ------------------------------------------------------------------------------------
+// Details: CMIUtilString constructor.
+// Type: Method.
+// Args: vpData - Pointer to UTF8 text data.
+// nLen - Length of string.
+// Return: None.
+// Throws: None.
+//--
+CMIUtilString::CMIUtilString(const char *vpData, size_t nLen)
+ : std::string(vpData, nLen)
+{
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: CMIUtilString assignment operator.
// Type: Method.
// Args: vpRhs - Pointer to UTF8 text data.
Modified: lldb/trunk/tools/lldb-mi/MIUtilString.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIUtilString.h?rev=247899&r1=247898&r2=247899&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilString.h (original)
+++ lldb/trunk/tools/lldb-mi/MIUtilString.h Thu Sep 17 11:22:30 2015
@@ -44,6 +44,7 @@ class CMIUtilString : public std::string
/* ctor */ CMIUtilString();
/* ctor */ CMIUtilString(const char *vpData);
/* ctor */ CMIUtilString(const char *const *vpData);
+ /* ctor */ CMIUtilString(const char *vpData, size_t nLen);
//
bool ExtractNumber(MIint64 &vwrNumber) const;
CMIUtilString FindAndReplace(const CMIUtilString &vFind, const CMIUtilString &vReplaceWith) const;
More information about the lldb-commits
mailing list