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 initialize(void)
49 err_no_mem.err.str = cdecl__strerror(CDECL_ENOMEM);
51 gl_tls_key_init(tls_key, free_err);
54 * This default error message is a stop-gap measure until all library
55 * error conditions use the new interface.
57 cdecl__set_error(&(const struct cdecl_error){ .code = CDECL_ENOPARSE });
60 const struct cdecl_error *cdecl_get_error(void)
62 struct err_state *state;
64 gl_once(tls_initialized, initialize);
66 state = gl_tls_get(tls_key);
72 void cdecl__set_error(const struct cdecl_error *err)
74 struct err_state *state;
77 gl_once(tls_initialized, initialize);
80 need_len = strlen(err->str) + 1;
83 state = gl_tls_get(tls_key);
84 if (state == &err_no_mem)
86 if (!state || state->nstr < need_len) {
87 struct err_state *tmp;
89 tmp = realloc(state, sizeof *state + need_len);
91 /* Re-use the existing state buffer, if any. */
93 state->err = err_no_mem.err;
97 gl_tls_set(tls_key, state);
102 state->nstr = need_len;
103 gl_tls_set(tls_key, state);
108 memcpy(state->str, err->str, need_len);
109 state->err.str = state->str;
111 state->err.str = cdecl__strerror(state->err.code);