const char * MR_strerror(int errnum, char *buf, size_t buflen) { #if defined(MR_HAVE_STRERROR_S) /* ** MSVC has strerror_s. It also exists in C11 Annex K and is enabled by ** defining a preprocessor macro __STDC_WANT_LIB_EXT1__ */ if (strerror_s(buf, buflen, errnum) != 0) { generic_strerror(buf, buflen, errnum); } return buf; #elif defined(MR_HAVE_STRERROR_R) /* ** The XSI-compliant and Mac OS X strerror_r populates buf unless it fails. ** The GNU-specific strerror_r does not always populate buf. */ #if !defined(__GNU_LIBRARY__) || \ ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE) int x = strerror_r(errnum, buf, buflen); if (x != 0) { generic_strerror(buf, buflen, errnum); } return buf; #else const char *s = strerror_r(errnum, buf, buflen); return s; #endif #else /* ** Fallback using deprecated variables. This is used on MinGW at least. ** ** strerror_l is another thread-safe alternative, specified in POSIX. ** It is locale-sensitive and takes a locale argument so we don't use it ** for now. */ if (errnum >= 0 && errnum < sys_nerr && sys_errlist[errnum] != NULL) { return sys_errlist[errnum]; } else { generic_strerror(buf, buflen, errnum); return buf; } #endif }
const char * MR_strerror(int errnum, char *buf, size_t buflen) { #if defined(MR_HAVE_STRERROR_S) && !defined(MR_MINGW) // MSVC has strerror_s. It also exists in C11 Annex K and is enabled by // defining a preprocessor macro __STDC_WANT_LIB_EXT1__ // // On MinGW-w64, strerror_s results in an undefined reference to strerror_s // in MSVCRT.DLL on Windows XP. Avoid it until we drop support for XP. if (strerror_s(buf, buflen, errnum) != 0) { generic_strerror(buf, buflen, errnum); } return buf; #elif defined(MR_HAVE_STRERROR_R) // The XSI-compliant and Mac OS X strerror_r populates buf unless it fails. // The GNU-specific strerror_r does not always populate buf. #if !defined(__GNU_LIBRARY__) || \ ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE) int x = strerror_r(errnum, buf, buflen); if (x != 0) { generic_strerror(buf, buflen, errnum); } return buf; #else const char *s = strerror_r(errnum, buf, buflen); return s; #endif #else // Fallback using deprecated variables. This is used on MinGW at least. // // strerror_l is another thread-safe alternative, specified in POSIX. // It is locale-sensitive and takes a locale argument so we don't use it // for now. if (errnum >= 0 && errnum < sys_nerr && sys_errlist[errnum] != NULL) { return sys_errlist[errnum]; } else { generic_strerror(buf, buflen, errnum); return buf; } #endif }