]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/Error.cpp
Import libxo-0.7.2; add xo_options.7.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Core / Error.cpp
1 //===-- Error.cpp -----------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 #ifdef __APPLE__
12 #include <mach/mach.h>
13 #endif
14
15 // C++ Includes
16 #include <cerrno>
17 #include <cstdarg>
18
19 // Other libraries and framework includes
20 #include "llvm/ADT/SmallVector.h"
21
22 // Project includes
23 #include "lldb/Core/Error.h"
24 #include "lldb/Core/Log.h"
25 #include "lldb/Host/PosixApi.h"
26
27 using namespace lldb;
28 using namespace lldb_private;
29
30 Error::Error() : m_code(0), m_type(eErrorTypeInvalid), m_string() {}
31
32 Error::Error(ValueType err, ErrorType type)
33     : m_code(err), m_type(type), m_string() {}
34
35 Error::Error(const Error &rhs) = default;
36
37 Error::Error(const char *format, ...)
38     : m_code(0), m_type(eErrorTypeInvalid), m_string() {
39   va_list args;
40   va_start(args, format);
41   SetErrorToGenericError();
42   SetErrorStringWithVarArg(format, args);
43   va_end(args);
44 }
45
46 //----------------------------------------------------------------------
47 // Assignment operator
48 //----------------------------------------------------------------------
49 const Error &Error::operator=(const Error &rhs) {
50   if (this != &rhs) {
51     m_code = rhs.m_code;
52     m_type = rhs.m_type;
53     m_string = rhs.m_string;
54   }
55   return *this;
56 }
57
58 //----------------------------------------------------------------------
59 // Assignment operator
60 //----------------------------------------------------------------------
61 const Error &Error::operator=(uint32_t err) {
62   m_code = err;
63   m_type = eErrorTypeMachKernel;
64   m_string.clear();
65   return *this;
66 }
67
68 Error::~Error() = default;
69
70 //----------------------------------------------------------------------
71 // Get the error value as a NULL C string. The error string will be
72 // fetched and cached on demand. The cached error string value will
73 // remain until the error value is changed or cleared.
74 //----------------------------------------------------------------------
75 const char *Error::AsCString(const char *default_error_str) const {
76   if (Success())
77     return nullptr;
78
79   if (m_string.empty()) {
80     const char *s = nullptr;
81     switch (m_type) {
82     case eErrorTypeMachKernel:
83 #if defined(__APPLE__)
84       s = ::mach_error_string(m_code);
85 #endif
86       break;
87
88     case eErrorTypePOSIX:
89       s = ::strerror(m_code);
90       break;
91
92     default:
93       break;
94     }
95     if (s != nullptr)
96       m_string.assign(s);
97   }
98   if (m_string.empty()) {
99     if (default_error_str)
100       m_string.assign(default_error_str);
101     else
102       return nullptr; // User wanted a nullptr string back...
103   }
104   return m_string.c_str();
105 }
106
107 //----------------------------------------------------------------------
108 // Clear the error and any cached error string that it might contain.
109 //----------------------------------------------------------------------
110 void Error::Clear() {
111   m_code = 0;
112   m_type = eErrorTypeInvalid;
113   m_string.clear();
114 }
115
116 //----------------------------------------------------------------------
117 // Access the error value.
118 //----------------------------------------------------------------------
119 Error::ValueType Error::GetError() const { return m_code; }
120
121 //----------------------------------------------------------------------
122 // Access the error type.
123 //----------------------------------------------------------------------
124 ErrorType Error::GetType() const { return m_type; }
125
126 //----------------------------------------------------------------------
127 // Returns true if this object contains a value that describes an
128 // error or otherwise non-success result.
129 //----------------------------------------------------------------------
130 bool Error::Fail() const { return m_code != 0; }
131
132 //----------------------------------------------------------------------
133 // Log the error given a string with format. If the this object
134 // contains an error code, update the error string to contain the
135 // "error: " followed by the formatted string, followed by the error
136 // value and any string that describes the current error. This
137 // allows more context to be given to an error string that remains
138 // cached in this object. Logging always occurs even when the error
139 // code contains a non-error value.
140 //----------------------------------------------------------------------
141 void Error::PutToLog(Log *log, const char *format, ...) {
142   char *arg_msg = nullptr;
143   va_list args;
144   va_start(args, format);
145   ::vasprintf(&arg_msg, format, args);
146   va_end(args);
147
148   if (arg_msg != nullptr) {
149     if (Fail()) {
150       const char *err_str = AsCString();
151       if (err_str == nullptr)
152         err_str = "???";
153
154       SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str,
155                                m_code);
156       if (log != nullptr)
157         log->Error("%s", m_string.c_str());
158     } else {
159       if (log != nullptr)
160         log->Printf("%s err = 0x%8.8x", arg_msg, m_code);
161     }
162     ::free(arg_msg);
163   }
164 }
165
166 //----------------------------------------------------------------------
167 // Log the error given a string with format. If the this object
168 // contains an error code, update the error string to contain the
169 // "error: " followed by the formatted string, followed by the error
170 // value and any string that describes the current error. This
171 // allows more context to be given to an error string that remains
172 // cached in this object. Logging only occurs even when the error
173 // code contains a error value.
174 //----------------------------------------------------------------------
175 void Error::LogIfError(Log *log, const char *format, ...) {
176   if (Fail()) {
177     char *arg_msg = nullptr;
178     va_list args;
179     va_start(args, format);
180     ::vasprintf(&arg_msg, format, args);
181     va_end(args);
182
183     if (arg_msg != nullptr) {
184       const char *err_str = AsCString();
185       if (err_str == nullptr)
186         err_str = "???";
187
188       SetErrorStringWithFormat("%s err = %s (0x%8.8x)", arg_msg, err_str,
189                                m_code);
190       if (log != nullptr)
191         log->Error("%s", m_string.c_str());
192
193       ::free(arg_msg);
194     }
195   }
196 }
197
198 //----------------------------------------------------------------------
199 // Set accesssor for the error value to "err" and the type to
200 // "eErrorTypeMachKernel"
201 //----------------------------------------------------------------------
202 void Error::SetMachError(uint32_t err) {
203   m_code = err;
204   m_type = eErrorTypeMachKernel;
205   m_string.clear();
206 }
207
208 void Error::SetExpressionError(lldb::ExpressionResults result,
209                                const char *mssg) {
210   m_code = result;
211   m_type = eErrorTypeExpression;
212   m_string = mssg;
213 }
214
215 int Error::SetExpressionErrorWithFormat(lldb::ExpressionResults result,
216                                         const char *format, ...) {
217   int length = 0;
218
219   if (format != nullptr && format[0]) {
220     va_list args;
221     va_start(args, format);
222     length = SetErrorStringWithVarArg(format, args);
223     va_end(args);
224   } else {
225     m_string.clear();
226   }
227   m_code = result;
228   m_type = eErrorTypeExpression;
229   return length;
230 }
231
232 //----------------------------------------------------------------------
233 // Set accesssor for the error value and type.
234 //----------------------------------------------------------------------
235 void Error::SetError(ValueType err, ErrorType type) {
236   m_code = err;
237   m_type = type;
238   m_string.clear();
239 }
240
241 //----------------------------------------------------------------------
242 // Update the error value to be "errno" and update the type to
243 // be "POSIX".
244 //----------------------------------------------------------------------
245 void Error::SetErrorToErrno() {
246   m_code = errno;
247   m_type = eErrorTypePOSIX;
248   m_string.clear();
249 }
250
251 //----------------------------------------------------------------------
252 // Update the error value to be LLDB_GENERIC_ERROR and update the type
253 // to be "Generic".
254 //----------------------------------------------------------------------
255 void Error::SetErrorToGenericError() {
256   m_code = LLDB_GENERIC_ERROR;
257   m_type = eErrorTypeGeneric;
258   m_string.clear();
259 }
260
261 //----------------------------------------------------------------------
262 // Set accessor for the error string value for a specific error.
263 // This allows any string to be supplied as an error explanation.
264 // The error string value will remain until the error value is
265 // cleared or a new error value/type is assigned.
266 //----------------------------------------------------------------------
267 void Error::SetErrorString(llvm::StringRef err_str) {
268   if (!err_str.empty()) {
269     // If we have an error string, we should always at least have an error
270     // set to a generic value.
271     if (Success())
272       SetErrorToGenericError();
273   }
274   m_string = err_str;
275 }
276
277 //------------------------------------------------------------------
278 /// Set the current error string to a formatted error string.
279 ///
280 /// @param format
281 ///     A printf style format string
282 //------------------------------------------------------------------
283 int Error::SetErrorStringWithFormat(const char *format, ...) {
284   if (format != nullptr && format[0]) {
285     va_list args;
286     va_start(args, format);
287     int length = SetErrorStringWithVarArg(format, args);
288     va_end(args);
289     return length;
290   } else {
291     m_string.clear();
292   }
293   return 0;
294 }
295
296 int Error::SetErrorStringWithVarArg(const char *format, va_list args) {
297   if (format != nullptr && format[0]) {
298     // If we have an error string, we should always at least have
299     // an error set to a generic value.
300     if (Success())
301       SetErrorToGenericError();
302
303     // Try and fit our error into a 1024 byte buffer first...
304     llvm::SmallVector<char, 1024> buf;
305     buf.resize(1024);
306     // Copy in case our first call to vsnprintf doesn't fit into our
307     // allocated buffer above
308     va_list copy_args;
309     va_copy(copy_args, args);
310     unsigned length = ::vsnprintf(buf.data(), buf.size(), format, args);
311     if (length >= buf.size()) {
312       // The error formatted string didn't fit into our buffer, resize it
313       // to the exact needed size, and retry
314       buf.resize(length + 1);
315       length = ::vsnprintf(buf.data(), buf.size(), format, copy_args);
316       va_end(copy_args);
317       assert(length < buf.size());
318     }
319     m_string.assign(buf.data(), length);
320     va_end(args);
321     return length;
322   } else {
323     m_string.clear();
324   }
325   return 0;
326 }
327
328 //----------------------------------------------------------------------
329 // Returns true if the error code in this object is considered a
330 // successful return value.
331 //----------------------------------------------------------------------
332 bool Error::Success() const { return m_code == 0; }
333
334 bool Error::WasInterrupted() const {
335   return (m_type == eErrorTypePOSIX && m_code == EINTR);
336 }