/* See LICENSE file for copyright and license details. */ #include "common.h" /** * Get a description of an error * * @param error_code The error code, may be an `errno` value, if * `LIBGAMMA_ERRNO_SET`, the current value of `errno` * will be used * @param buf Buffer that shall be used if a description must be generated * @param bufsize The size of `buf`, 1024 is recommended * @return The description associated with the error code; * can only be `NULL` if `buf` is `NULL`. If the buffer * is insufficient, a truncated but NUL-terminated * description is returned and `errno` is set to `ERANGE`; * `errno` is otherwise unmodified */ const char * libgamma_strerror_r(int error_code, char buf[], size_t bufsize) { const char *desc; int saved_errno; if (error_code == LIBGAMMA_ERRNO_SET) error_code = errno; switch (error_code) { #define X(NAME, DESC)\ case NAME:\ desc = DESC;\ break; LIST_ERRORS(X) #undef X default: desc = NULL; break; } if (desc) return desc; if (error_code >= 0) { saved_errno = errno; desc = _Generic(strerror_r(error_code, buf, bufsize), /* XSI strerror_r */ int: (errno = (int)(intptr_t)strerror_r(error_code, buf, bufsize)) ? NULL : buf, /* GNU strerror_r */ char *: (char *)(intptr_t)strerror_r(error_code, buf, bufsize)); if (desc) { errno = saved_errno; if (!buf || strcmp(buf, "No error information")) return buf; } else if (errno == ERANGE) { return buf; } else { errno = saved_errno; } } if (!buf) return buf; *buf = '\0'; /* TODO what happended here? */ snprintf(buf, bufsize, "Unknown error #%i\n", error_code); return buf; }