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 1030fdc8d8SChris Lattner #include "lldb/Core/SourceManager.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1630fdc8d8SChris Lattner #include "lldb/Core/DataBuffer.h" 17e37d605eSJim Ingham #include "lldb/Core/Debugger.h" 1830fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 19b6d70ebcSSean Callanan #include "lldb/Symbol/ClangNamespaceDecl.h" 20176761e5SGreg Clayton #include "lldb/Symbol/SymbolContext.h" 217e14f91dSGreg Clayton #include "lldb/Target/Target.h" 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner using namespace lldb_private; 2430fdc8d8SChris Lattner 2530fdc8d8SChris Lattner static inline bool is_newline_char(char ch) 2630fdc8d8SChris Lattner { 2730fdc8d8SChris Lattner return ch == '\n' || ch == '\r'; 2830fdc8d8SChris Lattner } 2930fdc8d8SChris Lattner 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner //---------------------------------------------------------------------- 3230fdc8d8SChris Lattner // SourceManager constructor 3330fdc8d8SChris Lattner //---------------------------------------------------------------------- 34e37d605eSJim Ingham SourceManager::SourceManager(Target &target) : 3530fdc8d8SChris Lattner m_last_file_sp (), 3630fdc8d8SChris Lattner m_last_file_line (0), 3730fdc8d8SChris Lattner m_last_file_context_before (0), 38b7f6b2faSJim Ingham m_last_file_context_after (10), 39f3277750SJim Ingham m_default_set(false), 40e37d605eSJim Ingham m_target (&target), 41e37d605eSJim Ingham m_debugger(NULL) 42e37d605eSJim Ingham { 43e37d605eSJim Ingham m_debugger = &(m_target->GetDebugger()); 44e37d605eSJim Ingham } 45e37d605eSJim Ingham 46e37d605eSJim Ingham SourceManager::SourceManager(Debugger &debugger) : 47e37d605eSJim Ingham m_last_file_sp (), 48e37d605eSJim Ingham m_last_file_line (0), 49e37d605eSJim Ingham m_last_file_context_before (0), 50e37d605eSJim Ingham m_last_file_context_after (10), 51f3277750SJim Ingham m_default_set(false), 52e37d605eSJim Ingham m_target (NULL), 53e37d605eSJim Ingham m_debugger (&debugger) 5430fdc8d8SChris Lattner { 5530fdc8d8SChris Lattner } 5630fdc8d8SChris Lattner 5730fdc8d8SChris Lattner //---------------------------------------------------------------------- 5830fdc8d8SChris Lattner // Destructor 5930fdc8d8SChris Lattner //---------------------------------------------------------------------- 6030fdc8d8SChris Lattner SourceManager::~SourceManager() 6130fdc8d8SChris Lattner { 6230fdc8d8SChris Lattner } 6330fdc8d8SChris Lattner 6430fdc8d8SChris Lattner size_t 6530fdc8d8SChris Lattner SourceManager::DisplaySourceLines 6630fdc8d8SChris Lattner ( 6730fdc8d8SChris Lattner const FileSpec &file_spec, 6830fdc8d8SChris Lattner uint32_t line, 6930fdc8d8SChris Lattner uint32_t context_before, 7030fdc8d8SChris Lattner uint32_t context_after, 7130fdc8d8SChris Lattner Stream *s 7230fdc8d8SChris Lattner ) 7330fdc8d8SChris Lattner { 74b7f6b2faSJim Ingham m_last_file_sp = GetFile (file_spec); 7530fdc8d8SChris Lattner m_last_file_line = line + context_after + 1; 7630fdc8d8SChris Lattner m_last_file_context_before = context_before; 7730fdc8d8SChris Lattner m_last_file_context_after = context_after; 7830fdc8d8SChris Lattner if (m_last_file_sp.get()) 7930fdc8d8SChris Lattner return m_last_file_sp->DisplaySourceLines (line, context_before, context_after, s); 8030fdc8d8SChris Lattner 8130fdc8d8SChris Lattner return 0; 8230fdc8d8SChris Lattner } 8330fdc8d8SChris Lattner 8430fdc8d8SChris Lattner SourceManager::FileSP 85b7f6b2faSJim Ingham SourceManager::GetFile (const FileSpec &file_spec) 8630fdc8d8SChris Lattner { 8730fdc8d8SChris Lattner FileSP file_sp; 88e37d605eSJim Ingham file_sp = m_debugger->GetSourceFileCache().FindSourceFile (file_spec); 8964bab489SJohnny Chen // If file_sp is no good or it points to a non-existent file, reset it. 9064bab489SJohnny Chen if (!file_sp || !file_sp->GetFileSpec().Exists()) 9130fdc8d8SChris Lattner { 92b7f6b2faSJim Ingham file_sp.reset (new File (file_spec, m_target)); 93e37d605eSJim Ingham 94e37d605eSJim Ingham m_debugger->GetSourceFileCache().AddSourceFile(file_sp); 9530fdc8d8SChris Lattner } 9630fdc8d8SChris Lattner return file_sp; 9730fdc8d8SChris Lattner } 9830fdc8d8SChris Lattner 9930fdc8d8SChris Lattner size_t 10030fdc8d8SChris Lattner SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile 10130fdc8d8SChris Lattner ( 10230fdc8d8SChris Lattner uint32_t line, 10330fdc8d8SChris Lattner uint32_t context_before, 10430fdc8d8SChris Lattner uint32_t context_after, 10530fdc8d8SChris Lattner const char* current_line_cstr, 106176761e5SGreg Clayton Stream *s, 107176761e5SGreg Clayton const SymbolContextList *bp_locs 10830fdc8d8SChris Lattner ) 10930fdc8d8SChris Lattner { 110e37d605eSJim Ingham size_t return_value = 0; 11130fdc8d8SChris Lattner if (line == 0) 11230fdc8d8SChris Lattner { 11330fdc8d8SChris Lattner if (m_last_file_line != 0 11430fdc8d8SChris Lattner && m_last_file_line != UINT32_MAX) 11530fdc8d8SChris Lattner line = m_last_file_line + context_before; 11630fdc8d8SChris Lattner else 11730fdc8d8SChris Lattner line = 1; 11830fdc8d8SChris Lattner } 11930fdc8d8SChris Lattner 12030fdc8d8SChris Lattner m_last_file_line = line + context_after + 1; 12130fdc8d8SChris Lattner m_last_file_context_before = context_before; 12230fdc8d8SChris Lattner m_last_file_context_after = context_after; 12330fdc8d8SChris Lattner 12430fdc8d8SChris Lattner if (context_before == UINT32_MAX) 12530fdc8d8SChris Lattner context_before = 0; 12630fdc8d8SChris Lattner if (context_after == UINT32_MAX) 12730fdc8d8SChris Lattner context_after = 10; 12830fdc8d8SChris Lattner 12930fdc8d8SChris Lattner if (m_last_file_sp.get()) 13030fdc8d8SChris Lattner { 13130fdc8d8SChris Lattner const uint32_t start_line = line <= context_before ? 1 : line - context_before; 13230fdc8d8SChris Lattner const uint32_t end_line = line + context_after; 13330fdc8d8SChris Lattner uint32_t curr_line; 13430fdc8d8SChris Lattner for (curr_line = start_line; curr_line <= end_line; ++curr_line) 13530fdc8d8SChris Lattner { 13630fdc8d8SChris Lattner if (!m_last_file_sp->LineIsValid (curr_line)) 13730fdc8d8SChris Lattner { 13830fdc8d8SChris Lattner m_last_file_line = UINT32_MAX; 13930fdc8d8SChris Lattner break; 14030fdc8d8SChris Lattner } 14130fdc8d8SChris Lattner 142176761e5SGreg Clayton char prefix[32] = ""; 143176761e5SGreg Clayton if (bp_locs) 144176761e5SGreg Clayton { 145176761e5SGreg Clayton uint32_t bp_count = bp_locs->NumLineEntriesWithLine (curr_line); 146176761e5SGreg Clayton 147176761e5SGreg Clayton if (bp_count > 0) 148176761e5SGreg Clayton ::snprintf (prefix, sizeof (prefix), "[%u] ", bp_count); 149176761e5SGreg Clayton else 150176761e5SGreg Clayton ::snprintf (prefix, sizeof (prefix), " "); 151176761e5SGreg Clayton } 152176761e5SGreg Clayton 153e37d605eSJim Ingham return_value += s->Printf("%s%2.2s %-4u\t", 154176761e5SGreg Clayton prefix, 155176761e5SGreg Clayton curr_line == line ? current_line_cstr : "", 156176761e5SGreg Clayton curr_line); 157e37d605eSJim Ingham size_t this_line_size = m_last_file_sp->DisplaySourceLines (curr_line, 0, 0, s); 158e37d605eSJim Ingham if (this_line_size == 0) 15930fdc8d8SChris Lattner { 16030fdc8d8SChris Lattner m_last_file_line = UINT32_MAX; 16130fdc8d8SChris Lattner break; 16230fdc8d8SChris Lattner } 163e37d605eSJim Ingham else 164e37d605eSJim Ingham return_value += this_line_size; 16530fdc8d8SChris Lattner } 16630fdc8d8SChris Lattner } 167e37d605eSJim Ingham return return_value; 16830fdc8d8SChris Lattner } 16930fdc8d8SChris Lattner 17030fdc8d8SChris Lattner size_t 17130fdc8d8SChris Lattner SourceManager::DisplaySourceLinesWithLineNumbers 17230fdc8d8SChris Lattner ( 17330fdc8d8SChris Lattner const FileSpec &file_spec, 17430fdc8d8SChris Lattner uint32_t line, 17530fdc8d8SChris Lattner uint32_t context_before, 17630fdc8d8SChris Lattner uint32_t context_after, 17730fdc8d8SChris Lattner const char* current_line_cstr, 178176761e5SGreg Clayton Stream *s, 179176761e5SGreg Clayton const SymbolContextList *bp_locs 18030fdc8d8SChris Lattner ) 18130fdc8d8SChris Lattner { 18230fdc8d8SChris Lattner bool same_as_previous = m_last_file_sp && m_last_file_sp->FileSpecMatches (file_spec); 18330fdc8d8SChris Lattner 18430fdc8d8SChris Lattner if (!same_as_previous) 185b7f6b2faSJim Ingham m_last_file_sp = GetFile (file_spec); 18630fdc8d8SChris Lattner 18730fdc8d8SChris Lattner if (line == 0) 18830fdc8d8SChris Lattner { 18930fdc8d8SChris Lattner if (!same_as_previous) 19030fdc8d8SChris Lattner m_last_file_line = 0; 19130fdc8d8SChris Lattner } 19230fdc8d8SChris Lattner 193176761e5SGreg Clayton return DisplaySourceLinesWithLineNumbersUsingLastFile (line, context_before, context_after, current_line_cstr, s, bp_locs); 19430fdc8d8SChris Lattner } 19530fdc8d8SChris Lattner 19630fdc8d8SChris Lattner size_t 197176761e5SGreg Clayton SourceManager::DisplayMoreWithLineNumbers (Stream *s, const SymbolContextList *bp_locs) 19830fdc8d8SChris Lattner { 19930fdc8d8SChris Lattner if (m_last_file_sp) 20030fdc8d8SChris Lattner { 20130fdc8d8SChris Lattner if (m_last_file_line == UINT32_MAX) 20230fdc8d8SChris Lattner return 0; 203e37d605eSJim Ingham return DisplaySourceLinesWithLineNumbersUsingLastFile (0, m_last_file_context_before, m_last_file_context_after, "", s, bp_locs); 20430fdc8d8SChris Lattner } 20530fdc8d8SChris Lattner return 0; 20630fdc8d8SChris Lattner } 20730fdc8d8SChris Lattner 208b7f6b2faSJim Ingham bool 209b7f6b2faSJim Ingham SourceManager::SetDefaultFileAndLine (const FileSpec &file_spec, uint32_t line) 210b7f6b2faSJim Ingham { 211b7f6b2faSJim Ingham FileSP old_file_sp = m_last_file_sp; 212b7f6b2faSJim Ingham m_last_file_sp = GetFile (file_spec); 213f3277750SJim Ingham 214f3277750SJim Ingham m_default_set = true; 215b7f6b2faSJim Ingham if (m_last_file_sp) 216b7f6b2faSJim Ingham { 217b7f6b2faSJim Ingham m_last_file_line = line; 218b7f6b2faSJim Ingham return true; 219b7f6b2faSJim Ingham } 220b7f6b2faSJim Ingham else 221b7f6b2faSJim Ingham { 222b7f6b2faSJim Ingham m_last_file_sp = old_file_sp; 223b7f6b2faSJim Ingham return false; 224b7f6b2faSJim Ingham } 225b7f6b2faSJim Ingham } 226b7f6b2faSJim Ingham 227b7f6b2faSJim Ingham bool 228b7f6b2faSJim Ingham SourceManager::GetDefaultFileAndLine (FileSpec &file_spec, uint32_t &line) 229b7f6b2faSJim Ingham { 230b7f6b2faSJim Ingham if (m_last_file_sp) 231b7f6b2faSJim Ingham { 232b7f6b2faSJim Ingham file_spec = m_last_file_sp->GetFileSpec(); 233b7f6b2faSJim Ingham line = m_last_file_line; 234b7f6b2faSJim Ingham return true; 235b7f6b2faSJim Ingham } 236f3277750SJim Ingham else if (!m_default_set) 237f3277750SJim Ingham { 238f3277750SJim Ingham // If nobody has set the default file and line then try here. If there's no executable, then we 239f3277750SJim Ingham // will try again later when there is one. Otherwise, if we can't find it we won't look again, 240f3277750SJim Ingham // somebody will have to set it (for instance when we stop somewhere...) 241f3277750SJim Ingham Module *executable_ptr = m_target->GetExecutableModulePointer(); 242f3277750SJim Ingham if (executable_ptr) 243f3277750SJim Ingham { 244f3277750SJim Ingham SymbolContextList sc_list; 245f3277750SJim Ingham uint32_t num_matches; 246f3277750SJim Ingham ConstString main_name("main"); 247f3277750SJim Ingham bool symbols_okay = false; // Force it to be a debug symbol. 2489df05fbbSSean Callanan bool inlines_okay = true; 249f3277750SJim Ingham bool append = false; 2509df05fbbSSean Callanan num_matches = executable_ptr->FindFunctions (main_name, NULL, lldb::eFunctionNameTypeBase, inlines_okay, symbols_okay, append, sc_list); 251f3277750SJim Ingham for (uint32_t idx = 0; idx < num_matches; idx++) 252f3277750SJim Ingham { 253f3277750SJim Ingham SymbolContext sc; 254f3277750SJim Ingham sc_list.GetContextAtIndex(idx, sc); 2556f6bf26aSGreg Clayton if (sc.function) 256f3277750SJim Ingham { 2576f6bf26aSGreg Clayton lldb_private::LineEntry line_entry; 2586f6bf26aSGreg Clayton if (sc.function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry (line_entry)) 2596f6bf26aSGreg Clayton { 2606f6bf26aSGreg Clayton SetDefaultFileAndLine (line_entry.file, 2616f6bf26aSGreg Clayton line_entry.line); 2626f6bf26aSGreg Clayton file_spec = m_last_file_sp->GetFileSpec(); 2636f6bf26aSGreg Clayton line = m_last_file_line; 2646f6bf26aSGreg Clayton return true; 265f3277750SJim Ingham } 266f3277750SJim Ingham } 267f3277750SJim Ingham } 268f3277750SJim Ingham } 2696f6bf26aSGreg Clayton } 270b7f6b2faSJim Ingham return false; 271b7f6b2faSJim Ingham } 27230fdc8d8SChris Lattner 273969795f1SJim Ingham void 274969795f1SJim Ingham SourceManager::FindLinesMatchingRegex (FileSpec &file_spec, 275969795f1SJim Ingham RegularExpression& regex, 276969795f1SJim Ingham uint32_t start_line, 277969795f1SJim Ingham uint32_t end_line, 278969795f1SJim Ingham std::vector<uint32_t> &match_lines) 279969795f1SJim Ingham { 280969795f1SJim Ingham match_lines.clear(); 281969795f1SJim Ingham FileSP file_sp = GetFile (file_spec); 282969795f1SJim Ingham if (!file_sp) 283969795f1SJim Ingham return; 284969795f1SJim Ingham return file_sp->FindLinesMatchingRegex (regex, start_line, end_line, match_lines); 285969795f1SJim Ingham } 28630fdc8d8SChris Lattner 2877e14f91dSGreg Clayton SourceManager::File::File(const FileSpec &file_spec, Target *target) : 2887e14f91dSGreg Clayton m_file_spec_orig (file_spec), 28930fdc8d8SChris Lattner m_file_spec(file_spec), 2907e14f91dSGreg Clayton m_mod_time (file_spec.GetModificationTime()), 2917e14f91dSGreg Clayton m_data_sp(), 29230fdc8d8SChris Lattner m_offsets() 29330fdc8d8SChris Lattner { 2947e14f91dSGreg Clayton if (!m_mod_time.IsValid()) 2957e14f91dSGreg Clayton { 296e37d605eSJim Ingham if (target) 297e37d605eSJim Ingham { 298e37d605eSJim Ingham if (!file_spec.GetDirectory() && file_spec.GetFilename()) 299e37d605eSJim Ingham { 300e37d605eSJim Ingham // If this is just a file name, lets see if we can find it in the target: 301e37d605eSJim Ingham bool check_inlines = false; 302e37d605eSJim Ingham SymbolContextList sc_list; 303e37d605eSJim Ingham size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (file_spec.GetFilename().AsCString(), 304e37d605eSJim Ingham 0, 305e37d605eSJim Ingham check_inlines, 306e37d605eSJim Ingham lldb::eSymbolContextModule | lldb::eSymbolContextCompUnit, 307e37d605eSJim Ingham sc_list); 308e37d605eSJim Ingham bool got_multiple = false; 309e37d605eSJim Ingham if (num_matches != 0) 310e37d605eSJim Ingham { 311e37d605eSJim Ingham if (num_matches > 1) 312e37d605eSJim Ingham { 313e37d605eSJim Ingham SymbolContext sc; 314e37d605eSJim Ingham FileSpec *test_cu_spec = NULL; 315e37d605eSJim Ingham 316e37d605eSJim Ingham for (unsigned i = 0; i < num_matches; i++) 317e37d605eSJim Ingham { 318e37d605eSJim Ingham sc_list.GetContextAtIndex(i, sc); 319e37d605eSJim Ingham if (sc.comp_unit) 320e37d605eSJim Ingham { 321e37d605eSJim Ingham if (test_cu_spec) 322e37d605eSJim Ingham { 323e37d605eSJim Ingham if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit)) 324e37d605eSJim Ingham got_multiple = true; 325e37d605eSJim Ingham break; 326e37d605eSJim Ingham } 327e37d605eSJim Ingham else 328e37d605eSJim Ingham test_cu_spec = sc.comp_unit; 329e37d605eSJim Ingham } 330e37d605eSJim Ingham } 331e37d605eSJim Ingham } 332e37d605eSJim Ingham if (!got_multiple) 333e37d605eSJim Ingham { 334e37d605eSJim Ingham SymbolContext sc; 335e37d605eSJim Ingham sc_list.GetContextAtIndex (0, sc); 336*d804d285SGreg Clayton m_file_spec = sc.comp_unit; 337e37d605eSJim Ingham m_mod_time = m_file_spec.GetModificationTime(); 338e37d605eSJim Ingham } 339e37d605eSJim Ingham } 340e37d605eSJim Ingham } 34164bab489SJohnny Chen // Try remapping if m_file_spec does not correspond to an existing file. 34264bab489SJohnny Chen if (!m_file_spec.Exists()) 343e37d605eSJim Ingham { 344*d804d285SGreg Clayton FileSpec new_file_spec; 345*d804d285SGreg Clayton // Check target specific source remappings first, then fall back to 346*d804d285SGreg Clayton // modules objects can have individual path remappings that were detected 347*d804d285SGreg Clayton // when the debug info for a module was found. 348*d804d285SGreg Clayton // then 349*d804d285SGreg Clayton if (target->GetSourcePathMap().FindFile (m_file_spec, new_file_spec) || 350*d804d285SGreg Clayton target->GetImages().FindSourceFile (m_file_spec, new_file_spec)) 35164bab489SJohnny Chen { 352*d804d285SGreg Clayton m_file_spec = new_file_spec; 35364bab489SJohnny Chen m_mod_time = m_file_spec.GetModificationTime(); 35464bab489SJohnny Chen } 3557e14f91dSGreg Clayton } 356e37d605eSJim Ingham } 357e37d605eSJim Ingham } 3587e14f91dSGreg Clayton 3597e14f91dSGreg Clayton if (m_mod_time.IsValid()) 3607e14f91dSGreg Clayton m_data_sp = m_file_spec.ReadFileContents (); 36130fdc8d8SChris Lattner } 36230fdc8d8SChris Lattner 36330fdc8d8SChris Lattner SourceManager::File::~File() 36430fdc8d8SChris Lattner { 36530fdc8d8SChris Lattner } 36630fdc8d8SChris Lattner 36730fdc8d8SChris Lattner uint32_t 36830fdc8d8SChris Lattner SourceManager::File::GetLineOffset (uint32_t line) 36930fdc8d8SChris Lattner { 37030fdc8d8SChris Lattner if (line == 0) 37130fdc8d8SChris Lattner return UINT32_MAX; 37230fdc8d8SChris Lattner 37330fdc8d8SChris Lattner if (line == 1) 37430fdc8d8SChris Lattner return 0; 37530fdc8d8SChris Lattner 37630fdc8d8SChris Lattner if (CalculateLineOffsets (line)) 37730fdc8d8SChris Lattner { 37830fdc8d8SChris Lattner if (line < m_offsets.size()) 37930fdc8d8SChris Lattner return m_offsets[line - 1]; // yes we want "line - 1" in the index 38030fdc8d8SChris Lattner } 38130fdc8d8SChris Lattner return UINT32_MAX; 38230fdc8d8SChris Lattner } 38330fdc8d8SChris Lattner 38430fdc8d8SChris Lattner bool 38530fdc8d8SChris Lattner SourceManager::File::LineIsValid (uint32_t line) 38630fdc8d8SChris Lattner { 38730fdc8d8SChris Lattner if (line == 0) 38830fdc8d8SChris Lattner return false; 38930fdc8d8SChris Lattner 39030fdc8d8SChris Lattner if (CalculateLineOffsets (line)) 39130fdc8d8SChris Lattner return line < m_offsets.size(); 39230fdc8d8SChris Lattner return false; 39330fdc8d8SChris Lattner } 39430fdc8d8SChris Lattner 39530fdc8d8SChris Lattner size_t 39630fdc8d8SChris Lattner SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s) 39730fdc8d8SChris Lattner { 3989625d08cSGreg Clayton // TODO: use host API to sign up for file modifications to anything in our 3999625d08cSGreg Clayton // source cache and only update when we determine a file has been updated. 4009625d08cSGreg Clayton // For now we check each time we want to display info for the file. 4019625d08cSGreg Clayton TimeValue curr_mod_time (m_file_spec.GetModificationTime()); 40264bab489SJohnny Chen 40364bab489SJohnny Chen if (curr_mod_time.IsValid() && m_mod_time != curr_mod_time) 4049625d08cSGreg Clayton { 4059625d08cSGreg Clayton m_mod_time = curr_mod_time; 4069625d08cSGreg Clayton m_data_sp = m_file_spec.ReadFileContents (); 4079625d08cSGreg Clayton m_offsets.clear(); 4089625d08cSGreg Clayton } 4099625d08cSGreg Clayton 41064bab489SJohnny Chen // Sanity check m_data_sp before proceeding. 41164bab489SJohnny Chen if (!m_data_sp) 41264bab489SJohnny Chen return 0; 41364bab489SJohnny Chen 41430fdc8d8SChris Lattner const uint32_t start_line = line <= context_before ? 1 : line - context_before; 41530fdc8d8SChris Lattner const uint32_t start_line_offset = GetLineOffset (start_line); 41630fdc8d8SChris Lattner if (start_line_offset != UINT32_MAX) 41730fdc8d8SChris Lattner { 41830fdc8d8SChris Lattner const uint32_t end_line = line + context_after; 41930fdc8d8SChris Lattner uint32_t end_line_offset = GetLineOffset (end_line + 1); 42030fdc8d8SChris Lattner if (end_line_offset == UINT32_MAX) 42130fdc8d8SChris Lattner end_line_offset = m_data_sp->GetByteSize(); 42230fdc8d8SChris Lattner 42330fdc8d8SChris Lattner assert (start_line_offset <= end_line_offset); 42430fdc8d8SChris Lattner size_t bytes_written = 0; 42530fdc8d8SChris Lattner if (start_line_offset < end_line_offset) 42630fdc8d8SChris Lattner { 42730fdc8d8SChris Lattner size_t count = end_line_offset - start_line_offset; 42830fdc8d8SChris Lattner const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset; 42930fdc8d8SChris Lattner bytes_written = s->Write(cstr, count); 43030fdc8d8SChris Lattner if (!is_newline_char(cstr[count-1])) 43130fdc8d8SChris Lattner bytes_written += s->EOL(); 43230fdc8d8SChris Lattner } 43330fdc8d8SChris Lattner return bytes_written; 43430fdc8d8SChris Lattner } 43530fdc8d8SChris Lattner return 0; 43630fdc8d8SChris Lattner } 43730fdc8d8SChris Lattner 438969795f1SJim Ingham void 439969795f1SJim Ingham SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines) 440969795f1SJim Ingham { 441969795f1SJim Ingham TimeValue curr_mod_time (m_file_spec.GetModificationTime()); 442969795f1SJim Ingham if (m_mod_time != curr_mod_time) 443969795f1SJim Ingham { 444969795f1SJim Ingham m_mod_time = curr_mod_time; 445969795f1SJim Ingham m_data_sp = m_file_spec.ReadFileContents (); 446969795f1SJim Ingham m_offsets.clear(); 447969795f1SJim Ingham } 448969795f1SJim Ingham 449969795f1SJim Ingham match_lines.clear(); 450969795f1SJim Ingham 451969795f1SJim Ingham if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line))) 452969795f1SJim Ingham return; 453969795f1SJim Ingham if (start_line > end_line) 454969795f1SJim Ingham return; 455969795f1SJim Ingham 456969795f1SJim Ingham for (uint32_t line_no = start_line; line_no < end_line; line_no++) 457969795f1SJim Ingham { 458969795f1SJim Ingham std::string buffer; 459969795f1SJim Ingham if (!GetLine (line_no, buffer)) 460969795f1SJim Ingham break; 461969795f1SJim Ingham if (regex.Execute(buffer.c_str())) 462969795f1SJim Ingham { 463969795f1SJim Ingham match_lines.push_back(line_no); 464969795f1SJim Ingham } 465969795f1SJim Ingham } 466969795f1SJim Ingham } 467969795f1SJim Ingham 46830fdc8d8SChris Lattner bool 46930fdc8d8SChris Lattner SourceManager::File::FileSpecMatches (const FileSpec &file_spec) 47030fdc8d8SChris Lattner { 471644247c1SGreg Clayton return FileSpec::Equal (m_file_spec, file_spec, false); 47230fdc8d8SChris Lattner } 47330fdc8d8SChris Lattner 474e37d605eSJim Ingham bool 475e37d605eSJim Ingham lldb_private::operator== (const SourceManager::File &lhs, const SourceManager::File &rhs) 476e37d605eSJim Ingham { 477e37d605eSJim Ingham if (lhs.m_file_spec == rhs.m_file_spec) 478e37d605eSJim Ingham { 479e37d605eSJim Ingham if (lhs.m_mod_time.IsValid()) 480e37d605eSJim Ingham { 481e37d605eSJim Ingham if (rhs.m_mod_time.IsValid()) 482e37d605eSJim Ingham return lhs.m_mod_time == rhs.m_mod_time; 483e37d605eSJim Ingham else 484e37d605eSJim Ingham return false; 485e37d605eSJim Ingham } 486e37d605eSJim Ingham else if (rhs.m_mod_time.IsValid()) 487e37d605eSJim Ingham return false; 488e37d605eSJim Ingham else 489e37d605eSJim Ingham return true; 490e37d605eSJim Ingham } 491e37d605eSJim Ingham else 492e37d605eSJim Ingham return false; 493e37d605eSJim Ingham } 49430fdc8d8SChris Lattner 49530fdc8d8SChris Lattner bool 49630fdc8d8SChris Lattner SourceManager::File::CalculateLineOffsets (uint32_t line) 49730fdc8d8SChris Lattner { 49830fdc8d8SChris Lattner line = UINT32_MAX; // TODO: take this line out when we support partial indexing 49930fdc8d8SChris Lattner if (line == UINT32_MAX) 50030fdc8d8SChris Lattner { 50130fdc8d8SChris Lattner // Already done? 50230fdc8d8SChris Lattner if (!m_offsets.empty() && m_offsets[0] == UINT32_MAX) 50330fdc8d8SChris Lattner return true; 50430fdc8d8SChris Lattner 50530fdc8d8SChris Lattner if (m_offsets.empty()) 50630fdc8d8SChris Lattner { 50730fdc8d8SChris Lattner if (m_data_sp.get() == NULL) 50830fdc8d8SChris Lattner return false; 50930fdc8d8SChris Lattner 51030fdc8d8SChris Lattner const char *start = (char *)m_data_sp->GetBytes(); 51130fdc8d8SChris Lattner if (start) 51230fdc8d8SChris Lattner { 51330fdc8d8SChris Lattner const char *end = start + m_data_sp->GetByteSize(); 51430fdc8d8SChris Lattner 51530fdc8d8SChris Lattner // Calculate all line offsets from scratch 51630fdc8d8SChris Lattner 51730fdc8d8SChris Lattner // Push a 1 at index zero to indicate the file has been completely indexed. 51830fdc8d8SChris Lattner m_offsets.push_back(UINT32_MAX); 51930fdc8d8SChris Lattner register const char *s; 52030fdc8d8SChris Lattner for (s = start; s < end; ++s) 52130fdc8d8SChris Lattner { 52230fdc8d8SChris Lattner register char curr_ch = *s; 52330fdc8d8SChris Lattner if (is_newline_char (curr_ch)) 52430fdc8d8SChris Lattner { 52530fdc8d8SChris Lattner register char next_ch = s[1]; 52630fdc8d8SChris Lattner if (is_newline_char (next_ch)) 52730fdc8d8SChris Lattner { 52830fdc8d8SChris Lattner if (curr_ch != next_ch) 52930fdc8d8SChris Lattner ++s; 53030fdc8d8SChris Lattner } 53130fdc8d8SChris Lattner m_offsets.push_back(s + 1 - start); 53230fdc8d8SChris Lattner } 53330fdc8d8SChris Lattner } 53430fdc8d8SChris Lattner if (!m_offsets.empty()) 53530fdc8d8SChris Lattner { 53630fdc8d8SChris Lattner if (m_offsets.back() < end - start) 53730fdc8d8SChris Lattner m_offsets.push_back(end - start); 53830fdc8d8SChris Lattner } 53930fdc8d8SChris Lattner return true; 54030fdc8d8SChris Lattner } 54130fdc8d8SChris Lattner } 54230fdc8d8SChris Lattner else 54330fdc8d8SChris Lattner { 54430fdc8d8SChris Lattner // Some lines have been populated, start where we last left off 54530fdc8d8SChris Lattner assert(!"Not implemented yet"); 54630fdc8d8SChris Lattner } 54730fdc8d8SChris Lattner 54830fdc8d8SChris Lattner } 54930fdc8d8SChris Lattner else 55030fdc8d8SChris Lattner { 55130fdc8d8SChris Lattner // Calculate all line offsets up to "line" 55230fdc8d8SChris Lattner assert(!"Not implemented yet"); 55330fdc8d8SChris Lattner } 55430fdc8d8SChris Lattner return false; 55530fdc8d8SChris Lattner } 556e37d605eSJim Ingham 557969795f1SJim Ingham bool 558969795f1SJim Ingham SourceManager::File::GetLine (uint32_t line_no, std::string &buffer) 559969795f1SJim Ingham { 560969795f1SJim Ingham if (!LineIsValid(line_no)) 561969795f1SJim Ingham return false; 562969795f1SJim Ingham 563969795f1SJim Ingham uint32_t start_offset = GetLineOffset (line_no); 564969795f1SJim Ingham uint32_t end_offset = GetLineOffset (line_no + 1); 565969795f1SJim Ingham if (end_offset == UINT32_MAX) 566969795f1SJim Ingham { 567969795f1SJim Ingham end_offset = m_data_sp->GetByteSize(); 568969795f1SJim Ingham } 569969795f1SJim Ingham buffer.assign((char *) m_data_sp->GetBytes() + start_offset, end_offset - start_offset); 570969795f1SJim Ingham 571969795f1SJim Ingham return true; 572969795f1SJim Ingham } 573969795f1SJim Ingham 574e37d605eSJim Ingham void 575e37d605eSJim Ingham SourceManager::SourceFileCache::AddSourceFile (const FileSP &file_sp) 576e37d605eSJim Ingham { 577e37d605eSJim Ingham FileSpec file_spec; 578e37d605eSJim Ingham FileCache::iterator pos = m_file_cache.find(file_spec); 579e37d605eSJim Ingham if (pos == m_file_cache.end()) 580e37d605eSJim Ingham m_file_cache[file_spec] = file_sp; 581e37d605eSJim Ingham else 582e37d605eSJim Ingham { 583e37d605eSJim Ingham if (file_sp != pos->second) 584e37d605eSJim Ingham m_file_cache[file_spec] = file_sp; 585e37d605eSJim Ingham } 586e37d605eSJim Ingham } 587e37d605eSJim Ingham 588e37d605eSJim Ingham SourceManager::FileSP 589e37d605eSJim Ingham SourceManager::SourceFileCache::FindSourceFile (const FileSpec &file_spec) const 590e37d605eSJim Ingham { 591e37d605eSJim Ingham FileSP file_sp; 592e37d605eSJim Ingham FileCache::const_iterator pos = m_file_cache.find(file_spec); 593e37d605eSJim Ingham if (pos != m_file_cache.end()) 594e37d605eSJim Ingham file_sp = pos->second; 595e37d605eSJim Ingham return file_sp; 596e37d605eSJim Ingham } 597e37d605eSJim Ingham 598