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