diff options
| author | Ulrich Drepper <drepper@redhat.com> | 1999-06-16 22:55:47 +0000 |
|---|---|---|
| committer | Ulrich Drepper <drepper@redhat.com> | 1999-06-16 22:55:47 +0000 |
| commit | d64b6ad07585b8a37e5fecc9a47fcee766d52ede (patch) | |
| tree | 076b36cc9c1b82254348212e75939d842885563a /stdio-common/vfscanf.c | |
| parent | bc938d3de936a8e429b16237180c046139be8247 (diff) | |
| download | glibc-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.c | 1313 |
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 |
