X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/3df85155e2dbf9307dd64bd222bf74389c45a75c..0c61f9637a469ac7a28b5a329551b03e6ad14d62:/src/error.c diff --git a/src/error.c b/src/error.c index e18ec80..9b89bac 100644 --- a/src/error.c +++ b/src/error.c @@ -1,12 +1,30 @@ +/* + * Error handling for libcdecl. + * Copyright © 2011-2012, 2021 Nick Bowler + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include #include #include #include #include #include + #include "cdecl.h" -#include "error.h" -#include "i18n.h" +#include "cdecl-internal.h" gl_once_define(static, tls_initialized); static gl_tls_key_t tls_key; @@ -21,51 +39,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) -{ - if (err == &err_no_mem) - return; - - free(err); -} - -static void initialize(void) +const char *cdecl__strerror(unsigned code) { - cdecl__init_i18n(); - err_no_mem.err.str = gettext(err_no_mem.err.str); +# include "errtab.h" - gl_tls_key_init(tls_key, free_err); + assert(code < sizeof offtab / sizeof offtab[0]); + assert(offtab[code] != 0); - /* - * 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 +98,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); +}