Home | History | Annotate | Download | only in LD
      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 
     19 namespace mcld {
     20 
     21 //===----------------------------------------------------------------------===//
     22 //  Diagnostic
     23 Diagnostic::Diagnostic(DiagnosticEngine& pEngine) : m_Engine(pEngine) {
     24 }
     25 
     26 Diagnostic::~Diagnostic() {
     27 }
     28 
     29 // format - format this diagnostic into string, subsituting the formal
     30 // arguments. The result is appended at on the pOutStr.
     31 void 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 
     38 const 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.
     70 void 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