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