Message ID | 20180307193205.4751-3-zackw@panix.com |
---|---|
State | New |
Headers | show |
Series | Use more flags parameters instead of global bits in stdio | expand |
On 07/03/2018 16:31, Zack Weinberg wrote: > There are two flags currently defined: SCANF_LDBL_IS_DBL is the mode > used by __nldbl_ scanf variants, and SCANF_ISOC99_A is the mode used > by __isoc99_ scanf variants. In this patch, the new functions honor > these flag bits if they're set, but they still also look at the > corresponding bits of environmental state, and callers all pass zero. > > The new functions do *not* have the "errp" argument possessed by > _IO_vfscanf and _IO_vfwscanf. All internal callers passed NULL for > that argument. External callers could theoretically exist, so I > preserved wrappers, but they are flagged as compat symbols and they > don't preserve the three-way distinction among types of errors that > was formerly exposed. These functions probably should have been in > the list of deprecated _IO_ symbols in 2.27 NEWS -- they're not just > aliases for vfscanf and vfwscanf. > > (It was necessary to introduce ldbl_compat_symbol for _IO_vfscanf. > Please check that part of the patch very carefully, I am still not > confident I understand all of the details of ldbl-opt.) > > This patch also introduces helper inlines in libio/strfile.h that > encapsulate the process of initializing an _IO_strfile object for > reading. This allows us to call __vfscanf_internal directly from > sscanf, and __vfwscanf_internal directly from swscanf, without > duplicating the initialization code. (Previously, they called their > v-counterparts, but that won't work if we want to control *both* C99 > mode and ldbl-is-dbl mode using the flags argument to__vfscanf_internal.) > It's still a little awkward, especially for wide strfiles, but it's > much better than what we had. Look good in general, some remarks below. > > * libio/libioP.h (SCANF_LDBL_IS_DBL, SCANF_ISOC99_A): New constants. > (__vfscanf_internal, __vfwscanf_internal): New function prototypes. > * libio/libio.h: Remove libc_hidden_proto for _IO_vfscanf. > * libio/strfile.h: Add multiple inclusion guard. > (_IO_strfile_read, _IO_strfile_readw): New inline functions. > > * sysdeps/generic/math_ldbl_opt.h: Include shlib-compat.h, for > consistency with the other version of this file. > (ldbl_compat_symbol): New macro. > * sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h (ldbl_compat_symbol): > New macro. > > * stdio-common/vfscanf-internal.c: Rename from vfscanf.c. > Define __vfscanf_internal or __vfwscanf_internal, depending on > COMPILE_WPRINTF; don't define any other public symbols. > Temporarily check __ldbl_is_dbl and _IO_FLAGS2_SCANF_STD as well > as the mode_flags argument. > (encode_error, conv_error, input_error): Don't set errval. > * stdio-common/vfwscanf-internal.c: Rename from vfwscanf.c. > Include vfscanf-internal.c. > * stdio-common/vfscanf.c, stdio-common/vfwscanf.c: New files > defining the public entry points vfscanf and vfwscanf respectively. > * stdio-common/iovfscanf.c, stdio-common/iovfwscanf.c: New files > defining the compat symbols _IO_vfscanf and _IO_vfwscanf respectively. > * stdio-common/Makefile (routines): Add vfscanf-internal, > vfwscanf-internal, iovfscanf, iovfwscanf. > * stdio-common/Versions: Mention GLIBC_2.28, so that > it can be used in SHLIB_COMPAT expressions. > * sysdeps/ieee754/ldbl-opt/nldbl-compat.c (__nldbl__IO_vfscanf): > Wrap definition and compat_symbol line in #if SHLIB_COMPAT. > > * libio/iovsscanf.c, libio/vscanf.c, libio/vwscanf.c, libio/wscanf.c > * libio/iovswscanf.c, stdio-common/isoc99_fscanf.c > * stdio-common/isoc99_scanf.c, stdio-common/isoc99_vfscanf.c > * stdio-common/isoc99_vscanf.c, stdio-common/isoc99_vsscanf.c > * stdio-common/scanf.c, sysdeps/ieee754/ldbl-opt/nldbl-compat.c > * wcsmbs/isoc99_fwscanf.c, wcsmbs/isoc99_vfwscanf.c > * wcsmbs/isoc99_vswscanf.c, wcsmbs/isoc99_vwscanf.c > * wcsmbs/isoc99_wscanf.c: Use __vfscanf_internal instead of > _IO_vfscanf, and/or __vfwscanf_internal instead of _IO_vfwscanf. > > * libio/iovsscanf.c, stdio-common/isoc99_vsscanf.c: > Use _IO_strfile_read. Clean up includes. > * stdio-common/sscanf.c, stdio-common/isoc99_sscanf.c: > Use _IO_strfile_read to set up a FILE, and then call > __vfwcanf_internal directly. Clean up includes. > > * libio/iovswscanf.c, wcsmbs/isoc99_vswscanf.c: > Use _IO_strfile_readw. Clean up includes. > * libio/swscanf.c, wcsmbs/isoc99_swscanf.c: > Use _IO_strfile_readw to set up a FILE, and then call > __vfwscanf_internal directly. Clean up includes. > --- > libio/iovsscanf.c | 12 +- > libio/iovswscanf.c | 14 +- > libio/libio.h | 1 - > libio/libioP.h | 9 + > libio/strfile.h | 33 +- > libio/swscanf.c | 10 +- > libio/vscanf.c | 2 +- > libio/vwscanf.c | 2 +- > libio/wscanf.c | 2 +- > stdio-common/Makefile | 3 +- > stdio-common/Versions | 3 + > stdio-common/iovfscanf.c | 34 + > stdio-common/iovfwscanf.c | 34 + > stdio-common/isoc99_fscanf.c | 2 +- > stdio-common/isoc99_scanf.c | 2 +- > stdio-common/isoc99_sscanf.c | 8 +- > stdio-common/isoc99_vfscanf.c | 2 +- > stdio-common/isoc99_vscanf.c | 2 +- > stdio-common/isoc99_vsscanf.c | 17 +- > stdio-common/scanf.c | 2 +- > stdio-common/sscanf.c | 12 +- > stdio-common/{vfscanf.c => vfscanf-internal.c} | 46 +- > stdio-common/vfscanf.c | 27 + > stdio-common/{vfwscanf.c => vfwscanf-internal.c} | 2 +- > stdio-common/vfwscanf.c | 25 + > sysdeps/generic/math_ldbl_opt.h | 4 + > sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h | 4 + > sysdeps/ieee754/ldbl-opt/nldbl-compat.c | 12 +- > wcsmbs/isoc99_fwscanf.c | 2 +- > wcsmbs/isoc99_swscanf.c | 12 +- > wcsmbs/isoc99_vfwscanf.c | 2 +- > wcsmbs/isoc99_vswscanf.c | 16 +- > wcsmbs/isoc99_vwscanf.c | 2 +- > wcsmbs/isoc99_wscanf.c | 2 +- > 34 files changed, 211 insertions(+), 115 deletions(-) > create mode 100644 stdio-common/iovfscanf.c > create mode 100644 stdio-common/iovfwscanf.c > create mode 100644 stdio-common/vfscanf.c > create mode 100644 stdio-common/vfwscanf.c > > diff --git a/libio/iovsscanf.c b/libio/iovsscanf.c > index e56ab8bd7d..ee6a99ec6a 100644 > --- a/libio/iovsscanf.c > +++ b/libio/iovsscanf.c > @@ -24,22 +24,14 @@ > This exception applies to code released by its copyright holders > in files containing the exception. */ > > -#include "libioP.h" > #include "strfile.h" > > int > _IO_vsscanf (const char *string, const char *format, va_list args) > { > - int ret; > _IO_strfile sf; > -#ifdef _IO_MTSAFE_IO > - sf._sbf._f._lock = NULL; > -#endif > - _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL); > - _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; > - _IO_str_init_static_internal (&sf, (char*)string, 0, NULL); > - ret = _IO_vfscanf (&sf._sbf._f, format, args, NULL); > - return ret; > + FILE *f = _IO_strfile_read (&sf, string); > + return __vfscanf_internal (f, format, args, 0); > } > ldbl_weak_alias (_IO_vsscanf, __vsscanf) > ldbl_weak_alias (_IO_vsscanf, vsscanf) Ok. > diff --git a/libio/iovswscanf.c b/libio/iovswscanf.c > index 5bd1c88412..cb9cbe15cc 100644 > --- a/libio/iovswscanf.c > +++ b/libio/iovswscanf.c > @@ -24,24 +24,16 @@ > This exception applies to code released by its copyright holders > in files containing the exception. */ > > -#include "libioP.h" > -#include "strfile.h" > #include <wchar.h> > +#include "strfile.h" > > int > __vswscanf (const wchar_t *string, const wchar_t *format, va_list args) > { > - int ret; > _IO_strfile sf; > struct _IO_wide_data wd; > -#ifdef _IO_MTSAFE_IO > - sf._sbf._f._lock = NULL; > -#endif > - _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, 0, &wd, &_IO_wstr_jumps); > - _IO_fwide (&sf._sbf._f, 1); > - _IO_wstr_init_static (&sf._sbf._f, (wchar_t *)string, 0, NULL); > - ret = _IO_vfwscanf ((FILE *) &sf._sbf, format, args, NULL); > - return ret; > + FILE *f = _IO_strfile_readw (&sf, &wd, string); > + return __vfwscanf_internal (f, format, args, 0); > } > libc_hidden_def (__vswscanf) > ldbl_hidden_def (__vswscanf, vswscanf) Ok. > diff --git a/libio/libio.h b/libio/libio.h > index 00f9169613..d4eba2df54 100644 > --- a/libio/libio.h > +++ b/libio/libio.h > @@ -321,7 +321,6 @@ libc_hidden_proto (_IO_padn) > libc_hidden_proto (_IO_putc) > libc_hidden_proto (_IO_sgetn) > libc_hidden_proto (_IO_vfprintf) > -libc_hidden_proto (_IO_vfscanf) > > #ifdef _IO_MTSAFE_IO > # undef _IO_peekc Ok. > diff --git a/libio/libioP.h b/libio/libioP.h > index 8afe7032e3..a471c90be8 100644 > --- a/libio/libioP.h > +++ b/libio/libioP.h > @@ -704,6 +704,15 @@ extern off64_t _IO_seekpos_unlocked (FILE *, off64_t, int) > > #endif /* _G_HAVE_MMAP */ > > +/* Flags for __vfscanf_internal and __vfwscanf_internal. */ > +#define SCANF_LDBL_IS_DBL 0x0001 > +#define SCANF_ISOC99_A 0x0002 > + > +extern int __vfscanf_internal (FILE *fp, const char *format, va_list argp, > + unsigned int flags); > +extern int __vfwscanf_internal (FILE *fp, const wchar_t *format, va_list argp, > + unsigned int flags); > + > extern int _IO_vscanf (const char *, va_list) __THROW; > > #ifdef _IO_MTSAFE_IO Ok. > diff --git a/libio/strfile.h b/libio/strfile.h > index 46ac81809a..715149f5bd 100644 > --- a/libio/strfile.h > +++ b/libio/strfile.h > @@ -24,7 +24,9 @@ > This exception applies to code released by its copyright holders > in files containing the exception. */ > > -#include <stdio.h> > +#ifndef STRFILE_H_ > +#define STRFILE_H_ > + > #include "libioP.h" > > typedef void *(*_IO_alloc_type) (size_t); > @@ -81,3 +83,32 @@ typedef struct > } _IO_wstrnfile; > > extern const struct _IO_jump_t _IO_wstrn_jumps attribute_hidden; > + > +/* Initialize an _IO_strfile SF to read from narrow string STRING, and > + return the corresponding FILE object. It is not necessary to fclose > + the FILE when it is no longer needed. */ > +static inline FILE * > +_IO_strfile_read (_IO_strfile *sf, const char *string) > +{ > + sf->_sbf._f._lock = NULL; > + _IO_no_init (&sf->_sbf._f, _IO_USER_LOCK, -1, NULL, NULL); > + _IO_JUMPS (&sf->_sbf) = &_IO_str_jumps; > + _IO_str_init_static_internal (sf, (char*)string, 0, NULL); > + return &sf->_sbf._f; > +} Should we add a note about _IO_MTSAFE_IO cleanup? > + > +/* Initialize an _IO_strfile SF and _IO_wide_data WD to read from wide > + string STRING, and return the corresponding FILE object. It is not > + necessary to fclose the FILE when it is no longer needed. */ > +static inline FILE * > +_IO_strfile_readw (_IO_strfile *sf, struct _IO_wide_data *wd, > + const wchar_t *string) > +{ > + sf->_sbf._f._lock = NULL; > + _IO_no_init (&sf->_sbf._f, _IO_USER_LOCK, 0, wd, &_IO_wstr_jumps); > + _IO_fwide (&sf->_sbf._f, 1); > + _IO_wstr_init_static (&sf->_sbf._f, (wchar_t *)string, 0, NULL); > + return &sf->_sbf._f; > +} > + > +#endif /* strfile.h. */ Ok. > diff --git a/libio/swscanf.c b/libio/swscanf.c > index c8686bcbaf..90f721cc51 100644 > --- a/libio/swscanf.c > +++ b/libio/swscanf.c > @@ -15,20 +15,22 @@ > License along with the GNU C Library; if not, see > <http://www.gnu.org/licenses/>. */ > > -#include <libioP.h> > #include <stdarg.h> > -#include <wchar.h> > +#include "strfile.h" > > /* Read formatted input from S, according to the format string FORMAT. */ > -/* VARARGS2 */ > + > int > __swscanf (const wchar_t *s, const wchar_t *format, ...) > { > va_list arg; > int done; > + _IO_strfile sf; > + struct _IO_wide_data wd; > + FILE *f = _IO_strfile_readw (&sf, &wd, s); > > va_start (arg, format); > - done = __vswscanf (s, format, arg); > + done = __vfwscanf_internal (f, format, arg, 0); > va_end (arg); > > return done; Ok. > diff --git a/libio/vscanf.c b/libio/vscanf.c > index 9c27122c27..a3e2dd43f2 100644 > --- a/libio/vscanf.c > +++ b/libio/vscanf.c > @@ -32,6 +32,6 @@ > int > _IO_vscanf (const char *format, va_list args) > { > - return _IO_vfscanf (_IO_stdin, format, args, NULL); > + return __vfscanf_internal (_IO_stdin, format, args, 0); > } > ldbl_weak_alias (_IO_vscanf, vscanf) Ok. > diff --git a/libio/vwscanf.c b/libio/vwscanf.c > index 0d5f558758..7af770c8c3 100644 > --- a/libio/vwscanf.c > +++ b/libio/vwscanf.c > @@ -30,6 +30,6 @@ > int > __vwscanf (const wchar_t *format, va_list args) > { > - return _IO_vfwscanf (_IO_stdin, format, args, NULL); > + return __vfwscanf_internal (_IO_stdin, format, args, 0); > } > ldbl_strong_alias (__vwscanf, vwscanf) Ok. > diff --git a/libio/wscanf.c b/libio/wscanf.c > index c8cdad0acd..fe27ff6fa6 100644 > --- a/libio/wscanf.c > +++ b/libio/wscanf.c > @@ -30,7 +30,7 @@ __wscanf (const wchar_t *format, ...) > int done; > > va_start (arg, format); > - done = _IO_vfwscanf (stdin, format, arg, NULL); > + done = __vfwscanf_internal (stdin, format, arg, 0); > va_end (arg); > > return done; Ok. > diff --git a/stdio-common/Makefile b/stdio-common/Makefile > index 9dfc115313..b7b1f01bdd 100644 > --- a/stdio-common/Makefile > +++ b/stdio-common/Makefile > @@ -39,7 +39,8 @@ routines := \ > flockfile ftrylockfile funlockfile \ > isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \ > isoc99_vsscanf \ > - psiginfo gentempfd > + psiginfo gentempfd \ > + vfscanf-internal vfwscanf-internal iovfscanf iovfwscanf > > aux := errlist siglist printf-parsemb printf-parsewc fxprintf > Ok. > diff --git a/stdio-common/Versions b/stdio-common/Versions > index 5016f69c20..7af44949f7 100644 > --- a/stdio-common/Versions > +++ b/stdio-common/Versions > @@ -57,6 +57,9 @@ libc { > psiginfo; > register_printf_modifier; register_printf_type; register_printf_specifier; > } > + GLIBC_2.28 { > + # SHLIB_COMPAT(GLIBC_2_0, GLIBC_2_28) used in iovfscanf.c etc > + } > GLIBC_PRIVATE { > # global variables > _itoa_lower_digits; > diff --git a/stdio-common/iovfscanf.c b/stdio-common/iovfscanf.c > new file mode 100644 > index 0000000000..fb347d60cb > --- /dev/null > +++ b/stdio-common/iovfscanf.c > @@ -0,0 +1,34 @@ > +/* Copyright (C) 1991-2018 Free Software Foundation, Inc. > + This file is part of the GNU C Library. Missing one line description. > + > + 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 <libioP.h> > +#include <shlib-compat.h> > + > +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) > + > +int > +attribute_compat_text_section > +__IO_vfscanf (FILE *fp, const char *format, va_list ap, int *errp) > +{ > + int rv = __vfscanf_internal (fp, format, ap, 0); > + if (__glibc_unlikely (errp != 0)) > + *errp = (rv == -1); > + return rv; > +} > +ldbl_compat_symbol (libc, __IO_vfscanf, _IO_vfscanf, GLIBC_2_0); > + > +#endif > diff --git a/stdio-common/iovfwscanf.c b/stdio-common/iovfwscanf.c > new file mode 100644 > index 0000000000..73936f68b2 > --- /dev/null > +++ b/stdio-common/iovfwscanf.c > @@ -0,0 +1,34 @@ > +/* Copyright (C) 1991-2018 Free Software Foundation, Inc. > + This file is part of the GNU C Library. Missing one line description. > + > + 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 <libioP.h> > +#include <shlib-compat.h> > + > +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) > + > +int > +attribute_compat_text_section > +__IO_vfwscanf (FILE *fp, const wchar_t *format, va_list ap, int *errp) > +{ > + int rv = __vfwscanf_internal (fp, format, ap, 0); > + if (__glibc_unlikely (errp != 0)) > + *errp = (rv == -1); > + return rv; > +} > +compat_symbol (libc, __IO_vfwscanf, _IO_vfwscanf, GLIBC_2_0); > + > +#endif > diff --git a/stdio-common/isoc99_fscanf.c b/stdio-common/isoc99_fscanf.c > index 9cdf85e679..4210d11f2b 100644 > --- a/stdio-common/isoc99_fscanf.c > +++ b/stdio-common/isoc99_fscanf.c > @@ -31,7 +31,7 @@ __isoc99_fscanf (FILE *stream, const char *format, ...) > stream->_flags2 |= _IO_FLAGS2_SCANF_STD; > > va_start (arg, format); > - done = _IO_vfscanf (stream, format, arg, NULL); > + done = __vfscanf_internal (stream, format, arg, 0); > va_end (arg); > > _IO_release_lock (stream); Ok. > diff --git a/stdio-common/isoc99_scanf.c b/stdio-common/isoc99_scanf.c > index bf7dbe86bb..64c873eed9 100644 > --- a/stdio-common/isoc99_scanf.c > +++ b/stdio-common/isoc99_scanf.c > @@ -34,7 +34,7 @@ __isoc99_scanf (const char *format, ...) > stdin->_flags2 |= _IO_FLAGS2_SCANF_STD; > > va_start (arg, format); > - done = _IO_vfscanf (stdin, format, arg, NULL); > + done = __vfscanf_internal (stdin, format, arg, 0); > va_end (arg); > > #ifdef _IO_MTSAFE_IO Ok. > diff --git a/stdio-common/isoc99_sscanf.c b/stdio-common/isoc99_sscanf.c > index 56a60a2c05..95b94a68b5 100644 > --- a/stdio-common/isoc99_sscanf.c > +++ b/stdio-common/isoc99_sscanf.c > @@ -16,8 +16,7 @@ > <http://www.gnu.org/licenses/>. */ > > #include <stdarg.h> > -#include <stdio.h> > -#include <libioP.h> > +#include <libio/strfile.h> > > /* Read formatted input from S, according to the format string FORMAT. */ > /* VARARGS2 */ I think you can cleanup this VARARGS2 comment as before. > @@ -26,9 +25,12 @@ __isoc99_sscanf (const char *s, const char *format, ...) > { > va_list arg; > int done; > + _IO_strfile sf; > + FILE *f = _IO_strfile_read (&sf, s); > + f->_flags2 |= _IO_FLAGS2_SCANF_STD; > > va_start (arg, format); > - done = __isoc99_vsscanf (s, format, arg); > + done = __vfscanf_internal (f, format, arg, 0); > va_end (arg); > > return done; Ok. > diff --git a/stdio-common/isoc99_vfscanf.c b/stdio-common/isoc99_vfscanf.c > index b80e05f8db..c96ca831ae 100644 > --- a/stdio-common/isoc99_vfscanf.c > +++ b/stdio-common/isoc99_vfscanf.c > @@ -27,7 +27,7 @@ __isoc99_vfscanf (FILE *stream, const char *format, va_list args) > > _IO_acquire_lock_clear_flags2 (stream); > stream->_flags2 |= _IO_FLAGS2_SCANF_STD; > - done = _IO_vfscanf (stream, format, args, NULL); > + done = __vfscanf_internal (stream, format, args, 0); > _IO_release_lock (stream); > return done; > } Ok. > diff --git a/stdio-common/isoc99_vscanf.c b/stdio-common/isoc99_vscanf.c > index 0b747f85ba..72ae72ddee 100644 > --- a/stdio-common/isoc99_vscanf.c > +++ b/stdio-common/isoc99_vscanf.c > @@ -27,7 +27,7 @@ __isoc99_vscanf (const char *format, va_list args) > > _IO_acquire_lock_clear_flags2 (stdin); > stdin->_flags2 |= _IO_FLAGS2_SCANF_STD; > - done = _IO_vfscanf (stdin, format, args, NULL); > + done = __vfscanf_internal (stdin, format, args, 0); > _IO_release_lock (stdin); > return done; > } Ok. > diff --git a/stdio-common/isoc99_vsscanf.c b/stdio-common/isoc99_vsscanf.c > index ac85ef2d0d..02bc0f50e6 100644 > --- a/stdio-common/isoc99_vsscanf.c > +++ b/stdio-common/isoc99_vsscanf.c > @@ -24,23 +24,14 @@ > This exception applies to code released by its copyright holders > in files containing the exception. */ > > -#include <libioP.h> > -#include <stdio.h> > -#include "../libio/strfile.h" > +#include <libio/strfile.h> > > int > __isoc99_vsscanf (const char *string, const char *format, va_list args) > { > - int ret; > _IO_strfile sf; > -#ifdef _IO_MTSAFE_IO > - sf._sbf._f._lock = NULL; > -#endif > - _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL); > - _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; > - _IO_str_init_static_internal (&sf, (char*)string, 0, NULL); > - sf._sbf._f._flags2 |= _IO_FLAGS2_SCANF_STD; > - ret = _IO_vfscanf (&sf._sbf._f, format, args, NULL); > - return ret; > + FILE *f = _IO_strfile_read (&sf, string); > + f->_flags2 |= _IO_FLAGS2_SCANF_STD; > + return __vfscanf_internal (f, format, args, 0); > } > libc_hidden_def (__isoc99_vsscanf) Ok. > diff --git a/stdio-common/scanf.c b/stdio-common/scanf.c > index e61b5f1ad3..de38d70353 100644 > --- a/stdio-common/scanf.c > +++ b/stdio-common/scanf.c > @@ -30,7 +30,7 @@ __scanf (const char *format, ...) > int done; > > va_start (arg, format); > - done = _IO_vfscanf (stdin, format, arg, NULL); > + done = __vfscanf_internal (stdin, format, arg, 0); > va_end (arg); > > return done; Ok. > diff --git a/stdio-common/sscanf.c b/stdio-common/sscanf.c > index 88cd641798..e25e9c27a5 100644 > --- a/stdio-common/sscanf.c > +++ b/stdio-common/sscanf.c > @@ -16,26 +16,24 @@ > <http://www.gnu.org/licenses/>. */ > > #include <stdarg.h> > -#include <stdio.h> > -#include <libioP.h> > -#define __vsscanf(s, f, a) _IO_vsscanf (s, f, a) > +#include <libio/strfile.h> > > /* Read formatted input from S, according to the format string FORMAT. */ > -/* VARARGS2 */ > + > int > __sscanf (const char *s, const char *format, ...) > { > va_list arg; > int done; > + _IO_strfile sf; > + FILE *f = _IO_strfile_read (&sf, s); > > va_start (arg, format); > - done = __vsscanf (s, format, arg); > + done = __vfscanf_internal (f, format, arg, 0); > va_end (arg); > > return done; > } > ldbl_hidden_def (__sscanf, sscanf) > ldbl_strong_alias (__sscanf, sscanf) > -#undef _IO_sscanf > -/* This is for libg++. */ > ldbl_strong_alias (__sscanf, _IO_sscanf) Ok. > diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf-internal.c > similarity index 98% > rename from stdio-common/vfscanf.c > rename to stdio-common/vfscanf-internal.c > index 3263268c7e..93b07ad4bc 100644 > --- a/stdio-common/vfscanf.c > +++ b/stdio-common/vfscanf-internal.c > @@ -132,16 +132,13 @@ > #include "printf-parse.h" /* Use read_int. */ > > #define encode_error() do { \ > - errval = 4; \ > __set_errno (EILSEQ); \ > goto errout; \ > } while (0) > #define conv_error() do { \ > - errval = 2; \ > goto errout; \ > } while (0) > #define input_error() do { \ > - errval = 1; \ > if (done == 0) done = EOF; \ > goto errout; \ > } while (0) > @@ -267,12 +264,12 @@ 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 (FILE *s, const wchar_t *format, va_list argptr, > - int *errp) > +__vfwscanf_internal (FILE *s, const wchar_t *format, va_list argptr, > + unsigned int mode_flags) > #else > int > -_IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, > - int *errp) > +__vfscanf_internal (FILE *s, const char *format, va_list argptr, > + unsigned int mode_flags) > #endif > { > va_list arg; > @@ -283,7 +280,6 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, > WINT_T c = 0; /* Last char read. */ > int width; /* Maximum field width. */ > int flags; /* Modifiers for current format element. */ > - int errval = 0; > #ifndef COMPILE_WSCANF > locale_t loc = _NL_CURRENT_LOCALE; > struct __locale_data *const curctype = loc->__locales[LC_CTYPE]; > @@ -335,6 +331,14 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, > struct char_buffer charbuf; > scratch_buffer_init (&charbuf.scratch); > > +#define LDBL_DISTINCT (__glibc_likely ((mode_flags & SCANF_LDBL_IS_DBL) == 0)) > +#define USE_ISOC99_A (__glibc_likely (mode_flags & SCANF_ISOC99_A)) > + /* Temporarily honor the environmental mode bits. */ > + if (__ldbl_is_dbl) > + mode_flags |= SCANF_LDBL_IS_DBL; > + if (s->_flags2 & _IO_FLAGS2_SCANF_STD) > + mode_flags |= SCANF_ISOC99_A; > + > #ifdef __va_copy > __va_copy (arg, argptr); > #else > @@ -566,7 +570,7 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, > } > /* In __isoc99_*scanf %as, %aS and %a[ extension is not > supported at all. */ > - if (s->_flags2 & _IO_FLAGS2_SCANF_STD) > + if (USE_ISOC99_A) > { > --f; > break; > @@ -2422,7 +2426,7 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, > done = EOF; > goto errout; > } > - if ((flags & LONGDBL) && !__ldbl_is_dbl) > + if ((flags & LONGDBL) && LDBL_DISTINCT) > { > long double d = __strtold_internal > (char_buffer_start (&charbuf), &tw, flags & GROUP); > @@ -3017,8 +3021,6 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, > UNLOCK_STREAM (s); > > scratch_buffer_free (&charbuf.scratch); > - if (errp != NULL) > - *errp |= errval; > > if (__glibc_unlikely (done == EOF)) > { > @@ -3044,23 +3046,3 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, > } > return done; > } > - > -#ifdef COMPILE_WSCANF > -int > -__vfwscanf (FILE *s, const wchar_t *format, va_list argptr) > -{ > - return _IO_vfwscanf (s, format, argptr, NULL); > -} > -ldbl_weak_alias (__vfwscanf, vfwscanf) > -#else > -int > -___vfscanf (FILE *s, const char *format, va_list argptr) > -{ > - return _IO_vfscanf_internal (s, format, argptr, NULL); > -} > -ldbl_strong_alias (_IO_vfscanf_internal, _IO_vfscanf) > -ldbl_hidden_def (_IO_vfscanf_internal, _IO_vfscanf) > -ldbl_strong_alias (___vfscanf, __vfscanf) > -ldbl_hidden_def (___vfscanf, __vfscanf) > -ldbl_weak_alias (___vfscanf, vfscanf) > -#endif Ok. > diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c > index 0000000000..5eedca8340 100644 > --- /dev/null 2018-02-21 11:21:31.435874074 -0500 > +++ b/stdio-common/vfscanf.c 2018-03-07 08:44:37.578545222 -0500 > @@ -0,0 +1,27 @@ > +/* Copyright (C) 1991-2018 Free Software Foundation, Inc. > + This file is part of the GNU C Library. Missing one line description. > + > + 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 <libioP.h> > + > +int > +___vfscanf (FILE *s, const char *format, va_list argptr) > +{ > + return __vfscanf_internal (s, format, argptr, 0); > +} > +ldbl_strong_alias (___vfscanf, __vfscanf) > +ldbl_hidden_def (___vfscanf, __vfscanf) > +ldbl_weak_alias (___vfscanf, vfscanf) Ok. > diff --git a/stdio-common/vfwscanf.c b/stdio-common/vfwscanf-internal.c > similarity index 50% > rename from stdio-common/vfscanf.c > rename to stdio-common/vfscanf-internal.c > index 26b1a66608..26c89270b7 100644 > --- a/stdio-common/vfwscanf.c > +++ b/stdio-common/vfwscanf-internal.c > @@ -1,2 +1,2 @@ > #define COMPILE_WSCANF 1 > -#include "vfscanf.c" > +#include "vfscanf-internal.c" Ok. > diff --git a/stdio-common/vfwscanf.c b/stdio-common/vfwscanf.c > new file mode 100644 > index 0000000000..0554b7eae1 > --- a/stdio-common/vfwscanf.c > +++ b/stdio-common/vfwscanf.c > @@ -0,0 +1,25 @@ > +/* Copyright (C) 1991-2018 Free Software Foundation, Inc. > + This file is part of the GNU C Library. Missing one line description. > + > + 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 <libioP.h> > + > +int > +__vfwscanf (FILE *s, const wchar_t *format, va_list argptr) > +{ > + return __vfwscanf_internal (s, format, argptr, 0); > +} > +ldbl_weak_alias (__vfwscanf, vfwscanf) Ok. > diff --git a/sysdeps/generic/math_ldbl_opt.h b/sysdeps/generic/math_ldbl_opt.h > index 8a5d8ba107..92f670dff7 100644 > --- a/sysdeps/generic/math_ldbl_opt.h > +++ b/sysdeps/generic/math_ldbl_opt.h > @@ -6,9 +6,13 @@ > for platforms where compatibility symbols are required for a previous > ABI that defined long double functions as aliases for the double code. */ > > +#include <shlib-compat.h> > + > #define LONG_DOUBLE_COMPAT(lib, introduced) 0 > #define long_double_symbol(lib, local, symbol) > #define ldbl_hidden_def(local, name) libc_hidden_def (name) > #define ldbl_strong_alias(name, aliasname) strong_alias (name, aliasname) > #define ldbl_weak_alias(name, aliasname) weak_alias (name, aliasname) > +#define ldbl_compat_symbol(lib, local, symbol, version) \ > + compat_symbol (lib, local, symbol, version) > #define __ldbl_is_dbl 0 Isn't the idea that if long double being a different type than double the compat symbols are not really required? I think this should be just an empty macro. > diff --git a/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h b/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h > index af861c11ea..ee70d085fd 100644 > --- a/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h > +++ b/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h > @@ -20,10 +20,14 @@ > long_double_symbol (libc, __GL_##name##_##aliasname, aliasname); > # define long_double_symbol_1(lib, local, symbol, version) \ > versioned_symbol (lib, local, symbol, version) > +# define ldbl_compat_symbol(lib, local, symbol, version) \ > + compat_symbol (lib, local, symbol, LONG_DOUBLE_COMPAT_VERSION) > #else > # define ldbl_hidden_def(local, name) libc_hidden_def (name) > # define ldbl_strong_alias(name, aliasname) strong_alias (name, aliasname) > # define ldbl_weak_alias(name, aliasname) weak_alias (name, aliasname) > +# define ldbl_compat_symbol(lib, local, symbol, version) \ > + compat_symbol (lib, local, symbol, version) > # ifndef __ASSEMBLER__ > /* Note that weak_alias cannot be used - it is defined to nothing > in most of the C files. */ Ok. > diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c > index 7d19eaba8d..9ac88deb74 100644 > --- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c > +++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c > @@ -329,16 +329,20 @@ __nldbl_wprintf (const wchar_t *fmt, ...) > return done; > } > > +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) > int > attribute_compat_text_section > __nldbl__IO_vfscanf (FILE *s, const char *fmt, va_list ap, int *errp) > { > int res; > set_no_long_double (); > - res = _IO_vfscanf (s, fmt, ap, errp); > + res = __vfscanf_internal (s, fmt, ap, 0); > clear_no_long_double (); > + if (__glibc_unlikely (errp != 0)) > + *errp = (res == -1); > return res; > } > +#endif > > int > attribute_compat_text_section > @@ -346,7 +350,7 @@ __nldbl___vfscanf (FILE *s, const char *fmt, va_list ap) > { > int res; > set_no_long_double (); > - res = _IO_vfscanf (s, fmt, ap, NULL); > + res = __vfscanf_internal (s, fmt, ap, 0); > clear_no_long_double (); > return res; > } > @@ -422,7 +426,7 @@ __nldbl_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap) > { > int res; > set_no_long_double (); > - res = _IO_vfwscanf (s, fmt, ap, NULL); > + res = __vfwscanf_internal (s, fmt, ap, 0); > clear_no_long_double (); > return res; > } > @@ -1026,7 +1030,9 @@ compat_symbol (libc, __nldbl_vdprintf, vdprintf, GLIBC_2_0); > compat_symbol (libc, __nldbl_vsnprintf, vsnprintf, GLIBC_2_0); > compat_symbol (libc, __nldbl_vsprintf, vsprintf, GLIBC_2_0); > compat_symbol (libc, __nldbl__IO_sscanf, _IO_sscanf, GLIBC_2_0); > +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) > compat_symbol (libc, __nldbl__IO_vfscanf, _IO_vfscanf, GLIBC_2_0); > +#endif > compat_symbol (libc, __nldbl___vfscanf, __vfscanf, GLIBC_2_0); > compat_symbol (libc, __nldbl___vsscanf, __vsscanf, GLIBC_2_0); > compat_symbol (libc, __nldbl_fscanf, fscanf, GLIBC_2_0); I am not sure that nesting SHLIB_COMPAT is correct way logically and stylisc here: the compat symbol will be create only for ABI which initial version of GLIBC_2_0 (which might not be an issue with current ABIs that requires ldbl to dbl compat symbol). Should we just add it on the end of the list? > diff --git a/wcsmbs/isoc99_fwscanf.c b/wcsmbs/isoc99_fwscanf.c > index 0c6a2c47ac..00b07dd48e 100644 > --- a/wcsmbs/isoc99_fwscanf.c > +++ b/wcsmbs/isoc99_fwscanf.c > @@ -32,7 +32,7 @@ __isoc99_fwscanf (FILE *stream, const wchar_t *format, ...) > stream->_flags2 |= _IO_FLAGS2_SCANF_STD; > > va_start (arg, format); > - done = _IO_vfwscanf (stream, format, arg, NULL); > + done = __vfwscanf_internal (stream, format, arg, 0); > va_end (arg); > > _IO_release_lock (stream); Ok. > diff --git a/wcsmbs/isoc99_swscanf.c b/wcsmbs/isoc99_swscanf.c > index ff523db706..40401d0aa1 100644 > --- a/wcsmbs/isoc99_swscanf.c > +++ b/wcsmbs/isoc99_swscanf.c > @@ -16,20 +16,22 @@ > <http://www.gnu.org/licenses/>. */ > > #include <stdarg.h> > -#include <stdio.h> > -#include <libioP.h> > -#include <wchar.h> > +#include <libio/strfile.h> > > /* Read formatted input from S, according to the format string FORMAT. */ > -/* VARARGS2 */ > + > int > __isoc99_swscanf (const wchar_t *s, const wchar_t *format, ...) > { > va_list arg; > int done; > + _IO_strfile sf; > + struct _IO_wide_data wd; > + FILE *f = _IO_strfile_readw (&sf, &wd, s); > + f->_flags2 |= _IO_FLAGS2_SCANF_STD; > > va_start (arg, format); > - done = __isoc99_vswscanf (s, format, arg); > + done = __vfwscanf_internal (f, format, arg, 0); > va_end (arg); > > return done; Ok. > diff --git a/wcsmbs/isoc99_vfwscanf.c b/wcsmbs/isoc99_vfwscanf.c > index 7beb45b4d3..f70c6b596d 100644 > --- a/wcsmbs/isoc99_vfwscanf.c > +++ b/wcsmbs/isoc99_vfwscanf.c > @@ -28,7 +28,7 @@ __isoc99_vfwscanf (FILE *stream, const wchar_t *format, va_list args) > > _IO_acquire_lock_clear_flags2 (stream); > stream->_flags2 |= _IO_FLAGS2_SCANF_STD; > - done = _IO_vfwscanf (stream, format, args, NULL); > + done = __vfwscanf_internal (stream, format, args, 0); > _IO_release_lock (stream); > return done; > } Ok. > diff --git a/wcsmbs/isoc99_vswscanf.c b/wcsmbs/isoc99_vswscanf.c > index 130769154d..b91eb651a3 100644 > --- a/wcsmbs/isoc99_vswscanf.c > +++ b/wcsmbs/isoc99_vswscanf.c > @@ -24,24 +24,16 @@ > This exception applies to code released by its copyright holders > in files containing the exception. */ > > -#include <libioP.h> > #include <wchar.h> > -#include "../libio/strfile.h" > +#include <libio/strfile.h> > > int > __isoc99_vswscanf (const wchar_t *string, const wchar_t *format, va_list args) > { > - int ret; > _IO_strfile sf; > struct _IO_wide_data wd; > -#ifdef _IO_MTSAFE_IO > - sf._sbf._f._lock = NULL; > -#endif > - _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, 0, &wd, &_IO_wstr_jumps); > - _IO_fwide (&sf._sbf._f, 1); > - _IO_wstr_init_static (&sf._sbf._f, (wchar_t *)string, 0, NULL); > - sf._sbf._f._flags2 |= _IO_FLAGS2_SCANF_STD; > - ret = _IO_vfwscanf ((FILE *) &sf._sbf, format, args, NULL); > - return ret; > + FILE *f = _IO_strfile_readw (&sf, &wd, string); > + f->_flags2 |= _IO_FLAGS2_SCANF_STD; > + return __vfwscanf_internal (f, format, args, 0); > } > libc_hidden_def (__isoc99_vswscanf) Ok. > diff --git a/wcsmbs/isoc99_vwscanf.c b/wcsmbs/isoc99_vwscanf.c > index 049521b964..eb22c8acae 100644 > --- a/wcsmbs/isoc99_vwscanf.c > +++ b/wcsmbs/isoc99_vwscanf.c > @@ -28,7 +28,7 @@ __isoc99_vwscanf (const wchar_t *format, va_list args) > > _IO_acquire_lock_clear_flags2 (stdin); > stdin->_flags2 |= _IO_FLAGS2_SCANF_STD; > - done = _IO_vfwscanf (stdin, format, args, NULL); > + done = __vfwscanf_internal (stdin, format, args, 0); > _IO_release_lock (stdin); > return done; > } Ok. > diff --git a/wcsmbs/isoc99_wscanf.c b/wcsmbs/isoc99_wscanf.c > index abfbd50c11..59f80d78fb 100644 > --- a/wcsmbs/isoc99_wscanf.c > +++ b/wcsmbs/isoc99_wscanf.c > @@ -33,7 +33,7 @@ __isoc99_wscanf (const wchar_t *format, ...) > stdin->_flags2 |= _IO_FLAGS2_SCANF_STD; > > va_start (arg, format); > - done = _IO_vfwscanf (stdin, format, arg, NULL); > + done = __vfwscanf_internal (stdin, format, arg, 0); > va_end (arg); > > _IO_release_lock (stdin); > Ok.
On Wed, 07 Mar 2018, Zack Weinberg wrote: >(It was necessary to introduce ldbl_compat_symbol for _IO_vfscanf. >Please check that part of the patch very carefully, I am still not >confident I understand all of the details of ldbl-opt.) It looks good on powerpc64... Oldest symbol (where long double had the same format as double) is still there as a compat symbol with version GLIBC_2.3... The newer symbol, is a bit different, in the sense that it is now a compat symbol (it was a default symbol previously). Here's what readelf has to tell us: Before the patch set: 1355: 00000000001eea70 124 FUNC GLOBAL DEFAULT 27 _IO_vfscanf@GLIBC_2.3 1356: 00000000001f0a98 23552 FUNC GLOBAL DEFAULT 27 _IO_vfscanf@@GLIBC_2.4 After the patch set: 1355: 00000000001f0bd0 136 FUNC GLOBAL DEFAULT 27 _IO_vfscanf@GLIBC_2.4 1356: 00000000001ee968 136 FUNC GLOBAL DEFAULT 27 _IO_vfscanf@GLIBC_2.3 For the static library, I think that Adhemerval is right (see comment below). > * libio/libioP.h (SCANF_LDBL_IS_DBL, SCANF_ISOC99_A): New constants. > (__vfscanf_internal, __vfwscanf_internal): New function prototypes. > * libio/libio.h: Remove libc_hidden_proto for _IO_vfscanf. ~~~~~~~~ Spaces instead of tabs. > * libio/strfile.h: Add multiple inclusion guard. Perhaps mention the removal of stdio.h inclusion? > * stdio-common/Versions: Mention GLIBC_2.28, so that > it can be used in SHLIB_COMPAT expressions. ~~~~~~~~ Spaces instead of tabs. >+extern int __vfscanf_internal (FILE *fp, const char *format, va_list argp, >+ unsigned int flags); ~~~~~~~~~~~~~~~~~~~~~~~~ >+extern int __vfwscanf_internal (FILE *fp, const wchar_t *format, va_list argp, >+ unsigned int flags); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Spaces instead of tabs. >+/* Initialize an _IO_strfile SF and _IO_wide_data WD to read from wide >+ string STRING, and return the corresponding FILE object. It is not >+ necessary to fclose the FILE when it is no longer needed. */ >+static inline FILE * >+_IO_strfile_readw (_IO_strfile *sf, struct _IO_wide_data *wd, >+ const wchar_t *string) ~~~~~~~~~~~~~~~~ Spaces instead of tabs. >--- /dev/null >+++ b/stdio-common/iovfscanf.c >@@ -0,0 +1,34 @@ >+/* Copyright (C) 1991-2018 Free Software Foundation, Inc. Should this (and other new files) be copyright 2018, since they're new? >--- a/stdio-common/vfscanf.c >+++ b/stdio-common/vfscanf-internal.c >-_IO_vfwscanf (FILE *s, const wchar_t *format, va_list argptr, >- int *errp) >+__vfwscanf_internal (FILE *s, const wchar_t *format, va_list argptr, >+ unsigned int mode_flags) ~~~~~~~~~~~~~~~~ Spaces instead of tabs. >-_IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, >- int *errp) >+__vfscanf_internal (FILE *s, const char *format, va_list argptr, >+ unsigned int mode_flags) ~~~~~~~~~~~~~~~~ Spaces instead of tabs. >--- a/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h >+++ b/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h >@@ -20,10 +20,14 @@ > long_double_symbol (libc, __GL_##name##_##aliasname, aliasname); > # define long_double_symbol_1(lib, local, symbol, version) \ > versioned_symbol (lib, local, symbol, version) >+# define ldbl_compat_symbol(lib, local, symbol, version) \ >+ compat_symbol (lib, local, symbol, LONG_DOUBLE_COMPAT_VERSION) > #else > # define ldbl_hidden_def(local, name) libc_hidden_def (name) > # define ldbl_strong_alias(name, aliasname) strong_alias (name, aliasname) > # define ldbl_weak_alias(name, aliasname) weak_alias (name, aliasname) >+# define ldbl_compat_symbol(lib, local, symbol, version) \ >+ compat_symbol (lib, local, symbol, version) I believe that Adhemerval's comment is correct and ldbl_compat_symbol should translate to nothing when building static libraries.
On 03/13/2018 01:35 PM, Adhemerval Zanella wrote: >> @@ -1026,7 +1030,9 @@ compat_symbol (libc, __nldbl_vdprintf, vdprintf, GLIBC_2_0); >> compat_symbol (libc, __nldbl_vsnprintf, vsnprintf, GLIBC_2_0); >> compat_symbol (libc, __nldbl_vsprintf, vsprintf, GLIBC_2_0); >> compat_symbol (libc, __nldbl__IO_sscanf, _IO_sscanf, GLIBC_2_0); >> +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) >> compat_symbol (libc, __nldbl__IO_vfscanf, _IO_vfscanf, GLIBC_2_0); >> +#endif >> compat_symbol (libc, __nldbl___vfscanf, __vfscanf, GLIBC_2_0); >> compat_symbol (libc, __nldbl___vsscanf, __vsscanf, GLIBC_2_0); >> compat_symbol (libc, __nldbl_fscanf, fscanf, GLIBC_2_0); > I am not sure that nesting SHLIB_COMPAT is correct way logically and stylisc here: > the compat symbol will be create only for ABI which initial version of GLIBC_2_0 > (which might not be an issue with current ABIs that requires ldbl to dbl compat > symbol). Wouldn't GLIBC_2_0 be expanded to the relevant default ABI baseline for the port and do the right thing here? Thanks, Florian
On 03/26/2018 05:27 PM, Gabriel F. T. Gomes wrote: > On Wed, 07 Mar 2018, Zack Weinberg wrote: > >> (It was necessary to introduce ldbl_compat_symbol for _IO_vfscanf. >> Please check that part of the patch very carefully, I am still not >> confident I understand all of the details of ldbl-opt.) > > It looks good on powerpc64... Oldest symbol (where long double had the > same format as double) is still there as a compat symbol with version > GLIBC_2.3... The newer symbol, is a bit different, in the sense that it > is now a compat symbol (it was a default symbol previously). > > Here's what readelf has to tell us: > > Before the patch set: > 1355: 00000000001eea70 124 FUNC GLOBAL DEFAULT 27 _IO_vfscanf@GLIBC_2.3 > 1356: 00000000001f0a98 23552 FUNC GLOBAL DEFAULT 27 _IO_vfscanf@@GLIBC_2.4 > > After the patch set: > 1355: 00000000001f0bd0 136 FUNC GLOBAL DEFAULT 27 _IO_vfscanf@GLIBC_2.4 > 1356: 00000000001ee968 136 FUNC GLOBAL DEFAULT 27 _IO_vfscanf@GLIBC_2.3 I think that's correct and intended because there is no user redirect to _IO_vfscanf in public headers, and libndbl_nonshared.a does not use this interface, either (it uses __nldbl__IO_vfscanf). >> --- a/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h >> +++ b/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h >> @@ -20,10 +20,14 @@ >> long_double_symbol (libc, __GL_##name##_##aliasname, aliasname); >> # define long_double_symbol_1(lib, local, symbol, version) \ >> versioned_symbol (lib, local, symbol, version) >> +# define ldbl_compat_symbol(lib, local, symbol, version) \ >> + compat_symbol (lib, local, symbol, LONG_DOUBLE_COMPAT_VERSION) >> #else >> # define ldbl_hidden_def(local, name) libc_hidden_def (name) >> # define ldbl_strong_alias(name, aliasname) strong_alias (name, aliasname) >> # define ldbl_weak_alias(name, aliasname) weak_alias (name, aliasname) >> +# define ldbl_compat_symbol(lib, local, symbol, version) \ >> + compat_symbol (lib, local, symbol, version) > > I believe that Adhemerval's comment is correct and ldbl_compat_symbol > should translate to nothing when building static libraries. The shared library should not contain any definition for the compat symbol. The SHLIB_COMPAT mechanism takes care of that. But I do wonder if we need this mechanism at all. Wouldn't it be more appropriate to define LONG_DOUBLE_COMPAT_VERSION by default, as GLIBC_2_0, and then just use compat_symbol (libc, __IO_vfscanf, _IO_vfscanf, LONG_DOUBLE_COMPAT_VERSION); ? This pretends that GLIBC_2_0 already underwent the long double transition, and this seems somewhat consistent to me. Thanks, Florian
On 03/07/2018 08:31 PM, Zack Weinberg wrote: > diff --git a/stdio-common/iovfwscanf.c b/stdio-common/iovfwscanf.c > new file mode 100644 > index 0000000000..73936f68b2 > --- /dev/null > +++ b/stdio-common/iovfwscanf.c > @@ -0,0 +1,34 @@ > +/* 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 <libioP.h> > +#include <shlib-compat.h> > + > +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) > + > +int > +attribute_compat_text_section > +__IO_vfwscanf (FILE *fp, const wchar_t *format, va_list ap, int *errp) > +{ > + int rv = __vfwscanf_internal (fp, format, ap, 0); > + if (__glibc_unlikely (errp != 0)) > + *errp = (rv == -1); > + return rv; > +} > +compat_symbol (libc, __IO_vfwscanf, _IO_vfwscanf, GLIBC_2_0); > + > +#endif _IO_vfwscanf was listed in <libio.h>, but never exported from the library. If it is not needed anymore, you can just drop the function. Thanks, Florian
On 03/07/2018 08:31 PM, Zack Weinberg wrote: > diff --git a/stdio-common/iovfscanf.c b/stdio-common/iovfscanf.c > new file mode 100644 > index 0000000000..fb347d60cb > --- /dev/null > +++ b/stdio-common/iovfscanf.c > @@ -0,0 +1,34 @@ > +/* 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 <libioP.h> > +#include <shlib-compat.h> > + > +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) > + > +int > +attribute_compat_text_section > +__IO_vfscanf (FILE *fp, const char *format, va_list ap, int *errp) > +{ > + int rv = __vfscanf_internal (fp, format, ap, 0); > + if (__glibc_unlikely (errp != 0)) > + *errp = (rv == -1); > + return rv; > +} > +ldbl_compat_symbol (libc, __IO_vfscanf, _IO_vfscanf, GLIBC_2_0); > + > +#endif Now that _IO_vfscanf is a compat symbol, its wrapper should be removed from the libnldbl_nonshared.a library. That is, the file sysdeps/ieee754/ldbl-opt/nldbl-iovfscanf.c should be deleted by this patch (and the makefile adjusted). Thanks, Florian
diff --git a/libio/iovsscanf.c b/libio/iovsscanf.c index e56ab8bd7d..ee6a99ec6a 100644 --- a/libio/iovsscanf.c +++ b/libio/iovsscanf.c @@ -24,22 +24,14 @@ This exception applies to code released by its copyright holders in files containing the exception. */ -#include "libioP.h" #include "strfile.h" int _IO_vsscanf (const char *string, const char *format, va_list args) { - int ret; _IO_strfile sf; -#ifdef _IO_MTSAFE_IO - sf._sbf._f._lock = NULL; -#endif - _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL); - _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; - _IO_str_init_static_internal (&sf, (char*)string, 0, NULL); - ret = _IO_vfscanf (&sf._sbf._f, format, args, NULL); - return ret; + FILE *f = _IO_strfile_read (&sf, string); + return __vfscanf_internal (f, format, args, 0); } ldbl_weak_alias (_IO_vsscanf, __vsscanf) ldbl_weak_alias (_IO_vsscanf, vsscanf) diff --git a/libio/iovswscanf.c b/libio/iovswscanf.c index 5bd1c88412..cb9cbe15cc 100644 --- a/libio/iovswscanf.c +++ b/libio/iovswscanf.c @@ -24,24 +24,16 @@ This exception applies to code released by its copyright holders in files containing the exception. */ -#include "libioP.h" -#include "strfile.h" #include <wchar.h> +#include "strfile.h" int __vswscanf (const wchar_t *string, const wchar_t *format, va_list args) { - int ret; _IO_strfile sf; struct _IO_wide_data wd; -#ifdef _IO_MTSAFE_IO - sf._sbf._f._lock = NULL; -#endif - _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, 0, &wd, &_IO_wstr_jumps); - _IO_fwide (&sf._sbf._f, 1); - _IO_wstr_init_static (&sf._sbf._f, (wchar_t *)string, 0, NULL); - ret = _IO_vfwscanf ((FILE *) &sf._sbf, format, args, NULL); - return ret; + FILE *f = _IO_strfile_readw (&sf, &wd, string); + return __vfwscanf_internal (f, format, args, 0); } libc_hidden_def (__vswscanf) ldbl_hidden_def (__vswscanf, vswscanf) diff --git a/libio/libio.h b/libio/libio.h index 00f9169613..d4eba2df54 100644 --- a/libio/libio.h +++ b/libio/libio.h @@ -321,7 +321,6 @@ libc_hidden_proto (_IO_padn) libc_hidden_proto (_IO_putc) libc_hidden_proto (_IO_sgetn) libc_hidden_proto (_IO_vfprintf) -libc_hidden_proto (_IO_vfscanf) #ifdef _IO_MTSAFE_IO # undef _IO_peekc diff --git a/libio/libioP.h b/libio/libioP.h index 8afe7032e3..a471c90be8 100644 --- a/libio/libioP.h +++ b/libio/libioP.h @@ -704,6 +704,15 @@ extern off64_t _IO_seekpos_unlocked (FILE *, off64_t, int) #endif /* _G_HAVE_MMAP */ +/* Flags for __vfscanf_internal and __vfwscanf_internal. */ +#define SCANF_LDBL_IS_DBL 0x0001 +#define SCANF_ISOC99_A 0x0002 + +extern int __vfscanf_internal (FILE *fp, const char *format, va_list argp, + unsigned int flags); +extern int __vfwscanf_internal (FILE *fp, const wchar_t *format, va_list argp, + unsigned int flags); + extern int _IO_vscanf (const char *, va_list) __THROW; #ifdef _IO_MTSAFE_IO diff --git a/libio/strfile.h b/libio/strfile.h index 46ac81809a..715149f5bd 100644 --- a/libio/strfile.h +++ b/libio/strfile.h @@ -24,7 +24,9 @@ This exception applies to code released by its copyright holders in files containing the exception. */ -#include <stdio.h> +#ifndef STRFILE_H_ +#define STRFILE_H_ + #include "libioP.h" typedef void *(*_IO_alloc_type) (size_t); @@ -81,3 +83,32 @@ typedef struct } _IO_wstrnfile; extern const struct _IO_jump_t _IO_wstrn_jumps attribute_hidden; + +/* Initialize an _IO_strfile SF to read from narrow string STRING, and + return the corresponding FILE object. It is not necessary to fclose + the FILE when it is no longer needed. */ +static inline FILE * +_IO_strfile_read (_IO_strfile *sf, const char *string) +{ + sf->_sbf._f._lock = NULL; + _IO_no_init (&sf->_sbf._f, _IO_USER_LOCK, -1, NULL, NULL); + _IO_JUMPS (&sf->_sbf) = &_IO_str_jumps; + _IO_str_init_static_internal (sf, (char*)string, 0, NULL); + return &sf->_sbf._f; +} + +/* Initialize an _IO_strfile SF and _IO_wide_data WD to read from wide + string STRING, and return the corresponding FILE object. It is not + necessary to fclose the FILE when it is no longer needed. */ +static inline FILE * +_IO_strfile_readw (_IO_strfile *sf, struct _IO_wide_data *wd, + const wchar_t *string) +{ + sf->_sbf._f._lock = NULL; + _IO_no_init (&sf->_sbf._f, _IO_USER_LOCK, 0, wd, &_IO_wstr_jumps); + _IO_fwide (&sf->_sbf._f, 1); + _IO_wstr_init_static (&sf->_sbf._f, (wchar_t *)string, 0, NULL); + return &sf->_sbf._f; +} + +#endif /* strfile.h. */ diff --git a/libio/swscanf.c b/libio/swscanf.c index c8686bcbaf..90f721cc51 100644 --- a/libio/swscanf.c +++ b/libio/swscanf.c @@ -15,20 +15,22 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <libioP.h> #include <stdarg.h> -#include <wchar.h> +#include "strfile.h" /* Read formatted input from S, according to the format string FORMAT. */ -/* VARARGS2 */ + int __swscanf (const wchar_t *s, const wchar_t *format, ...) { va_list arg; int done; + _IO_strfile sf; + struct _IO_wide_data wd; + FILE *f = _IO_strfile_readw (&sf, &wd, s); va_start (arg, format); - done = __vswscanf (s, format, arg); + done = __vfwscanf_internal (f, format, arg, 0); va_end (arg); return done; diff --git a/libio/vscanf.c b/libio/vscanf.c index 9c27122c27..a3e2dd43f2 100644 --- a/libio/vscanf.c +++ b/libio/vscanf.c @@ -32,6 +32,6 @@ int _IO_vscanf (const char *format, va_list args) { - return _IO_vfscanf (_IO_stdin, format, args, NULL); + return __vfscanf_internal (_IO_stdin, format, args, 0); } ldbl_weak_alias (_IO_vscanf, vscanf) diff --git a/libio/vwscanf.c b/libio/vwscanf.c index 0d5f558758..7af770c8c3 100644 --- a/libio/vwscanf.c +++ b/libio/vwscanf.c @@ -30,6 +30,6 @@ int __vwscanf (const wchar_t *format, va_list args) { - return _IO_vfwscanf (_IO_stdin, format, args, NULL); + return __vfwscanf_internal (_IO_stdin, format, args, 0); } ldbl_strong_alias (__vwscanf, vwscanf) diff --git a/libio/wscanf.c b/libio/wscanf.c index c8cdad0acd..fe27ff6fa6 100644 --- a/libio/wscanf.c +++ b/libio/wscanf.c @@ -30,7 +30,7 @@ __wscanf (const wchar_t *format, ...) int done; va_start (arg, format); - done = _IO_vfwscanf (stdin, format, arg, NULL); + done = __vfwscanf_internal (stdin, format, arg, 0); va_end (arg); return done; diff --git a/stdio-common/Makefile b/stdio-common/Makefile index 9dfc115313..b7b1f01bdd 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -39,7 +39,8 @@ routines := \ flockfile ftrylockfile funlockfile \ isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \ isoc99_vsscanf \ - psiginfo gentempfd + psiginfo gentempfd \ + vfscanf-internal vfwscanf-internal iovfscanf iovfwscanf aux := errlist siglist printf-parsemb printf-parsewc fxprintf diff --git a/stdio-common/Versions b/stdio-common/Versions index 5016f69c20..7af44949f7 100644 --- a/stdio-common/Versions +++ b/stdio-common/Versions @@ -57,6 +57,9 @@ libc { psiginfo; register_printf_modifier; register_printf_type; register_printf_specifier; } + GLIBC_2.28 { + # SHLIB_COMPAT(GLIBC_2_0, GLIBC_2_28) used in iovfscanf.c etc + } GLIBC_PRIVATE { # global variables _itoa_lower_digits; diff --git a/stdio-common/iovfscanf.c b/stdio-common/iovfscanf.c new file mode 100644 index 0000000000..fb347d60cb --- /dev/null +++ b/stdio-common/iovfscanf.c @@ -0,0 +1,34 @@ +/* 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 <libioP.h> +#include <shlib-compat.h> + +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) + +int +attribute_compat_text_section +__IO_vfscanf (FILE *fp, const char *format, va_list ap, int *errp) +{ + int rv = __vfscanf_internal (fp, format, ap, 0); + if (__glibc_unlikely (errp != 0)) + *errp = (rv == -1); + return rv; +} +ldbl_compat_symbol (libc, __IO_vfscanf, _IO_vfscanf, GLIBC_2_0); + +#endif diff --git a/stdio-common/iovfwscanf.c b/stdio-common/iovfwscanf.c new file mode 100644 index 0000000000..73936f68b2 --- /dev/null +++ b/stdio-common/iovfwscanf.c @@ -0,0 +1,34 @@ +/* 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 <libioP.h> +#include <shlib-compat.h> + +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) + +int +attribute_compat_text_section +__IO_vfwscanf (FILE *fp, const wchar_t *format, va_list ap, int *errp) +{ + int rv = __vfwscanf_internal (fp, format, ap, 0); + if (__glibc_unlikely (errp != 0)) + *errp = (rv == -1); + return rv; +} +compat_symbol (libc, __IO_vfwscanf, _IO_vfwscanf, GLIBC_2_0); + +#endif diff --git a/stdio-common/isoc99_fscanf.c b/stdio-common/isoc99_fscanf.c index 9cdf85e679..4210d11f2b 100644 --- a/stdio-common/isoc99_fscanf.c +++ b/stdio-common/isoc99_fscanf.c @@ -31,7 +31,7 @@ __isoc99_fscanf (FILE *stream, const char *format, ...) stream->_flags2 |= _IO_FLAGS2_SCANF_STD; va_start (arg, format); - done = _IO_vfscanf (stream, format, arg, NULL); + done = __vfscanf_internal (stream, format, arg, 0); va_end (arg); _IO_release_lock (stream); diff --git a/stdio-common/isoc99_scanf.c b/stdio-common/isoc99_scanf.c index bf7dbe86bb..64c873eed9 100644 --- a/stdio-common/isoc99_scanf.c +++ b/stdio-common/isoc99_scanf.c @@ -34,7 +34,7 @@ __isoc99_scanf (const char *format, ...) stdin->_flags2 |= _IO_FLAGS2_SCANF_STD; va_start (arg, format); - done = _IO_vfscanf (stdin, format, arg, NULL); + done = __vfscanf_internal (stdin, format, arg, 0); va_end (arg); #ifdef _IO_MTSAFE_IO diff --git a/stdio-common/isoc99_sscanf.c b/stdio-common/isoc99_sscanf.c index 56a60a2c05..95b94a68b5 100644 --- a/stdio-common/isoc99_sscanf.c +++ b/stdio-common/isoc99_sscanf.c @@ -16,8 +16,7 @@ <http://www.gnu.org/licenses/>. */ #include <stdarg.h> -#include <stdio.h> -#include <libioP.h> +#include <libio/strfile.h> /* Read formatted input from S, according to the format string FORMAT. */ /* VARARGS2 */ @@ -26,9 +25,12 @@ __isoc99_sscanf (const char *s, const char *format, ...) { va_list arg; int done; + _IO_strfile sf; + FILE *f = _IO_strfile_read (&sf, s); + f->_flags2 |= _IO_FLAGS2_SCANF_STD; va_start (arg, format); - done = __isoc99_vsscanf (s, format, arg); + done = __vfscanf_internal (f, format, arg, 0); va_end (arg); return done; diff --git a/stdio-common/isoc99_vfscanf.c b/stdio-common/isoc99_vfscanf.c index b80e05f8db..c96ca831ae 100644 --- a/stdio-common/isoc99_vfscanf.c +++ b/stdio-common/isoc99_vfscanf.c @@ -27,7 +27,7 @@ __isoc99_vfscanf (FILE *stream, const char *format, va_list args) _IO_acquire_lock_clear_flags2 (stream); stream->_flags2 |= _IO_FLAGS2_SCANF_STD; - done = _IO_vfscanf (stream, format, args, NULL); + done = __vfscanf_internal (stream, format, args, 0); _IO_release_lock (stream); return done; } diff --git a/stdio-common/isoc99_vscanf.c b/stdio-common/isoc99_vscanf.c index 0b747f85ba..72ae72ddee 100644 --- a/stdio-common/isoc99_vscanf.c +++ b/stdio-common/isoc99_vscanf.c @@ -27,7 +27,7 @@ __isoc99_vscanf (const char *format, va_list args) _IO_acquire_lock_clear_flags2 (stdin); stdin->_flags2 |= _IO_FLAGS2_SCANF_STD; - done = _IO_vfscanf (stdin, format, args, NULL); + done = __vfscanf_internal (stdin, format, args, 0); _IO_release_lock (stdin); return done; } diff --git a/stdio-common/isoc99_vsscanf.c b/stdio-common/isoc99_vsscanf.c index ac85ef2d0d..02bc0f50e6 100644 --- a/stdio-common/isoc99_vsscanf.c +++ b/stdio-common/isoc99_vsscanf.c @@ -24,23 +24,14 @@ This exception applies to code released by its copyright holders in files containing the exception. */ -#include <libioP.h> -#include <stdio.h> -#include "../libio/strfile.h" +#include <libio/strfile.h> int __isoc99_vsscanf (const char *string, const char *format, va_list args) { - int ret; _IO_strfile sf; -#ifdef _IO_MTSAFE_IO - sf._sbf._f._lock = NULL; -#endif - _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL); - _IO_JUMPS (&sf._sbf) = &_IO_str_jumps; - _IO_str_init_static_internal (&sf, (char*)string, 0, NULL); - sf._sbf._f._flags2 |= _IO_FLAGS2_SCANF_STD; - ret = _IO_vfscanf (&sf._sbf._f, format, args, NULL); - return ret; + FILE *f = _IO_strfile_read (&sf, string); + f->_flags2 |= _IO_FLAGS2_SCANF_STD; + return __vfscanf_internal (f, format, args, 0); } libc_hidden_def (__isoc99_vsscanf) diff --git a/stdio-common/scanf.c b/stdio-common/scanf.c index e61b5f1ad3..de38d70353 100644 --- a/stdio-common/scanf.c +++ b/stdio-common/scanf.c @@ -30,7 +30,7 @@ __scanf (const char *format, ...) int done; va_start (arg, format); - done = _IO_vfscanf (stdin, format, arg, NULL); + done = __vfscanf_internal (stdin, format, arg, 0); va_end (arg); return done; diff --git a/stdio-common/sscanf.c b/stdio-common/sscanf.c index 88cd641798..e25e9c27a5 100644 --- a/stdio-common/sscanf.c +++ b/stdio-common/sscanf.c @@ -16,26 +16,24 @@ <http://www.gnu.org/licenses/>. */ #include <stdarg.h> -#include <stdio.h> -#include <libioP.h> -#define __vsscanf(s, f, a) _IO_vsscanf (s, f, a) +#include <libio/strfile.h> /* Read formatted input from S, according to the format string FORMAT. */ -/* VARARGS2 */ + int __sscanf (const char *s, const char *format, ...) { va_list arg; int done; + _IO_strfile sf; + FILE *f = _IO_strfile_read (&sf, s); va_start (arg, format); - done = __vsscanf (s, format, arg); + done = __vfscanf_internal (f, format, arg, 0); va_end (arg); return done; } ldbl_hidden_def (__sscanf, sscanf) ldbl_strong_alias (__sscanf, sscanf) -#undef _IO_sscanf -/* This is for libg++. */ ldbl_strong_alias (__sscanf, _IO_sscanf) diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf-internal.c similarity index 98% rename from stdio-common/vfscanf.c rename to stdio-common/vfscanf-internal.c index 3263268c7e..93b07ad4bc 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf-internal.c @@ -132,16 +132,13 @@ #include "printf-parse.h" /* Use read_int. */ #define encode_error() do { \ - errval = 4; \ __set_errno (EILSEQ); \ goto errout; \ } while (0) #define conv_error() do { \ - errval = 2; \ goto errout; \ } while (0) #define input_error() do { \ - errval = 1; \ if (done == 0) done = EOF; \ goto errout; \ } while (0) @@ -267,12 +264,12 @@ 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 (FILE *s, const wchar_t *format, va_list argptr, - int *errp) +__vfwscanf_internal (FILE *s, const wchar_t *format, va_list argptr, + unsigned int mode_flags) #else int -_IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, - int *errp) +__vfscanf_internal (FILE *s, const char *format, va_list argptr, + unsigned int mode_flags) #endif { va_list arg; @@ -283,7 +280,6 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, WINT_T c = 0; /* Last char read. */ int width; /* Maximum field width. */ int flags; /* Modifiers for current format element. */ - int errval = 0; #ifndef COMPILE_WSCANF locale_t loc = _NL_CURRENT_LOCALE; struct __locale_data *const curctype = loc->__locales[LC_CTYPE]; @@ -335,6 +331,14 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, struct char_buffer charbuf; scratch_buffer_init (&charbuf.scratch); +#define LDBL_DISTINCT (__glibc_likely ((mode_flags & SCANF_LDBL_IS_DBL) == 0)) +#define USE_ISOC99_A (__glibc_likely (mode_flags & SCANF_ISOC99_A)) + /* Temporarily honor the environmental mode bits. */ + if (__ldbl_is_dbl) + mode_flags |= SCANF_LDBL_IS_DBL; + if (s->_flags2 & _IO_FLAGS2_SCANF_STD) + mode_flags |= SCANF_ISOC99_A; + #ifdef __va_copy __va_copy (arg, argptr); #else @@ -566,7 +570,7 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, } /* In __isoc99_*scanf %as, %aS and %a[ extension is not supported at all. */ - if (s->_flags2 & _IO_FLAGS2_SCANF_STD) + if (USE_ISOC99_A) { --f; break; @@ -2422,7 +2426,7 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, done = EOF; goto errout; } - if ((flags & LONGDBL) && !__ldbl_is_dbl) + if ((flags & LONGDBL) && LDBL_DISTINCT) { long double d = __strtold_internal (char_buffer_start (&charbuf), &tw, flags & GROUP); @@ -3017,8 +3021,6 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, UNLOCK_STREAM (s); scratch_buffer_free (&charbuf.scratch); - if (errp != NULL) - *errp |= errval; if (__glibc_unlikely (done == EOF)) { @@ -3044,23 +3046,3 @@ _IO_vfscanf_internal (FILE *s, const char *format, va_list argptr, } return done; } - -#ifdef COMPILE_WSCANF -int -__vfwscanf (FILE *s, const wchar_t *format, va_list argptr) -{ - return _IO_vfwscanf (s, format, argptr, NULL); -} -ldbl_weak_alias (__vfwscanf, vfwscanf) -#else -int -___vfscanf (FILE *s, const char *format, va_list argptr) -{ - return _IO_vfscanf_internal (s, format, argptr, NULL); -} -ldbl_strong_alias (_IO_vfscanf_internal, _IO_vfscanf) -ldbl_hidden_def (_IO_vfscanf_internal, _IO_vfscanf) -ldbl_strong_alias (___vfscanf, __vfscanf) -ldbl_hidden_def (___vfscanf, __vfscanf) -ldbl_weak_alias (___vfscanf, vfscanf) -#endif diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index 0000000000..5eedca8340 100644 --- /dev/null 2018-02-21 11:21:31.435874074 -0500 +++ b/stdio-common/vfscanf.c 2018-03-07 08:44:37.578545222 -0500 @@ -0,0 +1,27 @@ +/* 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 <libioP.h> + +int +___vfscanf (FILE *s, const char *format, va_list argptr) +{ + return __vfscanf_internal (s, format, argptr, 0); +} +ldbl_strong_alias (___vfscanf, __vfscanf) +ldbl_hidden_def (___vfscanf, __vfscanf) +ldbl_weak_alias (___vfscanf, vfscanf) diff --git a/stdio-common/vfwscanf.c b/stdio-common/vfwscanf-internal.c similarity index 50% rename from stdio-common/vfscanf.c rename to stdio-common/vfscanf-internal.c index 26b1a66608..26c89270b7 100644 --- a/stdio-common/vfwscanf.c +++ b/stdio-common/vfwscanf-internal.c @@ -1,2 +1,2 @@ #define COMPILE_WSCANF 1 -#include "vfscanf.c" +#include "vfscanf-internal.c" diff --git a/stdio-common/vfwscanf.c b/stdio-common/vfwscanf.c new file mode 100644 index 0000000000..0554b7eae1 --- a/stdio-common/vfwscanf.c +++ b/stdio-common/vfwscanf.c @@ -0,0 +1,25 @@ +/* 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 <libioP.h> + +int +__vfwscanf (FILE *s, const wchar_t *format, va_list argptr) +{ + return __vfwscanf_internal (s, format, argptr, 0); +} +ldbl_weak_alias (__vfwscanf, vfwscanf) diff --git a/sysdeps/generic/math_ldbl_opt.h b/sysdeps/generic/math_ldbl_opt.h index 8a5d8ba107..92f670dff7 100644 --- a/sysdeps/generic/math_ldbl_opt.h +++ b/sysdeps/generic/math_ldbl_opt.h @@ -6,9 +6,13 @@ for platforms where compatibility symbols are required for a previous ABI that defined long double functions as aliases for the double code. */ +#include <shlib-compat.h> + #define LONG_DOUBLE_COMPAT(lib, introduced) 0 #define long_double_symbol(lib, local, symbol) #define ldbl_hidden_def(local, name) libc_hidden_def (name) #define ldbl_strong_alias(name, aliasname) strong_alias (name, aliasname) #define ldbl_weak_alias(name, aliasname) weak_alias (name, aliasname) +#define ldbl_compat_symbol(lib, local, symbol, version) \ + compat_symbol (lib, local, symbol, version) #define __ldbl_is_dbl 0 diff --git a/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h b/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h index af861c11ea..ee70d085fd 100644 --- a/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h +++ b/sysdeps/ieee754/ldbl-opt/math_ldbl_opt.h @@ -20,10 +20,14 @@ long_double_symbol (libc, __GL_##name##_##aliasname, aliasname); # define long_double_symbol_1(lib, local, symbol, version) \ versioned_symbol (lib, local, symbol, version) +# define ldbl_compat_symbol(lib, local, symbol, version) \ + compat_symbol (lib, local, symbol, LONG_DOUBLE_COMPAT_VERSION) #else # define ldbl_hidden_def(local, name) libc_hidden_def (name) # define ldbl_strong_alias(name, aliasname) strong_alias (name, aliasname) # define ldbl_weak_alias(name, aliasname) weak_alias (name, aliasname) +# define ldbl_compat_symbol(lib, local, symbol, version) \ + compat_symbol (lib, local, symbol, version) # ifndef __ASSEMBLER__ /* Note that weak_alias cannot be used - it is defined to nothing in most of the C files. */ diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c index 7d19eaba8d..9ac88deb74 100644 --- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c +++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c @@ -329,16 +329,20 @@ __nldbl_wprintf (const wchar_t *fmt, ...) return done; } +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) int attribute_compat_text_section __nldbl__IO_vfscanf (FILE *s, const char *fmt, va_list ap, int *errp) { int res; set_no_long_double (); - res = _IO_vfscanf (s, fmt, ap, errp); + res = __vfscanf_internal (s, fmt, ap, 0); clear_no_long_double (); + if (__glibc_unlikely (errp != 0)) + *errp = (res == -1); return res; } +#endif int attribute_compat_text_section @@ -346,7 +350,7 @@ __nldbl___vfscanf (FILE *s, const char *fmt, va_list ap) { int res; set_no_long_double (); - res = _IO_vfscanf (s, fmt, ap, NULL); + res = __vfscanf_internal (s, fmt, ap, 0); clear_no_long_double (); return res; } @@ -422,7 +426,7 @@ __nldbl_vfwscanf (FILE *s, const wchar_t *fmt, va_list ap) { int res; set_no_long_double (); - res = _IO_vfwscanf (s, fmt, ap, NULL); + res = __vfwscanf_internal (s, fmt, ap, 0); clear_no_long_double (); return res; } @@ -1026,7 +1030,9 @@ compat_symbol (libc, __nldbl_vdprintf, vdprintf, GLIBC_2_0); compat_symbol (libc, __nldbl_vsnprintf, vsnprintf, GLIBC_2_0); compat_symbol (libc, __nldbl_vsprintf, vsprintf, GLIBC_2_0); compat_symbol (libc, __nldbl__IO_sscanf, _IO_sscanf, GLIBC_2_0); +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_28) compat_symbol (libc, __nldbl__IO_vfscanf, _IO_vfscanf, GLIBC_2_0); +#endif compat_symbol (libc, __nldbl___vfscanf, __vfscanf, GLIBC_2_0); compat_symbol (libc, __nldbl___vsscanf, __vsscanf, GLIBC_2_0); compat_symbol (libc, __nldbl_fscanf, fscanf, GLIBC_2_0); diff --git a/wcsmbs/isoc99_fwscanf.c b/wcsmbs/isoc99_fwscanf.c index 0c6a2c47ac..00b07dd48e 100644 --- a/wcsmbs/isoc99_fwscanf.c +++ b/wcsmbs/isoc99_fwscanf.c @@ -32,7 +32,7 @@ __isoc99_fwscanf (FILE *stream, const wchar_t *format, ...) stream->_flags2 |= _IO_FLAGS2_SCANF_STD; va_start (arg, format); - done = _IO_vfwscanf (stream, format, arg, NULL); + done = __vfwscanf_internal (stream, format, arg, 0); va_end (arg); _IO_release_lock (stream); diff --git a/wcsmbs/isoc99_swscanf.c b/wcsmbs/isoc99_swscanf.c index ff523db706..40401d0aa1 100644 --- a/wcsmbs/isoc99_swscanf.c +++ b/wcsmbs/isoc99_swscanf.c @@ -16,20 +16,22 @@ <http://www.gnu.org/licenses/>. */ #include <stdarg.h> -#include <stdio.h> -#include <libioP.h> -#include <wchar.h> +#include <libio/strfile.h> /* Read formatted input from S, according to the format string FORMAT. */ -/* VARARGS2 */ + int __isoc99_swscanf (const wchar_t *s, const wchar_t *format, ...) { va_list arg; int done; + _IO_strfile sf; + struct _IO_wide_data wd; + FILE *f = _IO_strfile_readw (&sf, &wd, s); + f->_flags2 |= _IO_FLAGS2_SCANF_STD; va_start (arg, format); - done = __isoc99_vswscanf (s, format, arg); + done = __vfwscanf_internal (f, format, arg, 0); va_end (arg); return done; diff --git a/wcsmbs/isoc99_vfwscanf.c b/wcsmbs/isoc99_vfwscanf.c index 7beb45b4d3..f70c6b596d 100644 --- a/wcsmbs/isoc99_vfwscanf.c +++ b/wcsmbs/isoc99_vfwscanf.c @@ -28,7 +28,7 @@ __isoc99_vfwscanf (FILE *stream, const wchar_t *format, va_list args) _IO_acquire_lock_clear_flags2 (stream); stream->_flags2 |= _IO_FLAGS2_SCANF_STD; - done = _IO_vfwscanf (stream, format, args, NULL); + done = __vfwscanf_internal (stream, format, args, 0); _IO_release_lock (stream); return done; } diff --git a/wcsmbs/isoc99_vswscanf.c b/wcsmbs/isoc99_vswscanf.c index 130769154d..b91eb651a3 100644 --- a/wcsmbs/isoc99_vswscanf.c +++ b/wcsmbs/isoc99_vswscanf.c @@ -24,24 +24,16 @@ This exception applies to code released by its copyright holders in files containing the exception. */ -#include <libioP.h> #include <wchar.h> -#include "../libio/strfile.h" +#include <libio/strfile.h> int __isoc99_vswscanf (const wchar_t *string, const wchar_t *format, va_list args) { - int ret; _IO_strfile sf; struct _IO_wide_data wd; -#ifdef _IO_MTSAFE_IO - sf._sbf._f._lock = NULL; -#endif - _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, 0, &wd, &_IO_wstr_jumps); - _IO_fwide (&sf._sbf._f, 1); - _IO_wstr_init_static (&sf._sbf._f, (wchar_t *)string, 0, NULL); - sf._sbf._f._flags2 |= _IO_FLAGS2_SCANF_STD; - ret = _IO_vfwscanf ((FILE *) &sf._sbf, format, args, NULL); - return ret; + FILE *f = _IO_strfile_readw (&sf, &wd, string); + f->_flags2 |= _IO_FLAGS2_SCANF_STD; + return __vfwscanf_internal (f, format, args, 0); } libc_hidden_def (__isoc99_vswscanf) diff --git a/wcsmbs/isoc99_vwscanf.c b/wcsmbs/isoc99_vwscanf.c index 049521b964..eb22c8acae 100644 --- a/wcsmbs/isoc99_vwscanf.c +++ b/wcsmbs/isoc99_vwscanf.c @@ -28,7 +28,7 @@ __isoc99_vwscanf (const wchar_t *format, va_list args) _IO_acquire_lock_clear_flags2 (stdin); stdin->_flags2 |= _IO_FLAGS2_SCANF_STD; - done = _IO_vfwscanf (stdin, format, args, NULL); + done = __vfwscanf_internal (stdin, format, args, 0); _IO_release_lock (stdin); return done; } diff --git a/wcsmbs/isoc99_wscanf.c b/wcsmbs/isoc99_wscanf.c index abfbd50c11..59f80d78fb 100644 --- a/wcsmbs/isoc99_wscanf.c +++ b/wcsmbs/isoc99_wscanf.c @@ -33,7 +33,7 @@ __isoc99_wscanf (const wchar_t *format, ...) stdin->_flags2 |= _IO_FLAGS2_SCANF_STD; va_start (arg, format); - done = _IO_vfwscanf (stdin, format, arg, NULL); + done = __vfwscanf_internal (stdin, format, arg, 0); va_end (arg); _IO_release_lock (stdin);