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