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