1
0
mirror of https://git.savannah.gnu.org/git/gnulib.git synced 2026-10-24 00:48:56 +03:00

vasnprintf: Work around two grouping bugs on many platforms.

* m4/printf.m4 (gl_PRINTF_FLAG_GROUPING_INT_PRECISION): New macro.
(gl_PRINTF_FLAG_GROUPING_MULTIBYTE): New macro.
* m4/fprintf-posix.m4 (gl_FUNC_FPRINTF_IS_POSIX): Require
gl_PRINTF_FLAG_GROUPING_INT_PRECISION,
gl_PRINTF_FLAG_GROUPING_MULTIBYTE. Test
gl_cv_func_printf_flag_grouping_int_precision,
gl_cv_func_printf_flag_grouping_multibyte.
* m4/dprintf-posix.m4 (gl_FUNC_DPRINTF_IS_POSIX): Likewise.
* m4/snprintf-posix.m4 (gl_FUNC_SNPRINTF_IS_POSIX): Likewise.
* m4/sprintf-posix.m4 (gl_FUNC_SPRINTF_IS_POSIX): Likewise.
* m4/vasnprintf-posix.m4 (gl_FUNC_VASNPRINTF_IS_POSIX): Likewise.
* m4/vasprintf-posix.m4 (gl_FUNC_VASPRINTF_IS_POSIX): Likewise.
* m4/vdprintf-posix.m4 (gl_FUNC_VDPRINTF_IS_POSIX): Likewise.
* m4/vfprintf-posix.m4 (gl_FUNC_VFPRINTF_IS_POSIX): Likewise.
* m4/vsnprintf-posix.m4 (gl_FUNC_VSNPRINTF_IS_POSIX): Likewise.
* m4/vsprintf-posix.m4 (gl_FUNC_VSPRINTF_IS_POSIX): Likewise.
* m4/obstack-printf-posix.m4 (gl_FUNC_OBSTACK_PRINTF_IS_POSIX):
Likewise.
* m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF_FLAG_GROUPING): Require
gl_PRINTF_FLAG_GROUPING_INT_PRECISION,
gl_PRINTF_FLAG_GROUPING_MULTIBYTE. Test
gl_cv_func_printf_flag_grouping_int_precision,
gl_cv_func_printf_flag_grouping_multibyte. Define the C macro
NEED_PRINTF_FLAG_GROUPING_INT.
* lib/vasnprintf.c (thousands_separator_char): New function.
(THOUSEP_CHAR_MAXLEN): New macro.
(thousands_separator_wchar): New function.
(THOUSEP_WCHAR_MAXLEN): New macro.
(MAX_ROOM_NEEDED): Improve the room estimate for FLAG_GROUP.
(VASNPRINTF): Add code for emitting thousands separators in the %f, %F,
%g, %G implementations and in the code relies the system's
sprintf/snprintf/swprintf function. Test NEED_PRINTF_FLAG_GROUPING and
NEED_PRINTF_FLAG_GROUPING_INT where needed.
* tests/test-vasnprintf-posix2.c (main): Add tests of the grouping flag.
* tests/test-vasnwprintf-posix2.c (main): Likewise.
* tests/test-vasnprintf-posix2.sh: Test in both French locales, not only
in one of them.
* tests/test-vasnwprintf-posix2.sh: Likewise.
* modules/vasnprintf-posix-tests (Depends-on): Add localeconv.
* modules/vasnwprintf-posix-tests (Depends-on): Likewise.
* doc/posix-functions/fprintf.texi: Mention the grouping bug with
precision on integers and the grouping bug with a multibyte thousands
separator.
* doc/posix-functions/vfprintf.texi: Likewise.
* doc/posix-functions/printf.texi: Likewise.
* doc/posix-functions/vprintf.texi: Likewise.
* doc/posix-functions/sprintf.texi: Likewise.
* doc/posix-functions/vsprintf.texi: Likewise.
* doc/posix-functions/snprintf.texi: Likewise.
* doc/posix-functions/vsnprintf.texi: Likewise.
* doc/posix-functions/dprintf.texi: Likewise.
* doc/posix-functions/vdprintf.texi: Likewise.
* doc/posix-functions/fwprintf.texi: Likewise.
* doc/posix-functions/vfwprintf.texi: Likewise.
* doc/posix-functions/wprintf.texi: Likewise.
* doc/posix-functions/vwprintf.texi: Likewise.
* doc/posix-functions/swprintf.texi: Likewise.
* doc/posix-functions/vswprintf.texi: Likewise.
* doc/posix-functions/asprintf.texi: Likewise.
* doc/posix-functions/vasprintf.texi: Likewise.
* doc/glibc-functions/obstack_printf.texi: Likewise.
* doc/glibc-functions/obstack_vprintf.texi: Likewise.
This commit is contained in:
Bruno Haible
2025-04-12 00:09:23 +02:00
parent aef99bf939
commit f7a63a906e
41 changed files with 1763 additions and 251 deletions

View File

@@ -1,3 +1,69 @@
2025-04-11 Bruno Haible <bruno@clisp.org>
vasnprintf: Work around two grouping bugs on many platforms.
* m4/printf.m4 (gl_PRINTF_FLAG_GROUPING_INT_PRECISION): New macro.
(gl_PRINTF_FLAG_GROUPING_MULTIBYTE): New macro.
* m4/fprintf-posix.m4 (gl_FUNC_FPRINTF_IS_POSIX): Require
gl_PRINTF_FLAG_GROUPING_INT_PRECISION,
gl_PRINTF_FLAG_GROUPING_MULTIBYTE. Test
gl_cv_func_printf_flag_grouping_int_precision,
gl_cv_func_printf_flag_grouping_multibyte.
* m4/dprintf-posix.m4 (gl_FUNC_DPRINTF_IS_POSIX): Likewise.
* m4/snprintf-posix.m4 (gl_FUNC_SNPRINTF_IS_POSIX): Likewise.
* m4/sprintf-posix.m4 (gl_FUNC_SPRINTF_IS_POSIX): Likewise.
* m4/vasnprintf-posix.m4 (gl_FUNC_VASNPRINTF_IS_POSIX): Likewise.
* m4/vasprintf-posix.m4 (gl_FUNC_VASPRINTF_IS_POSIX): Likewise.
* m4/vdprintf-posix.m4 (gl_FUNC_VDPRINTF_IS_POSIX): Likewise.
* m4/vfprintf-posix.m4 (gl_FUNC_VFPRINTF_IS_POSIX): Likewise.
* m4/vsnprintf-posix.m4 (gl_FUNC_VSNPRINTF_IS_POSIX): Likewise.
* m4/vsprintf-posix.m4 (gl_FUNC_VSPRINTF_IS_POSIX): Likewise.
* m4/obstack-printf-posix.m4 (gl_FUNC_OBSTACK_PRINTF_IS_POSIX):
Likewise.
* m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF_FLAG_GROUPING): Require
gl_PRINTF_FLAG_GROUPING_INT_PRECISION,
gl_PRINTF_FLAG_GROUPING_MULTIBYTE. Test
gl_cv_func_printf_flag_grouping_int_precision,
gl_cv_func_printf_flag_grouping_multibyte. Define the C macro
NEED_PRINTF_FLAG_GROUPING_INT.
* lib/vasnprintf.c (thousands_separator_char): New function.
(THOUSEP_CHAR_MAXLEN): New macro.
(thousands_separator_wchar): New function.
(THOUSEP_WCHAR_MAXLEN): New macro.
(MAX_ROOM_NEEDED): Improve the room estimate for FLAG_GROUP.
(VASNPRINTF): Add code for emitting thousands separators in the %f, %F,
%g, %G implementations and in the code relies the system's
sprintf/snprintf/swprintf function. Test NEED_PRINTF_FLAG_GROUPING and
NEED_PRINTF_FLAG_GROUPING_INT where needed.
* tests/test-vasnprintf-posix2.c (main): Add tests of the grouping flag.
* tests/test-vasnwprintf-posix2.c (main): Likewise.
* tests/test-vasnprintf-posix2.sh: Test in both French locales, not only
in one of them.
* tests/test-vasnwprintf-posix2.sh: Likewise.
* modules/vasnprintf-posix-tests (Depends-on): Add localeconv.
* modules/vasnwprintf-posix-tests (Depends-on): Likewise.
* doc/posix-functions/fprintf.texi: Mention the grouping bug with
precision on integers and the grouping bug with a multibyte thousands
separator.
* doc/posix-functions/vfprintf.texi: Likewise.
* doc/posix-functions/printf.texi: Likewise.
* doc/posix-functions/vprintf.texi: Likewise.
* doc/posix-functions/sprintf.texi: Likewise.
* doc/posix-functions/vsprintf.texi: Likewise.
* doc/posix-functions/snprintf.texi: Likewise.
* doc/posix-functions/vsnprintf.texi: Likewise.
* doc/posix-functions/dprintf.texi: Likewise.
* doc/posix-functions/vdprintf.texi: Likewise.
* doc/posix-functions/fwprintf.texi: Likewise.
* doc/posix-functions/vfwprintf.texi: Likewise.
* doc/posix-functions/wprintf.texi: Likewise.
* doc/posix-functions/vwprintf.texi: Likewise.
* doc/posix-functions/swprintf.texi: Likewise.
* doc/posix-functions/vswprintf.texi: Likewise.
* doc/posix-functions/asprintf.texi: Likewise.
* doc/posix-functions/vasprintf.texi: Likewise.
* doc/glibc-functions/obstack_printf.texi: Likewise.
* doc/glibc-functions/obstack_vprintf.texi: Likewise.
2025-04-11 Bruno Haible <bruno@clisp.org>
vasnprintf: Follow glibc's behaviour on glibc systems.

View File

@@ -42,6 +42,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, AIX 5.2, HP-UX 11,

View File

@@ -42,6 +42,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, AIX 5.2, HP-UX 11,

View File

@@ -71,6 +71,14 @@ NetBSD 3.0.
This function doesn't support the @code{'} flag on some platforms:
NetBSD 3.0, Cygwin 1.5.24.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not round the argument of the @samp{a} directive correctly
on some platforms:
macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, AIX 7.3, Solaris 11.4.

View File

@@ -28,6 +28,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
Solaris 11.4.

View File

@@ -58,6 +58,14 @@ NetBSD 3.0, mingw, MSVC 14.
This function doesn't support the @code{'} flag on some platforms:
NetBSD 3.0, Cygwin 1.5.24, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not round the argument of the @samp{a} directive correctly
on some platforms:
macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, AIX 7.3, Solaris 11.4.

View File

@@ -24,6 +24,14 @@ This function does not support size specifiers as in C23 (@code{w8},
@code{wf64}) on some platforms:
glibc 2.37, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5, AIX 7.3, Solaris 11.4, Cygwin 3.5.3, mingw, MSVC, Android 9.0.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{b} directive, required by ISO C23,
on some platforms:
glibc 2.34, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5,

View File

@@ -30,6 +30,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, AIX 5.2, HP-UX 11,

View File

@@ -43,6 +43,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, AIX 5.2, HP-UX 11,

View File

@@ -27,6 +27,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, AIX 5.2, HP-UX 11,

View File

@@ -60,6 +60,14 @@ characters on some platforms:
musl libc 1.2.3,
macOS 14, FreeBSD 13.1, NetBSD 10.0, OpenBSD 7.2, AIX 7.2, mingw.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{b} directive, required by ISO C23,
on some platforms:
glibc 2.34, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5,

View File

@@ -45,6 +45,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, Solaris 11.4, Cygwin 1.5.x.

View File

@@ -28,6 +28,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
Solaris 11.4.

View File

@@ -30,6 +30,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, AIX 5.2, HP-UX 11,

View File

@@ -24,6 +24,14 @@ This function does not support size specifiers as in C23 (@code{w8},
@code{wf64}) on some platforms:
glibc 2.37, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5, AIX 7.3, Solaris 11.4, Cygwin 3.5.3, mingw, MSVC, Android 9.0.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{b} directive, required by ISO C23,
on some platforms:
glibc 2.34, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5,

View File

@@ -30,6 +30,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, AIX 5.2, HP-UX 11,

View File

@@ -40,6 +40,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, AIX 5.2, HP-UX 11,

View File

@@ -27,6 +27,14 @@ printf @code{"%f"}, @code{"%e"}, @code{"%g"} of Infinity and NaN yields an
incorrect result on some platforms:
AIX 7.3, Solaris 11.4, mingw, MSVC 14.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{a} and @samp{A} directives on some
platforms:
FreeBSD 5.2.1, OpenBSD 4.0, AIX 5.2, HP-UX 11,

View File

@@ -26,6 +26,14 @@ This function does not support size specifiers as in C23 (@code{w8},
@code{wf64}) on some platforms:
glibc 2.37, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5, AIX 7.3, Solaris 11.4, Cygwin 3.5.3, mingw, MSVC, Android 9.0.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{b} directive, required by ISO C23,
on some platforms:
glibc 2.34, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5,

View File

@@ -27,6 +27,14 @@ This function does not support size specifiers as in C23 (@code{w8},
@code{wf64}) on some platforms:
glibc 2.37, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5, AIX 7.3, Solaris 11.4, Cygwin 3.5.3, mingw, MSVC, Android 9.0.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{b} directive, required by ISO C23,
on some platforms:
glibc 2.34, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5,

View File

@@ -27,6 +27,14 @@ This function does not support size specifiers as in C23 (@code{w8},
@code{wf64}) on some platforms:
glibc 2.37, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5, AIX 7.3, Solaris 11.4, Cygwin 3.5.3, mingw, MSVC, Android 9.0.
@item
This function doesn't support the @code{'} flag together with a precision
on an integer argument correctly on some platforms:
glibc 2.36, FreeBSD 14.0, NetBSD 10.0, Solaris 11, Cygwin 3.6.0, Haiku.
@item
This function doesn't support the @code{'} flag correctly in locales where
the thousands separator is a multibyte character on some platforms:
NetBSD 10.0, Solaris 11 OpenIndiana.
@item
This function does not support the @samp{b} directive, required by ISO C23,
on some platforms:
glibc 2.34, musl libc, macOS 14, FreeBSD 13.2, NetBSD 10.0, OpenBSD 7.5,

View File

@@ -88,7 +88,7 @@
#include <errno.h> /* errno */
#include <limits.h> /* CHAR_BIT, INT_MAX, INT_WIDTH, LONG_WIDTH */
#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP, LDBL_MANT_DIG */
#if HAVE_NL_LANGINFO
#if HAVE_NL_LANGINFO || __GLIBC__ >= 2 || defined __CYGWIN__
# include <langinfo.h>
#endif
#ifndef VASNPRINTF
@@ -371,7 +371,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 || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
#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) || (NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT)
/* Determine the decimal-point character according to the current locale. */
# ifndef decimal_point_char_defined
# define decimal_point_char_defined 1
@@ -398,6 +398,94 @@ decimal_point_char (void)
# endif
#endif
#if (!WIDE_CHAR_VERSION && (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE)) || ((!WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR) && (NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT))
/* Determine the thousands-separator character according to the current
locale.
It is a single multibyte character.
In glibc: 35x ".", 90x ",", 23x U+202F, 1x U+2019, 1x U+066C, on other
systems also U+00A0. */
# ifndef thousands_separator_char_defined
# define thousands_separator_char_defined 1
static const char *
thousands_separator_char (char stackbuf[10])
{
/* Determine it in a multithread-safe way. We know nl_langinfo is
multithread-safe on glibc systems, on Mac OS X systems, and on NetBSD,
but is not required to be multithread-safe by POSIX. sprintf(), however,
is multithread-safe. localeconv() is rarely multithread-safe. */
# if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__) || defined __NetBSD__)
return nl_langinfo (THOUSEP);
# elif 1
sprintf (stackbuf, "%'.0f", 1000.0);
/* Now stackbuf = "1<thousep>000". */
stackbuf[strlen (stackbuf) - 3] = '\0';
# if defined __sun
/* Solaris specific hack: Replace wrong result (0xC2 means U+00A0). */
if (strcmp (&stackbuf[1], "\302") == 0)
strcpy (&stackbuf[1], MB_CUR_MAX > 1 ? "\302\240" : "\240");
# endif
return &stackbuf[1];
# else
return localeconv () -> thousands_sep;
# endif
}
# endif
#endif
/* Maximum number of 'char' in the char[] representation of the thousands
separator. */
#define THOUSEP_CHAR_MAXLEN 3
#if WIDE_CHAR_VERSION && ((NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) || ((NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT) && DCHAR_IS_TCHAR))
/* Determine the thousands-separator character, as a wide character, according
to the current locale.
It is a single wide character. */
# ifndef thousands_separator_wchar_defined
# define thousands_separator_wchar_defined 1
static const wchar_t *
thousands_separator_wchar (wchar_t stackbuf[10])
{
# if __GLIBC__ >= 2 || defined __CYGWIN__
/* On glibc, in the unibyte locale fr_FR, the *wprintf routines use U+202F
as separator, which cannot be represented in the locale encoding. */
stackbuf[0] =
(wchar_t) (unsigned long) nl_langinfo (_NL_NUMERIC_THOUSANDS_SEP_WC);
stackbuf[1] = L'\0';
return stackbuf;
# elif defined __sun
/* Use sprintf, because swprintf retrieves a wrong value for the
thousands-separator wide character (e.g. (wchar_t) 0xffffffa0). */
char tmp[10];
sprintf (tmp, "%'.0f", 1000.0);
/* Now tmp = L"1<thousep>000". */
tmp[strlen (tmp) - 3] = '\0';
/* Solaris specific hack: Replace wrong result (0xC2 means U+00A0). */
if (strcmp (&tmp[1], "\302") == 0)
strcpy (&tmp[1], MB_CUR_MAX > 1 ? "\302\240" : "\240");
if (tmp[1] != '\0')
{
mbstate_t state;
mbszero (&state);
if ((int) mbrtowc (&stackbuf[0], &tmp[1], strlen (&tmp[1]), &state) > 0)
stackbuf[1] = L'\0';
else
stackbuf[0] = L'\0';
}
else
stackbuf[0] = L'\0';
return stackbuf;
# else
swprintf (stackbuf, 10, L"%'.0f", 1000.0);
/* Now stackbuf = L"1<thousep>000". */
stackbuf[local_wcslen (stackbuf) - 3] = '\0';
return &stackbuf[1];
# endif
}
# endif
#endif
/* Maximum number of 'wchar_t' in the wchar_t[] representation of the thousands
separator. */
#define THOUSEP_WCHAR_MAXLEN 1
#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE
/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
@@ -1852,8 +1940,15 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
}
if (tmp_length < precision)
tmp_length = precision;
/* Multiply by 2, as an estimate for FLAG_GROUP. */
tmp_length = xsum (tmp_length, tmp_length);
/* Account for thousands separators. */
if (flags & FLAG_GROUP)
{
# if WIDE_CHAR_VERSION
tmp_length = xsum (tmp_length, tmp_length / 3 * THOUSEP_WCHAR_MAXLEN);
# else
tmp_length = xsum (tmp_length, tmp_length / 3 * THOUSEP_CHAR_MAXLEN);
# endif
}
/* Add 1, to account for a leading sign. */
tmp_length = xsum (tmp_length, 1);
break;
@@ -4903,6 +4998,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
}
# endif
/* Account for thousands separators. */
if (flags & FLAG_GROUP)
{
# if WIDE_CHAR_VERSION
tmp_length = xsum (tmp_length, tmp_length / 3 * THOUSEP_WCHAR_MAXLEN);
# else
tmp_length = xsum (tmp_length, tmp_length / 3 * THOUSEP_CHAR_MAXLEN);
# endif
}
/* Account for sign, decimal point etc. */
tmp_length = xsum (tmp_length, 12);
@@ -4998,12 +5103,49 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
ndigits = strlen (digits);
if (ndigits > precision)
do
{
--ndigits;
*p++ = digits[ndigits];
}
while (ndigits > precision);
{
const DCHAR_T *thousep = NULL;
DCHAR_T thousep_buf[10];
# if !WIDE_CHAR_VERSION
size_t thousep_len;
# endif
if ((flags & FLAG_GROUP)
&& (ndigits - precision > 3))
{
/* Determine the thousands separator of the
current locale. */
# if WIDE_CHAR_VERSION
/* DCHAR_T is wchar_t. */
thousep = thousands_separator_wchar (thousep_buf);
# else
/* DCHAR_T is char. */
thousep = thousands_separator_char (thousep_buf);
thousep_len = strlen (thousep);
# endif
if (*thousep == 0)
thousep = NULL;
}
for (;;)
{
--ndigits;
*p++ = digits[ndigits];
if (ndigits == precision)
break;
if (thousep != NULL
/* implies (flags & FLAG_GROUP) */
&& ((ndigits - precision) % 3) == 0)
{
# if WIDE_CHAR_VERSION
*p++ = thousep[0];
# else
memcpy (p, thousep, thousep_len);
p += thousep_len;
# endif
}
}
}
else
*p++ = '0';
/* Here ndigits <= precision. */
@@ -5258,8 +5400,49 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
{
size_t ecount = exponent + 1;
/* Note: count <= precision = ndigits. */
for (; ecount > 0; ecount--)
*p++ = digits[--ndigits];
const DCHAR_T *thousep = NULL;
DCHAR_T thousep_buf[10];
# if !WIDE_CHAR_VERSION
size_t thousep_len;
# endif
if ((flags & FLAG_GROUP) && (ecount > 3))
{
/* Determine the thousands separator of the
current locale. */
# if WIDE_CHAR_VERSION
/* DCHAR_T is wchar_t. */
thousep = thousands_separator_wchar (thousep_buf);
# else
/* DCHAR_T is char. */
thousep = thousands_separator_char (thousep_buf);
thousep_len = strlen (thousep);
# endif
if (*thousep == 0)
thousep = NULL;
}
if (ecount > 0)
for (;;)
{
--ndigits;
*p++ = digits[ndigits];
if (--ecount == 0)
break;
if (thousep != NULL
/* implies (flags & FLAG_GROUP) */
&& (ecount % 3) == 0)
{
# if WIDE_CHAR_VERSION
*p++ = thousep[0];
# else
memcpy (p, thousep, thousep_len);
p += thousep_len;
# endif
}
}
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
@@ -5460,12 +5643,49 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
ndigits = strlen (digits);
if (ndigits > precision)
do
{
--ndigits;
*p++ = digits[ndigits];
}
while (ndigits > precision);
{
const DCHAR_T *thousep = NULL;
DCHAR_T thousep_buf[10];
# if !WIDE_CHAR_VERSION
size_t thousep_len;
# endif
if ((flags & FLAG_GROUP)
&& (ndigits - precision > 3))
{
/* Determine the thousands separator of the
current locale. */
# if WIDE_CHAR_VERSION
/* DCHAR_T is wchar_t. */
thousep = thousands_separator_wchar (thousep_buf);
# else
/* DCHAR_T is char. */
thousep = thousands_separator_char (thousep_buf);
thousep_len = strlen (thousep);
# endif
if (*thousep == 0)
thousep = NULL;
}
for (;;)
{
--ndigits;
*p++ = digits[ndigits];
if (ndigits == precision)
break;
if (thousep != NULL
/* implies (flags & FLAG_GROUP) */
&& ((ndigits - precision) % 3) == 0)
{
# if WIDE_CHAR_VERSION
*p++ = thousep[0];
# else
memcpy (p, thousep, thousep_len);
p += thousep_len;
# endif
}
}
}
else
*p++ = '0';
/* Here ndigits <= precision. */
@@ -5728,8 +5948,49 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
{
size_t ecount = exponent + 1;
/* Note: ecount <= precision = ndigits. */
for (; ecount > 0; ecount--)
*p++ = digits[--ndigits];
const DCHAR_T *thousep = NULL;
DCHAR_T thousep_buf[10];
# if !WIDE_CHAR_VERSION
size_t thousep_len;
# endif
if ((flags & FLAG_GROUP) && (ecount > 3))
{
/* Determine the thousands separator of the
current locale. */
# if WIDE_CHAR_VERSION
/* DCHAR_T is wchar_t. */
thousep = thousands_separator_wchar (thousep_buf);
# else
/* DCHAR_T is char. */
thousep = thousands_separator_char (thousep_buf);
thousep_len = strlen (thousep);
# endif
if (*thousep == 0)
thousep = NULL;
}
if (ecount > 0)
for (;;)
{
--ndigits;
*p++ = digits[ndigits];
if (--ecount == 0)
break;
if (thousep != NULL
/* implies (flags & FLAG_GROUP) */
&& (ecount % 3) == 0)
{
# if WIDE_CHAR_VERSION
*p++ = thousep[0];
# else
memcpy (p, thousep, thousep_len);
p += thousep_len;
# endif
}
}
if ((flags & FLAG_ALT) || ndigits > nzeroes)
{
*p++ = decimal_point_char ();
@@ -5937,13 +6198,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
{
arg_type type = a.arg[dp->arg_index].type;
int flags = dp->flags;
#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
int has_width;
#endif
#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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
#if !USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_FLAG_LEFTADJUST || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
size_t width;
#endif
#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_FLAG_ALT_PRECISION_ZERO || 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) || NEED_PRINTF_FLAG_LEFTADJUST || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
int has_precision;
size_t precision;
#endif
@@ -5952,9 +6213,14 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
#else
# define prec_ourselves 0
#endif
#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
int group_ourselves;
#else
# define group_ourselves 0
#endif
#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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
int pad_ourselves;
#else
# define pad_ourselves 0
@@ -5969,10 +6235,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
TCHAR_T *tmp;
#endif
#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
has_width = 0;
#endif
#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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
#if !USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_FLAG_LEFTADJUST || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
width = 0;
if (dp->width_start != dp->width_end)
{
@@ -6003,13 +6269,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
if (width > (size_t) INT_MAX)
goto overflow;
# define WIDTH_IS_CHECKED 1
# if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
has_width = 1;
# endif
}
#endif
#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_FLAG_ALT_PRECISION_ZERO || 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) || NEED_PRINTF_FLAG_LEFTADJUST || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
has_precision = 0;
precision = 6;
if (dp->precision_start != dp->precision_end)
@@ -6074,8 +6340,37 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
#endif
/* Decide whether to add the thousands separators ourselves. */
#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
if (flags & FLAG_GROUP)
{
switch (dp->conversion)
{
case 'd': case 'i': case 'u':
# if NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
group_ourselves = 1;
# else
group_ourselves = prec_ourselves;
# endif
break;
case 'f': case 'F': case 'g': case 'G':
# if NEED_PRINTF_FLAG_GROUPING
group_ourselves = 1;
# else
group_ourselves = prec_ourselves;
# endif
break;
default:
group_ourselves = 0;
break;
}
}
else
group_ourselves = 0;
#endif
/* Decide whether to perform the padding ourselves. */
#if !((WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST) && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT)
switch (dp->conversion)
{
# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
@@ -6092,7 +6387,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
pad_ourselves = 1;
break;
default:
pad_ourselves = prec_ourselves;
pad_ourselves = prec_ourselves | group_ourselves;
break;
}
#endif
@@ -6125,14 +6420,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
sprintf. */
fbp = buf;
*fbp++ = '%';
#if NEED_PRINTF_FLAG_GROUPING
/* The underlying implementation doesn't support the ' flag.
Produce no grouping characters in this case; this is
acceptable because the grouping is locale dependent. */
#else
if (flags & FLAG_GROUP)
if ((flags & FLAG_GROUP) && !group_ourselves)
*fbp++ = '\'';
#endif
if (flags & FLAG_LEFT)
*fbp++ = '-';
if (flags & FLAG_SHOWSIGN)
@@ -6947,6 +7236,124 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
#endif
#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
if (group_ourselves) /* implies (flags & FLAG_GROUP) */
/* Handle the grouping. */
switch (dp->conversion)
{
/* These are the only conversion to which grouping
applies. */
case 'd': case 'i': case 'u':
case 'f': case 'F': case 'g': case 'G':
{
/* Determine the thousands separator of the current
locale. */
const TCHAR_T *thousep;
TCHAR_T thousep_buf[10];
# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
/* TCHAR_T is wchar_t. */
thousep = thousands_separator_wchar (thousep_buf);
# else
/* TCHAR_T is char. */
thousep = thousands_separator_char (thousep_buf);
# endif
/* Nothing to do in locales where thousep is the empty
string. */
if (*thousep != 0)
{
/* Since FLAG_LOCALIZED is only supported on glibc
systems, here we can assume that all digits are
the ASCII digits '0'..'9'. */
TCHAR_T *number_ptr =
# if USE_SNPRINTF
(TCHAR_T *) (result + length);
# else
tmp;
# endif
TCHAR_T *end_ptr = number_ptr + count;
/* Find where the leading digits start. */
TCHAR_T *digits_ptr = number_ptr;
if (count >= 1
&& (*digits_ptr == '-' || *digits_ptr == '+'
|| *digits_ptr == ' '))
digits_ptr++;
/* Find where the leading digits end. */
TCHAR_T *digits_end_ptr;
switch (dp->conversion)
{
case 'd': case 'i': case 'u':
digits_end_ptr = end_ptr;
break;
case 'f': case 'F': case 'g': case 'G':
{
TCHAR_T decimal_point = decimal_point_char ();
for (digits_end_ptr = digits_ptr;
digits_end_ptr < end_ptr;
digits_end_ptr++)
if (*digits_end_ptr == decimal_point
|| *digits_end_ptr == 'e')
break;
}
break;
}
/* Determine the number of thousands separators
to insert. */
size_t insert = digits_end_ptr - digits_ptr;
insert = (insert > 0 ? (insert - 1) / 3 : 0);
if (insert > 0)
{
# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
# define thousep_len 1
# else
size_t thousep_len = strlen (thousep);
# endif
# if USE_SNPRINTF
size_t digits_offset = digits_ptr - number_ptr;
size_t digits_end_offset = digits_end_ptr - number_ptr;
size_t n =
xsum (length,
(count + insert * thousep_len + TCHARS_PER_DCHAR - 1)
/ TCHARS_PER_DCHAR);
length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
ENSURE_ALLOCATION (n);
length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
number_ptr = (TCHAR_T *) (result + length);
end_ptr = number_ptr + count;
digits_ptr = number_ptr + digits_offset;
digits_end_ptr = number_ptr + digits_end_offset;
# endif
count += insert * thousep_len;
const TCHAR_T *p = end_ptr;
TCHAR_T *q = end_ptr + insert * thousep_len;
while (p > digits_end_ptr)
*--q = *--p;
for (; insert > 0; insert--)
{
*--q = *--p;
*--q = *--p;
*--q = *--p;
# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
*--q = *thousep;
# else
q -= thousep_len;
memcpy (q, thousep, thousep_len);
# endif
}
/* Here q == p. Done with the insertions. */
}
}
}
break;
}
#endif
#if !USE_SNPRINTF
if (count >= tmp_length)
/* tmp_length was incorrectly calculated - fix the
@@ -6957,6 +7364,7 @@ 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'
|| (flags & FLAG_GROUP)
# if __GLIBC__ >= 2 && !defined __UCLIBC__
|| (flags & FLAG_LOCALIZED)
# endif
@@ -7098,7 +7506,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
/* Here count <= allocated - length. */
/* Perform padding. */
#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
if (pad_ourselves && has_width)
{
size_t w;

View File

@@ -1,5 +1,5 @@
# dprintf-posix.m4
# serial 10
# serial 11
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,6 +33,8 @@ AC_DEFUN([gl_FUNC_DPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -67,19 +69,27 @@ AC_DEFUN([gl_FUNC_DPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
# dprintf exists and is
# already POSIX compliant.
gl_cv_func_dprintf_posix=yes
case "$gl_cv_func_printf_precision" in
*yes)
case "$gl_cv_func_printf_enomem" in
*yes)
# dprintf exists and is
# already POSIX compliant.
gl_cv_func_dprintf_posix=yes
;;
esac
;;
esac
;;
esac
;;

View File

@@ -1,5 +1,5 @@
# fprintf-posix.m4
# serial 21
# serial 22
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,6 +33,8 @@ AC_DEFUN([gl_FUNC_FPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -65,19 +67,27 @@ AC_DEFUN([gl_FUNC_FPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
# fprintf exists and is
# already POSIX compliant.
gl_cv_func_fprintf_posix=yes
case "$gl_cv_func_printf_precision" in
*yes)
case "$gl_cv_func_printf_enomem" in
*yes)
# fprintf exists and is
# already POSIX compliant.
gl_cv_func_fprintf_posix=yes
;;
esac
;;
esac
;;
esac
;;

View File

@@ -1,5 +1,5 @@
# obstack-printf-posix.m4
# serial 11
# serial 12
dnl Copyright (C) 2008-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -37,6 +37,8 @@ AC_DEFUN([gl_FUNC_OBSTACK_PRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -71,19 +73,27 @@ AC_DEFUN([gl_FUNC_OBSTACK_PRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
# obstack_printf exists and is
# already POSIX compliant.
gl_cv_func_obstack_printf_posix=yes
case "$gl_cv_func_printf_precision" in
*yes)
case "$gl_cv_func_printf_enomem" in
*yes)
# obstack_printf exists and is
# already POSIX compliant.
gl_cv_func_obstack_printf_posix=yes
;;
esac
;;
esac
;;
esac
;;

View File

@@ -1,5 +1,5 @@
# printf.m4
# serial 95
# serial 96
dnl Copyright (C) 2003, 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -1186,6 +1186,112 @@ changequote([,])dnl
])
])
dnl Test whether the *printf family of functions supports POSIX/XSI format
dnl strings with the ' flag for grouping of decimal digits on integers,
dnl together with a precision.
dnl Result is gl_cv_func_printf_flag_grouping_int_precision.
AC_DEFUN([gl_PRINTF_FLAG_GROUPING_INT_PRECISION],
[
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_HOST])
AC_CACHE_CHECK([whether printf supports grouping on integers with a precision],
[gl_cv_func_printf_flag_grouping_int_precision],
[
dnl Prepare a guess, used when cross-compiling or when specific locales
dnl are not available.
case "$host_os" in
# Guess no on FreeBSD, NetBSD, Solaris, Cygwin, Haiku.
freebsd* | dragonfly* | netbsd* | solaris* | cygwin* | haiku*)
gl_cv_func_printf_flag_grouping_int_precision="guessing no";;
*)
gl_cv_func_printf_flag_grouping_int_precision="guessing yes";;
esac
AC_RUN_IFELSE(
[AC_LANG_SOURCE([[
#include <locale.h>
#include <stdio.h>
#include <string.h>
static char buf[100];
int main ()
{
if (setlocale (LC_ALL, "fr_FR.UTF-8") != NULL
|| setlocale (LC_ALL, "fr_FR") != NULL
|| setlocale (LC_ALL, "fr_FR.ISO-8859-1") != NULL
|| setlocale (LC_ALL, "fr_FR.ISO8859-1") != NULL)
{
if (sprintf (buf, "%'.10d", 1000) < 0)
return 1;
if (strlen (buf) == 10 && strcmp (buf, "0000001000") != 0)
/* The sprintf implementation has produced fewer than 10 digits. */
return 2;
else
return 0;
}
return 3;
}]])],
[gl_cv_func_printf_flag_grouping_int_precision=yes],
[if test $? = 2; then
gl_cv_func_printf_flag_grouping_int_precision=no
fi
],
[:])
])
])
dnl Test whether the *printf family of functions supports POSIX/XSI format
dnl strings with the ' flag for grouping of decimal digits, when the thousands
dnl separator is a multibyte character (such as U+00A0 or U+202F in a UTF-8
dnl locale).
dnl Result is gl_cv_func_printf_flag_grouping_multibyte.
AC_DEFUN([gl_PRINTF_FLAG_GROUPING_MULTIBYTE],
[
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_HOST])
AC_CACHE_CHECK([whether printf supports grouping with a multibyte separator],
[gl_cv_func_printf_flag_grouping_multibyte],
[
dnl Prepare a guess, used when cross-compiling or when specific locales
dnl are not available.
case "$host_os" in
# Guess no on NetBSD and Solaris 11 OpenIndiana.
netbsd* | solaris*)
gl_cv_func_printf_flag_grouping_multibyte="guessing no";;
*)
gl_cv_func_printf_flag_grouping_multibyte="guessing yes";;
esac
AC_RUN_IFELSE(
[AC_LANG_SOURCE([[
#include <locale.h>
#include <stdio.h>
#include <string.h>
static char buf[100];
int main ()
{
if (setlocale (LC_ALL, "fr_FR.UTF-8") == NULL)
return 0;
if (sprintf (buf, "%'.0f", 1000.0) < 0)
return 1;
if (strlen (localeconv ()->thousands_sep) > 1)
{
if (strlen (buf) <= 4 + 1)
return 2;
else
return 3;
}
return 0;
}]])],
[:],
[case $? in
2) gl_cv_func_printf_flag_grouping_multibyte=no ;;
3) gl_cv_func_printf_flag_grouping_multibyte=yes ;;
esac
],
[:])
])
])
dnl Test whether the *printf family of functions supports the - flag correctly.
dnl (ISO C99.) See
dnl <https://lists.gnu.org/r/bug-coreutils/2008-02/msg00035.html>
@@ -2161,20 +2267,22 @@ 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_FLAG_ALT_PRECISION_ZERO
dnl 18 = gl_PRINTF_PRECISION
dnl 19 = gl_PRINTF_ENOMEM
dnl 20 = gl_SNPRINTF_PRESENCE
dnl 21 = gl_SNPRINTF_TRUNCATION_C99
dnl 22 = gl_SNPRINTF_RETVAL_C99
dnl 23 = gl_SNPRINTF_DIRECTIVE_N
dnl 24 = gl_SNPRINTF_SIZE1
dnl 25 = gl_VSNPRINTF_ZEROSIZE_C99
dnl 26 = gl_SWPRINTF_WORKS
dnl 27 = gl_SWPRINTF_DIRECTIVE_LA
dnl 28 = gl_SWPRINTF_DIRECTIVE_LC
dnl 15 = gl_PRINTF_FLAG_GROUPING_INT_PRECISION
dnl 16 = gl_PRINTF_FLAG_GROUPING_MULTIBYTE
dnl 17 = gl_PRINTF_FLAG_LEFTADJUST
dnl 18 = gl_PRINTF_FLAG_ZERO
dnl 19 = gl_PRINTF_FLAG_ALT_PRECISION_ZERO
dnl 20 = gl_PRINTF_PRECISION
dnl 21 = gl_PRINTF_ENOMEM
dnl 22 = gl_SNPRINTF_PRESENCE
dnl 23 = gl_SNPRINTF_TRUNCATION_C99
dnl 24 = gl_SNPRINTF_RETVAL_C99
dnl 25 = gl_SNPRINTF_DIRECTIVE_N
dnl 26 = gl_SNPRINTF_SIZE1
dnl 27 = gl_VSNPRINTF_ZEROSIZE_C99
dnl 28 = gl_SWPRINTF_WORKS
dnl 29 = gl_SWPRINTF_DIRECTIVE_LA
dnl 30 = gl_SWPRINTF_DIRECTIVE_LC
dnl
dnl 1 = checking whether printf supports size specifiers as in C99...
dnl 2 = checking whether printf supports size specifiers as in C23...
@@ -2190,62 +2298,64 @@ 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 the alternative flag with a zero precision...
dnl 18 = checking whether printf supports large precisions...
dnl 19 = checking whether printf survives out-of-memory conditions...
dnl 20 = checking for snprintf...
dnl 21 = checking whether snprintf truncates the result as in C99...
dnl 22 = checking whether snprintf returns a byte count as in C99...
dnl 23 = checking whether snprintf fully supports the 'n' directive...
dnl 24 = checking whether snprintf respects a size of 1...
dnl 25 = checking whether vsnprintf respects a zero size as in C99...
dnl 26 = checking whether swprintf works...
dnl 27 = checking whether swprintf supports the 'La' and 'LA' directives...
dnl 28 = checking whether swprintf supports the 'lc' directive...
dnl 15 = checking whether printf supports grouping on integers with a precision...
dnl 16 = checking whether printf supports grouping with a multibyte separator...
dnl 17 = checking whether printf supports the left-adjust flag correctly...
dnl 18 = checking whether printf supports the zero flag correctly...
dnl 19 = checking whether printf supports the alternative flag with a zero precision...
dnl 20 = checking whether printf supports large precisions...
dnl 21 = checking whether printf survives out-of-memory conditions...
dnl 22 = checking for snprintf...
dnl 23 = checking whether snprintf truncates the result as in C99...
dnl 24 = checking whether snprintf returns a byte count as in C99...
dnl 25 = checking whether snprintf fully supports the 'n' directive...
dnl 26 = checking whether snprintf respects a size of 1...
dnl 27 = checking whether vsnprintf respects a zero size as in C99...
dnl 28 = checking whether swprintf works...
dnl 29 = checking whether swprintf supports the 'La' and 'LA' directives...
dnl 30 = checking whether swprintf supports the 'lc' directive...
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 21 22 23 24 25 26 27 28
dnl musl libc 1.2.3 . # . . . . # # . . . # . . . . ? . . . . . . . . # . #
dnl glibc 2.35 . # . . . . . . . . . . . . . . . . . . . . . . . . . .
dnl glibc 2.5 . # . . . . # # . . . . . . . . . . . . . . . . . . # .
dnl glibc 2.3.6 . # . . . # # # . . . . . . . . . . . . . . . . . . # .
dnl FreeBSD 14.0 . . . . . # . . . . . . . . . . . . # . . . . . . # . #
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 27 28 29 30
dnl musl libc 1.2.3 . # . . . . # # . . . # . . . . . . . . . . . . . . . # . #
dnl glibc 2.35 . # . . . . . . . . . . . . # . . . . . . . . . . . . . . .
dnl glibc 2.5 . # . . . . # # . . . . . . # . . . . . . . . . . . . . # .
dnl glibc 2.3.6 . # . . . # # # . . . . . . . . . . . . . . . . . . . . # .
dnl FreeBSD 14.0 . . . . . # . . . . . . . . # . . . . . # . . . . . . # . #
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 # # # # # # # # # . . ? # # ? ? . # ? # ? . # # # . . # ? ?

View File

@@ -1,5 +1,5 @@
# snprintf-posix.m4
# serial 22
# serial 23
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,6 +33,8 @@ AC_DEFUN([gl_FUNC_SNPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -72,29 +74,37 @@ AC_DEFUN([gl_FUNC_SNPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
case "$gl_cv_func_snprintf_truncation_c99" in
case "$gl_cv_func_printf_precision" in
*yes)
case "$gl_cv_func_snprintf_retval_c99" in
case "$gl_cv_func_printf_enomem" in
*yes)
case m4_ifdef([gl_PRINTF_SUPPORT_N_DIRECTIVE],["$gl_cv_func_snprintf_directive_n"],["yes"]) in
case "$gl_cv_func_snprintf_truncation_c99" in
*yes)
case "$gl_cv_func_snprintf_size1" in
case "$gl_cv_func_snprintf_retval_c99" in
*yes)
case "$gl_cv_func_vsnprintf_zerosize_c99" in
case m4_ifdef([gl_PRINTF_SUPPORT_N_DIRECTIVE],["$gl_cv_func_snprintf_directive_n"],["yes"]) in
*yes)
# snprintf exists and is
# already POSIX compliant.
gl_cv_func_snprintf_posix=yes
case "$gl_cv_func_snprintf_size1" in
*yes)
case "$gl_cv_func_vsnprintf_zerosize_c99" in
*yes)
# snprintf exists and is
# already POSIX compliant.
gl_cv_func_snprintf_posix=yes
;;
esac
;;
esac
;;
esac
;;

View File

@@ -1,5 +1,5 @@
# sprintf-posix.m4
# serial 19
# serial 20
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,6 +33,8 @@ AC_DEFUN([gl_FUNC_SPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -65,19 +67,27 @@ AC_DEFUN([gl_FUNC_SPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
# sprintf exists and is
# already POSIX compliant.
gl_cv_func_sprintf_posix=yes
case "$gl_cv_func_printf_precision" in
*yes)
case "$gl_cv_func_printf_enomem" in
*yes)
# sprintf exists and is
# already POSIX compliant.
gl_cv_func_sprintf_posix=yes
;;
esac
;;
esac
;;
esac
;;

View File

@@ -1,5 +1,5 @@
# vasnprintf-posix.m4
# serial 20
# serial 21
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -32,6 +32,8 @@ AC_DEFUN_ONCE([gl_FUNC_VASNPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -65,21 +67,29 @@ AC_DEFUN_ONCE([gl_FUNC_VASNPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
if test $ac_cv_func_vasnprintf = yes; then
# vasnprintf exists and is
# already POSIX compliant.
gl_cv_func_vasnprintf_posix=yes
fi
case "$gl_cv_func_printf_precision" in
*yes)
case "$gl_cv_func_printf_enomem" in
*yes)
if test $ac_cv_func_vasnprintf = yes; then
# vasnprintf exists and is
# already POSIX compliant.
gl_cv_func_vasnprintf_posix=yes
fi
;;
esac
;;
esac
;;
esac
;;

View File

@@ -1,5 +1,5 @@
# vasnprintf.m4
# serial 54
# serial 55
dnl Copyright (C) 2002-2004, 2006-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -358,8 +358,19 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_LC],
AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_GROUPING],
[
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
case "$gl_cv_func_printf_flag_grouping" in
*yes)
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
case "$gl_cv_func_printf_flag_grouping,$gl_cv_func_printf_flag_grouping_multibyte" in
*yes,*yes)
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
;;
*)
AC_DEFINE([NEED_PRINTF_FLAG_GROUPING_INT], [1],
[Define if the vasnprintf implementation needs special code for the
' flag, for integer directives only.])
;;
esac
;;
*)
AC_DEFINE([NEED_PRINTF_FLAG_GROUPING], [1],

View File

@@ -1,5 +1,5 @@
# vasprintf-posix.m4
# serial 20
# serial 21
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,6 +33,8 @@ AC_DEFUN([gl_FUNC_VASPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -66,21 +68,29 @@ AC_DEFUN([gl_FUNC_VASPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" 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_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
;;

View File

@@ -1,5 +1,5 @@
# vdprintf-posix.m4
# serial 10
# serial 11
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,6 +33,8 @@ AC_DEFUN([gl_FUNC_VDPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -67,19 +69,27 @@ AC_DEFUN([gl_FUNC_VDPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
# vdprintf exists and is
# already POSIX compliant.
gl_cv_func_vdprintf_posix=yes
case "$gl_cv_func_printf_precision" in
*yes)
case "$gl_cv_func_printf_enomem" in
*yes)
# vdprintf exists and is
# already POSIX compliant.
gl_cv_func_vdprintf_posix=yes
;;
esac
;;
esac
;;
esac
;;

View File

@@ -1,5 +1,5 @@
# vfprintf-posix.m4
# serial 21
# serial 22
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,6 +33,8 @@ AC_DEFUN([gl_FUNC_VFPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -65,19 +67,27 @@ AC_DEFUN([gl_FUNC_VFPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
# vfprintf exists and is
# already POSIX compliant.
gl_cv_func_vfprintf_posix=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
;;

View File

@@ -1,5 +1,5 @@
# vsnprintf-posix.m4
# serial 23
# serial 24
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,6 +33,8 @@ AC_DEFUN([gl_FUNC_VSNPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -73,29 +75,37 @@ AC_DEFUN([gl_FUNC_VSNPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
case "$gl_cv_func_snprintf_truncation_c99" in
case "$gl_cv_func_printf_precision" in
*yes)
case "$gl_cv_func_snprintf_retval_c99" in
case "$gl_cv_func_printf_enomem" in
*yes)
case m4_ifdef([gl_PRINTF_SUPPORT_N_DIRECTIVE],["$gl_cv_func_snprintf_directive_n"],["yes"]) in
case "$gl_cv_func_snprintf_truncation_c99" in
*yes)
case "$gl_cv_func_snprintf_size1" in
case "$gl_cv_func_snprintf_retval_c99" in
*yes)
case "$gl_cv_func_vsnprintf_zerosize_c99" in
case m4_ifdef([gl_PRINTF_SUPPORT_N_DIRECTIVE],["$gl_cv_func_snprintf_directive_n"],["yes"]) in
*yes)
# vsnprintf exists and is
# already POSIX compliant.
gl_cv_func_vsnprintf_posix=yes
case "$gl_cv_func_snprintf_size1" in
*yes)
case "$gl_cv_func_vsnprintf_zerosize_c99" in
*yes)
# vsnprintf exists and is
# already POSIX compliant.
gl_cv_func_vsnprintf_posix=yes
;;
esac
;;
esac
;;
esac
;;

View File

@@ -1,5 +1,5 @@
# vsprintf-posix.m4
# serial 19
# serial 20
dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,6 +33,8 @@ AC_DEFUN([gl_FUNC_VSPRINTF_IS_POSIX],
AC_REQUIRE([gl_PRINTF_DIRECTIVE_LC])
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_INT_PRECISION])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING_MULTIBYTE])
AC_REQUIRE([gl_PRINTF_FLAG_LEFTADJUST])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
AC_REQUIRE([gl_PRINTF_FLAG_ALT_PRECISION_ZERO])
@@ -65,19 +67,27 @@ AC_DEFUN([gl_FUNC_VSPRINTF_IS_POSIX],
*yes)
case "$gl_cv_func_printf_flag_grouping" in
*yes)
case "$gl_cv_func_printf_flag_leftadjust" in
case "$gl_cv_func_printf_flag_grouping_int_precision" in
*yes)
case "$gl_cv_func_printf_flag_zero" in
case "$gl_cv_func_printf_flag_grouping_multibyte" in
*yes)
case "$gl_cv_func_printf_flag_alt_precision_zero" in
case "$gl_cv_func_printf_flag_leftadjust" in
*yes)
case "$gl_cv_func_printf_precision" in
case "$gl_cv_func_printf_flag_zero" in
*yes)
case "$gl_cv_func_printf_enomem" in
case "$gl_cv_func_printf_flag_alt_precision_zero" in
*yes)
# vsprintf exists and is
# already POSIX compliant.
gl_cv_func_vsprintf_posix=yes
case "$gl_cv_func_printf_precision" in
*yes)
case "$gl_cv_func_printf_enomem" in
*yes)
# vsprintf exists and is
# already POSIX compliant.
gl_cv_func_vsprintf_posix=yes
;;
esac
;;
esac
;;
esac
;;

View File

@@ -16,6 +16,7 @@ float-h
nan
snan
setlocale
localeconv
configure.ac:
AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE])

View File

@@ -17,6 +17,7 @@ float-h
nan
snan
setlocale
localeconv
wcscmp
wcsspn
wmemcmp

View File

@@ -59,5 +59,375 @@ main (int argc, char *argv[])
free (result);
}
/* Test that a locale dependent grouping separator is used correctly. */
{
const char *separator =
localeconv ()->thousands_sep; /* = nl_langinfo (THOUSEP) */
size_t separator_len = strlen (separator);
/* Tests of %d directive with grouping separator. */
{
size_t length;
char *result = asnprintf (NULL, &length, "%'d", 1000);
ASSERT (result != NULL);
ASSERT (length == 4 + separator_len);
ASSERT (memcmp (result, "1", 1) == 0
&& memcmp (result + 1, separator, separator_len) == 0
&& strcmp (result + 1 + separator_len, "000") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'d", -1000);
ASSERT (result != NULL);
ASSERT (length == 5 + separator_len);
ASSERT (memcmp (result, "-1", 2) == 0
&& memcmp (result + 2, separator, separator_len) == 0
&& strcmp (result + 2 + separator_len, "000") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'d", -142857);
ASSERT (result != NULL);
ASSERT (length == 7 + separator_len);
ASSERT (memcmp (result, "-142", 4) == 0
&& memcmp (result + 4, separator, separator_len) == 0
&& strcmp (result + 4 + separator_len, "857") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'d", 2147483647);
ASSERT (result != NULL);
ASSERT (length == 10 + 3 * separator_len);
ASSERT (memcmp (result, "2", 1) == 0
&& memcmp (result + 1, separator, separator_len) == 0
&& memcmp (result + 1 + separator_len, "147", 3) == 0
&& memcmp (result + 4 + separator_len, separator, separator_len) == 0
&& memcmp (result + 4 + 2 * separator_len, "483", 3) == 0
&& memcmp (result + 7 + 2 * separator_len, separator, separator_len) == 0
&& strcmp (result + 7 + 3 * separator_len, "647") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'d", -2147483647);
ASSERT (result != NULL);
ASSERT (length == 11 + 3 * separator_len);
ASSERT (memcmp (result, "-2", 2) == 0
&& memcmp (result + 2, separator, separator_len) == 0
&& memcmp (result + 2 + separator_len, "147", 3) == 0
&& memcmp (result + 5 + separator_len, separator, separator_len) == 0
&& memcmp (result + 5 + 2 * separator_len, "483", 3) == 0
&& memcmp (result + 8 + 2 * separator_len, separator, separator_len) == 0
&& strcmp (result + 8 + 3 * separator_len, "647") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'.10d", 1000);
ASSERT (result != NULL);
if (length == 10 + separator_len)
{
/* Most implementations don't add the grouping character within the
leading zeroes. */
ASSERT (length == 10 + separator_len);
ASSERT (memcmp (result, "0000001", 7) == 0
&& memcmp (result + 7, separator, separator_len) == 0
&& strcmp (result + 7 + separator_len, "000") == 0);
}
else
{
/* But there are good arguments for adding the grouping character
within the leading zeroes.
<https://sourceware.org/bugzilla/show_bug.cgi?id=23432> */
ASSERT (length == 10 + 3 * separator_len);
ASSERT (memcmp (result, "0", 1) == 0
&& memcmp (result + 1, separator, separator_len) == 0
&& memcmp (result + 1 + separator_len, "000", 3) == 0
&& memcmp (result + 4 + separator_len, separator, separator_len) == 0
&& memcmp (result + 4 + 2 * separator_len, "001", 3) == 0
&& memcmp (result + 7 + 2 * separator_len, separator, separator_len) == 0
&& strcmp (result + 7 + 3 * separator_len, "000") == 0);
}
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'.10d", -1000);
ASSERT (result != NULL);
if (length == 11 + separator_len)
{
/* Most implementations don't add the grouping character within the
leading zeroes. */
ASSERT (length == 11 + separator_len);
ASSERT (memcmp (result, "-0000001", 8) == 0
&& memcmp (result + 8, separator, separator_len) == 0
&& strcmp (result + 8 + separator_len, "000") == 0);
}
else
{
/* But there are good arguments for adding the grouping character
within the leading zeroes.
<https://sourceware.org/bugzilla/show_bug.cgi?id=23432> */
ASSERT (length == 11 + 3 * separator_len);
ASSERT (memcmp (result, "-0", 2) == 0
&& memcmp (result + 2, separator, separator_len) == 0
&& memcmp (result + 2 + separator_len, "000", 3) == 0
&& memcmp (result + 5 + separator_len, separator, separator_len) == 0
&& memcmp (result + 5 + 2 * separator_len, "001", 3) == 0
&& memcmp (result + 8 + 2 * separator_len, separator, separator_len) == 0
&& strcmp (result + 8 + 3 * separator_len, "000") == 0);
}
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'10d", 1000);
ASSERT (result != NULL);
if (separator_len > 0)
{
if (length == 10)
{
/* Result according to POSIX, which says that the width is
measured in "bytes".
<https://pubs.opengroup.org/onlinepubs/9799919799/functions/fprintf.html>
<https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap05.html#tag_05> */
ASSERT (length == 10);
ASSERT (memcmp (result, " 1" + separator_len, 7 - separator_len) == 0
&& memcmp (result + 7 - separator_len, separator, separator_len) == 0
&& strcmp (result + 7, "000") == 0);
}
else
{
/* Result according to glibc, which measures the width in
multibyte characters or column positions.
<https://sourceware.org/bugzilla/show_bug.cgi?id=28943>
<https://sourceware.org/bugzilla/show_bug.cgi?id=30883>
<https://sourceware.org/bugzilla/show_bug.cgi?id=31542> */
ASSERT (length == 9 + separator_len);
ASSERT (memcmp (result, " 1", 6) == 0
&& memcmp (result + 6, separator, separator_len) == 0
&& strcmp (result + 6 + separator_len, "000") == 0);
}
}
else
{
ASSERT (length == 10);
ASSERT (strcmp (result, " 1000") == 0);
}
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'10d", -1000);
ASSERT (result != NULL);
if (separator_len > 0)
{
if (length == 10)
{
/* Result according to POSIX, which says that the width is
measured in "bytes".
<https://pubs.opengroup.org/onlinepubs/9799919799/functions/fprintf.html>
<https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap05.html#tag_05> */
ASSERT (length == 10);
ASSERT (memcmp (result, " -1" + separator_len, 7 - separator_len) == 0
&& memcmp (result + 7 - separator_len, separator, separator_len) == 0
&& strcmp (result + 7, "000") == 0);
}
else
{
/* Result according to glibc, which measures the width in
multibyte characters or column positions.
<https://sourceware.org/bugzilla/show_bug.cgi?id=28943>
<https://sourceware.org/bugzilla/show_bug.cgi?id=30883>
<https://sourceware.org/bugzilla/show_bug.cgi?id=31542> */
ASSERT (length == 9 + separator_len);
ASSERT (memcmp (result, " -1", 6) == 0
&& memcmp (result + 6, separator, separator_len) == 0
&& strcmp (result + 6 + separator_len, "000") == 0);
}
}
else
{
ASSERT (length == 10);
ASSERT (strcmp (result, " -1000") == 0);
}
free (result);
}
/* Tests of %f directive with grouping separator. */
{
size_t length;
char *result = asnprintf (NULL, &length, "%'.0f", 1000.0);
ASSERT (result != NULL);
ASSERT (length == 4 + separator_len);
ASSERT (memcmp (result, "1", 1) == 0
&& memcmp (result + 1, separator, separator_len) == 0
&& strcmp (result + 1 + separator_len, "000") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'.5f", 3141592653.5897932386);
ASSERT (result != NULL);
ASSERT (length == 16 + 3 * separator_len);
ASSERT (memcmp (result, "3", 1) == 0
&& memcmp (result + 1, separator, separator_len) == 0
&& memcmp (result + 1 + separator_len, "141", 3) == 0
&& memcmp (result + 4 + separator_len, separator, separator_len) == 0
&& memcmp (result + 4 + 2 * separator_len, "592", 3) == 0
&& memcmp (result + 7 + 2 * separator_len, separator, separator_len) == 0
&& strcmp (result + 7 + 3 * separator_len, "653,58979") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'.5f", -3141592653.5897932386);
ASSERT (result != NULL);
ASSERT (length == 17 + 3 * separator_len);
ASSERT (memcmp (result, "-3", 2) == 0
&& memcmp (result + 2, separator, separator_len) == 0
&& memcmp (result + 2 + separator_len, "141", 3) == 0
&& memcmp (result + 5 + separator_len, separator, separator_len) == 0
&& memcmp (result + 5 + 2 * separator_len, "592", 3) == 0
&& memcmp (result + 8 + 2 * separator_len, separator, separator_len) == 0
&& strcmp (result + 8 + 3 * separator_len, "653,58979") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'010.0f", 1000.0);
ASSERT (result != NULL);
if (separator_len > 0)
{
if (length == 10)
{
/* Result according to POSIX, which says that the width is
measured in "bytes".
<https://pubs.opengroup.org/onlinepubs/9799919799/functions/fprintf.html>
<https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap05.html#tag_05> */
ASSERT (length == 10);
ASSERT (memcmp (result, "0000001" + separator_len, 7 - separator_len) == 0
&& memcmp (result + 7 - separator_len, separator, separator_len) == 0
&& strcmp (result + 7, "000") == 0);
}
else
{
/* Result according to glibc, which measures the width in
multibyte characters or column positions.
<https://sourceware.org/bugzilla/show_bug.cgi?id=28943>
<https://sourceware.org/bugzilla/show_bug.cgi?id=30883>
<https://sourceware.org/bugzilla/show_bug.cgi?id=31542> */
ASSERT (length == 9 + separator_len);
ASSERT (memcmp (result, "000001", 6) == 0
&& memcmp (result + 6, separator, separator_len) == 0
&& strcmp (result + 6 + separator_len, "000") == 0);
}
}
else
{
ASSERT (length == 10);
ASSERT (strcmp (result, "0000001000") == 0);
}
free (result);
}
/* Tests of %g directive with grouping separator. */
{
size_t length;
char *result = asnprintf (NULL, &length, "%'g", 1000.0);
ASSERT (result != NULL);
ASSERT (length == 4 + separator_len);
ASSERT (memcmp (result, "1", 1) == 0
&& memcmp (result + 1, separator, separator_len) == 0
&& strcmp (result + 1 + separator_len, "000") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'g", -142857.0);
ASSERT (result != NULL);
ASSERT (length == 7 + separator_len);
ASSERT (memcmp (result, "-142", 4) == 0
&& memcmp (result + 4, separator, separator_len) == 0
&& strcmp (result + 4 + separator_len, "857") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'.5g", 3141592653.5897932386);
ASSERT (result != NULL);
ASSERT (length == 10);
ASSERT (strcmp (result, "3,1416e+09") == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'.5g", -3141592653.5897932386);
ASSERT (result != NULL);
ASSERT (length == 11);
ASSERT (strcmp (result, "-3,1416e+09") == 0);
free (result);
}
{
size_t length;
char *result =
asnprintf (NULL, &length, "%'.50g",
42351647362715016953416125033982098102569580078125.0);
ASSERT (result != NULL);
ASSERT (length == 50 + 16 * separator_len);
ASSERT (memcmp (result, "42", 2) == 0
&& memcmp (result + 2, separator, separator_len) == 0
&& memcmp (result + 2 + separator_len, "351", 3) == 0
&& memcmp (result + 5 + separator_len, separator, separator_len) == 0
&& memcmp (result + 5 + 2 * separator_len, "647", 3) == 0
&& memcmp (result + 8 + 2 * separator_len, separator, separator_len) == 0
&& memcmp (result + 8 + 3 * separator_len, "362", 3) == 0
&& memcmp (result + 11 + 3 * separator_len, separator, separator_len) == 0
&& memcmp (result + 11 + 4 * separator_len, "715", 3) == 0
&& memcmp (result + 14 + 4 * separator_len, separator, separator_len) == 0);
free (result);
}
{
size_t length;
char *result = asnprintf (NULL, &length, "%'010g", 1000.0);
ASSERT (result != NULL);
if (separator_len > 0)
{
if (length == 10)
{
/* Result according to POSIX, which says that the width is
measured in "bytes".
<https://pubs.opengroup.org/onlinepubs/9799919799/functions/fprintf.html>
<https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap05.html#tag_05> */
ASSERT (length == 10);
ASSERT (memcmp (result, "0000001" + separator_len, 7 - separator_len) == 0
&& memcmp (result + 7 - separator_len, separator, separator_len) == 0
&& strcmp (result + 7, "000") == 0);
}
else
{
/* Result according to glibc, which measures the width in
multibyte characters or column positions.
<https://sourceware.org/bugzilla/show_bug.cgi?id=28943>
<https://sourceware.org/bugzilla/show_bug.cgi?id=30883>
<https://sourceware.org/bugzilla/show_bug.cgi?id=31542> */
ASSERT (length == 9 + separator_len);
ASSERT (memcmp (result, "000001", 6) == 0
&& memcmp (result + 6, separator, separator_len) == 0
&& strcmp (result + 6 + separator_len, "000") == 0);
}
}
else
{
ASSERT (length == 10);
ASSERT (strcmp (result, "0000001000") == 0);
}
free (result);
}
}
return test_exit_status;
}

View File

@@ -3,19 +3,13 @@
# Test whether a french locale is installed.
: "${LOCALE_FR=fr_FR}"
: "${LOCALE_FR_UTF8=fr_FR.UTF-8}"
if test $LOCALE_FR != none; then
testlocale=$LOCALE_FR
else
if test $LOCALE_FR_UTF8 != none; then
testlocale=$LOCALE_FR_UTF8
if test $LOCALE_FR = none && test $LOCALE_FR_UTF8 = none; then
if test -f /usr/bin/localedef; then
echo "Skipping test: no french locale is installed"
else
if test -f /usr/bin/localedef; then
echo "Skipping test: no french locale is installed"
else
echo "Skipping test: no french locale is supported"
fi
exit 77
echo "Skipping test: no french locale is supported"
fi
exit 77
fi
if $LC_NUMERIC_IMPLEMENTED; then
@@ -25,5 +19,11 @@ else
exit 77
fi
LC_ALL=$testlocale \
${CHECKER} ./test-vasnprintf-posix2${EXEEXT}
if test $LOCALE_FR != none; then
LC_ALL=$LOCALE_FR ${CHECKER} ./test-vasnprintf-posix2${EXEEXT} || exit 1
fi
if test $LOCALE_FR_UTF8 != none; then
LC_ALL=$LOCALE_FR_UTF8 ${CHECKER} ./test-vasnprintf-posix2${EXEEXT} || exit 1
fi
exit 0

View File

@@ -24,6 +24,10 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#if __GLIBC__ >= 2 || defined __CYGWIN__
# include <langinfo.h>
# include <stdint.h>
#endif
#include "macros.h"
@@ -60,5 +64,276 @@ main (int argc, char *argv[])
free (result);
}
/* Test that a locale dependent grouping separator is used correctly. */
{
wchar_t separator[10];
#if __GLIBC__ >= 2 || defined __CYGWIN__
/* On glibc, in the unibyte locale fr_FR, the *wprintf routines use U+202F
as separator, which cannot be represented in the locale encoding. */
separator[0] = (wchar_t) (uintptr_t) nl_langinfo (_NL_NUMERIC_THOUSANDS_SEP_WC);
separator[1] = L'\0';
#else
const char *separator_mb =
localeconv ()->thousands_sep; /* = nl_langinfo (THOUSEP) */
mbstowcs (separator, separator_mb, SIZEOF (separator));
#endif
size_t separator_len = wcslen (separator);
/* Tests of %d directive with grouping separator. */
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'d", 1000);
ASSERT (result != NULL);
ASSERT (length == 4 + separator_len);
ASSERT (wmemcmp (result, L"1", 1) == 0
&& wmemcmp (result + 1, separator, separator_len) == 0
&& wcscmp (result + 1 + separator_len, L"000") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'d", -1000);
ASSERT (result != NULL);
ASSERT (length == 5 + separator_len);
ASSERT (wmemcmp (result, L"-1", 2) == 0
&& wmemcmp (result + 2, separator, separator_len) == 0
&& wcscmp (result + 2 + separator_len, L"000") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'d", -142857);
ASSERT (result != NULL);
ASSERT (length == 7 + separator_len);
ASSERT (wmemcmp (result, L"-142", 4) == 0
&& wmemcmp (result + 4, separator, separator_len) == 0
&& wcscmp (result + 4 + separator_len, L"857") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'d", 2147483647);
ASSERT (result != NULL);
ASSERT (length == 10 + 3 * separator_len);
ASSERT (wmemcmp (result, L"2", 1) == 0
&& wmemcmp (result + 1, separator, separator_len) == 0
&& wmemcmp (result + 1 + separator_len, L"147", 3) == 0
&& wmemcmp (result + 4 + separator_len, separator, separator_len) == 0
&& wmemcmp (result + 4 + 2 * separator_len, L"483", 3) == 0
&& wmemcmp (result + 7 + 2 * separator_len, separator, separator_len) == 0
&& wcscmp (result + 7 + 3 * separator_len, L"647") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'d", -2147483647);
ASSERT (result != NULL);
ASSERT (length == 11 + 3 * separator_len);
ASSERT (wmemcmp (result, L"-2", 2) == 0
&& wmemcmp (result + 2, separator, separator_len) == 0
&& wmemcmp (result + 2 + separator_len, L"147", 3) == 0
&& wmemcmp (result + 5 + separator_len, separator, separator_len) == 0
&& wmemcmp (result + 5 + 2 * separator_len, L"483", 3) == 0
&& wmemcmp (result + 8 + 2 * separator_len, separator, separator_len) == 0
&& wcscmp (result + 8 + 3 * separator_len, L"647") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'.10d", 1000);
ASSERT (result != NULL);
if (length == 10 + separator_len)
{
/* Most implementations don't add the grouping character within the
leading zeroes. */
ASSERT (length == 10 + separator_len);
ASSERT (wmemcmp (result, L"0000001", 7) == 0
&& wmemcmp (result + 7, separator, separator_len) == 0
&& wcscmp (result + 7 + separator_len, L"000") == 0);
}
else
{
/* But there are good arguments for adding the grouping character
within the leading zeroes too.
<https://sourceware.org/bugzilla/show_bug.cgi?id=23432> */
ASSERT (length == 10 + 3 * separator_len);
ASSERT (wmemcmp (result, L"0", 1) == 0
&& wmemcmp (result + 1, separator, separator_len) == 0
&& wmemcmp (result + 1 + separator_len, L"000", 3) == 0
&& wmemcmp (result + 4 + separator_len, separator, separator_len) == 0
&& wmemcmp (result + 4 + 2 * separator_len, L"001", 3) == 0
&& wmemcmp (result + 7 + 2 * separator_len, separator, separator_len) == 0
&& wcscmp (result + 7 + 3 * separator_len, L"000") == 0);
}
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'.10d", -1000);
ASSERT (result != NULL);
if (length == 11 + separator_len)
{
/* Most implementations don't add the grouping character within the
leading zeroes. */
ASSERT (length == 11 + separator_len);
ASSERT (wmemcmp (result, L"-0000001", 8) == 0
&& wmemcmp (result + 8, separator, separator_len) == 0
&& wcscmp (result + 8 + separator_len, L"000") == 0);
}
else
{
/* But there are good arguments for adding the grouping character
within the leading zeroes too.
<https://sourceware.org/bugzilla/show_bug.cgi?id=23432> */
ASSERT (length == 11 + 3 * separator_len);
ASSERT (wmemcmp (result, L"-0", 2) == 0
&& wmemcmp (result + 2, separator, separator_len) == 0
&& wmemcmp (result + 2 + separator_len, L"000", 3) == 0
&& wmemcmp (result + 5 + separator_len, separator, separator_len) == 0
&& wmemcmp (result + 5 + 2 * separator_len, L"001", 3) == 0
&& wmemcmp (result + 8 + 2 * separator_len, separator, separator_len) == 0
&& wcscmp (result + 8 + 3 * separator_len, L"000") == 0);
}
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'10d", 1000);
ASSERT (result != NULL);
ASSERT (length == 10);
ASSERT (wmemcmp (result, L" 1" + separator_len, 7 - separator_len) == 0
&& wmemcmp (result + 7 - separator_len, separator, separator_len) == 0
&& wcscmp (result + 7, L"000") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'10d", -1000);
ASSERT (result != NULL);
ASSERT (length == 10);
ASSERT (wmemcmp (result, L" -1" + separator_len, 7 - separator_len) == 0
&& wmemcmp (result + 7 - separator_len, separator, separator_len) == 0
&& wcscmp (result + 7, L"000") == 0);
free (result);
}
/* Tests of %f directive with grouping separator. */
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'.0f", 1000.0);
ASSERT (result != NULL);
ASSERT (length == 4 + separator_len);
ASSERT (wmemcmp (result, L"1", 1) == 0
&& wmemcmp (result + 1, separator, separator_len) == 0
&& wcscmp (result + 1 + separator_len, L"000") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'.5f", 3141592653.5897932386);
ASSERT (result != NULL);
ASSERT (length == 16 + 3 * separator_len);
ASSERT (wmemcmp (result, L"3", 1) == 0
&& wmemcmp (result + 1, separator, separator_len) == 0
&& wmemcmp (result + 1 + separator_len, L"141", 3) == 0
&& wmemcmp (result + 4 + separator_len, separator, separator_len) == 0
&& wmemcmp (result + 4 + 2 * separator_len, L"592", 3) == 0
&& wmemcmp (result + 7 + 2 * separator_len, separator, separator_len) == 0
&& wcscmp (result + 7 + 3 * separator_len, L"653,58979") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'.5f", -3141592653.5897932386);
ASSERT (result != NULL);
ASSERT (length == 17 + 3 * separator_len);
ASSERT (wmemcmp (result, L"-3", 2) == 0
&& wmemcmp (result + 2, separator, separator_len) == 0
&& wmemcmp (result + 2 + separator_len, L"141", 3) == 0
&& wmemcmp (result + 5 + separator_len, separator, separator_len) == 0
&& wmemcmp (result + 5 + 2 * separator_len, L"592", 3) == 0
&& wmemcmp (result + 8 + 2 * separator_len, separator, separator_len) == 0
&& wcscmp (result + 8 + 3 * separator_len, L"653,58979") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'010.0f", 1000.0);
ASSERT (result != NULL);
ASSERT (length == 10);
ASSERT (wmemcmp (result, L"0000001" + separator_len, 7 - separator_len) == 0
&& wmemcmp (result + 7 - separator_len, separator, separator_len) == 0
&& wcscmp (result + 7, L"000") == 0);
free (result);
}
/* Tests of %g directive with grouping separator. */
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'g", 1000.0);
ASSERT (result != NULL);
ASSERT (length == 4 + separator_len);
ASSERT (wmemcmp (result, L"1", 1) == 0
&& wmemcmp (result + 1, separator, separator_len) == 0
&& wcscmp (result + 1 + separator_len, L"000") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'g", -142857.0);
ASSERT (result != NULL);
ASSERT (length == 7 + separator_len);
ASSERT (wmemcmp (result, L"-142", 4) == 0
&& wmemcmp (result + 4, separator, separator_len) == 0
&& wcscmp (result + 4 + separator_len, L"857") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'.5g", 3141592653.5897932386);
ASSERT (result != NULL);
ASSERT (length == 10);
ASSERT (wcscmp (result, L"3,1416e+09") == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'.5g", -3141592653.5897932386);
ASSERT (result != NULL);
ASSERT (length == 11);
ASSERT (wcscmp (result, L"-3,1416e+09") == 0);
free (result);
}
{
size_t length;
wchar_t *result =
asnwprintf (NULL, &length, L"%'.50g",
42351647362715016953416125033982098102569580078125.0);
ASSERT (result != NULL);
ASSERT (length == 50 + 16 * separator_len);
ASSERT (wmemcmp (result, L"42", 2) == 0
&& wmemcmp (result + 2, separator, separator_len) == 0
&& wmemcmp (result + 2 + separator_len, L"351", 3) == 0
&& wmemcmp (result + 5 + separator_len, separator, separator_len) == 0
&& wmemcmp (result + 5 + 2 * separator_len, L"647", 3) == 0
&& wmemcmp (result + 8 + 2 * separator_len, separator, separator_len) == 0
&& wmemcmp (result + 8 + 3 * separator_len, L"362", 3) == 0
&& wmemcmp (result + 11 + 3 * separator_len, separator, separator_len) == 0
&& wmemcmp (result + 11 + 4 * separator_len, L"715", 3) == 0
&& wmemcmp (result + 14 + 4 * separator_len, separator, separator_len) == 0);
free (result);
}
{
size_t length;
wchar_t *result = asnwprintf (NULL, &length, L"%'010g", 1000.0);
ASSERT (result != NULL);
ASSERT (length == 10);
ASSERT (wmemcmp (result, L"0000001" + separator_len, 7 - separator_len) == 0
&& wmemcmp (result + 7 - separator_len, separator, separator_len) == 0
&& wcscmp (result + 7, L"000") == 0);
free (result);
}
}
return test_exit_status;
}

View File

@@ -3,19 +3,13 @@
# Test whether a french locale is installed.
: "${LOCALE_FR=fr_FR}"
: "${LOCALE_FR_UTF8=fr_FR.UTF-8}"
if test $LOCALE_FR != none; then
testlocale=$LOCALE_FR
else
if test $LOCALE_FR_UTF8 != none; then
testlocale=$LOCALE_FR_UTF8
if test $LOCALE_FR = none && test $LOCALE_FR_UTF8 = none; then
if test -f /usr/bin/localedef; then
echo "Skipping test: no french locale is installed"
else
if test -f /usr/bin/localedef; then
echo "Skipping test: no french locale is installed"
else
echo "Skipping test: no french locale is supported"
fi
exit 77
echo "Skipping test: no french locale is supported"
fi
exit 77
fi
if $LC_NUMERIC_IMPLEMENTED; then
@@ -25,5 +19,11 @@ else
exit 77
fi
LC_ALL=$testlocale \
${CHECKER} ./test-vasnwprintf-posix2${EXEEXT}
if test $LOCALE_FR != none; then
LC_ALL=$LOCALE_FR ${CHECKER} ./test-vasnwprintf-posix2${EXEEXT} || exit 1
fi
if test $LOCALE_FR_UTF8 != none; then
LC_ALL=$LOCALE_FR_UTF8 ${CHECKER} ./test-vasnwprintf-posix2${EXEEXT} || exit 1
fi
exit 0