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