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