aboutsummaryrefslogtreecommitdiff
path: root/stdio-common/vfscanf.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-06-16 22:55:47 +0000
committerUlrich Drepper <drepper@redhat.com>1999-06-16 22:55:47 +0000
commitd64b6ad07585b8a37e5fecc9a47fcee766d52ede (patch)
tree076b36cc9c1b82254348212e75939d842885563a /stdio-common/vfscanf.c
parentbc938d3de936a8e429b16237180c046139be8247 (diff)
downloadglibc-d64b6ad07585b8a37e5fecc9a47fcee766d52ede.tar.xz
glibc-d64b6ad07585b8a37e5fecc9a47fcee766d52ede.zip
Update.
* Versions.def: Add GLIBC_2.2 for libc. * iconv/gconv.h: Make header suitable for inclusion in public header by protecting all names with __. * iconv/gconv.c: Adapt for symbol name changes. * iconv/gconv.h: Likewise. * iconv/gconv_builtin.c: Likewise. * iconv/gconv_close.c: Likewise. * iconv/gconv_db.c: Likewise. * iconv/gconv_dl.c: Likewise. * iconv/gconv_int.h: Likewise. * iconv/gconv_open.c: Likewise. * iconv/gconv_simple.c: Likewise. * iconv/iconv.c: Likewise. * iconv/iconv_close.c: Likewise. * iconv/iconv_open.c: Likewise. * iconv/loop.c: Likewise. * iconv/skeleton.c: Likewise. * iconvdata/8bit-gap.c: Likewise. * iconvdata/8bit-generic.c: Likewise. * iconvdata/ansi_x3.110.c: Likewise. * iconvdata/big5.c: Likewise. * iconvdata/cns11643.h: Likewise. * iconvdata/cns11643l1.h: Likewise. * iconvdata/euc-cn.c: Likewise. * iconvdata/euc-jp.c: Likewise. * iconvdata/euc-kr.c: Likewise. * iconvdata/euc-tw.c: Likewise. * iconvdata/gb2312.h: Likewise. * iconvdata/iso-2022-jp.c: Likewise. * iconvdata/iso-2022-kr.c: Likewise. * iconvdata/iso646.c: Likewise. * iconvdata/iso8859-1.c: Likewise. * iconvdata/iso_6937-2.c: Likewise. * iconvdata/iso_6937.c: Likewise. * iconvdata/jis0201.h: Likewise. * iconvdata/jis0208.h: Likewise. * iconvdata/jis0212.h: Likewise. * iconvdata/johab.c: Likewise. * iconvdata/ksc5601.h: Likewise. * iconvdata/sjis.c: Likewise. * iconvdata/t.61.c: Likewise. * iconvdata/uhc.c: Likewise. * stdlib/mblen.c: Likewise. * stdlib/mbtowc.c: Likewise. * stdlib/wctomb.c: Likewise. * wcsmbs/btowc.c: Likewise. * wcsmbs/mbrtowc.c: Likewise. * wcsmbs/mbsnrtowcs.c: Likewise. * wcsmbs/mbsrtowcs.c: Likewise. * wcsmbs/wchar.h: Likewise. * wcsmbs/wcrtomb.c: Likewise. * wcsmbs/wcsmbsload.c: Likewise. * wcsmbs/wcsmbsload.h: Likewise. * wcsmbs/wcsnrtombs.c: Likewise. * wcsmbs/wcsrtombs.c: Likewise. * wcsmbs/wctob.c: Likewise. * include/limits.h (MB_LEN_MAX): Increase to 16. * sysdeps/generic/_G_config.h: Define _G_fpos_t as struct. Define _G_iconv_t. * sysdeps/unix/sysv/linux/_G_config.h: Likewise. * include/wchar.h: Change mbstate_t to __mbstate_t. * libio/Makefile (routines): Add wfiledoalloc, oldiofgetpos, oldiofgetpos64, oldiofsetpos, oldiofsetpos64, fputwc, fputwc_u, getwc, getwc_u, getwchar, getwchar_u, iofgetws, iofgetws_u, iofputws, iofputws_u, iogetwline, iowpadn, ioungetwc, putwc, putwc_u, putchar, putchar_u, swprintf, vwprintf, wprintf, wscanf, fwscanf, vwscanf, vswprintf, iovswscanf, swscanf, wgenops, wstrops, wfileops, and iofwide. (tests): Add tst_swprintf, tst_wprintf, tst_swscanf, and tst_wscanf. * libio/Versions: Add _IO_fgetpos, _IO_fgetpos64, _IO_fsetpos, _IO_fsetpos64, fgetpos, fgetpos64, fgetwc, fgetwc_unlocked, fgetws, fgetws_unlocked, fputwc, fputwc_unlocked, fputws, fputws_unlocked, fsetpos, fsetpos64, fwide, fwprintf, fwscanf, getwc, getwc_unlocked, getwchar, getwchar_unlocked, putwc, putwc_unlocked, putwchar, putwchar_unlocked, swprintf, swscanf, ungetwc, vfwprintf, vswprintf, vwprintf, vfwscanf, vswscanf, vwscanf, wprintf, and wscanf to GLIBC_2.2 for libc. * libio/libio.h: Define codecvt struct. Define _IO_wide_data. Extend _IO_file contain pointer to codecvt, widedata and mode. (_IO_getwc_unlocked): New macro. (_IO_putwc_unlocked): New macro. (_IO_fwide): New macro. * libio/libioP.h: Add new prototypes and adjust existing declarations. * libio/fileops.c (_IO_new_file_close_it): Reset normal or widedata buffers based on mode. (new_do_write): Set _IO_write_end to _IO_buf_end if stream is wide oriented. (_IO_new_file_overflow): Don't depend only on _IO_CURRENTLY_PUTTING flag to be enough to signal unallocated buffer. For wide oriented stream don't make it linebuffered. Don't use _IO_do_flush, use _IO_new_do_write directly. (_IO_new_file_seekoff): Change return value type to _IO_off64_t. (_IO_file_seek): Likewise. * libio/genops.c (_IO_least_marker): Make global. (__underflow): Orient stream if not already done. (__uflow): Likewise. (_IO_default_seekpos): Change to type _IO_off64_t. (_IO_default_seekoff): Likewise. (_IO_default_seek): Likewise. (_IO_no_init): New function. Similar to _IO_init but allows to orient in initialization. * libio/iolibio.h: Add prototype for _IO_vswprintf. Change _IO_pos_BAD to use _IO_off64_t. * libio/ftello.c: Use _IO_off_t. For now abort when use with wide char stream. * libio/ftello64.c: Likewise. * libio/ioftell.c: Likewise. * libio/iofopncook.c: Likewise. * libio/ioseekoff.c: Likewise. * libio/ioseekpos.c: Likewise. * libio/oldfileops.c: Likewise. * libio/iofgetpos.c: Store state of conversion if necessary. * libio/iofgetpos64.c: Likewise. * libio/iofsetpos.c: Restore conversion state if necessary. * libio/iofsetpos64.c: Likewise. * libio/iofdopen.c: Initialize so that stream can be wide oriented. * libio/iofopen.c: Likewise. * libio/iofopen64.c: Likewise. * libio/iopopen.c: Likewise. * libio/iovdprintf.c: Likewise. * libio/iovsprintf.c: Likewise. * libio/iovsscanf.c: Likewise. * libio/memstream.c: Likewise. * libio/obprintf.c: Likewise. * libio/iofputs.c: Orient stream if not already happened. * libio/iofputs_u.c: Likewise. * libio/iofwrite.c: Likewise. * libio/iofwrite_u.c: Likewise. * libio/ioputs.c: Likewise. * libio/iosetbuffer.c: Handle not yet oriented stream. * libio/iosetvbuf.c: Likewise. * libio/oldstdfiles.c: Adjust FILEBUF_LITERAL call. * libio/stdfiles.c: Likewise. * libio/strops.c (_IO_str_overflow): Correctly free buffer after failed allocation. (_IO_str_seekoff): Use _IO_off64_t. * libio/vasprintf.c: Pre-orient stream. * libio/vsnprintf.c: Likewise. * libio/fputwc.c: New file. * libio/fputwc_u.c: New file. * libio/fwprintf.c: New file. * libio/fwscanf.c: New file. * libio/getwc.c: New file. * libio/getwc_u.c: New file. * libio/getwchar.c: New file. * libio/getwchar_u.c: New file. * libio/iofgetws.c: New file. * libio/iofgetws_u.c: New file. * libio/iofputws.c: New file. * libio/iofputws_u.c: New file. * libio/iofwide.c: New file. * libio/iogetwline.c: New file. * libio/ioungetwc.c: New file. * libio/iovswscanf.c: New file. * libio/iowpadn.c: New file. * libio/oldiofgetpos.c: New file. * libio/oldiofgetpos64.c: New file. * libio/oldiofsetpos.c: New file. * libio/oldiofsetpos64.c: New file. * libio/putwc.c: New file. * libio/putwc_u.c: New file. * libio/putwchar.c: New file. * libio/putwchar_u.c: New file. * libio/swprintf.c: New file. * libio/swscanf.c: New file. * libio/tst_swprintf.c: New file. * libio/tst_swscanf.c: New file. * libio/tst_wprintf.c: New file. * libio/tst_wscanf.c: New file. * libio/tst_wscanf.input: New file. * libio/vswprintf.c: New file. * libio/vwprintf.c: New file. * libio/vwscanf.c: New file. * libio/wfiledoalloc.c: New file. * libio/wfileops.c: New file. * libio/wgenops.c: New file. * libio/wprintf.c: New file. * libio/wscanf.c: New file. * libio/wstrops.c: New file. * stdio-common/Makefile (routines): Add _itowa, itowa-digits, vfwprintf, and vfwscanf. * stdio-common/_itoa.c (base_table): Rename to _IO_base_table and make global. * stdio-common/_itowa.c: New file. * stdio-common/_itowa.h: New file. * stdio-common/itoa-digits.c: Minimal optimization. * stdio-common/itowa-digits.c: New file. * stdio-common/printf-parse.h: Allow use in wide character context. * stdio-common/printf-prs.c: Define ISASCII and MBRLEN. * stdio-common/printf.h (printf_info): Add wide bit. * stdio-common/printf_fp.c: Determine from wide bit whether stream is wide oriented or not. * stdio-common/printf_size.c: Likewise. * sysdeps/generic/printf_fphex.c: Likewise. * stdlib/strfmon.c: Call __printf_fp with wide bit cleared. * stdio-common/vfprintf.c: Rewrite to allow use in wide character context. * stdio-common/vfscand.c: Likewise. * stdio-common/vfwprintf.c: New file. * stdio-common/vfwscanf.c: New file. * time/Makefile (routines): Add wcsftime. (tests): Add tst_wcsftime. * time/Versions: Add wcsftime to GLIBC_2.2 for libc. * time/strftime.c: Make usable as wcsftime. * time/wcsftime.c: New file. * time/tst_wcsftime.c: New file. * wcsmbs/Makefile (routines): Add wmempcpy and wcschrnul. * wcsmbs/Versions: Add wmempcpy and wcschrnul to GLIBC_2.2 for libc. * wcsmbs/wcschrnul.c: New file. * wcsmbs/wmemcpy.c: New file. * wcsmbs/wmemcpy.c: Rename to __wmemcpy and make wmemcpy weak alias. * wcsmbs/wmemmove.c: Likewise for wmemmove. * manual/stdio.texi: Document is_char and wide element if printf_info. * manual/time.texi: Document wcsftime. * include/wchar.h: Add prototypes for __wmemcpy, __wmempcpy, __wmemmove, __wcschrnul, and __vfwscanf. * locale/langinfo.h: Add new LC_TIME entries for wchar_t data. * locale/C-time.c: Adapt for above change. * locale/categories.def: Likewise. * locale/localeinfo.h: Likewise. * localedata/Makefile: Don't run tests for now.
Diffstat (limited to 'stdio-common/vfscanf.c')
-rw-r--r--stdio-common/vfscanf.c1313
1 files changed, 990 insertions, 323 deletions
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 0339edbeca..5caf616be3 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -16,6 +16,7 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <ctype.h>
@@ -69,13 +70,56 @@
# undef va_list
# define va_list _IO_va_list
-# define ungetc(c, s) ((void) ((int) c == EOF \
+
+# ifdef COMPILE_WPRINTF
+# define ungetc(c, s) ((void) ((int) c == WEOF \
+ || (--read_in, \
+ _IO_sputbackwc (s, (unsigned char) c))))
+# define inchar() (c == EOF ? EOF \
+ : ((c = _IO_getwc_unlocked (s)), \
+ (void) (c != EOF && ++read_in), c))
+
+# define MEMCPY(d, s, n) wmemcpy (d, s, n)
+# define ISSPACE(Ch) iswspace (Ch)
+# define ISDIGIT(Ch) iswdigit (Ch)
+# define ISXDIGIT(Ch) iswxdigit (Ch)
+# define UNGETC(Ch, S) ungetwc (Ch, S)
+# define TOLOWER(Ch) towlower (Ch)
+# define ORIENT if (_IO_fwide (s, 1) != 1) return EOF
+# 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
+# else
+# define ungetc(c, s) ((void) ((int) c == EOF \
|| (--read_in, \
_IO_sputbackc (s, (unsigned char) c))))
-# define inchar() (c == EOF ? EOF \
+# define inchar() (c == EOF ? EOF \
: ((c = _IO_getc_unlocked (s)), \
(void) (c != EOF && ++read_in), c))
-# define encode_error() do { \
+# define MEMCPY(d, s, n) memcpy (d, s, n)
+# define ISSPACE(Ch) isspace (Ch)
+# define ISDIGIT(Ch) isdigit (Ch)
+# define ISXDIGIT(Ch) isxdigit (Ch)
+# define UNGETC(Ch, S) ungetc (Ch, S)
+# define TOLOWER(Ch) tolower (Ch)
+# define ORIENT if (_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
+
+# define encode_error() do { \
if (errp != NULL) *errp |= 4; \
_IO_funlockfile (s); \
__libc_cleanup_end (0); \
@@ -94,7 +138,7 @@
__libc_cleanup_end (0); \
return done ?: EOF; \
} while (0)
-# define memory_error() do { \
+# define memory_error() do { \
_IO_funlockfile (s); \
__set_errno (ENOMEM); \
__libc_cleanup_end (0); \
@@ -180,30 +224,39 @@
FORMAT, using the argument list in ARG.
Return the number of assignments made, or -1 for an input error. */
#ifdef USE_IN_LIBIO
+# ifdef COMPILE_WPRINTF
+int
+_IO_vfwscanf (s, format, argptr, errp)
+ _IO_FILE *s;
+ const wchar_t *format;
+ _IO_va_list argptr;
+ int *errp;
+# else
int
_IO_vfscanf (s, format, argptr, errp)
_IO_FILE *s;
const char *format;
_IO_va_list argptr;
int *errp;
+# endif
#else
int
__vfscanf (FILE *s, const char *format, va_list argptr)
#endif
{
va_list arg;
- register const char *f = format;
- register unsigned char fc; /* Current character of the format. */
+ register const CHAR_T *f = format;
+ register UCHAR_T fc; /* Current character of the format. */
register size_t done = 0; /* Assignments done. */
register size_t read_in = 0; /* Chars read in. */
- register int c = 0; /* Last char read. */
+ register WINT_T c = 0; /* Last char read. */
register int width; /* Maximum field width. */
register int flags; /* Modifiers for current format element. */
/* Status for reading F-P nums. */
char got_dot, got_e, negative;
/* If a [...] is a [^...]. */
- char not_in;
+ CHAR_T not_in;
#define exp_char not_in
/* Base for integral numbers. */
int base;
@@ -236,8 +289,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
/* Nonzero if we are reading a pointer. */
int read_pointer;
/* Workspace. */
- char *tw; /* Temporary pointer. */
- char *wp = NULL; /* Workspace. */
+ CHAR_T *tw; /* Temporary pointer. */
+ CHAR_T *wp = NULL; /* Workspace. */
size_t wpmax = 0; /* Maximal size of workspace. */
size_t wpsize; /* Currently used bytes in workspace. */
#define ADDW(Ch) \
@@ -245,11 +298,11 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
{ \
if (wpsize == wpmax) \
{ \
- char *old = wp; \
+ CHAR_T *old = wp; \
wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \
- wp = (char *) alloca (wpmax); \
+ wp = (CHAR_T *) alloca (wpmax * sizeof (wchar_t)); \
if (old != NULL) \
- memcpy (wp, old, wpsize); \
+ MEMCPY (wp, old, wpsize); \
} \
wp[wpsize++] = (Ch); \
} \
@@ -261,6 +314,10 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
arg = (va_list) argptr;
#endif
+#ifdef ORIENT
+ ORIENT;
+#endif
+
ARGCHECK (s, format);
/* Figure out the decimal point character. */
@@ -280,8 +337,10 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
LOCK_STREAM (s);
+#ifndef COMPILE_WPRINTF
/* From now on we use `state' to convert the format string. */
memset (&state, '\0', sizeof (state));
+#endif
/* Run through the format string. */
while (*f != '\0')
@@ -320,6 +379,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
# endif
#endif
+#ifndef COMPILE_WPRINTF
if (!isascii (*f))
{
/* Non-ASCII, may be a multibyte. */
@@ -341,12 +401,13 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
continue;
}
}
+#endif
fc = *f++;
if (fc != '%')
{
/* Remember to skip spaces. */
- if (isspace (fc))
+ if (ISSPACE (fc))
{
skip_space = 1;
continue;
@@ -363,7 +424,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
string. Now it's time to skip all leading white space. */
if (skip_space)
{
- while (isspace (c))
+ while (ISSPACE (c))
if (inchar () == EOF && errno == EINTR)
conv_error ();
skip_space = 0;
@@ -371,7 +432,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
if (c != fc)
{
- ungetc (c, s);
+ UNGETC (c, s);
conv_error ();
}
@@ -391,12 +452,12 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
wpsize = 0;
/* Check for a positional parameter specification. */
- if (isdigit (*f))
+ if (ISDIGIT (*f))
{
- argpos = *f++ - '0';
- while (isdigit (*f))
- argpos = argpos * 10 + (*f++ - '0');
- if (*f == '$')
+ argpos = *f++ - L_('0');
+ while (ISDIGIT (*f))
+ argpos = argpos * 10 + (*f++ - L_('0'));
+ if (*f == L_('$'))
++f;
else
{
@@ -409,27 +470,27 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
}
/* Check for the assignment-suppressing and the number grouping flag. */
- while (*f == '*' || *f == '\'')
+ while (*f == L_('*') || *f == L_('\''))
switch (*f++)
{
- case '*':
+ case L_('*'):
flags |= SUPPRESS;
break;
- case '\'':
+ case L_('\''):
flags |= GROUP;
break;
}
/* We have seen width. */
- if (isdigit (*f))
+ if (ISDIGIT (*f))
flags |= WIDTH;
/* Find the maximum field width. */
width = 0;
- while (isdigit (*f))
+ while (ISDIGIT (*f))
{
width *= 10;
- width += *f++ - '0';
+ width += *f++ - L_('0');
}
got_width:
if (width == 0)
@@ -438,9 +499,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
/* Check for type modifiers. */
switch (*f++)
{
- case 'h':
+ case L_('h'):
/* ints are short ints or chars. */
- if (*f == 'h')
+ if (*f == L_('h'))
{
++f;
flags |= CHAR;
@@ -448,8 +509,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
else
flags |= SHORT;
break;
- case 'l':
- if (*f == 'l')
+ case L_('l'):
+ if (*f == L_('l'))
{
/* A double `l' is equivalent to an `L'. */
++f;
@@ -459,15 +520,15 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
/* ints are long ints. */
flags |= LONG;
break;
- case 'q':
- case 'L':
+ case L_('q'):
+ case L_('L'):
/* doubles are long doubles, and ints are long long ints. */
flags |= LONGDBL | LONG;
break;
- case 'a':
+ case L_('a'):
/* The `a' is used as a flag only if followed by `s', `S' or
`['. */
- if (*f != 's' && *f != 'S' && *f != '[')
+ if (*f != L_('s') && *f != L_('S') && *f != L_('['))
{
--f;
break;
@@ -476,19 +537,19 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
arg and fill it in with a malloc'd pointer. */
flags |= MALLOC;
break;
- case 'z':
+ case L_('z'):
if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
flags |= LONGDBL;
else if (sizeof (size_t) > sizeof (unsigned int))
flags |= LONG;
break;
- case 'j':
+ case L_('j'):
if (need_longlong && sizeof (uintmax_t) > sizeof (unsigned long int))
flags |= LONGDBL;
else if (sizeof (uintmax_t) > sizeof (unsigned int))
flags |= LONG;
break;
- case 't':
+ case L_('t'):
if (need_longlong && sizeof (ptrdiff_t) > sizeof (long int))
flags |= LONGDBL;
else if (sizeof (ptrdiff_t) > sizeof (int))
@@ -501,12 +562,13 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
}
/* End of the format string? */
- if (*f == '\0')
+ if (*f == L_('\0'))
conv_error ();
/* Find the conversion specifier. */
fc = *f++;
- if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
+ if (skip_space || (fc != L_('[') && fc != L_('c')
+ && fc != L_('C') && fc != L_('n')))
{
/* Eat whitespace. */
int save_errno = errno;
@@ -514,15 +576,15 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
do
if (inchar () == EOF && errno == EINTR)
input_error ();
- while (isspace (c));
+ while (ISSPACE (c));
errno = save_errno;
- ungetc (c, s);
+ UNGETC (c, s);
skip_space = 0;
}
switch (fc)
{
- case '%': /* Must match a literal '%'. */
+ case L_('%'): /* Must match a literal '%'. */
c = inchar ();
if (c == EOF)
input_error ();
@@ -533,7 +595,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
}
break;
- case 'n': /* Answer number of assignments done. */
+ case L_('n'): /* Answer number of assignments done. */
/* Corrigendum 1 to ISO C 1990 describes the allowed flags
with the 'n' conversion specifier. */
if (!(flags & SUPPRESS))
@@ -581,7 +643,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
}
break;
- case 'c': /* Match characters. */
+ case L_('c'): /* Match characters. */
if ((flags & LONG) == 0)
{
if (!(flags & SUPPRESS))
@@ -598,6 +660,26 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
if (width == -1)
width = 1;
+#ifdef COMPILE_WPRINTF
+ /* We have to convert the wide character(s) into multibyte
+ characters and store the result. */
+ memset (&state, '\0', sizeof (state));
+
+ do
+ {
+ size_t n;
+
+ n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
+ if (n == (size_t) -1)
+ /* No valid wide character. */
+ input_error ();
+
+ /* Increment the output pointer. Even if we don't
+ write anything. */
+ str += n;
+ }
+ while (--width > 0 && inchar () != EOF);
+#else
if (!(flags & SUPPRESS))
{
do
@@ -606,6 +688,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
}
else
while (--width > 0 && inchar () != EOF);
+#endif
if (!(flags & SUPPRESS))
++done;
@@ -613,238 +696,448 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
break;
}
/* FALLTHROUGH */
- case 'C':
- /* Get UTF-8 encoded wide character. Here we assume (as in
- other parts of the libc) that we only have to handle
- UTF-8. */
+ case L_('C'):
+ if (!(flags & SUPPRESS))
+ {
+ wstr = ARG (wchar_t *);
+ if (str == NULL)
+ conv_error ();
+ }
+
+ c = inchar ();
+ if (c == EOF)
+ input_error ();
+
+#ifdef COMPILE_WPRINTF
+ /* Just store the incoming wide characters. */
+ if (!(flags & SUPPRESS))
+ {
+ do
+ *wstr++ = c;
+ while (--width > 0 && inchar () != EOF);
+ }
+ else
+ while (--width > 0 && inchar () != EOF);
+#else
{
- wint_t val;
- size_t cnt = 0;
- int first = 1;
+ /* We have to convert the multibyte input sequence to wide
+ characters. */
+ char buf[MB_LEN_MAX];
+ mbstate_t cstate;
- if (!(flags & SUPPRESS))
- {
- wstr = ARG (wchar_t *);
- if (str == NULL)
- conv_error ();
- }
+ memset (&cstate, '\0', sizeof (cstate));
do
{
-#define NEXT_WIDE_CHAR(First) \
- c = inchar (); \
- if (c == EOF) \
- { \
- /* EOF is only an error for the first character. */ \
- if (First) \
- input_error (); \
- else \
- break; \
- } \
- val = c; \
- if (val >= 0x80) \
- { \
- if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
- encode_error (); \
- if ((c & 0xe0) == 0xc0) \
- { \
- /* We expect two bytes. */ \
- cnt = 1; \
- val &= 0x1f; \
- } \
- else if ((c & 0xf0) == 0xe0) \
- { \
- /* We expect three bytes. */ \
- cnt = 2; \
- val &= 0x0f; \
- } \
- else if ((c & 0xf8) == 0xf0) \
- { \
- /* We expect four bytes. */ \
- cnt = 3; \
- val &= 0x07; \
- } \
- else if ((c & 0xfc) == 0xf8) \
- { \
- /* We expect five bytes. */ \
- cnt = 4; \
- val &= 0x03; \
- } \
- else \
- { \
- /* We expect six bytes. */ \
- cnt = 5; \
- val &= 0x01; \
- } \
- \
- do \
- { \
- c = inchar (); \
- if (c == EOF \
- || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
- encode_error (); \
- val <<= 6; \
- val |= c & 0x3f; \
- } \
- while (--cnt > 0); \
- } \
- \
- if (!(flags & SUPPRESS)) \
- *wstr++ = val; \
- First = 0
-
- NEXT_WIDE_CHAR (first);
- }
- while (--width > 0);
+ size_t cnt;
- if (!(flags & SUPPRESS))
- ++done;
+ /* This is what we present the mbrtowc function first. */
+ buf[0] = c;
+ cnt = 1;
+
+ while (1)
+ {
+ size_t n;
+
+ n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
+ buf, cnt, &cstate);
+
+ if (n == (size_t) -2)
+ {
+ /* Possibly correct character, just not enough
+ input. */
+ assert (cnt < MB_CUR_MAX);
+
+ if (inchar () == EOF)
+ encode_error ();
+
+ buf[cnt++] = c;
+ continue;
+ }
+
+ if (n != cnt)
+ encode_error ();
+
+ /* We have a match. */
+ break;
+ }
+
+ /* Advance the result pointer. */
+ ++wstr;
+ }
+ while (--width > 0 && inchar () != EOF);
}
- break;
+#endif
- case 's': /* Read a string. */
- if (flags & LONG)
- /* We have to process a wide character string. */
- goto wide_char_string;
+ if (!(flags & SUPPRESS))
+ ++done;
+ break;
+
+ case L_('s'): /* Read a string. */
+ if (!(flags & LONG))
+ {
#define