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