1//===- TextDiagnosticPrinter.cpp ------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include <mcld/LD/TextDiagnosticPrinter.h>
10#include <mcld/MC/MCLDInfo.h>
11#include <llvm/Support/Signals.h>
12#include <string>
13
14using namespace mcld;
15
16static const enum llvm::raw_ostream::Colors UnreachableColor = llvm::raw_ostream::RED;
17static const enum llvm::raw_ostream::Colors FatalColor       = llvm::raw_ostream::YELLOW;
18static const enum llvm::raw_ostream::Colors ErrorColor       = llvm::raw_ostream::RED;
19static const enum llvm::raw_ostream::Colors WarningColor     = llvm::raw_ostream::MAGENTA;
20static const enum llvm::raw_ostream::Colors DebugColor       = llvm::raw_ostream::CYAN;
21static const enum llvm::raw_ostream::Colors NoteColor        = llvm::raw_ostream::GREEN;
22static const enum llvm::raw_ostream::Colors IgnoreColor      = llvm::raw_ostream::BLUE;
23
24// Used for changing only the bold attribute.
25static const enum llvm::raw_ostream::Colors SavedColor = llvm::raw_ostream::SAVEDCOLOR;
26
27//===----------------------------------------------------------------------===//
28// TextDiagnosticPrinter
29TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream& pOStream,
30                                             const MCLDInfo& pLDInfo)
31  : m_OStream(pOStream), m_LDInfo(pLDInfo), m_pInput(NULL) {
32}
33
34TextDiagnosticPrinter::~TextDiagnosticPrinter()
35{
36}
37
38/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
39/// capturing it to a log as needed.
40void
41TextDiagnosticPrinter::handleDiagnostic(DiagnosticEngine::Severity pSeverity,
42                                        const Diagnostic& pInfo)
43{
44  DiagnosticPrinter::handleDiagnostic(pSeverity, pInfo);
45
46  std::string out_string;
47  pInfo.format(out_string);
48
49  switch (pSeverity) {
50    case DiagnosticEngine::Unreachable: {
51      m_OStream.changeColor(UnreachableColor, true);
52      m_OStream << "Unreachable: ";
53      m_OStream.resetColor();
54      m_OStream << out_string << "\n";
55      break;
56    }
57    case DiagnosticEngine::Fatal: {
58      m_OStream.changeColor(FatalColor, true);
59      m_OStream << "Fatal: ";
60      m_OStream.resetColor();
61      m_OStream << out_string << "\n";
62      break;
63    }
64    case DiagnosticEngine::Error: {
65      m_OStream.changeColor(ErrorColor, true);
66      m_OStream << "Error: ";
67      m_OStream.resetColor();
68      m_OStream << out_string << "\n";
69      break;
70    }
71    case DiagnosticEngine::Warning: {
72      m_OStream.changeColor(WarningColor, true);
73      m_OStream << "Warning: ";
74      m_OStream.resetColor();
75      m_OStream << out_string << "\n";
76      break;
77    }
78    case DiagnosticEngine::Debug: {
79      // show debug message only if verbose >= 0
80      if (0 <= m_LDInfo.options().verbose()) {
81        m_OStream.changeColor(DebugColor, true);
82        m_OStream << "Debug: ";
83        m_OStream.resetColor();
84        m_OStream << out_string << "\n";
85      }
86      break;
87    }
88    case DiagnosticEngine::Note: {
89      // show ignored message only if verbose >= 1
90      if (1 <= m_LDInfo.options().verbose()) {
91        m_OStream.changeColor(NoteColor, true);
92        m_OStream << "Note: ";
93        m_OStream.resetColor();
94        m_OStream << out_string << "\n";
95      }
96      break;
97    }
98    case DiagnosticEngine::Ignore: {
99      // show ignored message only if verbose >= 2
100      if (2 <= m_LDInfo.options().verbose()) {
101        m_OStream.changeColor(IgnoreColor, true);
102        m_OStream << "Ignore: ";
103        m_OStream.resetColor();
104        m_OStream << out_string << "\n";
105      }
106      break;
107    }
108    default:
109      break;
110  }
111
112  switch (pSeverity) {
113    case DiagnosticEngine::Unreachable: {
114      m_OStream << "\n\n";
115      m_OStream.changeColor(llvm::raw_ostream::YELLOW);
116      m_OStream << "You encounter a bug of MCLinker, please report to:\n"
117                << "  mclinker@googlegroups.com\n";
118      m_OStream.resetColor();
119    }
120    /** fall through **/
121    case DiagnosticEngine::Fatal: {
122      // If we reached here, we are failing ungracefully. Run the interrupt handlers
123      // to make sure any special cleanups get done, in particular that we remove
124      // files registered with RemoveFileOnSignal.
125      llvm::sys::RunInterruptHandlers();
126      exit(1);
127      break;
128    }
129    case DiagnosticEngine::Error: {
130      int16_t error_limit = m_LDInfo.options().maxErrorNum();
131      if ((error_limit != -1) &&
132          (getNumErrors() > static_cast<unsigned>(error_limit))) {
133        m_OStream << "\n\n";
134        m_OStream.changeColor(llvm::raw_ostream::YELLOW);
135        m_OStream << "too many error messages (>" << error_limit << ")...\n";
136        m_OStream.resetColor();
137        llvm::sys::RunInterruptHandlers();
138        exit(1);
139      }
140      break;
141    }
142    case DiagnosticEngine::Warning: {
143      int16_t warning_limit = m_LDInfo.options().maxWarnNum();
144      if ((warning_limit != -1) &&
145          (getNumWarnings() > static_cast<unsigned>(warning_limit))) {
146        m_OStream << "\n\n";
147        m_OStream.changeColor(llvm::raw_ostream::YELLOW);
148        m_OStream << "too many warning messages (>" << warning_limit << ")...\n";
149        m_OStream.resetColor();
150        llvm::sys::RunInterruptHandlers();
151        exit(1);
152      }
153    }
154    default:
155      break;
156  }
157}
158
159void TextDiagnosticPrinter::beginInput(const Input& pInput, const MCLDInfo& pLDInfo)
160{
161  m_pInput = &pInput;
162}
163
164void TextDiagnosticPrinter::endInput()
165{
166  m_pInput = NULL;
167}
168