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 16 using namespace mcld; 17 18 //===----------------------------------------------------------------------===// 19 // Diagnostic 20 Diagnostic::Diagnostic(DiagnosticEngine& pEngine) 21 : m_Engine(pEngine) { 22 } 23 24 Diagnostic::~Diagnostic() 25 { 26 } 27 28 // format - format this diagnostic into string, subsituting the formal 29 // arguments. The result is appended at on the pOutStr. 30 void 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 38 const 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. 70 void 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, *argument = NULL; 91 size_t modifier_len = 0, argument_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 argument = cur_char; 104 cur_char = findMatch('}', cur_char, pEnd); 105 106 if (cur_char == pEnd) { 107 // DIAG's format error 108 llvm::report_fatal_error(llvm::Twine("Mismatched {} in the diagnostic: ") + 109 llvm::Twine(getID())); 110 } 111 112 argument_len = cur_char - argument; 113 ++cur_char; // skip '}' 114 } 115 } 116 if (!isdigit(*cur_char)) { 117 llvm::report_fatal_error(llvm::Twine("In diagnostic: ") + 118 llvm::Twine(getID()) + llvm::Twine(": ") + 119 llvm::Twine(pBegin) + 120 llvm::Twine("\nNo given arugment number:\n")); 121 } 122 123 unsigned int arg_no = *cur_char - '0'; 124 ++cur_char; // skip argument number 125 126 DiagnosticEngine::ArgumentKind kind = getArgKind(arg_no); 127 switch (kind) { 128 case DiagnosticEngine::ak_std_string: { 129 if (0 != modifier_len) { 130 llvm::report_fatal_error(llvm::Twine("In diagnostic: ") + 131 llvm::Twine(getID()) + 132 llvm::Twine(": ") + llvm::Twine(pBegin) + 133 llvm::Twine("\nNo modifiers for strings yet\n")); 134 } 135 const std::string& str = getArgStdStr(arg_no); 136 pOutStr.append(str.begin(), str.end()); 137 break; 138 } 139 case DiagnosticEngine::ak_c_string: { 140 if (0 != modifier_len) { 141 llvm::report_fatal_error(llvm::Twine("In diagnostic: ") + 142 llvm::Twine(getID()) + 143 llvm::Twine(": ") + llvm::Twine(pBegin) + 144 llvm::Twine("\nNo modifiers for strings yet\n")); 145 } 146 const char* str = getArgCStr(arg_no); 147 if (NULL == str) 148 str = "(null)"; 149 pOutStr.append(str); 150 break; 151 } 152 case DiagnosticEngine::ak_sint: { 153 int val = getArgSInt(arg_no); 154 llvm::raw_string_ostream(pOutStr) << val; 155 break; 156 } 157 case DiagnosticEngine::ak_uint: { 158 unsigned int val = getArgUInt(arg_no); 159 llvm::raw_string_ostream(pOutStr) << val; 160 break; 161 } 162 case DiagnosticEngine::ak_bool: { 163 bool val = getArgBool(arg_no); 164 if (val) 165 pOutStr.append("true"); 166 else 167 pOutStr.append("false"); 168 break; 169 } 170 } // end of switch 171 } // end of while 172 } 173 174