summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2023-05-15 10:39:43 +0800
committerPo Lu <luangruo@yahoo.com>2023-05-15 10:40:34 +0800
commit5a3f009ad70d87366889e977d3b7d13f01b93e69 (patch)
tree28f084eb094292f6a5eb2d2d1ad6e919e3c12753 /lib
parenta46e231a5f27c46933cc53865cee452ad1a0c0d3 (diff)
downloademacs-5a3f009ad70d87366889e977d3b7d13f01b93e69.tar.gz
; Update from Gnulib
Diffstat (limited to 'lib')
-rw-r--r--lib/fseterr.h5
-rw-r--r--lib/gnulib.mk.in10
-rw-r--r--lib/isnand-nolibm.h5
-rw-r--r--lib/isnanf-nolibm.h5
-rw-r--r--lib/isnanl-nolibm.h5
-rw-r--r--lib/math.in.h14
-rw-r--r--lib/printf-args.c123
-rw-r--r--lib/printf-args.h59
-rw-r--r--lib/printf-parse.c497
-rw-r--r--lib/printf-parse.h8
-rw-r--r--lib/size_max.h5
-rw-r--r--lib/vasnprintf.c1512
-rw-r--r--lib/vasnprintf.h5
-rw-r--r--lib/xsize.h8
14 files changed, 1888 insertions, 373 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,14 +3544,399 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
}
#endif
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
+#if NEED_WPRINTF_DIRECTIVE_C && WIDE_CHAR_VERSION
+ else if (dp->conversion == 'c'
+ && a.arg[dp->arg_index].type != TYPE_WIDE_CHAR)
+ {
+ /* Implement the 'c' directive ourselves, in order to avoid
+ EILSEQ in the "C" locale. */
+ 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);
+ }
+ }
+
+ /* %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;
+
+ 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
+# if NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
|| a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
# endif
)
@@ -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