blob: 4d3e9f31a4867aa4f27e4c3cde6348d7178f2e7c [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- SourceManager.cpp ---------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012#include "lldb/Core/SourceManager.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Core/DataBuffer.h"
Jim Inghame37d6052011-09-13 00:29:56 +000019#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000020#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021#include "lldb/Core/Stream.h"
Sean Callananb6d70eb2011-10-12 02:08:07 +000022#include "lldb/Symbol/ClangNamespaceDecl.h"
Greg Clayton1f746072012-08-29 21:13:06 +000023#include "lldb/Symbol/CompileUnit.h"
24#include "lldb/Symbol/Function.h"
Greg Clayton176761e2011-04-19 04:19:37 +000025#include "lldb/Symbol/SymbolContext.h"
Greg Clayton7e14f912011-04-23 02:04:55 +000026#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027
28using namespace lldb_private;
29
30static inline bool is_newline_char(char ch)
31{
32 return ch == '\n' || ch == '\r';
33}
34
35
36//----------------------------------------------------------------------
37// SourceManager constructor
38//----------------------------------------------------------------------
Jim Inghame37d6052011-09-13 00:29:56 +000039SourceManager::SourceManager(Target &target) :
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040 m_last_file_sp (),
Greg Claytone4ca5152013-03-13 18:25:49 +000041 m_last_line (0),
42 m_last_count (0),
Jim Inghamf3277752011-10-07 22:16:04 +000043 m_default_set(false),
Jim Inghame37d6052011-09-13 00:29:56 +000044 m_target (&target),
45 m_debugger(NULL)
46{
47 m_debugger = &(m_target->GetDebugger());
48}
49
50SourceManager::SourceManager(Debugger &debugger) :
51 m_last_file_sp (),
Greg Claytone4ca5152013-03-13 18:25:49 +000052 m_last_line (0),
53 m_last_count (0),
Jim Inghamf3277752011-10-07 22:16:04 +000054 m_default_set(false),
Jim Inghame37d6052011-09-13 00:29:56 +000055 m_target (NULL),
56 m_debugger (&debugger)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057{
58}
59
60//----------------------------------------------------------------------
61// Destructor
62//----------------------------------------------------------------------
63SourceManager::~SourceManager()
64{
65}
66
Chris Lattner30fdc8d2010-06-08 16:52:24 +000067SourceManager::FileSP
Jim Inghamb7f6b2f2011-09-08 22:13:49 +000068SourceManager::GetFile (const FileSpec &file_spec)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000069{
70 FileSP file_sp;
Jim Inghame37d6052011-09-13 00:29:56 +000071 file_sp = m_debugger->GetSourceFileCache().FindSourceFile (file_spec);
Johnny Chen64bab482011-12-12 21:59:28 +000072 // If file_sp is no good or it points to a non-existent file, reset it.
73 if (!file_sp || !file_sp->GetFileSpec().Exists())
Chris Lattner30fdc8d2010-06-08 16:52:24 +000074 {
Jim Inghamb7f6b2f2011-09-08 22:13:49 +000075 file_sp.reset (new File (file_spec, m_target));
Jim Inghame37d6052011-09-13 00:29:56 +000076
77 m_debugger->GetSourceFileCache().AddSourceFile(file_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000078 }
79 return file_sp;
80}
81
82size_t
Greg Claytone4ca5152013-03-13 18:25:49 +000083SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile (uint32_t start_line,
84 uint32_t count,
85 uint32_t curr_line,
86 const char* current_line_cstr,
87 Stream *s,
88 const SymbolContextList *bp_locs)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089{
Greg Claytone4ca5152013-03-13 18:25:49 +000090 if (count == 0)
91 return 0;
Jim Inghame37d6052011-09-13 00:29:56 +000092 size_t return_value = 0;
Greg Claytone4ca5152013-03-13 18:25:49 +000093 if (start_line == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094 {
Greg Claytone4ca5152013-03-13 18:25:49 +000095 if (m_last_line != 0 && m_last_line != UINT32_MAX)
96 start_line = m_last_line + m_last_count;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000097 else
Greg Claytone4ca5152013-03-13 18:25:49 +000098 start_line = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000099 }
100
Greg Claytone4ca5152013-03-13 18:25:49 +0000101 if (!m_default_set)
102 {
103 FileSpec tmp_spec;
104 uint32_t tmp_line;
105 GetDefaultFileAndLine(tmp_spec, tmp_line);
106 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000107
Greg Claytone4ca5152013-03-13 18:25:49 +0000108 m_last_line = start_line;
109 m_last_count = count;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110
111 if (m_last_file_sp.get())
112 {
Greg Claytone4ca5152013-03-13 18:25:49 +0000113 const uint32_t end_line = start_line + count - 1;
114 for (uint32_t line = start_line; line <= end_line; ++line)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115 {
Greg Claytone4ca5152013-03-13 18:25:49 +0000116 if (!m_last_file_sp->LineIsValid (line))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 {
Greg Claytone4ca5152013-03-13 18:25:49 +0000118 m_last_line = UINT32_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119 break;
120 }
121
Greg Clayton176761e2011-04-19 04:19:37 +0000122 char prefix[32] = "";
123 if (bp_locs)
124 {
Greg Claytone4ca5152013-03-13 18:25:49 +0000125 uint32_t bp_count = bp_locs->NumLineEntriesWithLine (line);
Greg Clayton176761e2011-04-19 04:19:37 +0000126
127 if (bp_count > 0)
128 ::snprintf (prefix, sizeof (prefix), "[%u] ", bp_count);
129 else
130 ::snprintf (prefix, sizeof (prefix), " ");
131 }
132
Jim Inghame37d6052011-09-13 00:29:56 +0000133 return_value += s->Printf("%s%2.2s %-4u\t",
Greg Claytone4ca5152013-03-13 18:25:49 +0000134 prefix,
135 line == curr_line ? current_line_cstr : "",
136 line);
137 size_t this_line_size = m_last_file_sp->DisplaySourceLines (line, 0, 0, s);
Jim Inghame37d6052011-09-13 00:29:56 +0000138 if (this_line_size == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000139 {
Greg Claytone4ca5152013-03-13 18:25:49 +0000140 m_last_line = UINT32_MAX;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141 break;
142 }
Jim Inghame37d6052011-09-13 00:29:56 +0000143 else
144 return_value += this_line_size;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000145 }
146 }
Jim Inghame37d6052011-09-13 00:29:56 +0000147 return return_value;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000148}
149
150size_t
151SourceManager::DisplaySourceLinesWithLineNumbers
152(
153 const FileSpec &file_spec,
154 uint32_t line,
155 uint32_t context_before,
156 uint32_t context_after,
157 const char* current_line_cstr,
Greg Clayton176761e2011-04-19 04:19:37 +0000158 Stream *s,
159 const SymbolContextList *bp_locs
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160)
161{
162 bool same_as_previous = m_last_file_sp && m_last_file_sp->FileSpecMatches (file_spec);
163
164 if (!same_as_previous)
Jim Inghamb7f6b2f2011-09-08 22:13:49 +0000165 m_last_file_sp = GetFile (file_spec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000166
Greg Claytone4ca5152013-03-13 18:25:49 +0000167 uint32_t start_line;
168 uint32_t count = context_before + context_after + 1;
169 if (line > context_before)
170 start_line = line - context_before;
171 else
172 start_line = 1;
173
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174 if (line == 0)
175 {
176 if (!same_as_previous)
Greg Claytone4ca5152013-03-13 18:25:49 +0000177 m_last_line = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178 }
179
Greg Claytone4ca5152013-03-13 18:25:49 +0000180 return DisplaySourceLinesWithLineNumbersUsingLastFile (start_line, count, line, current_line_cstr, s, bp_locs);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000181}
182
183size_t
Greg Claytone4ca5152013-03-13 18:25:49 +0000184SourceManager::DisplayMoreWithLineNumbers (Stream *s,
185 uint32_t count,
186 bool reverse,
187 const SymbolContextList *bp_locs)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188{
Jim Ingham196bbc22013-01-09 03:27:33 +0000189 // If we get called before anybody has set a default file and line, then try to figure it out here.
190 if (!m_default_set)
191 {
192 FileSpec tmp_spec;
193 uint32_t tmp_line;
194 GetDefaultFileAndLine(tmp_spec, tmp_line);
195 }
196
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197 if (m_last_file_sp)
198 {
Greg Claytone4ca5152013-03-13 18:25:49 +0000199 if (m_last_line == UINT32_MAX)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000200 return 0;
Jim Ingham196bbc22013-01-09 03:27:33 +0000201
Greg Claytone4ca5152013-03-13 18:25:49 +0000202 if (reverse && m_last_line == 1)
Jim Ingham196bbc22013-01-09 03:27:33 +0000203 return 0;
Greg Claytone4ca5152013-03-13 18:25:49 +0000204
205 if (count > 0)
206 m_last_count = count;
207 else if (m_last_count == 0)
208 m_last_count = 10;
209
210 if (m_last_line > 0)
Jim Ingham196bbc22013-01-09 03:27:33 +0000211 {
212 if (reverse)
213 {
214 // If this is the first time we've done a reverse, then back up one more time so we end
215 // up showing the chunk before the last one we've shown:
Greg Claytone4ca5152013-03-13 18:25:49 +0000216 if (m_last_line > m_last_count)
217 m_last_line -= m_last_count;
Jim Ingham196bbc22013-01-09 03:27:33 +0000218 else
Greg Claytone4ca5152013-03-13 18:25:49 +0000219 m_last_line = 1;
Jim Ingham196bbc22013-01-09 03:27:33 +0000220 }
221 else
Greg Claytone4ca5152013-03-13 18:25:49 +0000222 m_last_line += m_last_count;
Jim Ingham196bbc22013-01-09 03:27:33 +0000223 }
224 else
Greg Claytone4ca5152013-03-13 18:25:49 +0000225 m_last_line = 1;
Jim Ingham196bbc22013-01-09 03:27:33 +0000226
Greg Claytone4ca5152013-03-13 18:25:49 +0000227 return DisplaySourceLinesWithLineNumbersUsingLastFile (m_last_line, m_last_count, UINT32_MAX, "", s, bp_locs);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228 }
229 return 0;
230}
231
Jim Inghamb7f6b2f2011-09-08 22:13:49 +0000232bool
233SourceManager::SetDefaultFileAndLine (const FileSpec &file_spec, uint32_t line)
234{
235 FileSP old_file_sp = m_last_file_sp;
236 m_last_file_sp = GetFile (file_spec);
Jim Inghamf3277752011-10-07 22:16:04 +0000237
238 m_default_set = true;
Jim Inghamb7f6b2f2011-09-08 22:13:49 +0000239 if (m_last_file_sp)
240 {
Greg Claytone4ca5152013-03-13 18:25:49 +0000241 m_last_line = line;
Jim Inghamb7f6b2f2011-09-08 22:13:49 +0000242 return true;
243 }
244 else
245 {
246 m_last_file_sp = old_file_sp;
247 return false;
248 }
249}
250
251bool
252SourceManager::GetDefaultFileAndLine (FileSpec &file_spec, uint32_t &line)
253{
254 if (m_last_file_sp)
255 {
256 file_spec = m_last_file_sp->GetFileSpec();
Greg Claytone4ca5152013-03-13 18:25:49 +0000257 line = m_last_line;
Jim Inghamb7f6b2f2011-09-08 22:13:49 +0000258 return true;
259 }
Jim Inghamf3277752011-10-07 22:16:04 +0000260 else if (!m_default_set)
261 {
262 // If nobody has set the default file and line then try here. If there's no executable, then we
263 // will try again later when there is one. Otherwise, if we can't find it we won't look again,
264 // somebody will have to set it (for instance when we stop somewhere...)
265 Module *executable_ptr = m_target->GetExecutableModulePointer();
266 if (executable_ptr)
267 {
268 SymbolContextList sc_list;
Jim Inghamf3277752011-10-07 22:16:04 +0000269 ConstString main_name("main");
270 bool symbols_okay = false; // Force it to be a debug symbol.
Sean Callanan9df05fb2012-02-10 22:52:19 +0000271 bool inlines_okay = true;
Jim Inghamf3277752011-10-07 22:16:04 +0000272 bool append = false;
Greg Claytonc7bece562013-01-25 18:06:21 +0000273 size_t num_matches = executable_ptr->FindFunctions (main_name,
274 NULL,
275 lldb::eFunctionNameTypeBase,
276 inlines_okay,
277 symbols_okay,
278 append,
279 sc_list);
280 for (size_t idx = 0; idx < num_matches; idx++)
Jim Inghamf3277752011-10-07 22:16:04 +0000281 {
282 SymbolContext sc;
283 sc_list.GetContextAtIndex(idx, sc);
Greg Clayton6f6bf262011-12-10 21:05:26 +0000284 if (sc.function)
Jim Inghamf3277752011-10-07 22:16:04 +0000285 {
Greg Clayton6f6bf262011-12-10 21:05:26 +0000286 lldb_private::LineEntry line_entry;
287 if (sc.function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry (line_entry))
288 {
289 SetDefaultFileAndLine (line_entry.file,
290 line_entry.line);
291 file_spec = m_last_file_sp->GetFileSpec();
Greg Claytone4ca5152013-03-13 18:25:49 +0000292 line = m_last_line;
Greg Clayton6f6bf262011-12-10 21:05:26 +0000293 return true;
294 }
Jim Inghamf3277752011-10-07 22:16:04 +0000295 }
296 }
Jim Inghamf3277752011-10-07 22:16:04 +0000297 }
Jim Inghamf3277752011-10-07 22:16:04 +0000298 }
Greg Clayton6f6bf262011-12-10 21:05:26 +0000299 return false;
Jim Inghamb7f6b2f2011-09-08 22:13:49 +0000300}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000301
Jim Ingham969795f2011-09-21 01:17:13 +0000302void
303SourceManager::FindLinesMatchingRegex (FileSpec &file_spec,
Greg Claytond804d282012-03-15 21:01:31 +0000304 RegularExpression& regex,
305 uint32_t start_line,
306 uint32_t end_line,
307 std::vector<uint32_t> &match_lines)
Jim Ingham969795f2011-09-21 01:17:13 +0000308{
309 match_lines.clear();
310 FileSP file_sp = GetFile (file_spec);
311 if (!file_sp)
312 return;
313 return file_sp->FindLinesMatchingRegex (regex, start_line, end_line, match_lines);
314}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000315
Greg Clayton7e14f912011-04-23 02:04:55 +0000316SourceManager::File::File(const FileSpec &file_spec, Target *target) :
317 m_file_spec_orig (file_spec),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000318 m_file_spec(file_spec),
Greg Clayton7e14f912011-04-23 02:04:55 +0000319 m_mod_time (file_spec.GetModificationTime()),
320 m_data_sp(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000321 m_offsets()
322{
Greg Clayton7e14f912011-04-23 02:04:55 +0000323 if (!m_mod_time.IsValid())
324 {
Jim Inghame37d6052011-09-13 00:29:56 +0000325 if (target)
326 {
327 if (!file_spec.GetDirectory() && file_spec.GetFilename())
328 {
329 // If this is just a file name, lets see if we can find it in the target:
330 bool check_inlines = false;
331 SymbolContextList sc_list;
332 size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (file_spec.GetFilename().AsCString(),
333 0,
334 check_inlines,
335 lldb::eSymbolContextModule | lldb::eSymbolContextCompUnit,
336 sc_list);
337 bool got_multiple = false;
338 if (num_matches != 0)
339 {
340 if (num_matches > 1)
341 {
342 SymbolContext sc;
343 FileSpec *test_cu_spec = NULL;
344
345 for (unsigned i = 0; i < num_matches; i++)
346 {
347 sc_list.GetContextAtIndex(i, sc);
348 if (sc.comp_unit)
349 {
350 if (test_cu_spec)
351 {
352 if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit))
353 got_multiple = true;
354 break;
355 }
356 else
357 test_cu_spec = sc.comp_unit;
358 }
359 }
360 }
361 if (!got_multiple)
362 {
363 SymbolContext sc;
364 sc_list.GetContextAtIndex (0, sc);
Greg Claytond804d282012-03-15 21:01:31 +0000365 m_file_spec = sc.comp_unit;
Jim Inghame37d6052011-09-13 00:29:56 +0000366 m_mod_time = m_file_spec.GetModificationTime();
367 }
368 }
369 }
Johnny Chen64bab482011-12-12 21:59:28 +0000370 // Try remapping if m_file_spec does not correspond to an existing file.
371 if (!m_file_spec.Exists())
Jim Inghame37d6052011-09-13 00:29:56 +0000372 {
Greg Claytond804d282012-03-15 21:01:31 +0000373 FileSpec new_file_spec;
374 // Check target specific source remappings first, then fall back to
375 // modules objects can have individual path remappings that were detected
376 // when the debug info for a module was found.
377 // then
378 if (target->GetSourcePathMap().FindFile (m_file_spec, new_file_spec) ||
379 target->GetImages().FindSourceFile (m_file_spec, new_file_spec))
Johnny Chen64bab482011-12-12 21:59:28 +0000380 {
Greg Claytond804d282012-03-15 21:01:31 +0000381 m_file_spec = new_file_spec;
Johnny Chen64bab482011-12-12 21:59:28 +0000382 m_mod_time = m_file_spec.GetModificationTime();
383 }
Jim Inghame37d6052011-09-13 00:29:56 +0000384 }
385 }
Greg Clayton7e14f912011-04-23 02:04:55 +0000386 }
387
388 if (m_mod_time.IsValid())
389 m_data_sp = m_file_spec.ReadFileContents ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390}
391
392SourceManager::File::~File()
393{
394}
395
396uint32_t
397SourceManager::File::GetLineOffset (uint32_t line)
398{
399 if (line == 0)
400 return UINT32_MAX;
401
402 if (line == 1)
403 return 0;
404
405 if (CalculateLineOffsets (line))
406 {
407 if (line < m_offsets.size())
408 return m_offsets[line - 1]; // yes we want "line - 1" in the index
409 }
410 return UINT32_MAX;
411}
412
413bool
414SourceManager::File::LineIsValid (uint32_t line)
415{
416 if (line == 0)
417 return false;
418
419 if (CalculateLineOffsets (line))
420 return line < m_offsets.size();
421 return false;
422}
423
424size_t
425SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s)
426{
Greg Clayton9625d082010-12-08 20:16:12 +0000427 // TODO: use host API to sign up for file modifications to anything in our
428 // source cache and only update when we determine a file has been updated.
429 // For now we check each time we want to display info for the file.
430 TimeValue curr_mod_time (m_file_spec.GetModificationTime());
Johnny Chen64bab482011-12-12 21:59:28 +0000431
432 if (curr_mod_time.IsValid() && m_mod_time != curr_mod_time)
Greg Clayton9625d082010-12-08 20:16:12 +0000433 {
434 m_mod_time = curr_mod_time;
435 m_data_sp = m_file_spec.ReadFileContents ();
436 m_offsets.clear();
437 }
438
Johnny Chen64bab482011-12-12 21:59:28 +0000439 // Sanity check m_data_sp before proceeding.
440 if (!m_data_sp)
441 return 0;
442
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000443 const uint32_t start_line = line <= context_before ? 1 : line - context_before;
444 const uint32_t start_line_offset = GetLineOffset (start_line);
445 if (start_line_offset != UINT32_MAX)
446 {
447 const uint32_t end_line = line + context_after;
448 uint32_t end_line_offset = GetLineOffset (end_line + 1);
449 if (end_line_offset == UINT32_MAX)
450 end_line_offset = m_data_sp->GetByteSize();
451
452 assert (start_line_offset <= end_line_offset);
453 size_t bytes_written = 0;
454 if (start_line_offset < end_line_offset)
455 {
456 size_t count = end_line_offset - start_line_offset;
457 const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset;
458 bytes_written = s->Write(cstr, count);
459 if (!is_newline_char(cstr[count-1]))
460 bytes_written += s->EOL();
461 }
462 return bytes_written;
463 }
464 return 0;
465}
466
Jim Ingham969795f2011-09-21 01:17:13 +0000467void
468SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines)
469{
470 TimeValue curr_mod_time (m_file_spec.GetModificationTime());
471 if (m_mod_time != curr_mod_time)
472 {
473 m_mod_time = curr_mod_time;
474 m_data_sp = m_file_spec.ReadFileContents ();
475 m_offsets.clear();
476 }
477
478 match_lines.clear();
479
480 if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line)))
481 return;
482 if (start_line > end_line)
483 return;
484
485 for (uint32_t line_no = start_line; line_no < end_line; line_no++)
486 {
487 std::string buffer;
488 if (!GetLine (line_no, buffer))
489 break;
490 if (regex.Execute(buffer.c_str()))
491 {
492 match_lines.push_back(line_no);
493 }
494 }
495}
496
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000497bool
498SourceManager::File::FileSpecMatches (const FileSpec &file_spec)
499{
Greg Clayton644247c2011-07-07 01:59:51 +0000500 return FileSpec::Equal (m_file_spec, file_spec, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000501}
502
Jim Inghame37d6052011-09-13 00:29:56 +0000503bool
504lldb_private::operator== (const SourceManager::File &lhs, const SourceManager::File &rhs)
505{
506 if (lhs.m_file_spec == rhs.m_file_spec)
507 {
508 if (lhs.m_mod_time.IsValid())
509 {
510 if (rhs.m_mod_time.IsValid())
511 return lhs.m_mod_time == rhs.m_mod_time;
512 else
513 return false;
514 }
515 else if (rhs.m_mod_time.IsValid())
516 return false;
517 else
518 return true;
519 }
520 else
521 return false;
522}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000523
524bool
525SourceManager::File::CalculateLineOffsets (uint32_t line)
526{
527 line = UINT32_MAX; // TODO: take this line out when we support partial indexing
528 if (line == UINT32_MAX)
529 {
530 // Already done?
531 if (!m_offsets.empty() && m_offsets[0] == UINT32_MAX)
532 return true;
533
534 if (m_offsets.empty())
535 {
536 if (m_data_sp.get() == NULL)
537 return false;
538
539 const char *start = (char *)m_data_sp->GetBytes();
540 if (start)
541 {
542 const char *end = start + m_data_sp->GetByteSize();
543
544 // Calculate all line offsets from scratch
545
546 // Push a 1 at index zero to indicate the file has been completely indexed.
547 m_offsets.push_back(UINT32_MAX);
548 register const char *s;
549 for (s = start; s < end; ++s)
550 {
551 register char curr_ch = *s;
552 if (is_newline_char (curr_ch))
553 {
Greg Claytonf6cdd122013-02-07 03:38:34 +0000554 if (s + 1 < end)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000555 {
Greg Claytonf6cdd122013-02-07 03:38:34 +0000556 register char next_ch = s[1];
557 if (is_newline_char (next_ch))
558 {
559 if (curr_ch != next_ch)
560 ++s;
561 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000562 }
563 m_offsets.push_back(s + 1 - start);
564 }
565 }
566 if (!m_offsets.empty())
567 {
568 if (m_offsets.back() < end - start)
569 m_offsets.push_back(end - start);
570 }
571 return true;
572 }
573 }
574 else
575 {
576 // Some lines have been populated, start where we last left off
Greg Claytonc7bece562013-01-25 18:06:21 +0000577 assert("Not implemented yet" == NULL);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000578 }
579
580 }
581 else
582 {
583 // Calculate all line offsets up to "line"
Greg Claytonc7bece562013-01-25 18:06:21 +0000584 assert("Not implemented yet" == NULL);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000585 }
586 return false;
587}
Jim Inghame37d6052011-09-13 00:29:56 +0000588
Jim Ingham969795f2011-09-21 01:17:13 +0000589bool
590SourceManager::File::GetLine (uint32_t line_no, std::string &buffer)
591{
592 if (!LineIsValid(line_no))
593 return false;
594
Greg Claytonc7bece562013-01-25 18:06:21 +0000595 size_t start_offset = GetLineOffset (line_no);
596 size_t end_offset = GetLineOffset (line_no + 1);
Jim Ingham969795f2011-09-21 01:17:13 +0000597 if (end_offset == UINT32_MAX)
598 {
599 end_offset = m_data_sp->GetByteSize();
600 }
601 buffer.assign((char *) m_data_sp->GetBytes() + start_offset, end_offset - start_offset);
602
603 return true;
604}
605
Jim Inghame37d6052011-09-13 00:29:56 +0000606void
607SourceManager::SourceFileCache::AddSourceFile (const FileSP &file_sp)
608{
609 FileSpec file_spec;
610 FileCache::iterator pos = m_file_cache.find(file_spec);
611 if (pos == m_file_cache.end())
612 m_file_cache[file_spec] = file_sp;
613 else
614 {
615 if (file_sp != pos->second)
616 m_file_cache[file_spec] = file_sp;
617 }
618}
619
620SourceManager::FileSP
621SourceManager::SourceFileCache::FindSourceFile (const FileSpec &file_spec) const
622{
623 FileSP file_sp;
624 FileCache::const_iterator pos = m_file_cache.find(file_spec);
625 if (pos != m_file_cache.end())
626 file_sp = pos->second;
627 return file_sp;
628}
629