summaryrefslogtreecommitdiff
path: root/stdio-common
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2018-12-27 19:31:37 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2018-12-27 19:31:37 +0000
commit74a412373b66a38b6ce8156f027ce26f89a7462f (patch)
treea59ce0af7ffd48641ca9124d697f7a6b57b26931 /stdio-common
parent2004eeba8fb2a92105bbf95b280fff6dc1d84144 (diff)
parent4cbfda396f7cd9e83116c28965ade73d80c1cb82 (diff)
Merge commit 'refs/top-bases/t/ONSTACK' into t/ONSTACK
Diffstat (limited to 'stdio-common')
-rw-r--r--stdio-common/Makefile72
-rw-r--r--stdio-common/Versions5
-rw-r--r--stdio-common/_i18n_number.h25
-rw-r--r--stdio-common/_itoa.c2
-rw-r--r--stdio-common/_itowa.c2
-rw-r--r--stdio-common/_itowa.h2
-rw-r--r--stdio-common/asprintf.c2
-rw-r--r--stdio-common/bits/printf-ldbl.h2
-rw-r--r--stdio-common/bug-vfprintf-nargs.c2
-rw-r--r--stdio-common/bug16.c3
-rw-r--r--stdio-common/bug21.c2
-rw-r--r--stdio-common/bug25.c1
-rw-r--r--stdio-common/bug26.c2
-rw-r--r--stdio-common/bug3.c2
-rw-r--r--stdio-common/bug4.c2
-rw-r--r--stdio-common/bug5.c4
-rw-r--r--stdio-common/bug7.c22
-rw-r--r--stdio-common/ctermid.c2
-rw-r--r--stdio-common/cuserid.c2
-rw-r--r--stdio-common/dprintf.c2
-rw-r--r--stdio-common/errlist.c6
-rw-r--r--stdio-common/errnobug.c2
-rw-r--r--stdio-common/flockfile.c2
-rw-r--r--stdio-common/fprintf.c2
-rw-r--r--stdio-common/fscanf.c2
-rw-r--r--stdio-common/ftrylockfile.c2
-rw-r--r--stdio-common/funlockfile.c2
-rw-r--r--stdio-common/fxprintf.c80
-rw-r--r--stdio-common/gentempfd.c26
-rw-r--r--stdio-common/getline.c10
-rw-r--r--stdio-common/getw.c2
-rw-r--r--stdio-common/isoc99_fscanf.c2
-rw-r--r--stdio-common/isoc99_scanf.c2
-rw-r--r--stdio-common/isoc99_sscanf.c2
-rw-r--r--stdio-common/isoc99_vfscanf.c4
-rw-r--r--stdio-common/isoc99_vscanf.c4
-rw-r--r--stdio-common/isoc99_vsscanf.c4
-rw-r--r--stdio-common/itoa-digits.c2
-rw-r--r--stdio-common/itoa-udigits.c2
-rw-r--r--stdio-common/itowa-digits.c2
-rw-r--r--stdio-common/perror.c2
-rw-r--r--stdio-common/printf-parse.h2
-rw-r--r--stdio-common/printf-parsemb.c3
-rw-r--r--stdio-common/printf-prs.c2
-rw-r--r--stdio-common/printf.c2
-rw-r--r--stdio-common/printf.h15
-rw-r--r--stdio-common/printf_fp.c260
-rw-r--r--stdio-common/printf_fphex.c145
-rw-r--r--stdio-common/printf_size.c93
-rw-r--r--stdio-common/psiginfo.c7
-rw-r--r--stdio-common/psignal.c2
-rw-r--r--stdio-common/putw.c2
-rw-r--r--stdio-common/reg-modifier.c2
-rw-r--r--stdio-common/reg-printf.c4
-rw-r--r--stdio-common/reg-type.c2
-rw-r--r--stdio-common/remove.c2
-rw-r--r--stdio-common/rename.c2
-rw-r--r--stdio-common/renameat.c7
-rw-r--r--stdio-common/renameat2.c30
-rw-r--r--stdio-common/scanf.c2
-rw-r--r--stdio-common/scanf11.c2
-rw-r--r--stdio-common/scanf14.c2
-rw-r--r--stdio-common/scanf4.c2
-rw-r--r--stdio-common/scanf7.c2
-rw-r--r--stdio-common/siglist.c2
-rw-r--r--stdio-common/snprintf.c3
-rw-r--r--stdio-common/sprintf.c2
-rw-r--r--stdio-common/sscanf.c2
-rw-r--r--stdio-common/stdio_ext.h2
-rw-r--r--stdio-common/stdio_lim.h.in33
-rw-r--r--stdio-common/tempnam.c2
-rw-r--r--stdio-common/tempname.c2
-rw-r--r--stdio-common/test-fseek.c4
-rw-r--r--stdio-common/test-popen.c10
-rw-r--r--stdio-common/test-vfprintf.c9
-rw-r--r--stdio-common/test_rdwr.c4
-rw-r--r--stdio-common/tmpfile.c28
-rw-r--r--stdio-common/tmpfile64.c2
-rw-r--r--stdio-common/tmpnam.c2
-rw-r--r--stdio-common/tmpnam_r.c2
-rw-r--r--stdio-common/tst-fdopen.c11
-rw-r--r--stdio-common/tst-fgets.c2
-rw-r--r--stdio-common/tst-fileno.c2
-rw-r--r--stdio-common/tst-fmemopen.c2
-rw-r--r--stdio-common/tst-fmemopen2.c3
-rw-r--r--stdio-common/tst-fmemopen3.c120
-rw-r--r--stdio-common/tst-fmemopen4.c71
-rw-r--r--stdio-common/tst-fphex-wide.c2
-rw-r--r--stdio-common/tst-fphex.c7
-rw-r--r--stdio-common/tst-fseek.c2
-rw-r--r--stdio-common/tst-fwrite.c2
-rw-r--r--stdio-common/tst-gets.c7
-rw-r--r--stdio-common/tst-long-dbl-fphex.c7
-rw-r--r--stdio-common/tst-popen.c2
-rw-r--r--stdio-common/tst-printf-bz18872.sh2
-rw-r--r--stdio-common/tst-printf-round.c7
-rw-r--r--stdio-common/tst-printf.c84
-rw-r--r--stdio-common/tst-printf.sh52
-rw-r--r--stdio-common/tst-printfsz-islongdouble.c51
-rw-r--r--stdio-common/tst-printfsz-islongdouble.sh38
-rw-r--r--stdio-common/tst-printfsz.c2
-rw-r--r--stdio-common/tst-put-error.c2
-rw-r--r--stdio-common/tst-renameat2.c204
-rw-r--r--stdio-common/tst-scanf-round.c51
-rw-r--r--stdio-common/tst-sprintf.c2
-rw-r--r--stdio-common/tst-sprintf3.c16
-rw-r--r--stdio-common/tst-sscanf.c9
-rw-r--r--stdio-common/tst-swprintf.c4
-rw-r--r--stdio-common/tst-tmpnam.c2
-rwxr-xr-xstdio-common/tst-unbputc.sh2
-rw-r--r--stdio-common/tst-ungetc.c11
-rw-r--r--stdio-common/tst-unlockedio.c4
-rw-r--r--stdio-common/tst-vfprintf-mbs-prec.c543
-rw-r--r--stdio-common/tst-vfprintf-user-type.c220
-rw-r--r--stdio-common/tst-vfprintf-width-prec.c108
-rw-r--r--stdio-common/tstdiomisc.c40
-rw-r--r--stdio-common/tstgetln.c4
-rw-r--r--stdio-common/tstscanf.c5
-rw-r--r--stdio-common/vfprintf.c260
-rw-r--r--stdio-common/vfscanf.c88
-rw-r--r--stdio-common/vprintf.c2
121 files changed, 2277 insertions, 797 deletions
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index cc79d347bc..a10f12ab3c 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991-2016 Free Software Foundation, Inc.
+# Copyright (C) 1991-2018 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
@@ -35,11 +35,11 @@ routines := \
perror psignal \
tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \
getline getw putw \
- remove rename renameat \
+ remove rename renameat renameat2 \
flockfile ftrylockfile funlockfile \
isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \
isoc99_vsscanf \
- psiginfo
+ psiginfo gentempfd
aux := errlist siglist printf-parsemb printf-parsewc fxprintf
@@ -58,16 +58,23 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \
bug25 tst-printf-round bug23-2 bug23-3 bug23-4 bug26 tst-fmemopen3 \
- tst-printf-bz18872
+ tst-printf-bz18872 tst-vfprintf-width-prec tst-fmemopen4 \
+ tst-vfprintf-user-type \
+ tst-vfprintf-mbs-prec \
+ tst-scanf-round \
+ tst-renameat2 \
-test-srcs = tst-unbputc tst-printf
+test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)tst-unbputc.out $(objpfx)tst-printf.out \
$(objpfx)tst-printf-bz18872-mem.out \
- $(objpfx)tst-setvbuf1-cmp.out
+ $(objpfx)tst-setvbuf1-cmp.out \
+ $(objpfx)tst-vfprintf-width-prec-mem.out \
+ $(objpfx)tst-printfsz-islongdouble.out
generated += tst-printf-bz18872.c tst-printf-bz18872.mtrace \
- tst-printf-bz18872-mem.out
+ tst-printf-bz18872-mem.out \
+ tst-vfprintf-width-prec.mtrace tst-vfprintf-width-prec-mem.out
endif
include ../Rules
@@ -83,16 +90,24 @@ $(objpfx)tst-grouping.out: $(gen-locales)
$(objpfx)tst-sprintf.out: $(gen-locales)
$(objpfx)tst-sscanf.out: $(gen-locales)
$(objpfx)tst-swprintf.out: $(gen-locales)
+$(objpfx)tst-vfprintf-mbs-prec.out: $(gen-locales)
endif
tst-printf-bz18872-ENV = MALLOC_TRACE=$(objpfx)tst-printf-bz18872.mtrace
+tst-vfprintf-width-prec-ENV = \
+ MALLOC_TRACE=$(objpfx)tst-vfprintf-width-prec.mtrace
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
- $(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' > $@; \
$(evaluate-test)
$(objpfx)tst-printf.out: tst-printf.sh $(objpfx)tst-printf
- $(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
+ $(SHELL) $< $(common-objpfx) '$(test-program-prefix)' > $@; \
+ $(evaluate-test)
+
+$(objpfx)tst-printfsz-islongdouble.out: \
+ tst-printfsz-islongdouble.sh $(objpfx)tst-printfsz-islongdouble
+ $(SHELL) $^ '$(test-program-prefix)' $@; \
$(evaluate-test)
# We generate this source because it requires a printf invocation with
@@ -100,19 +115,19 @@ $(objpfx)tst-printf.out: tst-printf.sh $(objpfx)tst-printf
$(objpfx)tst-printf-bz18872.c: tst-printf-bz18872.sh
rm -f $@ && $(BASH) $^ > $@.new && mv $@.new $@
-$(objpfx)tst-printf-bz18872-mem.out: $(objpfx)tst-printf-bz18872.out
- $(common-objpfx)malloc/mtrace $(objpfx)tst-printf-bz18872.mtrace > $@; \
+$(objpfx)tst-%-mem.out: $(objpfx)tst-%.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-$*.mtrace > $@; \
$(evaluate-test)
-CFLAGS-vfprintf.c = -Wno-uninitialized
-CFLAGS-vfwprintf.c = -Wno-uninitialized
+CFLAGS-vfprintf.c += -Wno-uninitialized
+CFLAGS-vfwprintf.c += -Wno-uninitialized
-CFLAGS-tmpfile.c = -fexceptions
-CFLAGS-tmpfile64.c = -fexceptions
-CFLAGS-tempname.c = -fexceptions
-CFLAGS-psignal.c = -fexceptions
-CFLAGS-vprintf.c = -fexceptions
-CFLAGS-cuserid.c = -fexceptions
+CFLAGS-tmpfile.c += -fexceptions
+CFLAGS-tmpfile64.c += -fexceptions
+CFLAGS-tempname.c += -fexceptions
+CFLAGS-psignal.c += -fexceptions
+CFLAGS-vprintf.c += -fexceptions
+CFLAGS-cuserid.c += -fexceptions
CFLAGS-vfprintf.c += -fexceptions
CFLAGS-fprintf.c += -fexceptions
@@ -126,17 +141,27 @@ CFLAGS-isoc99_vfscanf.c += -fexceptions
CFLAGS-isoc99_vscanf.c += -fexceptions
CFLAGS-isoc99_fscanf.c += -fexceptions
CFLAGS-isoc99_scanf.c += -fexceptions
-CFLAGS-errlist.c = $(fno-unit-at-a-time)
-CFLAGS-siglist.c = $(fno-unit-at-a-time)
+CFLAGS-errlist.c += $(fno-unit-at-a-time)
+CFLAGS-siglist.c += $(fno-unit-at-a-time)
# The following is a hack since we must compile scanf1{5,7}.c without any
# GNU extension. The latter are needed, though, when internal headers
# are used. So made sure we see the installed headers first.
-CFLAGS-scanf15.c = -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \
+CFLAGS-scanf15.c += -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \
-I../wctype
-CFLAGS-scanf17.c = -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \
+CFLAGS-scanf17.c += -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \
-I../wctype
+CFLAGS-bug3.c += -DOBJPFX=\"$(objpfx)\"
+CFLAGS-bug4.c += -DOBJPFX=\"$(objpfx)\"
+CFLAGS-bug5.c += -DOBJPFX=\"$(objpfx)\"
+CFLAGS-test-fseek.c += -DOBJPFX=\"$(objpfx)\"
+CFLAGS-test-popen.c += -DOBJPFX=\"$(objpfx)\"
+CFLAGS-test_rdwr.c += -DOBJPFX=\"$(objpfx)\"
+
+# tst-gets.c tests a deprecated function.
+CFLAGS-tst-gets.c += -Wno-deprecated-declarations
+
CPPFLAGS += $(libio-mtsafe)
$(objpfx)tst-setvbuf1.out: /dev/null $(objpfx)tst-setvbuf1
@@ -148,3 +173,4 @@ $(objpfx)tst-setvbuf1-cmp.out: tst-setvbuf1.expect $(objpfx)tst-setvbuf1.out
$(evaluate-test)
$(objpfx)tst-printf-round: $(libm)
+$(objpfx)tst-scanf-round: $(libm)
diff --git a/stdio-common/Versions b/stdio-common/Versions
index 06b96f678a..b8217578c8 100644
--- a/stdio-common/Versions
+++ b/stdio-common/Versions
@@ -57,8 +57,13 @@ libc {
psiginfo;
register_printf_modifier; register_printf_type; register_printf_specifier;
}
+ GLIBC_2.28 {
+ renameat2;
+ }
GLIBC_PRIVATE {
# global variables
_itoa_lower_digits;
+ # Used in libcrypt.
+ __snprintf;
}
}
diff --git a/stdio-common/_i18n_number.h b/stdio-common/_i18n_number.h
index 324297be71..40797715c8 100644
--- a/stdio-common/_i18n_number.h
+++ b/stdio-common/_i18n_number.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.org>, 2000.
@@ -19,6 +19,7 @@
#include <stdbool.h>
#include <wchar.h>
#include <wctype.h>
+#include <scratch_buffer.h>
#include "../locale/outdigits.h"
#include "../locale/outdigitswc.h"
@@ -65,17 +66,13 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end)
/* Copy existing string so that nothing gets overwritten. */
CHAR_T *src;
- bool use_alloca = __libc_use_alloca ((rear_ptr - w) * sizeof (CHAR_T));
- if (__builtin_expect (use_alloca, true))
- src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T));
- else
- {
- src = (CHAR_T *) malloc ((rear_ptr - w) * sizeof (CHAR_T));
- if (src == NULL)
- /* If we cannot allocate the memory don't rewrite the string.
- It is better than nothing. */
- return w;
- }
+ struct scratch_buffer buffer;
+ scratch_buffer_init (&buffer);
+ if (!scratch_buffer_set_array_size (&buffer, rear_ptr - w, sizeof (CHAR_T)))
+ /* If we cannot allocate the memory don't rewrite the string.
+ It is better than nothing. */
+ return w;
+ src = buffer.data;
CHAR_T *s = (CHAR_T *) __mempcpy (src, w,
(rear_ptr - w) * sizeof (CHAR_T));
@@ -110,8 +107,6 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end)
}
}
- if (! use_alloca)
- free (src);
-
+ scratch_buffer_free (&buffer);
return w;
}
diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c
index b05c59b014..3749ee97e3 100644
--- a/stdio-common/_itoa.c
+++ b/stdio-common/_itoa.c
@@ -1,5 +1,5 @@
/* Internal function for converting integers to ASCII.
- Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ Copyright (C) 1994-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Torbjorn Granlund <tege@matematik.su.se>
and Ulrich Drepper <drepper@gnu.org>.
diff --git a/stdio-common/_itowa.c b/stdio-common/_itowa.c
index acbb870e97..531be71ab3 100644
--- a/stdio-common/_itowa.c
+++ b/stdio-common/_itowa.c
@@ -1,5 +1,5 @@
/* Internal function for converting integers to ASCII.
- Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ Copyright (C) 1994-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Torbjorn Granlund <tege@matematik.su.se>
and Ulrich Drepper <drepper@gnu.org>.
diff --git a/stdio-common/_itowa.h b/stdio-common/_itowa.h
index a5bf6d143d..b0c8f99c49 100644
--- a/stdio-common/_itowa.h
+++ b/stdio-common/_itowa.h
@@ -1,5 +1,5 @@
/* Internal function for converting integers to ASCII.
- Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ Copyright (C) 1994-2018 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
diff --git a/stdio-common/asprintf.c b/stdio-common/asprintf.c
index 5500aa90ce..bff858e657 100644
--- a/stdio-common/asprintf.c
+++ b/stdio-common/asprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/bits/printf-ldbl.h b/stdio-common/bits/printf-ldbl.h
index aaa092158a..d61a68253e 100644
--- a/stdio-common/bits/printf-ldbl.h
+++ b/stdio-common/bits/printf-ldbl.h
@@ -1,5 +1,5 @@
/* -mlong-double-64 compatibility mode for <printf.h> functions.
- Copyright (C) 2006-2016 Free Software Foundation, Inc.
+ Copyright (C) 2006-2018 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
diff --git a/stdio-common/bug-vfprintf-nargs.c b/stdio-common/bug-vfprintf-nargs.c
index f3cfb4a23b..f06137968b 100644
--- a/stdio-common/bug-vfprintf-nargs.c
+++ b/stdio-common/bug-vfprintf-nargs.c
@@ -1,5 +1,5 @@
/* Test for vfprintf nargs allocation overflow (BZ #13656).
- Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Copyright (C) 2012-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Kees Cook <keescook@chromium.org>, 2012.
diff --git a/stdio-common/bug16.c b/stdio-common/bug16.c
index 1112c39d05..91bc452826 100644
--- a/stdio-common/bug16.c
+++ b/stdio-common/bug16.c
@@ -1,3 +1,4 @@
+#include <array_length.h>
#include <stdio.h>
#include <string.h>
@@ -19,7 +20,7 @@ do_test (void)
char buf[100];
int ret = 0;
- for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+ for (size_t i = 0; i < array_length (tests); ++i)
{
snprintf (buf, sizeof (buf), "%.0LA", tests[i].val);
diff --git a/stdio-common/bug21.c b/stdio-common/bug21.c
index ca27272ba1..7a8c6a3542 100644
--- a/stdio-common/bug21.c
+++ b/stdio-common/bug21.c
@@ -1,5 +1,5 @@
#include <stdio.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
static int
do_test (void)
diff --git a/stdio-common/bug25.c b/stdio-common/bug25.c
index 30c133974b..617f21ab71 100644
--- a/stdio-common/bug25.c
+++ b/stdio-common/bug25.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <unistd.h>
static const char expected[] = "\
diff --git a/stdio-common/bug26.c b/stdio-common/bug26.c
index 4994f9c616..6b31f28920 100644
--- a/stdio-common/bug26.c
+++ b/stdio-common/bug26.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2013-2018 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
diff --git a/stdio-common/bug3.c b/stdio-common/bug3.c
index 6b2ed6b8e0..62a6cab330 100644
--- a/stdio-common/bug3.c
+++ b/stdio-common/bug3.c
@@ -6,7 +6,7 @@ main (void)
{
FILE *f;
int i;
- const char filename[] = "/tmp/bug3.test";
+ const char filename[] = OBJPFX "bug3.test";
f = fopen(filename, "w+");
for (i=0; i<9000; i++)
diff --git a/stdio-common/bug4.c b/stdio-common/bug4.c
index a0377862a5..cf7fe116eb 100644
--- a/stdio-common/bug4.c
+++ b/stdio-common/bug4.c
@@ -10,7 +10,7 @@ main (int argc, char *argv[])
FILE *f;
int i;
char buffer[31];
- const char filename[] = "/tmp/bug4.test";
+ const char filename[] = OBJPFX "bug4.test";
while ((i = getopt (argc, argv, "rw")) != -1)
switch (i)
diff --git a/stdio-common/bug5.c b/stdio-common/bug5.c
index f655845891..7bfe9b2b8d 100644
--- a/stdio-common/bug5.c
+++ b/stdio-common/bug5.c
@@ -14,8 +14,8 @@ main (void)
{
FILE *in;
FILE *out;
- static char inname[] = "/tmp/bug5.in";
- static char outname[] = "/tmp/bug5.out";
+ static char inname[] = OBJPFX "bug5test.in";
+ static char outname[] = OBJPFX "bug5test.out";
char *printbuf;
size_t i;
int result;
diff --git a/stdio-common/bug7.c b/stdio-common/bug7.c
index 2b1efe3bc6..c9c2ef5139 100644
--- a/stdio-common/bug7.c
+++ b/stdio-common/bug7.c
@@ -1,21 +1,25 @@
/* Regression test for fseek and freopen bugs. */
#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
int
main (int argc, char *argv[])
{
int lose = 0;
- char filename[L_tmpnam];
+ char filename[] = "/tmp/bug7.XXXXXX";
FILE *fp;
- if (tmpnam (filename) == NULL)
+ int fd = mkstemp (filename);
+ if (fd == -1)
{
- printf ("tmpnam failed\n");
+ printf ("mkstemp failed\n");
lose = 1;
}
else
{
+ close (fd);
fp = fopen (filename, "w+");
fprintf (fp, "Hello world!\n");
fflush (fp);
@@ -32,17 +36,21 @@ main (int argc, char *argv[])
{
FILE *file1;
FILE *file2;
- char filename1[L_tmpnam];
- char filename2[L_tmpnam];
+ char filename1[] = "/tmp/bug7.XXXXXX";
+ char filename2[] = "/tmp/bug7.XXXXXX";
int ch;
- if (tmpnam (filename1) == NULL || tmpnam (filename2) == NULL)
+ int fd1 = mkstemp (filename1);
+ int fd2 = mkstemp (filename2);
+ if (fd1 == -1 || fd2 == -1)
{
- printf ("tmpnam failed\n");
+ printf ("mkstemp failed\n");
lose = 1;
}
else
{
+ close (fd1);
+ close (fd2);
file1 = fopen (filename1, "w");
fclose (file1);
diff --git a/stdio-common/ctermid.c b/stdio-common/ctermid.c
index d1577897d7..f4af8e98e9 100644
--- a/stdio-common/ctermid.c
+++ b/stdio-common/ctermid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/cuserid.c b/stdio-common/cuserid.c
index 574b46478f..bfae5bc038 100644
--- a/stdio-common/cuserid.c
+++ b/stdio-common/cuserid.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/dprintf.c b/stdio-common/dprintf.c
index e9762e2230..11bd12b838 100644
--- a/stdio-common/dprintf.c
+++ b/stdio-common/dprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c
index 440a8e1920..b94b4b4422 100644
--- a/stdio-common/errlist.c
+++ b/stdio-common/errlist.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -15,9 +15,9 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <array_length.h>
#include <stddef.h>
-
const char *const _sys_errlist[] =
{
"Error 0", /* 0 */
@@ -33,4 +33,4 @@ const char *const _sys_errlist[] =
"Too many open files", /* 10 = EMFILE */
};
-const int _sys_nerr = sizeof (_sys_errlist) / sizeof (_sys_errlist[0]);
+const int _sys_nerr = array_length (_sys_errlist);
diff --git a/stdio-common/errnobug.c b/stdio-common/errnobug.c
index e046222875..7127c126fb 100644
--- a/stdio-common/errnobug.c
+++ b/stdio-common/errnobug.c
@@ -1,6 +1,6 @@
/* Regression test for reported old bug that errno is clobbered
by the first successful output to a stream on an unseekable object.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2018 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
diff --git a/stdio-common/flockfile.c b/stdio-common/flockfile.c
index 34c59d738e..60ddd34087 100644
--- a/stdio-common/flockfile.c
+++ b/stdio-common/flockfile.c
@@ -1,5 +1,5 @@
/* Lock I/O stream. Singlethreaded version.
- Copyright (C) 1996-2016 Free Software Foundation, Inc.
+ Copyright (C) 1996-2018 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
diff --git a/stdio-common/fprintf.c b/stdio-common/fprintf.c
index 1c41b0f5a4..2bbf14bf5d 100644
--- a/stdio-common/fprintf.c
+++ b/stdio-common/fprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/fscanf.c b/stdio-common/fscanf.c
index 4c10444a0a..b60a2a3b81 100644
--- a/stdio-common/fscanf.c
+++ b/stdio-common/fscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/ftrylockfile.c b/stdio-common/ftrylockfile.c
index fe871e1c5e..02e426b6f1 100644
--- a/stdio-common/ftrylockfile.c
+++ b/stdio-common/ftrylockfile.c
@@ -1,5 +1,5 @@
/* Try locking I/O stream. Singlethreaded version.
- Copyright (C) 1996-2016 Free Software Foundation, Inc.
+ Copyright (C) 1996-2018 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
diff --git a/stdio-common/funlockfile.c b/stdio-common/funlockfile.c
index 95fb06850b..a59a18c9a4 100644
--- a/stdio-common/funlockfile.c
+++ b/stdio-common/funlockfile.c
@@ -1,5 +1,5 @@
/* Unlock I/O stream. Singlethreaded version.
- Copyright (C) 1996-2016 Free Software Foundation, Inc.
+ Copyright (C) 1996-2018 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
diff --git a/stdio-common/fxprintf.c b/stdio-common/fxprintf.c
index 097265167d..c4a1146b20 100644
--- a/stdio-common/fxprintf.c
+++ b/stdio-common/fxprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2005-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.org>.
@@ -16,14 +16,50 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <assert.h>
-#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
-#include <wchar.h>
+#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include <libioP.h>
+static int
+locked_vfxprintf (FILE *fp, const char *fmt, va_list ap)
+{
+ if (_IO_fwide (fp, 0) <= 0)
+ return _IO_vfprintf (fp, fmt, ap);
+
+ /* We must convert the narrow format string to a wide one.
+ Each byte can produce at most one wide character. */
+ wchar_t *wfmt;
+ mbstate_t mbstate;
+ int res;
+ int used_malloc = 0;
+ size_t len = strlen (fmt) + 1;
+
+ if (__glibc_unlikely (len > SIZE_MAX / sizeof (wchar_t)))
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+ if (__libc_use_alloca (len * sizeof (wchar_t)))
+ wfmt = alloca (len * sizeof (wchar_t));
+ else if ((wfmt = malloc (len * sizeof (wchar_t))) == NULL)
+ return -1;
+ else
+ used_malloc = 1;
+
+ memset (&mbstate, 0, sizeof mbstate);
+ res = __mbsrtowcs (wfmt, &fmt, len, &mbstate);
+
+ if (res != -1)
+ res = _IO_vfwprintf (fp, wfmt, ap);
+
+ if (used_malloc)
+ free (wfmt);
+
+ return res;
+}
int
__fxprintf (FILE *fp, const char *fmt, ...)
@@ -33,23 +69,31 @@ __fxprintf (FILE *fp, const char *fmt, ...)
va_list ap;
va_start (ap, fmt);
+ _IO_flockfile (fp);
- int res;
- if (_IO_fwide (fp, 0) > 0)
- {
- size_t len = strlen (fmt) + 1;
- wchar_t wfmt[len];
- for (size_t i = 0; i < len; ++i)
- {
- assert (isascii (fmt[i]));
- wfmt[i] = fmt[i];
- }
- res = __vfwprintf (fp, wfmt, ap);
- }
- else
- res = _IO_vfprintf (fp, fmt, ap);
+ int res = locked_vfxprintf (fp, fmt, ap);
+ _IO_funlockfile (fp);
va_end (ap);
+ return res;
+}
+int
+__fxprintf_nocancel (FILE *fp, const char *fmt, ...)
+{
+ if (fp == NULL)
+ fp = stderr;
+
+ va_list ap;
+ va_start (ap, fmt);
+ _IO_flockfile (fp);
+ int save_flags2 = fp->_flags2;
+ fp->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+ int res = locked_vfxprintf (fp, fmt, ap);
+
+ fp->_flags2 = save_flags2;
+ _IO_funlockfile (fp);
+ va_end (ap);
return res;
}
diff --git a/stdio-common/gentempfd.c b/stdio-common/gentempfd.c
new file mode 100644
index 0000000000..d45cbb8588
--- /dev/null
+++ b/stdio-common/gentempfd.c
@@ -0,0 +1,26 @@
+/* Generate a temporary file descriptor. Generic/POSIX version.
+ Copyright (C) 2017-2018 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+
+int
+__gen_tempfd (int flags)
+{
+ return -1;
+}
+libc_hidden_def (__gen_tempfd)
diff --git a/stdio-common/getline.c b/stdio-common/getline.c
index 39e4a39910..77f77c2400 100644
--- a/stdio-common/getline.c
+++ b/stdio-common/getline.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -17,19 +17,15 @@
#include <stddef.h>
#include <stdio.h>
+#include "../libio/libioP.h"
#undef __getline
-#include "../libio/libioP.h"
-#undef ssize_t
-#define ssize_t _IO_ssize_t
-#define __getdelim _IO_getdelim
-
/* Like getdelim, but always looks for a newline. */
ssize_t
__getline (char **lineptr, size_t *n, FILE *stream)
{
- return __getdelim (lineptr, n, '\n', stream);
+ return _IO_getdelim (lineptr, n, '\n', stream);
}
weak_alias (__getline, getline)
diff --git a/stdio-common/getw.c b/stdio-common/getw.c
index abf5459e6f..781a0dc97b 100644
--- a/stdio-common/getw.c
+++ b/stdio-common/getw.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/isoc99_fscanf.c b/stdio-common/isoc99_fscanf.c
index 6fe490a69d..9cdf85e679 100644
--- a/stdio-common/isoc99_fscanf.c
+++ b/stdio-common/isoc99_fscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/isoc99_scanf.c b/stdio-common/isoc99_scanf.c
index 51f6c3c1a1..bf7dbe86bb 100644
--- a/stdio-common/isoc99_scanf.c
+++ b/stdio-common/isoc99_scanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/isoc99_sscanf.c b/stdio-common/isoc99_sscanf.c
index 57207dfcf4..56a60a2c05 100644
--- a/stdio-common/isoc99_sscanf.c
+++ b/stdio-common/isoc99_sscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/isoc99_vfscanf.c b/stdio-common/isoc99_vfscanf.c
index d4dc4360dd..b80e05f8db 100644
--- a/stdio-common/isoc99_vfscanf.c
+++ b/stdio-common/isoc99_vfscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -21,7 +21,7 @@
/* Read formatted input from STREAM according to the format string FORMAT. */
/* VARARGS2 */
int
-__isoc99_vfscanf (FILE *stream, const char *format, _IO_va_list args)
+__isoc99_vfscanf (FILE *stream, const char *format, va_list args)
{
int done;
diff --git a/stdio-common/isoc99_vscanf.c b/stdio-common/isoc99_vscanf.c
index 2df433cbef..0b747f85ba 100644
--- a/stdio-common/isoc99_vscanf.c
+++ b/stdio-common/isoc99_vscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -21,7 +21,7 @@
/* Read formatted input from STDIN according to the format string FORMAT. */
/* VARARGS2 */
int
-__isoc99_vscanf (const char *format, _IO_va_list args)
+__isoc99_vscanf (const char *format, va_list args)
{
int done;
diff --git a/stdio-common/isoc99_vsscanf.c b/stdio-common/isoc99_vsscanf.c
index 720f122083..ac85ef2d0d 100644
--- a/stdio-common/isoc99_vsscanf.c
+++ b/stdio-common/isoc99_vsscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2018 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
@@ -29,7 +29,7 @@
#include "../libio/strfile.h"
int
-__isoc99_vsscanf (const char *string, const char *format, _IO_va_list args)
+__isoc99_vsscanf (const char *string, const char *format, va_list args)
{
int ret;
_IO_strfile sf;
diff --git a/stdio-common/itoa-digits.c b/stdio-common/itoa-digits.c
index b819abc0ac..00619521ed 100644
--- a/stdio-common/itoa-digits.c
+++ b/stdio-common/itoa-digits.c
@@ -1,5 +1,5 @@
/* Digits.
- Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ Copyright (C) 1994-2018 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
diff --git a/stdio-common/itoa-udigits.c b/stdio-common/itoa-udigits.c
index ac303ca5a2..607b08ee3b 100644
--- a/stdio-common/itoa-udigits.c
+++ b/stdio-common/itoa-udigits.c
@@ -1,5 +1,5 @@
/* Digits.
- Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ Copyright (C) 1994-2018 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
diff --git a/stdio-common/itowa-digits.c b/stdio-common/itowa-digits.c
index 399d57e981..5727a4ec88 100644
--- a/stdio-common/itowa-digits.c
+++ b/stdio-common/itowa-digits.c
@@ -1,5 +1,5 @@
/* Digits.
- Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ Copyright (C) 1994-2018 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
diff --git a/stdio-common/perror.c b/stdio-common/perror.c
index c2bba6800e..b6836c93f6 100644
--- a/stdio-common/perror.c
+++ b/stdio-common/perror.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/printf-parse.h b/stdio-common/printf-parse.h
index 0f21fedc3d..e07186ec83 100644
--- a/stdio-common/printf-parse.h
+++ b/stdio-common/printf-parse.h
@@ -1,5 +1,5 @@
/* Internal header for parsing printf format strings.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
This file is part of th GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/stdio-common/printf-parsemb.c b/stdio-common/printf-parsemb.c
index 66cef10b20..ecbc4e3169 100644
--- a/stdio-common/printf-parsemb.c
+++ b/stdio-common/printf-parsemb.c
@@ -1,5 +1,5 @@
/* Helper functions for parsing printf format strings.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
This file is part of th GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -79,6 +79,7 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn,
spec->info.extra = 0;
spec->info.pad = ' ';
spec->info.wide = sizeof (UCHAR_T) > 1;
+ spec->info.is_binary128 = 0;
/* Test for positional argument. */
if (ISDIGIT (*format))
diff --git a/stdio-common/printf-prs.c b/stdio-common/printf-prs.c
index b51b567f10..93b872a875 100644
--- a/stdio-common/printf-prs.c
+++ b/stdio-common/printf-prs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/printf.c b/stdio-common/printf.c
index acc67d2740..205b5e42df 100644
--- a/stdio-common/printf.c
+++ b/stdio-common/printf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/printf.h b/stdio-common/printf.h
index d731216197..06d674359a 100644
--- a/stdio-common/printf.h
+++ b/stdio-common/printf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -22,11 +22,12 @@
__BEGIN_DECLS
-#define __need_FILE
-#include <stdio.h>
+#include <bits/types/FILE.h>
+
#define __need_size_t
#define __need_wchar_t
#include <stddef.h>
+
#include <stdarg.h>
@@ -47,7 +48,9 @@ struct printf_info
unsigned int is_char:1; /* hh flag. */
unsigned int wide:1; /* Nonzero for wide character streams. */
unsigned int i18n:1; /* I flag. */
- unsigned int __pad:4; /* Unused so far. */
+ unsigned int is_binary128:1; /* Floating-point argument is ABI-compatible
+ with IEC 60559 binary128. */
+ unsigned int __pad:3; /* Unused so far. */
unsigned short int user; /* Bits for user-installed modifiers. */
wchar_t pad; /* Padding character. */
};
@@ -111,13 +114,13 @@ extern int register_printf_function (int __spec, printf_function __func,
it returns a positive value representing the bit set in the USER
field in 'struct printf_info'. */
-extern int register_printf_modifier (const wchar_t *__str) __wur __THROW;
+extern int register_printf_modifier (const wchar_t *__str) __THROW __wur;
/* Register variable argument handler for user type. The return value
is to be used in ARGINFO functions to signal the use of the
type. */
-extern int register_printf_type (printf_va_arg_function __fct) __wur __THROW;
+extern int register_printf_type (printf_va_arg_function __fct) __THROW __wur;
/* Parse FMT, and fill in N elements of ARGTYPES with the
diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index 4134f8ab89..66ab59bad2 100644
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -1,5 +1,5 @@
/* Floating point output for `printf'.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
@@ -21,6 +21,7 @@
/* The gmp headers need some configuration frobs. */
#define HAVE_ALLOCA 1
+#include <array_length.h>
#include <libioP.h>
#include <alloca.h>
#include <ctype.h>
@@ -55,17 +56,12 @@
#endif
#include <assert.h>
-/* This defines make it possible to use the same code for GNU C library and
- the GNU I/O library. */
#define PUT(f, s, n) _IO_sputn (f, s, n)
#define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
-/* We use this file GNU C library and GNU I/O library. So make
- names equal. */
#undef putc
#define putc(c, f) (wide \
? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
-#define size_t _IO_size_t
-#define FILE _IO_FILE
+
/* Macros for doing the actual output. */
@@ -139,14 +135,11 @@ extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
int *expt, int *is_neg,
long double value);
-extern unsigned int __guess_grouping (unsigned int intdig_max,
- const char *grouping);
static wchar_t *group_number (wchar_t *buf, wchar_t *bufend,
unsigned int intdig_no, const char *grouping,
- wchar_t thousands_sep, int ngroups)
- internal_function;
+ wchar_t thousands_sep, int ngroups);
struct hack_digit_param
{
@@ -209,15 +202,18 @@ hack_digit (struct hack_digit_param *p)
}
int
-___printf_fp (FILE *fp,
- const struct printf_info *info,
- const void *const *args)
+__printf_fp_l (FILE *fp, locale_t loc,
+ const struct printf_info *info,
+ const void *const *args)
{
/* The floating-point value to output. */
union
{
double dbl;
- __long_double_t ldbl;
+ long double ldbl;
+#if __HAVE_DISTINCT_FLOAT128
+ _Float128 f128;
+#endif
}
fpnum;
@@ -234,9 +230,17 @@ ___printf_fp (FILE *fp,
const char *special = NULL;
const wchar_t *wspecial = NULL;
+ /* When _Float128 is enabled in the library and ABI-distinct from long
+ double, we need mp_limbs enough for any of them. */
+#if __HAVE_DISTINCT_FLOAT128
+# define GREATER_MANT_DIG FLT128_MANT_DIG
+#else
+# define GREATER_MANT_DIG LDBL_MANT_DIG
+#endif
/* We need just a few limbs for the input before shifting to the right
position. */
- mp_limb_t fp_input[(LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB];
+ mp_limb_t fp_input[(GREATER_MANT_DIG + BITS_PER_MP_LIMB - 1)
+ / BITS_PER_MP_LIMB];
/* We need to shift the contents of fp_input by this amount of bits. */
int to_shift = 0;
@@ -263,18 +267,19 @@ ___printf_fp (FILE *fp,
/* Figure out the decimal point character. */
if (info->extra == 0)
{
- decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
- decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
+ decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
+ decimalwc = _nl_lookup_word
+ (loc, LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
}
else
{
- decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
+ decimal = _nl_lookup (loc, LC_MONETARY, MON_DECIMAL_POINT);
if (*decimal == '\0')
- decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
- decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
+ decimal = _nl_lookup (loc, LC_NUMERIC, DECIMAL_POINT);
+ decimalwc = _nl_lookup_word (loc, LC_MONETARY,
_NL_MONETARY_DECIMAL_POINT_WC);
if (decimalwc == L'\0')
- decimalwc = _NL_CURRENT_WORD (LC_NUMERIC,
+ decimalwc = _nl_lookup_word (loc, LC_NUMERIC,
_NL_NUMERIC_DECIMAL_POINT_WC);
}
/* The decimal point character must not be zero. */
@@ -284,9 +289,9 @@ ___printf_fp (FILE *fp,
if (info->group)
{
if (info->extra == 0)
- grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+ grouping = _nl_lookup (loc, LC_NUMERIC, GROUPING);
else
- grouping = _NL_CURRENT (LC_MONETARY, MON_GROUPING);
+ grouping = _nl_lookup (loc, LC_MONETARY, MON_GROUPING);
if (*grouping <= 0 || *grouping == CHAR_MAX)
grouping = NULL;
@@ -296,19 +301,20 @@ ___printf_fp (FILE *fp,
if (wide)
{
if (info->extra == 0)
- thousands_sepwc =
- _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
+ thousands_sepwc = _nl_lookup_word
+ (loc, LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
else
thousands_sepwc =
- _NL_CURRENT_WORD (LC_MONETARY,
+ _nl_lookup_word (loc, LC_MONETARY,
_NL_MONETARY_THOUSANDS_SEP_WC);
}
else
{
if (info->extra == 0)
- thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
+ thousands_sep = _nl_lookup (loc, LC_NUMERIC, THOUSANDS_SEP);
else
- thousands_sep = _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP);
+ thousands_sep = _nl_lookup
+ (loc, LC_MONETARY, MON_THOUSANDS_SEP);
}
if ((wide && thousands_sepwc == L'\0')
@@ -325,94 +331,62 @@ ___printf_fp (FILE *fp,
else
grouping = NULL;
+#define PRINTF_FP_FETCH(FLOAT, VAR, SUFFIX, MANT_DIG) \
+ { \
+ (VAR) = *(const FLOAT *) args[0]; \
+ \
+ /* Check for special values: not a number or infinity. */ \
+ if (isnan (VAR)) \
+ { \
+ is_neg = signbit (VAR); \
+ if (isupper (info->spec)) \
+ { \
+ special = "NAN"; \
+ wspecial = L"NAN"; \
+ } \
+ else \
+ { \
+ special = "nan"; \
+ wspecial = L"nan"; \
+ } \
+ } \
+ else if (isinf (VAR)) \
+ { \
+ is_neg = signbit (VAR); \
+ if (isupper (info->spec)) \
+ { \
+ special = "INF"; \
+ wspecial = L"INF"; \
+ } \
+ else \
+ { \
+ special = "inf"; \
+ wspecial = L"inf"; \
+ } \
+ } \
+ else \
+ { \
+ p.fracsize = __mpn_extract_##SUFFIX \
+ (fp_input, array_length (fp_input), \
+ &p.exponent, &is_neg, VAR); \
+ to_shift = 1 + p.fracsize * BITS_PER_MP_LIMB - MANT_DIG; \
+ } \
+ }
+
/* Fetch the argument value. */
+#if __HAVE_DISTINCT_FLOAT128
+ if (info->is_binary128)
+ PRINTF_FP_FETCH (_Float128, fpnum.f128, float128, FLT128_MANT_DIG)
+ else
+#endif
#ifndef __NO_LONG_DOUBLE_MATH
if (info->is_long_double && sizeof (long double) > sizeof (double))
- {
- fpnum.ldbl = *(const long double *) args[0];
-
- /* Check for special values: not a number or infinity. */
- if (isnan (fpnum.ldbl))
- {
- is_neg = signbit (fpnum.ldbl);
- if (isupper (info->spec))
- {
- special = "NAN";
- wspecial = L"NAN";
- }
- else
- {
- special = "nan";
- wspecial = L"nan";
- }
- }
- else if (isinf (fpnum.ldbl))
- {
- is_neg = signbit (fpnum.ldbl);
- if (isupper (info->spec))
- {
- special = "INF";
- wspecial = L"INF";
- }
- else
- {
- special = "inf";
- wspecial = L"inf";
- }
- }
- else
- {
- p.fracsize = __mpn_extract_long_double (fp_input,
- (sizeof (fp_input) /
- sizeof (fp_input[0])),
- &p.exponent, &is_neg,
- fpnum.ldbl);
- to_shift = 1 + p.fracsize * BITS_PER_MP_LIMB - LDBL_MANT_DIG;
- }
- }
+ PRINTF_FP_FETCH (long double, fpnum.ldbl, long_double, LDBL_MANT_DIG)
else
-#endif /* no long double */
- {
- fpnum.dbl = *(const double *) args[0];
+#endif
+ PRINTF_FP_FETCH (double, fpnum.dbl, double, DBL_MANT_DIG)
- /* Check for special values: not a number or infinity. */
- if (isnan (fpnum.dbl))
- {
- is_neg = signbit (fpnum.dbl);
- if (isupper (info->spec))
- {
- special = "NAN";
- wspecial = L"NAN";
- }
- else
- {
- special = "nan";
- wspecial = L"nan";
- }
- }
- else if (isinf (fpnum.dbl))
- {
- is_neg = signbit (fpnum.dbl);
- if (isupper (info->spec))
- {
- special = "INF";
- wspecial = L"INF";
- }
- else
- {
- special = "inf";
- wspecial = L"inf";
- }
- }
- else
- {
- p.fracsize = __mpn_extract_double (fp_input,
- (sizeof (fp_input)
- / sizeof (fp_input[0])),
- &p.exponent, &is_neg, fpnum.dbl);
- to_shift = 1 + p.fracsize * BITS_PER_MP_LIMB - DBL_MANT_DIG;
- }
- }
+#undef PRINTF_FP_FETCH
if (special)
{
@@ -448,7 +422,8 @@ ___printf_fp (FILE *fp,
{
mp_size_t bignum_size = ((abs (p.exponent) + BITS_PER_MP_LIMB - 1)
/ BITS_PER_MP_LIMB
- + (LDBL_MANT_DIG / BITS_PER_MP_LIMB > 2 ? 8 : 4))
+ + (GREATER_MANT_DIG / BITS_PER_MP_LIMB > 2
+ ? 8 : 4))
* sizeof (mp_limb_t);
p.frac = (mp_limb_t *) alloca (bignum_size);
p.tmp = (mp_limb_t *) alloca (bignum_size);
@@ -463,7 +438,15 @@ ___printf_fp (FILE *fp,
{
/* |FP| >= 8.0. */
int scaleexpo = 0;
- int explog = LDBL_MAX_10_EXP_LOG;
+ int explog;
+#if __HAVE_DISTINCT_FLOAT128
+ if (info->is_binary128)
+ explog = FLT128_MAX_10_EXP_LOG;
+ else
+ explog = LDBL_MAX_10_EXP_LOG;
+#else
+ explog = LDBL_MAX_10_EXP_LOG;
+#endif
int exp10 = 0;
const struct mp_power *powers = &_fpioconst_pow10[explog + 1];
int cnt_h, cnt_l, i;
@@ -497,6 +480,27 @@ ___printf_fp (FILE *fp,
{
if (p.scalesize == 0)
{
+#if __HAVE_DISTINCT_FLOAT128
+ if ((FLT128_MANT_DIG
+ > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB)
+ && info->is_binary128)
+ {
+#define _FLT128_FPIO_CONST_SHIFT \
+ (((FLT128_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) \
+ - _FPIO_CONST_OFFSET)
+ /* 64bit const offset is not enough for
+ IEEE 854 quad long double (_Float128). */
+ p.tmpsize = powers->arraysize + _FLT128_FPIO_CONST_SHIFT;
+ memcpy (p.tmp + _FLT128_FPIO_CONST_SHIFT,
+ &__tens[powers->arrayoff],
+ p.tmpsize * sizeof (mp_limb_t));
+ MPN_ZERO (p.tmp, _FLT128_FPIO_CONST_SHIFT);
+ /* Adjust p.exponent, as scaleexpo will be this much
+ bigger too. */
+ p.exponent += _FLT128_FPIO_CONST_SHIFT * BITS_PER_MP_LIMB;
+ }
+ else
+#endif /* __HAVE_DISTINCT_FLOAT128 */
#ifndef __NO_LONG_DOUBLE_MATH
if (LDBL_MANT_DIG > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB
&& info->is_long_double)
@@ -637,7 +641,15 @@ ___printf_fp (FILE *fp,
{
/* |FP| < 1.0. */
int exp10 = 0;
- int explog = LDBL_MAX_10_EXP_LOG;
+ int explog;
+#if __HAVE_DISTINCT_FLOAT128
+ if (info->is_binary128)
+ explog = FLT128_MAX_10_EXP_LOG;
+ else
+ explog = LDBL_MAX_10_EXP_LOG;
+#else
+ explog = LDBL_MAX_10_EXP_LOG;
+#endif
const struct mp_power *powers = &_fpioconst_pow10[explog + 1];
/* Now shift the input value to its right place. */
@@ -1171,9 +1183,11 @@ ___printf_fp (FILE *fp,
size_t decimal_len;
size_t thousands_sep_len;
wchar_t *copywc;
- size_t factor = (info->i18n
- ? _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX)
- : 1);
+ size_t factor;
+ if (info->i18n)
+ factor = _nl_lookup_word (loc, LC_CTYPE, _NL_CTYPE_MB_CUR_MAX);
+ else
+ factor = 1;
decimal_len = strlen (decimal);
@@ -1244,8 +1258,17 @@ ___printf_fp (FILE *fp,
}
return done;
}
+libc_hidden_def (__printf_fp_l)
+
+int
+___printf_fp (FILE *fp, const struct printf_info *info,
+ const void *const *args)
+{
+ return __printf_fp_l (fp, _NL_CURRENT_LOCALE, info, args);
+}
ldbl_hidden_def (___printf_fp, __printf_fp)
ldbl_strong_alias (___printf_fp, __printf_fp)
+
/* Return the number of extra grouping characters that will be inserted
into a number with INTDIG_MAX integer digits. */
@@ -1290,7 +1313,6 @@ __guess_grouping (unsigned int intdig_max, const char *grouping)
Return the new end of buffer. */
static wchar_t *
-internal_function
group_number (wchar_t *buf, wchar_t *bufend, unsigned int intdig_no,
const char *grouping, wchar_t thousands_sep, int ngroups)
{
diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c
index 255c7e0372..df3956316d 100644
--- a/stdio-common/printf_fphex.c
+++ b/stdio-common/printf_fphex.c
@@ -1,5 +1,5 @@
/* Print floating point number in hexadecimal notation according to ISO C99.
- Copyright (C) 1997-2016 Free Software Foundation, Inc.
+ Copyright (C) 1997-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -17,6 +17,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <array_length.h>
#include <ctype.h>
#include <ieee754.h>
#include <math.h>
@@ -31,21 +32,24 @@
#include <stdbool.h>
#include <rounding-mode.h>
+#if __HAVE_DISTINCT_FLOAT128
+# include "ieee754_float128.h"
+# include <ldbl-128/printf_fphex_macros.h>
+# define PRINT_FPHEX_FLOAT128 \
+ PRINT_FPHEX (_Float128, fpnum.flt128, ieee854_float128, \
+ IEEE854_FLOAT128_BIAS)
+#endif
+
/* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */
#include <assert.h>
-/* This defines make it possible to use the same code for GNU C library and
- the GNU I/O library. */
#include <libioP.h>
#define PUT(f, s, n) _IO_sputn (f, s, n)
#define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
-/* We use this file GNU C library and GNU I/O library. So make
- names equal. */
#undef putc
#define putc(c, f) (wide \
? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
-#define size_t _IO_size_t
-#define FILE _IO_FILE
+
/* Macros for doing the actual output. */
@@ -94,6 +98,9 @@ __printf_fphex (FILE *fp,
{
union ieee754_double dbl;
long double ldbl;
+#if __HAVE_DISTINCT_FLOAT128
+ _Float128 flt128;
+#endif
}
fpnum;
@@ -157,82 +164,57 @@ __printf_fphex (FILE *fp,
/* The decimal point character must never be zero. */
assert (*decimal != '\0' && decimalwc != L'\0');
+#define PRINTF_FPHEX_FETCH(FLOAT, VAR) \
+ { \
+ (VAR) = *(const FLOAT *) args[0]; \
+ \
+ /* Check for special values: not a number or infinity. */ \
+ if (isnan (VAR)) \
+ { \
+ if (isupper (info->spec)) \
+ { \
+ special = "NAN"; \
+ wspecial = L"NAN"; \
+ } \
+ else \
+ { \
+ special = "nan"; \
+ wspecial = L"nan"; \
+ } \
+ } \
+ else \
+ { \
+ if (isinf (VAR)) \
+ { \
+ if (isupper (info->spec)) \
+ { \
+ special = "INF"; \
+ wspecial = L"INF"; \
+ } \
+ else \
+ { \
+ special = "inf"; \
+ wspecial = L"inf"; \
+ } \
+ } \
+ } \
+ negative = signbit (VAR); \
+ }
/* Fetch the argument value. */
+#if __HAVE_DISTINCT_FLOAT128
+ if (info->is_binary128)
+ PRINTF_FPHEX_FETCH (_Float128, fpnum.flt128)
+ else
+#endif
#ifndef __NO_LONG_DOUBLE_MATH
if (info->is_long_double && sizeof (long double) > sizeof (double))
- {
- fpnum.ldbl = *(const long double *) args[0];
-
- /* Check for special values: not a number or infinity. */
- if (isnan (fpnum.ldbl))
- {
- if (isupper (info->spec))
- {
- special = "NAN";
- wspecial = L"NAN";
- }
- else
- {
- special = "nan";
- wspecial = L"nan";
- }
- }
- else
- {
- if (isinf (fpnum.ldbl))
- {
- if (isupper (info->spec))
- {
- special = "INF";
- wspecial = L"INF";
- }
- else
- {
- special = "inf";
- wspecial = L"inf";
- }
- }
- }
- negative = signbit (fpnum.ldbl);
- }
+ PRINTF_FPHEX_FETCH (long double, fpnum.ldbl)
else
-#endif /* no long double */
- {
- fpnum.dbl.d = *(const double *) args[0];
+#endif
+ PRINTF_FPHEX_FETCH (double, fpnum.dbl.d)
- /* Check for special values: not a number or infinity. */
- if (isnan (fpnum.dbl.d))
- {
- if (isupper (info->spec))
- {
- special = "NAN";
- wspecial = L"NAN";
- }
- else
- {
- special = "nan";
- wspecial = L"nan";
- }
- }
- else
- {
- if (isinf (fpnum.dbl.d))
- {
- if (isupper (info->spec))
- {
- special = "INF";
- wspecial = L"INF";
- }
- else
- {
- special = "inf";
- wspecial = L"inf";
- }
- }
- }
- negative = signbit (fpnum.dbl.d);
- }
+#undef PRINTF_FPHEX_FETCH
if (special)
{
@@ -260,6 +242,11 @@ __printf_fphex (FILE *fp,
return done;
}
+#if __HAVE_DISTINCT_FLOAT128
+ if (info->is_binary128)
+ PRINT_FPHEX_FLOAT128;
+ else
+#endif
if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
{
/* We have 52 bits of mantissa plus one implicit digit. Since
@@ -329,8 +316,8 @@ __printf_fphex (FILE *fp,
/* Look for trailing zeroes. */
if (! zero_mantissa)
{
- wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]];
- numend = &numbuf[sizeof numbuf / sizeof numbuf[0]];
+ wnumend = array_end (wnumbuf);
+ numend = array_end (numbuf);
while (wnumend[-1] == L'0')
{
--wnumend;
diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c
index 154ba9da1b..7e073c50d4 100644
--- a/stdio-common/printf_size.c
+++ b/stdio-common/printf_size.c
@@ -1,5 +1,5 @@
/* Print size value using units for orders of magnitude.
- Copyright (C) 1997-2016 Free Software Foundation, Inc.
+ Copyright (C) 1997-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
Based on a proposal by Larry McVoy <lm@sgi.com>.
@@ -24,18 +24,12 @@
#include <printf.h>
#include <libioP.h>
-
-/* This defines make it possible to use the same code for GNU C library and
- the GNU I/O library. */
#define PUT(f, s, n) _IO_sputn (f, s, n)
#define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
-/* We use this file GNU C library and GNU I/O library. So make
- names equal. */
#undef putc
#define putc(c, f) (wide \
? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
-#define size_t _IO_size_t
-#define FILE _IO_FILE
+
/* Macros for doing the actual output. */
@@ -104,6 +98,9 @@ __printf_size (FILE *fp, const struct printf_info *info,
{
union ieee754_double dbl;
long double ldbl;
+#if __HAVE_DISTINCT_FLOAT128
+ _Float128 f128;
+#endif
}
fpnum;
const void *ptr = &fpnum;
@@ -118,57 +115,45 @@ __printf_size (FILE *fp, const struct printf_info *info,
int done = 0;
int wide = info->wide;
+#define PRINTF_SIZE_FETCH(FLOAT, VAR) \
+ { \
+ (VAR) = *(const FLOAT *) args[0]; \
+ \
+ /* Check for special values: not a number or infinity. */ \
+ if (isnan (VAR)) \
+ { \
+ special = "nan"; \
+ wspecial = L"nan"; \
+ /* is_neg = 0; Already zero */ \
+ } \
+ else if (isinf (VAR)) \
+ { \
+ is_neg = signbit (VAR); \
+ special = "inf"; \
+ wspecial = L"inf"; \
+ } \
+ else \
+ while ((VAR) >= divisor && tag[1] != '\0') \
+ { \
+ (VAR) /= divisor; \
+ ++tag; \
+ } \
+ }
+
/* Fetch the argument value. */
+#if __HAVE_DISTINCT_FLOAT128
+ if (info->is_binary128)
+ PRINTF_SIZE_FETCH (_Float128, fpnum.f128)
+ else
+#endif
#ifndef __NO_LONG_DOUBLE_MATH
if (info->is_long_double && sizeof (long double) > sizeof (double))
- {
- fpnum.ldbl = *(const long double *) args[0];
-
- /* Check for special values: not a number or infinity. */
- if (isnan (fpnum.ldbl))
- {
- special = "nan";
- wspecial = L"nan";
- // is_neg = 0; Already zero
- }
- else if (isinf (fpnum.ldbl))
- {
- is_neg = signbit (fpnum.ldbl);
- special = "inf";
- wspecial = L"inf";
- }
- else
- while (fpnum.ldbl >= divisor && tag[1] != '\0')
- {
- fpnum.ldbl /= divisor;
- ++tag;
- }
- }
+ PRINTF_SIZE_FETCH (long double, fpnum.ldbl)
else
-#endif /* no long double */
- {
- fpnum.dbl.d = *(const double *) args[0];
+#endif
+ PRINTF_SIZE_FETCH (double, fpnum.dbl.d)
- /* Check for special values: not a number or infinity. */
- if (isnan (fpnum.dbl.d))
- {
- special = "nan";
- wspecial = L"nan";
- // is_neg = 0; Already zero
- }
- else if (isinf (fpnum.dbl.d))
- {
- is_neg = signbit (fpnum.dbl.d);
- special = "inf";
- wspecial = L"inf";
- }
- else
- while (fpnum.dbl.d >= divisor && tag[1] != '\0')
- {
- fpnum.dbl.d /= divisor;
- ++tag;
- }
- }
+#undef PRINTF_SIZE_FETCH
if (special)
{
diff --git a/stdio-common/psiginfo.c b/stdio-common/psiginfo.c
index 96c6e91b2a..8f6c53aeb4 100644
--- a/stdio-common/psiginfo.c
+++ b/stdio-common/psiginfo.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2018 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
@@ -15,6 +15,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <array_length.h>
#include <errno.h>
#include <libintl.h>
#include <signal.h>
@@ -116,7 +117,7 @@ psiginfo (const siginfo_t *pinfo, const char *s)
case sig: \
base = C(codestrs_, sig).str; \
offarr = C (codes_, sig); \
- offarr_len = sizeof (C (codes_, sig)) / sizeof (C (codes_, sig)[0]);\
+ offarr_len = array_length (C (codes_, sig)); \
break
H (SIGILL);
@@ -199,5 +200,5 @@ Signal generated by the completion of an I/O request");
fclose (fp);
- write_not_cancel (STDERR_FILENO, buf, strlen (buf));
+ __write_nocancel (STDERR_FILENO, buf, strlen (buf));
}
diff --git a/stdio-common/psignal.c b/stdio-common/psignal.c
index f391ada336..9642a679eb 100644
--- a/stdio-common/psignal.c
+++ b/stdio-common/psignal.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/putw.c b/stdio-common/putw.c
index a70d3a0d91..789cf0de3e 100644
--- a/stdio-common/putw.c
+++ b/stdio-common/putw.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/reg-modifier.c b/stdio-common/reg-modifier.c
index 9a9a678ab7..80f21e205c 100644
--- a/stdio-common/reg-modifier.c
+++ b/stdio-common/reg-modifier.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2018 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
diff --git a/stdio-common/reg-printf.c b/stdio-common/reg-printf.c
index cd64c2abdd..35db28aa33 100644
--- a/stdio-common/reg-printf.c
+++ b/stdio-common/reg-printf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -32,6 +32,7 @@ __libc_lock_define_initialized (static, lock)
int __register_printf_specifier (int, printf_function,
printf_arginfo_size_function);
+libc_hidden_proto (__register_printf_specifier)
int __register_printf_function (int, printf_function,
printf_arginfo_function);
@@ -72,6 +73,7 @@ __register_printf_specifier (int spec, printf_function converter,
return result;
}
+libc_hidden_def (__register_printf_specifier)
weak_alias (__register_printf_specifier, register_printf_specifier)
diff --git a/stdio-common/reg-type.c b/stdio-common/reg-type.c
index aaaf46af30..aac53f088d 100644
--- a/stdio-common/reg-type.c
+++ b/stdio-common/reg-type.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2009-2018 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
diff --git a/stdio-common/remove.c b/stdio-common/remove.c
index 7bbe476585..e01ba517da 100644
--- a/stdio-common/remove.c
+++ b/stdio-common/remove.c
@@ -1,5 +1,5 @@
/* ANSI C `remove' function to delete a file or directory. Stub version.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2018 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
diff --git a/stdio-common/rename.c b/stdio-common/rename.c
index 993a96f2bd..564e8852ac 100644
--- a/stdio-common/rename.c
+++ b/stdio-common/rename.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/renameat.c b/stdio-common/renameat.c
index 40698025b9..98c8f1d18b 100644
--- a/stdio-common/renameat.c
+++ b/stdio-common/renameat.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2005-2018 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
@@ -22,7 +22,7 @@
/* Rename the file OLD relative to OLDFD to NEW relative to NEWFD. */
int
-renameat (int oldfd, const char *old, int newfd, const char *new)
+__renameat (int oldfd, const char *old, int newfd, const char *new)
{
if ((oldfd < 0 && oldfd != AT_FDCWD) || (newfd < 0 && newfd != AT_FDCWD))
{
@@ -40,5 +40,6 @@ renameat (int oldfd, const char *old, int newfd, const char *new)
return -1;
}
-
+libc_hidden_def (__renameat)
+weak_alias (__renameat, renameat)
stub_warning (renameat)
diff --git a/stdio-common/renameat2.c b/stdio-common/renameat2.c
new file mode 100644
index 0000000000..c2cedcd2cb
--- /dev/null
+++ b/stdio-common/renameat2.c
@@ -0,0 +1,30 @@
+/* Generic implementation of the renameat function.
+ Copyright (C) 2018 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+
+int
+renameat2 (int oldfd, const char *old, int newfd, const char *new,
+ unsigned int flags)
+{
+ if (flags == 0)
+ return __renameat (oldfd, old, newfd, new);
+ __set_errno (EINVAL);
+ return -1;
+}
diff --git a/stdio-common/scanf.c b/stdio-common/scanf.c
index c020bb85ba..e61b5f1ad3 100644
--- a/stdio-common/scanf.c
+++ b/stdio-common/scanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/scanf11.c b/stdio-common/scanf11.c
index fcf98464b4..1928da44cd 100644
--- a/stdio-common/scanf11.c
+++ b/stdio-common/scanf11.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/stdio-common/scanf14.c b/stdio-common/scanf14.c
index cffccb0b19..2bcd9c9893 100644
--- a/stdio-common/scanf14.c
+++ b/stdio-common/scanf14.c
@@ -2,7 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
#define FAIL() \
do { \
diff --git a/stdio-common/scanf4.c b/stdio-common/scanf4.c
index 9bb14bb16b..7a2abec89b 100644
--- a/stdio-common/scanf4.c
+++ b/stdio-common/scanf4.c
@@ -1,6 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
int
main(int arc, char *argv[])
diff --git a/stdio-common/scanf7.c b/stdio-common/scanf7.c
index 53ddf4cb09..f568738d7e 100644
--- a/stdio-common/scanf7.c
+++ b/stdio-common/scanf7.c
@@ -1,6 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
int
main (int argc, char *argv[])
diff --git a/stdio-common/siglist.c b/stdio-common/siglist.c
index 9dbceb7e39..722604f4c2 100644
--- a/stdio-common/siglist.c
+++ b/stdio-common/siglist.c
@@ -1,5 +1,5 @@
/* Define list of all signal numbers and their names.
- Copyright (C) 1997-2016 Free Software Foundation, Inc.
+ Copyright (C) 1997-2018 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
diff --git a/stdio-common/snprintf.c b/stdio-common/snprintf.c
index a3cc518976..29a169b08b 100644
--- a/stdio-common/snprintf.c
+++ b/stdio-common/snprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -35,4 +35,5 @@ __snprintf (char *s, size_t maxlen, const char *format, ...)
return done;
}
+libc_hidden_def (__snprintf)
ldbl_weak_alias (__snprintf, snprintf)
diff --git a/stdio-common/sprintf.c b/stdio-common/sprintf.c
index 76f51f6c22..bf5671dde9 100644
--- a/stdio-common/sprintf.c
+++ b/stdio-common/sprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/sscanf.c b/stdio-common/sscanf.c
index 993636120b..88cd641798 100644
--- a/stdio-common/sscanf.c
+++ b/stdio-common/sscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/stdio_ext.h b/stdio-common/stdio_ext.h
index eca2b19204..62aa5fdfed 100644
--- a/stdio-common/stdio_ext.h
+++ b/stdio-common/stdio_ext.h
@@ -1,5 +1,5 @@
/* Functions to access FILE structure internals.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 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
diff --git a/stdio-common/stdio_lim.h.in b/stdio-common/stdio_lim.h.in
index dc9cdbedc2..9d18b16ace 100644
--- a/stdio-common/stdio_lim.h.in
+++ b/stdio-common/stdio_lim.h.in
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2018 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
@@ -15,28 +15,25 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#if !defined _STDIO_H && !defined __need_FOPEN_MAX && !defined __need_IOV_MAX
+#ifndef _BITS_STDIO_LIM_H
+#define _BITS_STDIO_LIM_H 1
+
+#ifndef _STDIO_H
# error "Never include <bits/stdio_lim.h> directly; use <stdio.h> instead."
#endif
-#ifdef _STDIO_H
-# define L_tmpnam @L_tmpnam@
-# define TMP_MAX @TMP_MAX@
-# define FILENAME_MAX @FILENAME_MAX@
+#define L_tmpnam @L_tmpnam@
+#define TMP_MAX @TMP_MAX@
+#define FILENAME_MAX @FILENAME_MAX@
-# ifdef __USE_POSIX
-# define L_ctermid @L_ctermid@
-# if !defined __USE_XOPEN2K || defined __USE_GNU
-# define L_cuserid @L_cuserid@
-# endif
+#ifdef __USE_POSIX
+# define L_ctermid @L_ctermid@
+# if !defined __USE_XOPEN2K || defined __USE_GNU
+# define L_cuserid @L_cuserid@
# endif
#endif
-#if defined __need_FOPEN_MAX || defined _STDIO_H
-# undef FOPEN_MAX
-# define FOPEN_MAX @FOPEN_MAX@
-#endif
+#undef FOPEN_MAX
+#define FOPEN_MAX @FOPEN_MAX@
-#if defined __need_IOV_MAX && !defined IOV_MAX
-@define_IOV_MAX@
-#endif
+#endif /* bits/stdio_lim.h */
diff --git a/stdio-common/tempnam.c b/stdio-common/tempnam.c
index 7a53262e9a..5e64482b48 100644
--- a/stdio-common/tempnam.c
+++ b/stdio-common/tempnam.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/tempname.c b/stdio-common/tempname.c
index 07102c51e7..015c1d0334 100644
--- a/stdio-common/tempname.c
+++ b/stdio-common/tempname.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/test-fseek.c b/stdio-common/test-fseek.c
index 455b2bea92..17cd90b053 100644
--- a/stdio-common/test-fseek.c
+++ b/stdio-common/test-fseek.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -17,7 +17,7 @@
#include <stdio.h>
-#define TESTFILE "/tmp/test.dat"
+#define TESTFILE OBJPFX "test.dat"
static int
do_test (void)
diff --git a/stdio-common/test-popen.c b/stdio-common/test-popen.c
index caf5731940..206f212468 100644
--- a/stdio-common/test-popen.c
+++ b/stdio-common/test-popen.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2018 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
@@ -59,7 +59,7 @@ do_test (void)
the perhaps incompatible new shared libraries. */
unsetenv ("LD_LIBRARY_PATH");
- output = popen ("/bin/cat >/tmp/tstpopen.tmp", "w");
+ output = popen ("/bin/cat >" OBJPFX "tstpopen.tmp", "w");
if (output == NULL)
{
perror ("popen");
@@ -69,10 +69,10 @@ do_test (void)
write_data (output);
wstatus = pclose (output);
printf ("writing pclose returned %d\n", wstatus);
- input = popen ("/bin/cat /tmp/tstpopen.tmp", "r");
+ input = popen ("/bin/cat " OBJPFX "tstpopen.tmp", "r");
if (input == NULL)
{
- perror ("/tmp/tstpopen.tmp");
+ perror (OBJPFX "tstpopen.tmp");
puts ("Test FAILED!");
exit (1);
}
@@ -80,7 +80,7 @@ do_test (void)
rstatus = pclose (input);
printf ("reading pclose returned %d\n", rstatus);
- remove ("/tmp/tstpopen.tmp");
+ remove (OBJPFX "tstpopen.tmp");
errno = 0;
output = popen ("/bin/cat", "m");
diff --git a/stdio-common/test-vfprintf.c b/stdio-common/test-vfprintf.c
index b8829eaf10..bc6b0a54bb 100644
--- a/stdio-common/test-vfprintf.c
+++ b/stdio-common/test-vfprintf.c
@@ -1,5 +1,5 @@
/* Tests of *printf for very large strings.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
@@ -17,6 +17,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <array_length.h>
#include <locale.h>
#include <mcheck.h>
#include <stdint.h>
@@ -25,15 +26,13 @@
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
const char *locs[] =
{
"C", "de_DE.ISO-8859-1", "de_DE.UTF-8", "ja_JP.EUC-JP"
};
-#define nlocs (sizeof (locs) / sizeof (locs[0]))
-
char large[50000];
@@ -56,7 +55,7 @@ do_test (void)
}
unlink (buf);
- for (i = 0; i < nlocs; ++i)
+ for (i = 0; i < array_length (locs); ++i)
{
FILE *fp;
struct stat st;
diff --git a/stdio-common/test_rdwr.c b/stdio-common/test_rdwr.c
index 3b994d130b..348987351f 100644
--- a/stdio-common/test_rdwr.c
+++ b/stdio-common/test_rdwr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -38,7 +38,7 @@ main (int argc, char **argv)
else
name = *argv;
- (void) sprintf (filename, "/tmp/%s.test", name);
+ (void) sprintf (filename, OBJPFX "%s.test", name);
f = fopen (filename, "w+");
if (f == NULL)
diff --git a/stdio-common/tmpfile.c b/stdio-common/tmpfile.c
index d4720a4e9a..5ffecae60c 100644
--- a/stdio-common/tmpfile.c
+++ b/stdio-common/tmpfile.c
@@ -1,5 +1,5 @@
/* Open a stdio stream on an anonymous temporary file. Generic/POSIX version.
- Copyright (C) 1991-2016 Free Software Foundation, Inc.
+ Copyright (C) 1991-2018 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
@@ -34,23 +34,31 @@
FILE *
tmpfile (void)
{
- char buf[FILENAME_MAX];
int fd;
FILE *f;
-
- if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0))
- return NULL;
int flags = 0;
#ifdef FLAGS
flags = FLAGS;
#endif
- fd = __gen_tempname (buf, 0, flags, __GT_FILE);
+
+ /* First try a system specific method. */
+ fd = __gen_tempfd (flags);
+
if (fd < 0)
- return NULL;
+ {
+ char buf[FILENAME_MAX];
+
+ if (__path_search (buf, sizeof buf, NULL, "tmpf", 0))
+ return NULL;
+
+ fd = __gen_tempname (buf, 0, flags, __GT_FILE);
+ if (fd < 0)
+ return NULL;
- /* Note that this relies on the Unix semantics that
- a file is not really removed until it is closed. */
- (void) __unlink (buf);
+ /* Note that this relies on the Unix semantics that
+ a file is not really removed until it is closed. */
+ (void) __unlink (buf);
+ }
if ((f = __fdopen (fd, "w+b")) == NULL)
__close (fd);
diff --git a/stdio-common/tmpfile64.c b/stdio-common/tmpfile64.c
index 6864c33bbe..36f852d258 100644
--- a/stdio-common/tmpfile64.c
+++ b/stdio-common/tmpfile64.c
@@ -1,5 +1,5 @@
/* Open a stdio stream on an anonymous, large temporary file. Generic version.
- Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Copyright (C) 2012-2018 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
diff --git a/stdio-common/tmpnam.c b/stdio-common/tmpnam.c
index 6f0b1d596e..9b0b6114a3 100644
--- a/stdio-common/tmpnam.c
+++ b/stdio-common/tmpnam.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/tmpnam_r.c b/stdio-common/tmpnam_r.c
index aa26737060..baba861667 100644
--- a/stdio-common/tmpnam_r.c
+++ b/stdio-common/tmpnam_r.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
diff --git a/stdio-common/tst-fdopen.c b/stdio-common/tst-fdopen.c
index e70a0cd6a5..136fff5858 100644
--- a/stdio-common/tst-fdopen.c
+++ b/stdio-common/tst-fdopen.c
@@ -1,6 +1,7 @@
/* Test for fdopen bugs. */
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
@@ -18,12 +19,18 @@ char buffer[256];
int
main (int argc, char *argv[])
{
- char *name;
+ char name[] = "/tmp/tst-fdopen.XXXXXX";
FILE *fp = NULL;
int retval = 0;
int fd;
- name = tmpnam (NULL);
+ fd = mkstemp (name);
+ if (fd == -1)
+ {
+ printf ("mkstemp failed: %m\n");
+ return 1;
+ }
+ close (fd);
fp = fopen (name, "w");
assert (fp != NULL)
fputs ("foobar and baz", fp);
diff --git a/stdio-common/tst-fgets.c b/stdio-common/tst-fgets.c
index 0aa9030e3a..912b7068eb 100644
--- a/stdio-common/tst-fgets.c
+++ b/stdio-common/tst-fgets.c
@@ -1,5 +1,5 @@
/* Derived from the test case in
- http://sourceware.org/bugzilla/show_bug.cgi?id=713. */
+ https://sourceware.org/bugzilla/show_bug.cgi?id=713. */
#include <stdio.h>
static int
diff --git a/stdio-common/tst-fileno.c b/stdio-common/tst-fileno.c
index a1a05a9d1b..92ccbda5b5 100644
--- a/stdio-common/tst-fileno.c
+++ b/stdio-common/tst-fileno.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2018 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
diff --git a/stdio-common/tst-fmemopen.c b/stdio-common/tst-fmemopen.c
index cd151cc173..b030282273 100644
--- a/stdio-common/tst-fmemopen.c
+++ b/stdio-common/tst-fmemopen.c
@@ -1,5 +1,5 @@
/* basic fmemopen interface testing.
- Copyright (C) 2014-2016 Free Software Foundation, Inc.
+ Copyright (C) 2014-2018 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
diff --git a/stdio-common/tst-fmemopen2.c b/stdio-common/tst-fmemopen2.c
index 9d0891dcd4..ac1e87a5e0 100644
--- a/stdio-common/tst-fmemopen2.c
+++ b/stdio-common/tst-fmemopen2.c
@@ -1,5 +1,5 @@
/* fmemopen tests.
- Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2015-2018 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
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
+#include <stdint.h>
#include <errno.h>
/* Check fmemopen with user provided buffer open for write. */
diff --git a/stdio-common/tst-fmemopen3.c b/stdio-common/tst-fmemopen3.c
index 250f9ecc75..7878886e3d 100644
--- a/stdio-common/tst-fmemopen3.c
+++ b/stdio-common/tst-fmemopen3.c
@@ -1,5 +1,5 @@
/* fmemopen tests for append and read mode.
- Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2015-2018 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
@@ -25,8 +25,13 @@ static void
print_buffer (const char *s, size_t n)
{
size_t i;
+ printf ("{");
for (i=0; i<n; ++i)
- printf ("0x%02X (%c), ", s[i], s[i]);
+ {
+ printf ("0x%02X (%c)", s[i], s[i]);
+ if (i != n)
+ printf (", ");
+ }
}
/* This test check append mode initial position (a/a+) based on POSIX defition
@@ -186,6 +191,112 @@ do_test_read_seek_negative (void)
}
static int
+do_test_write_append_2 (const char *str)
+{
+ char buf[10];
+ size_t strn = strlen (str);
+ strcpy (buf, str);
+
+ FILE *fp = fmemopen (buf, sizeof (buf), "a+");
+ size_t r = ftell (fp);
+ size_t e = strlen (buf);
+ if (r != e)
+ {
+ printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e);
+ return 1;
+ }
+
+ if (fseek (fp, 0, SEEK_SET) == -1)
+ {
+ printf ("%s: fseek returned -1\n", __FUNCTION__);
+ return 1;
+ }
+
+ int gr;
+ for (int i=0; i<strn; ++i)
+ {
+ if ((gr = getc (fp)) != str[i])
+ {
+ printf ("%s: getc failed returned %d, expected %d\n", __FUNCTION__,
+ gr, str[i]);
+ return 1;
+ }
+ }
+ if ((gr = getc (fp)) != EOF)
+ {
+ printf ("%s: getc failed returned %d, expected EOF\n", __FUNCTION__,
+ gr);
+ return 1;
+ }
+
+ if (fseek (fp, e+1, SEEK_SET) == -1)
+ {
+ printf ("%s: fseek returned -1\n", __FUNCTION__);
+ return 1;
+ }
+
+ if ((r = ftell (fp)) != e+1)
+ {
+ printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+1);
+ return 1;
+ }
+
+ if ((gr = getc (fp)) != EOF)
+ {
+ printf ("%s: getc failed returned %i\n", __FUNCTION__, gr);
+ return 1;
+ }
+
+ /* Check if internal position is not changed with a getc returning EOF. */
+ if ((r = ftell (fp)) != e+1)
+ {
+ printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+1);
+ return 1;
+ }
+
+ if (fseek (fp, 0, SEEK_CUR) == -1)
+ {
+ printf ("%s: fseek returned -1\n", __FUNCTION__);
+ return 1;
+ }
+
+ /* This should be overwritten by fprintf + fflush. */
+ buf[e+2] = 'X';
+
+ if ((r = fprintf (fp, "%d", 101)) != 3)
+ {
+ printf ("%s: fprintf returned %zu, expected %d\n", __FUNCTION__, r, 3);
+ return 1;
+ }
+
+ fflush (fp);
+
+ /* Check if internal position is changed by 3 (strlen of '101'). */
+ if ((r = ftell (fp)) != e+3)
+ {
+ printf ("%s: ftell returned %zu, expected %zu\n", __FUNCTION__, r, e+3);
+ return 1;
+ }
+
+ char exp[20];
+ sprintf (exp, "%s%d", str, 101);
+ if (memcmp (buf, exp, strlen (exp)) != 0)
+ {
+ printf ("%s: check failed:", __FUNCTION__);
+ printf ("\nexpected: ");
+ print_buffer (buf, sizeof (buf));
+ printf ("\nbuffer: ");
+ print_buffer (exp, sizeof (exp));
+ printf ("\n");
+ return 1;
+ }
+
+ fclose(fp);
+
+ return 0;
+}
+
+static int
do_test (void)
{
int ret = 0;
@@ -199,6 +310,11 @@ do_test (void)
ret += do_test_read_seek_negative ();
+ /* First test plus addend will fit in the define buffer of size 10. */
+ ret += do_test_write_append_2 ("test");
+ /* The second test will also fit, but not the final '\0'. */
+ ret += do_test_write_append_2 ("testing");
+
return ret;
}
diff --git a/stdio-common/tst-fmemopen4.c b/stdio-common/tst-fmemopen4.c
new file mode 100644
index 0000000000..a48fa361c4
--- /dev/null
+++ b/stdio-common/tst-fmemopen4.c
@@ -0,0 +1,71 @@
+/* fmemopen tests for BZ#1930 and BZ#20005.
+ Copyright (C) 2016-2018 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+
+/* Check if fflush does not reset the file position. */
+static int
+do_test (void)
+{
+ char buffer[500] = "x";
+
+ FILE *stream = fmemopen (buffer, sizeof (buffer), "r+");
+ if (stream == NULL)
+ {
+ printf ("error: fmemopen could not open stream\n");
+ return 1;
+ }
+
+ const char test[] = "test";
+
+ size_t r = fwrite (test, sizeof (char), sizeof (test), stream);
+ if (r != sizeof (test))
+ {
+ printf ("error: fwrite returned %zu, expected %zu\n", r, sizeof(test));
+ return 1;
+ }
+
+ r = ftell (stream);
+ if (r != sizeof (test))
+ {
+ printf ("error: ftell return %zu, expected %zu\n", r, sizeof(test));
+ return 1;
+ }
+
+ if (fflush (stream) != 0)
+ {
+ printf ("error: fflush failed\n");
+ return 1;
+ }
+
+ r = ftell (stream);
+ if (r != sizeof (test))
+ {
+ printf ("error: ftell return %zu, expected %zu\n", r, sizeof(test));
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdio-common/tst-fphex-wide.c b/stdio-common/tst-fphex-wide.c
index 1f4797c9f8..04c27ba39d 100644
--- a/stdio-common/tst-fphex-wide.c
+++ b/stdio-common/tst-fphex-wide.c
@@ -1,6 +1,6 @@
/* Test program for %a wprintf formats.
This file is part of the GNU C Library.
- Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Copyright (C) 2012-2018 Free Software Foundation, Inc.
Contributed by Marek Polacek <polacek@redhat.com>, 2012.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/stdio-common/tst-fphex.c b/stdio-common/tst-fphex.c
index c2e8961d62..efba482537 100644
--- a/stdio-common/tst-fphex.c
+++ b/stdio-common/tst-fphex.c
@@ -1,5 +1,6 @@
/* Test program for %a printf formats. */
+#include <array_length.h>
#include <stdio.h>
#include <string.h>
@@ -49,12 +50,10 @@ do_test (void)
const struct testcase *t;
int result = 0;
- for (t = testcases;
- t < &testcases[sizeof testcases / sizeof testcases[0]];
- ++t)
+ for (t = testcases; t < array_end (testcases); ++t)
{
CHAR_T buf[1024];
- int n = SPRINT (buf, sizeof buf / sizeof (buf[0]), t->fmt, t->value);
+ int n = SPRINT (buf, array_length (buf), t->fmt, t->value);
if (n != STR_LEN (t->expect) || STR_CMP (buf, t->expect) != 0)
{
PRINT (L_("" S "\tExpected \"" S "\" (%Zu)\n\tGot \""
diff --git a/stdio-common/tst-fseek.c b/stdio-common/tst-fseek.c
index 2598edd0b3..9d5f7466f6 100644
--- a/stdio-common/tst-fseek.c
+++ b/stdio-common/tst-fseek.c
@@ -1,5 +1,5 @@
/* Tests of fseek and fseeko.
- Copyright (C) 2000-2016 Free Software Foundation, Inc.
+ Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
diff --git a/stdio-common/tst-fwrite.c b/stdio-common/tst-fwrite.c
index 2986c8932a..1db10d0f6a 100644
--- a/stdio-common/tst-fwrite.c
+++ b/stdio-common/tst-fwrite.c
@@ -1,5 +1,5 @@
/* Derived from the test case in
- http://sourceware.org/bugzilla/show_bug.cgi?id=1078. */
+ https://sourceware.org/bugzilla/show_bug.cgi?id=1078. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/stdio-common/tst-gets.c b/stdio-common/tst-gets.c
index 073bc54984..7ecbee2ec8 100644
--- a/stdio-common/tst-gets.c
+++ b/stdio-common/tst-gets.c
@@ -1,5 +1,5 @@
/* Tests for gets.
- Copyright (C) 2001-2016 Free Software Foundation, Inc.
+ Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -17,6 +17,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file tests gets. Force it to be declared. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_GETS
+#define __GLIBC_USE_DEPRECATED_GETS 1
+
#include <stdio.h>
#include <string.h>
diff --git a/stdio-common/tst-long-dbl-fphex.c b/stdio-common/tst-long-dbl-fphex.c
index 6241dfd48e..33dc73190d 100644
--- a/stdio-common/tst-long-dbl-fphex.c
+++ b/stdio-common/tst-long-dbl-fphex.c
@@ -1,5 +1,5 @@
/* This file is part of the GNU C Library.
- Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Copyright (C) 2012-2018 Free Software Foundation, Inc.
Contributed by Marek Polacek <polacek@redhat.com>, 2012.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <array_length.h>
#include <wchar.h>
/* Prototype for our test function. */
@@ -28,9 +29,9 @@ do_test (void)
int result = 0;
const long double x = 24.5;
wchar_t a[16];
- swprintf (a, sizeof a / sizeof a[0], L"%La\n", x);
+ swprintf (a, array_length (a), L"%La\n", x);
wchar_t A[16];
- swprintf (A, sizeof A / sizeof A[0], L"%LA\n", x);
+ swprintf (A, array_length (a), L"%LA\n", x);
/* Here wprintf can return four valid variants. We must accept all
of them. */
diff --git a/stdio-common/tst-popen.c b/stdio-common/tst-popen.c
index 94cb59d1c6..87d1c37679 100644
--- a/stdio-common/tst-popen.c
+++ b/stdio-common/tst-popen.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
diff --git a/stdio-common/tst-printf-bz18872.sh b/stdio-common/tst-printf-bz18872.sh
index b96695b400..8b2aec42d9 100644
--- a/stdio-common/tst-printf-bz18872.sh
+++ b/stdio-common/tst-printf-bz18872.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# Copyright (C) 2015-2016 Free Software Foundation, Inc.
+# Copyright (C) 2015-2018 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
diff --git a/stdio-common/tst-printf-round.c b/stdio-common/tst-printf-round.c
index 93a29b509b..d8b6345c39 100644
--- a/stdio-common/tst-printf-round.c
+++ b/stdio-common/tst-printf-round.c
@@ -1,5 +1,5 @@
/* Test for correct rounding of printf floating-point output.
- Copyright (C) 2012-2016 Free Software Foundation, Inc.
+ Copyright (C) 2012-2018 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
@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <array_length.h>
#include <fenv.h>
#include <stdio.h>
#include <string.h>
@@ -167,7 +168,7 @@ do_test (void)
int save_round_mode __attribute__ ((unused)) = fegetround ();
int result = 0;
- for (size_t i = 0; i < sizeof (dec_tests) / sizeof (dec_tests[0]); i++)
+ for (size_t i = 0; i < array_length (dec_tests); i++)
{
result |= test_dec_in_one_mode (dec_tests[i].d, dec_tests[i].fmt,
dec_tests[i].rn, "default rounding mode");
@@ -197,7 +198,7 @@ do_test (void)
#endif
}
- for (size_t i = 0; i < sizeof (hex_tests) / sizeof (hex_tests[0]); i++)
+ for (size_t i = 0; i < array_length (hex_tests); i++)
{
result |= test_hex_in_one_mode (hex_tests[i].d, hex_tests[i].fmt,
hex_tests[i].rn, "default rounding mode");
diff --git a/stdio-common/tst-printf.c b/stdio-common/tst-printf.c
index 2896b18ecd..70d9e584b3 100644
--- a/stdio-common/tst-printf.c
+++ b/stdio-common/tst-printf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -26,12 +26,18 @@
#endif
#include <float.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
/* This whole file is picayune tests of corner cases of printf format strings.
The compiler warnings are not useful here. */
DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat");
+#if __GNUC_PREREQ (7, 0)
+/* Compiler warnings about snprintf output truncation should also be
+ ignored. */
+DIAG_IGNORE_NEEDS_COMMENT (7.0, "-Wformat-truncation");
+#endif
+
static void rfg1 (void);
static void rfg2 (void);
static void rfg3 (void);
@@ -63,75 +69,7 @@ fmtst2chk (const char *fmt)
(void) printf(fmt, 4, 4, 0x12);
(void) printf("'\n");
}
-
-/* This page is covered by the following copyright: */
-
-/* (C) Copyright C E Chew
- *
- * Feel free to copy, use and distribute this software provided:
- *
- * 1. you do not pretend that you wrote it
- * 2. you leave this copyright notice intact.
- */
-
-/*
- * Extracted from exercise.c for glibc-1.05 bug report by Bruce Evans.
- */
-
-#define DEC -123
-#define INT 255
-#define UNS (~0)
-
-/* Formatted Output Test
- *
- * This exercises the output formatting code.
- */
-static void
-fp_test (void)
-{
- int i, j, k, l;
- char buf[7];
- char *prefix = buf;
- char tp[20];
-
- puts("\nFormatted output test");
- printf("prefix 6d 6o 6x 6X 6u\n");
- strcpy(prefix, "%");
- for (i = 0; i < 2; i++) {
- for (j = 0; j < 2; j++) {
- for (k = 0; k < 2; k++) {
- for (l = 0; l < 2; l++) {
- strcpy(prefix, "%");
- if (i == 0) strcat(prefix, "-");
- if (j == 0) strcat(prefix, "+");
- if (k == 0) strcat(prefix, "#");
- if (l == 0) strcat(prefix, "0");
- printf("%5s |", prefix);
- strcpy(tp, prefix);
- strcat(tp, "6d |");
- printf(tp, DEC);
- strcpy(tp, prefix);
- strcat(tp, "6o |");
- printf(tp, INT);
- strcpy(tp, prefix);
- strcat(tp, "6x |");
- printf(tp, INT);
- strcpy(tp, prefix);
- strcat(tp, "6X |");
- printf(tp, INT);
- strcpy(tp, prefix);
- strcat(tp, "6u |");
- printf(tp, UNS);
- printf("\n");
- }
- }
- }
- }
- printf("%10s\n", (char *) NULL);
- printf("%-10s\n", (char *) NULL);
-}
-
static int
do_test (void)
{
@@ -175,6 +113,8 @@ I am ready for my first lesson today.";
printf("null string:\t\"%s\"\n", (char *)NULL);
printf("limited string:\t\"%.22s\"\n", longstr);
+ printf("a-style max:\t\"%a\"\n", DBL_MAX);
+ printf("a-style -max:\t\"%a\"\n", -DBL_MAX);
printf("e-style >= 1:\t\"%e\"\n", 12.34);
printf("e-style >= .1:\t\"%e\"\n", 0.1234);
printf("e-style < .1:\t\"%e\"\n", 0.001234);
@@ -229,8 +169,8 @@ I am ready for my first lesson today.";
snprintf(buf2, sizeof(buf2), "%.999999u", 10));
}
- fp_test ();
-
+ printf("%.8f\n", DBL_MAX);
+ printf("%.8f\n", -DBL_MAX);
printf ("%e should be 1.234568e+06\n", 1234567.8);
printf ("%f should be 1234567.800000\n", 1234567.8);
printf ("%g should be 1.23457e+06\n", 1234567.8);
diff --git a/stdio-common/tst-printf.sh b/stdio-common/tst-printf.sh
index 5755a1bc0a..b543cc646c 100644
--- a/stdio-common/tst-printf.sh
+++ b/stdio-common/tst-printf.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Testing of printf.
-# Copyright (C) 2000-2016 Free Software Foundation, Inc.
+# Copyright (C) 2000-2018 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
@@ -57,6 +57,8 @@ space-padded string: " Hi, Z."
left-adjusted S string: "Hi, Z. "
null string: "(null)"
limited string: "Good morning, Doctor C"
+a-style max: "0x1.fffffffffffffp+1023"
+a-style -max: "-0x1.fffffffffffffp+1023"
e-style >= 1: "1.234000e+01"
e-style >= .1: "1.234000e-01"
e-style < .1: "1.234000e-03"
@@ -103,27 +105,8 @@ something really insane: 1.00000000000000000000000000000000000000000000000000000
| 123456.0000| 1.2346e+05| 1.235e+05|
snprintf ("%30s", "foo") == 30, " "
snprintf ("%.999999u", 10) == 999999
-
-Formatted output test
-prefix 6d 6o 6x 6X 6u
-%-+#0 |-123 |0377 |0xff |0XFF |4294967295 |
- %-+# |-123 |0377 |0xff |0XFF |4294967295 |
- %-+0 |-123 |377 |ff |FF |4294967295 |
- %-+ |-123 |377 |ff |FF |4294967295 |
- %-#0 |-123 |0377 |0xff |0XFF |4294967295 |
- %-# |-123 |0377 |0xff |0XFF |4294967295 |
- %-0 |-123 |377 |ff |FF |4294967295 |
- %- |-123 |377 |ff |FF |4294967295 |
- %+#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |
- %+# | -123 | 0377 | 0xff | 0XFF |4294967295 |
- %+0 |-00123 |000377 |0000ff |0000FF |4294967295 |
- %+ | -123 | 377 | ff | FF |4294967295 |
- %#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |
- %# | -123 | 0377 | 0xff | 0XFF |4294967295 |
- %0 |-00123 |000377 |0000ff |0000FF |4294967295 |
- % | -123 | 377 | ff | FF |4294967295 |
- (null)
-(null)
+179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000
+-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000
1.234568e+06 should be 1.234568e+06
1234567.800000 should be 1234567.800000
1.23457e+06 should be 1.23457e+06
@@ -173,6 +156,8 @@ space-padded string: " Hi, Z."
left-adjusted S string: "Hi, Z. "
null string: "(null)"
limited string: "Good morning, Doctor C"
+a-style max: "0x1.fffffffffffffp+1023"
+a-style -max: "-0x1.fffffffffffffp+1023"
e-style >= 1: "1.234000e+01"
e-style >= .1: "1.234000e-01"
e-style < .1: "1.234000e-03"
@@ -219,27 +204,8 @@ something really insane: 1.00000000000000000000000000000000000000000000000000000
| 123456.0000| 1.2346e+05| 1.235e+05|
snprintf ("%30s", "foo") == 30, " "
snprintf ("%.999999u", 10) == 999999
-
-Formatted output test
-prefix 6d 6o 6x 6X 6u
-%-+#0 |-123 |0377 |0xff |0XFF |4294967295 |
- %-+# |-123 |0377 |0xff |0XFF |4294967295 |
- %-+0 |-123 |377 |ff |FF |4294967295 |
- %-+ |-123 |377 |ff |FF |4294967295 |
- %-#0 |-123 |0377 |0xff |0XFF |4294967295 |
- %-# |-123 |0377 |0xff |0XFF |4294967295 |
- %-0 |-123 |377 |ff |FF |4294967295 |
- %- |-123 |377 |ff |FF |4294967295 |
- %+#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |
- %+# | -123 | 0377 | 0xff | 0XFF |4294967295 |
- %+0 |-00123 |000377 |0000ff |0000FF |4294967295 |
- %+ | -123 | 377 | ff | FF |4294967295 |
- %#0 |-00123 |000377 |0x00ff |0X00FF |4294967295 |
- %# | -123 | 0377 | 0xff | 0XFF |4294967295 |
- %0 |-00123 |000377 |0000ff |0000FF |4294967295 |
- % | -123 | 377 | ff | FF |4294967295 |
- (null)
-(null)
+179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000
+-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.00000000
1.234568e+06 should be 1.234568e+06
1234567.800000 should be 1234567.800000
1.23457e+06 should be 1.23457e+06
diff --git a/stdio-common/tst-printfsz-islongdouble.c b/stdio-common/tst-printfsz-islongdouble.c
new file mode 100644
index 0000000000..a6a534bb3d
--- /dev/null
+++ b/stdio-common/tst-printfsz-islongdouble.c
@@ -0,0 +1,51 @@
+/* Test for the behaviour of 'is_long_double' in printf_size.
+ Copyright (C) 2018 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <printf.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ double d = 2000;
+ double *dptr = &d;
+ long double ld = 4000;
+ long double *ldptr = & ld;
+ struct printf_info info;
+
+ memset (&info, 0, sizeof (info));
+ info.spec = L'f';
+
+ /* Print a value with double type. */
+ printf_size (stdout, &info, (void *) &dptr);
+
+ /* Printf a value with long double type. */
+ info.is_long_double = 1;
+ printf_size (stdout, &info, (void *) &ldptr);
+
+ /* Setting both 'is_long_double' and 'is_binary128' to one is out of
+ the scope of this test, because such configuration is only valid
+ when _Float128 and long double are ABI-distinct (which is not
+ always true in this arch-independent test). */
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/stdio-common/tst-printfsz-islongdouble.sh b/stdio-common/tst-printfsz-islongdouble.sh
new file mode 100644
index 0000000000..6eda634844
--- /dev/null
+++ b/stdio-common/tst-printfsz-islongdouble.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Test for the behaviour of 'is_binary128' in printf_size.
+# Copyright (C) 2018 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
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+test_program=$1; shift
+test_program_prefix=$1; shift
+test_program_output=$1; shift
+
+status=0
+
+${test_program_prefix} \
+ ${test_program} \
+ > ${test_program_output} || status=1
+
+echo -n "2k4k" | cmp - ${test_program_output} > /dev/null 2>&1 ||
+{
+ status=1
+ echo "*** output comparison failed"
+}
+
+exit $status
diff --git a/stdio-common/tst-printfsz.c b/stdio-common/tst-printfsz.c
index 8a3385f94d..47aa8536b3 100644
--- a/stdio-common/tst-printfsz.c
+++ b/stdio-common/tst-printfsz.c
@@ -2,7 +2,7 @@
#include <printf.h>
#include <stdio.h>
#include <string.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
#define V 12345678.12345678
diff --git a/stdio-common/tst-put-error.c b/stdio-common/tst-put-error.c
index 86e7fbd104..4366ed6f2c 100644
--- a/stdio-common/tst-put-error.c
+++ b/stdio-common/tst-put-error.c
@@ -1,6 +1,6 @@
/* Verify that print functions return error when there is an I/O error.
- Copyright (C) 2005-2016 Free Software Foundation, Inc.
+ Copyright (C) 2005-2018 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
diff --git a/stdio-common/tst-renameat2.c b/stdio-common/tst-renameat2.c
new file mode 100644
index 0000000000..958b0918d6
--- /dev/null
+++ b/stdio-common/tst-renameat2.c
@@ -0,0 +1,204 @@
+/* Linux implementation for renameat2 function.
+ Copyright (C) 2018 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/xunistd.h>
+#include <unistd.h>
+
+/* Directory with the temporary files. */
+static char *directory;
+static int directory_fd;
+
+/* Paths within that directory. */
+static char *old_path; /* File is called "old". */
+static char *new_path; /* File is called "new". */
+
+/* Subdirectory within the directory above. */
+static char *subdirectory;
+int subdirectory_fd;
+
+/* And a pathname in that directory (called "file"). */
+static char *subdir_path;
+
+static void
+prepare (int argc, char **argv)
+{
+ directory = support_create_temp_directory ("tst-renameat2-");
+ directory_fd = xopen (directory, O_RDONLY | O_DIRECTORY, 0);
+ old_path = xasprintf ("%s/old", directory);
+ add_temp_file (old_path);
+ new_path = xasprintf ("%s/new", directory);
+ add_temp_file (new_path);
+ subdirectory = xasprintf ("%s/subdir", directory);
+ xmkdir (subdirectory, 0777);
+ add_temp_file (subdirectory);
+ subdirectory_fd = xopen (subdirectory, O_RDONLY | O_DIRECTORY, 0);
+ subdir_path = xasprintf ("%s/file", subdirectory);
+ add_temp_file (subdir_path);
+}
+
+/* Delete all files, preparing a clean slate for the next test. */
+static void
+delete_all_files (void)
+{
+ char *files[] = { old_path, new_path, subdir_path };
+ for (size_t i = 0; i < array_length (files); ++i)
+ if (unlink (files[i]) != 0 && errno != ENOENT)
+ FAIL_EXIT1 ("unlink (\"%s\"): %m", files[i]);
+}
+
+/* Return true if PATH exists in the file system. */
+static bool
+file_exists (const char *path)
+{
+ return access (path, F_OK) == 0;
+}
+
+/* Check that PATH exists and has size EXPECTED_SIZE. */
+static void
+check_size (const char *path, off64_t expected_size)
+{
+ struct stat64 st;
+ xstat (path, &st);
+ if (st.st_size != expected_size)
+ FAIL_EXIT1 ("file \"%s\": expected size %lld, actual size %lld",
+ path, (unsigned long long int) expected_size,
+ (unsigned long long int) st.st_size);
+}
+
+/* Rename tests where the target does not exist. */
+static void
+rename_without_existing_target (unsigned int flags)
+{
+ delete_all_files ();
+ support_write_file_string (old_path, "");
+ TEST_COMPARE (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, flags), 0);
+ TEST_VERIFY (!file_exists (old_path));
+ TEST_VERIFY (file_exists (new_path));
+
+ delete_all_files ();
+ support_write_file_string (old_path, "");
+ TEST_COMPARE (renameat2 (directory_fd, "old", AT_FDCWD, new_path, flags), 0);
+ TEST_VERIFY (!file_exists (old_path));
+ TEST_VERIFY (file_exists (new_path));
+
+ delete_all_files ();
+ support_write_file_string (old_path, "");
+ TEST_COMPARE (renameat2 (directory_fd, "old", subdirectory_fd, "file", 0),
+ 0);
+ TEST_VERIFY (!file_exists (old_path));
+ TEST_VERIFY (file_exists (subdir_path));
+}
+
+static int
+do_test (void)
+{
+ /* Tests with zero flags argument. These are expected to succeed
+ because this renameat2 variant can be implemented with
+ renameat. */
+ rename_without_existing_target (0);
+
+ /* renameat2 without flags replaces an existing destination. */
+ delete_all_files ();
+ support_write_file_string (old_path, "123");
+ support_write_file_string (new_path, "1234");
+ TEST_COMPARE (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, 0), 0);
+ TEST_VERIFY (!file_exists (old_path));
+ check_size (new_path, 3);
+
+ /* Now we need to check for kernel support of renameat2 with
+ flags. */
+ delete_all_files ();
+ support_write_file_string (old_path, "");
+ if (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, RENAME_NOREPLACE)
+ != 0)
+ {
+ if (errno == EINVAL)
+ puts ("warning: no support for renameat2 with flags");
+ else
+ FAIL_EXIT1 ("renameat2 probe failed: %m");
+ }
+ else
+ {
+ /* We have full renameat2 support. */
+ rename_without_existing_target (RENAME_NOREPLACE);
+
+ /* Now test RENAME_NOREPLACE with an existing target. */
+ delete_all_files ();
+ support_write_file_string (old_path, "123");
+ support_write_file_string (new_path, "1234");
+ TEST_COMPARE (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path,
+ RENAME_NOREPLACE), -1);
+ TEST_COMPARE (errno, EEXIST);
+ check_size (old_path, 3);
+ check_size (new_path, 4);
+
+ delete_all_files ();
+ support_write_file_string (old_path, "123");
+ support_write_file_string (new_path, "1234");
+ TEST_COMPARE (renameat2 (directory_fd, "old", AT_FDCWD, new_path,
+ RENAME_NOREPLACE), -1);
+ TEST_COMPARE (errno, EEXIST);
+ check_size (old_path, 3);
+ check_size (new_path, 4);
+
+ delete_all_files ();
+ support_write_file_string (old_path, "123");
+ support_write_file_string (subdir_path, "1234");
+ TEST_COMPARE (renameat2 (directory_fd, "old", subdirectory_fd, "file",
+ RENAME_NOREPLACE), -1);
+ TEST_COMPARE (errno, EEXIST);
+ check_size (old_path, 3);
+ check_size (subdir_path, 4);
+
+ /* The flag combination of RENAME_NOREPLACE and RENAME_EXCHANGE
+ is invalid. */
+ TEST_COMPARE (renameat2 (directory_fd, "ignored",
+ subdirectory_fd, "ignored",
+ RENAME_NOREPLACE | RENAME_EXCHANGE), -1);
+ TEST_COMPARE (errno, EINVAL);
+ }
+
+ /* Create all the pathnames to avoid warnings from the test
+ harness. */
+ support_write_file_string (old_path, "");
+ support_write_file_string (new_path, "");
+ support_write_file_string (subdir_path, "");
+
+ free (directory);
+ free (subdirectory);
+ free (old_path);
+ free (new_path);
+ free (subdir_path);
+
+ xclose (directory_fd);
+ xclose (subdirectory_fd);
+
+ return 0;
+}
+
+#define PREPARE prepare
+#include <support/test-driver.c>
diff --git a/stdio-common/tst-scanf-round.c b/stdio-common/tst-scanf-round.c
new file mode 100644
index 0000000000..a2fb620abf
--- /dev/null
+++ b/stdio-common/tst-scanf-round.c
@@ -0,0 +1,51 @@
+/* Test for correct rounding of negative floating-point numbers by scanf
+ (bug 23280).
+ Copyright (C) 2018 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <fenv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+#ifdef FE_DOWNWARD
+ if (fesetround (FE_DOWNWARD) == 0)
+ {
+ double a = strtod ("-0.1", NULL);
+ double b = 0;
+ int r = sscanf ("-0.1", "%lf", &b);
+ TEST_VERIFY (r == 1);
+ TEST_VERIFY (a == b);
+ }
+#endif
+#ifdef FE_UPWARD
+ if (fesetround (FE_UPWARD) == 0)
+ {
+ double a = strtod ("-0.1", NULL);
+ double b = 0;
+ int r = sscanf ("-0.1", "%lf", &b);
+ TEST_VERIFY (r == 1);
+ TEST_VERIFY (a == b);
+ }
+#endif
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/stdio-common/tst-sprintf.c b/stdio-common/tst-sprintf.c
index d5284b9697..cbd35447a9 100644
--- a/stdio-common/tst-sprintf.c
+++ b/stdio-common/tst-sprintf.c
@@ -2,7 +2,7 @@
#include <stdlib.h>
#include <locale.h>
#include <string.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
static int
diff --git a/stdio-common/tst-sprintf3.c b/stdio-common/tst-sprintf3.c
index cffd1b69d0..deaee93803 100644
--- a/stdio-common/tst-sprintf3.c
+++ b/stdio-common/tst-sprintf3.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2012-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2012-2018 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
@@ -38,11 +38,11 @@ do_test (void)
# define COMPARE_LDBL(u, v) ((u).l == (v).l)
#endif
-#define TEST(val) \
+#define TEST_N(val, n) \
do \
{ \
u.l = (val); \
- snprintf (buf, sizeof buf, "%.30LgL", u.l); \
+ snprintf (buf, sizeof buf, "%." #n "LgL", u.l); \
if (strcmp (buf, #val) != 0) \
{ \
printf ("Error on line %d: %s != %s\n", __LINE__, buf, #val); \
@@ -50,19 +50,25 @@ do_test (void)
} \
if (sscanf (#val, "%Lg", &v.l) != 1 || !COMPARE_LDBL (u, v)) \
{ \
- printf ("Error sscanf on line %d: %.30Lg != %.30Lg\n", __LINE__, \
- u.l, v.l); \
+ printf ("Error sscanf on line %d: %." #n "Lg != %." #n "Lg\n", \
+ __LINE__, u.l, v.l); \
result = 1; \
} \
/* printf ("%s %Lg %016Lx %016Lx\n", #val, u.l, u.x[0], u.x[1]); */ \
} \
while (0)
+#define TEST(val) TEST_N (val,30)
+
#if LDBL_MANT_DIG >= 106
# if LDBL_MANT_DIG == 106
TEST (2.22507385850719347803989925739e-308L);
TEST (2.22507385850719397210554509863e-308L);
TEST (2.22507385850720088902458687609e-308L);
+
+ /* Verify precision is not lost for long doubles
+ of the form +1.pN,-1.pM. */
+ TEST_N (3.32306998946228968225951765070082e+35L, 34);
# endif
TEST (2.22507385850720138309023271733e-308L);
TEST (2.22507385850720187715587855858e-308L);
diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c
index f52cc9e07e..87a6c0defa 100644
--- a/stdio-common/tst-sscanf.c
+++ b/stdio-common/tst-sscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2000.
@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <array_length.h>
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
@@ -184,7 +185,7 @@ do_test (void)
break;
}
- for (i = 0; i < sizeof (int_tests) / sizeof (int_tests[0]); ++i)
+ for (i = 0; i < array_length (int_tests); ++i)
{
long dummy;
int ret;
@@ -198,7 +199,7 @@ do_test (void)
}
}
- for (i = 0; i < sizeof (double_tests) / sizeof (double_tests[0]); ++i)
+ for (i = 0; i < array_length (double_tests); ++i)
{
double dummy;
int ret;
@@ -212,7 +213,7 @@ do_test (void)
}
}
- for (i = 0; i < sizeof (double_tests2) / sizeof (double_tests2[0]); ++i)
+ for (i = 0; i < array_length (double_tests2); ++i)
{
double dummy;
int ret;
diff --git a/stdio-common/tst-swprintf.c b/stdio-common/tst-swprintf.c
index ce62c6bf68..07194eb67d 100644
--- a/stdio-common/tst-swprintf.c
+++ b/stdio-common/tst-swprintf.c
@@ -1,3 +1,4 @@
+#include <array_length.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
@@ -16,7 +17,6 @@ static int
do_test (void)
{
wchar_t buf[1000];
-#define nbuf (sizeof (buf) / sizeof (buf[0]))
int result = 0;
ssize_t n;
@@ -27,7 +27,7 @@ do_test (void)
}
#define CHECK(fmt, nexp, exp) \
- n = swprintf (buf, nbuf, fmt, input); \
+ n = swprintf (buf, array_length (buf), fmt, input); \
if (n != nexp) \
{ \
printf ("swprintf (.., .., L\"%ls\", \"%ls\") return %d, not %d\n", \
diff --git a/stdio-common/tst-tmpnam.c b/stdio-common/tst-tmpnam.c
index e3dc0776cd..f82576ad3e 100644
--- a/stdio-common/tst-tmpnam.c
+++ b/stdio-common/tst-tmpnam.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1998-2018 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
diff --git a/stdio-common/tst-unbputc.sh b/stdio-common/tst-unbputc.sh
index 8156400730..90a810ccee 100755
--- a/stdio-common/tst-unbputc.sh
+++ b/stdio-common/tst-unbputc.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Testing the stdio implementation
-# Copyright (C) 2000-2016 Free Software Foundation, Inc.
+# Copyright (C) 2000-2018 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
diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c
index 44cf6a6bf6..1344b2b591 100644
--- a/stdio-common/tst-ungetc.c
+++ b/stdio-common/tst-ungetc.c
@@ -1,6 +1,7 @@
/* Test for ungetc bugs. */
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#undef assert
@@ -15,13 +16,19 @@
int
main (int argc, char *argv[])
{
- char *name;
+ char name[] = "/tmp/tst-ungetc.XXXXXX";
FILE *fp = NULL;
int retval = 0;
int c;
char buffer[64];
- name = tmpnam (NULL);
+ int fd = mkstemp (name);
+ if (fd == -1)
+ {
+ printf ("mkstemp failed: %m\n");
+ return 1;
+ }
+ close (fd);
fp = fopen (name, "w");
assert (fp != NULL)
fputs ("bla", fp);
diff --git a/stdio-common/tst-unlockedio.c b/stdio-common/tst-unlockedio.c
index 4e47e14f5b..4837fd2e4b 100644
--- a/stdio-common/tst-unlockedio.c
+++ b/stdio-common/tst-unlockedio.c
@@ -1,5 +1,5 @@
/* Test for some *_unlocked stdio interfaces.
- Copyright (C) 2004-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
@@ -20,7 +20,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
int fd;
static void do_prepare (void);
diff --git a/stdio-common/tst-vfprintf-mbs-prec.c b/stdio-common/tst-vfprintf-mbs-prec.c
new file mode 100644
index 0000000000..7f95e6cceb
--- /dev/null
+++ b/stdio-common/tst-vfprintf-mbs-prec.c
@@ -0,0 +1,543 @@
+/* Test for wchar_t/multi-byte conversion and precision in vfprintf.
+ Copyright (C) 2017-2018 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/test-driver.h>
+#include <wchar.h>
+
+#define DYNARRAY_STRUCT str
+#define DYNARRAY_ELEMENT char
+#define DYNARRAY_PREFIX str_
+#include <malloc/dynarray-skeleton.c>
+
+#define DYNARRAY_STRUCT wstr
+#define DYNARRAY_ELEMENT wchar_t
+#define DYNARRAY_PREFIX wstr_
+#include <malloc/dynarray-skeleton.c>
+
+#define DYNARRAY_STRUCT len
+#define DYNARRAY_ELEMENT size_t
+#define DYNARRAY_PREFIX len_
+#include <malloc/dynarray-skeleton.c>
+
+/* This should be larger than the internal buffer in vfprintf. The
+ constant needs to be kept in sync with the format strings in
+ test_mbs_long and test_wide_long. */
+enum { WIDE_STRING_LENGTH = 1000 };
+
+/* Creates two large, random strings used for truncation testing.
+ After the call, *MBS will be encoded in UTF-8, and *WIDE will
+ contain the same string in the internal UCS-32 encoding. Both
+ strings are null-terminated. The array *LENGTH counts the number
+ of multi-byte characters for each prefix string of *WIDE: The first
+ N wide characters of *WIDE correspond the first (*LENGTH)[N] bytes
+ of *MBS. The caller should deallocate all three arrays using
+ free. */
+static void
+make_random_string (char **mbs, wchar_t **wide, size_t **length)
+{
+ struct str str;
+ str_init (&str);
+ struct wstr wstr;
+ wstr_init (&wstr);
+ struct len len;
+ len_init (&len);
+
+ for (int i = 0; i < WIDE_STRING_LENGTH; ++i)
+ {
+ len_add (&len, str_size (&str));
+ /* Cover some multi-byte UTF-8 sequences. Avoid the null
+ character. */
+ uint32_t ch = 1 + (rand () % 521);
+ wstr_add (&wstr, ch);
+
+ /* Limited UTF-8 conversion. */
+ if (ch <= 127)
+ str_add (&str, ch);
+ else
+ {
+ /* We only implement two-byte sequences. */
+ uint32_t first = ch >> 6;
+ TEST_VERIFY (first < 32);
+ str_add (&str, 0xC0 | first);
+ str_add (&str, 0x80 | (ch & 0x3f));
+ }
+ }
+ len_add (&len, str_size (&str));
+ wstr_add (&wstr, L'\0');
+ str_add (&str, '\0');
+
+ *mbs = str_finalize (&str, NULL);
+ TEST_VERIFY_EXIT (*mbs != NULL);
+ *wide = wstr_finalize (&wstr, NULL);
+ TEST_VERIFY_EXIT (*wide != NULL);
+ *length = len_finalize (&len, NULL);
+ TEST_VERIFY_EXIT (*length != NULL);
+}
+
+/* snprintf tests (multi-byte result). */
+static void
+test_mbs_result (void)
+{
+ char buf[200];
+
+ /* ASCII wide string. */
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%ls", L"xyz") == 3);
+ TEST_VERIFY (strcmp (buf, "xyz") == 0);
+
+ /* Unicode wide string. */
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+
+ /* Varying precisions. */
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%.1ls", L"x\u00DFz") == 1);
+ TEST_VERIFY (strcmp (buf, "x") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%.2ls", L"x\u00DFz") == 1);
+ TEST_VERIFY (strcmp (buf, "x") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%.3ls", L"x\u00DFz") == 3);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%.4ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%.5ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+
+ /* Varying precisions with width 2, right-justified. */
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.1ls", L"x\u00DFz") == 2);
+ TEST_VERIFY (strcmp (buf, " x") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.2ls", L"x\u00DFz") == 2);
+ TEST_VERIFY (strcmp (buf, " x") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.3ls", L"x\u00DFz") == 3);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.4ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%2.5ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+
+ /* Varying precisions with width 2, left-justified. */
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.1ls", L"x\u00DFz") == 2);
+ TEST_VERIFY (strcmp (buf, "x ") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.2ls", L"x\u00DFz") == 2);
+ TEST_VERIFY (strcmp (buf, "x ") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.3ls", L"x\u00DFz") == 3);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.4ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-2.5ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+
+ /* Varying precisions with width 3, right-justified. */
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.1ls", L"x\u00DFz") == 3);
+ TEST_VERIFY (strcmp (buf, " x") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.2ls", L"x\u00DFz") == 3);
+ TEST_VERIFY (strcmp (buf, " x") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.3ls", L"x\u00DFz") == 3);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.4ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%3.5ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+
+ /* Varying precisions with width 3, left-justified. */
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.1ls", L"x\u00DFz") == 3);
+ TEST_VERIFY (strcmp (buf, "x ") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.2ls", L"x\u00DFz") == 3);
+ TEST_VERIFY (strcmp (buf, "x ") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.3ls", L"x\u00DFz") == 3);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9F") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.4ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-3.5ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+
+ /* Varying precisions with width 4, right-justified. */
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.1ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, " x") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.2ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, " x") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.3ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, " x\xC3\x9F") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.4ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%4.5ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+
+ /* Varying precisions with width 4, left-justified. */
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.1ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x ") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.2ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x ") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.3ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9F ") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.4ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+ memset (buf, '@', sizeof (buf));
+ TEST_VERIFY (snprintf (buf, sizeof (buf), "%-4.5ls", L"x\u00DFz") == 4);
+ TEST_VERIFY (strcmp (buf, "x\xC3\x9Fz") == 0);
+}
+
+/* swprintf tests (wide string result). */
+static void
+test_wide_result (void)
+{
+ enum { size = 20 };
+ wchar_t buf[20];
+
+ /* ASCII wide string. */
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%s", "xyz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"xyz") == 0);
+
+ /* Unicode wide string. */
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+
+ /* Varying precisions. */
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%.1s", "x\xC3\x9Fz") == 1);
+ TEST_VERIFY (wcscmp (buf, L"x") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%.2s", "x\xC3\x9Fz") == 2);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DF") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%.3s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%.4s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+
+ /* Varying precisions with width 2, right-justified. */
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%2.1s", "x\xC3\x9Fz") == 2);
+ TEST_VERIFY (wcscmp (buf, L" x") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%2.2s", "x\xC3\x9Fz") == 2);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DF") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%2.3s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%2.4s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+
+ /* Varying precisions with width 2, left-justified. */
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-2.1s", "x\xC3\x9Fz") == 2);
+ TEST_VERIFY (wcscmp (buf, L"x ") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-2.2s", "x\xC3\x9Fz") == 2);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DF") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-2.3s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-2.4s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+
+ /* Varying precisions with width 3, right-justified. */
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%3.1s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L" x") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%3.2s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L" x\u00DF") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%3.3s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%3.4s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+
+ /* Varying precisions with width 3, left-justified. */
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-3.1s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x ") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-3.2s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DF ") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-3.3s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-3.4s", "x\xC3\x9Fz") == 3);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz") == 0);
+
+ /* Varying precisions with width 4, right-justified. */
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%4.1s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L" x") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%4.2s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L" x\u00DF") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%4.3s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L" x\u00DFz") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%4.4s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L" x\u00DFz") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%4.5s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L" x\u00DFz") == 0);
+
+ /* Varying precisions with width 4, left-justified. */
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-4.1s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L"x ") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-4.2s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DF ") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-4.3s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz ") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-4.4s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz ") == 0);
+ wmemset (buf, '@', size);
+ TEST_VERIFY (swprintf (buf, size, L"%-4.5s", "x\xC3\x9Fz") == 4);
+ TEST_VERIFY (wcscmp (buf, L"x\u00DFz ") == 0);
+}
+
+/* Test with long strings and multi-byte result. */
+static void
+test_mbs_long (const char *mbs, const wchar_t *wide, const size_t *length)
+{
+ char buf[4000];
+ _Static_assert (sizeof (buf) > 3 * WIDE_STRING_LENGTH,
+ "buffer size consistent with string length");
+ const char *suffix = "||TERM";
+ TEST_VERIFY_EXIT (sizeof (buf)
+ > length[WIDE_STRING_LENGTH] + strlen (suffix));
+
+ /* Test formatting of the entire string. */
+ {
+ int ret = snprintf (buf, sizeof (buf), "%ls%s", wide, suffix);
+ TEST_VERIFY (ret == length[WIDE_STRING_LENGTH] + strlen (suffix));
+ TEST_VERIFY (memcmp (buf, mbs, length[WIDE_STRING_LENGTH]) == 0);
+ TEST_VERIFY (strcmp (buf + length[WIDE_STRING_LENGTH], suffix) == 0);
+
+ /* Left-justified string, printed in full. */
+ ret = snprintf (buf, sizeof (buf), "%-3500ls%s", wide, suffix);
+ TEST_VERIFY (ret == 3500 + strlen (suffix));
+ TEST_VERIFY (memcmp (buf, mbs, length[WIDE_STRING_LENGTH]) == 0);
+ for (size_t i = length[WIDE_STRING_LENGTH]; i < 3500; ++i)
+ TEST_VERIFY (buf[i] == ' ');
+ TEST_VERIFY (strcmp (buf + 3500, suffix) == 0);
+
+ /* Right-justified string, printed in full. */
+ ret = snprintf (buf, sizeof (buf), "%3500ls%s", wide, suffix);
+ TEST_VERIFY (ret == 3500 + strlen (suffix));
+ size_t padding = 3500 - length[WIDE_STRING_LENGTH];
+ for (size_t i = 0; i < padding; ++i)
+ TEST_VERIFY (buf[i] == ' ');
+ TEST_VERIFY (memcmp (buf + padding, mbs, length[WIDE_STRING_LENGTH]) == 0);
+ TEST_VERIFY (strcmp (buf + 3500, suffix) == 0);
+ }
+
+ size_t wide_characters_converted = 0;
+ for (int mbs_len = 0; mbs_len <= length[WIDE_STRING_LENGTH] + 1;
+ ++mbs_len)
+ {
+ if (wide_characters_converted < WIDE_STRING_LENGTH
+ && mbs_len >= length[wide_characters_converted + 1])
+ /* The requested prefix length contains room for another wide
+ character. */
+ ++wide_characters_converted;
+ if (test_verbose > 0)
+ printf ("info: %s: mbs_len=%d wide_chars_converted=%zu length=%zu\n",
+ __func__, mbs_len, wide_characters_converted,
+ length[wide_characters_converted]);
+ TEST_VERIFY (length[wide_characters_converted] <= mbs_len);
+ TEST_VERIFY (wide_characters_converted == 0
+ || length[wide_characters_converted - 1] < mbs_len);
+
+ int ret = snprintf (buf, sizeof (buf), "%.*ls%s", mbs_len, wide, suffix);
+ TEST_VERIFY (ret == length[wide_characters_converted] + strlen (suffix));
+ TEST_VERIFY (memcmp (buf, mbs, length[wide_characters_converted]) == 0);
+ TEST_VERIFY (strcmp (buf + length[wide_characters_converted],
+ suffix) == 0);
+
+ /* Left-justified string, printed in full. */
+ if (test_verbose)
+ printf ("info: %s: left-justified\n", __func__);
+ ret = snprintf (buf, sizeof (buf), "%-3500.*ls%s",
+ mbs_len, wide, suffix);
+ TEST_VERIFY (ret == 3500 + strlen (suffix));
+ TEST_VERIFY (memcmp (buf, mbs, length[wide_characters_converted]) == 0);
+ for (size_t i = length[wide_characters_converted]; i < 3500; ++i)
+ TEST_VERIFY (buf[i] == ' ');
+ TEST_VERIFY (strcmp (buf + 3500, suffix) == 0);
+
+ /* Right-justified string, printed in full. */
+ if (test_verbose)
+ printf ("info: %s: right-justified\n", __func__);
+ ret = snprintf (buf, sizeof (buf), "%3500.*ls%s", mbs_len, wide, suffix);
+ TEST_VERIFY (ret == 3500 + strlen (suffix));
+ size_t padding = 3500 - length[wide_characters_converted];
+ for (size_t i = 0; i < padding; ++i)
+ TEST_VERIFY (buf[i] == ' ');
+ TEST_VERIFY (memcmp (buf + padding, mbs,
+ length[wide_characters_converted]) == 0);
+ TEST_VERIFY (strcmp (buf + 3500, suffix) == 0);
+ }
+}
+
+/* Test with long strings and wide string result. */
+static void
+test_wide_long (const char *mbs, const wchar_t *wide, const size_t *length)
+{
+ wchar_t buf[2000];
+ _Static_assert (sizeof (buf) > sizeof (wchar_t) * WIDE_STRING_LENGTH,
+ "buffer size consistent with string length");
+ const wchar_t *suffix = L"||TERM";
+ TEST_VERIFY_EXIT (sizeof (buf)
+ > length[WIDE_STRING_LENGTH] + wcslen (suffix));
+
+ /* Test formatting of the entire string. */
+ {
+ int ret = swprintf (buf, sizeof (buf), L"%s%ls", mbs, suffix);
+ TEST_VERIFY (ret == WIDE_STRING_LENGTH + wcslen (suffix));
+ TEST_VERIFY (wmemcmp (buf, wide, WIDE_STRING_LENGTH) == 0);
+ TEST_VERIFY (wcscmp (buf + WIDE_STRING_LENGTH, suffix) == 0);
+
+ /* Left-justified string, printed in full. */
+ ret = swprintf (buf, sizeof (buf), L"%-1500s%ls", mbs, suffix);
+ TEST_VERIFY (ret == 1500 + wcslen (suffix));
+ TEST_VERIFY (wmemcmp (buf, wide, WIDE_STRING_LENGTH) == 0);
+ for (size_t i = WIDE_STRING_LENGTH; i < 1500; ++i)
+ TEST_VERIFY (buf[i] == L' ');
+ TEST_VERIFY (wcscmp (buf + 1500, suffix) == 0);
+
+ /* Right-justified string, printed in full. */
+ ret = swprintf (buf, sizeof (buf), L"%1500s%ls", mbs, suffix);
+ TEST_VERIFY (ret == 1500 + wcslen (suffix));
+ size_t padding = 1500 - WIDE_STRING_LENGTH;
+ for (size_t i = 0; i < padding; ++i)
+ TEST_VERIFY (buf[i] == ' ');
+ TEST_VERIFY (wmemcmp (buf + padding, wide, WIDE_STRING_LENGTH) == 0);
+ TEST_VERIFY (wcscmp (buf + 1500, suffix) == 0);
+ }
+
+ for (int wide_len = 0; wide_len <= WIDE_STRING_LENGTH + 1; ++wide_len)
+ {
+ size_t actual_wide_len;
+ if (wide_len < WIDE_STRING_LENGTH)
+ actual_wide_len = wide_len;
+ else
+ actual_wide_len = WIDE_STRING_LENGTH;
+ if (test_verbose > 0)
+ printf ("info: %s: wide_len=%d actual_wide_len=%zu\n",
+ __func__, wide_len, actual_wide_len);
+
+ int ret = swprintf (buf, sizeof (buf), L"%.*s%ls",
+ wide_len, mbs, suffix);
+ TEST_VERIFY (ret == actual_wide_len + wcslen (suffix));
+ TEST_VERIFY (wmemcmp (buf, wide, actual_wide_len) == 0);
+ TEST_VERIFY (wcscmp (buf + actual_wide_len, suffix) == 0);
+
+ /* Left-justified string, printed in full. */
+ ret = swprintf (buf, sizeof (buf), L"%-1500.*s%ls",
+ wide_len, mbs, suffix);
+ TEST_VERIFY (ret == 1500 + wcslen (suffix));
+ TEST_VERIFY (wmemcmp (buf, wide, actual_wide_len) == 0);
+ for (size_t i = actual_wide_len; i < 1500; ++i)
+ TEST_VERIFY (buf[i] == L' ');
+ TEST_VERIFY (wcscmp (buf + 1500, suffix) == 0);
+
+ /* Right-justified string, printed in full. */
+ ret = swprintf (buf, sizeof (buf), L"%1500.*s%ls",
+ wide_len, mbs, suffix);
+ TEST_VERIFY (ret == 1500 + wcslen (suffix));
+ size_t padding = 1500 - actual_wide_len;
+ for (size_t i = 0; i < padding; ++i)
+ TEST_VERIFY (buf[i] == L' ');
+ TEST_VERIFY (wmemcmp (buf + padding, wide, actual_wide_len) == 0);
+ TEST_VERIFY (wcscmp (buf + 1500, suffix) == 0);
+ }
+}
+
+static int
+do_test (void)
+{
+ /* This test only covers UTF-8 as a multi-byte character set. A
+ locale with a multi-byte character set with shift state would be
+ a relevant test target as well, but glibc currently does not ship
+ such a locale. */
+ TEST_VERIFY (setlocale (LC_CTYPE, "de_DE.UTF-8") != NULL);
+
+ test_mbs_result ();
+ test_wide_result ();
+
+ char *mbs;
+ wchar_t *wide;
+ size_t *length;
+ make_random_string (&mbs, &wide, &length);
+ TEST_VERIFY (strlen (mbs) == length[WIDE_STRING_LENGTH]);
+ if (test_verbose > 0)
+ printf ("info: long multi-byte string contains %zu characters\n",
+ length[WIDE_STRING_LENGTH]);
+ test_mbs_long (mbs, wide, length);
+ test_wide_long (mbs, wide, length);
+ free (mbs);
+ free (wide);
+ free (length);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/stdio-common/tst-vfprintf-user-type.c b/stdio-common/tst-vfprintf-user-type.c
new file mode 100644
index 0000000000..1ee86312d8
--- /dev/null
+++ b/stdio-common/tst-vfprintf-user-type.c
@@ -0,0 +1,220 @@
+/* Test for user-defined types in vfprintf.
+ Copyright (C) 2017-2018 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
+ <http://www.gnu.org/licenses/>. */
+
+/* This test contains a printf format specifier, %P, with a custom
+ type which is a long/double pair. If a precision is specified,
+ this indicates the number of such pairs which constitute the
+ argument. */
+
+#include <locale.h>
+#include <printf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+#include <wchar.h>
+
+/* Initialized by do_test using register_printf_type. */
+static int user_type;
+
+struct two_argument
+{
+ long i;
+ double d;
+};
+
+static void
+my_va_arg_function (void *mem, va_list *ap)
+{
+ if (test_verbose > 0)
+ printf ("info: %s (%p) called\n", __func__, mem);
+
+ struct two_argument *pair = mem;
+ pair->i = va_arg (*ap, long);
+ pair->d = va_arg (*ap, double);
+}
+
+static int
+my_printf_function (FILE *fp, const struct printf_info *info,
+ const void *const *args)
+{
+ if (test_verbose > 0)
+ printf ("info: %s (%p, %p, {%p}@%p) called for %%%lc (prec %d)\n",
+ __func__, fp, info, args[0], args, (wint_t) info->spec,
+ info->prec);
+
+ TEST_VERIFY (info->spec == 'P');
+ size_t nargs;
+ int printed;
+ if (info->prec >= 0)
+ {
+ if (fputc ('{', fp) < 0)
+ return -1;
+ nargs = info->prec;
+ printed = 1;
+ }
+ else
+ {
+ nargs = 1;
+ printed = 0;
+ }
+
+ for (size_t i = 0; i < nargs; ++i)
+ {
+ if (i != 0)
+ {
+ if (fputc (',', fp) < 0)
+ return -1;
+ ++printed;
+ }
+
+ /* NB: Triple pointer indirection. ARGS is an array of void *,
+ and those pointers point to a pointer to the memory area
+ supplied to my_va_arg_function. */
+ struct two_argument *pair = *(void **) args[i];
+ int ret = fprintf (fp, "(%ld, %f)", pair->i, pair->d);
+ if (ret < 0)
+ return -1;
+ printed += ret;
+ }
+ if (info->prec >= 0)
+ {
+ if (fputc ('}', fp) < 0)
+ return -1;
+ ++printed;
+ }
+ return printed;
+}
+
+static int
+my_arginfo_function (const struct printf_info *info,
+ size_t n, int *argtypes, int *size)
+{
+ /* Avoid recursion. */
+ if (info->spec != 'P')
+ return -1;
+ if (test_verbose > 0)
+ printf ("info: %s (%p, %zu, %p, %p) called for %%%lc (prec %d)\n",
+ __func__, info, n, argtypes, size, (wint_t) info->spec,
+ info->prec);
+
+ TEST_VERIFY_EXIT (n >= 1);
+ size_t nargs;
+ if (info->prec >= 0)
+ nargs = info->prec;
+ else
+ nargs = 1;
+
+ size_t to_fill = nargs;
+ if (to_fill > n)
+ to_fill = n;
+ for (size_t i = 0; i < to_fill; ++i)
+ {
+ argtypes[i] = user_type;
+ size[i] = sizeof (struct two_argument);
+ }
+ if (test_verbose > 0)
+ printf ("info: %s return value: %zu\n", __func__, nargs);
+ return nargs;
+}
+
+static int
+do_test (void)
+{
+ user_type = register_printf_type (my_va_arg_function);
+ if (test_verbose > 0)
+ printf ("info: allocated user type: %d\n", user_type);
+ TEST_VERIFY_EXIT (user_type >= PA_LAST);
+ TEST_VERIFY_EXIT (register_printf_specifier
+ ('P', my_printf_function, my_arginfo_function) >= 0);
+
+ /* Alias declaration for asprintf, to avoid the format string
+ attribute and the associated warning. */
+ extern int asprintf_alias (char **, const char *, ...) __asm__ ("asprintf");
+ TEST_VERIFY (asprintf_alias == asprintf);
+ char *str = NULL;
+ TEST_VERIFY (asprintf_alias (&str, "[[%P]]", 123L, 456.0) >= 0);
+ if (test_verbose > 0)
+ printf ("info: %s\n", str);
+ TEST_VERIFY (strcmp (str, "[[(123, 456.000000)]]") == 0);
+ free (str);
+
+ str = NULL;
+ TEST_VERIFY (asprintf_alias (&str, "[[%1$P %1$P]]", 123L, 457.0) >= 0);
+ if (test_verbose > 0)
+ printf ("info: %s\n", str);
+ TEST_VERIFY (strcmp (str, "[[(123, 457.000000) (123, 457.000000)]]") == 0);
+ free (str);
+
+ str = NULL;
+ TEST_VERIFY (asprintf_alias (&str, "[[%.1P]]", 1L, 2.0) >= 0);
+ if (test_verbose > 0)
+ printf ("info: %s\n", str);
+ TEST_VERIFY (strcmp (str, "[[{(1, 2.000000)}]]") == 0);
+ free (str);
+
+ str = NULL;
+ TEST_VERIFY (asprintf_alias (&str, "[[%.2P]]", 1L, 2.0, 3L, 4.0) >= 0);
+ if (test_verbose > 0)
+ printf ("info: %s\n", str);
+ TEST_VERIFY (strcmp (str, "[[{(1, 2.000000),(3, 4.000000)}]]") == 0);
+ free (str);
+
+ str = NULL;
+ TEST_VERIFY (asprintf_alias
+ (&str, "[[%.2P | %.3P]]",
+ /* argument 1: */ 1L, 2.0, 3L, 4.0,
+ /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
+ >= 0);
+ if (test_verbose > 0)
+ printf ("info: %s\n", str);
+ TEST_VERIFY (strcmp (str,
+ "[["
+ "{(1, 2.000000),(3, 4.000000)}"
+ " | "
+ "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
+ "]]") == 0);
+ free (str);
+
+ /* The following subtest fails due to bug 21534. */
+#if 0
+ str = NULL;
+ TEST_VERIFY (asprintf_alias
+ (&str, "[[%1$.2P | %2$.3P | %1$.2P]]",
+ /* argument 1: */ 1L, 2.0, 3L, 4.0,
+ /* argument 2: */ 5L, 6.0, 7L, 8.0, 9L, 10.0)
+ >= 0);
+ if (test_verbose > 0)
+ printf ("info: %s\n", str);
+ TEST_VERIFY (strcmp (str,
+ "[["
+ "{(1, 2.000000),(3, 4.000000)}"
+ " | "
+ "{(5, 6.000000),(7, 8.000000),(9, 10.000000)}"
+ " | "
+ "{(1, 2.000000),(3, 4.000000)}"
+ "]]") == 0);
+ free (str);
+#endif
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/stdio-common/tst-vfprintf-width-prec.c b/stdio-common/tst-vfprintf-width-prec.c
new file mode 100644
index 0000000000..fa61f5c22c
--- /dev/null
+++ b/stdio-common/tst-vfprintf-width-prec.c
@@ -0,0 +1,108 @@
+/* Test for memory leak with large width and precision.
+ Copyright (C) 1991-2018 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <mcheck.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <wchar.h>
+
+static int
+do_test (void)
+{
+ mtrace ();
+
+ int ret;
+ {
+ char *result;
+ ret = asprintf (&result, "%133000.133001x", 17);
+ if (ret < 0)
+ {
+ printf ("error: asprintf: %m\n");
+ return 1;
+ }
+ free (result);
+ }
+ {
+ wchar_t *result = calloc (ret + 1, sizeof (wchar_t));
+ if (result == NULL)
+ {
+ printf ("error: calloc (%d, %zu): %m", ret + 1, sizeof (wchar_t));
+ return 1;
+ }
+
+ ret = swprintf (result, ret + 1, L"%133000.133001x", 17);
+ if (ret < 0)
+ {
+ printf ("error: swprintf: %d (%m)\n", ret);
+ return 1;
+ }
+ free (result);
+ }
+
+ /* Limit the size of the process, so that the second allocation will
+ fail. */
+ {
+ struct rlimit limit;
+ if (getrlimit (RLIMIT_AS, &limit) != 0)
+ {
+ printf ("getrlimit (RLIMIT_AS) failed: %m\n");
+ return 1;
+ }
+ long target = 200 * 1024 * 1024;
+ if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
+ {
+ limit.rlim_cur = target;
+ if (setrlimit (RLIMIT_AS, &limit) != 0)
+ {
+ printf ("setrlimit (RLIMIT_AS) failed: %m\n");
+ return 1;
+ }
+ }
+ }
+
+ {
+ char *result;
+ ret = asprintf (&result, "%133000.999999999x", 17);
+ if (ret >= 0)
+ {
+ printf ("error: asprintf: incorrect result %d\n", ret);
+ return 1;
+ }
+ }
+ {
+ wchar_t result[100];
+ if (result == NULL)
+ {
+ printf ("error: calloc (%d, %zu): %m", ret + 1, sizeof (wchar_t));
+ return 1;
+ }
+
+ ret = swprintf (result, 100, L"%133000.999999999x", 17);
+ if (ret >= 0)
+ {
+ printf ("error: swprintf: incorrect result %d\n", ret);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdio-common/tstdiomisc.c b/stdio-common/tstdiomisc.c
index 5548a71e52..c2fc73deb1 100644
--- a/stdio-common/tstdiomisc.c
+++ b/stdio-common/tstdiomisc.c
@@ -1,9 +1,10 @@
+#include <array_length.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
static int
t1 (void)
@@ -66,8 +67,7 @@ t3 (void)
retval = sprintf (buf, "%p", (char *) NULL);
result |= retval != 5 || strcmp (buf, "(nil)") != 0;
- retval = swprintf (wbuf, sizeof (wbuf) / sizeof (wbuf[0]),
- L"%p", (char *) NULL);
+ retval = swprintf (wbuf, array_length (wbuf), L"%p", (char *) NULL);
result |= retval != 5 || wcscmp (wbuf, L"(nil)") != 0;
return result;
@@ -94,6 +94,14 @@ F (void)
qnanval = NAN;
+ /* The %f and %F arguments are in fact constants, but GCC is
+ prevented from seeing this (volatile is used) so it cannot tell
+ that the output is not truncated. */
+ DIAG_PUSH_NEEDS_COMMENT;
+#if __GNUC_PREREQ (7, 0)
+ DIAG_IGNORE_NEEDS_COMMENT (7.0, "-Wformat-truncation");
+#endif
+
snprintf (buf, sizeof buf, "%a %A %e %E %f %F %g %G",
qnanval, qnanval, qnanval, qnanval,
qnanval, qnanval, qnanval, qnanval);
@@ -134,38 +142,38 @@ F (void)
printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n",
buf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G",
+ swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G",
qnanval, qnanval, qnanval, qnanval,
qnanval, qnanval, qnanval, qnanval);
result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0;
printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G",
+ swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G",
-qnanval, -qnanval, -qnanval, -qnanval,
-qnanval, -qnanval, -qnanval, -qnanval);
result |= wcscmp (wbuf, L"-nan -NAN -nan -NAN -nan -NAN -nan -NAN") != 0;
printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n",
wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G",
+ swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G",
snanval, snanval, snanval, snanval,
snanval, snanval, snanval, snanval);
result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0;
printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G",
+ swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G",
msnanval, msnanval, msnanval, msnanval,
msnanval, msnanval, msnanval, msnanval);
result |= wcscmp (wbuf, L"-nan -NAN -nan -NAN -nan -NAN -nan -NAN") != 0;
printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n",
wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G",
+ swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G",
infval, infval, infval, infval, infval, infval, infval, infval);
result |= wcscmp (wbuf, L"inf INF inf INF inf INF inf INF") != 0;
printf ("expected L\"inf INF inf INF inf INF inf INF\", got L\"%S\"\n", wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G",
+ swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G",
-infval, -infval, -infval, -infval,
-infval, -infval, -infval, -infval);
result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0;
@@ -215,14 +223,14 @@ F (void)
printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n",
buf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]),
+ swprintf (wbuf, array_length (wbuf),
L"%La %LA %Le %LE %Lf %LF %Lg %LG",
lqnanval, lqnanval, lqnanval, lqnanval,
lqnanval, lqnanval, lqnanval, lqnanval);
result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0;
printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]),
+ swprintf (wbuf, array_length (wbuf),
L"%La %LA %Le %LE %Lf %LF %Lg %LG",
-lqnanval, -lqnanval, -lqnanval, -lqnanval,
-lqnanval, -lqnanval, -lqnanval, -lqnanval);
@@ -230,14 +238,14 @@ F (void)
printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n",
wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]),
+ swprintf (wbuf, array_length (wbuf),
L"%La %LA %Le %LE %Lf %LF %Lg %LG",
lsnanval, lsnanval, lsnanval, lsnanval,
lsnanval, lsnanval, lsnanval, lsnanval);
result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0;
printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]),
+ swprintf (wbuf, array_length (wbuf),
L"%La %LA %Le %LE %Lf %LF %Lg %LG",
lmsnanval, lmsnanval, lmsnanval, lmsnanval,
lmsnanval, lmsnanval, lmsnanval, lmsnanval);
@@ -245,14 +253,14 @@ F (void)
printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n",
wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]),
+ swprintf (wbuf, array_length (wbuf),
L"%La %LA %Le %LE %Lf %LF %Lg %LG",
linfval, linfval, linfval, linfval,
linfval, linfval, linfval, linfval);
result |= wcscmp (wbuf, L"inf INF inf INF inf INF inf INF") != 0;
printf ("expected L\"inf INF inf INF inf INF inf INF\", got L\"%S\"\n", wbuf);
- swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]),
+ swprintf (wbuf, array_length (wbuf),
L"%La %LA %Le %LE %Lf %LF %Lg %LG",
-linfval, -linfval, -linfval, -linfval,
-linfval, -linfval, -linfval, -linfval);
@@ -260,6 +268,8 @@ F (void)
printf ("expected L\"-inf -INF -inf -INF -inf -INF -inf -INF\", got L\"%S\"\n",
wbuf);
+ DIAG_POP_NEEDS_COMMENT;
+
return result;
}
diff --git a/stdio-common/tstgetln.c b/stdio-common/tstgetln.c
index d52b2bce60..6960e68620 100644
--- a/stdio-common/tstgetln.c
+++ b/stdio-common/tstgetln.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2018 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
@@ -16,8 +16,6 @@
<http://www.gnu.org/licenses/>. */
#include <stdio.h>
-#undef ssize_t
-#define ssize_t _IO_ssize_t
int
main (int argc, char *argv[])
diff --git a/stdio-common/tstscanf.c b/stdio-common/tstscanf.c
index 767b4d6202..019a5c8a4d 100644
--- a/stdio-common/tstscanf.c
+++ b/stdio-common/tstscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -15,6 +15,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <array_length.h>
#ifdef BSD
#include </usr/include/stdio.h>
#else
@@ -154,7 +155,7 @@ main (int argc, char **argv)
{
int count;
- if (rounds++ >= sizeof (ok) / sizeof (ok[0]))
+ if (rounds++ >= array_length (ok))
{
fputs ("test failed!\n", stdout);
result = 1;
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 6829d4dc8e..ae412e4b84 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -15,6 +15,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <array_length.h>
#include <ctype.h>
#include <limits.h>
#include <printf.h>
@@ -38,13 +39,12 @@
Beside this it is also shared between the normal and wide character
implementation as defined in ISO/IEC 9899:1990/Amendment 1:1995. */
-
#include <libioP.h>
-#define FILE _IO_FILE
-#undef va_list
-#define va_list _IO_va_list
-#undef BUFSIZ
-#define BUFSIZ _IO_BUFSIZ
+
+/* In some cases we need extra space for all the output which is not
+ counted in the width of the string. We assume 32 characters is
+ enough. */
+#define EXTSIZ 32
#define ARGCHECK(S, Format) \
do \
{ \
@@ -58,11 +58,11 @@
} \
if (Format == NULL) \
{ \
- MAYBE_SET_EINVAL; \
+ __set_errno (EINVAL); \
return -1; \
} \
} while (0)
-#define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED)
+#define UNBUFFERED_P(S) ((S)->_flags & _IO_UNBUFFERED)
#define done_add(val) \
do { \
@@ -92,7 +92,7 @@ typedef const char *THOUSANDS_SEP_T;
do { \
if (width > 0) \
{ \
- _IO_ssize_t written = _IO_padn (s, (Padchar), width); \
+ ssize_t written = _IO_padn (s, (Padchar), width); \
if (__glibc_unlikely (written != width)) \
{ \
done = -1; \
@@ -122,7 +122,7 @@ typedef wchar_t THOUSANDS_SEP_T;
do { \
if (width > 0) \
{ \
- _IO_ssize_t written = _IO_wpadn (s, (Padchar), width); \
+ ssize_t written = _IO_wpadn (s, (Padchar), width); \
if (__glibc_unlikely (written != width)) \
{ \
done = -1; \
@@ -201,7 +201,7 @@ typedef wchar_t THOUSANDS_SEP_T;
static const CHAR_T null[] = L_("(null)");
/* Size of the work_buffer variable (in characters, not bytes. */
-enum { WORK_BUFFER_SIZE = 1000 };
+enum { WORK_BUFFER_SIZE = 1000 / sizeof (CHAR_T) };
/* This table maps a character into a number representing a class. In
each step there is a destination label for each class. */
@@ -591,9 +591,8 @@ static const uint8_t jump_table[] =
string = _itoa (number.longlong, workend, base, \
spec == L_('X')); \
if (group && grouping) \
- string = group_number (string, workend, grouping, \
- thousands_sep); \
- \
+ string = group_number (work_buffer, string, workend, \
+ grouping, thousands_sep); \
if (use_outdigits && base == 10) \
string = _i18n_number_rewrite (string, workend, workend); \
} \
@@ -649,9 +648,8 @@ static const uint8_t jump_table[] =
string = _itoa_word (number.word, workend, base, \
spec == L_('X')); \
if (group && grouping) \
- string = group_number (string, workend, grouping, \
- thousands_sep); \
- \
+ string = group_number (work_buffer, string, workend, \
+ grouping, thousands_sep); \
if (use_outdigits && base == 10) \
string = _i18n_number_rewrite (string, workend, workend); \
} \
@@ -766,7 +764,8 @@ static const uint8_t jump_table[] =
.pad = pad, \
.extra = 0, \
.i18n = use_outdigits, \
- .wide = sizeof (CHAR_T) != 1 }; \
+ .wide = sizeof (CHAR_T) != 1, \
+ .is_binary128 = 0}; \
\
if (is_long_double) \
the_arg.pa_long_double = va_arg (ap, long double); \
@@ -784,6 +783,8 @@ static const uint8_t jump_table[] =
fspec->data_arg_type = PA_DOUBLE; \
fspec->info.is_long_double = 0; \
} \
+ /* Not supported by *printf functions. */ \
+ fspec->info.is_binary128 = 0; \
\
function_done = __printf_fp (s, &fspec->info, &ptr); \
} \
@@ -823,7 +824,8 @@ static const uint8_t jump_table[] =
.group = group, \
.pad = pad, \
.extra = 0, \
- .wide = sizeof (CHAR_T) != 1 }; \
+ .wide = sizeof (CHAR_T) != 1, \
+ .is_binary128 = 0}; \
\
if (is_long_double) \
the_arg.pa_long_double = va_arg (ap, long double); \
@@ -838,6 +840,8 @@ static const uint8_t jump_table[] =
ptr = (const void *) &args_value[fspec->data_arg]; \
if (__ldbl_is_dbl) \
fspec->info.is_long_double = 0; \
+ /* Not supported by *printf functions. */ \
+ fspec->info.is_binary128 = 0; \
\
function_done = __printf_fphex (s, &fspec->info, &ptr); \
} \
@@ -987,11 +991,10 @@ static const uint8_t jump_table[] =
if (string == NULL) \
{ \
/* Write "(null)" if there's space. */ \
- if (prec == -1 \
- || prec >= (int) (sizeof (null) / sizeof (null[0])) - 1) \
+ if (prec == -1 || prec >= (int) array_length (null) - 1) \
{ \
string = (CHAR_T *) null; \
- len = (sizeof (null) / sizeof (null[0])) - 1; \
+ len = array_length (null) - 1; \
} \
else \
{ \
@@ -1082,7 +1085,7 @@ static const uint8_t jump_table[] =
LABEL (form_wcharacter): \
{ \
/* Wide character. */ \
- char buf[MB_CUR_MAX]; \
+ char buf[MB_LEN_MAX]; \
mbstate_t mbstate; \
size_t len; \
\
@@ -1212,10 +1215,10 @@ static const uint8_t jump_table[] =
/* Helper function to provide temporary buffering for unbuffered streams. */
static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list)
- __THROW __attribute__ ((noinline)) internal_function;
+ __THROW __attribute__ ((noinline));
/* Handle positional format specifiers. */
-static int printf_positional (_IO_FILE *s,
+static int printf_positional (FILE *s,
const CHAR_T *format, int readonly_format,
va_list ap, va_list *ap_savep, int done,
int nspecs_done, const UCHAR_T *lead_str_end,
@@ -1227,8 +1230,8 @@ static int printf_unknown (FILE *, const struct printf_info *,
const void *const *) __THROW;
/* Group digits of number string. */
-static CHAR_T *group_number (CHAR_T *, CHAR_T *, const char *, THOUSANDS_SEP_T)
- __THROW internal_function;
+static CHAR_T *group_number (CHAR_T *, CHAR_T *, CHAR_T *, const char *,
+ THOUSANDS_SEP_T);
/* The function itself. */
int
@@ -1456,20 +1459,19 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
left = 1;
}
- if (__glibc_unlikely (width >= INT_MAX / sizeof (CHAR_T) - 32))
+ if (__glibc_unlikely (width >= INT_MAX / sizeof (CHAR_T) - EXTSIZ))
{
__set_errno (EOVERFLOW);
done = -1;
goto all_done;
}
- if (width >= WORK_BUFFER_SIZE - 32)
+ if (width >= WORK_BUFFER_SIZE - EXTSIZ)
{
- /* We have to use a special buffer. The "32" is just a safe
- bet for all the output which is not counted in the width. */
- size_t needed = ((size_t) width + 32) * sizeof (CHAR_T);
+ /* We have to use a special buffer. */
+ size_t needed = ((size_t) width + EXTSIZ) * sizeof (CHAR_T);
if (__libc_use_alloca (needed))
- workend = (CHAR_T *) alloca (needed) + width + 32;
+ workend = (CHAR_T *) alloca (needed) + width + EXTSIZ;
else
{
workstart = (CHAR_T *) malloc (needed);
@@ -1478,7 +1480,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
done = -1;
goto all_done;
}
- workend = workstart + width + 32;
+ workend = workstart + width + EXTSIZ;
}
}
}
@@ -1489,20 +1491,19 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
width = read_int (&f);
if (__glibc_unlikely (width == -1
- || width >= INT_MAX / sizeof (CHAR_T) - 32))
+ || width >= INT_MAX / sizeof (CHAR_T) - EXTSIZ))
{
__set_errno (EOVERFLOW);
done = -1;
goto all_done;
}
- if (width >= WORK_BUFFER_SIZE - 32)
+ if (width >= WORK_BUFFER_SIZE - EXTSIZ)
{
- /* We have to use a special buffer. The "32" is just a safe
- bet for all the output which is not counted in the width. */
- size_t needed = ((size_t) width + 32) * sizeof (CHAR_T);
+ /* We have to use a special buffer. */
+ size_t needed = ((size_t) width + EXTSIZ) * sizeof (CHAR_T);
if (__libc_use_alloca (needed))
- workend = (CHAR_T *) alloca (needed) + width + 32;
+ workend = (CHAR_T *) alloca (needed) + width + EXTSIZ;
else
{
workstart = (CHAR_T *) malloc (needed);
@@ -1511,7 +1512,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
done = -1;
goto all_done;
}
- workend = workstart + width + 32;
+ workend = workstart + width + EXTSIZ;
}
}
if (*f == L_('$'))
@@ -1562,18 +1563,23 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
}
else
prec = 0;
- if (prec > width && prec > WORK_BUFFER_SIZE - 32)
+ if (prec > width && prec > WORK_BUFFER_SIZE - EXTSIZ)
{
- if (__glibc_unlikely (prec >= INT_MAX / sizeof (CHAR_T) - 32))
+ /* Deallocate any previously allocated buffer because it is
+ too small. */
+ if (__glibc_unlikely (workstart != NULL))
+ free (workstart);
+ workstart = NULL;
+ if (__glibc_unlikely (prec >= INT_MAX / sizeof (CHAR_T) - EXTSIZ))
{
__set_errno (EOVERFLOW);
done = -1;
goto all_done;
}
- size_t needed = ((size_t) prec + 32) * sizeof (CHAR_T);
+ size_t needed = ((size_t) prec + EXTSIZ) * sizeof (CHAR_T);
if (__libc_use_alloca (needed))
- workend = (CHAR_T *) alloca (needed) + prec + 32;
+ workend = (CHAR_T *) alloca (needed) + prec + EXTSIZ;
else
{
workstart = (CHAR_T *) malloc (needed);
@@ -1582,7 +1588,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
done = -1;
goto all_done;
}
- workend = workstart + prec + 32;
+ workend = workstart + prec + EXTSIZ;
}
}
JUMP (*f, step2_jumps);
@@ -1689,21 +1695,23 @@ do_positional:
}
static int
-printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
+printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
va_list ap, va_list *ap_savep, int done, int nspecs_done,
const UCHAR_T *lead_str_end,
CHAR_T *work_buffer, int save_errno,
const char *grouping, THOUSANDS_SEP_T thousands_sep)
{
- /* For the argument descriptions, which may be allocated on the heap. */
- void *args_malloced = NULL;
-
/* For positional argument handling. */
struct scratch_buffer specsbuf;
scratch_buffer_init (&specsbuf);
struct printf_spec *specs = specsbuf.data;
size_t specs_limit = specsbuf.length / sizeof (specs[0]);
+ /* Used as a backing store for args_value, args_size, args_type
+ below. */
+ struct scratch_buffer argsbuf;
+ scratch_buffer_init (&argsbuf);
+
/* Array with information about the needed arguments. This has to
be dynamically extensible. */
size_t nspecs = 0;
@@ -1712,10 +1720,6 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
determine the size of the array needed to store the argument
attributes. */
size_t nargs = 0;
- size_t bytes_per_arg;
- union printf_arg *args_value;
- int *args_size;
- int *args_type;
/* Positional parameters refer to arguments directly. This could
also determine the maximum number of arguments. Track the
@@ -1765,38 +1769,29 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
/* Determine the number of arguments the format string consumes. */
nargs = MAX (nargs, max_ref_arg);
- /* Calculate total size needed to represent a single argument across
- all three argument-related arrays. */
- bytes_per_arg = (sizeof (*args_value) + sizeof (*args_size)
- + sizeof (*args_type));
-
- /* Check for potential integer overflow. */
- if (__glibc_unlikely (nargs > INT_MAX / bytes_per_arg))
- {
- __set_errno (EOVERFLOW);
- done = -1;
- goto all_done;
- }
-
- /* Allocate memory for all three argument arrays. */
- if (__libc_use_alloca (nargs * bytes_per_arg))
- args_value = alloca (nargs * bytes_per_arg);
- else
- {
- args_value = args_malloced = malloc (nargs * bytes_per_arg);
- if (args_value == NULL)
- {
- done = -1;
- goto all_done;
- }
- }
- /* Set up the remaining two arrays to each point past the end of the
- prior array, since space for all three has been allocated now. */
- args_size = &args_value[nargs].pa_int;
- args_type = &args_size[nargs];
- memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
- nargs * sizeof (*args_type));
+ union printf_arg *args_value;
+ int *args_size;
+ int *args_type;
+ {
+ /* Calculate total size needed to represent a single argument
+ across all three argument-related arrays. */
+ size_t bytes_per_arg
+ = sizeof (*args_value) + sizeof (*args_size) + sizeof (*args_type);
+ if (!scratch_buffer_set_array_size (&argsbuf, nargs, bytes_per_arg))
+ {
+ done = -1;
+ goto all_done;
+ }
+ args_value = argsbuf.data;
+ /* Set up the remaining two arrays to each point past the end of
+ the prior array, since space for all three has been allocated
+ now. */
+ args_size = &args_value[nargs].pa_int;
+ args_type = &args_size[nargs];
+ memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
+ nargs * sizeof (*args_type));
+ }
/* XXX Could do sanity check here: If any element in ARGS_TYPE is
still zero after this loop, format is invalid. For now we
@@ -1959,23 +1954,23 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
}
/* Maybe the buffer is too small. */
- if (MAX (prec, width) + 32 > WORK_BUFFER_SIZE)
+ if (MAX (prec, width) + EXTSIZ > WORK_BUFFER_SIZE)
{
- if (__libc_use_alloca ((MAX (prec, width) + 32)
+ if (__libc_use_alloca ((MAX (prec, width) + EXTSIZ)
* sizeof (CHAR_T)))
- workend = ((CHAR_T *) alloca ((MAX (prec, width) + 32)
+ workend = ((CHAR_T *) alloca ((MAX (prec, width) + EXTSIZ)
* sizeof (CHAR_T))
- + (MAX (prec, width) + 32));
+ + (MAX (prec, width) + EXTSIZ));
else
{
- workstart = (CHAR_T *) malloc ((MAX (prec, width) + 32)
+ workstart = (CHAR_T *) malloc ((MAX (prec, width) + EXTSIZ)
* sizeof (CHAR_T));
if (workstart == NULL)
{
done = -1;
goto all_done;
}
- workend = workstart + (MAX (prec, width) + 32);
+ workend = workstart + (MAX (prec, width) + EXTSIZ);
}
}
@@ -2062,10 +2057,9 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
- specs[nspecs_done].end_of_fmt);
}
all_done:
- if (__glibc_unlikely (args_malloced != NULL))
- free (args_malloced);
if (__glibc_unlikely (workstart != NULL))
free (workstart);
+ scratch_buffer_free (&argsbuf);
scratch_buffer_free (&specsbuf);
return done;
}
@@ -2122,16 +2116,20 @@ printf_unknown (FILE *s, const struct printf_info *info,
return done;
}
-/* Group the digits according to the grouping rules of the current locale.
- The interpretation of GROUPING is as in `struct lconv' from <locale.h>. */
+/* Group the digits from W to REAR_PTR according to the grouping rules
+ of the current locale. The interpretation of GROUPING is as in
+ `struct lconv' from <locale.h>. The grouped number extends from
+ the returned pointer until REAR_PTR. FRONT_PTR to W is used as a
+ scratch area. */
static CHAR_T *
-internal_function
-group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping,
- THOUSANDS_SEP_T thousands_sep)
+group_number (CHAR_T *front_ptr, CHAR_T *w, CHAR_T *rear_ptr,
+ const char *grouping, THOUSANDS_SEP_T thousands_sep)
{
+ /* Length of the current group. */
int len;
- CHAR_T *src, *s;
#ifndef COMPILE_WPRINTF
+ /* Length of the separator (in wide mode, the separator is always a
+ single wide character). */
int tlen = strlen (thousands_sep);
#endif
@@ -2144,26 +2142,34 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping,
len = *grouping++;
/* Copy existing string so that nothing gets overwritten. */
- src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T));
- s = (CHAR_T *) __mempcpy (src, w,
- (rear_ptr - w) * sizeof (CHAR_T));
+ memmove (front_ptr, w, (rear_ptr - w) * sizeof (CHAR_T));
+ CHAR_T *s = front_ptr + (rear_ptr - w);
+
w = rear_ptr;
/* Process all characters in the string. */
- while (s > src)
+ while (s > front_ptr)
{
*--w = *--s;
- if (--len == 0 && s > src)
+ if (--len == 0 && s > front_ptr)
{
/* A new group begins. */
#ifdef COMPILE_WPRINTF
- *--w = thousands_sep;
+ if (w != s)
+ *--w = thousands_sep;
+ else
+ /* Not enough room for the separator. */
+ goto copy_rest;
#else
int cnt = tlen;
- do
- *--w = thousands_sep[--cnt];
- while (cnt > 0);
+ if (tlen < w - s)
+ do
+ *--w = thousands_sep[--cnt];
+ while (cnt > 0);
+ else
+ /* Not enough room for the separator. */
+ goto copy_rest;
#endif
if (*grouping == CHAR_MAX
@@ -2172,17 +2178,16 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping,
#endif
)
{
- /* No further grouping to be done.
- Copy the rest of the number. */
- do
- *--w = *--s;
- while (s > src);
+ copy_rest:
+ /* No further grouping to be done. Copy the rest of the
+ number. */
+ memmove (w, s, (front_ptr -s) * sizeof (CHAR_T));
break;
}
else if (*grouping != '\0')
- /* The previous grouping repeats ad infinitum. */
len = *grouping++;
else
+ /* The previous grouping repeats ad infinitum. */
len = grouping[-1];
}
}
@@ -2196,22 +2201,21 @@ struct helper_file
#ifdef COMPILE_WPRINTF
struct _IO_wide_data _wide_data;
#endif
- _IO_FILE *_put_stream;
+ FILE *_put_stream;
#ifdef _IO_MTSAFE_IO
_IO_lock_t lock;
#endif
};
static int
-_IO_helper_overflow (_IO_FILE *s, int c)
+_IO_helper_overflow (FILE *s, int c)
{
- _IO_FILE *target = ((struct helper_file*) s)->_put_stream;
+ FILE *target = ((struct helper_file*) s)->_put_stream;
#ifdef COMPILE_WPRINTF
int used = s->_wide_data->_IO_write_ptr - s->_wide_data->_IO_write_base;
if (used)
{
- _IO_size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base,
- used);
+ size_t written = _IO_sputn (target, s->_wide_data->_IO_write_base, used);
if (written == 0 || written == WEOF)
return WEOF;
__wmemmove (s->_wide_data->_IO_write_base,
@@ -2223,7 +2227,7 @@ _IO_helper_overflow (_IO_FILE *s, int c)
int used = s->_IO_write_ptr - s->_IO_write_base;
if (used)
{
- _IO_size_t written = _IO_sputn (target, s->_IO_write_base, used);
+ size_t written = _IO_sputn (target, s->_IO_write_base, used);
if (written == 0 || written == EOF)
return EOF;
memmove (s->_IO_write_base, s->_IO_write_base + written,
@@ -2235,7 +2239,7 @@ _IO_helper_overflow (_IO_FILE *s, int c)
}
#ifdef COMPILE_WPRINTF
-static const struct _IO_jump_t _IO_helper_jumps =
+static const struct _IO_jump_t _IO_helper_jumps libio_vtable =
{
JUMP_INIT_DUMMY,
JUMP_INIT (finish, _IO_wdefault_finish),
@@ -2257,7 +2261,7 @@ static const struct _IO_jump_t _IO_helper_jumps =
JUMP_INIT (stat, _IO_default_stat)
};
#else
-static const struct _IO_jump_t _IO_helper_jumps =
+static const struct _IO_jump_t _IO_helper_jumps libio_vtable =
{
JUMP_INIT_DUMMY,
JUMP_INIT (finish, _IO_default_finish),
@@ -2281,13 +2285,11 @@ static const struct _IO_jump_t _IO_helper_jumps =
#endif
static int
-internal_function
-buffered_vfprintf (_IO_FILE *s, const CHAR_T *format,
- _IO_va_list args)
+buffered_vfprintf (FILE *s, const CHAR_T *format, va_list args)
{
- CHAR_T buf[_IO_BUFSIZ];
+ CHAR_T buf[BUFSIZ];
struct helper_file helper;
- _IO_FILE *hp = (_IO_FILE *) &helper._f;
+ FILE *hp = (FILE *) &helper._f;
int result, to_flush;
/* Orient the stream. */
@@ -2305,7 +2307,7 @@ buffered_vfprintf (_IO_FILE *s, const CHAR_T *format,
_IO_setp (hp, buf, buf + sizeof buf);
hp->_mode = -1;
#endif
- hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS|_IO_USER_LOCK;
+ hp->_flags = _IO_MAGIC|_IO_NO_READS|_IO_USER_LOCK;
#if _IO_JUMPS_OFFSET
hp->_vtable_offset = 0;
#endif
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 8cd59557a6..1ce836a324 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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
@@ -27,7 +27,7 @@
#include <string.h>
#include <wchar.h>
#include <wctype.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
#include <libc-lock.h>
#include <locale/localeinfo.h>
#include <scratch_buffer.h>
@@ -72,10 +72,6 @@
#include <locale/localeinfo.h>
#include <libioP.h>
-#include <libio.h>
-
-#undef va_list
-#define va_list _IO_va_list
#ifdef COMPILE_WSCANF
# define ungetc(c, s) ((void) (c == WEOF \
@@ -133,6 +129,8 @@
# define WINT_T int
#endif
+#include "printf-parse.h" /* Use read_int. */
+
#define encode_error() do { \
errval = 4; \
__set_errno (EILSEQ); \
@@ -174,7 +172,7 @@
} \
else if (format == NULL) \
{ \
- MAYBE_SET_EINVAL; \
+ __set_errno (EINVAL); \
return EOF; \
} \
} while (0)
@@ -269,11 +267,11 @@ char_buffer_add (struct char_buffer *buffer, CHAR_T ch)
Return the number of assignments made, or -1 for an input error. */
#ifdef COMPILE_WSCANF
int
-_IO_vfwscanf (_IO_FILE *s, const wchar_t *format, _IO_va_list argptr,
+_IO_vfwscanf (FILE *s, const wchar_t *format, va_list argptr,
int *errp)
#else
int
-_IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
+_IO_vfscanf_internal (FILE *s, const char *format, va_list argptr,
int *errp)
#endif
{
@@ -287,14 +285,14 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
int flags; /* Modifiers for current format element. */
int errval = 0;
#ifndef COMPILE_WSCANF
- __locale_t loc = _NL_CURRENT_LOCALE;
+ locale_t loc = _NL_CURRENT_LOCALE;
struct __locale_data *const curctype = loc->__locales[LC_CTYPE];
#endif
/* Errno of last failed inchar call. */
int inchar_errno = 0;
/* Status for reading F-P nums. */
- char got_digit, got_dot, got_e, negative;
+ char got_digit, got_dot, got_e, got_sign;
/* If a [...] is a [^...]. */
CHAR_T not_in;
#define exp_char not_in
@@ -488,9 +486,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Check for a positional parameter specification. */
if (ISDIGIT ((UCHAR_T) *f))
{
- argpos = (UCHAR_T) *f++ - L_('0');
- while (ISDIGIT ((UCHAR_T) *f))
- argpos = argpos * 10 + ((UCHAR_T) *f++ - L_('0'));
+ argpos = read_int ((const UCHAR_T **) &f);
if (*f == L_('$'))
++f;
else
@@ -525,11 +521,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Find the maximum field width. */
width = 0;
- while (ISDIGIT ((UCHAR_T) *f))
- {
- width *= 10;
- width += (UCHAR_T) *f++ - L_('0');
- }
+ if (ISDIGIT ((UCHAR_T) *f))
+ width = read_int ((const UCHAR_T **) &f);
got_width:
if (width == 0)
width = -1;
@@ -757,7 +750,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
size_t n;
if (!(flags & SUPPRESS) && (flags & POSIX_MALLOC)
- && str + MB_CUR_MAX >= *strptr + strsize)
+ && *strptr + strsize - str <= MB_LEN_MAX)
{
/* We have to enlarge the buffer if the `m' flag
was given. */
@@ -769,7 +762,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
{
/* Can't allocate that much. Last-ditch effort. */
newstr = (char *) realloc (*strptr,
- strleng + MB_CUR_MAX);
+ strleng + MB_LEN_MAX);
if (newstr == NULL)
{
/* c can't have `a' flag, only `m'. */
@@ -780,7 +773,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
{
*strptr = newstr;
str = newstr + strleng;
- strsize = strleng + MB_CUR_MAX;
+ strsize = strleng + MB_LEN_MAX;
}
}
else
@@ -1048,7 +1041,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
size_t n;
if (!(flags & SUPPRESS) && (flags & MALLOC)
- && str + MB_CUR_MAX >= *strptr + strsize)
+ && *strptr + strsize - str <= MB_LEN_MAX)
{
/* We have to enlarge the buffer if the `a' or `m'
flag was given. */
@@ -1061,7 +1054,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Can't allocate that much. Last-ditch
effort. */
newstr = (char *) realloc (*strptr,
- strleng + MB_CUR_MAX);
+ strleng + MB_LEN_MAX);
if (newstr == NULL)
{
if (flags & POSIX_MALLOC)
@@ -1081,7 +1074,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
{
*strptr = newstr;
str = newstr + strleng;
- strsize = strleng + MB_CUR_MAX;
+ strsize = strleng + MB_LEN_MAX;
}
}
else
@@ -1097,7 +1090,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (__glibc_unlikely (n == (size_t) -1))
encode_error ();
- assert (n <= MB_CUR_MAX);
+ assert (n <= MB_LEN_MAX);
str += n;
}
#else
@@ -1921,20 +1914,19 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (__glibc_unlikely (c == EOF))
input_error ();
- got_digit = got_dot = got_e = 0;
+ got_digit = got_dot = got_e = got_sign = 0;
/* Check for a sign. */
if (c == L_('-') || c == L_('+'))
{
- negative = c == L_('-');
+ got_sign = 1;
+ char_buffer_add (&charbuf, c);
if (__glibc_unlikely (width == 0 || inchar () == EOF))
/* EOF is only an input error before we read any chars. */
conv_error ();
if (width > 0)
--width;
}
- else
- negative = 0;
/* Take care for the special arguments "nan" and "inf". */
if (TOLOWER (c) == L_('n'))
@@ -2183,7 +2175,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
digits with ASCII letters. */
&& !(flags & HEXA_FLOAT)
/* Minimum requirement. */
- && (char_buffer_size (&charbuf) == 0 || got_dot)
+ && (char_buffer_size (&charbuf) == got_sign || got_dot)
&& (map = __wctrans ("to_inpunct")) != NULL)
{
/* Reget the first character. */
@@ -2202,8 +2194,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
for localized FP numbers, then we may have localized
digits. Note, we test GOT_DOT above. */
#ifdef COMPILE_WSCANF
- if (char_buffer_size (&charbuf) == 0
- || (char_buffer_size (&charbuf) == 1
+ if (char_buffer_size (&charbuf) == got_sign
+ || (char_buffer_size (&charbuf) == got_sign + 1
&& wcdigits[11] == decimal))
#else
char mbdigits[12][MB_LEN_MAX + 1];
@@ -2211,13 +2203,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
mbstate_t state;
memset (&state, '\0', sizeof (state));
- bool match_so_far = char_buffer_size (&charbuf) == 0;
+ bool match_so_far = char_buffer_size (&charbuf) == got_sign;
size_t mblen = __wcrtomb (mbdigits[11], wcdigits[11], &state);
if (mblen != (size_t) -1)
{
mbdigits[11][mblen] = '\0';
match_so_far |=
- (char_buffer_size (&charbuf) == strlen (decimal)
+ (char_buffer_size (&charbuf) == strlen (decimal) + got_sign
&& strcmp (decimal, mbdigits[11]) == 0);
}
else
@@ -2227,7 +2219,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
from a file. */
if (decimal_len <= MB_LEN_MAX)
{
- match_so_far |= char_buffer_size (&charbuf) == decimal_len;
+ match_so_far |= (char_buffer_size (&charbuf)
+ == decimal_len + got_sign);
memcpy (mbdigits[11], decimal, decimal_len + 1);
}
else
@@ -2291,7 +2284,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (got_e && charbuf.current[-1] == exp_char
&& (c == L_('-') || c == L_('+')))
char_buffer_add (&charbuf, c);
- else if (char_buffer_size (&charbuf) > 0 && !got_e
+ else if (char_buffer_size (&charbuf) > got_sign && !got_e
&& (CHAR_T) TOLOWER (c) == exp_char)
{
char_buffer_add (&charbuf, exp_char);
@@ -2415,9 +2408,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Have we read any character? If we try to read a number
in hexadecimal notation and we have read only the `0x'
prefix this is an error. */
- if (__glibc_unlikely (char_buffer_size (&charbuf) == 0
+ if (__glibc_unlikely (char_buffer_size (&charbuf) == got_sign
|| ((flags & HEXA_FLOAT)
- && char_buffer_size (&charbuf) == 2)))
+ && (char_buffer_size (&charbuf)
+ == 2 + got_sign))))
conv_error ();
scan_float:
@@ -2434,21 +2428,21 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
long double d = __strtold_internal
(char_buffer_start (&charbuf), &tw, flags & GROUP);
if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf))
- *ARG (long double *) = negative ? -d : d;
+ *ARG (long double *) = d;
}
else if (flags & (LONG | LONGDBL))
{
double d = __strtod_internal
(char_buffer_start (&charbuf), &tw, flags & GROUP);
if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf))
- *ARG (double *) = negative ? -d : d;
+ *ARG (double *) = d;
}
else
{
float d = __strtof_internal
(char_buffer_start (&charbuf), &tw, flags & GROUP);
if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf))
- *ARG (float *) = negative ? -d : d;
+ *ARG (float *) = d;
}
if (__glibc_unlikely (tw == char_buffer_start (&charbuf)))
@@ -2675,7 +2669,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Possibly correct character, just not enough
input. */
++cnt;
- assert (cnt < MB_CUR_MAX);
+ assert (cnt < MB_LEN_MAX);
continue;
}
cnt = 0;
@@ -2827,7 +2821,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (!(flags & SUPPRESS))
{
if ((flags & MALLOC)
- && str + MB_CUR_MAX >= *strptr + strsize)
+ && *strptr + strsize - str <= MB_LEN_MAX)
{
/* Enlarge the buffer. */
size_t strleng = str - *strptr;
@@ -2839,7 +2833,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Can't allocate that much. Last-ditch
effort. */
newstr = (char *) realloc (*strptr,
- strleng + MB_CUR_MAX);
+ strleng + MB_LEN_MAX);
if (newstr == NULL)
{
if (flags & POSIX_MALLOC)
@@ -2859,7 +2853,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
{
*strptr = newstr;
str = newstr + strleng;
- strsize = strleng + MB_CUR_MAX;
+ strsize = strleng + MB_LEN_MAX;
}
}
else
@@ -2875,7 +2869,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (__glibc_unlikely (n == (size_t) -1))
encode_error ();
- assert (n <= MB_CUR_MAX);
+ assert (n <= MB_LEN_MAX);
str += n;
}
while (--width > 0 && inchar () != WEOF);
diff --git a/stdio-common/vprintf.c b/stdio-common/vprintf.c
index df66e18045..d459642dc8 100644
--- a/stdio-common/vprintf.c
+++ b/stdio-common/vprintf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2018 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