diff options
Diffstat (limited to 'stdio-common')
| -rw-r--r-- | stdio-common/Makefile | 3 | ||||
| -rw-r--r-- | stdio-common/Versions | 3 | ||||
| -rw-r--r-- | stdio-common/iovfscanf.c | 38 | ||||
| -rw-r--r-- | stdio-common/iovfwscanf.c | 38 | ||||
| -rw-r--r-- | stdio-common/isoc99_fscanf.c | 2 | ||||
| -rw-r--r-- | stdio-common/isoc99_scanf.c | 2 | ||||
| -rw-r--r-- | stdio-common/isoc99_sscanf.c | 9 | ||||
| -rw-r--r-- | stdio-common/isoc99_vfscanf.c | 2 | ||||
| -rw-r--r-- | stdio-common/isoc99_vscanf.c | 2 | ||||
| -rw-r--r-- | stdio-common/isoc99_vsscanf.c | 17 | ||||
| -rw-r--r-- | stdio-common/scanf.c | 2 | ||||
| -rw-r--r-- | stdio-common/sscanf.c | 12 | ||||
| -rw-r--r-- | stdio-common/vfscanf-internal.c | 3049 | ||||
| -rw-r--r-- | stdio-common/vfscanf.c | 3042 | ||||
| -rw-r--r-- | stdio-common/vfwscanf-internal.c | 2 | ||||
| -rw-r--r-- | stdio-common/vfwscanf.c | 28 |
16 files changed, 3178 insertions, 3073 deletions
diff --git a/stdio-common/Makefile b/stdio-common/Makefile index a10f12ab3c..f3b3ceddbd 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 b8217578c8..522f302198 100644 --- a/stdio-common/Versions +++ b/stdio-common/Versions @@ -60,6 +60,9 @@ libc { GLIBC_2.28 { renameat2; } + GLIBC_2.29 { + # SHLIB_COMPAT(GLIBC_2_0, GLIBC_2_29) 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..77e698f665 --- /dev/null +++ b/stdio-common/iovfscanf.c @@ -0,0 +1,38 @@ +/* Implementation and symbols for _IO_vfscanf. + 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 <libioP.h> +#include <shlib-compat.h> + +/* This function is provided for ports older than GLIBC 2.29 because + external callers could theoretically exist. Newer ports do not need, + since it is not part of the API. */ +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_29) + +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..26a57788cb --- /dev/null +++ b/stdio-common/iovfwscanf.c @@ -0,0 +1,38 @@ +/* Implementation and symbols for _IO_vfwscanf. + 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> + +/* This function is provided for ports older than GLIBC 2.29 because + external callers could theoretically exist. Newer ports do not need, + since it is not part of the API. */ +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_29) + +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..2c89a03fe9 100644 --- a/stdio-common/isoc99_sscanf.c +++ b/stdio-common/isoc99_sscanf.c @@ -16,19 +16,20 @@ <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 */ int __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-internal.c b/stdio-common/vfscanf-internal.c new file mode 100644 index 0000000000..6bd0138f66 --- /dev/null +++ b/stdio-common/vfscanf-internal.c @@ -0,0 +1,3049 @@ +/* Internal functions for the *scanf* implementation. + 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 <assert.h> +#include <errno.h> +#include <limits.h> +#include <ctype.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <wchar.h> +#include <wctype.h> +#include <libc-diag.h> +#include <libc-lock.h> +#include <locale/localeinfo.h> +#include <scratch_buffer.h> + +#ifdef __GNUC__ +# define HAVE_LONGLONG +# define LONGLONG long long +#else +# define LONGLONG long +#endif + +/* Determine whether we have to handle `long long' at all. */ +#if LONG_MAX == LONG_LONG_MAX +# define need_longlong 0 +#else +# define need_longlong 1 +#endif + +/* Determine whether we have to handle `long'. */ +#if INT_MAX == LONG_MAX +# define need_long 0 +#else +# define need_long 1 +#endif + +/* Those are flags in the conversion format. */ +#define LONG 0x0001 /* l: long or double */ +#define LONGDBL 0x0002 /* L: long long or long double */ +#define SHORT 0x0004 /* h: short */ +#define SUPPRESS 0x0008 /* *: suppress assignment */ +#define POINTER 0x0010 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x0020 /* do not skip blanks */ +#define NUMBER_SIGNED 0x0040 /* signed integer */ +#define GROUP 0x0080 /* ': group numbers */ +#define GNU_MALLOC 0x0100 /* a: malloc strings */ +#define CHAR 0x0200 /* hh: char */ +#define I18N 0x0400 /* I: use locale's digits */ +#define HEXA_FLOAT 0x0800 /* hexadecimal float */ +#define READ_POINTER 0x1000 /* this is a pointer value */ +#define POSIX_MALLOC 0x2000 /* m: malloc strings */ +#define MALLOC (GNU_MALLOC | POSIX_MALLOC) + +#include <locale/localeinfo.h> +#include <libioP.h> + +#ifdef COMPILE_WSCANF +# define ungetc(c, s) ((void) (c == WEOF \ + || (--read_in, \ + _IO_sputbackwc (s, c)))) +# define ungetc_not_eof(c, s) ((void) (--read_in, \ + _IO_sputbackwc (s, c))) +# define inchar() (c == WEOF ? ((errno = inchar_errno), WEOF) \ + : ((c = _IO_getwc_unlocked (s)), \ + (void) (c != WEOF \ + ? ++read_in \ + : (size_t) (inchar_errno = errno)), c)) + +# define ISSPACE(Ch) iswspace (Ch) +# define ISDIGIT(Ch) iswdigit (Ch) +# define ISXDIGIT(Ch) iswxdigit (Ch) +# define TOLOWER(Ch) towlower (Ch) +# define ORIENT if (_IO_fwide (s, 1) != 1) return WEOF +# define __strtoll_internal __wcstoll_internal +# define __strtoull_internal __wcstoull_internal +# define __strtol_internal __wcstol_internal +# define __strtoul_internal __wcstoul_internal +# define __strtold_internal __wcstold_internal +# define __strtod_internal __wcstod_internal +# define __strtof_internal __wcstof_internal + +# define L_(Str) L##Str +# define CHAR_T wchar_t +# define UCHAR_T unsigned int +# define WINT_T wint_t +# undef EOF +# define EOF WEOF +#else +# define ungetc(c, s) ((void) ((int) c == EOF \ + || (--read_in, \ + _IO_sputbackc (s, (unsigned char) c)))) +# define ungetc_not_eof(c, s) ((void) (--read_in, \ + _IO_sputbackc (s, (unsigned char) c))) +# define inchar() (c == EOF ? ((errno = inchar_errno), EOF) \ + : ((c = _IO_getc_unlocked (s)), \ + (void) (c != EOF \ + ? ++read_in \ + : (size_t) (inchar_errno = errno)), c)) +# define ISSPACE(Ch) __isspace_l (Ch, loc) +# define ISDIGIT(Ch) __isdigit_l (Ch, loc) +# define ISXDIGIT(Ch) __isxdigit_l (Ch, loc) +# define TOLOWER(Ch) __tolower_l ((unsigned char) (Ch), loc) +# define ORIENT if (_IO_vtable_offset (s) == 0 \ + && _IO_fwide (s, -1) != -1) \ + return EOF + +# define L_(Str) Str +# define CHAR_T char +# define UCHAR_T unsigned char +# define WINT_T int +#endif + +#include "printf-parse.h" /* Use read_int. */ + +#define encode_error() do { \ + __set_errno (EILSEQ); \ + goto errout; \ + } while (0) +#define conv_error() do { \ + goto errout; \ + } while (0) +#define input_error() do { \ + if (done == 0) done = EOF; \ + goto errout; \ + } while (0) +#define add_ptr_to_free(ptr) \ + do \ + { \ + if (ptrs_to_free == NULL \ + || ptrs_to_free->count == (sizeof (ptrs_to_free->ptrs) \ + / sizeof (ptrs_to_free->ptrs[0]))) \ + { \ + struct ptrs_to_free *new_ptrs = alloca (sizeof (*ptrs_to_free)); \ + new_ptrs->count = 0; \ + new_ptrs->next = ptrs_to_free; \ + ptrs_to_free = new_ptrs; \ + } \ + ptrs_to_free->ptrs[ptrs_to_free->count++] = (ptr); \ + } \ + while (0) +#define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + CHECK_FILE (s, EOF); \ + if (s->_flags & _IO_NO_READS) \ + { \ + __set_errno (EBADF); \ + return EOF; \ + } \ + else if (format == NULL) \ + { \ + __set_errno (EINVAL); \ + return EOF; \ + } \ + } while (0) +#define LOCK_STREAM(S) \ + __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, (S)); \ + _IO_flockfile (S) +#define UNLOCK_STREAM(S) \ + _IO_funlockfile (S); \ + __libc_cleanup_region_end (0) + +struct ptrs_to_free +{ + size_t count; + struct ptrs_to_free *next; + char **ptrs[32]; +}; + +struct char_buffer { + CHAR_T *current; + CHAR_T *end; + struct scratch_buffer scratch; +}; + +/* Returns a pointer to the first CHAR_T object in the buffer. Only + valid if char_buffer_add (BUFFER, CH) has been called and + char_buffer_error (BUFFER) is false. */ +static inline CHAR_T * +char_buffer_start (const struct char_buffer *buffer) +{ + return (CHAR_T *) buffer->scratch.data; +} + +/* Returns the number of CHAR_T objects in the buffer. Only valid if + char_buffer_error (BUFFER) is false. */ +static inline size_t +char_buffer_size (const struct char_buffer *buffer) +{ + return buffer->current - char_buffer_start (buffer); +} + +/* Reinitializes BUFFER->current and BUFFER->end to cover the entire + scratch buffer. */ +static inline void +char_buffer_rewind (struct char_buffer *buffer) +{ + buffer->current = char_buffer_start (buffer); + buffer->end = buffer->current + buffer->scratch.length / sizeof (CHAR_T); +} + +/* Returns true if a previous call to char_buffer_add (BUFFER, CH) + failed. */ +static inline bool +char_buffer_error (const struct char_buffer *buffer) +{ + return __glibc_unlikely (buffer->current == NULL); +} + +/* Slow path for char_buffer_add. */ +static void +char_buffer_add_slow (struct char_buffer *buffer, CHAR_T ch) +{ + if (char_buffer_error (buffer)) + return; + size_t offset = buffer->end - (CHAR_T *) buffer->scratch.data; + if (!scratch_buffer_grow_preserve (&buffer->scratch)) + { + buffer->current = NULL; + buffer->end = NULL; + return; + } + char_buffer_rewind (buffer); + buffer->current += offset; + *buffer->current++ = ch; +} + +/* Adds CH to BUFFER. This function does not report any errors, check + for them with char_buffer_error. */ +static inline void +char_buffer_add (struct char_buffer *buffer, CHAR_T ch) + __attribute__ ((always_inline)); +static inline void +char_buffer_add (struct char_buffer *buffer, CHAR_T ch) +{ + if (__glibc_unlikely (buffer->current == buffer->end)) + char_buffer_add_slow (buffer, ch); + else + *buffer->current++ = ch; +} + +/* Read formatted input from S according to the format string + FORMAT, using the argument list in ARG. + Return the number of assignments made, or -1 for an input error. */ +#ifdef COMPILE_WSCANF +int +__vfwscanf_internal (FILE *s, const wchar_t *format, va_list argptr, + unsigned int mode_flags) +#else +int +__vfscanf_internal (FILE *s, const char *format, va_list argptr, + unsigned int mode_flags) +#endif +{ + va_list arg; + const CHAR_T *f = format; + UCHAR_T fc; /* Current character of the format. */ + WINT_T done = 0; /* Assignments done. */ + size_t read_in = 0; /* Chars read in. */ + WINT_T c = 0; /* Last char read. */ + int width; /* Maximum field width. */ + int flags; /* Modifiers for current format element. */ +#ifndef COMPILE_WSCANF + 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, got_sign; + /* If a [...] is a [^...]. */ + CHAR_T not_in; +#define exp_char not_in + /* Base for integral numbers. */ + int base; + /* Decimal point character. */ +#ifdef COMPILE_WSCANF + wint_t decimal; +#else + const char *decimal; +#endif + /* The thousands character of the current locale. */ +#ifdef COMPILE_WSCANF + wint_t thousands; +#else + const char *thousands; +#endif + struct ptrs_to_free *ptrs_to_free = NULL; + /* State for the conversions. */ + mbstate_t state; |
