emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/android 5a3f009ad70 2/2: ; Update from Gnulib


From: Po Lu
Subject: feature/android 5a3f009ad70 2/2: ; Update from Gnulib
Date: Sun, 14 May 2023 23:14:28 -0400 (EDT)

branch: feature/android
commit 5a3f009ad70d87366889e977d3b7d13f01b93e69
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    ; Update from Gnulib
---
 lib/fseterr.h         |    5 +
 lib/gnulib.mk.in      |   10 +-
 lib/isnand-nolibm.h   |    5 +
 lib/isnanf-nolibm.h   |    5 +
 lib/isnanl-nolibm.h   |    5 +
 lib/math.in.h         |   14 +-
 lib/printf-args.c     |  123 ++++
 lib/printf-args.h     |   59 +-
 lib/printf-parse.c    |  497 +++++++++-------
 lib/printf-parse.h    |    8 +-
 lib/size_max.h        |    5 +
 lib/vasnprintf.c      | 1578 +++++++++++++++++++++++++++++++++++++++++++------
 lib/vasnprintf.h      |    5 +
 lib/xsize.h           |    8 +-
 m4/exponentd.m4       |    4 +-
 m4/exponentf.m4       |    4 +-
 m4/exponentl.m4       |    4 +-
 m4/gnulib-comp.m4     |   19 +-
 m4/printf-posix.m4    |   36 ++
 m4/printf.m4          |  540 ++++++++++++++---
 m4/vasnprintf.m4      |  132 ++++-
 m4/vasprintf-posix.m4 |   80 +--
 m4/vfprintf-posix.m4  |   76 ++-
 23 files changed, 2644 insertions(+), 578 deletions(-)

diff --git a/lib/fseterr.h b/lib/fseterr.h
index 0e9d2060aef..87dc347332d 100644
--- a/lib/fseterr.h
+++ b/lib/fseterr.h
@@ -17,6 +17,11 @@
 #ifndef _FSETERR_H
 #define _FSETERR_H
 
+/* This file uses HAVE___FSETERR.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
 #include <stdio.h>
 
 /* Set the error indicator of the stream FP.
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index e447a2c4054..1f59f02b1e9 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -186,6 +186,8 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
 ANDROID = @ANDROID@
 ANDROID_ABI = @ANDROID_ABI@
 ANDROID_BUILD_CFLAGS = @ANDROID_BUILD_CFLAGS@
+ANDROID_CC = @ANDROID_CC@
+ANDROID_CFLAGS = @ANDROID_CFLAGS@
 ANDROID_DEBUGGABLE = @ANDROID_DEBUGGABLE@
 ANDROID_JAR = @ANDROID_JAR@
 ANDROID_LDFLAGS = @ANDROID_LDFLAGS@
@@ -194,6 +196,7 @@ ANDROID_MIN_SDK = @ANDROID_MIN_SDK@
 ANDROID_OBJ = @ANDROID_OBJ@
 ANDROID_SDK_18_OR_EARLIER = @ANDROID_SDK_18_OR_EARLIER@
 ANDROID_SDK_8_OR_EARLIER = @ANDROID_SDK_8_OR_EARLIER@
+ANDROID_SHARED_USER_ID = @ANDROID_SHARED_USER_ID@
 APKSIGNER = @APKSIGNER@
 APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
 AR = @AR@
@@ -1193,7 +1196,6 @@ LIB_WSOCK32 = @LIB_WSOCK32@
 LIB_XATTR = @LIB_XATTR@
 LIMITS_H = @LIMITS_H@
 LN_S_FILEONLY = @LN_S_FILEONLY@
-LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@
 LTLIBGMP = @LTLIBGMP@
 LTLIBINTL = @LTLIBINTL@
 LTLIBOBJS = @LTLIBOBJS@
@@ -1495,11 +1497,8 @@ REPLACE_REMAINDERL = @REPLACE_REMAINDERL@
 REPLACE_REMOVE = @REPLACE_REMOVE@
 REPLACE_RENAME = @REPLACE_RENAME@
 REPLACE_RENAMEAT = @REPLACE_RENAMEAT@
-<<<<<<< HEAD
-REPLACE_RINTL = @REPLACE_RINTL@
-=======
 REPLACE_REWINDDIR = @REPLACE_REWINDDIR@
->>>>>>> origin/master
+REPLACE_RINTL = @REPLACE_RINTL@
 REPLACE_RMDIR = @REPLACE_RMDIR@
 REPLACE_ROUND = @REPLACE_ROUND@
 REPLACE_ROUNDF = @REPLACE_ROUNDF@
@@ -1682,6 +1681,7 @@ datarootdir = @datarootdir@
 docdir = @docdir@
 dvidir = @dvidir@
 emacs_major_version = @emacs_major_version@
+emacs_use_mailutils = @emacs_use_mailutils@
 etcdir = @etcdir@
 etcdocdir = @etcdocdir@
 exec_prefix = @exec_prefix@
diff --git a/lib/isnand-nolibm.h b/lib/isnand-nolibm.h
index 9c75a8c47bf..bb5a38b39f0 100644
--- a/lib/isnand-nolibm.h
+++ b/lib/isnand-nolibm.h
@@ -14,6 +14,11 @@
    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
+/* This file uses HAVE_ISNAND_IN_LIBC.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
 #if HAVE_ISNAND_IN_LIBC
 /* Get declaration of isnan macro.  */
 # include <math.h>
diff --git a/lib/isnanf-nolibm.h b/lib/isnanf-nolibm.h
index cc6b4198ff1..f4bcba143e6 100644
--- a/lib/isnanf-nolibm.h
+++ b/lib/isnanf-nolibm.h
@@ -14,6 +14,11 @@
    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
+/* This file uses HAVE_ISNANF_IN_LIBC.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
 #if HAVE_ISNANF_IN_LIBC
 /* Get declaration of isnan macro or (older) isnanf function.  */
 # include <math.h>
diff --git a/lib/isnanl-nolibm.h b/lib/isnanl-nolibm.h
index f04c489bb8e..8becc5b409e 100644
--- a/lib/isnanl-nolibm.h
+++ b/lib/isnanl-nolibm.h
@@ -14,6 +14,11 @@
    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
+/* This file uses HAVE_ISNANL_IN_LIBC.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
 #if HAVE_ISNANL_IN_LIBC
 /* Get declaration of isnan macro or (older) isnanl function.  */
 # include <math.h>
diff --git a/lib/math.in.h b/lib/math.in.h
index 76d48a44437..f841a1356e4 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -48,14 +48,17 @@
 #ifndef _@GUARD_PREFIX@_MATH_H
 #define _@GUARD_PREFIX@_MATH_H
 
+/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE, _GL_ATTRIBUTE_CONST,
+   GNULIB_POSIXCHECK, HAVE_RAW_DECL_*.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
 /* On OpenVMS, NAN, INFINITY, and HUGEVAL macros are defined in <fp.h>.  */
 #if defined __VMS && ! defined NAN
 # include <fp.h>
 #endif
 
-#ifndef _GL_INLINE_HEADER_BEGIN
- #error "Please include config.h first."
-#endif
 _GL_INLINE_HEADER_BEGIN
 #ifndef _GL_MATH_INLINE
 # define _GL_MATH_INLINE _GL_INLINE
@@ -2630,6 +2633,11 @@ _GL_MATH_CXX_REAL_FLOATING_DECL_1 (isnan)
 _GL_MATH_CXX_REAL_FLOATING_DECL_2 (isnan, rpl_isnan, bool)
 #    define isnan rpl_isnan
 #    define GNULIB_NAMESPACE_LACKS_ISNAN 1
+#   elif (defined __FreeBSD__ && __clang_major__ >= 14)
+  /* Neither of the two possible _GL_MATH_CXX_REAL_FLOATING_DECL_2 invocations
+     works.  Inline functions are already present in 
/usr/include/c++/v1/math.h,
+     which comes from LLVM.  */
+#    define GNULIB_NAMESPACE_LACKS_ISNAN 1
 #   else
 _GL_MATH_CXX_REAL_FLOATING_DECL_2 (isnan, isnan, bool)
 #   endif
diff --git a/lib/printf-args.c b/lib/printf-args.c
index 5e14f654794..b2b21aeec18 100644
--- a/lib/printf-args.c
+++ b/lib/printf-args.c
@@ -29,6 +29,9 @@
 # include "printf-args.h"
 #endif
 
+/* Get INT_WIDTH.  */
+#include <limits.h>
+
 #ifdef STATIC
 STATIC
 #endif
@@ -71,6 +74,102 @@ PRINTF_FETCHARGS (va_list args, arguments *a)
       case TYPE_ULONGLONGINT:
         ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
         break;
+      case TYPE_INT8_T:
+        #if INT8_WIDTH < INT_WIDTH
+        ap->a.a_int8_t = va_arg (args, /* int8_t */ int);
+        #else
+        ap->a.a_int8_t = va_arg (args, int8_t);
+        #endif
+        break;
+      case TYPE_UINT8_T:
+        #if UINT8_WIDTH < INT_WIDTH
+        ap->a.a_uint8_t = va_arg (args, /* uint8_t */ int);
+        #else
+        ap->a.a_uint8_t = va_arg (args, uint8_t);
+        #endif
+        break;
+      case TYPE_INT16_T:
+        #if INT16_WIDTH < INT_WIDTH
+        ap->a.a_int16_t = va_arg (args, /* int16_t */ int);
+        #else
+        ap->a.a_int16_t = va_arg (args, int16_t);
+        #endif
+        break;
+      case TYPE_UINT16_T:
+        #if UINT16_WIDTH < INT_WIDTH
+        ap->a.a_uint16_t = va_arg (args, /* uint16_t */ int);
+        #else
+        ap->a.a_uint16_t = va_arg (args, uint16_t);
+        #endif
+        break;
+      case TYPE_INT32_T:
+        #if INT32_WIDTH < INT_WIDTH
+        ap->a.a_int32_t = va_arg (args, /* int32_t */ int);
+        #else
+        ap->a.a_int32_t = va_arg (args, int32_t);
+        #endif
+        break;
+      case TYPE_UINT32_T:
+        #if UINT32_WIDTH < INT_WIDTH
+        ap->a.a_uint32_t = va_arg (args, /* uint32_t */ int);
+        #else
+        ap->a.a_uint32_t = va_arg (args, uint32_t);
+        #endif
+        break;
+      case TYPE_INT64_T:
+        ap->a.a_int64_t = va_arg (args, int64_t);
+        break;
+      case TYPE_UINT64_T:
+        ap->a.a_uint64_t = va_arg (args, uint64_t);
+        break;
+      case TYPE_INT_FAST8_T:
+        #if INT_FAST8_WIDTH < INT_WIDTH
+        ap->a.a_int_fast8_t = va_arg (args, /* int_fast8_t */ int);
+        #else
+        ap->a.a_int_fast8_t = va_arg (args, int_fast8_t);
+        #endif
+        break;
+      case TYPE_UINT_FAST8_T:
+        #if UINT_FAST8_WIDTH < INT_WIDTH
+        ap->a.a_uint_fast8_t = va_arg (args, /* uint_fast8_t */ int);
+        #else
+        ap->a.a_uint_fast8_t = va_arg (args, uint_fast8_t);
+        #endif
+        break;
+      case TYPE_INT_FAST16_T:
+        #if INT_FAST16_WIDTH < INT_WIDTH
+        ap->a.a_int_fast16_t = va_arg (args, /* int_fast16_t */ int);
+        #else
+        ap->a.a_int_fast16_t = va_arg (args, int_fast16_t);
+        #endif
+        break;
+      case TYPE_UINT_FAST16_T:
+        #if UINT_FAST16_WIDTH < INT_WIDTH
+        ap->a.a_uint_fast16_t = va_arg (args, /* uint_fast16_t */ int);
+        #else
+        ap->a.a_uint_fast16_t = va_arg (args, uint_fast16_t);
+        #endif
+        break;
+      case TYPE_INT_FAST32_T:
+        #if INT_FAST32_WIDTH < INT_WIDTH
+        ap->a.a_int_fast32_t = va_arg (args, /* int_fast32_t */ int);
+        #else
+        ap->a.a_int_fast32_t = va_arg (args, int_fast32_t);
+        #endif
+        break;
+      case TYPE_UINT_FAST32_T:
+        #if UINT_FAST32_WIDTH < INT_WIDTH
+        ap->a.a_uint_fast32_t = va_arg (args, /* uint_fast32_t */ int);
+        #else
+        ap->a.a_uint_fast32_t = va_arg (args, uint_fast32_t);
+        #endif
+        break;
+      case TYPE_INT_FAST64_T:
+        ap->a.a_int_fast64_t = va_arg (args, int_fast64_t);
+        break;
+      case TYPE_UINT_FAST64_T:
+        ap->a.a_uint_fast64_t = va_arg (args, uint_fast64_t);
+        break;
       case TYPE_DOUBLE:
         ap->a.a_double = va_arg (args, double);
         break;
@@ -136,6 +235,30 @@ PRINTF_FETCHARGS (va_list args, arguments *a)
       case TYPE_COUNT_LONGLONGINT_POINTER:
         ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
         break;
+      case TYPE_COUNT_INT8_T_POINTER:
+        ap->a.a_count_int8_t_pointer = va_arg (args, int8_t *);
+        break;
+      case TYPE_COUNT_INT16_T_POINTER:
+        ap->a.a_count_int16_t_pointer = va_arg (args, int16_t *);
+        break;
+      case TYPE_COUNT_INT32_T_POINTER:
+        ap->a.a_count_int32_t_pointer = va_arg (args, int32_t *);
+        break;
+      case TYPE_COUNT_INT64_T_POINTER:
+        ap->a.a_count_int64_t_pointer = va_arg (args, int64_t *);
+        break;
+      case TYPE_COUNT_INT_FAST8_T_POINTER:
+        ap->a.a_count_int_fast8_t_pointer = va_arg (args, int_fast8_t *);
+        break;
+      case TYPE_COUNT_INT_FAST16_T_POINTER:
+        ap->a.a_count_int_fast16_t_pointer = va_arg (args, int_fast16_t *);
+        break;
+      case TYPE_COUNT_INT_FAST32_T_POINTER:
+        ap->a.a_count_int_fast32_t_pointer = va_arg (args, int_fast32_t *);
+        break;
+      case TYPE_COUNT_INT_FAST64_T_POINTER:
+        ap->a.a_count_int_fast64_t_pointer = va_arg (args, int_fast64_t *);
+        break;
 #if ENABLE_UNISTDIO
       /* The unistdio extensions.  */
       case TYPE_U8_STRING:
diff --git a/lib/printf-args.h b/lib/printf-args.h
index f303cb19e9b..11016102828 100644
--- a/lib/printf-args.h
+++ b/lib/printf-args.h
@@ -41,6 +41,9 @@
 # include <wchar.h>
 #endif
 
+/* Get intN_t, uintN_t, intN_fast_t, uintN_fast_t.  */
+#include <stdint.h>
+
 /* Get va_list.  */
 #include <stdarg.h>
 
@@ -59,6 +62,26 @@ typedef enum
   TYPE_ULONGINT,
   TYPE_LONGLONGINT,
   TYPE_ULONGLONGINT,
+  /* According to ISO C 23 § 7.23.6.1, "all exact-width integer types",
+     "all minimum-width integer types", and "all fastest minimum-width integer
+     types" defined in <stdint.h> should be supported.  But for portability
+     between platforms, we support only those with N = 8, 16, 32, 64.  */
+  TYPE_INT8_T,
+  TYPE_UINT8_T,
+  TYPE_INT16_T,
+  TYPE_UINT16_T,
+  TYPE_INT32_T,
+  TYPE_UINT32_T,
+  TYPE_INT64_T,
+  TYPE_UINT64_T,
+  TYPE_INT_FAST8_T,
+  TYPE_UINT_FAST8_T,
+  TYPE_INT_FAST16_T,
+  TYPE_UINT_FAST16_T,
+  TYPE_INT_FAST32_T,
+  TYPE_UINT_FAST32_T,
+  TYPE_INT_FAST64_T,
+  TYPE_UINT_FAST64_T,
   TYPE_DOUBLE,
   TYPE_LONGDOUBLE,
   TYPE_CHAR,
@@ -74,7 +97,15 @@ typedef enum
   TYPE_COUNT_SHORT_POINTER,
   TYPE_COUNT_INT_POINTER,
   TYPE_COUNT_LONGINT_POINTER,
-  TYPE_COUNT_LONGLONGINT_POINTER
+  TYPE_COUNT_LONGLONGINT_POINTER,
+  TYPE_COUNT_INT8_T_POINTER,
+  TYPE_COUNT_INT16_T_POINTER,
+  TYPE_COUNT_INT32_T_POINTER,
+  TYPE_COUNT_INT64_T_POINTER,
+  TYPE_COUNT_INT_FAST8_T_POINTER,
+  TYPE_COUNT_INT_FAST16_T_POINTER,
+  TYPE_COUNT_INT_FAST32_T_POINTER,
+  TYPE_COUNT_INT_FAST64_T_POINTER
 #if ENABLE_UNISTDIO
   /* The unistdio extensions.  */
 , TYPE_U8_STRING
@@ -99,7 +130,23 @@ typedef struct
     unsigned long int           a_ulongint;
     long long int               a_longlongint;
     unsigned long long int      a_ulonglongint;
-    float                       a_float;
+    int8_t                      a_int8_t;
+    uint8_t                     a_uint8_t;
+    int16_t                     a_int16_t;
+    uint16_t                    a_uint16_t;
+    int32_t                     a_int32_t;
+    uint32_t                    a_uint32_t;
+    int64_t                     a_int64_t;
+    uint64_t                    a_uint64_t;
+    int_fast8_t                 a_int_fast8_t;
+    uint_fast8_t                a_uint_fast8_t;
+    int_fast16_t                a_int_fast16_t;
+    uint_fast16_t               a_uint_fast16_t;
+    int_fast32_t                a_int_fast32_t;
+    uint_fast32_t               a_uint_fast32_t;
+    int_fast64_t                a_int_fast64_t;
+    uint_fast64_t               a_uint_fast64_t;
+    float                       a_float;                     /* unused */
     double                      a_double;
     long double                 a_longdouble;
     int                         a_char;
@@ -116,6 +163,14 @@ typedef struct
     int *                       a_count_int_pointer;
     long int *                  a_count_longint_pointer;
     long long int *             a_count_longlongint_pointer;
+    int8_t *                    a_count_int8_t_pointer;
+    int16_t *                   a_count_int16_t_pointer;
+    int32_t *                   a_count_int32_t_pointer;
+    int64_t *                   a_count_int64_t_pointer;
+    int_fast8_t *               a_count_int_fast8_t_pointer;
+    int_fast16_t *              a_count_int_fast16_t_pointer;
+    int_fast32_t *              a_count_int_fast32_t_pointer;
+    int_fast64_t *              a_count_int_fast64_t_pointer;
 #if ENABLE_UNISTDIO
     /* The unistdio extensions.  */
     const uint8_t *             a_u8_string;
diff --git a/lib/printf-parse.c b/lib/printf-parse.c
index 3040749abdf..d3f2c3cb5d1 100644
--- a/lib/printf-parse.c
+++ b/lib/printf-parse.c
@@ -326,226 +326,317 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, 
arguments *a)
             arg_type type;
 
             /* Parse argument type/size specifiers.  */
-            {
-              int flags = 0;
-
-              for (;;)
-                {
-                  if (*cp == 'h')
-                    {
-                      flags |= (1 << (flags & 1));
-                      cp++;
-                    }
-                  else if (*cp == 'L')
-                    {
-                      flags |= 4;
-                      cp++;
-                    }
-                  else if (*cp == 'l')
-                    {
-                      flags += 8;
-                      cp++;
-                    }
-                  else if (*cp == 'j')
-                    {
-                      if (sizeof (intmax_t) > sizeof (long))
-                        {
-                          /* intmax_t = long long */
-                          flags += 16;
-                        }
-                      else if (sizeof (intmax_t) > sizeof (int))
-                        {
-                          /* intmax_t = long */
-                          flags += 8;
-                        }
-                      cp++;
-                    }
-                  else if (*cp == 'z' || *cp == 'Z')
-                    {
-                      /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
-                         because the warning facility in gcc-2.95.2 understands
-                         only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784).  */
-                      if (sizeof (size_t) > sizeof (long))
-                        {
-                          /* size_t = long long */
-                          flags += 16;
-                        }
-                      else if (sizeof (size_t) > sizeof (int))
-                        {
-                          /* size_t = long */
-                          flags += 8;
-                        }
-                      cp++;
-                    }
-                  else if (*cp == 't')
-                    {
-                      if (sizeof (ptrdiff_t) > sizeof (long))
-                        {
-                          /* ptrdiff_t = long long */
-                          flags += 16;
-                        }
-                      else if (sizeof (ptrdiff_t) > sizeof (int))
-                        {
-                          /* ptrdiff_t = long */
-                          flags += 8;
-                        }
-                      cp++;
-                    }
+            /* Relevant for the conversion characters d, i.  */
+            arg_type signed_type = TYPE_INT;
+            /* Relevant for the conversion characters b, o, u, x, X.  */
+            arg_type unsigned_type = TYPE_UINT;
+            /* Relevant for the conversion characters n.  */
+            arg_type pointer_type = TYPE_COUNT_INT_POINTER;
+            /* Relevant for the conversion characters a, A, e, E, f, F, g, G.  
*/
+            arg_type floatingpoint_type = TYPE_DOUBLE;
+
+            if (*cp == 'h')
+              {
+                if (cp[1] == 'h')
+                  {
+                    signed_type = TYPE_SCHAR;
+                    unsigned_type = TYPE_UCHAR;
+                    pointer_type = TYPE_COUNT_SCHAR_POINTER;
+                    cp += 2;
+                  }
+                else
+                  {
+                    signed_type = TYPE_SHORT;
+                    unsigned_type = TYPE_USHORT;
+                    pointer_type = TYPE_COUNT_SHORT_POINTER;
+                    cp++;
+                  }
+              }
+            else if (*cp == 'l')
+              {
+                if (cp[1] == 'l')
+                  {
+                    signed_type = TYPE_LONGLONGINT;
+                    unsigned_type = TYPE_ULONGLONGINT;
+                    pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
+                    /* For backward compatibility only.  */
+                    floatingpoint_type = TYPE_LONGDOUBLE;
+                    cp += 2;
+                  }
+                else
+                  {
+                    signed_type = TYPE_LONGINT;
+                    unsigned_type = TYPE_ULONGINT;
+                    pointer_type = TYPE_COUNT_LONGINT_POINTER;
+                    cp++;
+                  }
+              }
+            else if (*cp == 'j')
+              {
+                if (sizeof (intmax_t) > sizeof (long))
+                  {
+                    /* intmax_t = long long */
+                    signed_type = TYPE_LONGLONGINT;
+                    unsigned_type = TYPE_ULONGLONGINT;
+                    pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
+                    /* For backward compatibility only.  */
+                    floatingpoint_type = TYPE_LONGDOUBLE;
+                  }
+                else if (sizeof (intmax_t) > sizeof (int))
+                  {
+                    /* intmax_t = long */
+                    signed_type = TYPE_LONGINT;
+                    unsigned_type = TYPE_ULONGINT;
+                    pointer_type = TYPE_COUNT_LONGINT_POINTER;
+                  }
+                cp++;
+              }
+            else if (*cp == 'z' || *cp == 'Z')
+              {
+                /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
+                   because the warning facility in gcc-2.95.2 understands
+                   only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784).  */
+                if (sizeof (size_t) > sizeof (long))
+                  {
+                    /* size_t = unsigned long long */
+                    signed_type = TYPE_LONGLONGINT;
+                    unsigned_type = TYPE_ULONGLONGINT;
+                    pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
+                    /* For backward compatibility only.  */
+                    floatingpoint_type = TYPE_LONGDOUBLE;
+                  }
+                else if (sizeof (size_t) > sizeof (int))
+                  {
+                    /* size_t = unsigned long */
+                    signed_type = TYPE_LONGINT;
+                    unsigned_type = TYPE_ULONGINT;
+                    pointer_type = TYPE_COUNT_LONGINT_POINTER;
+                  }
+                cp++;
+              }
+            else if (*cp == 't')
+              {
+                if (sizeof (ptrdiff_t) > sizeof (long))
+                  {
+                    /* ptrdiff_t = long long */
+                    signed_type = TYPE_LONGLONGINT;
+                    unsigned_type = TYPE_ULONGLONGINT;
+                    pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
+                    /* For backward compatibility only.  */
+                    floatingpoint_type = TYPE_LONGDOUBLE;
+                  }
+                else if (sizeof (ptrdiff_t) > sizeof (int))
+                  {
+                    /* ptrdiff_t = long */
+                    signed_type = TYPE_LONGINT;
+                    unsigned_type = TYPE_ULONGINT;
+                    pointer_type = TYPE_COUNT_LONGINT_POINTER;
+                  }
+                cp++;
+              }
+            else if (*cp == 'w')
+              {
+                /* wN and wfN are standardized in ISO C 23.  */
+                if (cp[1] == 'f')
+                  {
+                    if (cp[2] == '8')
+                      {
+                        signed_type = TYPE_INT_FAST8_T;
+                        unsigned_type = TYPE_UINT_FAST8_T;
+                        pointer_type = TYPE_COUNT_INT_FAST8_T_POINTER;
+                        cp += 3;
+                      }
+                    else if (cp[2] == '1' && cp[3] == '6')
+                      {
+                        signed_type = TYPE_INT_FAST16_T;
+                        unsigned_type = TYPE_UINT_FAST16_T;
+                        pointer_type = TYPE_COUNT_INT_FAST16_T_POINTER;
+                        cp += 4;
+                      }
+                    else if (cp[2] == '3' && cp[3] == '2')
+                      {
+                        signed_type = TYPE_INT_FAST32_T;
+                        unsigned_type = TYPE_UINT_FAST32_T;
+                        pointer_type = TYPE_COUNT_INT_FAST32_T_POINTER;
+                        cp += 4;
+                      }
+                    else if (cp[2] == '6' && cp[3] == '4')
+                      {
+                        signed_type = TYPE_INT_FAST64_T;
+                        unsigned_type = TYPE_UINT_FAST64_T;
+                        pointer_type = TYPE_COUNT_INT_FAST64_T_POINTER;
+                        cp += 4;
+                      }
+                  }
+                else
+                  {
+                    if (cp[1] == '8')
+                      {
+                        signed_type = TYPE_INT8_T;
+                        unsigned_type = TYPE_UINT8_T;
+                        pointer_type = TYPE_COUNT_INT8_T_POINTER;
+                        cp += 2;
+                      }
+                    else if (cp[1] == '1' && cp[2] == '6')
+                      {
+                        signed_type = TYPE_INT16_T;
+                        unsigned_type = TYPE_UINT16_T;
+                        pointer_type = TYPE_COUNT_INT16_T_POINTER;
+                        cp += 3;
+                      }
+                    else if (cp[1] == '3' && cp[2] == '2')
+                      {
+                        signed_type = TYPE_INT32_T;
+                        unsigned_type = TYPE_UINT32_T;
+                        pointer_type = TYPE_COUNT_INT32_T_POINTER;
+                        cp += 3;
+                      }
+                    else if (cp[1] == '6' && cp[2] == '4')
+                      {
+                        signed_type = TYPE_INT64_T;
+                        unsigned_type = TYPE_UINT64_T;
+                        pointer_type = TYPE_COUNT_INT64_T_POINTER;
+                        cp += 3;
+                      }
+                  }
+              }
+            else if (*cp == 'L')
+              {
+                signed_type = TYPE_LONGLONGINT;
+                unsigned_type = TYPE_ULONGLONGINT;
+                pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
+                floatingpoint_type = TYPE_LONGDOUBLE;
+                cp++;
+              }
 #if defined __APPLE__ && defined __MACH__
-                  /* On Mac OS X 10.3, PRIdMAX is defined as "qd".
-                     We cannot change it to "lld" because PRIdMAX must also
-                     be understood by the system's printf routines.  */
-                  else if (*cp == 'q')
-                    {
-                      if (64 / 8 > sizeof (long))
-                        {
-                          /* int64_t = long long */
-                          flags += 16;
-                        }
-                      else
-                        {
-                          /* int64_t = long */
-                          flags += 8;
-                        }
-                      cp++;
-                    }
+            /* On Mac OS X 10.3, PRIdMAX is defined as "qd".
+               We cannot change it to "lld" because PRIdMAX must also
+               be understood by the system's printf routines.  */
+            else if (*cp == 'q')
+              {
+                if (64 / 8 > sizeof (long))
+                  {
+                    /* int64_t = long long */
+                    signed_type = TYPE_LONGLONGINT;
+                    unsigned_type = TYPE_ULONGLONGINT;
+                    pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
+                    /* For backward compatibility only.  */
+                    floatingpoint_type = TYPE_LONGDOUBLE;
+                  }
+                else
+                  {
+                    /* int64_t = long */
+                    signed_type = TYPE_LONGINT;
+                    unsigned_type = TYPE_ULONGINT;
+                    pointer_type = TYPE_COUNT_LONGINT_POINTER;
+                  }
+                cp++;
+              }
 #endif
 #if defined _WIN32 && ! defined __CYGWIN__
-                  /* On native Windows, PRIdMAX is defined as "I64d".
-                     We cannot change it to "lld" because PRIdMAX must also
-                     be understood by the system's printf routines.  */
-                  else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
-                    {
-                      if (64 / 8 > sizeof (long))
-                        {
-                          /* __int64 = long long */
-                          flags += 16;
-                        }
-                      else
-                        {
-                          /* __int64 = long */
-                          flags += 8;
-                        }
-                      cp += 3;
-                    }
+            /* On native Windows, PRIdMAX is defined as "I64d".
+               We cannot change it to "lld" because PRIdMAX must also
+               be understood by the system's printf routines.  */
+            else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
+              {
+                if (64 / 8 > sizeof (long))
+                  {
+                    /* __int64_t = long long */
+                    signed_type = TYPE_LONGLONGINT;
+                    unsigned_type = TYPE_ULONGLONGINT;
+                    pointer_type = TYPE_COUNT_LONGLONGINT_POINTER;
+                    /* For backward compatibility only.  */
+                    floatingpoint_type = TYPE_LONGDOUBLE;
+                  }
+                else
+                  {
+                    /* __int64_t = long */
+                    signed_type = TYPE_LONGINT;
+                    unsigned_type = TYPE_ULONGINT;
+                    pointer_type = TYPE_COUNT_LONGINT_POINTER;
+                  }
+                cp++;
+              }
 #endif
-                  else
-                    break;
-                }
 
-              /* Read the conversion character.  */
-              c = *cp++;
-              switch (c)
-                {
-                case 'd': case 'i':
-                  /* If 'long long' is larger than 'long':  */
-                  if (flags >= 16 || (flags & 4))
-                    type = TYPE_LONGLONGINT;
-                  else
-                  /* If 'long long' is the same as 'long', we parse "lld" into
-                     TYPE_LONGINT.  */
-                  if (flags >= 8)
-                    type = TYPE_LONGINT;
-                  else if (flags & 2)
-                    type = TYPE_SCHAR;
-                  else if (flags & 1)
-                    type = TYPE_SHORT;
-                  else
-                    type = TYPE_INT;
-                  break;
-                case 'o': case 'u': case 'x': case 'X':
-                  /* If 'unsigned long long' is larger than 'unsigned long':  
*/
-                  if (flags >= 16 || (flags & 4))
-                    type = TYPE_ULONGLONGINT;
-                  else
-                  /* If 'unsigned long long' is the same as 'unsigned long', we
-                     parse "llu" into TYPE_ULONGINT.  */
-                  if (flags >= 8)
-                    type = TYPE_ULONGINT;
-                  else if (flags & 2)
-                    type = TYPE_UCHAR;
-                  else if (flags & 1)
-                    type = TYPE_USHORT;
-                  else
-                    type = TYPE_UINT;
-                  break;
-                case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
-                case 'a': case 'A':
-                  if (flags >= 16 || (flags & 4))
-                    type = TYPE_LONGDOUBLE;
-                  else
-                    type = TYPE_DOUBLE;
-                  break;
-                case 'c':
-                  if (flags >= 8)
+            /* Read the conversion character.  */
+            c = *cp++;
+            switch (c)
+              {
+              case 'd': case 'i':
+                type = signed_type;
+                break;
+              case 'b': case 'o': case 'u': case 'x': case 'X':
+              #if SUPPORT_GNU_PRINTF_DIRECTIVES \
+                  || (__GLIBC__ + (__GLIBC_MINOR__ >= 35) > 2)
+              case 'B':
+              #endif
+                type = unsigned_type;
+                break;
+              case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+              case 'a': case 'A':
+                type = floatingpoint_type;
+                break;
+              case 'c':
+                if (signed_type == TYPE_LONGINT
+                    /* For backward compatibility only.  */
+                    || signed_type == TYPE_LONGLONGINT)
 #if HAVE_WINT_T
-                    type = TYPE_WIDE_CHAR;
+                  type = TYPE_WIDE_CHAR;
 #else
-                    goto error;
+                  goto error;
 #endif
-                  else
-                    type = TYPE_CHAR;
-                  break;
+                else
+                  type = TYPE_CHAR;
+                break;
 #if HAVE_WINT_T
-                case 'C':
-                  type = TYPE_WIDE_CHAR;
-                  c = 'c';
-                  break;
+              case 'C':
+                type = TYPE_WIDE_CHAR;
+                c = 'c';
+                break;
 #endif
-                case 's':
-                  if (flags >= 8)
+              case 's':
+                if (signed_type == TYPE_LONGINT
+                    /* For backward compatibility only.  */
+                    || signed_type == TYPE_LONGLONGINT)
 #if HAVE_WCHAR_T
-                    type = TYPE_WIDE_STRING;
+                  type = TYPE_WIDE_STRING;
 #else
-                    goto error;
+                  goto error;
 #endif
-                  else
-                    type = TYPE_STRING;
-                  break;
+                else
+                  type = TYPE_STRING;
+                break;
 #if HAVE_WCHAR_T
-                case 'S':
-                  type = TYPE_WIDE_STRING;
-                  c = 's';
-                  break;
+              case 'S':
+                type = TYPE_WIDE_STRING;
+                c = 's';
+                break;
 #endif
-                case 'p':
-                  type = TYPE_POINTER;
-                  break;
-                case 'n':
-                  /* If 'long long' is larger than 'long':  */
-                  if (flags >= 16 || (flags & 4))
-                    type = TYPE_COUNT_LONGLONGINT_POINTER;
-                  else
-                  /* If 'long long' is the same as 'long', we parse "lln" into
-                     TYPE_COUNT_LONGINT_POINTER.  */
-                  if (flags >= 8)
-                    type = TYPE_COUNT_LONGINT_POINTER;
-                  else if (flags & 2)
-                    type = TYPE_COUNT_SCHAR_POINTER;
-                  else if (flags & 1)
-                    type = TYPE_COUNT_SHORT_POINTER;
-                  else
-                    type = TYPE_COUNT_INT_POINTER;
-                  break;
+              case 'p':
+                type = TYPE_POINTER;
+                break;
+              case 'n':
+                type = pointer_type;
+                break;
 #if ENABLE_UNISTDIO
-                /* The unistdio extensions.  */
-                case 'U':
-                  if (flags >= 16)
-                    type = TYPE_U32_STRING;
-                  else if (flags >= 8)
-                    type = TYPE_U16_STRING;
-                  else
-                    type = TYPE_U8_STRING;
-                  break;
+              /* The unistdio extensions.  */
+              case 'U':
+                if (signed_type == TYPE_LONGLONGINT)
+                  type = TYPE_U32_STRING;
+                else if (signed_type == TYPE_LONGINT)
+                  type = TYPE_U16_STRING;
+                else
+                  type = TYPE_U8_STRING;
+                break;
 #endif
-                case '%':
-                  type = TYPE_NONE;
-                  break;
-                default:
-                  /* Unknown conversion character.  */
-                  goto error;
-                }
-            }
+              case '%':
+                type = TYPE_NONE;
+                break;
+              default:
+                /* Unknown conversion character.  */
+                goto error;
+              }
 
             if (type != TYPE_NONE)
               {
diff --git a/lib/printf-parse.h b/lib/printf-parse.h
index 1f86e32c99e..45febac1f04 100644
--- a/lib/printf-parse.h
+++ b/lib/printf-parse.h
@@ -61,7 +61,7 @@ typedef struct
   const char* precision_start;
   const char* precision_end;
   size_t precision_arg_index;
-  char conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */
+  char conversion; /* d i b B o u x X f F e E g G a A c s p n U % but not C S 
*/
   size_t arg_index;
 }
 char_directive;
@@ -91,7 +91,7 @@ typedef struct
   const uint8_t* precision_start;
   const uint8_t* precision_end;
   size_t precision_arg_index;
-  uint8_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */
+  uint8_t conversion; /* d i b B o u x X f F e E g G a A c s p n U % but not C 
S */
   size_t arg_index;
 }
 u8_directive;
@@ -119,7 +119,7 @@ typedef struct
   const uint16_t* precision_start;
   const uint16_t* precision_end;
   size_t precision_arg_index;
-  uint16_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S 
*/
+  uint16_t conversion; /* d i b B o u x X f F e E g G a A c s p n U % but not 
C S */
   size_t arg_index;
 }
 u16_directive;
@@ -147,7 +147,7 @@ typedef struct
   const uint32_t* precision_start;
   const uint32_t* precision_end;
   size_t precision_arg_index;
-  uint32_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S 
*/
+  uint32_t conversion; /* d i b B o u x X f F e E g G a A c s p n U % but not 
C S */
   size_t arg_index;
 }
 u32_directive;
diff --git a/lib/size_max.h b/lib/size_max.h
index 48af0250556..2cfd31a59b8 100644
--- a/lib/size_max.h
+++ b/lib/size_max.h
@@ -18,6 +18,11 @@
 #ifndef GNULIB_SIZE_MAX_H
 #define GNULIB_SIZE_MAX_H
 
+/* This file uses HAVE_STDINT_H.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
 /* Get SIZE_MAX declaration on systems like Solaris 7/8/9.  */
 # include <limits.h>
 /* Get SIZE_MAX declaration on systems like glibc 2.  */
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index 72b8cdbfa6b..802790e14e4 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -85,7 +85,7 @@
 #include <string.h>     /* memcpy(), strlen() */
 #include <wchar.h>      /* mbstate_t, mbrtowc(), mbrlen(), wcrtomb() */
 #include <errno.h>      /* errno */
-#include <limits.h>     /* CHAR_BIT */
+#include <limits.h>     /* CHAR_BIT, INT_WIDTH, LONG_WIDTH */
 #include <float.h>      /* DBL_MAX_EXP, LDBL_MAX_EXP */
 #if HAVE_NL_LANGINFO
 # include <langinfo.h>
@@ -103,29 +103,29 @@
 
 #include "attribute.h"
 
-#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+#if NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE || 
(NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
 # include <math.h>
 # include "float+.h"
 #endif
 
-#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
+#if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
 # include <math.h>
 # include "isnand-nolibm.h"
 #endif
 
-#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined 
IN_LIBINTL
+#if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || 
(NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
 # include <math.h>
 # include "isnanl-nolibm.h"
 # include "fpucw.h"
 #endif
 
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
+#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
 # include <math.h>
 # include "isnand-nolibm.h"
 # include "printf-frexp.h"
 #endif
 
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || 
(NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
 # include <math.h>
 # include "isnanl-nolibm.h"
 # include "printf-frexpl.h"
@@ -138,8 +138,6 @@
 #  define VASNPRINTF vasnwprintf
 #  define FCHAR_T wchar_t
 #  define DCHAR_T wchar_t
-#  define TCHAR_T wchar_t
-#  define DCHAR_IS_TCHAR 1
 #  define DIRECTIVE wchar_t_directive
 #  define DIRECTIVES wchar_t_directives
 #  define PRINTF_PARSE wprintf_parse
@@ -159,24 +157,32 @@
 # endif
 #endif
 #if WIDE_CHAR_VERSION
-  /* TCHAR_T is wchar_t.  */
-# define USE_SNPRINTF 1
-# if HAVE_DECL__SNWPRINTF
-   /* On Windows, the function swprintf() has a different signature than
-      on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
-      instead.  The mingw function snwprintf() has fewer bugs than the
-      MSVCRT function _snwprintf(), so prefer that.  */
-#  if defined __MINGW32__
-#   define SNPRINTF snwprintf
+  /* DCHAR_T is wchar_t.  */
+# if HAVE_DECL__SNWPRINTF || (HAVE_SWPRINTF && HAVE_WORKING_SWPRINTF)
+#  define TCHAR_T wchar_t
+#  define DCHAR_IS_TCHAR 1
+#  define USE_SNPRINTF 1
+#  if HAVE_DECL__SNWPRINTF
+    /* On Windows, the function swprintf() has a different signature than
+       on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
+       instead.  The mingw function snwprintf() has fewer bugs than the
+       MSVCRT function _snwprintf(), so prefer that.  */
+#   if defined __MINGW32__
+#    define SNPRINTF snwprintf
+#   else
+#    define SNPRINTF _snwprintf
+#    define USE_MSVC__SNPRINTF 1
+#   endif
 #  else
-#   define SNPRINTF _snwprintf
-#   define USE_MSVC__SNPRINTF 1
+    /* Unix.  */
+#   define SNPRINTF swprintf
 #  endif
 # else
-   /* Unix.  */
-#  define SNPRINTF swprintf
+   /* Old platforms such as NetBSD 3.0, OpenBSD 3.8, HP-UX 11.00, IRIX 6.5.  */
+#   define TCHAR_T char
 # endif
-#else
+#endif
+#if !WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR
   /* TCHAR_T is char.  */
   /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
      But don't use it on BeOS, since BeOS snprintf produces no output if the
@@ -241,7 +247,7 @@ local_strnlen (const char *string, size_t maxlen)
 # endif
 #endif
 
-#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && 
WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || 
USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && 
!WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
+#if (((!USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || 
USE_MSVC__SNPRINTF) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || 
!HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS) && 
!WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
 # if HAVE_WCSLEN
 #  define local_wcslen wcslen
 # else
@@ -264,8 +270,8 @@ local_wcslen (const wchar_t *s)
 # endif
 #endif
 
-#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && 
HAVE_WCHAR_T && WIDE_CHAR_VERSION
-# if HAVE_WCSNLEN
+#if (!USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || 
!HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && HAVE_WCHAR_T && 
WIDE_CHAR_VERSION
+# if HAVE_WCSNLEN && HAVE_DECL_WCSNLEN
 #  define local_wcsnlen wcsnlen
 # else
 #  ifndef local_wcsnlen_defined
@@ -283,7 +289,7 @@ local_wcsnlen (const wchar_t *s, size_t maxlen)
 # endif
 #endif
 
-#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || 
(NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && 
HAVE_WCHAR_T) || (ENABLE_WCHAR_FALLBACK && HAVE_WINT_T)) && !WIDE_CHAR_VERSION
+#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || 
NEED_PRINTF_DIRECTIVE_LS || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T) || 
((NEED_PRINTF_DIRECTIVE_LC || ENABLE_WCHAR_FALLBACK) && HAVE_WINT_T)) && 
!WIDE_CHAR_VERSION
 # if ENABLE_WCHAR_FALLBACK
 static size_t
 wctomb_fallback (char *s, wchar_t wc)
@@ -351,7 +357,7 @@ local_wctomb (char *s, wchar_t wc)
 # endif
 #endif
 
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || 
NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || 
NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
+#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || 
NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || 
NEED_PRINTF_INFINITE_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
 /* Determine the decimal-point character according to the current locale.  */
 # ifndef decimal_point_char_defined
 #  define decimal_point_char_defined 1
@@ -378,7 +384,7 @@ decimal_point_char (void)
 # endif
 #endif
 
-#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
+#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE
 
 /* Equivalent to !isfinite(x) || x == 0, but does not require libm.  */
 static int
@@ -389,7 +395,7 @@ is_infinite_or_zero (double x)
 
 #endif
 
-#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined 
IN_LIBINTL
+#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE
 
 /* Equivalent to !isfinite(x) || x == 0, but does not require libm.  */
 static int
@@ -400,7 +406,7 @@ is_infinite_or_zerol (long double x)
 
 #endif
 
-#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
+#if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE
 
 /* Converting 'long double' to decimal without rare rounding bugs requires
    real bignums.  We use the naming conventions of GNU gmp, but vastly simpler
@@ -1604,7 +1610,7 @@ is_borderline (const char *digits, size_t precision)
 
 #endif
 
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
+#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || 
!HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
 
 /* Use a different function name, to make it possible that the 'wchar_t'
    parametrization and the 'char' parametrization get compiled in the same
@@ -1627,24 +1633,156 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t 
arg_index, FCHAR_T conversion,
   switch (conversion)
     {
     case 'd': case 'i': case 'u':
-      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
-        tmp_length =
-          (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
-                          * 0.30103 /* binary -> decimal */
-                         )
-          + 1; /* turn floor into ceil */
-      else if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
-        tmp_length =
-          (unsigned int) (sizeof (unsigned long) * CHAR_BIT
-                          * 0.30103 /* binary -> decimal */
-                         )
-          + 1; /* turn floor into ceil */
-      else
-        tmp_length =
-          (unsigned int) (sizeof (unsigned int) * CHAR_BIT
-                          * 0.30103 /* binary -> decimal */
-                         )
-          + 1; /* turn floor into ceil */
+      switch (type)
+        {
+        default:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_LONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (long int) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_ULONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned long int) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_LONGLONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (long long int) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_ULONGLONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned long long int) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_INT8_T:
+          tmp_length =
+            (unsigned int) (sizeof (int8_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT8_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint8_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_INT16_T:
+          tmp_length =
+            (unsigned int) (sizeof (int16_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT16_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint16_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_INT32_T:
+          tmp_length =
+            (unsigned int) (sizeof (int32_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT32_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint32_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_INT64_T:
+          tmp_length =
+            (unsigned int) (sizeof (int64_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT64_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint64_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_INT_FAST8_T:
+          tmp_length =
+            (unsigned int) (sizeof (int_fast8_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST8_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_INT_FAST16_T:
+          tmp_length =
+            (unsigned int) (sizeof (int_fast16_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST16_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_INT_FAST32_T:
+          tmp_length =
+            (unsigned int) (sizeof (int_fast32_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST32_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_INT_FAST64_T:
+          tmp_length =
+            (unsigned int) (sizeof (int_fast64_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST64_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT
+                            * 0.30103 /* binary -> decimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        }
       if (tmp_length < precision)
         tmp_length = precision;
       /* Multiply by 2, as an estimate for FLAG_GROUP.  */
@@ -1653,25 +1791,156 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t 
arg_index, FCHAR_T conversion,
       tmp_length = xsum (tmp_length, 1);
       break;
 
+    case 'b':
+    #if SUPPORT_GNU_PRINTF_DIRECTIVES \
+        || (__GLIBC__ + (__GLIBC_MINOR__ >= 35) > 2)
+    case 'B':
+    #endif
+      switch (type)
+        {
+        default:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned int) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_ULONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned long int) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_ULONGLONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned long long int) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT8_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint8_t) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT16_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint16_t) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT32_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint32_t) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT64_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint64_t) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST8_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST16_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST32_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST64_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT)
+            + 1; /* turn floor into ceil */
+          break;
+        }
+      if (tmp_length < precision)
+        tmp_length = precision;
+      /* Add 2, to account for a prefix from the alternate form.  */
+      tmp_length = xsum (tmp_length, 2);
+      break;
+
     case 'o':
-      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
-        tmp_length =
-          (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
-                          * 0.333334 /* binary -> octal */
-                         )
-          + 1; /* turn floor into ceil */
-      else if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
-        tmp_length =
-          (unsigned int) (sizeof (unsigned long) * CHAR_BIT
-                          * 0.333334 /* binary -> octal */
-                         )
-          + 1; /* turn floor into ceil */
-      else
-        tmp_length =
-          (unsigned int) (sizeof (unsigned int) * CHAR_BIT
-                          * 0.333334 /* binary -> octal */
-                         )
-          + 1; /* turn floor into ceil */
+      switch (type)
+        {
+        default:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_ULONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned long int) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_ULONGLONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned long long int) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT8_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint8_t) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT16_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint16_t) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT32_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint32_t) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT64_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint64_t) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST8_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST16_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST32_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST64_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT
+                            * 0.333334 /* binary -> octal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        }
       if (tmp_length < precision)
         tmp_length = precision;
       /* Add 1, to account for a leading sign.  */
@@ -1679,27 +1948,89 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, 
FCHAR_T conversion,
       break;
 
     case 'x': case 'X':
-      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
-        tmp_length =
-          (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
-                          * 0.25 /* binary -> hexadecimal */
-                         )
-          + 1; /* turn floor into ceil */
-      else if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
-        tmp_length =
-          (unsigned int) (sizeof (unsigned long) * CHAR_BIT
-                          * 0.25 /* binary -> hexadecimal */
-                         )
-          + 1; /* turn floor into ceil */
-      else
-        tmp_length =
-          (unsigned int) (sizeof (unsigned int) * CHAR_BIT
-                          * 0.25 /* binary -> hexadecimal */
-                         )
-          + 1; /* turn floor into ceil */
+      switch (type)
+        {
+        default:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_ULONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned long int) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_ULONGLONGINT:
+          tmp_length =
+            (unsigned int) (sizeof (unsigned long long int) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT8_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint8_t) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT16_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint16_t) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT32_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint32_t) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT64_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint64_t) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST8_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST16_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST32_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        case TYPE_UINT_FAST64_T:
+          tmp_length =
+            (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT
+                            * 0.25 /* binary -> hexadecimal */
+                           )
+            + 1; /* turn floor into ceil */
+          break;
+        }
       if (tmp_length < precision)
         tmp_length = precision;
-      /* Add 2, to account for a leading sign or alternate form.  */
+      /* Add 2, to account for a prefix from the alternate form.  */
       tmp_length = xsum (tmp_length, 2);
       break;
 
@@ -2005,6 +2336,30 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                   case TYPE_COUNT_LONGLONGINT_POINTER:
                     *a.arg[dp->arg_index].a.a_count_longlongint_pointer = 
length;
                     break;
+                  case TYPE_COUNT_INT8_T_POINTER:
+                    *a.arg[dp->arg_index].a.a_count_int8_t_pointer = length;
+                    break;
+                  case TYPE_COUNT_INT16_T_POINTER:
+                    *a.arg[dp->arg_index].a.a_count_int16_t_pointer = length;
+                    break;
+                  case TYPE_COUNT_INT32_T_POINTER:
+                    *a.arg[dp->arg_index].a.a_count_int32_t_pointer = length;
+                    break;
+                  case TYPE_COUNT_INT64_T_POINTER:
+                    *a.arg[dp->arg_index].a.a_count_int64_t_pointer = length;
+                    break;
+                  case TYPE_COUNT_INT_FAST8_T_POINTER:
+                    *a.arg[dp->arg_index].a.a_count_int_fast8_t_pointer = 
length;
+                    break;
+                  case TYPE_COUNT_INT_FAST16_T_POINTER:
+                    *a.arg[dp->arg_index].a.a_count_int_fast16_t_pointer = 
length;
+                    break;
+                  case TYPE_COUNT_INT_FAST32_T_POINTER:
+                    *a.arg[dp->arg_index].a.a_count_int_fast32_t_pointer = 
length;
+                    break;
+                  case TYPE_COUNT_INT_FAST64_T_POINTER:
+                    *a.arg[dp->arg_index].a.a_count_int_fast64_t_pointer = 
length;
+                    break;
                   default:
                     abort ();
                   }
@@ -2394,7 +2749,150 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                   }
               }
 #endif
-#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || 
(NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && 
HAVE_WCHAR_T
+#if WIDE_CHAR_VERSION && !DCHAR_IS_TCHAR
+            else if ((dp->conversion == 's'
+                      && a.arg[dp->arg_index].type == TYPE_WIDE_STRING)
+                     || (dp->conversion == 'c'
+                         && a.arg[dp->arg_index].type == TYPE_WIDE_CHAR))
+              {
+                /* %ls or %lc in vasnwprintf.  See the specification of
+                    fwprintf.  */
+                /* It would be silly to use snprintf ("%ls", ...) and then
+                   convert back the result from a char[] to a wchar_t[].
+                   Instead, just copy the argument wchar_t[] to the result.  */
+                int flags = dp->flags;
+                size_t width;
+
+                width = 0;
+                if (dp->width_start != dp->width_end)
+                  {
+                    if (dp->width_arg_index != ARG_NONE)
+                      {
+                        int arg;
+
+                        if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                          abort ();
+                        arg = a.arg[dp->width_arg_index].a.a_int;
+                        width = arg;
+                        if (arg < 0)
+                          {
+                            /* "A negative field width is taken as a '-' flag
+                                followed by a positive field width."  */
+                            flags |= FLAG_LEFT;
+                            width = -width;
+                          }
+                      }
+                    else
+                      {
+                        const FCHAR_T *digitp = dp->width_start;
+
+                        do
+                          width = xsum (xtimes (width, 10), *digitp++ - '0');
+                        while (digitp != dp->width_end);
+                      }
+                  }
+
+                {
+                  const wchar_t *ls_arg;
+                  wchar_t lc_arg[1];
+                  size_t characters;
+
+                  if (dp->conversion == 's')
+                    {
+                      int has_precision;
+                      size_t precision;
+
+                      has_precision = 0;
+                      precision = 6;
+                      if (dp->precision_start != dp->precision_end)
+                        {
+                          if (dp->precision_arg_index != ARG_NONE)
+                            {
+                              int arg;
+
+                              if (!(a.arg[dp->precision_arg_index].type == 
TYPE_INT))
+                                abort ();
+                              arg = a.arg[dp->precision_arg_index].a.a_int;
+                              /* "A negative precision is taken as if the 
precision
+                                  were omitted."  */
+                              if (arg >= 0)
+                                {
+                                  precision = arg;
+                                  has_precision = 1;
+                                }
+                            }
+                          else
+                            {
+                              const FCHAR_T *digitp = dp->precision_start + 1;
+
+                              precision = 0;
+                              while (digitp != dp->precision_end)
+                                precision = xsum (xtimes (precision, 10), 
*digitp++ - '0');
+                              has_precision = 1;
+                            }
+                        }
+
+                      ls_arg = a.arg[dp->arg_index].a.a_wide_string;
+
+                      if (has_precision)
+                        {
+                          /* Use only at most PRECISION wide characters, from
+                             the left.  */
+                          const wchar_t *ls_arg_end;
+
+                          ls_arg_end = ls_arg;
+                          characters = 0;
+                          for (; precision > 0; precision--)
+                            {
+                              if (*ls_arg_end == 0)
+                                /* Found the terminating null wide character.  
*/
+                                break;
+                              ls_arg_end++;
+                              characters++;
+                            }
+                        }
+                      else
+                        {
+                          /* Use the entire string, and count the number of 
wide
+                             characters.  */
+                          characters = local_wcslen (ls_arg);
+                        }
+                    }
+                  else /* dp->conversion == 'c' */
+                    {
+                      lc_arg[0] = (wchar_t) a.arg[dp->arg_index].a.a_wide_char;
+                      ls_arg = lc_arg;
+                      characters = 1;
+                    }
+
+                  {
+                    size_t total = (characters < width ? width : characters);
+                    ENSURE_ALLOCATION (xsum (length, total));
+
+                    if (characters < width && !(flags & FLAG_LEFT))
+                      {
+                        size_t n = width - characters;
+                        DCHAR_SET (result + length, ' ', n);
+                        length += n;
+                      }
+
+                    if (characters > 0)
+                      {
+                        DCHAR_CPY (result + length, ls_arg, characters);
+                        length += characters;
+                      }
+
+                    if (characters < width && (flags & FLAG_LEFT))
+                      {
+                        size_t n = width - characters;
+                        DCHAR_SET (result + length, ' ', n);
+                        length += n;
+                      }
+                  }
+                }
+              }
+#endif
+#if (!USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || 
USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS || ENABLE_WCHAR_FALLBACK) && 
HAVE_WCHAR_T
             else if (dp->conversion == 's'
 # if WIDE_CHAR_VERSION
                      && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
@@ -2602,10 +3100,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 #  else
                           count = mbtowc (&wc, arg, arg_end - arg);
 #  endif
-                          if (count <= 0)
-                            /* mbrtowc not consistent with mbrlen, or mbtowc
-                               not consistent with mblen.  */
+                          if (count == 0)
+                            /* mbrtowc not consistent with strlen.  */
                             abort ();
+                          if (count < 0)
+                            /* Invalid or incomplete multibyte character.  */
+                            goto fail_with_EILSEQ;
                           ENSURE_ALLOCATION (xsum (length, 1));
                           result[length++] = wc;
                           arg += count;
@@ -2847,12 +3347,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 # endif
               }
 #endif
-#if ENABLE_WCHAR_FALLBACK && HAVE_WINT_T && !WIDE_CHAR_VERSION
+#if (NEED_PRINTF_DIRECTIVE_LC || ENABLE_WCHAR_FALLBACK) && HAVE_WINT_T && 
!WIDE_CHAR_VERSION
             else if (dp->conversion == 'c'
                      && a.arg[dp->arg_index].type == TYPE_WIDE_CHAR)
               {
                 /* Implement the 'lc' directive ourselves, in order to provide
-                   the fallback that avoids EILSEQ.  */
+                   a correct behaviour for the null wint_t argument and/or the
+                   fallback that avoids EILSEQ.  */
                 int flags = dp->flags;
                 int has_width;
                 size_t width;
@@ -2918,8 +3419,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 
                           count = local_wcrtomb (cbuf, arg, &state);
                           if (count < 0)
-                            /* Inconsistency.  */
-                            abort ();
+                            /* Cannot convert.  */
+                            goto fail_with_EILSEQ;
                           characters = count;
                         }
                     }
@@ -3017,9 +3518,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 #  endif
 
                           count = local_wcrtomb (cbuf, arg, &state);
-                          if (count <= 0)
-                            /* Inconsistency.  */
-                            abort ();
+                          if (count < 0)
+                            /* Cannot convert.  */
+                            goto fail_with_EILSEQ;
                           ENSURE_ALLOCATION (xsum (length, count));
                           memcpy (result + length, cbuf, count);
                           length += count;
@@ -3043,31 +3544,14 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                 }
               }
 #endif
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) 
&& !defined IN_LIBINTL
-            else if ((dp->conversion == 'a' || dp->conversion == 'A')
-# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && 
NEED_PRINTF_DOUBLE))
-                     && (0
-#  if NEED_PRINTF_DOUBLE
-                         || a.arg[dp->arg_index].type == TYPE_DOUBLE
-#  endif
-#  if NEED_PRINTF_LONG_DOUBLE
-                         || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
-#  endif
-                        )
-# endif
-                    )
+#if NEED_WPRINTF_DIRECTIVE_C && WIDE_CHAR_VERSION
+            else if (dp->conversion == 'c'
+                     && a.arg[dp->arg_index].type != TYPE_WIDE_CHAR)
               {
-                arg_type type = a.arg[dp->arg_index].type;
+                /* Implement the 'c' directive ourselves, in order to avoid
+                   EILSEQ in the "C" locale.  */
                 int flags = dp->flags;
                 size_t width;
-                int has_precision;
-                size_t precision;
-                size_t tmp_length;
-                size_t count;
-                DCHAR_T tmpbuf[700];
-                DCHAR_T *tmp;
-                DCHAR_T *pad_ptr;
-                DCHAR_T *p;
 
                 width = 0;
                 if (dp->width_start != dp->width_end)
@@ -3098,20 +3582,422 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                       }
                   }
 
-                has_precision = 0;
-                precision = 0;
-                if (dp->precision_start != dp->precision_end)
-                  {
-                    if (dp->precision_arg_index != ARG_NONE)
-                      {
-                        int arg;
+                /* %c in vasnwprintf.  See the specification of fwprintf.  */
+                {
+                  char arg = (char) a.arg[dp->arg_index].a.a_char;
+                  mbstate_t state;
+                  wchar_t wc;
 
-                        if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
-                          abort ();
-                        arg = a.arg[dp->precision_arg_index].a.a_int;
-                        /* "A negative precision is taken as if the precision
-                            were omitted."  */
-                        if (arg >= 0)
+                  memset (&state, '\0', sizeof (mbstate_t));
+                  int count = mbrtowc (&wc, &arg, 1, &state);
+                  if (count < 0)
+                    /* Invalid or incomplete multibyte character.  */
+                    goto fail_with_EILSEQ;
+
+                  if (1 < width && !(flags & FLAG_LEFT))
+                    {
+                      size_t n = width - 1;
+                      ENSURE_ALLOCATION (xsum (length, n));
+                      DCHAR_SET (result + length, ' ', n);
+                      length += n;
+                    }
+
+                  ENSURE_ALLOCATION (xsum (length, 1));
+                  result[length++] = wc;
+
+                  if (1 < width && (flags & FLAG_LEFT))
+                    {
+                      size_t n = width - 1;
+                      ENSURE_ALLOCATION (xsum (length, n));
+                      DCHAR_SET (result + length, ' ', n);
+                      length += n;
+                    }
+                }
+              }
+#endif
+#if NEED_PRINTF_DIRECTIVE_B || NEED_PRINTF_DIRECTIVE_UPPERCASE_B
+            else if (0
+# if NEED_PRINTF_DIRECTIVE_B
+                     || (dp->conversion == 'b')
+# endif
+# if NEED_PRINTF_DIRECTIVE_UPPERCASE_B
+                     || (dp->conversion == 'B')
+# endif
+                    )
+              {
+                arg_type type = a.arg[dp->arg_index].type;
+                int flags = dp->flags;
+                int has_width;
+                size_t width;
+                int has_precision;
+                size_t precision;
+                size_t tmp_length;
+                size_t count;
+                DCHAR_T tmpbuf[700];
+                DCHAR_T *tmp;
+                DCHAR_T *tmp_end;
+                DCHAR_T *tmp_start;
+                DCHAR_T *pad_ptr;
+                DCHAR_T *p;
+
+                has_width = 0;
+                width = 0;
+                if (dp->width_start != dp->width_end)
+                  {
+                    if (dp->width_arg_index != ARG_NONE)
+                      {
+                        int arg;
+
+                        if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                          abort ();
+                        arg = a.arg[dp->width_arg_index].a.a_int;
+                        width = arg;
+                        if (arg < 0)
+                          {
+                            /* "A negative field width is taken as a '-' flag
+                                followed by a positive field width."  */
+                            flags |= FLAG_LEFT;
+                            width = -width;
+                          }
+                      }
+                    else
+                      {
+                        const FCHAR_T *digitp = dp->width_start;
+
+                        do
+                          width = xsum (xtimes (width, 10), *digitp++ - '0');
+                        while (digitp != dp->width_end);
+                      }
+                    has_width = 1;
+                  }
+
+                has_precision = 0;
+                precision = 1;
+                if (dp->precision_start != dp->precision_end)
+                  {
+                    if (dp->precision_arg_index != ARG_NONE)
+                      {
+                        int arg;
+
+                        if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                          abort ();
+                        arg = a.arg[dp->precision_arg_index].a.a_int;
+                        /* "A negative precision is taken as if the precision
+                            were omitted."  */
+                        if (arg >= 0)
+                          {
+                            precision = arg;
+                            has_precision = 1;
+                          }
+                      }
+                    else
+                      {
+                        const FCHAR_T *digitp = dp->precision_start + 1;
+
+                        precision = 0;
+                        while (digitp != dp->precision_end)
+                          precision = xsum (xtimes (precision, 10), *digitp++ 
- '0');
+                        has_precision = 1;
+                      }
+                  }
+
+                /* Allocate a temporary buffer of sufficient size.  */
+                switch (type)
+                  {
+                  default:
+                    tmp_length =
+                      (unsigned int) (sizeof (unsigned int) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_ULONGINT:
+                    tmp_length =
+                      (unsigned int) (sizeof (unsigned long int) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_ULONGLONGINT:
+                    tmp_length =
+                      (unsigned int) (sizeof (unsigned long long int) * 
CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_UINT8_T:
+                    tmp_length =
+                      (unsigned int) (sizeof (uint8_t) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_UINT16_T:
+                    tmp_length =
+                      (unsigned int) (sizeof (uint16_t) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_UINT32_T:
+                    tmp_length =
+                      (unsigned int) (sizeof (uint32_t) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_UINT64_T:
+                    tmp_length =
+                      (unsigned int) (sizeof (uint64_t) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_UINT_FAST8_T:
+                    tmp_length =
+                      (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_UINT_FAST16_T:
+                    tmp_length =
+                      (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_UINT_FAST32_T:
+                    tmp_length =
+                      (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  case TYPE_UINT_FAST64_T:
+                    tmp_length =
+                      (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT)
+                      + 1; /* turn floor into ceil */
+                    break;
+                  }
+                if (tmp_length < precision)
+                  tmp_length = precision;
+                /* Add 2, to account for a prefix from the alternate form.  */
+                tmp_length = xsum (tmp_length, 2);
+
+                if (tmp_length < width)
+                  tmp_length = width;
+
+                if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
+                  tmp = tmpbuf;
+                else
+                  {
+                    size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
+
+                    if (size_overflow_p (tmp_memsize))
+                      /* Overflow, would lead to out of memory.  */
+                      goto out_of_memory;
+                    tmp = (DCHAR_T *) malloc (tmp_memsize);
+                    if (tmp == NULL)
+                      /* Out of memory.  */
+                      goto out_of_memory;
+                  }
+
+                tmp_end = tmp + tmp_length;
+
+                unsigned long long arg;
+                switch (type)
+                  {
+                  case TYPE_UCHAR:
+                    arg = a.arg[dp->arg_index].a.a_uchar;
+                    break;
+                  case TYPE_USHORT:
+                    arg = a.arg[dp->arg_index].a.a_ushort;
+                    break;
+                  case TYPE_UINT:
+                    arg = a.arg[dp->arg_index].a.a_uint;
+                    break;
+                  case TYPE_ULONGINT:
+                    arg = a.arg[dp->arg_index].a.a_ulongint;
+                    break;
+                  case TYPE_ULONGLONGINT:
+                    arg = a.arg[dp->arg_index].a.a_ulonglongint;
+                    break;
+                  case TYPE_UINT8_T:
+                    arg = a.arg[dp->arg_index].a.a_uint8_t;
+                    break;
+                  case TYPE_UINT16_T:
+                    arg = a.arg[dp->arg_index].a.a_uint16_t;
+                    break;
+                  case TYPE_UINT32_T:
+                    arg = a.arg[dp->arg_index].a.a_uint32_t;
+                    break;
+                  case TYPE_UINT64_T:
+                    arg = a.arg[dp->arg_index].a.a_uint64_t;
+                    break;
+                  case TYPE_UINT_FAST8_T:
+                    arg = a.arg[dp->arg_index].a.a_uint_fast8_t;
+                    break;
+                  case TYPE_UINT_FAST16_T:
+                    arg = a.arg[dp->arg_index].a.a_uint_fast16_t;
+                    break;
+                  case TYPE_UINT_FAST32_T:
+                    arg = a.arg[dp->arg_index].a.a_uint_fast32_t;
+                    break;
+                  case TYPE_UINT_FAST64_T:
+                    arg = a.arg[dp->arg_index].a.a_uint_fast64_t;
+                    break;
+                  default:
+                    abort ();
+                  }
+                int need_prefix = ((flags & FLAG_ALT) && arg != 0);
+
+                p = tmp_end;
+                /* "The result of converting a zero value with a precision
+                   of zero is no characters."  */
+                if (!(has_precision && precision == 0 && arg == 0))
+                  {
+                    do
+                      {
+                        *--p = '0' + (arg & 1);
+                        arg = arg >> 1;
+                      }
+                    while (arg != 0);
+                  }
+
+                if (has_precision)
+                  {
+                    DCHAR_T *digits_start = tmp_end - precision;
+                    while (p > digits_start)
+                      *--p = '0';
+                  }
+
+                pad_ptr = p;
+
+                if (need_prefix)
+                  {
+# if NEED_PRINTF_DIRECTIVE_B && !NEED_PRINTF_DIRECTIVE_UPPERCASE_B
+                    *--p = 'b';
+# elif NEED_PRINTF_DIRECTIVE_UPPERCASE_B && !NEED_PRINTF_DIRECTIVE_B
+                    *--p = 'B';
+# else
+                    *--p = dp->conversion;
+# endif
+                    *--p = '0';
+                  }
+                tmp_start = p;
+
+                /* The generated string now extends from tmp_start to tmp_end,
+                   with the zero padding insertion point being at pad_ptr,
+                   tmp_start <= pad_ptr <= tmp_end.  */
+                count = tmp_end - tmp_start;
+
+                if (count < width)
+                  {
+                    size_t pad = width - count;
+
+                    if (flags & FLAG_LEFT)
+                      {
+                        /* Pad with spaces on the right.  */
+                        for (p = tmp_start; p < tmp_end; p++)
+                          *(p - pad) = *p;
+                        for (p = tmp_end - pad; p < tmp_end; p++)
+                          *p = ' ';
+                      }
+                    else if ((flags & FLAG_ZERO)
+                             /* Neither ISO C nor POSIX specify that the '0'
+                                flag is ignored when a width and a precision
+                                are both present.  But most implementations
+                                do so.  */
+                             && !(has_width && has_precision))
+                      {
+                        /* Pad with zeroes.  */
+                        for (p = tmp_start; p < pad_ptr; p++)
+                          *(p - pad) = *p;
+                        for (p = pad_ptr - pad; p < pad_ptr; p++)
+                          *p = '0';
+                      }
+                    else
+                      {
+                        /* Pad with spaces on the left.  */
+                        for (p = tmp_start - pad; p < tmp_start; p++)
+                          *p = ' ';
+                      }
+
+                    tmp_start = tmp_start - pad;
+                  }
+
+                count = tmp_end - tmp_start;
+
+                if (count > tmp_length)
+                  /* tmp_length was incorrectly calculated - fix the
+                     code above!  */
+                  abort ();
+
+                /* Make room for the result.  */
+                if (count >= allocated - length)
+                  {
+                    size_t n = xsum (length, count);
+
+                    ENSURE_ALLOCATION (n);
+                  }
+
+                /* Append the result.  */
+                memcpy (result + length, tmp_start, count * sizeof (DCHAR_T));
+                if (tmp != tmpbuf)
+                  free (tmp);
+                length += count;
+              }
+#endif
+#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE 
|| (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
+            else if ((dp->conversion == 'a' || dp->conversion == 'A')
+# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && 
NEED_PRINTF_DOUBLE))
+                     && (0
+#  if NEED_PRINTF_DOUBLE
+                         || a.arg[dp->arg_index].type == TYPE_DOUBLE
+#  endif
+#  if NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && 
WIDE_CHAR_VERSION)
+                         || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
+#  endif
+                        )
+# endif
+                    )
+              {
+                arg_type type = a.arg[dp->arg_index].type;
+                int flags = dp->flags;
+                size_t width;
+                int has_precision;
+                size_t precision;
+                size_t tmp_length;
+                size_t count;
+                DCHAR_T tmpbuf[700];
+                DCHAR_T *tmp;
+                DCHAR_T *pad_ptr;
+                DCHAR_T *p;
+
+                width = 0;
+                if (dp->width_start != dp->width_end)
+                  {
+                    if (dp->width_arg_index != ARG_NONE)
+                      {
+                        int arg;
+
+                        if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                          abort ();
+                        arg = a.arg[dp->width_arg_index].a.a_int;
+                        width = arg;
+                        if (arg < 0)
+                          {
+                            /* "A negative field width is taken as a '-' flag
+                                followed by a positive field width."  */
+                            flags |= FLAG_LEFT;
+                            width = -width;
+                          }
+                      }
+                    else
+                      {
+                        const FCHAR_T *digitp = dp->width_start;
+
+                        do
+                          width = xsum (xtimes (width, 10), *digitp++ - '0');
+                        while (digitp != dp->width_end);
+                      }
+                  }
+
+                has_precision = 0;
+                precision = 0;
+                if (dp->precision_start != dp->precision_end)
+                  {
+                    if (dp->precision_arg_index != ARG_NONE)
+                      {
+                        int arg;
+
+                        if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                          abort ();
+                        arg = a.arg[dp->precision_arg_index].a.a_int;
+                        /* "A negative precision is taken as if the precision
+                            were omitted."  */
+                        if (arg >= 0)
                           {
                             precision = arg;
                             has_precision = 1;
@@ -3170,7 +4056,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                 p = tmp;
                 if (type == TYPE_LONGDOUBLE)
                   {
-# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
+# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || 
(NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
                     long double arg = a.arg[dp->arg_index].a.a_longdouble;
 
                     if (isnanl (arg))
@@ -3290,7 +4176,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                                 }
                               }
                               *p++ = dp->conversion - 'A' + 'P';
-#  if WIDE_CHAR_VERSION
+#  if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
                               {
                                 static const wchar_t decimal_format[] =
                                   { '%', '+', 'd', '\0' };
@@ -3441,7 +4327,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                                 }
                               }
                               *p++ = dp->conversion - 'A' + 'P';
-#  if WIDE_CHAR_VERSION
+#  if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
                               {
                                 static const wchar_t decimal_format[] =
                                   { '%', '+', 'd', '\0' };
@@ -3533,7 +4419,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                 length += count;
               }
 #endif
-#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || 
NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined 
IN_LIBINTL
+#if NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || 
NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE
             else if ((dp->conversion == 'f' || dp->conversion == 'F'
                       || dp->conversion == 'e' || dp->conversion == 'E'
                       || dp->conversion == 'g' || dp->conversion == 'G'
@@ -3901,7 +4787,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                                   }
 
                                 *p++ = dp->conversion; /* 'e' or 'E' */
-#   if WIDE_CHAR_VERSION
+#   if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
                                 {
                                   static const wchar_t decimal_format[] =
                                     { '%', '+', '.', '2', 'd', '\0' };
@@ -4082,7 +4968,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                                               }
                                           }
                                         *p++ = dp->conversion - 'G' + 'E'; /* 
'e' or 'E' */
-#   if WIDE_CHAR_VERSION
+#   if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
                                         {
                                           static const wchar_t 
decimal_format[] =
                                             { '%', '+', '.', '2', 'd', '\0' };
@@ -4359,7 +5245,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                                   }
 
                                 *p++ = dp->conversion; /* 'e' or 'E' */
-#   if WIDE_CHAR_VERSION
+#   if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
                                 {
                                   static const wchar_t decimal_format[] =
                                     /* Produce the same number of exponent 
digits
@@ -4552,7 +5438,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                                               }
                                           }
                                         *p++ = dp->conversion - 'G' + 'E'; /* 
'e' or 'E' */
-#   if WIDE_CHAR_VERSION
+#   if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
                                         {
                                           static const wchar_t 
decimal_format[] =
                                             /* Produce the same number of 
exponent digits
@@ -4720,13 +5606,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
               {
                 arg_type type = a.arg[dp->arg_index].type;
                 int flags = dp->flags;
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || 
NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
                 int has_width;
 #endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || 
!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || 
NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || 
USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
                 size_t width;
 #endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || 
NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || 
!HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (WIDE_CHAR_VERSION && 
MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST 
|| NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
                 int has_precision;
                 size_t precision;
 #endif
@@ -4735,7 +5621,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 #else
 #               define prec_ourselves 0
 #endif
-#if NEED_PRINTF_FLAG_LEFTADJUST
+#if (WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST
 #               define pad_ourselves 1
 #elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
                 int pad_ourselves;
@@ -4752,10 +5638,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                 TCHAR_T *tmp;
 #endif
 
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || 
NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
                 has_width = 0;
 #endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || 
!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || 
NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || 
USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
                 width = 0;
                 if (dp->width_start != dp->width_end)
                   {
@@ -4783,13 +5669,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           width = xsum (xtimes (width, 10), *digitp++ - '0');
                         while (digitp != dp->width_end);
                       }
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || 
NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+# if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
                     has_width = 1;
-#endif
+# endif
                   }
 #endif
 
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || 
NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || 
!HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (WIDE_CHAR_VERSION && 
MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST 
|| NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
                 has_precision = 0;
                 precision = 6;
                 if (dp->precision_start != dp->precision_end)
@@ -4826,6 +5712,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                 switch (dp->conversion)
                   {
                   case 'd': case 'i': case 'u':
+                  case 'b':
+                  #if SUPPORT_GNU_PRINTF_DIRECTIVES \
+                      || (__GLIBC__ + (__GLIBC_MINOR__ >= 35) > 2)
+                  case 'B':
+                  #endif
                   case 'o':
                   case 'x': case 'X': case 'p':
                     prec_ourselves = has_precision && (precision > 0);
@@ -4837,7 +5728,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 #endif
 
                 /* Decide whether to perform the padding ourselves.  */
-#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
+#if !((WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST) && 
(!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION)
                 switch (dp->conversion)
                   {
 # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
@@ -4956,6 +5847,54 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                   {
                   case TYPE_LONGLONGINT:
                   case TYPE_ULONGLONGINT:
+                  #if INT8_WIDTH > LONG_WIDTH
+                  case TYPE_INT8_T:
+                  #endif
+                  #if UINT8_WIDTH > LONG_WIDTH
+                  case TYPE_UINT8_T:
+                  #endif
+                  #if INT16_WIDTH > LONG_WIDTH
+                  case TYPE_INT16_T:
+                  #endif
+                  #if UINT16_WIDTH > LONG_WIDTH
+                  case TYPE_UINT16_T:
+                  #endif
+                  #if INT32_WIDTH > LONG_WIDTH
+                  case TYPE_INT32_T:
+                  #endif
+                  #if UINT32_WIDTH > LONG_WIDTH
+                  case TYPE_UINT32_T:
+                  #endif
+                  #if INT64_WIDTH > LONG_WIDTH
+                  case TYPE_INT64_T:
+                  #endif
+                  #if UINT64_WIDTH > LONG_WIDTH
+                  case TYPE_UINT64_T:
+                  #endif
+                  #if INT_FAST8_WIDTH > LONG_WIDTH
+                  case TYPE_INT_FAST8_T:
+                  #endif
+                  #if UINT_FAST8_WIDTH > LONG_WIDTH
+                  case TYPE_UINT_FAST8_T:
+                  #endif
+                  #if INT_FAST16_WIDTH > LONG_WIDTH
+                  case TYPE_INT_FAST16_T:
+                  #endif
+                  #if UINT_FAST16_WIDTH > LONG_WIDTH
+                  case TYPE_UINT_FAST16_T:
+                  #endif
+                  #if INT_FAST32_WIDTH > LONG_WIDTH
+                  case TYPE_INT3_FAST2_T:
+                  #endif
+                  #if UINT_FAST32_WIDTH > LONG_WIDTH
+                  case TYPE_UINT_FAST32_T:
+                  #endif
+                  #if INT_FAST64_WIDTH > LONG_WIDTH
+                  case TYPE_INT_FAST64_T:
+                  #endif
+                  #if UINT_FAST64_WIDTH > LONG_WIDTH
+                  case TYPE_UINT_FAST64_T:
+                  #endif
 #if defined _WIN32 && ! defined __CYGWIN__
                     *fbp++ = 'I';
                     *fbp++ = '6';
@@ -4967,12 +5906,60 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                     FALLTHROUGH;
                   case TYPE_LONGINT:
                   case TYPE_ULONGINT:
-#if HAVE_WINT_T
+                  #if INT8_WIDTH > INT_WIDTH && INT8_WIDTH <= LONG_WIDTH
+                  case TYPE_INT8_T:
+                  #endif
+                  #if UINT8_WIDTH > INT_WIDTH && UINT8_WIDTH <= LONG_WIDTH
+                  case TYPE_UINT8_T:
+                  #endif
+                  #if INT16_WIDTH > INT_WIDTH && INT16_WIDTH <= LONG_WIDTH
+                  case TYPE_INT16_T:
+                  #endif
+                  #if UINT16_WIDTH > INT_WIDTH && UINT16_WIDTH <= LONG_WIDTH
+                  case TYPE_UINT16_T:
+                  #endif
+                  #if INT32_WIDTH > INT_WIDTH && INT32_WIDTH <= LONG_WIDTH
+                  case TYPE_INT32_T:
+                  #endif
+                  #if UINT32_WIDTH > INT_WIDTH && UINT32_WIDTH <= LONG_WIDTH
+                  case TYPE_UINT32_T:
+                  #endif
+                  #if INT64_WIDTH > INT_WIDTH && INT64_WIDTH <= LONG_WIDTH
+                  case TYPE_INT64_T:
+                  #endif
+                  #if UINT64_WIDTH > INT_WIDTH && UINT64_WIDTH <= LONG_WIDTH
+                  case TYPE_UINT64_T:
+                  #endif
+                  #if INT_FAST8_WIDTH > INT_WIDTH && INT_FAST8_WIDTH <= 
LONG_WIDTH
+                  case TYPE_INT_FAST8_T:
+                  #endif
+                  #if UINT_FAST8_WIDTH > INT_WIDTH && UINT_FAST8_WIDTH <= 
LONG_WIDTH
+                  case TYPE_UINT_FAST8_T:
+                  #endif
+                  #if INT_FAST16_WIDTH > INT_WIDTH && INT_FAST16_WIDTH <= 
LONG_WIDTH
+                  case TYPE_INT_FAST16_T:
+                  #endif
+                  #if UINT_FAST16_WIDTH > INT_WIDTH && UINT_FAST16_WIDTH <= 
LONG_WIDTH
+                  case TYPE_UINT_FAST16_T:
+                  #endif
+                  #if INT_FAST32_WIDTH > INT_WIDTH && INT_FAST32_WIDTH <= 
LONG_WIDTH
+                  case TYPE_INT_FAST32_T:
+                  #endif
+                  #if UINT_FAST32_WIDTH > INT_WIDTH && UINT_FAST32_WIDTH <= 
LONG_WIDTH
+                  case TYPE_UINT_FAST32_T:
+                  #endif
+                  #if INT_FAST64_WIDTH > INT_WIDTH && INT_FAST64_WIDTH <= 
LONG_WIDTH
+                  case TYPE_INT_FAST64_T:
+                  #endif
+                  #if UINT_FAST64_WIDTH > INT_WIDTH && UINT_FAST64_WIDTH <= 
LONG_WIDTH
+                  case TYPE_UINT_FAST64_T:
+                  #endif
+                  #if HAVE_WINT_T
                   case TYPE_WIDE_CHAR:
-#endif
-#if HAVE_WCHAR_T
+                  #endif
+                  #if HAVE_WCHAR_T
                   case TYPE_WIDE_STRING:
-#endif
+                  #endif
                     *fbp++ = 'l';
                     break;
                   case TYPE_LONGDOUBLE:
@@ -4988,47 +5975,74 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 #endif
                   *fbp = dp->conversion;
 #if USE_SNPRINTF
-# if ((HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99)            \
+                /* Decide whether to pass %n in the format string
+                   to SNPRINTF.  */
+# if (((!WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR)                              \
+       && (HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99))       \
       || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3))       \
           && !defined __UCLIBC__)                                           \
       || (defined __APPLE__ && defined __MACH__)                            \
+      || defined __OpenBSD__                                                \
       || defined __ANDROID__                                                \
-      || (defined _WIN32 && ! defined __CYGWIN__))
-                /* On systems where we know that snprintf's return value
-                   conforms to ISO C 99 (HAVE_SNPRINTF_RETVAL_C99) and that
-                   snprintf always produces NUL-terminated strings
-                   (HAVE_SNPRINTF_TRUNCATION_C99), it is possible to avoid
-                   using %n.  And it is desirable to do so, because more and
-                   more platforms no longer support %n, for "security reasons".
-                   In particular, the following platforms:
+      || (defined _WIN32 && ! defined __CYGWIN__))                          \
+      || (WIDE_CHAR_VERSION && MUSL_LIBC)
+                /* We can avoid passing %n and instead rely on SNPRINTF's
+                   return value if
+                     - !WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR, because 
otherwise,
+                       when WIDE_CHAR_VERSION && DCHAR_IS_TCHAR,
+                       snwprintf()/_snwprintf() (Windows) and swprintf() (Unix)
+                       don't return the needed buffer size,
+                     and
+                     - we're compiling for a system where we know
+                       - that snprintf's return value conforms to ISO C 99
+                         (HAVE_SNPRINTF_RETVAL_C99) and
+                       - that snprintf always produces NUL-terminated strings
+                         (HAVE_SNPRINTF_TRUNCATION_C99).
+                   And it is desirable to do so, because more and more 
platforms
+                   no longer support %n, for "security reasons".  */
+                /* On specific platforms, listed below, we *must* avoid %n.
+                   In the case
+                     !WIDE_CHAR_VERSION && HAVE_SNPRINTF_RETVAL_C99 && 
!USE_MSVC__SNPRINTF
+                   we can rely on the return value of snprintf instead.  
Whereas
+                   in the opposite case
+                     WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || 
USE_MSVC__SNPRINTF
+                   we need to make room based on an estimation, computed by
+                   MAX_ROOM_NEEDED.  */
+                /* The following platforms forbid %n:
                      - On glibc2 systems from 2004-10-18 or newer, the use of
                        %n in format strings in writable memory may crash the
                        program (if compiled with _FORTIFY_SOURCE=2).
-                     - On Mac OS X 10.13 or newer, the use of %n in format
+                     - On macOS 10.13 or newer, the use of %n in format
                        strings in writable memory by default crashes the
                        program.
+                     - On OpenBSD, since 2021-08-30, the use of %n in format
+                       strings produces an abort (see
+                       
<https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/vfprintf.c.diff?r1=1.79&r2=1.80&f=h>,
+                       
<https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/vfwprintf.c.diff?r1=1.20&r2=1.21&f=h>).
                      - On Android, starting on 2018-03-07, the use of %n in
                        format strings produces a fatal error (see
                        
<https://android.googlesource.com/platform/bionic/+/41398d03b7e8e0dfb951660ae713e682e9fc0336>).
-                   On these platforms, HAVE_SNPRINTF_RETVAL_C99 and
-                   HAVE_SNPRINTF_TRUNCATION_C99 are 1. We have listed them
-                   explicitly in the condition above, in case of cross-
-                   compilation (just to be sure).  */
-                /* On native Windows systems (such as mingw), we can avoid 
using
-                   %n because:
+                     - On native Windows systems (such as mingw) where the OS 
is
+                       Windows Vista, the use of %n in format strings by 
default
+                       crashes the program. See
+                         <https://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
+                         
<https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/set-printf-count-output>
+                   On the first four of these platforms, if !WIDE_CHAR_VERSION,
+                   it is not a big deal to avoid %n, because on these 
platforms,
+                   HAVE_SNPRINTF_RETVAL_C99 and HAVE_SNPRINTF_TRUNCATION_C99 
are
+                   1.
+                   On native Windows, if !WIDE_CHAR_VERSION, it's not a big 
deal
+                   either because:
                      - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
                        snprintf does not write more than the specified number
                        of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
                        '4', '5', '6' into buf, not '4', '5', '\0'.)
                      - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
                        allows us to recognize the case of an insufficient
-                       buffer size: it returns -1 in this case.
-                   On native Windows systems (such as mingw) where the OS is
-                   Windows Vista, the use of %n in format strings by default
-                   crashes the program. See
-                     <https://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
-                     
<https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/set-printf-count-output>
-                   So we should avoid %n in this situation.  */
+                       buffer size: it returns -1 in this case.  */
+                /* Additionally, in the WIDE_CHAR_VERSION case, we cannot use 
%n
+                   on musl libc because we would run into an swprintf() bug.
+                   See <https://www.openwall.com/lists/musl/2023/03/19/1>.  */
                 fbp[1] = '\0';
 # else           /* AIX <= 5.1, HP-UX, IRIX, OSF/1, Solaris <= 9, BeOS */
                 fbp[1] = '%';
@@ -5189,6 +6203,102 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                           SNPRINTF_BUF (arg);
                         }
                         break;
+                      case TYPE_INT8_T:
+                        {
+                          int8_t arg = a.arg[dp->arg_index].a.a_int8_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_UINT8_T:
+                        {
+                          uint8_t arg = a.arg[dp->arg_index].a.a_uint8_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_INT16_T:
+                        {
+                          int16_t arg = a.arg[dp->arg_index].a.a_int16_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_UINT16_T:
+                        {
+                          uint16_t arg = a.arg[dp->arg_index].a.a_uint16_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_INT32_T:
+                        {
+                          int32_t arg = a.arg[dp->arg_index].a.a_int32_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_UINT32_T:
+                        {
+                          uint32_t arg = a.arg[dp->arg_index].a.a_uint32_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_INT64_T:
+                        {
+                          int64_t arg = a.arg[dp->arg_index].a.a_int64_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_UINT64_T:
+                        {
+                          uint64_t arg = a.arg[dp->arg_index].a.a_uint64_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_INT_FAST8_T:
+                        {
+                          int_fast8_t arg = 
a.arg[dp->arg_index].a.a_int_fast8_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_UINT_FAST8_T:
+                        {
+                          uint_fast8_t arg = 
a.arg[dp->arg_index].a.a_uint_fast8_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_INT_FAST16_T:
+                        {
+                          int_fast16_t arg = 
a.arg[dp->arg_index].a.a_int_fast16_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_UINT_FAST16_T:
+                        {
+                          uint_fast16_t arg = 
a.arg[dp->arg_index].a.a_uint_fast16_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_INT_FAST32_T:
+                        {
+                          int_fast32_t arg = 
a.arg[dp->arg_index].a.a_int_fast32_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_UINT_FAST32_T:
+                        {
+                          uint_fast32_t arg = 
a.arg[dp->arg_index].a.a_uint_fast32_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_INT_FAST64_T:
+                        {
+                          int_fast64_t arg = 
a.arg[dp->arg_index].a.a_int_fast64_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
+                      case TYPE_UINT_FAST64_T:
+                        {
+                          uint_fast64_t arg = 
a.arg[dp->arg_index].a.a_uint_fast64_t;
+                          SNPRINTF_BUF (arg);
+                        }
+                        break;
                       case TYPE_DOUBLE:
                         {
                           double arg = a.arg[dp->arg_index].a.a_double;
@@ -5271,12 +6381,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                             /* Look at the snprintf() return value.  */
                             if (retcount < 0)
                               {
-# if !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
+# if (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || 
USE_MSVC__SNPRINTF
                                 /* HP-UX 10.20 snprintf() is doubly deficient:
                                    It doesn't understand the '%n' directive,
                                    *and* it returns -1 (rather than the length
                                    that would have been required) when the
                                    buffer is too small.
+                                   Likewise, in case of
+                                   WIDE_CHAR_VERSION && DCHAR_IS_TCHAR, the
+                                   functions snwprintf()/_snwprintf() (Windows)
+                                   or swprintf() (Unix).
                                    But a failure at this point can also come
                                    from other reasons than a too small buffer,
                                    such as an invalid wide string argument to
@@ -5312,7 +6426,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 # endif
                               }
                             else
-                              count = retcount;
+                              {
+                                count = retcount;
+# if WIDE_CHAR_VERSION && defined __MINGW32__
+                                if (count == 0 && dp->conversion == 'c')
+                                  /* snwprintf returned 0 instead of 1.  But it
+                                     wrote a null wide character.  */
+                                  count = 1;
+# endif
+                              }
                           }
                       }
 #endif
@@ -5442,11 +6564,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 
 #if !DCHAR_IS_TCHAR
                     /* Convert from TCHAR_T[] to DCHAR_T[].  */
-                    if (dp->conversion == 'c' || dp->conversion == 's')
+                    if (dp->conversion == 'c' || dp->conversion == 's'
+# if __GLIBC__ >= 2 && !defined __UCLIBC__
+                        || (flags & FLAG_LOCALIZED)
+# endif
+                       )
                       {
-                        /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
-                           TYPE_WIDE_STRING.
-                           The result string is not certainly ASCII.  */
+                        /* The result string is not guaranteed to be ASCII.  */
                         const TCHAR_T *tmpsrc;
                         DCHAR_T *tmpdst;
                         size_t tmpdst_len;
@@ -5457,6 +6581,56 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 # else
                         tmpsrc = tmp;
 # endif
+# if WIDE_CHAR_VERSION
+                        /* Convert tmpsrc[0..count-1] to a freshly allocated
+                           wide character array.  */
+                        mbstate_t state;
+
+                        memset (&state, '\0', sizeof (mbstate_t));
+                        tmpdst_len = 0;
+                        {
+                          const TCHAR_T *src = tmpsrc;
+                          size_t srclen = count;
+
+                          for (; srclen > 0; tmpdst_len++)
+                            {
+                              /* Parse the next multibyte character.  */
+                              size_t ret = mbrtowc (NULL, src, srclen, &state);
+                              if (ret == (size_t)(-2) || ret == (size_t)(-1))
+                                goto fail_with_EILSEQ;
+                              if (ret == 0)
+                                ret = 1;
+                              src += ret;
+                              srclen -= ret;
+                            }
+                        }
+
+                        tmpdst =
+                          (wchar_t *) malloc ((tmpdst_len + 1) * sizeof 
(wchar_t));
+                        if (tmpdst == NULL)
+                          goto out_of_memory;
+
+                        memset (&state, '\0', sizeof (mbstate_t));
+                        {
+                          DCHAR_T *destptr = tmpdst;
+                          const TCHAR_T *src = tmpsrc;
+                          size_t srclen = count;
+
+                          for (; srclen > 0; destptr++)
+                            {
+                              /* Parse the next multibyte character.  */
+                              size_t ret = mbrtowc (destptr, src, srclen, 
&state);
+                              if (ret == (size_t)(-2) || ret == (size_t)(-1))
+                                /* Should already have been caught in the first
+                                   loop, above.  */
+                                abort ();
+                              if (ret == 0)
+                                ret = 1;
+                              src += ret;
+                              srclen -= ret;
+                            }
+                        }
+# else
                         tmpdst =
                           DCHAR_CONV_FROM_ENCODING (locale_charset (),
                                                     iconveh_question_mark,
@@ -5465,6 +6639,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                                                     NULL, &tmpdst_len);
                         if (tmpdst == NULL)
                           goto fail_with_errno;
+# endif
                         ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
                                                 { free (tmpdst); goto 
out_of_memory; });
                         DCHAR_CPY (result + length, tmpdst, tmpdst_len);
@@ -5531,7 +6706,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                     /* Here count <= allocated - length.  */
 
                     /* Perform padding.  */
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || 
NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 
NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || 
NEED_PRINTF_UNBOUNDED_PRECISION
                     if (pad_ourselves && has_width)
                       {
                         size_t w;
@@ -5590,6 +6765,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                                   if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
                                       || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
                                     pad_ptr = NULL;
+                                  else
+                                    /* Do the zero-padding after the "0x" or
+                                       "0b" prefix, not before.  */
+                                    if (p - rp >= 2
+                                        && *rp == '0'
+                                        && (((dp->conversion == 'a'
+                                              || dp->conversion == 'x')
+                                             && rp[1] == 'x')
+                                            || ((dp->conversion == 'A'
+                                                 || dp->conversion == 'X')
+                                                && rp[1] == 'X')
+                                            || (dp->conversion == 'b'
+                                                && rp[1] == 'b')
+                                            || (dp->conversion == 'B'
+                                                && rp[1] == 'B')))
+                                      pad_ptr += 2;
                                 }
                               /* The generated string now extends from rp to p,
                                  with the zero padding insertion point being at
@@ -5603,7 +6794,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                                   for (; pad > 0; pad--)
                                     *p++ = ' ';
                                 }
-                              else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+                              else if ((flags & FLAG_ZERO) && pad_ptr != NULL
+                                       /* ISO C says: "For d, i, o, u, x, and X
+                                          conversions, if a precision is
+                                          specified, the 0 flag is ignored.  */
+                                       && !(has_precision
+                                            && (dp->conversion == 'd'
+                                                || dp->conversion == 'i'
+                                                || dp->conversion == 'o'
+                                                || dp->conversion == 'u'
+                                                || dp->conversion == 'x'
+                                                || dp->conversion == 'X'
+                                                /* Although ISO C does not
+                                                   require it, treat 'b' and 
'B'
+                                                   like 'x' and 'X'.  */
+                                                || dp->conversion == 'b'
+                                                || dp->conversion == 'B')))
                                 {
                                   /* Pad with zeroes.  */
                                   DCHAR_T *q = end;
@@ -5697,7 +6903,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
     errno = ENOMEM;
     goto fail_with_errno;
 
-#if ENABLE_UNISTDIO || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || 
USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || 
ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T)
+#if ENABLE_UNISTDIO || ((!USE_SNPRINTF || WIDE_CHAR_VERSION || 
!HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS || 
ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T) || ((NEED_PRINTF_DIRECTIVE_LC || 
ENABLE_WCHAR_FALLBACK) && HAVE_WINT_T && !WIDE_CHAR_VERSION) || 
(NEED_WPRINTF_DIRECTIVE_C && WIDE_CHAR_VERSION)
   fail_with_EILSEQ:
     errno = EILSEQ;
     goto fail_with_errno;
diff --git a/lib/vasnprintf.h b/lib/vasnprintf.h
index f69649fb457..2d134070796 100644
--- a/lib/vasnprintf.h
+++ b/lib/vasnprintf.h
@@ -17,6 +17,11 @@
 #ifndef _VASNPRINTF_H
 #define _VASNPRINTF_H
 
+/* This file uses _GL_ATTRIBUTE_FORMAT.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
 /* Get va_list.  */
 #include <stdarg.h>
 
diff --git a/lib/xsize.h b/lib/xsize.h
index 1ec78e776fc..5b08d61f2f7 100644
--- a/lib/xsize.h
+++ b/lib/xsize.h
@@ -18,6 +18,11 @@
 #ifndef _XSIZE_H
 #define _XSIZE_H
 
+/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE, HAVE_STDINT_H.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
 /* Get size_t.  */
 #include <stddef.h>
 
@@ -30,9 +35,6 @@
 /* Get ATTRIBUTE_PURE.  */
 #include "attribute.h"
 
-#ifndef _GL_INLINE_HEADER_BEGIN
- #error "Please include config.h first."
-#endif
 _GL_INLINE_HEADER_BEGIN
 #ifndef XSIZE_INLINE
 # define XSIZE_INLINE _GL_INLINE
diff --git a/m4/exponentd.m4 b/m4/exponentd.m4
index 2ef46437deb..163114b89ec 100644
--- a/m4/exponentd.m4
+++ b/m4/exponentd.m4
@@ -1,9 +1,9 @@
-# exponentd.m4 serial 3
+# exponentd.m4 serial 4
 dnl Copyright (C) 2007-2008, 2010-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
-AC_DEFUN([gl_DOUBLE_EXPONENT_LOCATION],
+AC_DEFUN_ONCE([gl_DOUBLE_EXPONENT_LOCATION],
 [
   AC_CACHE_CHECK([where to find the exponent in a 'double'],
     [gl_cv_cc_double_expbit0],
diff --git a/m4/exponentf.m4 b/m4/exponentf.m4
index f6395f23f27..e761883939b 100644
--- a/m4/exponentf.m4
+++ b/m4/exponentf.m4
@@ -1,9 +1,9 @@
-# exponentf.m4 serial 2
+# exponentf.m4 serial 3
 dnl Copyright (C) 2007-2008, 2010-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
-AC_DEFUN([gl_FLOAT_EXPONENT_LOCATION],
+AC_DEFUN_ONCE([gl_FLOAT_EXPONENT_LOCATION],
 [
   AC_CACHE_CHECK([where to find the exponent in a 'float'],
     [gl_cv_cc_float_expbit0],
diff --git a/m4/exponentl.m4 b/m4/exponentl.m4
index e1fa5c48cc7..bc5638737e5 100644
--- a/m4/exponentl.m4
+++ b/m4/exponentl.m4
@@ -1,9 +1,9 @@
-# exponentl.m4 serial 5
+# exponentl.m4 serial 6
 dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
-AC_DEFUN([gl_LONG_DOUBLE_EXPONENT_LOCATION],
+AC_DEFUN_ONCE([gl_LONG_DOUBLE_EXPONENT_LOCATION],
 [
   AC_REQUIRE([gl_BIGENDIAN])
   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 9f701e95211..4c1e41daf51 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -232,12 +232,9 @@ AC_DEFUN([gl_EARLY],
   # Code from module vla:
   # Code from module warnings:
   # Code from module xalloc-oversized:
-<<<<<<< HEAD
   # Code from module xsize:
-=======
   # Code from module year2038:
   AC_REQUIRE([AC_SYS_YEAR2038])
->>>>>>> origin/master
 ])
 
 # This macro should be invoked from ./configure.ac, in the section
@@ -803,7 +800,7 @@ AC_DEFUN([gl_INIT],
   }
   func_gl_gnulib_m4code_fseterr ()
   {
-    if ! $gl_gnulib_enabled_fseterr; then
+    if $gl_gnulib_enabled_fseterr; then :; else
       gl_FUNC_FSETERR
       gl_CONDITIONAL([GL_COND_OBJ_FSETERR], [test $ac_cv_func___fseterr = no])
       gl_gnulib_enabled_fseterr=true
@@ -811,7 +808,7 @@ AC_DEFUN([gl_INIT],
   }
   func_gl_gnulib_m4code_getdelim ()
   {
-    if ! $gl_gnulib_enabled_getdelim; then
+    if $gl_gnulib_enabled_getdelim; then :; else
       gl_FUNC_GETDELIM
       gl_CONDITIONAL([GL_COND_OBJ_GETDELIM],
                      [test $HAVE_GETDELIM = 0 || test $REPLACE_GETDELIM = 1])
@@ -892,7 +889,7 @@ AC_DEFUN([gl_INIT],
   }
   func_gl_gnulib_m4code_3f0e593033d1fc2c127581960f641b66 ()
   {
-    if ! $gl_gnulib_enabled_3f0e593033d1fc2c127581960f641b66; then
+    if $gl_gnulib_enabled_3f0e593033d1fc2c127581960f641b66; then :; else
       gl_FUNC_ISNANF_NO_LIBM
       if test $gl_func_isnanf_no_libm != yes; then
         AC_LIBOBJ([isnanf])
@@ -1029,7 +1026,7 @@ AC_DEFUN([gl_INIT],
   }
   func_gl_gnulib_m4code_size_max ()
   {
-    if ! $gl_gnulib_enabled_size_max; then
+    if $gl_gnulib_enabled_size_max; then :; else
       gl_SIZE_MAX
       gl_gnulib_enabled_size_max=true
     fi
@@ -1056,7 +1053,7 @@ AC_DEFUN([gl_INIT],
   }
   func_gl_gnulib_m4code_vasnprintf ()
   {
-    if ! $gl_gnulib_enabled_vasnprintf; then
+    if $gl_gnulib_enabled_vasnprintf; then :; else
       AC_REQUIRE([AC_C_RESTRICT])
       gl_FUNC_VASNPRINTF
       gl_gnulib_enabled_vasnprintf=true
@@ -1065,7 +1062,7 @@ AC_DEFUN([gl_INIT],
   }
   func_gl_gnulib_m4code_ed5616be3593d355b981ffab56b9f37b ()
   {
-    if ! $gl_gnulib_enabled_ed5616be3593d355b981ffab56b9f37b; then
+    if $gl_gnulib_enabled_ed5616be3593d355b981ffab56b9f37b; then :; else
       gl_FUNC_VFPRINTF_POSIX
       gl_STDIO_MODULE_INDICATOR([vfprintf-posix])
       gl_MODULE_INDICATOR([vfprintf-posix])
@@ -1086,7 +1083,7 @@ AC_DEFUN([gl_INIT],
   }
   func_gl_gnulib_m4code_xsize ()
   {
-    if ! $gl_gnulib_enabled_xsize; then
+    if $gl_gnulib_enabled_xsize; then :; else
       gl_XSIZE
       gl_gnulib_enabled_xsize=true
       func_gl_gnulib_m4code_size_max
@@ -1749,7 +1746,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/pipe2.m4
   m4/printf-frexp.m4
   m4/printf-frexpl.m4
-  m4/printf-posix-rpl.m4
+  m4/printf-posix.m4
   m4/printf.m4
   m4/pselect.m4
   m4/pthread_sigmask.m4
diff --git a/m4/printf-posix.m4 b/m4/printf-posix.m4
new file mode 100644
index 00000000000..9aebf4002d6
--- /dev/null
+++ b/m4/printf-posix.m4
@@ -0,0 +1,36 @@
+# printf-posix.m4 serial 5
+dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_PRINTF_POSIX],
+[
+  AC_REQUIRE([gl_FUNC_PRINTF_IS_POSIX])
+  if test $gl_cv_func_printf_posix = no; then
+    gl_PREREQ_VASNPRINTF_WITH_POSIX_EXTRAS
+    gl_REPLACE_VASNPRINTF
+    gl_REPLACE_PRINTF
+  fi
+])
+
+dnl Test whether printf is POSIX compliant.
+dnl Result is gl_cv_func_printf_posix.
+AC_DEFUN([gl_FUNC_PRINTF_IS_POSIX],
+[
+  AC_REQUIRE([gl_FUNC_VFPRINTF_IS_POSIX])
+  gl_cv_func_printf_posix="$gl_cv_func_vfprintf_posix"
+])
+
+AC_DEFUN([gl_REPLACE_PRINTF],
+[
+  AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+  AC_REQUIRE([gl_ASM_SYMBOL_PREFIX])
+  AC_LIBOBJ([printf])
+  REPLACE_PRINTF=1
+  AC_DEFINE([REPLACE_PRINTF_POSIX], [1],
+    [Define if printf is overridden by a POSIX compliant gnulib 
implementation.])
+  gl_PREREQ_PRINTF
+])
+
+AC_DEFUN([gl_PREREQ_PRINTF], [:])
diff --git a/m4/printf.m4 b/m4/printf.m4
index de98a870e98..efb85a57afd 100644
--- a/m4/printf.m4
+++ b/m4/printf.m4
@@ -1,4 +1,4 @@
-# printf.m4 serial 74
+# printf.m4 serial 82
 dnl Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -101,6 +101,92 @@ changequote([,])dnl
     ])
 ])
 
+dnl Test whether the *printf family of functions supports the 'w8', 'w16',
+dnl 'w32', 'w64', 'wf8', 'wf16', 'wf32', 'wf64' size specifiers. (ISO C23)
+dnl Result is gl_cv_func_printf_sizes_c23.
+
+AC_DEFUN([gl_PRINTF_SIZES_C23],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([gl_AC_HEADER_STDINT_H])
+  AC_REQUIRE([gl_AC_HEADER_INTTYPES_H])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports size specifiers as in C23],
+    [gl_cv_func_printf_sizes_c23],
+    [
+      AC_RUN_IFELSE(
+        [AC_LANG_SOURCE([[
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+#endif
+static char buf[100];
+int main ()
+{
+  int result = 0;
+  buf[0] = '\0';
+  if (sprintf (buf, "%w8u %d", (uint8_t) 123, 33, 44, 55) < 0
+      || strcmp (buf, "123 33") != 0)
+    result |= 1;
+  buf[0] = '\0';
+  if (sprintf (buf, "%wf8u %d", (uint_fast8_t) 123, 33, 44, 55) < 0
+      || strcmp (buf, "123 33") != 0)
+    result |= 1;
+  buf[0] = '\0';
+  if (sprintf (buf, "%w16u %d", (uint16_t) 12345, 33, 44, 55) < 0
+      || strcmp (buf, "12345 33") != 0)
+    result |= 2;
+  buf[0] = '\0';
+  if (sprintf (buf, "%wf16u %d", (uint_fast16_t) 12345, 33, 44, 55) < 0
+      || strcmp (buf, "12345 33") != 0)
+    result |= 2;
+  buf[0] = '\0';
+  if (sprintf (buf, "%w32u %d", (uint32_t) 12345671, 33, 44, 55) < 0
+      || strcmp (buf, "12345671 33") != 0)
+    result |= 4;
+  buf[0] = '\0';
+  if (sprintf (buf, "%wf32u %d", (uint_fast32_t) 12345671, 33, 44, 55) < 0
+      || strcmp (buf, "12345671 33") != 0)
+    result |= 4;
+#if HAVE_STDINT_H_WITH_UINTMAX || HAVE_INTTYPES_H_WITH_UINTMAX
+  buf[0] = '\0';
+  if (sprintf (buf, "%w64u %d", (uint64_t) 12345671, 33, 44, 55) < 0
+      || strcmp (buf, "12345671 33") != 0)
+    result |= 8;
+  buf[0] = '\0';
+  if (sprintf (buf, "%wf64u %d", (uint_fast64_t) 12345671, 33, 44, 55) < 0
+      || strcmp (buf, "12345671 33") != 0)
+    result |= 8;
+#else
+  result |= 8;
+#endif
+  return result;
+}]])],
+        [gl_cv_func_printf_sizes_c23=yes],
+        [gl_cv_func_printf_sizes_c23=no],
+        [
+         case "$host_os" in
+                               # Guess no on glibc systems.
+           *-gnu* | gnu*)      gl_cv_func_printf_sizes_c23="guessing no";;
+                               # Guess no on musl systems.
+           *-musl* | midipix*) gl_cv_func_printf_sizes_c23="guessing no";;
+                               # Guess no on Android.
+           linux*-android*)    gl_cv_func_printf_sizes_c23="guessing no";;
+                               # Guess no on native Windows.
+           mingw*)             gl_cv_func_printf_sizes_c23="guessing no";;
+                               # If we don't know, obey --enable-cross-guesses.
+           *)                  
gl_cv_func_printf_sizes_c23="$gl_cross_guess_normal";;
+         esac
+        ])
+    ])
+])
+
 dnl Test whether the *printf family of functions supports 'long double'
 dnl arguments together with the 'L' size specifier. (ISO C99, POSIX:2001)
 dnl Result is gl_cv_func_printf_long_double.
@@ -603,6 +689,116 @@ int main ()
     ])
 ])
 
+dnl Test whether the *printf family of functions supports the 'b' conversion
+dnl specifier for binary output of integers.
+dnl (ISO C23)
+dnl Result is gl_cv_func_printf_directive_b.
+
+AC_DEFUN([gl_PRINTF_DIRECTIVE_B],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the 'b' directive],
+    [gl_cv_func_printf_directive_b],
+    [
+      AC_RUN_IFELSE(
+        [AC_LANG_SOURCE([[
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+  int result = 0;
+  if (sprintf (buf, "%b %d", 12345, 33, 44, 55) < 0
+      || strcmp (buf, "11000000111001 33") != 0)
+    result |= 1;
+  return result;
+}]])],
+        [gl_cv_func_printf_directive_b=yes],
+        [gl_cv_func_printf_directive_b=no],
+        [
+         case "$host_os" in
+                               # Guess yes on glibc >= 2.35 systems.
+           *-gnu* | gnu*)
+             AC_EGREP_CPP([Lucky], [
+               #include <features.h>
+               #ifdef __GNU_LIBRARY__
+                #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 35) || (__GLIBC__ > 
2)
+                 Lucky user
+                #endif
+               #endif
+               ],
+               [gl_cv_func_printf_directive_uppercase_b="guessing yes"],
+               [gl_cv_func_printf_directive_uppercase_b="guessing no"])
+             ;;
+                               # Guess no on musl systems.
+           *-musl* | midipix*) gl_cv_func_printf_directive_b="guessing no";;
+                               # Guess no on Android.
+           linux*-android*)    gl_cv_func_printf_directive_b="guessing no";;
+                               # Guess no on native Windows.
+           mingw*)             gl_cv_func_printf_directive_b="guessing no";;
+                               # If we don't know, obey --enable-cross-guesses.
+           *)                  
gl_cv_func_printf_directive_b="$gl_cross_guess_normal";;
+         esac
+        ])
+    ])
+])
+
+dnl Test whether the *printf family of functions supports the 'B' conversion
+dnl specifier for binary output of integers.
+dnl (GNU, encouraged by ISO C23 § 7.23.6.1)
+dnl Result is gl_cv_func_printf_directive_uppercase_b.
+
+AC_DEFUN([gl_PRINTF_DIRECTIVE_UPPERCASE_B],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the 'B' directive],
+    [gl_cv_func_printf_directive_uppercase_b],
+    [
+      AC_RUN_IFELSE(
+        [AC_LANG_SOURCE([[
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+  int result = 0;
+  if (sprintf (buf, "%#B %d", 12345, 33, 44, 55) < 0
+      || strcmp (buf, "0B11000000111001 33") != 0)
+    result |= 1;
+  return result;
+}]])],
+        [gl_cv_func_printf_directive_uppercase_b=yes],
+        [gl_cv_func_printf_directive_uppercase_b=no],
+        [
+         case "$host_os" in
+                               # Guess yes on glibc >= 2.35 systems.
+           *-gnu* | gnu*)
+             AC_EGREP_CPP([Lucky], [
+               #include <features.h>
+               #ifdef __GNU_LIBRARY__
+                #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 35) || (__GLIBC__ > 
2)
+                 Lucky user
+                #endif
+               #endif
+               ],
+               [gl_cv_func_printf_directive_uppercase_b="guessing yes"],
+               [gl_cv_func_printf_directive_uppercase_b="guessing no"])
+             ;;
+                               # Guess no on musl systems.
+           *-musl* | midipix*) 
gl_cv_func_printf_directive_uppercase_b="guessing no";;
+                               # Guess no on Android.
+           linux*-android*)    
gl_cv_func_printf_directive_uppercase_b="guessing no";;
+                               # Guess no on native Windows.
+           mingw*)             
gl_cv_func_printf_directive_uppercase_b="guessing no";;
+                               # If we don't know, obey --enable-cross-guesses.
+           *)                  
gl_cv_func_printf_directive_uppercase_b="$gl_cross_guess_normal";;
+         esac
+        ])
+    ])
+])
+
 dnl Test whether the *printf family of functions supports the %F format
 dnl directive. (ISO C99, POSIX:2001)
 dnl Result is gl_cv_func_printf_directive_f.
@@ -829,11 +1025,58 @@ changequote([,])dnl
     ])
 ])
 
+dnl Test whether the *printf family of functions supports the %lc format
+dnl directive and in particular, when the argument is a null wide character,
+dnl whether the functions don't produce a NUL byte.
+dnl Result is gl_cv_func_printf_directive_lc.
+
+AC_DEFUN([gl_PRINTF_DIRECTIVE_LC],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the 'lc' directive correctly],
+    [gl_cv_func_printf_directive_lc],
+    [
+      AC_RUN_IFELSE(
+        [AC_LANG_SOURCE([[
+#include <stdio.h>
+#include <wchar.h>
+#include <string.h>
+int main ()
+{
+  int result = 0;
+  char buf[100];
+  /* This test fails on glibc 2.35, FreeBSD 13.1, NetBSD 9.0, OpenBSD 7.2,
+     macOS 12.5, AIX 7.2, Solaris 11.4.
+     glibc 2.35 bug: <https://sourceware.org/bugzilla/show_bug.cgi?id=30257>  
*/
+  {
+    buf[0] = '\0';
+    if (sprintf (buf, "%lc%lc%lc", (wint_t) 'a', (wint_t) 0, (wint_t) 'z') < 0
+        || strcmp (buf, "az") != 0)
+      result |= 1;
+  }
+  return result;
+}]])],
+        [gl_cv_func_printf_directive_lc=yes],
+        [gl_cv_func_printf_directive_lc=no],
+        [
+changequote(,)dnl
+         case "$host_os" in
+                               # Guess yes on musl libc.
+           *-musl* | midipix*) gl_cv_func_printf_directive_lc="guessing yes";;
+                               # Guess no otherwise.
+           *)                  gl_cv_func_printf_directive_lc="guessing no";;
+         esac
+changequote([,])dnl
+        ])
+    ])
+])
+
 dnl Test whether the *printf family of functions supports POSIX/XSI format
 dnl strings with positions. (POSIX:2001)
 dnl Result is gl_cv_func_printf_positions.
 
-AC_DEFUN([gl_PRINTF_POSITIONS],
+AC_DEFUN_ONCE([gl_PRINTF_POSITIONS],
 [
   AC_REQUIRE([AC_PROG_CC])
   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
@@ -1641,88 +1884,227 @@ changequote([,])dnl
     ])
 ])
 
+dnl Test whether the swprintf function works correctly when it produces output
+dnl that contains null wide characters.
+dnl Result is gl_cv_func_swprintf_works.
+
+AC_DEFUN([gl_SWPRINTF_WORKS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CHECK_FUNCS_ONCE([swprintf])
+  AC_CACHE_CHECK([whether swprintf works],
+    [gl_cv_func_swprintf_works],
+    [
+      AC_RUN_IFELSE(
+        [AC_LANG_SOURCE([[
+#ifndef __USE_MINGW_ANSI_STDIO
+# define __USE_MINGW_ANSI_STDIO 1
+#endif
+#include <stdio.h>
+#include <wchar.h>
+int main()
+{
+  int result = 0;
+  { /* This test fails on musl, FreeBSD, NetBSD, OpenBSD, macOS, AIX.  */
+    wchar_t buf[5] = { 0xBEEF, 0xBEEF, 0xBEEF, 0xBEEF, 0xBEEF };
+    int ret = swprintf (buf, 4, L"%cz", '\0');
+    /* Expected result:
+         ret = 2, buf[0] = 0x0, buf[1] = 0x7a, buf[2] = 0x0, buf[3] = 0xbeef
+       musl libc 1.2.3:
+         ret = 2, buf[0] = 0x0, buf[1] = 0x0, buf[2] = 0x0, buf[3] = 0x0
+         Reported at <https://www.openwall.com/lists/musl/2023/03/22/9>.
+       FreeBSD 13.1, NetBSD 9.0, OpenBSD 7.2, macOS 12.5, AIX 7.2:
+         ret = 2, buf[0] = 0x0, buf[1] = 0xbeef, buf[2] = 0xbeef, buf[3] = 
0xbeef
+     */
+    if (ret < 0 || buf[1] != 'z')
+      result |= 1;
+  }
+  { /* This test fails on mingw.  */
+    wchar_t buf[2];
+    int ret = swprintf (buf, 2, L"%lc", (wint_t)0);
+    /* Expected: ret = 1
+       mingw:    ret = 0
+     */
+    if (ret != 1)
+      result |= 2;
+  }
+  return result;
+}]])],
+        [gl_cv_func_swprintf_works=yes],
+        [gl_cv_func_swprintf_works=no],
+        [case "$host_os" in
+                               # Guess yes on glibc systems.
+           *-gnu* | gnu*)      gl_cv_func_swprintf_works="guessing yes";;
+                               # Guess no on musl systems.
+           *-musl* | midipix*) gl_cv_func_swprintf_works="guessing yes";;
+                               # Guess no on FreeBSD, NetBSD, OpenBSD, macOS, 
AIX.
+           freebsd* | midnightbsd* | netbsd* | openbsd* | darwin* | aix*)
+                               gl_cv_func_swprintf_works="guessing no";;
+                               # Guess no on native Windows.
+           mingw* | pw*)       gl_cv_func_swprintf_works="guessing no";;
+                               # If we don't know, obey --enable-cross-guesses.
+           *)                  
gl_cv_func_swprintf_works="$gl_cross_guess_normal";;
+         esac
+        ])
+    ])
+])
+
+dnl Test whether the *wprintf family of functions supports the 'a' and 'A'
+dnl conversion specifier for hexadecimal output of 'long double' numbers.
+dnl (ISO C99, POSIX:2001)
+dnl Result is gl_cv_func_swprintf_directive_la.
+
+AC_DEFUN([gl_SWPRINTF_DIRECTIVE_LA],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether swprintf supports the 'La' and 'LA' directives],
+    [gl_cv_func_swprintf_directive_la],
+    [
+      AC_RUN_IFELSE(
+        [AC_LANG_SOURCE([[
+#include <stdio.h>
+#include <wchar.h>
+static wchar_t buf[100];
+int main ()
+{
+  int result = 0;
+  /* This catches a glibc 2.15 and Haiku 2022 bug.  */
+  if (swprintf (buf, sizeof (buf) / sizeof (wchar_t),
+                L"%La %d", 3.1416015625L, 33, 44, 55) < 0
+      || (wcscmp (buf, L"0x1.922p+1 33") != 0
+          && wcscmp (buf, L"0x3.244p+0 33") != 0
+          && wcscmp (buf, L"0x6.488p-1 33") != 0
+          && wcscmp (buf, L"0xc.91p-2 33") != 0))
+    result |= 1;
+  return result;
+}]])],
+        [gl_cv_func_swprintf_directive_la=yes],
+        [gl_cv_func_swprintf_directive_la=no],
+        [case "$host_os" in
+                                 # Guess yes on glibc >= 2.17 systems.
+           *-gnu* | gnu*)
+             AC_EGREP_CPP([Unlucky], [
+               #include <features.h>
+               #ifdef __GNU_LIBRARY__
+                #if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16) || (__GLIBC__ > 
2)) && !defined __UCLIBC__
+                 Unlucky
+                #endif
+               #endif
+               ],
+               [gl_cv_func_swprintf_directive_la="guessing yes"],
+               [gl_cv_func_swprintf_directive_la="guessing no"])
+             ;;
+                                 # Guess yes on musl systems.
+           *-musl* | midipix*)   gl_cv_func_swprintf_directive_la="guessing 
yes";;
+                                 # Guess yes on Android.
+           linux*-android*)      gl_cv_func_swprintf_directive_la="guessing 
no";;
+                                 # Guess yes on native Windows.
+           mingw*)               gl_cv_func_swprintf_directive_la="guessing 
no";;
+                                 # If we don't know, obey 
--enable-cross-guesses.
+           *)                    
gl_cv_func_swprintf_directive_la="$gl_cross_guess_normal";;
+         esac
+        ])
+    ])
+])
+
 dnl The results of these tests on various platforms are:
 dnl
 dnl 1 = gl_PRINTF_SIZES_C99
-dnl 2 = gl_PRINTF_LONG_DOUBLE
-dnl 3 = gl_PRINTF_INFINITE
-dnl 4 = gl_PRINTF_INFINITE_LONG_DOUBLE
-dnl 5 = gl_PRINTF_DIRECTIVE_A
-dnl 6 = gl_PRINTF_DIRECTIVE_F
-dnl 7 = gl_PRINTF_DIRECTIVE_N
-dnl 8 = gl_PRINTF_DIRECTIVE_LS
-dnl 9 = gl_PRINTF_POSITIONS
-dnl 10 = gl_PRINTF_FLAG_GROUPING
-dnl 11 = gl_PRINTF_FLAG_LEFTADJUST
-dnl 12 = gl_PRINTF_FLAG_ZERO
-dnl 13 = gl_PRINTF_PRECISION
-dnl 14 = gl_PRINTF_ENOMEM
-dnl 15 = gl_SNPRINTF_PRESENCE
-dnl 16 = gl_SNPRINTF_TRUNCATION_C99
-dnl 17 = gl_SNPRINTF_RETVAL_C99
-dnl 18 = gl_SNPRINTF_DIRECTIVE_N
-dnl 19 = gl_SNPRINTF_SIZE1
-dnl 20 = gl_VSNPRINTF_ZEROSIZE_C99
+dnl 2 = gl_PRINTF_SIZES_C23
+dnl 3 = gl_PRINTF_LONG_DOUBLE
+dnl 4 = gl_PRINTF_INFINITE
+dnl 5 = gl_PRINTF_INFINITE_LONG_DOUBLE
+dnl 6 = gl_PRINTF_DIRECTIVE_A
+dnl 7 = gl_PRINTF_DIRECTIVE_B
+dnl 8 = gl_PRINTF_DIRECTIVE_UPPERCASE_B
+dnl 9 = gl_PRINTF_DIRECTIVE_F
+dnl 10 = gl_PRINTF_DIRECTIVE_N
+dnl 11 = gl_PRINTF_DIRECTIVE_LS
+dnl 12 = gl_PRINTF_DIRECTIVE_LC
+dnl 13 = gl_PRINTF_POSITIONS
+dnl 14 = gl_PRINTF_FLAG_GROUPING
+dnl 15 = gl_PRINTF_FLAG_LEFTADJUST
+dnl 16 = gl_PRINTF_FLAG_ZERO
+dnl 17 = gl_PRINTF_PRECISION
+dnl 18 = gl_PRINTF_ENOMEM
+dnl 19 = gl_SNPRINTF_PRESENCE
+dnl 20 = gl_SNPRINTF_TRUNCATION_C99
+dnl 21 = gl_SNPRINTF_RETVAL_C99
+dnl 22 = gl_SNPRINTF_DIRECTIVE_N
+dnl 23 = gl_SNPRINTF_SIZE1
+dnl 24 = gl_VSNPRINTF_ZEROSIZE_C99
+dnl 25 = gl_SWPRINTF_WORKS
+dnl 26 = gl_SWPRINTF_DIRECTIVE_LA
 dnl
 dnl 1 = checking whether printf supports size specifiers as in C99...
-dnl 2 = checking whether printf supports 'long double' arguments...
-dnl 3 = checking whether printf supports infinite 'double' arguments...
-dnl 4 = checking whether printf supports infinite 'long double' arguments...
-dnl 5 = checking whether printf supports the 'a' and 'A' directives...
-dnl 6 = checking whether printf supports the 'F' directive...
-dnl 7 = checking whether printf supports the 'n' directive...
-dnl 8 = checking whether printf supports the 'ls' directive...
-dnl 9 = checking whether printf supports POSIX/XSI format strings with 
positions...
-dnl 10 = checking whether printf supports the grouping flag...
-dnl 11 = checking whether printf supports the left-adjust flag correctly...
-dnl 12 = checking whether printf supports the zero flag correctly...
-dnl 13 = checking whether printf supports large precisions...
-dnl 14 = checking whether printf survives out-of-memory conditions...
-dnl 15 = checking for snprintf...
-dnl 16 = checking whether snprintf truncates the result as in C99...
-dnl 17 = checking whether snprintf returns a byte count as in C99...
-dnl 18 = checking whether snprintf fully supports the 'n' directive...
-dnl 19 = checking whether snprintf respects a size of 1...
-dnl 20 = checking whether vsnprintf respects a zero size as in C99...
+dnl 2 = checking whether printf supports size specifiers as in C23...
+dnl 3 = checking whether printf supports 'long double' arguments...
+dnl 4 = checking whether printf supports infinite 'double' arguments...
+dnl 5 = checking whether printf supports infinite 'long double' arguments...
+dnl 6 = checking whether printf supports the 'a' and 'A' directives...
+dnl 7 = checking whether printf supports the 'b' directive...
+dnl 8 = checking whether printf supports the 'B' directive...
+dnl 9 = checking whether printf supports the 'F' directive...
+dnl 10 = checking whether printf supports the 'n' directive...
+dnl 11 = checking whether printf supports the 'ls' directive...
+dnl 12 = checking whether printf supports the 'lc' directive correctly...
+dnl 13 = checking whether printf supports POSIX/XSI format strings with 
positions...
+dnl 14 = checking whether printf supports the grouping flag...
+dnl 15 = checking whether printf supports the left-adjust flag correctly...
+dnl 16 = checking whether printf supports the zero flag correctly...
+dnl 17 = checking whether printf supports large precisions...
+dnl 18 = checking whether printf survives out-of-memory conditions...
+dnl 19 = checking for snprintf...
+dnl 20 = checking whether snprintf truncates the result as in C99...
+dnl 21 = checking whether snprintf returns a byte count as in C99...
+dnl 22 = checking whether snprintf fully supports the 'n' directive...
+dnl 23 = checking whether snprintf respects a size of 1...
+dnl 24 = checking whether vsnprintf respects a zero size as in C99...
+dnl 25 = checking whether swprintf works...
+dnl 26 = checking whether swprintf supports the 'La' and 'LA' directives...
 dnl
 dnl . = yes, # = no.
 dnl
-dnl                                  1  2  3  4  5  6  7  8  9 10 11 12 13 14 
15 16 17 18 19 20
-dnl   glibc 2.5                      .  .  .  .  .  .  .  .  .  .  .  .  .  .  
.  .  .  .  .  .
-dnl   glibc 2.3.6                    .  .  .  .  #  .  .  .  .  .  .  .  .  .  
.  .  .  .  .  .
-dnl   FreeBSD 13.0                   .  .  .  .  #  .  .  .  .  .  .  .  .  #  
.  .  .  .  .  .
-dnl   FreeBSD 5.4, 6.1               .  .  .  .  #  .  .  .  .  .  .  #  .  #  
.  .  .  .  .  .
-dnl   Mac OS X 10.13.5               .  .  .  #  #  .  #  .  .  .  .  .  .  .  
.  .  .  #  .  .
-dnl   Mac OS X 10.5.8                .  .  .  #  #  .  .  .  .  .  .  #  .  .  
.  .  .  .  .  .
-dnl   Mac OS X 10.3.9                .  .  .  .  #  .  .  .  .  .  .  #  .  #  
.  .  .  .  .  .
-dnl   OpenBSD 6.0, 6.7               .  .  .  .  #  .  .  .  .  .  .  .  .  #  
.  .  .  .  .  .
-dnl   OpenBSD 3.9, 4.0               .  .  #  #  #  #  .  #  .  #  .  #  .  #  
.  .  .  .  .  .
-dnl   Cygwin 1.7.0 (2009)            .  .  .  #  .  .  .  ?  .  .  .  .  .  ?  
.  .  .  .  .  .
-dnl   Cygwin 1.5.25 (2008)           .  .  .  #  #  .  .  #  .  .  .  .  .  #  
.  .  .  .  .  .
-dnl   Cygwin 1.5.19 (2006)           #  .  .  #  #  #  .  #  .  #  .  #  #  #  
.  .  .  .  .  .
-dnl   Solaris 11.4                   .  .  #  #  #  .  .  #  .  .  .  #  .  .  
.  .  .  .  .  .
-dnl   Solaris 11.3                   .  .  .  .  #  .  .  #  .  .  .  .  .  .  
.  .  .  .  .  .
-dnl   Solaris 11.0                   .  .  #  #  #  .  .  #  .  .  .  #  .  .  
.  .  .  .  .  .
-dnl   Solaris 10                     .  .  #  #  #  .  .  #  .  .  .  #  #  .  
.  .  .  .  .  .
-dnl   Solaris 2.6 ... 9              #  .  #  #  #  #  .  #  .  .  .  #  #  .  
.  .  #  .  .  .
-dnl   Solaris 2.5.1                  #  .  #  #  #  #  .  #  .  .  .  #  .  .  
#  #  #  #  #  #
-dnl   AIX 7.1                        .  .  #  #  #  .  .  .  .  .  .  #  #  .  
.  .  .  .  .  .
-dnl   AIX 5.2                        .  .  #  #  #  .  .  .  .  .  .  #  .  .  
.  .  .  .  .  .
-dnl   AIX 4.3.2, 5.1                 #  .  #  #  #  #  .  .  .  .  .  #  .  .  
.  .  #  .  .  .
-dnl   HP-UX 11.31                    .  .  .  .  #  .  .  .  .  .  .  #  .  .  
.  .  #  #  .  .
-dnl   HP-UX 11.{00,11,23}            #  .  .  .  #  #  .  .  .  .  .  #  .  .  
.  .  #  #  .  #
-dnl   HP-UX 10.20                    #  .  #  .  #  #  .  ?  .  .  #  #  .  .  
.  .  #  #  ?  #
-dnl   IRIX 6.5                       #  .  #  #  #  #  .  #  .  .  .  #  .  .  
.  .  #  .  .  .
-dnl   OSF/1 5.1                      #  .  #  #  #  #  .  .  .  .  .  #  .  .  
.  .  #  .  .  #
-dnl   OSF/1 4.0d                     #  .  #  #  #  #  .  .  .  .  .  #  .  .  
#  #  #  #  #  #
-dnl   NetBSD 9.0                     .  .  .  .  #  .  .  .  .  .  .  .  .  .  
.  .  .  .  .  .
-dnl   NetBSD 5.0                     .  .  .  #  #  .  .  .  .  .  .  #  .  #  
.  .  .  .  .  .
-dnl   NetBSD 4.0                     .  ?  ?  ?  ?  ?  .  ?  .  ?  ?  ?  ?  ?  
.  .  .  ?  ?  ?
-dnl   NetBSD 3.0                     .  .  .  .  #  #  .  ?  #  #  ?  #  .  #  
.  .  .  .  .  .
-dnl   Haiku                          .  .  .  #  #  #  .  #  .  .  .  .  .  ?  
.  .  ?  .  .  .
-dnl   BeOS                           #  #  .  #  #  #  .  ?  #  .  ?  .  #  ?  
.  .  ?  .  .  .
-dnl   Android 4.3                    .  .  #  #  #  #  #  #  .  #  .  #  .  #  
.  .  .  #  .  .
-dnl   old mingw / msvcrt             #  #  #  #  #  #  .  .  #  #  .  #  #  ?  
.  #  #  #  .  .
-dnl   MSVC 9                         #  #  #  #  #  #  #  .  #  #  .  #  #  ?  
#  #  #  #  .  .
-dnl   mingw 2009-2011                .  #  .  #  .  .  .  .  #  #  .  .  .  ?  
.  .  .  .  .  .
-dnl   mingw-w64 2011                 #  #  #  #  #  #  .  .  #  #  .  #  #  ?  
.  #  #  #  .  .
+dnl                                  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
+dnl   musl libc 1.2.3                .  #  .  .  .  .  #  #  .  .  .  .  .  .  
.  .  .  .  .  .  .  .  .  .  #  .
+dnl   glibc 2.35                     .  #  .  .  .  .  .  .  .  .  .  #  .  .  
.  .  .  .  .  .  .  .  .  .  .  .
+dnl   glibc 2.5                      .  #  .  .  .  .  #  #  .  .  .  #  .  .  
.  .  .  .  .  .  .  .  .  .  .  #
+dnl   glibc 2.3.6                    .  #  .  .  .  #  #  #  .  .  .  #  .  .  
.  .  .  .  .  .  .  .  .  .  .  #
+dnl   FreeBSD 13.0                   .  #  .  .  .  #  #  #  .  .  .  #  .  .  
.  .  .  #  .  .  .  .  .  .  #  .
+dnl   FreeBSD 5.4, 6.1               .  #  .  .  .  #  #  #  .  .  .  #  .  .  
.  #  .  #  .  .  .  .  .  .  #  ?
+dnl   Mac OS X 10.13.5               .  #  .  .  #  #  #  #  .  #  .  #  .  .  
.  .  .  .  .  .  .  #  .  .  #  ?
+dnl   Mac OS X 10.5.8                .  #  .  .  #  #  #  #  .  .  .  #  .  .  
.  #  .  .  .  .  .  .  .  .  #  ?
+dnl   Mac OS X 10.3.9                .  #  .  .  .  #  #  #  .  .  .  #  .  .  
.  #  .  #  .  .  .  .  .  .  #  ?
+dnl   OpenBSD 6.0, 6.7               .  #  .  .  .  #  #  #  .  .  .  #  .  .  
.  .  .  #  .  .  .  .  .  .  #  .
+dnl   OpenBSD 3.9, 4.0               .  #  .  #  #  #  #  #  #  .  #  #  .  #  
.  #  .  #  .  .  .  .  .  .  #  ?
+dnl   Cygwin 1.7.0 (2009)            .  #  .  .  #  .  #  #  .  .  ?  ?  .  .  
.  .  .  ?  .  .  .  .  .  .  ?  ?
+dnl   Cygwin 1.5.25 (2008)           .  #  .  .  #  #  #  #  .  .  #  ?  .  .  
.  .  .  #  .  .  .  .  .  .  ?  ?
+dnl   Cygwin 1.5.19 (2006)           #  #  .  .  #  #  #  #  #  .  #  ?  .  #  
.  #  #  #  .  .  .  .  .  .  ?  ?
+dnl   Solaris 11.4                   .  #  .  #  #  #  #  #  .  .  #  #  .  .  
.  #  .  .  .  .  .  .  .  .  .  ?
+dnl   Solaris 11.3                   .  #  .  .  .  #  #  #  .  .  #  #  .  .  
.  .  .  .  .  .  .  .  .  .  .  ?
+dnl   Solaris 11.0                   .  #  .  #  #  #  #  #  .  .  #  #  .  .  
.  #  .  .  .  .  .  .  .  .  ?  ?
+dnl   Solaris 10                     .  #  .  #  #  #  #  #  .  .  #  #  .  .  
.  #  #  .  .  .  .  .  .  .  ?  ?
+dnl   Solaris 2.6 ... 9              #  #  .  #  #  #  #  #  #  .  #  #  .  .  
.  #  #  .  .  .  #  .  .  .  ?  ?
+dnl   Solaris 2.5.1                  #  #  .  #  #  #  #  #  #  .  #  #  .  .  
.  #  .  .  #  #  #  #  #  #  ?  ?
+dnl   AIX 7.1                        .  #  .  #  #  #  #  #  .  .  .  #  .  .  
.  #  #  .  .  .  .  .  .  .  #  .
+dnl   AIX 5.2                        .  #  .  #  #  #  #  #  .  .  .  #  .  .  
.  #  .  .  .  .  .  .  .  .  #  ?
+dnl   AIX 4.3.2, 5.1                 #  #  .  #  #  #  #  #  #  .  .  #  .  .  
.  #  .  .  .  .  #  .  .  .  #  ?
+dnl   HP-UX 11.31                    .  #  .  .  .  #  #  #  .  .  .  ?  .  .  
.  #  .  .  .  .  #  #  .  .  ?  ?
+dnl   HP-UX 11.{00,11,23}            #  #  .  .  .  #  #  #  #  .  .  ?  .  .  
.  #  .  .  .  .  #  #  .  #  ?  ?
+dnl   HP-UX 10.20                    #  #  .  #  .  #  #  #  #  .  ?  ?  .  .  
#  #  .  .  .  .  #  #  ?  #  ?  ?
+dnl   IRIX 6.5                       #  #  .  #  #  #  #  #  #  .  #  #  .  .  
.  #  .  .  .  .  #  .  .  .  #  ?
+dnl   OSF/1 5.1                      #  #  .  #  #  #  #  #  #  .  .  ?  .  .  
.  #  .  .  .  .  #  .  .  #  ?  ?
+dnl   OSF/1 4.0d                     #  #  .  #  #  #  #  #  #  .  .  ?  .  .  
.  #  .  .  #  #  #  #  #  #  ?  ?
+dnl   NetBSD 9.0                     .  #  .  .  .  #  #  #  .  .  .  #  .  .  
.  .  .  .  .  .  .  .  .  .  #  .
+dnl   NetBSD 5.0                     .  #  .  .  #  #  #  #  .  .  .  #  .  .  
.  #  .  #  .  .  .  .  .  .  #  ?
+dnl   NetBSD 4.0                     .  #  ?  ?  ?  ?  #  #  ?  .  ?  #  .  ?  
?  ?  ?  ?  .  .  .  ?  ?  ?  #  ?
+dnl   NetBSD 3.0                     .  #  .  .  .  #  #  #  #  .  ?  #  #  #  
?  #  .  #  .  .  .  .  .  .  #  ?
+dnl   Haiku                          .  #  .  .  #  #  #  #  #  .  #  ?  .  .  
.  .  .  ?  .  .  ?  .  .  .  .  #
+dnl   BeOS                           #  #  #  .  #  #  #  #  #  .  ?  ?  #  .  
?  .  #  ?  .  .  ?  .  .  .  ?  ?
+dnl   Android 4.3                    .  #  .  #  #  #  #  #  #  #  #  ?  .  #  
.  #  .  #  .  .  .  #  .  .  ?  ?
+dnl   old mingw / msvcrt             #  #  #  #  #  #  #  #  #  .  .  ?  #  #  
.  #  #  ?  .  #  #  #  .  .  #  ?
+dnl   MSVC 9                         #  #  #  #  #  #  #  #  #  #  .  ?  #  #  
.  #  #  ?  #  #  #  #  .  .  #  ?
+dnl   mingw 2009-2011                .  #  #  .  #  .  #  #  .  .  .  ?  #  #  
.  .  .  ?  .  .  .  .  .  .  #  ?
+dnl   mingw-w64 2011                 #  #  #  #  #  #  #  #  #  .  .  ?  #  #  
.  #  #  ?  .  #  #  #  .  .  #  ?
diff --git a/m4/vasnprintf.m4 b/m4/vasnprintf.m4
index fda90c402b4..639b29a1f39 100644
--- a/m4/vasnprintf.m4
+++ b/m4/vasnprintf.m4
@@ -1,4 +1,4 @@
-# vasnprintf.m4 serial 39
+# vasnprintf.m4 serial 49
 dnl Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -29,6 +29,15 @@ AC_DEFUN([gl_REPLACE_VASNPRINTF],
   gl_PREREQ_ASNPRINTF
 ])
 
+AC_DEFUN([gl_FUNC_VASNWPRINTF],
+[
+  AC_LIBOBJ([printf-args])
+  gl_PREREQ_PRINTF_ARGS
+  gl_PREREQ_PRINTF_PARSE
+  gl_PREREQ_VASNWPRINTF
+  gl_PREREQ_ASNPRINTF
+])
+
 # Prerequisites of lib/printf-args.h, lib/printf-args.c.
 AC_DEFUN([gl_PREREQ_PRINTF_ARGS],
 [
@@ -37,6 +46,7 @@ AC_DEFUN([gl_PREREQ_PRINTF_ARGS],
 ])
 
 # Prerequisites of lib/printf-parse.h, lib/printf-parse.c.
+# Prerequisites of lib/wprintf-parse.h, lib/wprintf-parse.c.
 AC_DEFUN([gl_PREREQ_PRINTF_PARSE],
 [
   AC_REQUIRE([gl_FEATURES_H])
@@ -50,19 +60,13 @@ AC_DEFUN([gl_PREREQ_PRINTF_PARSE],
   AC_REQUIRE([gt_AC_TYPE_INTMAX_T])
 ])
 
-# Prerequisites of lib/vasnprintf.c.
+# Prerequisites of lib/vasnprintf.c if !WIDE_CHAR_VERSION.
 AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF],
 [
-  AC_REQUIRE([AC_FUNC_ALLOCA])
-  AC_REQUIRE([gt_TYPE_WCHAR_T])
-  AC_REQUIRE([gt_TYPE_WINT_T])
-  AC_CHECK_FUNCS([snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb])
+  AC_CHECK_FUNCS([snprintf strnlen wcrtomb])
   dnl Use the _snprintf function only if it is declared (because on NetBSD it
   dnl is defined as a weak alias of snprintf; we prefer to use the latter).
   AC_CHECK_DECLS([_snprintf], , , [[#include <stdio.h>]])
-  dnl Knowing DBL_EXPBIT0_WORD and DBL_EXPBIT0_BIT enables an optimization
-  dnl in the code for NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE.
-  AC_REQUIRE([gl_DOUBLE_EXPONENT_LOCATION])
   dnl We can avoid a lot of code by assuming that snprintf's return value
   dnl conforms to ISO C99. So check that.
   AC_REQUIRE([gl_SNPRINTF_RETVAL_C99])
@@ -84,6 +88,55 @@ AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF],
          terminated.])
       ;;
   esac
+  gl_PREREQ_VASNXPRINTF
+])
+
+# Prerequisites of lib/vasnwprintf.c.
+AC_DEFUN_ONCE([gl_PREREQ_VASNWPRINTF],
+[
+  AC_CHECK_FUNCS_ONCE([swprintf wcsnlen mbrtowc])
+  AC_CHECK_DECLS([_snwprintf], , , [[#include <stdio.h>]])
+  AC_CHECK_DECLS([wcsnlen], , , [[#include <wchar.h>]])
+  gl_SWPRINTF_WORKS
+  case "$gl_cv_func_swprintf_works" in
+    *yes)
+      AC_DEFINE([HAVE_WORKING_SWPRINTF], [1],
+        [Define if the swprintf function works correctly when it produces 
output
+         that contains null wide characters.])
+      ;;
+  esac
+  gl_MBRTOWC_C_LOCALE
+  case "$gl_cv_func_mbrtowc_C_locale_sans_EILSEQ" in
+    *yes) ;;
+    *)
+      AC_DEFINE([NEED_WPRINTF_DIRECTIVE_C], [1],
+        [Define if the vasnwprintf implementation needs special code for
+         the 'c' directive.])
+      ;;
+  esac
+  gl_SWPRINTF_DIRECTIVE_LA
+  case "$gl_cv_func_swprintf_directive_la" in
+    *yes) ;;
+    *)
+      AC_DEFINE([NEED_WPRINTF_DIRECTIVE_LA], [1],
+        [Define if the vasnwprintf implementation needs special code for
+         the 'a' directive with 'long double' arguments.])
+      ;;
+  esac
+  gl_MUSL_LIBC
+  gl_PREREQ_VASNXPRINTF
+])
+
+# Common prerequisites of lib/vasnprintf.c and lib/vasnwprintf.c.
+AC_DEFUN_ONCE([gl_PREREQ_VASNXPRINTF],
+[
+  AC_REQUIRE([AC_FUNC_ALLOCA])
+  AC_REQUIRE([gt_TYPE_WCHAR_T])
+  AC_REQUIRE([gt_TYPE_WINT_T])
+  AC_CHECK_FUNCS([wcslen])
+  dnl Knowing DBL_EXPBIT0_WORD and DBL_EXPBIT0_BIT enables an optimization
+  dnl in the code for NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE.
+  AC_REQUIRE([gl_DOUBLE_EXPONENT_LOCATION])
 ])
 
 # Extra prerequisites of lib/vasnprintf.c for supporting 'long double'
@@ -157,6 +210,21 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_A],
   esac
 ])
 
+# Extra prerequisites of lib/vasnprintf.c for supporting the 'b' directive.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_B],
+[
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_B])
+  case "$gl_cv_func_printf_directive_b" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_DIRECTIVE_B], [1],
+        [Define if the vasnprintf implementation needs special code for
+         the 'b' directive.])
+      ;;
+  esac
+])
+
 # Extra prerequisites of lib/vasnprintf.c for supporting the 'F' directive.
 AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_F],
 [
@@ -187,6 +255,21 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_LS],
   esac
 ])
 
+# Extra prerequisites of lib/vasnprintf.c for supporting the 'lc' directive.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_LC],
+[
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
+  case "$gl_cv_func_printf_directive_lc" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_DIRECTIVE_LC], [1],
+        [Define if the vasnprintf implementation needs special code for
+         the 'lc' directive.])
+      ;;
+  esac
+])
+
 # Extra prerequisites of lib/vasnprintf.c for supporting the ' flag.
 AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_GROUPING],
 [
@@ -276,15 +359,17 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_ENOMEM],
 ])
 
 # Prerequisites of lib/vasnprintf.c including all extras for POSIX compliance.
-AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS],
+AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_POSIX_EXTRAS],
 [
   AC_REQUIRE([gl_PREREQ_VASNPRINTF])
   gl_PREREQ_VASNPRINTF_LONG_DOUBLE
   gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE
   gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE
   gl_PREREQ_VASNPRINTF_DIRECTIVE_A
+  gl_PREREQ_VASNPRINTF_DIRECTIVE_B
   gl_PREREQ_VASNPRINTF_DIRECTIVE_F
   gl_PREREQ_VASNPRINTF_DIRECTIVE_LS
+  gl_PREREQ_VASNPRINTF_DIRECTIVE_LC
   gl_PREREQ_VASNPRINTF_FLAG_GROUPING
   gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST
   gl_PREREQ_VASNPRINTF_FLAG_ZERO
@@ -292,7 +377,34 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS],
   gl_PREREQ_VASNPRINTF_ENOMEM
 ])
 
+# Extra prerequisites of lib/vasnprintf.c for supporting the 'B' directive.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_UPPERCASE_B],
+[
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_UPPERCASE_B])
+  case "$gl_cv_func_printf_directive_uppercase_b" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_DIRECTIVE_UPPERCASE_B], [1],
+        [Define if the vasnprintf implementation needs special code for
+         the 'B' directive.])
+      ;;
+  esac
+])
+
+# Prerequisites of lib/vasnprintf.c including all extras for POSIX compliance
+# and GNU compatibility.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_GNU_EXTRAS],
+[
+  gl_PREREQ_VASNPRINTF_WITH_POSIX_EXTRAS
+  AC_DEFINE([SUPPORT_GNU_PRINTF_DIRECTIVES], [1],
+    [Define if the vasnprintf implementation should support GNU compatible
+     printf directives.])
+  gl_PREREQ_VASNPRINTF_DIRECTIVE_UPPERCASE_B
+])
+
 # Prerequisites of lib/asnprintf.c.
+# Prerequisites of lib/asnwprintf.c.
 AC_DEFUN([gl_PREREQ_ASNPRINTF],
 [
 ])
diff --git a/m4/vasprintf-posix.m4 b/m4/vasprintf-posix.m4
index 7c198a64108..3c7a6540bd1 100644
--- a/m4/vasprintf-posix.m4
+++ b/m4/vasprintf-posix.m4
@@ -1,19 +1,34 @@
-# vasprintf-posix.m4 serial 13
+# vasprintf-posix.m4 serial 17
 dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
 AC_DEFUN([gl_FUNC_VASPRINTF_POSIX],
+[
+  AC_REQUIRE([gl_FUNC_VASPRINTF_IS_POSIX])
+  if test $gl_cv_func_vasprintf_posix = no; then
+    gl_PREREQ_VASNPRINTF_WITH_POSIX_EXTRAS
+    gl_REPLACE_VASNPRINTF
+    gl_REPLACE_VASPRINTF
+  fi
+])
+
+dnl Test whether vasprintf exists and is POSIX compliant.
+dnl Result is gl_cv_func_vasprintf_posix.
+AC_DEFUN([gl_FUNC_VASPRINTF_IS_POSIX],
 [
   AC_REQUIRE([gl_PRINTF_SIZES_C99])
+  AC_REQUIRE([gl_PRINTF_SIZES_C23])
   AC_REQUIRE([gl_PRINTF_LONG_DOUBLE])
   AC_REQUIRE([gl_PRINTF_INFINITE])
   AC_REQUIRE([gl_PRINTF_INFINITE_LONG_DOUBLE])
   AC_REQUIRE([gl_PRINTF_DIRECTIVE_A])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_B])
   AC_REQUIRE([gl_PRINTF_DIRECTIVE_F])
   AC_REQUIRE([gl_PRINTF_DIRECTIVE_N])
   AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
   AC_REQUIRE([gl_PRINTF_POSITIONS])
   AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
   AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
@@ -24,37 +39,49 @@ AC_DEFUN([gl_FUNC_VASPRINTF_POSIX],
   AC_CHECK_FUNCS([vasprintf])
   case "$gl_cv_func_printf_sizes_c99" in
     *yes)
-      case "$gl_cv_func_printf_long_double" in
+      case "$gl_cv_func_printf_sizes_c23" in
         *yes)
-          case "$gl_cv_func_printf_infinite" in
+          case "$gl_cv_func_printf_long_double" in
             *yes)
-              case "$gl_cv_func_printf_infinite_long_double" in
+              case "$gl_cv_func_printf_infinite" in
                 *yes)
-                  case "$gl_cv_func_printf_directive_a" in
+                  case "$gl_cv_func_printf_infinite_long_double" in
                     *yes)
-                      case "$gl_cv_func_printf_directive_f" in
+                      case "$gl_cv_func_printf_directive_a" in
                         *yes)
-                          case "$gl_cv_func_printf_directive_n" in
+                          case "$gl_cv_func_printf_directive_b" in
                             *yes)
-                              case "$gl_cv_func_printf_directive_ls" in
+                              case "$gl_cv_func_printf_directive_f" in
                                 *yes)
-                                  case "$gl_cv_func_printf_positions" in
+                                  case "$gl_cv_func_printf_directive_n" in
                                     *yes)
-                                      case "$gl_cv_func_printf_flag_grouping" 
in
+                                      case "$gl_cv_func_printf_directive_ls" in
                                         *yes)
-                                          case 
"$gl_cv_func_printf_flag_leftadjust" in
+                                          case 
"$gl_cv_func_printf_directive_lc" in
                                             *yes)
-                                              case 
"$gl_cv_func_printf_flag_zero" in
+                                              case 
"$gl_cv_func_printf_positions" in
                                                 *yes)
-                                                  case 
"$gl_cv_func_printf_precision" in
+                                                  case 
"$gl_cv_func_printf_flag_grouping" in
                                                     *yes)
-                                                      case 
"$gl_cv_func_printf_enomem" in
+                                                      case 
"$gl_cv_func_printf_flag_leftadjust" in
                                                         *yes)
-                                                          if test 
$ac_cv_func_vasprintf = yes; then
-                                                            # vasprintf exists 
and is
-                                                            # already POSIX 
compliant.
-                                                            
gl_cv_func_vasprintf_posix=yes
-                                                          fi
+                                                          case 
"$gl_cv_func_printf_flag_zero" in
+                                                            *yes)
+                                                              case 
"$gl_cv_func_printf_precision" in
+                                                                *yes)
+                                                                  case 
"$gl_cv_func_printf_enomem" in
+                                                                    *yes)
+                                                                      if test 
$ac_cv_func_vasprintf = yes; then
+                                                                        # 
vasprintf exists and is
+                                                                        # 
already POSIX compliant.
+                                                                        
gl_cv_func_vasprintf_posix=yes
+                                                                      fi
+                                                                      ;;
+                                                                  esac
+                                                                  ;;
+                                                              esac
+                                                              ;;
+                                                          esac
                                                           ;;
                                                       esac
                                                       ;;
@@ -83,19 +110,4 @@ AC_DEFUN([gl_FUNC_VASPRINTF_POSIX],
       esac
       ;;
   esac
-  if test $gl_cv_func_vasprintf_posix = no; then
-    gl_PREREQ_VASNPRINTF_LONG_DOUBLE
-    gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE
-    gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE
-    gl_PREREQ_VASNPRINTF_DIRECTIVE_A
-    gl_PREREQ_VASNPRINTF_DIRECTIVE_F
-    gl_PREREQ_VASNPRINTF_DIRECTIVE_LS
-    gl_PREREQ_VASNPRINTF_FLAG_GROUPING
-    gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST
-    gl_PREREQ_VASNPRINTF_FLAG_ZERO
-    gl_PREREQ_VASNPRINTF_PRECISION
-    gl_PREREQ_VASNPRINTF_ENOMEM
-    gl_REPLACE_VASNPRINTF
-    gl_REPLACE_VASPRINTF
-  fi
 ])
diff --git a/m4/vfprintf-posix.m4 b/m4/vfprintf-posix.m4
index ec680522142..6b51c50adab 100644
--- a/m4/vfprintf-posix.m4
+++ b/m4/vfprintf-posix.m4
@@ -1,19 +1,34 @@
-# vfprintf-posix.m4 serial 14
+# vfprintf-posix.m4 serial 18
 dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
 AC_DEFUN([gl_FUNC_VFPRINTF_POSIX],
+[
+  AC_REQUIRE([gl_FUNC_VFPRINTF_IS_POSIX])
+  if test $gl_cv_func_vfprintf_posix = no; then
+    gl_PREREQ_VASNPRINTF_WITH_POSIX_EXTRAS
+    gl_REPLACE_VASNPRINTF
+    gl_REPLACE_VFPRINTF
+  fi
+])
+
+dnl Test whether vfprintf is POSIX compliant.
+dnl Result is gl_cv_func_vfprintf_posix.
+AC_DEFUN([gl_FUNC_VFPRINTF_IS_POSIX],
 [
   AC_REQUIRE([gl_PRINTF_SIZES_C99])
+  AC_REQUIRE([gl_PRINTF_SIZES_C23])
   AC_REQUIRE([gl_PRINTF_LONG_DOUBLE])
   AC_REQUIRE([gl_PRINTF_INFINITE])
   AC_REQUIRE([gl_PRINTF_INFINITE_LONG_DOUBLE])
   AC_REQUIRE([gl_PRINTF_DIRECTIVE_A])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_B])
   AC_REQUIRE([gl_PRINTF_DIRECTIVE_F])
   AC_REQUIRE([gl_PRINTF_DIRECTIVE_N])
   AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS])
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
   AC_REQUIRE([gl_PRINTF_POSITIONS])
   AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
   AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
@@ -23,35 +38,47 @@ AC_DEFUN([gl_FUNC_VFPRINTF_POSIX],
   gl_cv_func_vfprintf_posix=no
   case "$gl_cv_func_printf_sizes_c99" in
     *yes)
-      case "$gl_cv_func_printf_long_double" in
+      case "$gl_cv_func_printf_sizes_c23" in
         *yes)
-          case "$gl_cv_func_printf_infinite" in
+          case "$gl_cv_func_printf_long_double" in
             *yes)
-              case "$gl_cv_func_printf_infinite_long_double" in
+              case "$gl_cv_func_printf_infinite" in
                 *yes)
-                  case "$gl_cv_func_printf_directive_a" in
+                  case "$gl_cv_func_printf_infinite_long_double" in
                     *yes)
-                      case "$gl_cv_func_printf_directive_f" in
+                      case "$gl_cv_func_printf_directive_a" in
                         *yes)
-                          case "$gl_cv_func_printf_directive_n" in
+                          case "$gl_cv_func_printf_directive_b" in
                             *yes)
-                              case "$gl_cv_func_printf_directive_ls" in
+                              case "$gl_cv_func_printf_directive_f" in
                                 *yes)
-                                  case "$gl_cv_func_printf_positions" in
+                                  case "$gl_cv_func_printf_directive_n" in
                                     *yes)
-                                      case "$gl_cv_func_printf_flag_grouping" 
in
+                                      case "$gl_cv_func_printf_directive_ls" in
                                         *yes)
-                                          case 
"$gl_cv_func_printf_flag_leftadjust" in
+                                          case 
"$gl_cv_func_printf_directive_lc" in
                                             *yes)
-                                              case 
"$gl_cv_func_printf_flag_zero" in
+                                              case 
"$gl_cv_func_printf_positions" in
                                                 *yes)
-                                                  case 
"$gl_cv_func_printf_precision" in
+                                                  case 
"$gl_cv_func_printf_flag_grouping" in
                                                     *yes)
-                                                      case 
"$gl_cv_func_printf_enomem" in
+                                                      case 
"$gl_cv_func_printf_flag_leftadjust" in
                                                         *yes)
-                                                          # vfprintf exists 
and is
-                                                          # already POSIX 
compliant.
-                                                          
gl_cv_func_vfprintf_posix=yes
+                                                          case 
"$gl_cv_func_printf_flag_zero" in
+                                                            *yes)
+                                                              case 
"$gl_cv_func_printf_precision" in
+                                                                *yes)
+                                                                  case 
"$gl_cv_func_printf_enomem" in
+                                                                    *yes)
+                                                                      # 
vfprintf exists and is
+                                                                      # 
already POSIX compliant.
+                                                                      
gl_cv_func_vfprintf_posix=yes
+                                                                      ;;
+                                                                  esac
+                                                                  ;;
+                                                              esac
+                                                              ;;
+                                                          esac
                                                           ;;
                                                       esac
                                                       ;;
@@ -80,21 +107,6 @@ AC_DEFUN([gl_FUNC_VFPRINTF_POSIX],
       esac
       ;;
   esac
-  if test $gl_cv_func_vfprintf_posix = no; then
-    gl_PREREQ_VASNPRINTF_LONG_DOUBLE
-    gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE
-    gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE
-    gl_PREREQ_VASNPRINTF_DIRECTIVE_A
-    gl_PREREQ_VASNPRINTF_DIRECTIVE_F
-    gl_PREREQ_VASNPRINTF_DIRECTIVE_LS
-    gl_PREREQ_VASNPRINTF_FLAG_GROUPING
-    gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST
-    gl_PREREQ_VASNPRINTF_FLAG_ZERO
-    gl_PREREQ_VASNPRINTF_PRECISION
-    gl_PREREQ_VASNPRINTF_ENOMEM
-    gl_REPLACE_VASNPRINTF
-    gl_REPLACE_VFPRINTF
-  fi
 ])
 
 AC_DEFUN([gl_REPLACE_VFPRINTF],



reply via email to

[Prev in Thread] Current Thread [Next in Thread]