#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include "libdwflP.h"
static __thread int global_error;
int
dwfl_errno (void)
{
int result = global_error;
global_error = DWFL_E_NOERROR;
return result;
}
INTDEF (dwfl_errno)
struct msgtable
{
#define DWFL_ERROR(name, text) char msg_##name[sizeof text];
DWFL_ERRORS
#undef DWFL_ERROR
};
static const union
{
struct msgtable table;
char strings[
#define DWFL_ERROR(name, text) + sizeof text
DWFL_ERRORS
#undef DWFL_ERROR
];
} msgtable =
{
.table =
{
#define DWFL_ERROR(name, text) text,
DWFL_ERRORS
#undef DWFL_ERROR
}
};
#define msgstr (msgtable.strings)
static const uint_fast16_t msgidx[] =
{
#define DWFL_ERROR(name, text) \
[DWFL_E_##name] = offsetof (struct msgtable, msg_##name),
DWFL_ERRORS
#undef DWFL_ERROR
};
#define nmsgidx (sizeof msgidx / sizeof msgidx[0])
static inline int
canonicalize (Dwfl_Error error)
{
unsigned int value;
switch (error)
{
default:
value = error;
if ((value &~ 0xffff) != 0)
break;
assert (value < nmsgidx);
break;
case DWFL_E_ERRNO:
value = DWFL_E (ERRNO, errno);
break;
case DWFL_E_LIBELF:
value = DWFL_E (LIBELF, elf_errno ());
break;
case DWFL_E_LIBDW:
value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ());
break;
#if 0#endif
}
return value;
}
int
internal_function
__libdwfl_canon_error (Dwfl_Error error)
{
return canonicalize (error);
}
void
internal_function
__libdwfl_seterrno (Dwfl_Error error)
{
global_error = canonicalize (error);
}
static const char *
errnomsg(int error)
{
static char unknown[] = "unknown error";
#ifdef STRERROR_R_CHAR_P
return strerror_r (error, unknown, 0);
#else
static __thread char msg[128];
return strerror_r (error, msg, sizeof (msg)) ? unknown : msg;
#endif
}
const char *
dwfl_errmsg (int error)
{
if (error == 0 || error == -1)
{
int last_error = global_error;
if (error == 0 && last_error == 0)
return NULL;
error = last_error;
global_error = DWFL_E_NOERROR;
}
switch (error &~ 0xffff)
{
case OTHER_ERROR (ERRNO):
return errnomsg (error & 0xffff);
case OTHER_ERROR (LIBELF):
return elf_errmsg (error & 0xffff);
case OTHER_ERROR (LIBDW):
return INTUSE(dwarf_errmsg) (error & 0xffff);
#if 0#endif
}
return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
? error : DWFL_E_UNKNOWN_ERROR]]);
}
INTDEF (dwfl_errmsg)