Dawn, this breaks the OS X Xcode build because it can’t find “../lib/Support/regex_impl.h”. I only see that header in llvm/lib, but so far lldb-mi hasn’t had any LLVM dependencies and it doesn’t even have the right header search paths in Xcode. Should we be adding the LLVM headers as search paths?
Sean > On Sep 17, 2015, at 9:22 AM, Dawn Perchik via lldb-commits > <lldb-commits@lists.llvm.org> wrote: > > 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; > > > _______________________________________________ > lldb-commits mailing list > lldb-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits