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 11#include <llvm/Support/ErrorHandling.h> 12#include <llvm/Support/raw_ostream.h> 13#include <llvm/ADT/Twine.h> 14 15#include <algorithm> 16 17#include <ctype.h> 18 19namespace mcld { 20 21//===----------------------------------------------------------------------===// 22// Diagnostic 23Diagnostic::Diagnostic(DiagnosticEngine& pEngine) : m_Engine(pEngine) { 24} 25 26Diagnostic::~Diagnostic() { 27} 28 29// format - format this diagnostic into string, subsituting the formal 30// arguments. The result is appended at on the pOutStr. 31void Diagnostic::format(std::string& pOutStr) const { 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, 40 const char* pEnd) const { 41 unsigned int depth = 0; 42 for (; pBegin != pEnd; ++pBegin) { 43 if (depth == 0 && *pBegin == pVal) 44 return pBegin; 45 if (depth != 0 && *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, 71 const char* pEnd, 72 std::string& pOutStr) const { 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 } else if (ispunct(cur_char[1])) { 81 pOutStr.push_back(cur_char[1]); // %% -> %. 82 cur_char += 2; 83 continue; 84 } 85 86 // skip the %. 87 ++cur_char; 88 89 const char* modifier = NULL; 90 size_t modifier_len = 0; 91 92 // we get a modifier 93 if (!isdigit(*cur_char)) { 94 modifier = cur_char; 95 while (*cur_char == '-' || (*cur_char >= 'a' && *cur_char <= 'z')) 96 ++cur_char; 97 modifier_len = cur_char - modifier; 98 99 // we get an argument 100 if (*cur_char == '{') { 101 ++cur_char; // skip '{' 102 cur_char = findMatch('}', cur_char, pEnd); 103 104 if (cur_char == pEnd) { 105 // DIAG's format error 106 llvm::report_fatal_error( 107 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 (modifier_len != 0) { 128 llvm::report_fatal_error( 129 llvm::Twine("In diagnostic: ") + 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 (modifier_len != 0) { 139 llvm::report_fatal_error( 140 llvm::Twine("In diagnostic: ") + 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 (str == NULL) 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} // namespace mcld 178