aboutsummaryrefslogtreecommitdiff
path: root/stdio-common
diff options
context:
space:
mode:
Diffstat (limited to 'stdio-common')
-rw-r--r--stdio-common/Makefile3
-rw-r--r--stdio-common/Versions3
-rw-r--r--stdio-common/iovfscanf.c38
-rw-r--r--stdio-common/iovfwscanf.c38
-rw-r--r--stdio-common/isoc99_fscanf.c2
-rw-r--r--stdio-common/isoc99_scanf.c2
-rw-r--r--stdio-common/isoc99_sscanf.c9
-rw-r--r--stdio-common/isoc99_vfscanf.c2
-rw-r--r--stdio-common/isoc99_vscanf.c2
-rw-r--r--stdio-common/isoc99_vsscanf.c17
-rw-r--r--stdio-common/scanf.c2
-rw-r--r--stdio-common/sscanf.c12
-rw-r--r--stdio-common/vfscanf-internal.c3049
-rw-r--r--stdio-common/vfscanf.c3042
-rw-r--r--stdio-common/vfwscanf-internal.c2
-rw-r--r--stdio-common/vfwscanf.c28
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;