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