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/asprintf.c6
-rw-r--r--stdio-common/dprintf.c5
-rw-r--r--stdio-common/fprintf.c2
-rw-r--r--stdio-common/fxprintf.c4
-rw-r--r--stdio-common/printf.c3
-rw-r--r--stdio-common/snprintf.c4
-rw-r--r--stdio-common/sprintf.c4
-rw-r--r--stdio-common/vfprintf-internal.c2364
-rw-r--r--stdio-common/vfprintf.c2351
-rw-r--r--stdio-common/vfwprintf-internal.c2
-rw-r--r--stdio-common/vfwprintf.c28
-rw-r--r--stdio-common/vprintf.c4
13 files changed, 2410 insertions, 2370 deletions
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index f3b3ceddbd..84bad1fafe 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -40,7 +40,8 @@ routines := \
isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \
isoc99_vsscanf \
psiginfo gentempfd \
- vfscanf-internal vfwscanf-internal iovfscanf iovfwscanf
+ vfscanf-internal vfwscanf-internal iovfscanf iovfwscanf \
+ vfprintf-internal vfwprintf-internal
aux := errlist siglist printf-parsemb printf-parsewc fxprintf
diff --git a/stdio-common/asprintf.c b/stdio-common/asprintf.c
index bff858e657..8943ffcae1 100644
--- a/stdio-common/asprintf.c
+++ b/stdio-common/asprintf.c
@@ -16,11 +16,7 @@
<http://www.gnu.org/licenses/>. */
#include <stdarg.h>
-#include <stdio.h>
-
#include <libioP.h>
-#define vasprintf(s, f, a) _IO_vasprintf (s, f, a)
-#undef __asprintf
/* Write formatted output from FORMAT to a string which is
allocated with malloc and stored in *STRING_PTR. */
@@ -32,7 +28,7 @@ ___asprintf (char **string_ptr, const char *format, ...)
int done;
va_start (arg, format);
- done = vasprintf (string_ptr, format, arg);
+ done = __vasprintf_internal (string_ptr, format, arg, 0);
va_end (arg);
return done;
diff --git a/stdio-common/dprintf.c b/stdio-common/dprintf.c
index 11bd12b838..9adc8ae4c7 100644
--- a/stdio-common/dprintf.c
+++ b/stdio-common/dprintf.c
@@ -16,10 +16,7 @@
<http://www.gnu.org/licenses/>. */
#include <stdarg.h>
-#include <stdio.h>
-
#include <libioP.h>
-#define vdprintf(d, f, a) _IO_vdprintf (d, f, a)
/* Write formatted output to D, according to the format string FORMAT. */
/* VARARGS2 */
@@ -30,7 +27,7 @@ __dprintf (int d, const char *format, ...)
int done;
va_start (arg, format);
- done = vdprintf (d, format, arg);
+ done = __vdprintf_internal (d, format, arg, 0);
va_end (arg);
return done;
diff --git a/stdio-common/fprintf.c b/stdio-common/fprintf.c
index 2bbf14bf5d..c8f8ac4faf 100644
--- a/stdio-common/fprintf.c
+++ b/stdio-common/fprintf.c
@@ -29,7 +29,7 @@ __fprintf (FILE *stream, const char *format, ...)
int done;
va_start (arg, format);
- done = vfprintf (stream, format, arg);
+ done = __vfprintf_internal (stream, format, arg, 0);
va_end (arg);
return done;
diff --git a/stdio-common/fxprintf.c b/stdio-common/fxprintf.c
index 8d02b71f91..a028e8edd5 100644
--- a/stdio-common/fxprintf.c
+++ b/stdio-common/fxprintf.c
@@ -27,7 +27,7 @@ static int
locked_vfxprintf (FILE *fp, const char *fmt, va_list ap)
{
if (_IO_fwide (fp, 0) <= 0)
- return _IO_vfprintf (fp, fmt, ap);
+ return __vfprintf_internal (fp, fmt, ap, 0);
/* We must convert the narrow format string to a wide one.
Each byte can produce at most one wide character. */
@@ -53,7 +53,7 @@ locked_vfxprintf (FILE *fp, const char *fmt, va_list ap)
res = __mbsrtowcs (wfmt, &fmt, len, &mbstate);
if (res != -1)
- res = _IO_vfwprintf (fp, wfmt, ap);
+ res = __vfwprintf_internal (fp, wfmt, ap, 0);
if (used_malloc)
free (wfmt);
diff --git a/stdio-common/printf.c b/stdio-common/printf.c
index 205b5e42df..ea41dd557c 100644
--- a/stdio-common/printf.c
+++ b/stdio-common/printf.c
@@ -30,7 +30,7 @@ __printf (const char *format, ...)
int done;
va_start (arg, format);
- done = vfprintf (stdout, format, arg);
+ done = __vfprintf_internal (stdout, format, arg, 0);
va_end (arg);
return done;
@@ -38,5 +38,4 @@ __printf (const char *format, ...)
#undef _IO_printf
ldbl_strong_alias (__printf, printf);
-/* This is for libg++. */
ldbl_strong_alias (__printf, _IO_printf);
diff --git a/stdio-common/snprintf.c b/stdio-common/snprintf.c
index 29a169b08b..b75e160ea3 100644
--- a/stdio-common/snprintf.c
+++ b/stdio-common/snprintf.c
@@ -16,9 +16,7 @@
<http://www.gnu.org/licenses/>. */
#include <stdarg.h>
-#include <stdio.h>
#include <libioP.h>
-#define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
/* Write formatted output into S, according to the format
string FORMAT, writing no more than MAXLEN characters. */
@@ -30,7 +28,7 @@ __snprintf (char *s, size_t maxlen, const char *format, ...)
int done;
va_start (arg, format);
- done = __vsnprintf (s, maxlen, format, arg);
+ done = __vsnprintf_internal (s, maxlen, format, arg, 0);
va_end (arg);
return done;
diff --git a/stdio-common/sprintf.c b/stdio-common/sprintf.c
index bf5671dde9..77423b292f 100644
--- a/stdio-common/sprintf.c
+++ b/stdio-common/sprintf.c
@@ -16,9 +16,7 @@
<http://www.gnu.org/licenses/>. */
#include <stdarg.h>
-#include <stdio.h>
#include <libioP.h>
-#define vsprintf(s, f, a) _IO_vsprintf (s, f, a)
/* Write formatted output into S, according to the format string FORMAT. */
/* VARARGS2 */
@@ -29,7 +27,7 @@ __sprintf (char *s, const char *format, ...)
int done;
va_start (arg, format);
- done = vsprintf (s, format, arg);
+ done = __vsprintf_internal (s, format, arg, 0);
va_end (arg);
return done;
diff --git a/stdio-common/vfprintf-internal.c b/stdio-common/vfprintf-internal.c
new file mode 100644
index 0000000000..b0c86e99bd
--- /dev/null
+++ b/stdio-common/vfprintf-internal.c
@@ -0,0 +1,2364 @@
+/* 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 <array_length.h>
+#include <ctype.h>
+#include <limits.h>
+#include <printf.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <wchar.h>
+#include <libc-lock.h>
+#include <sys/param.h>
+#include <_itoa.h>
+#include <locale/localeinfo.h>
+#include <stdio.h>
+#include <scratch_buffer.h>
+
+/* This code is shared between the standard stdio implementation found
+ in GNU C library and the libio implementation originally found in
+ GNU libg++.
+
+ Beside this it is also shared between the normal and wide character
+ implementation as defined in ISO/IEC 9899:1990/Amendment 1:1995. */
+
+#include <libioP.h>
+
+#ifdef COMPILE_WPRINTF
+#include <wctype.h>
+#endif
+
+/* In some cases we need extra space for all the output which is not
+ counted in the width of the string. We assume 32 characters is
+ enough. */
+#define EXTSIZ 32
+#define ARGCHECK(S, Format) \
+ do \
+ { \
+ /* Check file argument for consistence. */ \
+ CHECK_FILE (S, -1); \
+ if (S->_flags & _IO_NO_WRITES) \
+ { \
+ S->_flags |= _IO_ERR_SEEN; \
+ __set_errno (EBADF); \
+ return -1; \
+ } \
+ if (Format == NULL) \
+ { \
+ __set_errno (EINVAL); \
+ return -1; \
+ } \
+ } while (0)
+#define UNBUFFERED_P(S) ((S)->_flags & _IO_UNBUFFERED)
+
+#define done_add(val) \
+ do { \
+ unsigned int _val = val; \
+ assert ((unsigned int) done < (unsigned int) INT_MAX); \
+ if (__glibc_unlikely (INT_MAX - done < _val)) \
+ { \
+ done = -1; \
+ __set_errno (EOVERFLOW); \
+ goto all_done; \
+ } \
+ done += _val; \
+ } while (0)
+
+#ifndef COMPILE_WPRINTF
+# define vfprintf __vfprintf_internal
+# define CHAR_T char
+# define UCHAR_T unsigned char
+# define INT_T int
+typedef const char *THOUSANDS_SEP_T;
+# define L_(Str) Str
+# define ISDIGIT(Ch) ((unsigned int) ((Ch) - '0') < 10)
+# define STR_LEN(Str) strlen (Str)
+
+# define PUT(F, S, N) _IO_sputn ((F), (S), (N))
+# define PAD(Padchar) \
+ do { \
+ if (width > 0) \
+ { \
+ ssize_t written = _IO_padn (s, (Padchar), width); \
+ if (__glibc_unlikely (written != width)) \
+ { \
+ done = -1; \
+ goto all_done; \
+ } \
+ done_add (written); \
+ } \
+ } while (0)
+# define PUTC(C, F) _IO_putc_unlocked (C, F)
+# define ORIENT if (_IO_vtable_offset (s) == 0 && _IO_fwide (s, -1) != -1)\
+ return -1
+#else
+# define vfprintf __vfwprintf_internal
+# define CHAR_T wchar_t
+/* This is a hack!!! There should be a type uwchar_t. */
+# define UCHAR_T unsigned int /* uwchar_t */
+# define INT_T wint_t
+typedef wchar_t THOUSANDS_SEP_T;
+# define L_(Str) L##Str
+# define ISDIGIT(Ch) ((unsigned int) ((Ch) - L'0') < 10)
+# define STR_LEN(Str) __wcslen (Str)
+
+# include <_itowa.h>
+
+# define PUT(F, S, N) _IO_sputn ((F), (S), (N))
+# define PAD(Padchar) \
+ do { \
+ if (width > 0) \
+ { \
+ ssize_t written = _IO_wpadn (s, (Padchar), width); \
+ if (__glibc_unlikely (written != width)) \
+ { \
+ done = -1; \
+ goto all_done; \
+ } \
+ done_add (written); \
+ } \
+ } while (0)
+# define PUTC(C, F) _IO_putwc_unlocked (C, F)
+# define ORIENT if (_IO_fwide (s, 1) != 1) return -1
+
+# undef _itoa
+# define _itoa(Val, Buf, Base, Case) _itowa (Val, Buf, Base, Case)
+# define _itoa_word(Val, Buf, Base, Case) _itowa_word (Val, Buf, Base, Case)
+# undef EOF
+# define EOF WEOF
+#endif
+
+#include "_i18n_number.h"
+
+/* Include the shared code for parsing the format string. */
+#include "printf-parse.h"
+
+
+#define outchar(Ch) \
+ do \
+ { \
+ const INT_T outc = (Ch); \
+ if (PUTC (outc, s) == EOF || done == INT_MAX) \
+ { \
+ done = -1; \
+ goto all_done; \
+ } \
+ ++done; \
+ } \
+ while (0)
+
+#define outstring(String, Len) \
+ do \
+ { \
+ assert ((size_t) done <= (size_t) INT_MAX); \
+ if ((size_t) PUT (s, (String), (Len)) != (size_t) (Len)) \
+ { \
+ done = -1; \
+ goto all_done; \
+ } \
+ if (__glibc_unlikely (INT_MAX - done < (Len))) \
+ { \
+ done = -1; \
+ __set_errno (EOVERFLOW); \
+ goto all_done; \
+ } \
+ done += (Len); \
+ } \
+ while (0)
+
+/* For handling long_double and longlong we use the same flag. If
+ `long' and `long long' are effectively the same type define it to
+ zero. */
+#if LONG_MAX == LONG_LONG_MAX
+# define is_longlong 0
+#else
+# define is_longlong is_long_double
+#endif
+
+/* If `long' and `int' is effectively the same type we don't have to
+ handle `long separately. */
+#if INT_MAX == LONG_MAX
+# define is_long_num 0
+#else
+# define is_long_num is_long
+#endif
+
+
+/* Global constants. */
+static const CHAR_T null[] = L_("(null)");
+
+/* Size of the work_buffer variable (in characters, not bytes. */
+enum { WORK_BUFFER_SIZE = 1000 / sizeof (CHAR_T) };
+
+/* This table maps a character into a number representing a class. In
+ each step there is a destination label for each class. */
+static const uint8_t jump_table[] =
+ {
+ /* ' ' */ 1, 0, 0, /* '#' */ 4,
+ 0, /* '%' */ 14, 0, /* '\''*/ 6,
+ 0, 0, /* '*' */ 7, /* '+' */ 2,
+ 0, /* '-' */ 3, /* '.' */ 9, 0,
+ /* '0' */ 5, /* '1' */ 8, /* '2' */ 8, /* '3' */ 8,
+ /* '4' */ 8, /* '5' */ 8, /* '6' */ 8, /* '7' */ 8,
+ /* '8' */ 8, /* '9' */ 8, 0, 0,
+ 0, 0, 0, 0,
+ 0, /* 'A' */ 26, 0, /* 'C' */ 25,
+ 0, /* 'E' */ 19, /* F */ 19, /* 'G' */ 19,
+ 0, /* 'I' */ 29, 0, 0,
+ /* 'L' */ 12, 0, 0, 0,
+ 0, 0, 0, /* 'S' */ 21,
+ 0, 0, 0, 0,
+ /* 'X' */ 18, 0, /* 'Z' */ 13, 0,
+ 0, 0, 0, 0,
+ 0, /* 'a' */ 26, 0, /* 'c' */ 20,
+ /* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19,
+ /* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28, 0,
+ /* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,
+ /* 'p' */ 22, /* 'q' */ 12, 0, /* 's' */ 21,
+ /* 't' */ 27, /* 'u' */ 16, 0, 0,
+ /* 'x' */ 18, 0, /* 'z' */ 13
+ };
+
+#define NOT_IN_JUMP_RANGE(Ch) ((Ch) < L_(' ') || (Ch) > L_('z'))
+#define CHAR_CLASS(Ch) (jump_table[(INT_T) (Ch) - L_(' ')])
+#define LABEL(Name) do_##Name
+#ifdef SHARED
+ /* 'int' is enough and it saves some space on 64 bit systems. */
+# define JUMP_TABLE_TYPE const int
+# define JUMP_TABLE_BASE_LABEL do_form_unknown
+# define REF(Name) &&do_##Name - &&JUMP_TABLE_BASE_LABEL
+# define JUMP(ChExpr, table) \
+ do \
+ { \
+ int offset; \
+ void *ptr; \
+ spec = (ChExpr); \
+ offset = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown) \
+ : table[CHAR_CLASS (spec)]; \
+ ptr = &&JUMP_TABLE_BASE_LABEL + offset; \
+ goto *ptr; \
+ } \
+ while (0)
+#else
+# define JUMP_TABLE_TYPE const void *const
+# define REF(Name) &&do_##Name
+# define JUMP(ChExpr, table) \
+ do \
+ { \
+ const void *ptr; \
+ spec = (ChExpr); \
+ ptr = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown) \
+ : table[CHAR_CLASS (spec)]; \
+ goto *ptr; \
+ } \
+ while (0)
+#endif
+
+#define STEP0_3_TABLE \
+ /* Step 0: at the beginning. */ \
+ static JUMP_TABLE_TYPE step0_jumps[30] = \
+ { \
+ REF (form_unknown), \
+ REF (flag_space), /* for ' ' */ \
+ REF (flag_plus), /* for '+' */ \
+ REF (flag_minus), /* for '-' */ \
+ REF (flag_hash), /* for '<hash>' */ \
+ REF (flag_zero), /* for '0' */ \
+ REF (flag_quote), /* for '\'' */ \
+ REF (width_asterics), /* for '*' */ \
+ REF (width), /* for '1'...'9' */ \
+ REF (precision), /* for '.' */ \
+ REF (mod_half), /* for 'h' */ \
+ REF (mod_long), /* for 'l' */ \
+ REF (mod_longlong), /* for 'L', 'q' */ \
+ REF (mod_size_t), /* for 'z', 'Z' */ \
+ REF (form_percent), /* for '%' */ \
+ REF (form_integer), /* for 'd', 'i' */ \
+ REF (form_unsigned), /* for 'u' */ \
+ REF (form_octal), /* for 'o' */ \
+ REF (form_hexa), /* for 'X', 'x' */ \
+ REF (form_float), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \
+ REF (form_character), /* for 'c' */ \
+ REF (form_string), /* for 's', 'S' */ \
+ REF (form_pointer), /* for 'p' */ \
+ REF (form_number), /* for 'n' */ \
+ REF (form_strerror), /* for 'm' */ \
+ REF (form_wcharacter), /* for 'C' */ \
+ REF (form_floathex), /* for 'A', 'a' */ \
+ REF (mod_ptrdiff_t), /* for 't' */ \
+ REF (mod_intmax_t), /* for 'j' */ \
+ REF (flag_i18n), /* for 'I' */ \
+ }; \
+ /* Step 1: after processing width. */ \
+ static JUMP_TABLE_TYPE step1_jumps[30] = \
+ { \
+ REF (form_unknown), \
+ REF (form_unknown), /* for ' ' */ \
+ REF (form_unknown), /* for '+' */ \
+ REF (form_unknown), /* for '-' */ \
+ REF (form_unknown), /* for '<hash>' */ \
+ REF (form_unknown), /* for '0' */ \
+ REF (form_unknown), /* for '\'' */ \
+ REF (form_unknown), /* for '*' */ \
+ REF (form_unknown), /* for '1'...'9' */ \
+ REF (precision), /* for '.' */ \
+ REF (mod_half), /* for 'h' */ \
+ REF (mod_long), /* for 'l' */ \
+ REF (mod_longlong), /* for 'L', 'q' */ \
+ REF (mod_size_t), /* for 'z', 'Z' */ \
+ REF (form_percent), /* for '%' */ \
+ REF (form_integer), /* for 'd', 'i' */ \
+ REF (form_unsigned), /* for 'u' */ \
+ REF (form_octal), /* for 'o' */ \
+ REF (form_hexa), /* for 'X', 'x' */ \
+ REF (form_float), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \
+ REF (form_character), /* for 'c' */ \
+ REF (form_string), /* for 's', 'S' */ \
+ REF (form_pointer), /* for 'p' */ \
+ REF (form_number), /* for 'n' */ \
+ REF (form_strerror), /* for 'm' */ \
+ REF (form_wcharacter), /* for 'C' */ \
+ REF (form_floathex), /* for 'A', 'a' */ \
+ REF (mod_ptrdiff_t), /* for 't' */ \
+ REF (mod_intmax_t), /* for 'j' */ \
+ REF (form_unknown) /* for 'I' */ \
+ }; \
+ /* Step 2: after processing precision. */ \
+ static JUMP_TABLE_TYPE step2_jumps[30] = \
+ { \
+ REF (form_unknown), \
+ REF (form_unknown), /* for ' ' */ \
+ REF (form_unknown), /* for '+' */ \
+ REF (form_unknown), /* for '-' */ \
+ REF (form_unknown), /* for '<hash>' */ \
+ REF (form_unknown), /* for '0' */ \
+ REF (form_unknown), /* for '\'' */ \
+ REF (form_unknown), /* for '*' */ \
+ REF (form_unknown), /* for '1'...'9' */ \
+ REF (form_unknown), /* for '.' */ \
+ REF (mod_half), /* for 'h' */ \
+ REF (mod_long), /* for 'l' */ \
+ REF (mod_longlong), /* for 'L', 'q' */ \
+ REF (mod_size_t), /* for 'z', 'Z' */ \
+ REF (form_percent), /* for '%' */ \
+ REF (form_integer), /* for 'd', 'i' */ \
+ REF (form_unsigned), /* for 'u' */ \
+ REF (form_octal), /* for 'o' */ \
+ REF (form_hexa), /* for 'X', 'x' */ \
+ REF (form_float), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \
+ REF (form_character), /* for 'c' */ \
+ REF (form_string), /* for 's', 'S' */ \
+ REF (form_pointer), /* for 'p' */ \
+ REF (form_number), /* for 'n' */ \
+ REF (form_strerror), /* for 'm' */ \
+ REF (form_wcharacter), /* for 'C' */ \
+ REF (form_floathex), /* for 'A', 'a' */ \
+ REF (mod_ptrdiff_t), /* for 't' */ \
+ REF (mod_intmax_t), /* for 'j' */ \
+ REF (form_unknown) /* for 'I' */ \
+ }; \
+ /* Step 3a: after processing first 'h' modifier. */ \
+ static JUMP_TABLE_TYPE step3a_jumps[30] = \
+ { \
+ REF (form_unknown), \
+ REF (form_unknown), /* for ' ' */ \
+ REF (form_unknown), /* for '+' */ \
+ REF (form_unknown), /* for '-' */ \
+ REF (form_unknown), /* for '<hash>' */ \
+ REF (form_unknown), /* for '0' */ \
+ REF (form_unknown), /* for '\'' */ \
+ REF (form_unknown), /* for '*' */ \
+ REF (form_unknown), /* for '1'...'9' */ \
+ REF (form_unknown), /* for '.' */ \
+ REF (mod_halfhalf), /* for 'h' */ \
+ REF (form_unknown), /* for 'l' */ \
+ REF (form_unknown), /* for 'L', 'q' */ \
+ REF (form_unknown), /* for 'z', 'Z' */ \
+ REF (form_percent), /* for '%' */ \
+ REF (form_integer), /* for 'd', 'i' */ \
+ REF (form_unsigned), /* for 'u' */ \
+ REF (form_octal), /* for 'o' */ \
+ REF (form_hexa), /* for 'X', 'x' */ \
+ REF (form_unknown), /* for 'E', 'e', 'F', 'f', 'G', 'g' */ \
+ REF (form_unknown), /* for 'c' */ \
+ REF (form_unknown), /* for 's', 'S' */ \
+ REF (form_unknown), /* for 'p' */ \
+ REF (form_number), /* for 'n' */ \
+ REF (form_unknown), /* for 'm' */ \
+ REF (form_unknown), /* for 'C' */ \
+ REF (form_unknown), /* for 'A', 'a' */ \
+ REF (form_unknown), /* for 't' */ \
+ REF (form_unknown), /* for 'j' */ \
+ REF (form_unknown) /* for 'I' */ \
<