[AD] 4.3 error handling redux |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
Here's another attempt at an error handling API. Since setjmp/longjmp won't
work, and I can't think of any other method to jump out of a user-defined
block, I just went with callbacks. It comes with three callbacks,
AL_ERROR_ABORT (default), AL_ERROR_WARN, and AL_ERROR_IGNORE. The user can
supply their own handler if they wish, and use the function
al_error_set_handler (any consensus on function name conventions yet?).
al_error is used to retrieve the last error code, along with optionally
grabbing a descriptive string of the problem. Getting the error with that
function will clear it. al_error_set is exposed because some user error
handlers and/or addons may want to check the error themselves, before passing
it back down to user code.
The only thing I'm not sure of is what to do with AL_NO_ERROR. OpenAL defines
this for itself, but I'm not sure what else to use.
The code...
#include <signal.h>
#include <stdio.h>
/* public */
typedef enum {
AL_NO_ERROR = 0,
AL_INVALID_PARAM = 1,
AL_INVALID_OBJECT = 2,
AL_GENERIC_ERROR = 255
} AL_ERROR_ENUM;
AL_ERROR_ENUM al_error(const char **str);
void al_error_set(AL_ERROR_ENUM code, const char *str);
void al_error_set_handler(void (*func)());
void AL_ERROR_ABORT(void);
void AL_ERROR_WARN(void);
#define AL_ERROR_IGNORE NULL
/* source only */
static __thread AL_ERROR_ENUM _al_errcode;
static __thread const char *_al_errstr;
static __thread void (*_allegro_error)(void) = AL_ERROR_ABORT;
void al_error_set_handler(void (*func)(void))
{
_allegro_error = func;
}
void AL_ERROR_ABORT(void)
{
const char *str;
AL_ERROR_ENUM code;
code = al_error(&str);
fprintf(stderr, "An error occured!\nCode: %d\nMessage: %s\nAborting\n",
code, str);
abort();
}
void AL_ERROR_WARN(void)
{
const char *str;
AL_ERROR_ENUM code;
code = al_error(&str);
fprintf(stderr, "An error occured!\nCode: %d\nMessage: %s\n", code, str);
al_error_set(code, str);
}
void al_error_set(AL_ERROR_ENUM code, const char *str)
{
_al_errcode = code;
if(!str)
{
switch(code)
{
#define CASE(x) case x: _al_errstr = #x; break
CASE(AL_NO_ERROR);
CASE(AL_INVALID_PARAM);
CASE(AL_INVALID_OBJECT);
CASE(AL_GENERIC_ERROR);
#undef CASE
default:
_al_errstr = "Unknown error";
break;
}
}
else
_al_errstr = str;
if(_allegro_error)
_allegro_error();
}
AL_ERROR_ENUM al_error(const char **str)
{
AL_ERROR_ENUM ret = _al_errcode;
if(str)
*str = _al_errstr;
_al_errcode = AL_NO_ERROR;
_al_errstr = NULL;
return ret;
}