Add strerrordesc_np() and strerrorname_np().
strerrordesc_np() isn't very useful (being just another name for
strerror()), but strerrorname_np() lets you get "ENOSYS" for ENOSYS,
which will make some of our test assertion messages clearer when we
switch over from strerror().
This also adds `%#m` formatting to all the relevant functions.
Test: treehugger
Change-Id: Icfe07a39a307d591c3f4f2a09d008dc021643062
diff --git a/libc/stdio/printf_common.h b/libc/stdio/printf_common.h
index 365728b..702f8d3 100644
--- a/libc/stdio/printf_common.h
+++ b/libc/stdio/printf_common.h
@@ -786,7 +786,7 @@
//
// Returns NULL on failure.
// To find out what happened check errno for ENOMEM, EILSEQ and EINVAL.
- static wchar_t* mbsconv(char* mbsarg, int prec) {
+ static wchar_t* mbsconv(const char* mbsarg, int prec) {
mbstate_t mbs;
const char* p;
size_t insize, nchars, nconv;
diff --git a/libc/stdio/vfprintf.cpp b/libc/stdio/vfprintf.cpp
index 12cceeb..e0509aa 100644
--- a/libc/stdio/vfprintf.cpp
+++ b/libc/stdio/vfprintf.cpp
@@ -340,6 +340,7 @@
case 'd':
case 'i':
_umax = SARG();
+signed_decimal:
if ((intmax_t)_umax < 0) {
_umax = -_umax;
sign = '-';
@@ -468,7 +469,15 @@
case 'n':
__fortify_fatal("%%n not allowed on Android");
case 'm':
- cp = strerror_r(caller_errno, buf, sizeof(buf));
+ if (flags & ALT) {
+ cp = const_cast<char*>(strerrorname_np(caller_errno));
+ if (cp == nullptr) {
+ _umax = caller_errno;
+ goto signed_decimal;
+ }
+ } else {
+ cp = strerror_r(caller_errno, buf, sizeof(buf));
+ }
goto string;
case 'O':
flags |= LONGINT;
diff --git a/libc/stdio/vfwprintf.cpp b/libc/stdio/vfwprintf.cpp
index d6f6a6b..72f973c 100644
--- a/libc/stdio/vfwprintf.cpp
+++ b/libc/stdio/vfwprintf.cpp
@@ -52,6 +52,19 @@
#include "printf_common.h"
+#define print_utf8(utf8, prec) \
+ do { \
+ free(convbuf); \
+ convbuf = helpers::mbsconv(utf8, prec); \
+ if (convbuf == nullptr) { \
+ fp->_flags |= __SERR; \
+ goto error; \
+ } else { \
+ cp = convbuf; \
+ } \
+ goto string; \
+ } while (0)
+
int FUNCTION_NAME(FILE* fp, const CHAR_TYPE* fmt0, va_list ap) {
int caller_errno = errno;
int n, n2;
@@ -319,6 +332,7 @@
case 'd':
case 'i':
_umax = SARG();
+signed_decimal:
if ((intmax_t)_umax < 0) {
_umax = -_umax;
sign = '-';
@@ -447,16 +461,13 @@
case 'n':
__fortify_fatal("%%n not allowed on Android");
case 'm':
- free(convbuf);
- convbuf = helpers::mbsconv(strerror_r(caller_errno,
- reinterpret_cast<char*>(buf), sizeof(buf)), prec);
- if (convbuf == nullptr) {
- fp->_flags |= __SERR;
- goto error;
- } else {
- cp = convbuf;
+ if (flags & ALT) {
+ const char* name = strerrorname_np(caller_errno);
+ if (name) print_utf8(name, prec);
+ _umax = caller_errno;
+ goto signed_decimal;
}
- goto string;
+ print_utf8(strerror_r(caller_errno, reinterpret_cast<char*>(buf), sizeof(buf)), prec);
case 'O':
flags |= LONGINT;
__BIONIC_FALLTHROUGH;
@@ -486,14 +497,7 @@
} else {
char* mbsarg;
if ((mbsarg = GETARG(char*)) == nullptr) mbsarg = const_cast<char*>("(null)");
- free(convbuf);
- convbuf = helpers::mbsconv(mbsarg, prec);
- if (convbuf == nullptr) {
- fp->_flags |= __SERR;
- goto error;
- } else {
- cp = convbuf;
- }
+ print_utf8(mbsarg, prec);
}
string:
if (prec >= 0) {