X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/3df85155e2dbf9307dd64bd222bf74389c45a75c..6d601969de9687819347cf27df8ddf6ab026e4b0:/src/error.c diff --git a/src/error.c b/src/error.c index e18ec80..093f56c 100644 --- a/src/error.c +++ b/src/error.c @@ -1,12 +1,31 @@ +/* + * 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; @@ -14,58 +33,42 @@ static gl_tls_key_t tls_key; struct err_state { struct cdecl_error err; size_t nstr; - char str[]; + char str[FLEXIBLE_ARRAY_MEMBER]; }; /* This error is reserved for extremely dire out-of-memory conditions. */ 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); + switch (code) { + case CDECL_ENOMEM: return gettext(strtab+err_enomem); + case CDECL_ENOPARSE: return gettext(strtab+err_enoparse); + } - /* - * 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 }); + assert(0); } -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 +101,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); +}