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"
19*b6d70ebcSSean 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);
89e37d605eSJim Ingham     if (!file_sp)
9030fdc8d8SChris Lattner     {
91b7f6b2faSJim Ingham         file_sp.reset (new File (file_spec, m_target));
92e37d605eSJim Ingham 
93e37d605eSJim Ingham         m_debugger->GetSourceFileCache().AddSourceFile(file_sp);
9430fdc8d8SChris Lattner     }
9530fdc8d8SChris Lattner     return file_sp;
9630fdc8d8SChris Lattner }
9730fdc8d8SChris Lattner 
9830fdc8d8SChris Lattner size_t
9930fdc8d8SChris Lattner SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile
10030fdc8d8SChris Lattner (
10130fdc8d8SChris Lattner     uint32_t line,
10230fdc8d8SChris Lattner     uint32_t context_before,
10330fdc8d8SChris Lattner     uint32_t context_after,
10430fdc8d8SChris Lattner     const char* current_line_cstr,
105176761e5SGreg Clayton     Stream *s,
106176761e5SGreg Clayton     const SymbolContextList *bp_locs
10730fdc8d8SChris Lattner )
10830fdc8d8SChris Lattner {
109e37d605eSJim Ingham     size_t return_value = 0;
11030fdc8d8SChris Lattner     if (line == 0)
11130fdc8d8SChris Lattner     {
11230fdc8d8SChris Lattner         if (m_last_file_line != 0
11330fdc8d8SChris Lattner             && m_last_file_line != UINT32_MAX)
11430fdc8d8SChris Lattner             line = m_last_file_line + context_before;
11530fdc8d8SChris Lattner         else
11630fdc8d8SChris Lattner             line = 1;
11730fdc8d8SChris Lattner     }
11830fdc8d8SChris Lattner 
11930fdc8d8SChris Lattner     m_last_file_line = line + context_after + 1;
12030fdc8d8SChris Lattner     m_last_file_context_before = context_before;
12130fdc8d8SChris Lattner     m_last_file_context_after = context_after;
12230fdc8d8SChris Lattner 
12330fdc8d8SChris Lattner     if (context_before == UINT32_MAX)
12430fdc8d8SChris Lattner         context_before = 0;
12530fdc8d8SChris Lattner     if (context_after == UINT32_MAX)
12630fdc8d8SChris Lattner         context_after = 10;
12730fdc8d8SChris Lattner 
12830fdc8d8SChris Lattner     if (m_last_file_sp.get())
12930fdc8d8SChris Lattner     {
13030fdc8d8SChris Lattner         const uint32_t start_line = line <= context_before ? 1 : line - context_before;
13130fdc8d8SChris Lattner         const uint32_t end_line = line + context_after;
13230fdc8d8SChris Lattner         uint32_t curr_line;
13330fdc8d8SChris Lattner         for (curr_line = start_line; curr_line <= end_line; ++curr_line)
13430fdc8d8SChris Lattner         {
13530fdc8d8SChris Lattner             if (!m_last_file_sp->LineIsValid (curr_line))
13630fdc8d8SChris Lattner             {
13730fdc8d8SChris Lattner                 m_last_file_line = UINT32_MAX;
13830fdc8d8SChris Lattner                 break;
13930fdc8d8SChris Lattner             }
14030fdc8d8SChris Lattner 
141176761e5SGreg Clayton             char prefix[32] = "";
142176761e5SGreg Clayton             if (bp_locs)
143176761e5SGreg Clayton             {
144176761e5SGreg Clayton                 uint32_t bp_count = bp_locs->NumLineEntriesWithLine (curr_line);
145176761e5SGreg Clayton 
146176761e5SGreg Clayton                 if (bp_count > 0)
147176761e5SGreg Clayton                     ::snprintf (prefix, sizeof (prefix), "[%u] ", bp_count);
148176761e5SGreg Clayton                 else
149176761e5SGreg Clayton                     ::snprintf (prefix, sizeof (prefix), "    ");
150176761e5SGreg Clayton             }
151176761e5SGreg Clayton 
152e37d605eSJim Ingham             return_value += s->Printf("%s%2.2s %-4u\t",
153176761e5SGreg Clayton                       prefix,
154176761e5SGreg Clayton                       curr_line == line ? current_line_cstr : "",
155176761e5SGreg Clayton                       curr_line);
156e37d605eSJim Ingham             size_t this_line_size = m_last_file_sp->DisplaySourceLines (curr_line, 0, 0, s);
157e37d605eSJim Ingham             if (this_line_size == 0)
15830fdc8d8SChris Lattner             {
15930fdc8d8SChris Lattner                 m_last_file_line = UINT32_MAX;
16030fdc8d8SChris Lattner                 break;
16130fdc8d8SChris Lattner             }
162e37d605eSJim Ingham             else
163e37d605eSJim Ingham                 return_value += this_line_size;
16430fdc8d8SChris Lattner         }
16530fdc8d8SChris Lattner     }
166e37d605eSJim Ingham     return return_value;
16730fdc8d8SChris Lattner }
16830fdc8d8SChris Lattner 
16930fdc8d8SChris Lattner size_t
17030fdc8d8SChris Lattner SourceManager::DisplaySourceLinesWithLineNumbers
17130fdc8d8SChris Lattner (
17230fdc8d8SChris Lattner     const FileSpec &file_spec,
17330fdc8d8SChris Lattner     uint32_t line,
17430fdc8d8SChris Lattner     uint32_t context_before,
17530fdc8d8SChris Lattner     uint32_t context_after,
17630fdc8d8SChris Lattner     const char* current_line_cstr,
177176761e5SGreg Clayton     Stream *s,
178176761e5SGreg Clayton     const SymbolContextList *bp_locs
17930fdc8d8SChris Lattner )
18030fdc8d8SChris Lattner {
18130fdc8d8SChris Lattner     bool same_as_previous = m_last_file_sp && m_last_file_sp->FileSpecMatches (file_spec);
18230fdc8d8SChris Lattner 
18330fdc8d8SChris Lattner     if (!same_as_previous)
184b7f6b2faSJim Ingham         m_last_file_sp = GetFile (file_spec);
18530fdc8d8SChris Lattner 
18630fdc8d8SChris Lattner     if (line == 0)
18730fdc8d8SChris Lattner     {
18830fdc8d8SChris Lattner         if (!same_as_previous)
18930fdc8d8SChris Lattner             m_last_file_line = 0;
19030fdc8d8SChris Lattner     }
19130fdc8d8SChris Lattner 
192176761e5SGreg Clayton     return DisplaySourceLinesWithLineNumbersUsingLastFile (line, context_before, context_after, current_line_cstr, s, bp_locs);
19330fdc8d8SChris Lattner }
19430fdc8d8SChris Lattner 
19530fdc8d8SChris Lattner size_t
196176761e5SGreg Clayton SourceManager::DisplayMoreWithLineNumbers (Stream *s, const SymbolContextList *bp_locs)
19730fdc8d8SChris Lattner {
19830fdc8d8SChris Lattner     if (m_last_file_sp)
19930fdc8d8SChris Lattner     {
20030fdc8d8SChris Lattner         if (m_last_file_line == UINT32_MAX)
20130fdc8d8SChris Lattner             return 0;
202e37d605eSJim Ingham         return DisplaySourceLinesWithLineNumbersUsingLastFile (0, m_last_file_context_before, m_last_file_context_after, "", s, bp_locs);
20330fdc8d8SChris Lattner     }
20430fdc8d8SChris Lattner     return 0;
20530fdc8d8SChris Lattner }
20630fdc8d8SChris Lattner 
207b7f6b2faSJim Ingham bool
208b7f6b2faSJim Ingham SourceManager::SetDefaultFileAndLine (const FileSpec &file_spec, uint32_t line)
209b7f6b2faSJim Ingham {
210b7f6b2faSJim Ingham     FileSP old_file_sp = m_last_file_sp;
211b7f6b2faSJim Ingham     m_last_file_sp = GetFile (file_spec);
212f3277750SJim Ingham 
213f3277750SJim Ingham     m_default_set = true;
214b7f6b2faSJim Ingham     if (m_last_file_sp)
215b7f6b2faSJim Ingham     {
216b7f6b2faSJim Ingham         m_last_file_line = line;
217b7f6b2faSJim Ingham         return true;
218b7f6b2faSJim Ingham     }
219b7f6b2faSJim Ingham     else
220b7f6b2faSJim Ingham     {
221b7f6b2faSJim Ingham         m_last_file_sp = old_file_sp;
222b7f6b2faSJim Ingham         return false;
223b7f6b2faSJim Ingham     }
224b7f6b2faSJim Ingham }
225b7f6b2faSJim Ingham 
226b7f6b2faSJim Ingham bool
227b7f6b2faSJim Ingham SourceManager::GetDefaultFileAndLine (FileSpec &file_spec, uint32_t &line)
228b7f6b2faSJim Ingham {
229b7f6b2faSJim Ingham     if (m_last_file_sp)
230b7f6b2faSJim Ingham     {
231b7f6b2faSJim Ingham         file_spec = m_last_file_sp->GetFileSpec();
232b7f6b2faSJim Ingham         line = m_last_file_line;
233b7f6b2faSJim Ingham         return true;
234b7f6b2faSJim Ingham     }
235f3277750SJim Ingham     else if (!m_default_set)
236f3277750SJim Ingham     {
237f3277750SJim Ingham         // If nobody has set the default file and line then try here.  If there's no executable, then we
238f3277750SJim Ingham         // will try again later when there is one.  Otherwise, if we can't find it we won't look again,
239f3277750SJim Ingham         // somebody will have to set it (for instance when we stop somewhere...)
240f3277750SJim Ingham         Module *executable_ptr = m_target->GetExecutableModulePointer();
241f3277750SJim Ingham         if (executable_ptr)
242f3277750SJim Ingham         {
243f3277750SJim Ingham             SymbolContextList sc_list;
244f3277750SJim Ingham             uint32_t num_matches;
245f3277750SJim Ingham             ConstString main_name("main");
246f3277750SJim Ingham             bool symbols_okay = false;  // Force it to be a debug symbol.
247f3277750SJim Ingham             bool append = false;
248*b6d70ebcSSean Callanan             num_matches = executable_ptr->FindFunctions (main_name, NULL, lldb::eFunctionNameTypeBase, symbols_okay, append, sc_list);
249f3277750SJim Ingham             for (uint32_t idx = 0; idx < num_matches; idx++)
250f3277750SJim Ingham             {
251f3277750SJim Ingham                 SymbolContext sc;
252f3277750SJim Ingham                 sc_list.GetContextAtIndex(idx, sc);
253f3277750SJim Ingham                 if (sc.line_entry.file)
254f3277750SJim Ingham                 {
255f3277750SJim Ingham                     SetDefaultFileAndLine(sc.line_entry.file, sc.line_entry.line);
256f3277750SJim Ingham                     break;
257f3277750SJim Ingham                 }
258f3277750SJim Ingham             }
259f3277750SJim Ingham             return GetDefaultFileAndLine (file_spec, line);
260f3277750SJim Ingham         }
261f3277750SJim Ingham         else
262f3277750SJim Ingham             return false;
263f3277750SJim Ingham     }
264b7f6b2faSJim Ingham     else
265b7f6b2faSJim Ingham         return false;
266b7f6b2faSJim Ingham }
26730fdc8d8SChris Lattner 
268969795f1SJim Ingham void
269969795f1SJim Ingham SourceManager::FindLinesMatchingRegex (FileSpec &file_spec,
270969795f1SJim Ingham                         RegularExpression& regex,
271969795f1SJim Ingham                         uint32_t start_line,
272969795f1SJim Ingham                         uint32_t end_line,
273969795f1SJim Ingham                         std::vector<uint32_t> &match_lines)
274969795f1SJim Ingham {
275969795f1SJim Ingham     match_lines.clear();
276969795f1SJim Ingham     FileSP file_sp = GetFile (file_spec);
277969795f1SJim Ingham     if (!file_sp)
278969795f1SJim Ingham         return;
279969795f1SJim Ingham     return file_sp->FindLinesMatchingRegex (regex, start_line, end_line, match_lines);
280969795f1SJim Ingham }
28130fdc8d8SChris Lattner 
2827e14f91dSGreg Clayton SourceManager::File::File(const FileSpec &file_spec, Target *target) :
2837e14f91dSGreg Clayton     m_file_spec_orig (file_spec),
28430fdc8d8SChris Lattner     m_file_spec(file_spec),
2857e14f91dSGreg Clayton     m_mod_time (file_spec.GetModificationTime()),
2867e14f91dSGreg Clayton     m_data_sp(),
28730fdc8d8SChris Lattner     m_offsets()
28830fdc8d8SChris Lattner {
2897e14f91dSGreg Clayton     if (!m_mod_time.IsValid())
2907e14f91dSGreg Clayton     {
291e37d605eSJim Ingham         if (target)
292e37d605eSJim Ingham         {
293e37d605eSJim Ingham             if (!file_spec.GetDirectory() && file_spec.GetFilename())
294e37d605eSJim Ingham             {
295e37d605eSJim Ingham                 // If this is just a file name, lets see if we can find it in the target:
296e37d605eSJim Ingham                 bool check_inlines = false;
297e37d605eSJim Ingham                 SymbolContextList sc_list;
298e37d605eSJim Ingham                 size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (file_spec.GetFilename().AsCString(),
299e37d605eSJim Ingham                                                                                           0,
300e37d605eSJim Ingham                                                                                           check_inlines,
301e37d605eSJim Ingham                                                                                           lldb::eSymbolContextModule | lldb::eSymbolContextCompUnit,
302e37d605eSJim Ingham                                                                                           sc_list);
303e37d605eSJim Ingham                 bool got_multiple = false;
304e37d605eSJim Ingham                 if (num_matches != 0)
305e37d605eSJim Ingham                 {
306e37d605eSJim Ingham                     if (num_matches > 1)
307e37d605eSJim Ingham                     {
308e37d605eSJim Ingham                         SymbolContext sc;
309e37d605eSJim Ingham                         FileSpec *test_cu_spec = NULL;
310e37d605eSJim Ingham 
311e37d605eSJim Ingham                         for (unsigned i = 0; i < num_matches; i++)
312e37d605eSJim Ingham                         {
313e37d605eSJim Ingham                             sc_list.GetContextAtIndex(i, sc);
314e37d605eSJim Ingham                             if (sc.comp_unit)
315e37d605eSJim Ingham                             {
316e37d605eSJim Ingham                                 if (test_cu_spec)
317e37d605eSJim Ingham                                 {
318e37d605eSJim Ingham                                     if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit))
319e37d605eSJim Ingham                                         got_multiple = true;
320e37d605eSJim Ingham                                         break;
321e37d605eSJim Ingham                                 }
322e37d605eSJim Ingham                                 else
323e37d605eSJim Ingham                                     test_cu_spec = sc.comp_unit;
324e37d605eSJim Ingham                             }
325e37d605eSJim Ingham                         }
326e37d605eSJim Ingham                     }
327e37d605eSJim Ingham                     if (!got_multiple)
328e37d605eSJim Ingham                     {
329e37d605eSJim Ingham                         SymbolContext sc;
330e37d605eSJim Ingham                         sc_list.GetContextAtIndex (0, sc);
331e37d605eSJim Ingham                         m_file_spec = static_cast<FileSpec *>(sc.comp_unit);
332e37d605eSJim Ingham                         m_mod_time = m_file_spec.GetModificationTime();
333e37d605eSJim Ingham                     }
334e37d605eSJim Ingham                 }
335e37d605eSJim Ingham             }
336e37d605eSJim Ingham             else
337e37d605eSJim Ingham             {
338e37d605eSJim Ingham                 if (target->GetSourcePathMap().RemapPath(file_spec.GetDirectory(), m_file_spec.GetDirectory()))
3397e14f91dSGreg Clayton                    m_mod_time = file_spec.GetModificationTime();
3407e14f91dSGreg Clayton             }
341e37d605eSJim Ingham         }
342e37d605eSJim Ingham     }
3437e14f91dSGreg Clayton 
3447e14f91dSGreg Clayton     if (m_mod_time.IsValid())
3457e14f91dSGreg Clayton         m_data_sp = m_file_spec.ReadFileContents ();
34630fdc8d8SChris Lattner }
34730fdc8d8SChris Lattner 
34830fdc8d8SChris Lattner SourceManager::File::~File()
34930fdc8d8SChris Lattner {
35030fdc8d8SChris Lattner }
35130fdc8d8SChris Lattner 
35230fdc8d8SChris Lattner uint32_t
35330fdc8d8SChris Lattner SourceManager::File::GetLineOffset (uint32_t line)
35430fdc8d8SChris Lattner {
35530fdc8d8SChris Lattner     if (line == 0)
35630fdc8d8SChris Lattner         return UINT32_MAX;
35730fdc8d8SChris Lattner 
35830fdc8d8SChris Lattner     if (line == 1)
35930fdc8d8SChris Lattner         return 0;
36030fdc8d8SChris Lattner 
36130fdc8d8SChris Lattner     if (CalculateLineOffsets (line))
36230fdc8d8SChris Lattner     {
36330fdc8d8SChris Lattner         if (line < m_offsets.size())
36430fdc8d8SChris Lattner             return m_offsets[line - 1]; // yes we want "line - 1" in the index
36530fdc8d8SChris Lattner     }
36630fdc8d8SChris Lattner     return UINT32_MAX;
36730fdc8d8SChris Lattner }
36830fdc8d8SChris Lattner 
36930fdc8d8SChris Lattner bool
37030fdc8d8SChris Lattner SourceManager::File::LineIsValid (uint32_t line)
37130fdc8d8SChris Lattner {
37230fdc8d8SChris Lattner     if (line == 0)
37330fdc8d8SChris Lattner         return false;
37430fdc8d8SChris Lattner 
37530fdc8d8SChris Lattner     if (CalculateLineOffsets (line))
37630fdc8d8SChris Lattner         return line < m_offsets.size();
37730fdc8d8SChris Lattner     return false;
37830fdc8d8SChris Lattner }
37930fdc8d8SChris Lattner 
38030fdc8d8SChris Lattner size_t
38130fdc8d8SChris Lattner SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s)
38230fdc8d8SChris Lattner {
3839625d08cSGreg Clayton     // TODO: use host API to sign up for file modifications to anything in our
3849625d08cSGreg Clayton     // source cache and only update when we determine a file has been updated.
3859625d08cSGreg Clayton     // For now we check each time we want to display info for the file.
3869625d08cSGreg Clayton     TimeValue curr_mod_time (m_file_spec.GetModificationTime());
3879625d08cSGreg Clayton     if (m_mod_time != curr_mod_time)
3889625d08cSGreg Clayton     {
3899625d08cSGreg Clayton         m_mod_time = curr_mod_time;
3909625d08cSGreg Clayton         m_data_sp = m_file_spec.ReadFileContents ();
3919625d08cSGreg Clayton         m_offsets.clear();
3929625d08cSGreg Clayton     }
3939625d08cSGreg Clayton 
39430fdc8d8SChris Lattner     const uint32_t start_line = line <= context_before ? 1 : line - context_before;
39530fdc8d8SChris Lattner     const uint32_t start_line_offset = GetLineOffset (start_line);
39630fdc8d8SChris Lattner     if (start_line_offset != UINT32_MAX)
39730fdc8d8SChris Lattner     {
39830fdc8d8SChris Lattner         const uint32_t end_line = line + context_after;
39930fdc8d8SChris Lattner         uint32_t end_line_offset = GetLineOffset (end_line + 1);
40030fdc8d8SChris Lattner         if (end_line_offset == UINT32_MAX)
40130fdc8d8SChris Lattner             end_line_offset = m_data_sp->GetByteSize();
40230fdc8d8SChris Lattner 
40330fdc8d8SChris Lattner         assert (start_line_offset <= end_line_offset);
40430fdc8d8SChris Lattner         size_t bytes_written = 0;
40530fdc8d8SChris Lattner         if (start_line_offset < end_line_offset)
40630fdc8d8SChris Lattner         {
40730fdc8d8SChris Lattner             size_t count = end_line_offset - start_line_offset;
40830fdc8d8SChris Lattner             const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset;
40930fdc8d8SChris Lattner             bytes_written = s->Write(cstr, count);
41030fdc8d8SChris Lattner             if (!is_newline_char(cstr[count-1]))
41130fdc8d8SChris Lattner                 bytes_written += s->EOL();
41230fdc8d8SChris Lattner         }
41330fdc8d8SChris Lattner         return bytes_written;
41430fdc8d8SChris Lattner     }
41530fdc8d8SChris Lattner     return 0;
41630fdc8d8SChris Lattner }
41730fdc8d8SChris Lattner 
418969795f1SJim Ingham void
419969795f1SJim Ingham SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines)
420969795f1SJim Ingham {
421969795f1SJim Ingham     TimeValue curr_mod_time (m_file_spec.GetModificationTime());
422969795f1SJim Ingham     if (m_mod_time != curr_mod_time)
423969795f1SJim Ingham     {
424969795f1SJim Ingham         m_mod_time = curr_mod_time;
425969795f1SJim Ingham         m_data_sp = m_file_spec.ReadFileContents ();
426969795f1SJim Ingham         m_offsets.clear();
427969795f1SJim Ingham     }
428969795f1SJim Ingham 
429969795f1SJim Ingham     match_lines.clear();
430969795f1SJim Ingham 
431969795f1SJim Ingham     if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line)))
432969795f1SJim Ingham         return;
433969795f1SJim Ingham     if (start_line > end_line)
434969795f1SJim Ingham         return;
435969795f1SJim Ingham 
436969795f1SJim Ingham     for (uint32_t line_no = start_line; line_no < end_line; line_no++)
437969795f1SJim Ingham     {
438969795f1SJim Ingham         std::string buffer;
439969795f1SJim Ingham         if (!GetLine (line_no, buffer))
440969795f1SJim Ingham             break;
441969795f1SJim Ingham         if (regex.Execute(buffer.c_str()))
442969795f1SJim Ingham         {
443969795f1SJim Ingham             match_lines.push_back(line_no);
444969795f1SJim Ingham         }
445969795f1SJim Ingham     }
446969795f1SJim Ingham }
447969795f1SJim Ingham 
44830fdc8d8SChris Lattner bool
44930fdc8d8SChris Lattner SourceManager::File::FileSpecMatches (const FileSpec &file_spec)
45030fdc8d8SChris Lattner {
451644247c1SGreg Clayton     return FileSpec::Equal (m_file_spec, file_spec, false);
45230fdc8d8SChris Lattner }
45330fdc8d8SChris Lattner 
454e37d605eSJim Ingham bool
455e37d605eSJim Ingham lldb_private::operator== (const SourceManager::File &lhs, const SourceManager::File &rhs)
456e37d605eSJim Ingham {
457e37d605eSJim Ingham     if (lhs.m_file_spec == rhs.m_file_spec)
458e37d605eSJim Ingham     {
459e37d605eSJim Ingham         if (lhs.m_mod_time.IsValid())
460e37d605eSJim Ingham         {
461e37d605eSJim Ingham             if (rhs.m_mod_time.IsValid())
462e37d605eSJim Ingham                 return lhs.m_mod_time == rhs.m_mod_time;
463e37d605eSJim Ingham             else
464e37d605eSJim Ingham                 return false;
465e37d605eSJim Ingham         }
466e37d605eSJim Ingham         else if (rhs.m_mod_time.IsValid())
467e37d605eSJim Ingham             return false;
468e37d605eSJim Ingham         else
469e37d605eSJim Ingham             return true;
470e37d605eSJim Ingham     }
471e37d605eSJim Ingham     else
472e37d605eSJim Ingham         return false;
473e37d605eSJim Ingham }
47430fdc8d8SChris Lattner 
47530fdc8d8SChris Lattner bool
47630fdc8d8SChris Lattner SourceManager::File::CalculateLineOffsets (uint32_t line)
47730fdc8d8SChris Lattner {
47830fdc8d8SChris Lattner     line = UINT32_MAX;  // TODO: take this line out when we support partial indexing
47930fdc8d8SChris Lattner     if (line == UINT32_MAX)
48030fdc8d8SChris Lattner     {
48130fdc8d8SChris Lattner         // Already done?
48230fdc8d8SChris Lattner         if (!m_offsets.empty() && m_offsets[0] == UINT32_MAX)
48330fdc8d8SChris Lattner             return true;
48430fdc8d8SChris Lattner 
48530fdc8d8SChris Lattner         if (m_offsets.empty())
48630fdc8d8SChris Lattner         {
48730fdc8d8SChris Lattner             if (m_data_sp.get() == NULL)
48830fdc8d8SChris Lattner                 return false;
48930fdc8d8SChris Lattner 
49030fdc8d8SChris Lattner             const char *start = (char *)m_data_sp->GetBytes();
49130fdc8d8SChris Lattner             if (start)
49230fdc8d8SChris Lattner             {
49330fdc8d8SChris Lattner                 const char *end = start + m_data_sp->GetByteSize();
49430fdc8d8SChris Lattner 
49530fdc8d8SChris Lattner                 // Calculate all line offsets from scratch
49630fdc8d8SChris Lattner 
49730fdc8d8SChris Lattner                 // Push a 1 at index zero to indicate the file has been completely indexed.
49830fdc8d8SChris Lattner                 m_offsets.push_back(UINT32_MAX);
49930fdc8d8SChris Lattner                 register const char *s;
50030fdc8d8SChris Lattner                 for (s = start; s < end; ++s)
50130fdc8d8SChris Lattner                 {
50230fdc8d8SChris Lattner                     register char curr_ch = *s;
50330fdc8d8SChris Lattner                     if (is_newline_char (curr_ch))
50430fdc8d8SChris Lattner                     {
50530fdc8d8SChris Lattner                         register char next_ch = s[1];
50630fdc8d8SChris Lattner                         if (is_newline_char (next_ch))
50730fdc8d8SChris Lattner                         {
50830fdc8d8SChris Lattner                             if (curr_ch != next_ch)
50930fdc8d8SChris Lattner                                 ++s;
51030fdc8d8SChris Lattner                         }
51130fdc8d8SChris Lattner                         m_offsets.push_back(s + 1 - start);
51230fdc8d8SChris Lattner                     }
51330fdc8d8SChris Lattner                 }
51430fdc8d8SChris Lattner                 if (!m_offsets.empty())
51530fdc8d8SChris Lattner                 {
51630fdc8d8SChris Lattner                     if (m_offsets.back() < end - start)
51730fdc8d8SChris Lattner                         m_offsets.push_back(end - start);
51830fdc8d8SChris Lattner                 }
51930fdc8d8SChris Lattner                 return true;
52030fdc8d8SChris Lattner             }
52130fdc8d8SChris Lattner         }
52230fdc8d8SChris Lattner         else
52330fdc8d8SChris Lattner         {
52430fdc8d8SChris Lattner             // Some lines have been populated, start where we last left off
52530fdc8d8SChris Lattner             assert(!"Not implemented yet");
52630fdc8d8SChris Lattner         }
52730fdc8d8SChris Lattner 
52830fdc8d8SChris Lattner     }
52930fdc8d8SChris Lattner     else
53030fdc8d8SChris Lattner     {
53130fdc8d8SChris Lattner         // Calculate all line offsets up to "line"
53230fdc8d8SChris Lattner         assert(!"Not implemented yet");
53330fdc8d8SChris Lattner     }
53430fdc8d8SChris Lattner     return false;
53530fdc8d8SChris Lattner }
536e37d605eSJim Ingham 
537969795f1SJim Ingham bool
538969795f1SJim Ingham SourceManager::File::GetLine (uint32_t line_no, std::string &buffer)
539969795f1SJim Ingham {
540969795f1SJim Ingham     if (!LineIsValid(line_no))
541969795f1SJim Ingham         return false;
542969795f1SJim Ingham 
543969795f1SJim Ingham     uint32_t start_offset = GetLineOffset (line_no);
544969795f1SJim Ingham     uint32_t end_offset = GetLineOffset (line_no + 1);
545969795f1SJim Ingham     if (end_offset == UINT32_MAX)
546969795f1SJim Ingham     {
547969795f1SJim Ingham         end_offset = m_data_sp->GetByteSize();
548969795f1SJim Ingham     }
549969795f1SJim Ingham     buffer.assign((char *) m_data_sp->GetBytes() + start_offset, end_offset - start_offset);
550969795f1SJim Ingham 
551969795f1SJim Ingham     return true;
552969795f1SJim Ingham }
553969795f1SJim Ingham 
554e37d605eSJim Ingham void
555e37d605eSJim Ingham SourceManager::SourceFileCache::AddSourceFile (const FileSP &file_sp)
556e37d605eSJim Ingham {
557e37d605eSJim Ingham     FileSpec file_spec;
558e37d605eSJim Ingham     FileCache::iterator pos = m_file_cache.find(file_spec);
559e37d605eSJim Ingham     if (pos == m_file_cache.end())
560e37d605eSJim Ingham         m_file_cache[file_spec] = file_sp;
561e37d605eSJim Ingham     else
562e37d605eSJim Ingham     {
563e37d605eSJim Ingham         if (file_sp != pos->second)
564e37d605eSJim Ingham             m_file_cache[file_spec] = file_sp;
565e37d605eSJim Ingham     }
566e37d605eSJim Ingham }
567e37d605eSJim Ingham 
568e37d605eSJim Ingham SourceManager::FileSP
569e37d605eSJim Ingham SourceManager::SourceFileCache::FindSourceFile (const FileSpec &file_spec) const
570e37d605eSJim Ingham {
571e37d605eSJim Ingham     FileSP file_sp;
572e37d605eSJim Ingham     FileCache::const_iterator pos = m_file_cache.find(file_spec);
573e37d605eSJim Ingham     if (pos != m_file_cache.end())
574e37d605eSJim Ingham         file_sp = pos->second;
575e37d605eSJim Ingham     return file_sp;
576e37d605eSJim Ingham }
577e37d605eSJim Ingham 
578