[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;
}




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/