130fdc8d8SChris Lattner //===-- SourceManager.cpp ---------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 10*93a64300SDaniel Malea #include "lldb/lldb-python.h" 11*93a64300SDaniel Malea 1230fdc8d8SChris Lattner #include "lldb/Core/SourceManager.h" 1330fdc8d8SChris Lattner 1430fdc8d8SChris Lattner // C Includes 1530fdc8d8SChris Lattner // C++ Includes 1630fdc8d8SChris Lattner // Other libraries and framework includes 1730fdc8d8SChris Lattner // Project includes 1830fdc8d8SChris Lattner #include "lldb/Core/DataBuffer.h" 19e37d605eSJim Ingham #include "lldb/Core/Debugger.h" 201f746071SGreg Clayton #include "lldb/Core/Module.h" 2130fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 22b6d70ebcSSean Callanan #include "lldb/Symbol/ClangNamespaceDecl.h" 231f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 241f746071SGreg Clayton #include "lldb/Symbol/Function.h" 25176761e5SGreg Clayton #include "lldb/Symbol/SymbolContext.h" 267e14f91dSGreg Clayton #include "lldb/Target/Target.h" 2730fdc8d8SChris Lattner 2830fdc8d8SChris Lattner using namespace lldb_private; 2930fdc8d8SChris Lattner 3030fdc8d8SChris Lattner static inline bool is_newline_char(char ch) 3130fdc8d8SChris Lattner { 3230fdc8d8SChris Lattner return ch == '\n' || ch == '\r'; 3330fdc8d8SChris Lattner } 3430fdc8d8SChris Lattner 3530fdc8d8SChris Lattner 3630fdc8d8SChris Lattner //---------------------------------------------------------------------- 3730fdc8d8SChris Lattner // SourceManager constructor 3830fdc8d8SChris Lattner //---------------------------------------------------------------------- 39e37d605eSJim Ingham SourceManager::SourceManager(Target &target) : 4030fdc8d8SChris Lattner m_last_file_sp (), 4130fdc8d8SChris Lattner m_last_file_line (0), 4230fdc8d8SChris Lattner m_last_file_context_before (0), 43b7f6b2faSJim Ingham m_last_file_context_after (10), 44f3277750SJim Ingham m_default_set(false), 45e37d605eSJim Ingham m_target (&target), 46e37d605eSJim Ingham m_debugger(NULL) 47e37d605eSJim Ingham { 48e37d605eSJim Ingham m_debugger = &(m_target->GetDebugger()); 49e37d605eSJim Ingham } 50e37d605eSJim Ingham 51e37d605eSJim Ingham SourceManager::SourceManager(Debugger &debugger) : 52e37d605eSJim Ingham m_last_file_sp (), 53e37d605eSJim Ingham m_last_file_line (0), 54e37d605eSJim Ingham m_last_file_context_before (0), 55e37d605eSJim Ingham m_last_file_context_after (10), 56f3277750SJim Ingham m_default_set(false), 57e37d605eSJim Ingham m_target (NULL), 58e37d605eSJim Ingham m_debugger (&debugger) 5930fdc8d8SChris Lattner { 6030fdc8d8SChris Lattner } 6130fdc8d8SChris Lattner 6230fdc8d8SChris Lattner //---------------------------------------------------------------------- 6330fdc8d8SChris Lattner // Destructor 6430fdc8d8SChris Lattner //---------------------------------------------------------------------- 6530fdc8d8SChris Lattner SourceManager::~SourceManager() 6630fdc8d8SChris Lattner { 6730fdc8d8SChris Lattner } 6830fdc8d8SChris Lattner 6930fdc8d8SChris Lattner size_t 7030fdc8d8SChris Lattner SourceManager::DisplaySourceLines 7130fdc8d8SChris Lattner ( 7230fdc8d8SChris Lattner const FileSpec &file_spec, 7330fdc8d8SChris Lattner uint32_t line, 7430fdc8d8SChris Lattner uint32_t context_before, 7530fdc8d8SChris Lattner uint32_t context_after, 7630fdc8d8SChris Lattner Stream *s 7730fdc8d8SChris Lattner ) 7830fdc8d8SChris Lattner { 79b7f6b2faSJim Ingham m_last_file_sp = GetFile (file_spec); 8030fdc8d8SChris Lattner m_last_file_line = line + context_after + 1; 8130fdc8d8SChris Lattner m_last_file_context_before = context_before; 8230fdc8d8SChris Lattner m_last_file_context_after = context_after; 8330fdc8d8SChris Lattner if (m_last_file_sp.get()) 8430fdc8d8SChris Lattner return m_last_file_sp->DisplaySourceLines (line, context_before, context_after, s); 8530fdc8d8SChris Lattner 8630fdc8d8SChris Lattner return 0; 8730fdc8d8SChris Lattner } 8830fdc8d8SChris Lattner 8930fdc8d8SChris Lattner SourceManager::FileSP 90b7f6b2faSJim Ingham SourceManager::GetFile (const FileSpec &file_spec) 9130fdc8d8SChris Lattner { 9230fdc8d8SChris Lattner FileSP file_sp; 93e37d605eSJim Ingham file_sp = m_debugger->GetSourceFileCache().FindSourceFile (file_spec); 9464bab489SJohnny Chen // If file_sp is no good or it points to a non-existent file, reset it. 9564bab489SJohnny Chen if (!file_sp || !file_sp->GetFileSpec().Exists()) 9630fdc8d8SChris Lattner { 97b7f6b2faSJim Ingham file_sp.reset (new File (file_spec, m_target)); 98e37d605eSJim Ingham 99e37d605eSJim Ingham m_debugger->GetSourceFileCache().AddSourceFile(file_sp); 10030fdc8d8SChris Lattner } 10130fdc8d8SChris Lattner return file_sp; 10230fdc8d8SChris Lattner } 10330fdc8d8SChris Lattner 10430fdc8d8SChris Lattner size_t 10530fdc8d8SChris Lattner SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile 10630fdc8d8SChris Lattner ( 10730fdc8d8SChris Lattner uint32_t line, 10830fdc8d8SChris Lattner uint32_t context_before, 10930fdc8d8SChris Lattner uint32_t context_after, 11030fdc8d8SChris Lattner const char* current_line_cstr, 111176761e5SGreg Clayton Stream *s, 112176761e5SGreg Clayton const SymbolContextList *bp_locs 11330fdc8d8SChris Lattner ) 11430fdc8d8SChris Lattner { 115e37d605eSJim Ingham size_t return_value = 0; 11630fdc8d8SChris Lattner if (line == 0) 11730fdc8d8SChris Lattner { 11830fdc8d8SChris Lattner if (m_last_file_line != 0 11930fdc8d8SChris Lattner && m_last_file_line != UINT32_MAX) 12030fdc8d8SChris Lattner line = m_last_file_line + context_before; 12130fdc8d8SChris Lattner else 12230fdc8d8SChris Lattner line = 1; 12330fdc8d8SChris Lattner } 12430fdc8d8SChris Lattner 12530fdc8d8SChris Lattner m_last_file_line = line + context_after + 1; 12630fdc8d8SChris Lattner m_last_file_context_before = context_before; 12730fdc8d8SChris Lattner m_last_file_context_after = context_after; 12830fdc8d8SChris Lattner 12930fdc8d8SChris Lattner if (context_before == UINT32_MAX) 13030fdc8d8SChris Lattner context_before = 0; 13130fdc8d8SChris Lattner if (context_after == UINT32_MAX) 13230fdc8d8SChris Lattner context_after = 10; 13330fdc8d8SChris Lattner 13430fdc8d8SChris Lattner if (m_last_file_sp.get()) 13530fdc8d8SChris Lattner { 13630fdc8d8SChris Lattner const uint32_t start_line = line <= context_before ? 1 : line - context_before; 13730fdc8d8SChris Lattner const uint32_t end_line = line + context_after; 13830fdc8d8SChris Lattner uint32_t curr_line; 13930fdc8d8SChris Lattner for (curr_line = start_line; curr_line <= end_line; ++curr_line) 14030fdc8d8SChris Lattner { 14130fdc8d8SChris Lattner if (!m_last_file_sp->LineIsValid (curr_line)) 14230fdc8d8SChris Lattner { 14330fdc8d8SChris Lattner m_last_file_line = UINT32_MAX; 14430fdc8d8SChris Lattner break; 14530fdc8d8SChris Lattner } 14630fdc8d8SChris Lattner 147176761e5SGreg Clayton char prefix[32] = ""; 148176761e5SGreg Clayton if (bp_locs) 149176761e5SGreg Clayton { 150176761e5SGreg Clayton uint32_t bp_count = bp_locs->NumLineEntriesWithLine (curr_line); 151176761e5SGreg Clayton 152176761e5SGreg Clayton if (bp_count > 0) 153176761e5SGreg Clayton ::snprintf (prefix, sizeof (prefix), "[%u] ", bp_count); 154176761e5SGreg Clayton else 155176761e5SGreg Clayton ::snprintf (prefix, sizeof (prefix), " "); 156176761e5SGreg Clayton } 157176761e5SGreg Clayton 158e37d605eSJim Ingham return_value += s->Printf("%s%2.2s %-4u\t", 159176761e5SGreg Clayton prefix, 160176761e5SGreg Clayton curr_line == line ? current_line_cstr : "", 161176761e5SGreg Clayton curr_line); 162e37d605eSJim Ingham size_t this_line_size = m_last_file_sp->DisplaySourceLines (curr_line, 0, 0, s); 163e37d605eSJim Ingham if (this_line_size == 0) 16430fdc8d8SChris Lattner { 16530fdc8d8SChris Lattner m_last_file_line = UINT32_MAX; 16630fdc8d8SChris Lattner break; 16730fdc8d8SChris Lattner } 168e37d605eSJim Ingham else 169e37d605eSJim Ingham return_value += this_line_size; 17030fdc8d8SChris Lattner } 17130fdc8d8SChris Lattner } 172e37d605eSJim Ingham return return_value; 17330fdc8d8SChris Lattner } 17430fdc8d8SChris Lattner 17530fdc8d8SChris Lattner size_t 17630fdc8d8SChris Lattner SourceManager::DisplaySourceLinesWithLineNumbers 17730fdc8d8SChris Lattner ( 17830fdc8d8SChris Lattner const FileSpec &file_spec, 17930fdc8d8SChris Lattner uint32_t line, 18030fdc8d8SChris Lattner uint32_t context_before, 18130fdc8d8SChris Lattner uint32_t context_after, 18230fdc8d8SChris Lattner const char* current_line_cstr, 183176761e5SGreg Clayton Stream *s, 184176761e5SGreg Clayton const SymbolContextList *bp_locs 18530fdc8d8SChris Lattner ) 18630fdc8d8SChris Lattner { 18730fdc8d8SChris Lattner bool same_as_previous = m_last_file_sp && m_last_file_sp->FileSpecMatches (file_spec); 18830fdc8d8SChris Lattner 18930fdc8d8SChris Lattner if (!same_as_previous) 190b7f6b2faSJim Ingham m_last_file_sp = GetFile (file_spec); 19130fdc8d8SChris Lattner 19230fdc8d8SChris Lattner if (line == 0) 19330fdc8d8SChris Lattner { 19430fdc8d8SChris Lattner if (!same_as_previous) 19530fdc8d8SChris Lattner m_last_file_line = 0; 19630fdc8d8SChris Lattner } 19730fdc8d8SChris Lattner 198176761e5SGreg Clayton return DisplaySourceLinesWithLineNumbersUsingLastFile (line, context_before, context_after, current_line_cstr, s, bp_locs); 19930fdc8d8SChris Lattner } 20030fdc8d8SChris Lattner 20130fdc8d8SChris Lattner size_t 202176761e5SGreg Clayton SourceManager::DisplayMoreWithLineNumbers (Stream *s, const SymbolContextList *bp_locs) 20330fdc8d8SChris Lattner { 20430fdc8d8SChris Lattner if (m_last_file_sp) 20530fdc8d8SChris Lattner { 20630fdc8d8SChris Lattner if (m_last_file_line == UINT32_MAX) 20730fdc8d8SChris Lattner return 0; 208e37d605eSJim Ingham return DisplaySourceLinesWithLineNumbersUsingLastFile (0, m_last_file_context_before, m_last_file_context_after, "", s, bp_locs); 20930fdc8d8SChris Lattner } 21030fdc8d8SChris Lattner return 0; 21130fdc8d8SChris Lattner } 21230fdc8d8SChris Lattner 213b7f6b2faSJim Ingham bool 214b7f6b2faSJim Ingham SourceManager::SetDefaultFileAndLine (const FileSpec &file_spec, uint32_t line) 215b7f6b2faSJim Ingham { 216b7f6b2faSJim Ingham FileSP old_file_sp = m_last_file_sp; 217b7f6b2faSJim Ingham m_last_file_sp = GetFile (file_spec); 218f3277750SJim Ingham 219f3277750SJim Ingham m_default_set = true; 220b7f6b2faSJim Ingham if (m_last_file_sp) 221b7f6b2faSJim Ingham { 222b7f6b2faSJim Ingham m_last_file_line = line; 223b7f6b2faSJim Ingham return true; 224b7f6b2faSJim Ingham } 225b7f6b2faSJim Ingham else 226b7f6b2faSJim Ingham { 227b7f6b2faSJim Ingham m_last_file_sp = old_file_sp; 228b7f6b2faSJim Ingham return false; 229b7f6b2faSJim Ingham } 230b7f6b2faSJim Ingham } 231b7f6b2faSJim Ingham 232b7f6b2faSJim Ingham bool 233b7f6b2faSJim Ingham SourceManager::GetDefaultFileAndLine (FileSpec &file_spec, uint32_t &line) 234b7f6b2faSJim Ingham { 235b7f6b2faSJim Ingham if (m_last_file_sp) 236b7f6b2faSJim Ingham { 237b7f6b2faSJim Ingham file_spec = m_last_file_sp->GetFileSpec(); 238b7f6b2faSJim Ingham line = m_last_file_line; 239b7f6b2faSJim Ingham return true; 240b7f6b2faSJim Ingham } 241f3277750SJim Ingham else if (!m_default_set) 242f3277750SJim Ingham { 243f3277750SJim Ingham // If nobody has set the default file and line then try here. If there's no executable, then we 244f3277750SJim Ingham // will try again later when there is one. Otherwise, if we can't find it we won't look again, 245f3277750SJim Ingham // somebody will have to set it (for instance when we stop somewhere...) 246f3277750SJim Ingham Module *executable_ptr = m_target->GetExecutableModulePointer(); 247f3277750SJim Ingham if (executable_ptr) 248f3277750SJim Ingham { 249f3277750SJim Ingham SymbolContextList sc_list; 250f3277750SJim Ingham uint32_t num_matches; 251f3277750SJim Ingham ConstString main_name("main"); 252f3277750SJim Ingham bool symbols_okay = false; // Force it to be a debug symbol. 2539df05fbbSSean Callanan bool inlines_okay = true; 254f3277750SJim Ingham bool append = false; 2559df05fbbSSean Callanan num_matches = executable_ptr->FindFunctions (main_name, NULL, lldb::eFunctionNameTypeBase, inlines_okay, symbols_okay, append, sc_list); 256f3277750SJim Ingham for (uint32_t idx = 0; idx < num_matches; idx++) 257f3277750SJim Ingham { 258f3277750SJim Ingham SymbolContext sc; 259f3277750SJim Ingham sc_list.GetContextAtIndex(idx, sc); 2606f6bf26aSGreg Clayton if (sc.function) 261f3277750SJim Ingham { 2626f6bf26aSGreg Clayton lldb_private::LineEntry line_entry; 2636f6bf26aSGreg Clayton if (sc.function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry (line_entry)) 2646f6bf26aSGreg Clayton { 2656f6bf26aSGreg Clayton SetDefaultFileAndLine (line_entry.file, 2666f6bf26aSGreg Clayton line_entry.line); 2676f6bf26aSGreg Clayton file_spec = m_last_file_sp->GetFileSpec(); 2686f6bf26aSGreg Clayton line = m_last_file_line; 2696f6bf26aSGreg Clayton return true; 270f3277750SJim Ingham } 271f3277750SJim Ingham } 272f3277750SJim Ingham } 273f3277750SJim Ingham } 2746f6bf26aSGreg Clayton } 275b7f6b2faSJim Ingham return false; 276b7f6b2faSJim Ingham } 27730fdc8d8SChris Lattner 278969795f1SJim Ingham void 279969795f1SJim Ingham SourceManager::FindLinesMatchingRegex (FileSpec &file_spec, 280969795f1SJim Ingham RegularExpression& regex, 281969795f1SJim Ingham uint32_t start_line, 282969795f1SJim Ingham uint32_t end_line, 283969795f1SJim Ingham std::vector<uint32_t> &match_lines) 284969795f1SJim Ingham { 285969795f1SJim Ingham match_lines.clear(); 286969795f1SJim Ingham FileSP file_sp = GetFile (file_spec); 287969795f1SJim Ingham if (!file_sp) 288969795f1SJim Ingham return; 289969795f1SJim Ingham return file_sp->FindLinesMatchingRegex (regex, start_line, end_line, match_lines); 290969795f1SJim Ingham } 29130fdc8d8SChris Lattner 2927e14f91dSGreg Clayton SourceManager::File::File(const FileSpec &file_spec, Target *target) : 2937e14f91dSGreg Clayton m_file_spec_orig (file_spec), 29430fdc8d8SChris Lattner m_file_spec(file_spec), 2957e14f91dSGreg Clayton m_mod_time (file_spec.GetModificationTime()), 2967e14f91dSGreg Clayton m_data_sp(), 29730fdc8d8SChris Lattner m_offsets() 29830fdc8d8SChris Lattner { 2997e14f91dSGreg Clayton if (!m_mod_time.IsValid()) 3007e14f91dSGreg Clayton { 301e37d605eSJim Ingham if (target) 302e37d605eSJim Ingham { 303e37d605eSJim Ingham if (!file_spec.GetDirectory() && file_spec.GetFilename()) 304e37d605eSJim Ingham { 305e37d605eSJim Ingham // If this is just a file name, lets see if we can find it in the target: 306e37d605eSJim Ingham bool check_inlines = false; 307e37d605eSJim Ingham SymbolContextList sc_list; 308e37d605eSJim Ingham size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (file_spec.GetFilename().AsCString(), 309e37d605eSJim Ingham 0, 310e37d605eSJim Ingham check_inlines, 311e37d605eSJim Ingham lldb::eSymbolContextModule | lldb::eSymbolContextCompUnit, 312e37d605eSJim Ingham sc_list); 313e37d605eSJim Ingham bool got_multiple = false; 314e37d605eSJim Ingham if (num_matches != 0) 315e37d605eSJim Ingham { 316e37d605eSJim Ingham if (num_matches > 1) 317e37d605eSJim Ingham { 318e37d605eSJim Ingham SymbolContext sc; 319e37d605eSJim Ingham FileSpec *test_cu_spec = NULL; 320e37d605eSJim Ingham 321e37d605eSJim Ingham for (unsigned i = 0; i < num_matches; i++) 322e37d605eSJim Ingham { 323e37d605eSJim Ingham sc_list.GetContextAtIndex(i, sc); 324e37d605eSJim Ingham if (sc.comp_unit) 325e37d605eSJim Ingham { 326e37d605eSJim Ingham if (test_cu_spec) 327e37d605eSJim Ingham { 328e37d605eSJim Ingham if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit)) 329e37d605eSJim Ingham got_multiple = true; 330e37d605eSJim Ingham break; 331e37d605eSJim Ingham } 332e37d605eSJim Ingham else 333e37d605eSJim Ingham test_cu_spec = sc.comp_unit; 334e37d605eSJim Ingham } 335e37d605eSJim Ingham } 336e37d605eSJim Ingham } 337e37d605eSJim Ingham if (!got_multiple) 338e37d605eSJim Ingham { 339e37d605eSJim Ingham SymbolContext sc; 340e37d605eSJim Ingham sc_list.GetContextAtIndex (0, sc); 341d804d285SGreg Clayton m_file_spec = sc.comp_unit; 342e37d605eSJim Ingham m_mod_time = m_file_spec.GetModificationTime(); 343e37d605eSJim Ingham } 344e37d605eSJim Ingham } 345e37d605eSJim Ingham } 34664bab489SJohnny Chen // Try remapping if m_file_spec does not correspond to an existing file. 34764bab489SJohnny Chen if (!m_file_spec.Exists()) 348e37d605eSJim Ingham { 349d804d285SGreg Clayton FileSpec new_file_spec; 350d804d285SGreg Clayton // Check target specific source remappings first, then fall back to 351d804d285SGreg Clayton // modules objects can have individual path remappings that were detected 352d804d285SGreg Clayton // when the debug info for a module was found. 353d804d285SGreg Clayton // then 354d804d285SGreg Clayton if (target->GetSourcePathMap().FindFile (m_file_spec, new_file_spec) || 355d804d285SGreg Clayton target->GetImages().FindSourceFile (m_file_spec, new_file_spec)) 35664bab489SJohnny Chen { 357d804d285SGreg Clayton m_file_spec = new_file_spec; 35864bab489SJohnny Chen m_mod_time = m_file_spec.GetModificationTime(); 35964bab489SJohnny Chen } 3607e14f91dSGreg Clayton } 361e37d605eSJim Ingham } 362e37d605eSJim Ingham } 3637e14f91dSGreg Clayton 3647e14f91dSGreg Clayton if (m_mod_time.IsValid()) 3657e14f91dSGreg Clayton m_data_sp = m_file_spec.ReadFileContents (); 36630fdc8d8SChris Lattner } 36730fdc8d8SChris Lattner 36830fdc8d8SChris Lattner SourceManager::File::~File() 36930fdc8d8SChris Lattner { 37030fdc8d8SChris Lattner } 37130fdc8d8SChris Lattner 37230fdc8d8SChris Lattner uint32_t 37330fdc8d8SChris Lattner SourceManager::File::GetLineOffset (uint32_t line) 37430fdc8d8SChris Lattner { 37530fdc8d8SChris Lattner if (line == 0) 37630fdc8d8SChris Lattner return UINT32_MAX; 37730fdc8d8SChris Lattner 37830fdc8d8SChris Lattner if (line == 1) 37930fdc8d8SChris Lattner return 0; 38030fdc8d8SChris Lattner 38130fdc8d8SChris Lattner if (CalculateLineOffsets (line)) 38230fdc8d8SChris Lattner { 38330fdc8d8SChris Lattner if (line < m_offsets.size()) 38430fdc8d8SChris Lattner return m_offsets[line - 1]; // yes we want "line - 1" in the index 38530fdc8d8SChris Lattner } 38630fdc8d8SChris Lattner return UINT32_MAX; 38730fdc8d8SChris Lattner } 38830fdc8d8SChris Lattner 38930fdc8d8SChris Lattner bool 39030fdc8d8SChris Lattner SourceManager::File::LineIsValid (uint32_t line) 39130fdc8d8SChris Lattner { 39230fdc8d8SChris Lattner if (line == 0) 39330fdc8d8SChris Lattner return false; 39430fdc8d8SChris Lattner 39530fdc8d8SChris Lattner if (CalculateLineOffsets (line)) 39630fdc8d8SChris Lattner return line < m_offsets.size(); 39730fdc8d8SChris Lattner return false; 39830fdc8d8SChris Lattner } 39930fdc8d8SChris Lattner 40030fdc8d8SChris Lattner size_t 40130fdc8d8SChris Lattner SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s) 40230fdc8d8SChris Lattner { 4039625d08cSGreg Clayton // TODO: use host API to sign up for file modifications to anything in our 4049625d08cSGreg Clayton // source cache and only update when we determine a file has been updated. 4059625d08cSGreg Clayton // For now we check each time we want to display info for the file. 4069625d08cSGreg Clayton TimeValue curr_mod_time (m_file_spec.GetModificationTime()); 40764bab489SJohnny Chen 40864bab489SJohnny Chen if (curr_mod_time.IsValid() && m_mod_time != curr_mod_time) 4099625d08cSGreg Clayton { 4109625d08cSGreg Clayton m_mod_time = curr_mod_time; 4119625d08cSGreg Clayton m_data_sp = m_file_spec.ReadFileContents (); 4129625d08cSGreg Clayton m_offsets.clear(); 4139625d08cSGreg Clayton } 4149625d08cSGreg Clayton 41564bab489SJohnny Chen // Sanity check m_data_sp before proceeding. 41664bab489SJohnny Chen if (!m_data_sp) 41764bab489SJohnny Chen return 0; 41864bab489SJohnny Chen 41930fdc8d8SChris Lattner const uint32_t start_line = line <= context_before ? 1 : line - context_before; 42030fdc8d8SChris Lattner const uint32_t start_line_offset = GetLineOffset (start_line); 42130fdc8d8SChris Lattner if (start_line_offset != UINT32_MAX) 42230fdc8d8SChris Lattner { 42330fdc8d8SChris Lattner const uint32_t end_line = line + context_after; 42430fdc8d8SChris Lattner uint32_t end_line_offset = GetLineOffset (end_line + 1); 42530fdc8d8SChris Lattner if (end_line_offset == UINT32_MAX) 42630fdc8d8SChris Lattner end_line_offset = m_data_sp->GetByteSize(); 42730fdc8d8SChris Lattner 42830fdc8d8SChris Lattner assert (start_line_offset <= end_line_offset); 42930fdc8d8SChris Lattner size_t bytes_written = 0; 43030fdc8d8SChris Lattner if (start_line_offset < end_line_offset) 43130fdc8d8SChris Lattner { 43230fdc8d8SChris Lattner size_t count = end_line_offset - start_line_offset; 43330fdc8d8SChris Lattner const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset; 43430fdc8d8SChris Lattner bytes_written = s->Write(cstr, count); 43530fdc8d8SChris Lattner if (!is_newline_char(cstr[count-1])) 43630fdc8d8SChris Lattner bytes_written += s->EOL(); 43730fdc8d8SChris Lattner } 43830fdc8d8SChris Lattner return bytes_written; 43930fdc8d8SChris Lattner } 44030fdc8d8SChris Lattner return 0; 44130fdc8d8SChris Lattner } 44230fdc8d8SChris Lattner 443969795f1SJim Ingham void 444969795f1SJim Ingham SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines) 445969795f1SJim Ingham { 446969795f1SJim Ingham TimeValue curr_mod_time (m_file_spec.GetModificationTime()); 447969795f1SJim Ingham if (m_mod_time != curr_mod_time) 448969795f1SJim Ingham { 449969795f1SJim Ingham m_mod_time = curr_mod_time; 450969795f1SJim Ingham m_data_sp = m_file_spec.ReadFileContents (); 451969795f1SJim Ingham m_offsets.clear(); 452969795f1SJim Ingham } 453969795f1SJim Ingham 454969795f1SJim Ingham match_lines.clear(); 455969795f1SJim Ingham 456969795f1SJim Ingham if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line))) 457969795f1SJim Ingham return; 458969795f1SJim Ingham if (start_line > end_line) 459969795f1SJim Ingham return; 460969795f1SJim Ingham 461969795f1SJim Ingham for (uint32_t line_no = start_line; line_no < end_line; line_no++) 462969795f1SJim Ingham { 463969795f1SJim Ingham std::string buffer; 464969795f1SJim Ingham if (!GetLine (line_no, buffer)) 465969795f1SJim Ingham break; 466969795f1SJim Ingham if (regex.Execute(buffer.c_str())) 467969795f1SJim Ingham { 468969795f1SJim Ingham match_lines.push_back(line_no); 469969795f1SJim Ingham } 470969795f1SJim Ingham } 471969795f1SJim Ingham } 472969795f1SJim Ingham 47330fdc8d8SChris Lattner bool 47430fdc8d8SChris Lattner SourceManager::File::FileSpecMatches (const FileSpec &file_spec) 47530fdc8d8SChris Lattner { 476644247c1SGreg Clayton return FileSpec::Equal (m_file_spec, file_spec, false); 47730fdc8d8SChris Lattner } 47830fdc8d8SChris Lattner 479e37d605eSJim Ingham bool 480e37d605eSJim Ingham lldb_private::operator== (const SourceManager::File &lhs, const SourceManager::File &rhs) 481e37d605eSJim Ingham { 482e37d605eSJim Ingham if (lhs.m_file_spec == rhs.m_file_spec) 483e37d605eSJim Ingham { 484e37d605eSJim Ingham if (lhs.m_mod_time.IsValid()) 485e37d605eSJim Ingham { 486e37d605eSJim Ingham if (rhs.m_mod_time.IsValid()) 487e37d605eSJim Ingham return lhs.m_mod_time == rhs.m_mod_time; 488e37d605eSJim Ingham else 489e37d605eSJim Ingham return false; 490e37d605eSJim Ingham } 491e37d605eSJim Ingham else if (rhs.m_mod_time.IsValid()) 492e37d605eSJim Ingham return false; 493e37d605eSJim Ingham else 494e37d605eSJim Ingham return true; 495e37d605eSJim Ingham } 496e37d605eSJim Ingham else 497e37d605eSJim Ingham return false; 498e37d605eSJim Ingham } 49930fdc8d8SChris Lattner 50030fdc8d8SChris Lattner bool 50130fdc8d8SChris Lattner SourceManager::File::CalculateLineOffsets (uint32_t line) 50230fdc8d8SChris Lattner { 50330fdc8d8SChris Lattner line = UINT32_MAX; // TODO: take this line out when we support partial indexing 50430fdc8d8SChris Lattner if (line == UINT32_MAX) 50530fdc8d8SChris Lattner { 50630fdc8d8SChris Lattner // Already done? 50730fdc8d8SChris Lattner if (!m_offsets.empty() && m_offsets[0] == UINT32_MAX) 50830fdc8d8SChris Lattner return true; 50930fdc8d8SChris Lattner 51030fdc8d8SChris Lattner if (m_offsets.empty()) 51130fdc8d8SChris Lattner { 51230fdc8d8SChris Lattner if (m_data_sp.get() == NULL) 51330fdc8d8SChris Lattner return false; 51430fdc8d8SChris Lattner 51530fdc8d8SChris Lattner const char *start = (char *)m_data_sp->GetBytes(); 51630fdc8d8SChris Lattner if (start) 51730fdc8d8SChris Lattner { 51830fdc8d8SChris Lattner const char *end = start + m_data_sp->GetByteSize(); 51930fdc8d8SChris Lattner 52030fdc8d8SChris Lattner // Calculate all line offsets from scratch 52130fdc8d8SChris Lattner 52230fdc8d8SChris Lattner // Push a 1 at index zero to indicate the file has been completely indexed. 52330fdc8d8SChris Lattner m_offsets.push_back(UINT32_MAX); 52430fdc8d8SChris Lattner register const char *s; 52530fdc8d8SChris Lattner for (s = start; s < end; ++s) 52630fdc8d8SChris Lattner { 52730fdc8d8SChris Lattner register char curr_ch = *s; 52830fdc8d8SChris Lattner if (is_newline_char (curr_ch)) 52930fdc8d8SChris Lattner { 53030fdc8d8SChris Lattner register char next_ch = s[1]; 53130fdc8d8SChris Lattner if (is_newline_char (next_ch)) 53230fdc8d8SChris Lattner { 53330fdc8d8SChris Lattner if (curr_ch != next_ch) 53430fdc8d8SChris Lattner ++s; 53530fdc8d8SChris Lattner } 53630fdc8d8SChris Lattner m_offsets.push_back(s + 1 - start); 53730fdc8d8SChris Lattner } 53830fdc8d8SChris Lattner } 53930fdc8d8SChris Lattner if (!m_offsets.empty()) 54030fdc8d8SChris Lattner { 54130fdc8d8SChris Lattner if (m_offsets.back() < end - start) 54230fdc8d8SChris Lattner m_offsets.push_back(end - start); 54330fdc8d8SChris Lattner } 54430fdc8d8SChris Lattner return true; 54530fdc8d8SChris Lattner } 54630fdc8d8SChris Lattner } 54730fdc8d8SChris Lattner else 54830fdc8d8SChris Lattner { 54930fdc8d8SChris Lattner // Some lines have been populated, start where we last left off 55030fdc8d8SChris Lattner assert(!"Not implemented yet"); 55130fdc8d8SChris Lattner } 55230fdc8d8SChris Lattner 55330fdc8d8SChris Lattner } 55430fdc8d8SChris Lattner else 55530fdc8d8SChris Lattner { 55630fdc8d8SChris Lattner // Calculate all line offsets up to "line" 55730fdc8d8SChris Lattner assert(!"Not implemented yet"); 55830fdc8d8SChris Lattner } 55930fdc8d8SChris Lattner return false; 56030fdc8d8SChris Lattner } 561e37d605eSJim Ingham 562969795f1SJim Ingham bool 563969795f1SJim Ingham SourceManager::File::GetLine (uint32_t line_no, std::string &buffer) 564969795f1SJim Ingham { 565969795f1SJim Ingham if (!LineIsValid(line_no)) 566969795f1SJim Ingham return false; 567969795f1SJim Ingham 568969795f1SJim Ingham uint32_t start_offset = GetLineOffset (line_no); 569969795f1SJim Ingham uint32_t end_offset = GetLineOffset (line_no + 1); 570969795f1SJim Ingham if (end_offset == UINT32_MAX) 571969795f1SJim Ingham { 572969795f1SJim Ingham end_offset = m_data_sp->GetByteSize(); 573969795f1SJim Ingham } 574969795f1SJim Ingham buffer.assign((char *) m_data_sp->GetBytes() + start_offset, end_offset - start_offset); 575969795f1SJim Ingham 576969795f1SJim Ingham return true; 577969795f1SJim Ingham } 578969795f1SJim Ingham 579e37d605eSJim Ingham void 580e37d605eSJim Ingham SourceManager::SourceFileCache::AddSourceFile (const FileSP &file_sp) 581e37d605eSJim Ingham { 582e37d605eSJim Ingham FileSpec file_spec; 583e37d605eSJim Ingham FileCache::iterator pos = m_file_cache.find(file_spec); 584e37d605eSJim Ingham if (pos == m_file_cache.end()) 585e37d605eSJim Ingham m_file_cache[file_spec] = file_sp; 586e37d605eSJim Ingham else 587e37d605eSJim Ingham { 588e37d605eSJim Ingham if (file_sp != pos->second) 589e37d605eSJim Ingham m_file_cache[file_spec] = file_sp; 590e37d605eSJim Ingham } 591e37d605eSJim Ingham } 592e37d605eSJim Ingham 593e37d605eSJim Ingham SourceManager::FileSP 594e37d605eSJim Ingham SourceManager::SourceFileCache::FindSourceFile (const FileSpec &file_spec) const 595e37d605eSJim Ingham { 596e37d605eSJim Ingham FileSP file_sp; 597e37d605eSJim Ingham FileCache::const_iterator pos = m_file_cache.find(file_spec); 598e37d605eSJim Ingham if (pos != m_file_cache.end()) 599e37d605eSJim Ingham file_sp = pos->second; 600e37d605eSJim Ingham return file_sp; 601e37d605eSJim Ingham } 602e37d605eSJim Ingham 603