5 #include <glthread/lock.h>
6 #include <glthread/tls.h>
11 gl_once_define(static, tls_initialized);
12 static gl_tls_key_t tls_key;
15 struct cdecl_error err;
20 /* This error is reserved for extremely dire out-of-memory conditions. */
21 static struct err_state err_no_mem = {
28 const char *cdecl__strerror(unsigned code)
32 assert(code < sizeof offtab / sizeof offtab[0]);
33 assert(offtab[code] != 0);
35 return gettext((char *)&strtab + offtab[code]);
38 static void free_err(void *err)
40 if (err == &err_no_mem)
46 static void set_error(const struct cdecl_error *err)
48 struct err_state *state;
52 need_len = strlen(err->str) + 1;
55 state = gl_tls_get(tls_key);
56 if (state == &err_no_mem)
58 if (!state || state->nstr < need_len) {
59 struct err_state *tmp;
61 tmp = realloc(state, sizeof *state + need_len);
63 /* Re-use the existing state buffer, if any. */
65 state->err = err_no_mem.err;
69 gl_tls_set(tls_key, state);
74 state->nstr = need_len;
75 gl_tls_set(tls_key, state);
80 memcpy(state->str, err->str, need_len);
81 state->err.str = state->str;
83 state->err.str = cdecl__strerror(state->err.code);
87 static void initialize(void)
90 err_no_mem.err.str = cdecl__strerror(CDECL_ENOMEM);
92 gl_tls_key_init(tls_key, free_err);
95 * This default error message is a stop-gap measure until all library
96 * error conditions use the new interface.
98 set_error(&(const struct cdecl_error){ .code = CDECL_ENOPARSE });
101 const struct cdecl_error *cdecl_get_error(void)
103 struct err_state *state;
105 gl_once(tls_initialized, initialize);
107 state = gl_tls_get(tls_key);
113 void cdecl__set_error(const struct cdecl_error *err)
115 gl_once(tls_initialized, initialize);