rename TGLoc -> SMLoc.
[oota-llvm.git] / lib / Support / SourceMgr.cpp
1 //===- SourceMgr.cpp - Manager for Simple Source Buffers & Diagnostics ----===//
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 //
10 // This file implements the SourceMgr class.  This class is used as a simple
11 // substrate for diagnostics, #include handling, and other low level things for
12 // simple parsers.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/MemoryBuffer.h"
18 #include "llvm/Support/raw_ostream.h"
19 using namespace llvm;
20
21 TGSourceMgr::~TGSourceMgr() {
22   while (!Buffers.empty()) {
23     delete Buffers.back().Buffer;
24     Buffers.pop_back();
25   }
26 }
27
28 /// FindBufferContainingLoc - Return the ID of the buffer containing the
29 /// specified location, returning -1 if not found.
30 int TGSourceMgr::FindBufferContainingLoc(SMLoc Loc) const {
31   for (unsigned i = 0, e = Buffers.size(); i != e; ++i)
32     if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() &&
33         // Use <= here so that a pointer to the null at the end of the buffer
34         // is included as part of the buffer.
35         Loc.getPointer() <= Buffers[i].Buffer->getBufferEnd())
36       return i;
37   return -1;
38 }
39
40 /// FindLineNumber - Find the line number for the specified location in the
41 /// specified file.  This is not a fast method.
42 unsigned TGSourceMgr::FindLineNumber(SMLoc Loc, int BufferID) const {
43   if (BufferID == -1) BufferID = FindBufferContainingLoc(Loc);
44   assert(BufferID != -1 && "Invalid Location!");
45   
46   MemoryBuffer *Buff = getBufferInfo(BufferID).Buffer;
47   
48   // Count the number of \n's between the start of the file and the specified
49   // location.
50   unsigned LineNo = 1;
51   
52   const char *Ptr = Buff->getBufferStart();
53
54   for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr)
55     if (*Ptr == '\n') ++LineNo;
56   return LineNo;
57 }
58
59 void TGSourceMgr::PrintIncludeStack(SMLoc IncludeLoc) const {
60   if (IncludeLoc == SMLoc()) return;  // Top of stack.
61   
62   int CurBuf = FindBufferContainingLoc(IncludeLoc);
63   assert(CurBuf != -1 && "Invalid or unspecified location!");
64
65   PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc);
66   
67   errs() << "Included from "
68          << getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
69          << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n";
70 }
71
72
73 void TGSourceMgr::PrintError(SMLoc ErrorLoc, const std::string &Msg) const {
74   raw_ostream &OS = errs();
75   
76   // First thing to do: find the current buffer containing the specified
77   // location.
78   int CurBuf = FindBufferContainingLoc(ErrorLoc);
79   assert(CurBuf != -1 && "Invalid or unspecified location!");
80   
81   PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc);
82   
83   MemoryBuffer *CurMB = getBufferInfo(CurBuf).Buffer;
84   
85   
86   OS << "Parsing " << CurMB->getBufferIdentifier() << ":"
87      << FindLineNumber(ErrorLoc, CurBuf) << ": ";
88   
89   OS << Msg << "\n";
90   
91   // Scan backward to find the start of the line.
92   const char *LineStart = ErrorLoc.getPointer();
93   while (LineStart != CurMB->getBufferStart() && 
94          LineStart[-1] != '\n' && LineStart[-1] != '\r')
95     --LineStart;
96   // Get the end of the line.
97   const char *LineEnd = ErrorLoc.getPointer();
98   while (LineEnd != CurMB->getBufferEnd() && 
99          LineEnd[0] != '\n' && LineEnd[0] != '\r')
100     ++LineEnd;
101   // Print out the line.
102   OS << std::string(LineStart, LineEnd) << "\n";
103   // Print out spaces before the caret.
104   for (const char *Pos = LineStart; Pos != ErrorLoc.getPointer(); ++Pos)
105     OS << (*Pos == '\t' ? '\t' : ' ');
106   OS << "^\n";
107 }