X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/3df85155e2dbf9307dd64bd222bf74389c45a75c..c9ec41ecea841cac0ad1aa265cdc6859a61c4ac2:/src/error.c diff --git a/src/error.c b/src/error.c index e18ec80..8d26d5b 100644 --- a/src/error.c +++ b/src/error.c @@ -21,51 +21,33 @@ struct err_state { static struct err_state err_no_mem = { .err = { .code = CDECL_ENOMEM, - .str = "failed to allocate memory", + .str = NULL, }, }; -static void free_err(void *err) +const char *cdecl__strerror(unsigned code) { - if (err == &err_no_mem) - return; +# include "errtab.h" - free(err); -} + assert(code < sizeof offtab / sizeof offtab[0]); + assert(offtab[code] != 0); -static void initialize(void) -{ - cdecl__init_i18n(); - err_no_mem.err.str = gettext(err_no_mem.err.str); - - gl_tls_key_init(tls_key, free_err); - - /* - * This default error message is a stop-gap measure until all library - * error conditions use the new interface. - */ - cdecl__set_error(&(const struct cdecl_error){ .code = CDECL_ENOPARSE }); + return gettext((char *)&strtab + offtab[code]); } -const struct cdecl_error *cdecl_get_error(void) +static void free_err(void *err) { - struct err_state *state; - - gl_once(tls_initialized, initialize); - - state = gl_tls_get(tls_key); - assert(state); + if (err == &err_no_mem) + return; - return &state->err; + free(err); } -void cdecl__set_error(const struct cdecl_error *err) +static void set_error(const struct cdecl_error *err) { struct err_state *state; size_t need_len = 0; - gl_once(tls_initialized, initialize); - if (err->str) { need_len = strlen(err->str) + 1; } @@ -98,6 +80,39 @@ void cdecl__set_error(const struct cdecl_error *err) memcpy(state->str, err->str, need_len); state->err.str = state->str; } else { - state->err.str = "unknown error"; + state->err.str = cdecl__strerror(state->err.code); } } + +static void initialize(void) +{ + cdecl__init_i18n(); + err_no_mem.err.str = cdecl__strerror(CDECL_ENOMEM); + + gl_tls_key_init(tls_key, free_err); + + /* + * This default error message is a stop-gap measure until all library + * error conditions use the new interface. + */ + set_error(&(const struct cdecl_error){ .code = CDECL_ENOPARSE }); +} + +const struct cdecl_error *cdecl_get_error(void) +{ + struct err_state *state; + + gl_once(tls_initialized, initialize); + + state = gl_tls_get(tls_key); + assert(state); + + return &state->err; +} + +void cdecl__set_error(const struct cdecl_error *err) +{ + gl_once(tls_initialized, initialize); + + set_error(err); +}