Diagnostic.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
1//===- Diagnostic.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/Diagnostic.h> 10#include <llvm/Support/ErrorHandling.h> 11#include <llvm/Support/raw_ostream.h> 12#include <llvm/ADT/Twine.h> 13#include <ctype.h> 14#include <algorithm> 15 16using namespace mcld; 17 18//===----------------------------------------------------------------------===// 19// Diagnostic 20Diagnostic::Diagnostic(DiagnosticEngine& pEngine) 21 : m_Engine(pEngine) { 22} 23 24Diagnostic::~Diagnostic() 25{ 26} 27 28// format - format this diagnostic into string, subsituting the formal 29// arguments. The result is appended at on the pOutStr. 30void Diagnostic::format(std::string& pOutStr) const 31{ 32 // we've not implemented DWARF LOC messages yet. So, keep pIsLoC false 33 llvm::StringRef desc = m_Engine.infoMap().getDescription(getID(), false); 34 35 format(desc.begin(), desc.end(), pOutStr); 36} 37 38const char* Diagnostic::findMatch(char pVal, 39 const char* pBegin, const char* pEnd ) const 40{ 41 unsigned int depth = 0; 42 for (; pBegin != pEnd; ++pBegin) { 43 if (0 == depth && *pBegin == pVal) 44 return pBegin; 45 if (0 != depth && *pBegin == '}') 46 --depth; 47 48 if ('%' == *pBegin) { 49 ++pBegin; 50 if (pBegin == pEnd) 51 break; 52 53 if (!isdigit(*pBegin) && !ispunct(*pBegin)) { 54 ++pBegin; 55 while (pBegin != pEnd && !isdigit(*pBegin) && *pBegin != '{') 56 ++pBegin; 57 58 if (pBegin == pEnd) 59 break; 60 if ('{' == *pBegin) 61 ++depth; 62 } 63 } 64 } // end of for 65 return pEnd; 66} 67 68// format - format the given formal string, subsituting the formal 69// arguments. The result is appended at on the pOutStr. 70void Diagnostic::format(const char* pBegin, const char* pEnd, 71 std::string& pOutStr) const 72{ 73 const char* cur_char = pBegin; 74 while (cur_char != pEnd) { 75 if ('%' != *cur_char) { 76 const char* new_end = std::find(cur_char, pEnd, '%'); 77 pOutStr.append(cur_char, new_end); 78 cur_char = new_end; 79 continue; 80 } 81 else if (ispunct(cur_char[1])) { 82 pOutStr.push_back(cur_char[1]); // %% -> %. 83 cur_char += 2; 84 continue; 85 } 86 87 // skip the %. 88 ++cur_char; 89 90 const char* modifier = NULL; 91 size_t modifier_len = 0; 92 93 // we get a modifier 94 if (!isdigit(*cur_char)) { 95 modifier = cur_char; 96 while (*cur_char == '-' || (*cur_char >= 'a' && *cur_char <= 'z')) 97 ++cur_char; 98 modifier_len = cur_char - modifier; 99 100 // we get an argument 101 if ('{' == *cur_char) { 102 ++cur_char; // skip '{' 103 cur_char = findMatch('}', cur_char, pEnd); 104 105 if (cur_char == pEnd) { 106 // DIAG's format error 107 llvm::report_fatal_error(llvm::Twine("Mismatched {} in the diagnostic: ") + 108 llvm::Twine(getID())); 109 } 110 111 ++cur_char; // skip '}' 112 } 113 } 114 if (!isdigit(*cur_char)) { 115 llvm::report_fatal_error(llvm::Twine("In diagnostic: ") + 116 llvm::Twine(getID()) + llvm::Twine(": ") + 117 llvm::Twine(pBegin) + 118 llvm::Twine("\nNo given arugment number:\n")); 119 } 120 121 unsigned int arg_no = *cur_char - '0'; 122 ++cur_char; // skip argument number 123 124 DiagnosticEngine::ArgumentKind kind = getArgKind(arg_no); 125 switch (kind) { 126 case DiagnosticEngine::ak_std_string: { 127 if (0 != modifier_len) { 128 llvm::report_fatal_error(llvm::Twine("In diagnostic: ") + 129 llvm::Twine(getID()) + 130 llvm::Twine(": ") + llvm::Twine(pBegin) + 131 llvm::Twine("\nNo modifiers for strings yet\n")); 132 } 133 const std::string& str = getArgStdStr(arg_no); 134 pOutStr.append(str.begin(), str.end()); 135 break; 136 } 137 case DiagnosticEngine::ak_c_string: { 138 if (0 != modifier_len) { 139 llvm::report_fatal_error(llvm::Twine("In diagnostic: ") + 140 llvm::Twine(getID()) + 141 llvm::Twine(": ") + llvm::Twine(pBegin) + 142 llvm::Twine("\nNo modifiers for strings yet\n")); 143 } 144 const char* str = getArgCStr(arg_no); 145 if (NULL == str) 146 str = "(null)"; 147 pOutStr.append(str); 148 break; 149 } 150 case DiagnosticEngine::ak_sint: { 151 int val = getArgSInt(arg_no); 152 llvm::raw_string_ostream(pOutStr) << val; 153 break; 154 } 155 case DiagnosticEngine::ak_uint: { 156 unsigned int val = getArgUInt(arg_no); 157 llvm::raw_string_ostream(pOutStr) << val; 158 break; 159 } 160 case DiagnosticEngine::ak_ulonglong: { 161 unsigned long long val = getArgUInt(arg_no); 162 llvm::raw_string_ostream(pOutStr) << val; 163 break; 164 } 165 case DiagnosticEngine::ak_bool: { 166 bool val = getArgBool(arg_no); 167 if (val) 168 pOutStr.append("true"); 169 else 170 pOutStr.append("false"); 171 break; 172 } 173 } // end of switch 174 } // end of while 175} 176 177