1*30fdc8d8SChris Lattner //===-- SourceManager.cpp ---------------------------------------*- C++ -*-===// 2*30fdc8d8SChris Lattner // 3*30fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 4*30fdc8d8SChris Lattner // 5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 7*30fdc8d8SChris Lattner // 8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 9*30fdc8d8SChris Lattner 10*30fdc8d8SChris Lattner #include "lldb/Core/SourceManager.h" 11*30fdc8d8SChris Lattner 12*30fdc8d8SChris Lattner // C Includes 13*30fdc8d8SChris Lattner // C++ Includes 14*30fdc8d8SChris Lattner // Other libraries and framework includes 15*30fdc8d8SChris Lattner // Project includes 16*30fdc8d8SChris Lattner #include "lldb/Core/DataBuffer.h" 17*30fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 18*30fdc8d8SChris Lattner 19*30fdc8d8SChris Lattner using namespace lldb_private; 20*30fdc8d8SChris Lattner 21*30fdc8d8SChris Lattner static inline bool is_newline_char(char ch) 22*30fdc8d8SChris Lattner { 23*30fdc8d8SChris Lattner return ch == '\n' || ch == '\r'; 24*30fdc8d8SChris Lattner } 25*30fdc8d8SChris Lattner 26*30fdc8d8SChris Lattner 27*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 28*30fdc8d8SChris Lattner // SourceManager constructor 29*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 30*30fdc8d8SChris Lattner SourceManager::SourceManager() : 31*30fdc8d8SChris Lattner m_file_cache (), 32*30fdc8d8SChris Lattner m_last_file_sp (), 33*30fdc8d8SChris Lattner m_last_file_line (0), 34*30fdc8d8SChris Lattner m_last_file_context_before (0), 35*30fdc8d8SChris Lattner m_last_file_context_after (0) 36*30fdc8d8SChris Lattner { 37*30fdc8d8SChris Lattner } 38*30fdc8d8SChris Lattner 39*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 40*30fdc8d8SChris Lattner // Destructor 41*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 42*30fdc8d8SChris Lattner SourceManager::~SourceManager() 43*30fdc8d8SChris Lattner { 44*30fdc8d8SChris Lattner } 45*30fdc8d8SChris Lattner 46*30fdc8d8SChris Lattner size_t 47*30fdc8d8SChris Lattner SourceManager::DisplaySourceLines 48*30fdc8d8SChris Lattner ( 49*30fdc8d8SChris Lattner const FileSpec &file_spec, 50*30fdc8d8SChris Lattner uint32_t line, 51*30fdc8d8SChris Lattner uint32_t context_before, 52*30fdc8d8SChris Lattner uint32_t context_after, 53*30fdc8d8SChris Lattner Stream *s 54*30fdc8d8SChris Lattner ) 55*30fdc8d8SChris Lattner { 56*30fdc8d8SChris Lattner m_last_file_sp = GetFile (file_spec); 57*30fdc8d8SChris Lattner m_last_file_line = line + context_after + 1; 58*30fdc8d8SChris Lattner m_last_file_context_before = context_before; 59*30fdc8d8SChris Lattner m_last_file_context_after = context_after; 60*30fdc8d8SChris Lattner if (m_last_file_sp.get()) 61*30fdc8d8SChris Lattner return m_last_file_sp->DisplaySourceLines (line, context_before, context_after, s); 62*30fdc8d8SChris Lattner 63*30fdc8d8SChris Lattner return 0; 64*30fdc8d8SChris Lattner } 65*30fdc8d8SChris Lattner 66*30fdc8d8SChris Lattner SourceManager::FileSP 67*30fdc8d8SChris Lattner SourceManager::GetFile (const FileSpec &file_spec) 68*30fdc8d8SChris Lattner { 69*30fdc8d8SChris Lattner FileSP file_sp; 70*30fdc8d8SChris Lattner FileCache::iterator pos = m_file_cache.find(file_spec); 71*30fdc8d8SChris Lattner if (pos != m_file_cache.end()) 72*30fdc8d8SChris Lattner file_sp = pos->second; 73*30fdc8d8SChris Lattner else 74*30fdc8d8SChris Lattner { 75*30fdc8d8SChris Lattner file_sp.reset (new File (file_spec)); 76*30fdc8d8SChris Lattner m_file_cache[file_spec] = file_sp; 77*30fdc8d8SChris Lattner } 78*30fdc8d8SChris Lattner return file_sp; 79*30fdc8d8SChris Lattner } 80*30fdc8d8SChris Lattner 81*30fdc8d8SChris Lattner size_t 82*30fdc8d8SChris Lattner SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile 83*30fdc8d8SChris Lattner ( 84*30fdc8d8SChris Lattner uint32_t line, 85*30fdc8d8SChris Lattner uint32_t context_before, 86*30fdc8d8SChris Lattner uint32_t context_after, 87*30fdc8d8SChris Lattner const char* current_line_cstr, 88*30fdc8d8SChris Lattner Stream *s 89*30fdc8d8SChris Lattner ) 90*30fdc8d8SChris Lattner { 91*30fdc8d8SChris Lattner if (line == 0) 92*30fdc8d8SChris Lattner { 93*30fdc8d8SChris Lattner if (m_last_file_line != 0 94*30fdc8d8SChris Lattner && m_last_file_line != UINT32_MAX) 95*30fdc8d8SChris Lattner line = m_last_file_line + context_before; 96*30fdc8d8SChris Lattner else 97*30fdc8d8SChris Lattner line = 1; 98*30fdc8d8SChris Lattner } 99*30fdc8d8SChris Lattner 100*30fdc8d8SChris Lattner m_last_file_line = line + context_after + 1; 101*30fdc8d8SChris Lattner m_last_file_context_before = context_before; 102*30fdc8d8SChris Lattner m_last_file_context_after = context_after; 103*30fdc8d8SChris Lattner 104*30fdc8d8SChris Lattner if (context_before == UINT32_MAX) 105*30fdc8d8SChris Lattner context_before = 0; 106*30fdc8d8SChris Lattner if (context_after == UINT32_MAX) 107*30fdc8d8SChris Lattner context_after = 10; 108*30fdc8d8SChris Lattner 109*30fdc8d8SChris Lattner if (m_last_file_sp.get()) 110*30fdc8d8SChris Lattner { 111*30fdc8d8SChris Lattner const uint32_t start_line = line <= context_before ? 1 : line - context_before; 112*30fdc8d8SChris Lattner const uint32_t end_line = line + context_after; 113*30fdc8d8SChris Lattner uint32_t curr_line; 114*30fdc8d8SChris Lattner for (curr_line = start_line; curr_line <= end_line; ++curr_line) 115*30fdc8d8SChris Lattner { 116*30fdc8d8SChris Lattner if (!m_last_file_sp->LineIsValid (curr_line)) 117*30fdc8d8SChris Lattner { 118*30fdc8d8SChris Lattner m_last_file_line = UINT32_MAX; 119*30fdc8d8SChris Lattner break; 120*30fdc8d8SChris Lattner } 121*30fdc8d8SChris Lattner 122*30fdc8d8SChris Lattner s->Printf("%4u %2.2s\t", curr_line, curr_line == line ? current_line_cstr : ""); 123*30fdc8d8SChris Lattner if (m_last_file_sp->DisplaySourceLines (curr_line, 0, 0, s) == 0) 124*30fdc8d8SChris Lattner { 125*30fdc8d8SChris Lattner m_last_file_line = UINT32_MAX; 126*30fdc8d8SChris Lattner break; 127*30fdc8d8SChris Lattner } 128*30fdc8d8SChris Lattner } 129*30fdc8d8SChris Lattner } 130*30fdc8d8SChris Lattner return 0; 131*30fdc8d8SChris Lattner } 132*30fdc8d8SChris Lattner 133*30fdc8d8SChris Lattner size_t 134*30fdc8d8SChris Lattner SourceManager::DisplaySourceLinesWithLineNumbers 135*30fdc8d8SChris Lattner ( 136*30fdc8d8SChris Lattner const FileSpec &file_spec, 137*30fdc8d8SChris Lattner uint32_t line, 138*30fdc8d8SChris Lattner uint32_t context_before, 139*30fdc8d8SChris Lattner uint32_t context_after, 140*30fdc8d8SChris Lattner const char* current_line_cstr, 141*30fdc8d8SChris Lattner Stream *s 142*30fdc8d8SChris Lattner ) 143*30fdc8d8SChris Lattner { 144*30fdc8d8SChris Lattner bool same_as_previous = m_last_file_sp && m_last_file_sp->FileSpecMatches (file_spec); 145*30fdc8d8SChris Lattner 146*30fdc8d8SChris Lattner if (!same_as_previous) 147*30fdc8d8SChris Lattner m_last_file_sp = GetFile (file_spec); 148*30fdc8d8SChris Lattner 149*30fdc8d8SChris Lattner if (line == 0) 150*30fdc8d8SChris Lattner { 151*30fdc8d8SChris Lattner if (!same_as_previous) 152*30fdc8d8SChris Lattner m_last_file_line = 0; 153*30fdc8d8SChris Lattner } 154*30fdc8d8SChris Lattner 155*30fdc8d8SChris Lattner return DisplaySourceLinesWithLineNumbersUsingLastFile (line, context_before, context_after, current_line_cstr, s); 156*30fdc8d8SChris Lattner } 157*30fdc8d8SChris Lattner 158*30fdc8d8SChris Lattner size_t 159*30fdc8d8SChris Lattner SourceManager::DisplayMoreWithLineNumbers (Stream *s) 160*30fdc8d8SChris Lattner { 161*30fdc8d8SChris Lattner if (m_last_file_sp) 162*30fdc8d8SChris Lattner { 163*30fdc8d8SChris Lattner if (m_last_file_line == UINT32_MAX) 164*30fdc8d8SChris Lattner return 0; 165*30fdc8d8SChris Lattner DisplaySourceLinesWithLineNumbersUsingLastFile (0, m_last_file_context_before, m_last_file_context_after, "", s); 166*30fdc8d8SChris Lattner } 167*30fdc8d8SChris Lattner return 0; 168*30fdc8d8SChris Lattner } 169*30fdc8d8SChris Lattner 170*30fdc8d8SChris Lattner 171*30fdc8d8SChris Lattner 172*30fdc8d8SChris Lattner SourceManager::File::File(const FileSpec &file_spec) : 173*30fdc8d8SChris Lattner m_file_spec(file_spec), 174*30fdc8d8SChris Lattner m_data_sp(file_spec.ReadFileContents ()), 175*30fdc8d8SChris Lattner m_offsets() 176*30fdc8d8SChris Lattner { 177*30fdc8d8SChris Lattner } 178*30fdc8d8SChris Lattner 179*30fdc8d8SChris Lattner SourceManager::File::~File() 180*30fdc8d8SChris Lattner { 181*30fdc8d8SChris Lattner } 182*30fdc8d8SChris Lattner 183*30fdc8d8SChris Lattner uint32_t 184*30fdc8d8SChris Lattner SourceManager::File::GetLineOffset (uint32_t line) 185*30fdc8d8SChris Lattner { 186*30fdc8d8SChris Lattner if (line == 0) 187*30fdc8d8SChris Lattner return UINT32_MAX; 188*30fdc8d8SChris Lattner 189*30fdc8d8SChris Lattner if (line == 1) 190*30fdc8d8SChris Lattner return 0; 191*30fdc8d8SChris Lattner 192*30fdc8d8SChris Lattner if (CalculateLineOffsets (line)) 193*30fdc8d8SChris Lattner { 194*30fdc8d8SChris Lattner if (line < m_offsets.size()) 195*30fdc8d8SChris Lattner return m_offsets[line - 1]; // yes we want "line - 1" in the index 196*30fdc8d8SChris Lattner } 197*30fdc8d8SChris Lattner return UINT32_MAX; 198*30fdc8d8SChris Lattner } 199*30fdc8d8SChris Lattner 200*30fdc8d8SChris Lattner bool 201*30fdc8d8SChris Lattner SourceManager::File::LineIsValid (uint32_t line) 202*30fdc8d8SChris Lattner { 203*30fdc8d8SChris Lattner if (line == 0) 204*30fdc8d8SChris Lattner return false; 205*30fdc8d8SChris Lattner 206*30fdc8d8SChris Lattner if (CalculateLineOffsets (line)) 207*30fdc8d8SChris Lattner return line < m_offsets.size(); 208*30fdc8d8SChris Lattner return false; 209*30fdc8d8SChris Lattner } 210*30fdc8d8SChris Lattner 211*30fdc8d8SChris Lattner size_t 212*30fdc8d8SChris Lattner SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s) 213*30fdc8d8SChris Lattner { 214*30fdc8d8SChris Lattner const uint32_t start_line = line <= context_before ? 1 : line - context_before; 215*30fdc8d8SChris Lattner const uint32_t start_line_offset = GetLineOffset (start_line); 216*30fdc8d8SChris Lattner if (start_line_offset != UINT32_MAX) 217*30fdc8d8SChris Lattner { 218*30fdc8d8SChris Lattner const uint32_t end_line = line + context_after; 219*30fdc8d8SChris Lattner uint32_t end_line_offset = GetLineOffset (end_line + 1); 220*30fdc8d8SChris Lattner if (end_line_offset == UINT32_MAX) 221*30fdc8d8SChris Lattner end_line_offset = m_data_sp->GetByteSize(); 222*30fdc8d8SChris Lattner 223*30fdc8d8SChris Lattner assert (start_line_offset <= end_line_offset); 224*30fdc8d8SChris Lattner size_t bytes_written = 0; 225*30fdc8d8SChris Lattner if (start_line_offset < end_line_offset) 226*30fdc8d8SChris Lattner { 227*30fdc8d8SChris Lattner size_t count = end_line_offset - start_line_offset; 228*30fdc8d8SChris Lattner const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset; 229*30fdc8d8SChris Lattner bytes_written = s->Write(cstr, count); 230*30fdc8d8SChris Lattner if (!is_newline_char(cstr[count-1])) 231*30fdc8d8SChris Lattner bytes_written += s->EOL(); 232*30fdc8d8SChris Lattner } 233*30fdc8d8SChris Lattner return bytes_written; 234*30fdc8d8SChris Lattner } 235*30fdc8d8SChris Lattner return 0; 236*30fdc8d8SChris Lattner } 237*30fdc8d8SChris Lattner 238*30fdc8d8SChris Lattner bool 239*30fdc8d8SChris Lattner SourceManager::File::FileSpecMatches (const FileSpec &file_spec) 240*30fdc8d8SChris Lattner { 241*30fdc8d8SChris Lattner return FileSpec::Compare (m_file_spec, file_spec, false) == 0; 242*30fdc8d8SChris Lattner } 243*30fdc8d8SChris Lattner 244*30fdc8d8SChris Lattner 245*30fdc8d8SChris Lattner bool 246*30fdc8d8SChris Lattner SourceManager::File::CalculateLineOffsets (uint32_t line) 247*30fdc8d8SChris Lattner { 248*30fdc8d8SChris Lattner line = UINT32_MAX; // TODO: take this line out when we support partial indexing 249*30fdc8d8SChris Lattner if (line == UINT32_MAX) 250*30fdc8d8SChris Lattner { 251*30fdc8d8SChris Lattner // Already done? 252*30fdc8d8SChris Lattner if (!m_offsets.empty() && m_offsets[0] == UINT32_MAX) 253*30fdc8d8SChris Lattner return true; 254*30fdc8d8SChris Lattner 255*30fdc8d8SChris Lattner if (m_offsets.empty()) 256*30fdc8d8SChris Lattner { 257*30fdc8d8SChris Lattner if (m_data_sp.get() == NULL) 258*30fdc8d8SChris Lattner return false; 259*30fdc8d8SChris Lattner 260*30fdc8d8SChris Lattner const char *start = (char *)m_data_sp->GetBytes(); 261*30fdc8d8SChris Lattner if (start) 262*30fdc8d8SChris Lattner { 263*30fdc8d8SChris Lattner const char *end = start + m_data_sp->GetByteSize(); 264*30fdc8d8SChris Lattner 265*30fdc8d8SChris Lattner // Calculate all line offsets from scratch 266*30fdc8d8SChris Lattner 267*30fdc8d8SChris Lattner // Push a 1 at index zero to indicate the file has been completely indexed. 268*30fdc8d8SChris Lattner m_offsets.push_back(UINT32_MAX); 269*30fdc8d8SChris Lattner register const char *s; 270*30fdc8d8SChris Lattner for (s = start; s < end; ++s) 271*30fdc8d8SChris Lattner { 272*30fdc8d8SChris Lattner register char curr_ch = *s; 273*30fdc8d8SChris Lattner if (is_newline_char (curr_ch)) 274*30fdc8d8SChris Lattner { 275*30fdc8d8SChris Lattner register char next_ch = s[1]; 276*30fdc8d8SChris Lattner if (is_newline_char (next_ch)) 277*30fdc8d8SChris Lattner { 278*30fdc8d8SChris Lattner if (curr_ch != next_ch) 279*30fdc8d8SChris Lattner ++s; 280*30fdc8d8SChris Lattner } 281*30fdc8d8SChris Lattner m_offsets.push_back(s + 1 - start); 282*30fdc8d8SChris Lattner } 283*30fdc8d8SChris Lattner } 284*30fdc8d8SChris Lattner if (!m_offsets.empty()) 285*30fdc8d8SChris Lattner { 286*30fdc8d8SChris Lattner if (m_offsets.back() < end - start) 287*30fdc8d8SChris Lattner m_offsets.push_back(end - start); 288*30fdc8d8SChris Lattner } 289*30fdc8d8SChris Lattner return true; 290*30fdc8d8SChris Lattner } 291*30fdc8d8SChris Lattner } 292*30fdc8d8SChris Lattner else 293*30fdc8d8SChris Lattner { 294*30fdc8d8SChris Lattner // Some lines have been populated, start where we last left off 295*30fdc8d8SChris Lattner assert(!"Not implemented yet"); 296*30fdc8d8SChris Lattner } 297*30fdc8d8SChris Lattner 298*30fdc8d8SChris Lattner } 299*30fdc8d8SChris Lattner else 300*30fdc8d8SChris Lattner { 301*30fdc8d8SChris Lattner // Calculate all line offsets up to "line" 302*30fdc8d8SChris Lattner assert(!"Not implemented yet"); 303*30fdc8d8SChris Lattner } 304*30fdc8d8SChris Lattner return false; 305*30fdc8d8SChris Lattner } 306