===================================================================
@@ -22,6 +22,8 @@ subdir := stdio-common
include ../Makeconfig
+fp_formats=E e F f G g
+
headers := \
bits/printf-ldbl.h \
bits/stdio_lim.h \
@@ -307,6 +309,20 @@ tests-internal = \
test-srcs = \
tst-printf \
+ tst-printf-format-c \
+ tst-printf-format-char \
+ tst-printf-format-double \
+ tst-printf-format-int \
+ tst-printf-format-ldouble \
+ tst-printf-format-llong \
+ tst-printf-format-long \
+ tst-printf-format-s \
+ tst-printf-format-short \
+ tst-printf-format-uchar \
+ tst-printf-format-uint \
+ tst-printf-format-ullong \
+ tst-printf-format-ulong \
+ tst-printf-format-ushort \
tst-printfsz-islongdouble \
tst-unbputc \
# test-srcs
@@ -330,6 +346,20 @@ tests-special += \
$(objpfx)tst-getline-mem.out \
$(objpfx)tst-printf-bz18872-mem.out \
$(objpfx)tst-printf-bz25691-mem.out \
+ $(objpfx)tst-printf-format-c.out \
+ $(objpfx)tst-printf-format-char.out \
+ $(foreach f,$(fp_formats),$(objpfx)tst-printf-format-double-$(f).out) \
+ $(objpfx)tst-printf-format-int.out \
+ $(foreach f,$(fp_formats),$(objpfx)tst-printf-format-ldouble-$(f).out) \
+ $(objpfx)tst-printf-format-llong.out \
+ $(objpfx)tst-printf-format-long.out \
+ $(objpfx)tst-printf-format-s.out \
+ $(objpfx)tst-printf-format-short.out \
+ $(objpfx)tst-printf-format-uchar.out \
+ $(objpfx)tst-printf-format-uint.out \
+ $(objpfx)tst-printf-format-ullong.out \
+ $(objpfx)tst-printf-format-ulong.out \
+ $(objpfx)tst-printf-format-ushort.out \
$(objpfx)tst-printf-fp-free-mem.out \
$(objpfx)tst-printf-fp-leak-mem.out \
$(objpfx)tst-ungetc-leak-mem.out \
@@ -354,6 +384,34 @@ generated += \
tst-printf-bz18872.mtrace \
tst-printf-bz25691-mem.out \
tst-printf-bz25691.mtrace \
+ tst-printf-format-c.mtrace \
+ tst-printf-format-c.out \
+ tst-printf-format-char.mtrace \
+ tst-printf-format-char.out \
+ $(foreach f,$(fp_formats),tst-printf-format-double-$(f).mtrace) \
+ $(foreach f,$(fp_formats),tst-printf-format-double-$(f).out) \
+ tst-printf-format-int.mtrace \
+ tst-printf-format-int.out \
+ $(foreach f,$(fp_formats),tst-printf-format-ldouble-$(f).mtrace) \
+ $(foreach f,$(fp_formats),tst-printf-format-ldouble-$(f).out) \
+ tst-printf-format-llong.mtrace \
+ tst-printf-format-llong.out \
+ tst-printf-format-long.mtrace \
+ tst-printf-format-long.out \
+ tst-printf-format-s.mtrace \
+ tst-printf-format-s.out \
+ tst-printf-format-short.mtrace \
+ tst-printf-format-short.out \
+ tst-printf-format-uchar.mtrace \
+ tst-printf-format-uchar.out \
+ tst-printf-format-uint.mtrace \
+ tst-printf-format-uint.out \
+ tst-printf-format-ullong.mtrace \
+ tst-printf-format-ullong.out \
+ tst-printf-format-ulong.mtrace \
+ tst-printf-format-ulong.out \
+ tst-printf-format-ushort.mtrace \
+ tst-printf-format-ushort.out \
tst-printf-fp-free-mem.out \
tst-printf-fp-free.mtrace \
tst-printf-fp-leak-mem.out \
@@ -485,6 +543,33 @@ $(objpfx)tst-printf.out: tst-printf.sh $
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
$(evaluate-test)
+# We can't split a quoted recipe line, so do it via an auxiliary variable.
+# For simplicity of the rules we always pass the stem as the first argument,
+# which tells the floating-point format test scripts what formatted output
+# conversion specifier to verify and is ignored by the remaining test scripts.
+make-tst-printf-format-out = \
+ AWK='$(AWK)' \
+ $(BASH) $< $* $(common-objpfx) \
+ '$(run-program-prefix-before-env) \
+ $(run-program-env) \
+ MALLOC_TRACE=$(@:.out=.mtrace) \
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so \
+ $(run-program-prefix-after-env)'
+$(objpfx)tst-printf-format-%.out: \
+ tst-printf-format-%.sh $(objpfx)tst-printf-format-% tst-printf-format.awk
+ $(make-tst-printf-format-out) > $@; \
+ $(evaluate-test)
+$(objpfx)tst-printf-format-double-%.out: \
+ tst-printf-format-double.sh $(objpfx)tst-printf-format-double \
+ tst-printf-format.awk
+ $(make-tst-printf-format-out) > $@; \
+ $(evaluate-test)
+$(objpfx)tst-printf-format-ldouble-%.out: \
+ tst-printf-format-ldouble.sh $(objpfx)tst-printf-format-ldouble \
+ tst-printf-format.awk
+ $(make-tst-printf-format-out) > $@; \
+ $(evaluate-test)
+
$(objpfx)tst-printfsz-islongdouble.out: \
tst-printfsz-islongdouble.sh $(objpfx)tst-printfsz-islongdouble
$(SHELL) $^ '$(test-program-prefix)' $@; \
===================================================================
@@ -0,0 +1,29 @@
+/* Test for formatted printf output for the 'c' conversion.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 3
+#define HUGE_WIDTH 4
+#define REF_FMT "c"
+#define REF_VAL(v) (v)
+typedef unsigned char type_t;
+static const type_t vals[] = { 0, 42, UCHAR_MAX };
+static const char length[] = "";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,33 @@
+#!/bin/bash
+# Testing of the 'c' printf conversion.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+echo Verifying c
+(set -o pipefail
+ ${test_program_prefix} ${common_objpfx}stdio-common/tst-printf-format-c c |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion c output error, first line:\n/") >&2 ||
+ exit 1
===================================================================
@@ -0,0 +1,31 @@
+/* Test for formatted printf output for signed char conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 3
+#define HUGE_WIDTH 5
+#define REF_FMT "i"
+#define REF_VAL(v) ((((v) & 0xff) ^ 0x80) - 0x80)
+typedef int type_t;
+static const type_t vals[] =
+ { SCHAR_MIN - 123, SCHAR_MIN - 1, SCHAR_MIN, -123, -1, 0, 1, 42, SCHAR_MAX,
+ SCHAR_MAX + 1, SCHAR_MAX + 42 };
+static const char length[] = "hh";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,40 @@
+#!/bin/bash
+# Testing of signed char printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=0
+
+for f in d i; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-char $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,33 @@
+/* Test for formatted printf output for double conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <float.h>
+#include <math.h>
+
+#define MID_WIDTH 20
+#define HUGE_WIDTH 320
+#define REF_FMT ".35e"
+#define REF_VAL(v) (v)
+#define PREC DBL_MANT_DIG
+typedef double type_t;
+static const type_t vals[] =
+ { -HUGE_VAL, -DBL_MAX, -DBL_MIN, copysign (0, -1), -NAN, NAN, 0, DBL_MIN,
+ DBL_MAX, HUGE_VAL };
+static const char length[] = "";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,73 @@
+#!/bin/bash
+# Testing of double printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+format=$1; shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+# For floating-point formats we need to use the bignum mode even if the
+# regular mode would do, because GAWK in the latter mode uses sprintf(3)
+# internally to process the conversion requested, so any bug in our code
+# would then be verified against itself, defeating the objective of doing
+# the verification against an independent implementation.
+AWK="${AWK:-awk} -M"
+
+status=77
+
+# Verify that AWK can handle the range required. It also catches:
+# "gawk: warning: -M ignored: MPFR/GMP support not compiled in"
+# message produced where bignum support is not there, which is the
+# only indication as the use of '-M' does not affect the exit status
+# in this case.
+ref="-1.79769313486231570814527423731704357e+308"
+val=$(echo "$ref" | $AWK '{ printf "%.35e\n", $1 }' 2>&1) &&
+ test "$val" = "$ref" && status=0
+
+test $status -eq 0 || { echo "No working AWK found" && exit $status; }
+
+# Check for any additional conversions that AWK handles conditionally
+# according to its version and/or the environment it has been built in.
+# The 'A' and 'a' conversions are not suitable to use at this point, as
+# output produced by AWK is different apparently due to a subtlety in
+# rounding, so do not try them.
+declare -A conversion_disabled
+ref="-inf"
+for f in f F; do
+ conversion_disabled[$f]=true
+ val=$(echo "$ref" | $AWK '{ printf "%'$f'\n", $1 }' 2>&1) &&
+ test "${val^^}" = "${ref^^}" && unset conversion_disabled[$f]
+done
+
+if test "${conversion_disabled[$format]+set}" = set; then
+ echo Unsupported $format
+ status=77
+else
+ echo Verifying $format
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-double $format |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 |
+ sed "s/^/Conversion $format output error, first line:\n/") >&2 ||
+ status=1
+fi
+
+exit $status
===================================================================
@@ -0,0 +1,29 @@
+/* Test for formatted printf output for int conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 8
+#define HUGE_WIDTH 15
+#define REF_FMT "i"
+#define REF_VAL(v) (v)
+typedef int type_t;
+static const type_t vals[] = { INT_MIN, -123, -1, 0, 1, 42, INT_MAX };
+static const char length[] = "";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Testing of int printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=77
+
+# Verify that AWK can handle the range required. It also catches:
+# "gawk: warning: -M ignored: MPFR/GMP support not compiled in"
+# message produced where bignum support is not there, which is the
+# only indication as the use of '-M' does not affect the exit status
+# in this case.
+ref="-2147483648"
+for AWK in "$AWK -M" "$AWK"; do
+ val=$(echo "$ref" | $AWK '{ printf "%d\n", $1 }' 2>&1) || continue
+ test "$val" = "$ref" && status=0 && break
+done
+
+test $status -eq 0 || { echo "No working AWK found" && exit $status; }
+
+for f in d i; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-int $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,35 @@
+/* Test for formatted printf output for long double conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <float.h>
+#include <math.h>
+#include <support/test-driver.h>
+
+#define MID_WIDTH 20
+#define HUGE_WIDTH 4950
+#define REF_FMT ".35Le"
+#define REF_VAL(v) (v)
+#define PREC LDBL_MANT_DIG
+typedef long double type_t;
+static const type_t vals[] =
+ { -HUGE_VAL, -LDBL_MAX, -LDBL_MIN, copysign (0, -1), -NAN, NAN, 0, LDBL_MIN,
+ LDBL_MAX, HUGE_VAL };
+static const char length[] = "L";
+
+#define TIMEOUT (DEFAULT_TIMEOUT * 64)
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,73 @@
+#!/bin/bash
+# Testing of long double printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+format=$1; shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+# For floating-point formats we need to use the bignum mode even if the
+# regular mode would do, because GAWK in the latter mode uses sprintf(3)
+# internally to process the conversion requested, so any bug in our code
+# would then be verified against itself, defeating the objective of doing
+# the verification against an independent implementation.
+AWK="${AWK:-awk} -M"
+
+status=77
+
+# Verify that AWK can handle the range required. It also catches:
+# "gawk: warning: -M ignored: MPFR/GMP support not compiled in"
+# message produced where bignum support is not there, which is the
+# only indication as the use of '-M' does not affect the exit status
+# in this case.
+ref="-1.18973149535723176508575932662800702e+4932"
+val=$(echo "$ref" | $AWK '{ PREC=113; printf "%.35e\n", $1 }' 2>&1) &&
+ test "$val" = "$ref" && status=0
+
+test $status -eq 0 || { echo "No working AWK found" && exit $status; }
+
+# Check for any additional conversions that AWK handles conditionally
+# according to its version and/or the environment it has been built in.
+# The 'A' and 'a' conversions are not suitable to use at this point, as
+# output produced by AWK is different apparently due to a subtlety in
+# rounding, so do not try them.
+declare -A conversion_disabled
+ref="-inf"
+for f in f F; do
+ conversion_disabled[$f]=true
+ val=$(echo "$ref" | $AWK '{ printf "%'$f'\n", $1 }' 2>&1) &&
+ test "${val^^}" = "${ref^^}" && unset conversion_disabled[$f]
+done
+
+if test "${conversion_disabled[$format]+set}" = set; then
+ echo Unsupported $format
+ status=77
+else
+ echo Verifying $format
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-ldouble $format |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 |
+ sed "s/^/Conversion $format output error, first line:\n/") >&2 ||
+ status=1
+fi
+
+exit $status
===================================================================
@@ -0,0 +1,29 @@
+/* Test for formatted printf output for long long int conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 15
+#define HUGE_WIDTH 25
+#define REF_FMT "lli"
+#define REF_VAL(v) (v)
+typedef long long int type_t;
+static const type_t vals[] = { LLONG_MIN, -123, -1, 0, 1, 42, LLONG_MAX };
+static const char length[] = "ll";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Testing of long long int printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=77
+
+# Verify that AWK can handle the range required. It also catches:
+# "gawk: warning: -M ignored: MPFR/GMP support not compiled in"
+# message produced where bignum support is not there, which is the
+# only indication as the use of '-M' does not affect the exit status
+# in this case.
+ref="9223372036854775807"
+for AWK in "$AWK -M" "$AWK"; do
+ val=$(echo "$ref" | $AWK '{ printf "%d\n", $1 }' 2>&1) || continue
+ test "$val" = "$ref" && status=0 && break
+done
+
+test $status -eq 0 || { echo "No working AWK found" && exit $status; }
+
+for f in d i; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-llong $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,29 @@
+/* Test for formatted printf output for long int conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 15
+#define HUGE_WIDTH 25
+#define REF_FMT "li"
+#define REF_VAL(v) (v)
+typedef long int type_t;
+static const type_t vals[] = { LONG_MIN, -123, -1, 0, 1, 42, LONG_MAX };
+static const char length[] = "l";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Testing of long int printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=77
+
+# Verify that AWK can handle the range required. It also catches:
+# "gawk: warning: -M ignored: MPFR/GMP support not compiled in"
+# message produced where bignum support is not there, which is the
+# only indication as the use of '-M' does not affect the exit status
+# in this case.
+ref="9223372036854775807"
+for AWK in "$AWK -M" "$AWK"; do
+ val=$(echo "$ref" | $AWK '{ printf "%d\n", $1 }' 2>&1) || continue
+ test "$val" = "$ref" && status=0 && break
+done
+
+test $status -eq 0 || { echo "No working AWK found" && exit $status; }
+
+for f in d i; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-long $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,30 @@
+/* Test for formatted printf output for the 's' conversion.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 5
+#define HUGE_WIDTH 10
+#define REF_FMT "s"
+#define REF_VAL(v) (v)
+typedef const char *type_t;
+static const type_t vals[] =
+ { "", "The", "quick", "brown fox", "jumps over the lazy dog" };
+static const char length[] = "";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,33 @@
+#!/bin/bash
+# Testing of the 's' printf conversion.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+echo Verifying s
+(set -o pipefail
+ ${test_program_prefix} ${common_objpfx}stdio-common/tst-printf-format-s s |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion s output error, first line:\n/") >&2 ||
+ exit 1
===================================================================
@@ -0,0 +1,31 @@
+/* Test for formatted printf output for short int conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 4
+#define HUGE_WIDTH 7
+#define REF_FMT "i"
+#define REF_VAL(v) ((((v) & 0xffff) ^ 0x8000) - 0x8000)
+typedef int type_t;
+static const type_t vals[] =
+ { SHRT_MIN - 123, SHRT_MIN - 1, SHRT_MIN, -123, -1, 0, 1, 42, SHRT_MAX,
+ SHRT_MAX + 1, SHRT_MAX + 42 };
+static const char length[] = "h";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,40 @@
+#!/bin/bash
+# Testing of short int printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=0
+
+for f in d i; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-short $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,370 @@
+/* Test skeleton for formatted printf output.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* The following definitions have to be supplied by the source including
+ this skeleton:
+
+ Macros:
+ MID_WIDTH Medium width/precision positive integer constant. Choose
+ such as to cause some, but not all the strings produced
+ to be truncated for the conversions handled.
+ HUGE_WIDTH Large width/precision positive integer constant. Choose
+ such as to cause none of the strings produced to be
+ truncated for the conversions handled.
+ REF_FMT Reference output format string. Use no flags and such
+ a precision and length modifier, where applicable, and
+ a conversion as to make sure the output produced allows
+ the original value to be reproduced.
+ REF_VAL(v) Reference value V transformation. For conversions with
+ a truncating length modifier define such as to reproduce
+ the truncation operation, otherwise let V pass through.
+ PREC [optional] Working precision positive integer constant.
+ Set to the number of binary digits in the significand for
+ the argument type handled; usually for floating-point
+ conversions only, but it may be required for 128-bit or
+ wider integer data types as well.
+
+ Typedefs:
+ type_t Variadic function argument type. Define to the promoted
+ type corresponding to the conversion argument type
+ handled.
+
+ Variables:
+ vals Array of TYPE_T values. Choose such as to cover boundary
+ and any special cases.
+ length Length modifier string. Define according to the
+ conversion argument type handled.
+
+ See tst-printf-format-*.c for usage examples. */
+
+#include <array_length.h>
+#include <mcheck.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Set to nonzero to select all possible tuples with repetitions of 1..n
+ elements from the set of flags as defined in FLAGS array below; n is
+ the length of FLAGS array. Otherwise select all possible tuples with
+ repetitions of 1..2 elements, followed by tuples of 3..n elements where
+ the index of each element k; k = 2..n in FLAGS is lower than the index
+ of element k-1 in FLAGS. */
+#ifndef TST_PRINTF_DUPS
+# define TST_PRINTF_DUPS 0
+#endif
+/* Set to nonzero to report the precision (number of significand digits)
+ required for floating-point calculations. */
+#ifndef PREC
+# define PREC 0
+#endif
+
+/* The list of conversions permitted for the '#' flag, the '0' flag,
+ and precision respectively. */
+#define HASH_FORMATS "boxXaAeEfFgG"
+#define ZERO_FORMATS "bdiouxXaAeEfFgG"
+#define PREC_FORMATS "bdiouxXaAeEfFgGs"
+
+/* Output format conversion flags. */
+static struct
+{
+ /* Flag character. */
+ char f;
+ /* List of conversion specifiers the flag is valid for; NULL if all. */
+ const char *s;
+} const flags[] =
+ { {'-'}, {'+'}, {' '}, {'#', HASH_FORMATS}, {'0', ZERO_FORMATS} };
+
+/* Helper to initialize elements of the PW array for the width and
+ precision to be specified as a positive integer directly in the
+ format, and then as both a negative and a positive argument to '*'. */
+#define STR(v) #v
+#define WPINIT(v) {0, STR (v)}, {v, NULL}, {-v, NULL}
+
+/* Width and precision settings to iterate over; zero is initialized
+ directly as it has no corresponding negated value and other values
+ use the helper above. */
+static struct wp
+{
+ /* Integer argument to '*', used if S is NULL. */
+ int i;
+ /* String denoting an integer to use in the format, or NULL to use '*'. */
+ const char *s;
+} const wp[] =
+ { {0, "0"}, {0, NULL}, WPINIT (1), WPINIT (2),
+ WPINIT (MID_WIDTH), WPINIT (HUGE_WIDTH) };
+
+/* Produce a record according to '%' and zero or more output format flags
+ already provided in FMT at indices 0..IDX-1, width W if non-NULL, '.'
+ precision specifier if POINT set to true, precision P if non-NULL,
+ any length modifiers L, conversion C, and value VAL.
+
+ Record formats produced:
+
+ %<FLAGS><L><C>:<VAL>:
+ %<FLAGS>.<L><C>:<VAL>:
+ %<FLAGS><W><L><C>:<VAL>:
+ %<FLAGS><W>.<L><C>:<VAL>:
+ %<FLAGS>.<P><L><C>:<VAL>:
+ %<FLAGS><W>.<P><L><C>:<VAL>:
+ %<FLAGS>*<L><C>:<W>:<VAL>:
+ %<FLAGS>*.<L><C>:<W>:<VAL>:
+ %<FLAGS>.*<L><C>:<P>:<VAL>:
+ %<FLAGS>*.*<L><C>:<W>:<P>:<VAL>:
+
+ Return 0 on success, -1 on failure. */
+
+static int
+do_printf (char *fmt, size_t idx,
+ const struct wp *w, bool point, const struct wp *p,
+ const char *l, char c, type_t val)
+{
+ int wpval[2] = { 0 };
+ size_t nint = 0;
+ int result;
+ size_t i;
+
+ if (w != NULL)
+ {
+ if (w->s == NULL)
+ {
+ fmt[idx++] = '*';
+ wpval[nint++] = w->i;
+ }
+ else
+ for (i = 0; w->s[i] != '\0'; i++)
+ fmt[idx++] = w->s[i];
+ }
+ if (point)
+ fmt[idx++] = '.';
+ if (p != NULL)
+ {
+ if (p->s == NULL)
+ {
+ fmt[idx++] = '*';
+ wpval[nint++] = p->i;
+ }
+ else
+ for (i = 0; p->s[i] != '\0'; i++)
+ fmt[idx++] = p->s[i];
+ }
+ for (i = 0; length[i] != '\0'; i++)
+ fmt[idx++] = length[i];
+ fmt[idx++] = c;
+ fmt[idx] = ':';
+ fmt[idx + 1] = '\0';
+ if (fputs (fmt, stdout) == EOF)
+ {
+ perror ("fputs");
+ return -1;
+ }
+ fmt[idx++] = '\0';
+ if (nint > 0)
+ {
+ result = printf ("%i:", wpval[0]);
+ if (result < 0)
+ {
+ perror ("printf");
+ return -1;
+ }
+ if (nint > 1)
+ {
+ result = printf ("%i:", wpval[1]);
+ if (result < 0)
+ {
+ perror ("printf");
+ return -1;
+ }
+ }
+ }
+ switch (nint)
+ {
+ case 0:
+ result = printf (fmt, val);
+ break;
+ case 1:
+ result = printf (fmt, wpval[0], val);
+ break;
+ case 2:
+ result = printf (fmt, wpval[0], wpval[1], val);
+ break;
+ default:
+ fputs ("Broken test, nint > 2\n", stderr);
+ return -1;
+ }
+ if (result < 0)
+ {
+ perror ("printf");
+ return -1;
+ }
+ if (fputs (":\n", stdout) == EOF)
+ {
+ perror ("fputs");
+ return -1;
+ }
+ return 0;
+}
+
+/* Produce a list of records according to '%' and zero or more output
+ format flags already provided in FMT at indices 0..IDX-1, iterating
+ over widths and precisions defined in global WP array, any length
+ modifiers L, conversion C, and value VAL. Inline '0' is omitted for
+ the width, as it is a flag already handled among the flags supplied.
+ Precision is omitted where the conversion does not allow it.
+
+ Return 0 on success, -1 on failure. */
+
+static int
+do_printf_flags (char *fmt, size_t idx, const char *l, char c, type_t val)
+{
+ bool do_prec = strchr (PREC_FORMATS, c) != NULL;
+ size_t i;
+
+ if (do_printf (fmt, idx, NULL, false, NULL, l, c, val) < 0)
+ return -1;
+ if (do_prec && do_printf (fmt, idx, NULL, true, NULL, l, c, val) < 0)
+ return -1;
+ for (i = 0; i < array_length (wp); i++)
+ {
+ size_t j;
+
+ if (do_prec && do_printf (fmt, idx, NULL, true, wp + i, l, c, val) < 0)
+ return -1;
+ /* Inline '0' is a flag rather than width and is handled elsewhere. */
+ if (wp[i].s != NULL && wp[i].s[0] == '0' && wp[i].s[1] == '\0')
+ continue;
+ if (do_printf (fmt, idx, wp + i, false, NULL, l, c, val) < 0)
+ return -1;
+ if (do_prec)
+ {
+ if (do_printf (fmt, idx, wp + i, true, NULL, l, c, val) < 0)
+ return -1;
+ for (j = 0; j < array_length (wp); j++)
+ if (do_printf (fmt, idx, wp + i, true, wp + j, l, c, val) < 0)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Produce a list of records using the formatted output specifier
+ supplied in ARGV[1] preceded by any length modifier supplied in
+ the global LENGTH variable, iterating over format flags defined
+ in the global FLAGS array, and values supplied in the global VALS
+ array. Note that the output specifier supplied is not verified
+ against TYPE_T, so undefined behavior will result if this is used
+ incorrectly.
+
+ If PREC is nonzero, then this record:
+
+ prec:<PREC>
+
+ is produced at the beginning. Then for each VAL from VALS a block
+ of records is produced starting with:
+
+ val:<VAL>
+
+ where VAL is formatted according to REF_FMT output format. The
+ block continues with records as shown with DO_PRINTF above using
+ flags iterated over according to TST_PRINTF_DUPS.
+
+ See the top of this file for the definitions that have to be
+ provided by the source including this skeleton. */
+
+static int
+do_test (int argc, char *argv[])
+{
+ char fmt[100] = {'%'};
+ size_t j;
+ size_t v;
+ char c;
+
+ if (argc < 2 || *argv[1] == '\0')
+ {
+ fprintf (stderr, "Usage: %s <specifier>\n", basename (argv[0]));
+ return EXIT_FAILURE;
+ }
+
+ mtrace ();
+
+ if (PREC && printf ("prec:%i\n", PREC) < 0)
+ {
+ perror ("printf");
+ return EXIT_FAILURE;
+ }
+
+ c = *argv[1];
+ for (v = 0; v < array_length (vals); v++)
+ {
+ if (printf ("val:%" REF_FMT "\n", REF_VAL (vals[v])) < 0)
+ {
+ perror ("printf");
+ return EXIT_FAILURE;
+ }
+
+ if (do_printf_flags (fmt, 1, length, c, vals[v]) < 0)
+ return EXIT_FAILURE;
+ for (j = 0; j < array_length (flags); j++)
+ {
+ bool done = false;
+ size_t i[j + 1];
+ size_t k;
+
+ memset (i, 0, sizeof (i));
+ while (!done)
+ {
+ bool skip = false;
+ size_t idx = 1;
+ char f;
+
+ for (k = 0; k <= j; k++)
+ {
+ const char *s = flags[i[k]].s;
+
+ if (s && strchr (s, c) == NULL)
+ skip = true;
+ if (!TST_PRINTF_DUPS && j > 1 && k > 0 && i[k] >= i[k - 1])
+ skip = true;
+ if (skip)
+ break;
+
+ f = flags[i[k]].f;
+ fmt[idx++] = f;
+ }
+ if (!skip && do_printf_flags (fmt, idx, length, c, vals[v]) < 0)
+ return EXIT_FAILURE;
+ for (k = 0; k <= j; k++)
+ {
+ i[k]++;
+ if (i[k] < array_length (flags))
+ break;
+ else if (k == j)
+ done = true;
+ else
+ i[k] = 0;
+ }
+ }
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
===================================================================
@@ -0,0 +1,30 @@
+/* Test for formatted printf output for unsigned char conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 3
+#define HUGE_WIDTH 4
+#define REF_FMT "u"
+#define REF_VAL(v) ((v) & 0xff)
+typedef unsigned int type_t;
+static const type_t vals[] =
+ { 0, 1, 42, UCHAR_MAX, UCHAR_MAX + 1, UCHAR_MAX + 42 };
+static const char length[] = "hh";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,40 @@
+#!/bin/bash
+# Testing of unsigned char printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=0
+
+for f in o u x X; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-uchar $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,29 @@
+/* Test for formatted printf output for unsigned int conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 7
+#define HUGE_WIDTH 14
+#define REF_FMT "u"
+#define REF_VAL(v) (v)
+typedef unsigned int type_t;
+static const type_t vals[] = { 0, 1, 42, UINT_MAX };
+static const char length[] = "";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Testing of unsigned int printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=77
+
+# Verify that AWK can handle the range required. It also catches:
+# "gawk: warning: -M ignored: MPFR/GMP support not compiled in"
+# message produced where bignum support is not there, which is the
+# only indication as the use of '-M' does not affect the exit status
+# in this case.
+ref="4294967295"
+for AWK in "$AWK -M" "$AWK"; do
+ val=$(echo "$ref" | $AWK '{ printf "%d\n", $1 }' 2>&1) || continue
+ test "$val" = "$ref" && status=0 && break
+done
+
+test $status -eq 0 || { echo "No working AWK found" && exit $status; }
+
+for f in o u x X; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-uint $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,29 @@
+/* Test for formatted printf output for unsigned long long int conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 14
+#define HUGE_WIDTH 24
+#define REF_FMT "llu"
+#define REF_VAL(v) (v)
+typedef unsigned long long int type_t;
+static const type_t vals[] = { 0, 1, 42, UINT_MAX, ULLONG_MAX };
+static const char length[] = "ll";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Testing of unsigned long long int printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=77
+
+# Verify that AWK can handle the range required. It also catches:
+# "gawk: warning: -M ignored: MPFR/GMP support not compiled in"
+# message produced where bignum support is not there, which is the
+# only indication as the use of '-M' does not affect the exit status
+# in this case.
+ref="18446744073709551615"
+for AWK in "$AWK -M" "$AWK"; do
+ val=$(echo "$ref" | $AWK '{ printf "%d\n", $1 }' 2>&1) || continue
+ test "$val" = "$ref" && status=0 && break
+done
+
+test $status -eq 0 || { echo "No working AWK found" && exit $status; }
+
+for f in o u x X; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-ullong $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,29 @@
+/* Test for formatted printf output for unsigned long int conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 14
+#define HUGE_WIDTH 24
+#define REF_FMT "lu"
+#define REF_VAL(v) (v)
+typedef unsigned long int type_t;
+static const type_t vals[] = { 0, 1, 42, ULONG_MAX };
+static const char length[] = "l";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Testing of unsigned long int printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=77
+
+# Verify that AWK can handle the range required. It also catches:
+# "gawk: warning: -M ignored: MPFR/GMP support not compiled in"
+# message produced where bignum support is not there, which is the
+# only indication as the use of '-M' does not affect the exit status
+# in this case.
+ref="18446744073709551615"
+for AWK in "$AWK -M" "$AWK"; do
+ val=$(echo "$ref" | $AWK '{ printf "%d\n", $1 }' 2>&1) || continue
+ test "$val" = "$ref" && status=0 && break
+done
+
+test $status -eq 0 || { echo "No working AWK found" && exit $status; }
+
+for f in o u x X; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-ulong $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,30 @@
+/* Test for formatted printf output for unsigned short int conversions.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+
+#define MID_WIDTH 3
+#define HUGE_WIDTH 6
+#define REF_FMT "u"
+#define REF_VAL(v) ((v) & 0xffff)
+typedef unsigned int type_t;
+static const type_t vals[] =
+ { 0, 1, 42, USHRT_MAX, USHRT_MAX + 1, USHRT_MAX + 42 };
+static const char length[] = "h";
+
+#include "tst-printf-format-skeleton.c"
===================================================================
@@ -0,0 +1,40 @@
+#!/bin/bash
+# Testing of unsigned short int printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+set -e
+
+shift
+common_objpfx=$1; shift
+test_program_prefix=$1; shift
+
+AWK=${AWK:-awk}
+
+status=0
+
+for f in o u x X; do
+ echo Verifying $f
+ (set -o pipefail
+ ${test_program_prefix} \
+ ${common_objpfx}stdio-common/tst-printf-format-ushort $f |
+ $AWK -f tst-printf-format.awk 2>&1 |
+ head -n 1 | sed "s/^/Conversion $f output error, first line:\n/") >&2 ||
+ status=1
+done
+
+exit $status
===================================================================
@@ -0,0 +1,119 @@
+# Testing of printf conversions.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <https://www.gnu.org/licenses/>.
+
+BEGIN {
+ FS = ":"
+}
+
+/^prec:/ {
+ PREC = $2
+}
+
+/^val:/ {
+ val = $2
+ # Prepend "+" for +Inf or +NaN value lacking a sign, because gawk
+ # interpretes them as strings rather than numeric values in the
+ # non-bignum mode unless a sign has been explicitly given. Keep
+ # original 'val' for reporting.
+ value = gensub(/^(INF|NAN|inf|nan)/, "+\\1", 1, val)
+}
+
+/^%/ {
+ # Discard the trailing empty field, used to improve legibility of data.
+ input = $--NF
+ format = $1
+ width = $2
+ precision = "." $(NF - 1)
+ # Discard any negative precision, which is to be taken as if omitted.
+ sub(/\.-.*/, "", precision)
+ # Simplify handling and paste the precision and width specified as
+ # arguments to '*' directly into the format.
+ sub(/\.\*/, precision, format)
+ sub(/\*/, width, format)
+ # Discard length modifiers. They are only relevant to C data types.
+ sub(/([DHLjhltz]|wf?[1-9][0-9]*)/, "", format)
+ # Discard the '#' flag with the octal conversion if output starts with
+ # 0 in the absence of this flag. In that case no extra 0 is supposed
+ # to be produced, but gawk prepends it anyway.
+ if (format ~ /#.*o/)
+ {
+ tmpfmt = gensub(/#/, "", "g", format)
+ tmpout = sprintf(tmpfmt, value)
+ if (tmpout ~ /^ *0/)
+ format = tmpfmt
+ }
+ # Likewise with the hexadecimal conversion where zero value with the
+ # precision of zero is supposed to produce no characters, but gawk
+ # outputs 0 instead.
+ else if (format ~ /#.*[Xx]/)
+ {
+ tmpfmt = gensub(/#/, "", "g", format)
+ tmpout = sprintf(tmpfmt, value)
+ if (tmpout ~ /^ *$/)
+ format = tmpfmt
+ }
+ # AWK interpretes input opportunistically as a number, which interferes
+ # with how the 'c' conversion works: "a" input will result in "a" output
+ # however "0" input will result in "^@" output rather than "0". Force
+ # the value to be interpreted as a string then, by appending "".
+ output = sprintf(format, value "")
+ # Make up for various anomalies with the handling of +/-Inf and +/-NaN
+ # values and reprint the output produced using the string conversion,
+ # with the field width carried over and the relevant flags handled by
+ # hand.
+ if (format ~ /[EFGefg]/ && value ~ /(INF|NAN|inf|nan)/)
+ {
+ minus = format ~ /-/ ? "-" : ""
+ sign = value ~ /-/ ? "-" : format ~ /\+/ ? "+" : format ~ / / ? " " : ""
+ if (format ~ /^%[^\.1-9]*[1-9][0-9]*/)
+ width = gensub(/^%[^\.1-9]*([1-9][0-9]*).*$/, "\\1", 1, format)
+ else
+ width = ""
+ output = gensub(/[-+ ]/, "", "g", output)
+ output = sprintf("%" minus width "s", sign output)
+ }
+ # Produce "+" where the '+' flag has been used with a signed integer
+ # conversion for zero value, observing any field width in effect.
+ # In that case "+" is always supposed to be produced, but with the
+ # precision of zero gawk in the non-bignum mode produces any padding
+ # requested only.
+ else if (format ~ /\+.*[di]/ && value == 0)
+ {
+ output = gensub(/^( *) $/, format ~ /-/ ? "+\\1" : "\\1+", 1, output)
+ output = gensub(/^$/, "+", 1, output)
+ }
+ # Produce " " where the space flag has been used with a signed integer
+ # conversion for zero value. In that case at least one " " is
+ # supposed to be produced, but with the precision of zero gawk in the
+ # non-bignum mode produces nothing.
+ else if (format ~ / .*[di]/ && value == 0)
+ {
+ output = gensub(/^$/, " ", 1, output)
+ }
+ if (output != input)
+ {
+ printf "(\"%s\"%s%s, %s) => \"%s\", expected \"%s\"\n", \
+ $1, (NF > 2 ? ", " $2 : ""), (NF > 3 ? ", " $3 : ""), val, \
+ input, output > "/dev/stderr"
+ status = 1
+ }
+}
+
+END {
+ exit status
+}