1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
/* 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:\
return DESC;
LIST_ERRORS(X)
#undef X
default:
break;
}
if (bufsize)
*buf = '\0';
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 == buf && (!bufsize || !*buf))
desc = NULL;
if (desc) {
errno = saved_errno;
if (!desc || strcmp(desc, "No error information"))
return desc;
} else if (errno == ERANGE) {
return buf;
} else {
errno = saved_errno;
}
}
if (!bufsize)
return NULL;
snprintf(buf, bufsize, "Unknown error #%i", error_code);
return buf;
}
|