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