(ORIENT): Swap the COMPILE_WSCANF case.
[kopensolaris-gnu/glibc.git] / stdio-common / vfscanf.c
1 /* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with the GNU C Library; see the file COPYING.LIB.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18
19 #include <assert.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <ctype.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <wchar.h>
29 #include <wctype.h>
30 #include <bits/libc-lock.h>
31 #include <locale/localeinfo.h>
32
33 #ifdef  __GNUC__
34 # define HAVE_LONGLONG
35 # define LONGLONG       long long
36 #else
37 # define LONGLONG       long
38 #endif
39
40 /* Determine whether we have to handle `long long' at all.  */
41 #if LONG_MAX == LONG_LONG_MAX
42 # define need_longlong  0
43 #else
44 # define need_longlong  1
45 #endif
46
47 /* Determine whether we have to handle `long'.  */
48 #if INT_MAX == LONG_MAX
49 # define need_long      0
50 #else
51 # define need_long      1
52 #endif
53
54 /* Those are flags in the conversion format. */
55 #define LONG            0x001   /* l: long or double */
56 #define LONGDBL         0x002   /* L: long long or long double */
57 #define SHORT           0x004   /* h: short */
58 #define SUPPRESS        0x008   /* *: suppress assignment */
59 #define POINTER         0x010   /* weird %p pointer (`fake hex') */
60 #define NOSKIP          0x020   /* do not skip blanks */
61 #define WIDTH           0x040   /* width was given */
62 #define GROUP           0x080   /* ': group numbers */
63 #define MALLOC          0x100   /* a: malloc strings */
64 #define CHAR            0x200   /* hh: char */
65 #define I18N            0x400   /* I: use locale's digits */
66
67
68 #ifdef USE_IN_LIBIO
69 # include <libioP.h>
70 # include <libio.h>
71
72 # undef va_list
73 # define va_list        _IO_va_list
74
75 # ifdef COMPILE_WSCANF
76 #  define ungetc(c, s)  ((void) (c == WEOF                                    \
77                                  || (--read_in,                               \
78                                      _IO_sputbackwc (s, c))))
79 #  define ungetc_not_eof(c, s)  ((void) (--read_in,                           \
80                                          _IO_sputbackwc (s, c)))
81 #  define inchar()      (c == WEOF ? WEOF                                     \
82                          : ((c = _IO_getwc_unlocked (s)),                     \
83                             (void) (c != WEOF && ++read_in), c))
84
85 #  define MEMCPY(d, s, n) __wmemcpy (d, s, n)
86 #  define ISSPACE(Ch)     iswspace (Ch)
87 #  define ISDIGIT(Ch)     iswdigit (Ch)
88 #  define ISXDIGIT(Ch)    iswxdigit (Ch)
89 #  define TOLOWER(Ch)     towlower (Ch)
90 #  define ORIENT          if (_IO_fwide (s, -1) != -1) return WEOF
91 #  define __strtoll_internal    __wcstoll_internal
92 #  define __strtoull_internal   __wcstoull_internal
93 #  define __strtol_internal     __wcstol_internal
94 #  define __strtoul_internal    __wcstoul_internal
95 #  define __strtold_internal    __wcstold_internal
96 #  define __strtod_internal     __wcstod_internal
97 #  define __strtof_internal     __wcstof_internal
98
99 #  define L_(Str)         L##Str
100 #  define CHAR_T          wchar_t
101 #  define UCHAR_T         unsigned int
102 #  define WINT_T          wint_t
103 #  undef EOF
104 #  define EOF             WEOF
105 # else
106 #  define ungetc(c, s)  ((void) ((int) c == EOF                               \
107                                  || (--read_in,                               \
108                                      _IO_sputbackc (s, (unsigned char) c))))
109 #  define ungetc_not_eof(c, s)  ((void) (--read_in,                           \
110                                          _IO_sputbackc (s, (unsigned char) c)))
111 #  define inchar()      (c == EOF ? EOF                                       \
112                          : ((c = _IO_getc_unlocked (s)),                      \
113                             (void) (c != EOF && ++read_in), c))
114 #  define MEMCPY(d, s, n) memcpy (d, s, n)
115 #  define ISSPACE(Ch)     isspace (Ch)
116 #  define ISDIGIT(Ch)     isdigit (Ch)
117 #  define ISXDIGIT(Ch)    isxdigit (Ch)
118 #  define TOLOWER(Ch)     tolower (Ch)
119 #  define ORIENT          if (s->_vtable_offset == 0 && _IO_fwide (s, 1) != 1)\
120                             return EOF
121
122 #  define L_(Str)         Str
123 #  define CHAR_T          char
124 #  define UCHAR_T         unsigned char
125 #  define WINT_T          int
126 # endif
127
128 # define encode_error() do {                                                  \
129                           if (errp != NULL) *errp |= 4;                       \
130                           _IO_funlockfile (s);                                \
131                           __libc_cleanup_end (0);                             \
132                           __set_errno (EILSEQ);                               \
133                           return done;                                        \
134                         } while (0)
135 # define conv_error()   do {                                                  \
136                           if (errp != NULL) *errp |= 2;                       \
137                           _IO_funlockfile (s);                                \
138                           __libc_cleanup_end (0);                             \
139                           return done;                                        \
140                         } while (0)
141 # define input_error()  do {                                                  \
142                           _IO_funlockfile (s);                                \
143                           if (errp != NULL) *errp |= 1;                       \
144                           __libc_cleanup_end (0);                             \
145                           return done ?: EOF;                                 \
146                         } while (0)
147 # define memory_error() do {                                                  \
148                           _IO_funlockfile (s);                                \
149                           __set_errno (ENOMEM);                               \
150                           __libc_cleanup_end (0);                             \
151                           return EOF;                                         \
152                         } while (0)
153 # define ARGCHECK(s, format)                                                  \
154   do                                                                          \
155     {                                                                         \
156       /* Check file argument for consistence.  */                             \
157       CHECK_FILE (s, EOF);                                                    \
158       if (s->_flags & _IO_NO_READS)                                           \
159         {                                                                     \
160           __set_errno (EBADF);                                                \
161           return EOF;                                                         \
162         }                                                                     \
163       else if (format == NULL)                                                \
164         {                                                                     \
165           MAYBE_SET_EINVAL;                                                   \
166           return EOF;                                                         \
167         }                                                                     \
168     } while (0)
169 # define LOCK_STREAM(S)                                                       \
170   __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S));    \
171   _IO_flockfile (S)
172 # define UNLOCK_STREAM(S)                                                     \
173   _IO_funlockfile (S);                                                        \
174   __libc_cleanup_region_end (0)
175 #else
176 # define ungetc(c, s)   ((void) (c != EOF && --read_in), ungetc (c, s))
177 # define ungetc_not_eof(c, s)   (--read_in, (ungetc) (c, s))
178 # define inchar()       (c == EOF ? EOF                                       \
179                          : ((c = getc (s)), (void) (c != EOF && ++read_in), c))
180 # define MEMCPY(d, s, n)  memcpy (d, s, n)
181 # define ISSPACE(Ch)      isspace (Ch)
182 # define ISDIGIT(Ch)      isdigit (Ch)
183 # define ISXDIGIT(Ch)     isxdigit (Ch)
184 # define TOLOWER(Ch)      tolower (Ch)
185
186 # define L_(Str)          Str
187 # define CHAR_T           char
188 # define UCHAR_T          unsigned char
189 # define WINT_T           int
190
191 # define encode_error() do {                                                  \
192                           funlockfile (s);                                    \
193                           __set_errno (EILSEQ);                               \
194                           return done;                                        \
195                         } while (0)
196 # define conv_error()   do {                                                  \
197                           funlockfile (s);                                    \
198                           return done;                                        \
199                         } while (0)
200 # define input_error()  do {                                                  \
201                           funlockfile (s);                                    \
202                           return done ?: EOF;                                 \
203                         } while (0)
204 # define memory_error() do {                                                  \
205                           funlockfile (s);                                    \
206                           __set_errno (ENOMEM);                               \
207                           return EOF;                                         \
208                         } while (0)
209 # define ARGCHECK(s, format)                                                  \
210   do                                                                          \
211     {                                                                         \
212       /* Check file argument for consistence.  */                             \
213       if (!__validfp (s) || !s->__mode.__read)                                \
214         {                                                                     \
215           __set_errno (EBADF);                                                \
216           return EOF;                                                         \
217         }                                                                     \
218       else if (format == NULL)                                                \
219         {                                                                     \
220           __set_errno (EINVAL);                                               \
221           return EOF;                                                         \
222         }                                                                     \
223     } while (0)
224 #if 1
225       /* XXX For now !!! */
226 # define flockfile(S) /* nothing */
227 # define funlockfile(S) /* nothing */
228 # define LOCK_STREAM(S)
229 # define UNLOCK_STREAM(S)
230 #else
231 # define LOCK_STREAM(S)                                                       \
232   __libc_cleanup_region_start (&__funlockfile, (S));                          \
233   __flockfile (S)
234 # define UNLOCK_STREAM(S)                                                     \
235   __funlockfile (S);                                                          \
236   __libc_cleanup_region_end (0)
237 #endif
238 #endif
239
240
241 /* Read formatted input from S according to the format string
242    FORMAT, using the argument list in ARG.
243    Return the number of assignments made, or -1 for an input error.  */
244 #ifdef USE_IN_LIBIO
245 # ifdef COMPILE_WSCANF
246 int
247 _IO_vfwscanf (s, format, argptr, errp)
248      _IO_FILE *s;
249      const wchar_t *format;
250      _IO_va_list argptr;
251      int *errp;
252 # else
253 int
254 _IO_vfscanf (s, format, argptr, errp)
255      _IO_FILE *s;
256      const char *format;
257      _IO_va_list argptr;
258      int *errp;
259 # endif
260 #else
261 int
262 __vfscanf (FILE *s, const char *format, va_list argptr)
263 #endif
264 {
265   va_list arg;
266   register const CHAR_T *f = format;
267   register UCHAR_T fc;  /* Current character of the format.  */
268   register size_t done = 0;     /* Assignments done.  */
269   register size_t read_in = 0;  /* Chars read in.  */
270   register WINT_T c = 0;        /* Last char read.  */
271   register int width;           /* Maximum field width.  */
272   register int flags;           /* Modifiers for current format element.  */
273
274   /* Status for reading F-P nums.  */
275   char got_dot, got_e, negative;
276   /* If a [...] is a [^...].  */
277   CHAR_T not_in;
278 #define exp_char not_in
279   /* Base for integral numbers.  */
280   int base;
281   /* Signedness for integral numbers.  */
282   int number_signed;
283 #define is_hexa number_signed
284   /* Decimal point character.  */
285 #ifdef COMPILE_WSCANF
286   wchar_t decimal;
287 #else
288   const char *decimal;
289 #endif
290   /* The thousands character of the current locale.  */
291 #ifdef COMPILE_WSCANF
292   wchar_t thousands;
293 #else
294   const char *thousands;
295 #endif
296   /* State for the conversions.  */
297   mbstate_t state;
298   /* Integral holding variables.  */
299   union
300     {
301       long long int q;
302       unsigned long long int uq;
303       long int l;
304       unsigned long int ul;
305     } num;
306   /* Character-buffer pointer.  */
307   char *str = NULL;
308   wchar_t *wstr = NULL;
309   char **strptr = NULL;
310   size_t strsize = 0;
311   /* We must not react on white spaces immediately because they can
312      possibly be matched even if in the input stream no character is
313      available anymore.  */
314   int skip_space = 0;
315   /* Nonzero if we are reading a pointer.  */
316   int read_pointer;
317   /* Workspace.  */
318   CHAR_T *tw;                   /* Temporary pointer.  */
319   CHAR_T *wp = NULL;            /* Workspace.  */
320   size_t wpmax = 0;             /* Maximal size of workspace.  */
321   size_t wpsize;                /* Currently used bytes in workspace.  */
322 #define ADDW(Ch)                                                            \
323   do                                                                        \
324     {                                                                       \
325       if (wpsize == wpmax)                                                  \
326         {                                                                   \
327           CHAR_T *old = wp;                                                 \
328           wpmax = (UCHAR_MAX + 1 > 2 * wpmax ? UCHAR_MAX + 1 : 2 * wpmax);  \
329           wp = (CHAR_T *) alloca (wpmax * sizeof (wchar_t));                \
330           if (old != NULL)                                                  \
331             MEMCPY (wp, old, wpsize);                                       \
332         }                                                                   \
333       wp[wpsize++] = (Ch);                                                  \
334     }                                                                       \
335   while (0)
336
337 #ifdef __va_copy
338   __va_copy (arg, argptr);
339 #else
340   arg = (va_list) argptr;
341 #endif
342
343 #ifdef ORIENT
344   ORIENT;
345 #endif
346
347   ARGCHECK (s, format);
348
349   /* Figure out the decimal point character.  */
350 #ifdef COMPILE_WSCANF
351   decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
352 #else
353   decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
354 #endif
355   /* Figure out the thousands separator character.  */
356 #ifdef COMPILE_WSCANF
357   thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
358 #else
359   thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
360   if (*thousands == '\0')
361     thousands = NULL;
362 #endif
363
364   /* Lock the stream.  */
365   LOCK_STREAM (s);
366
367
368 #ifndef COMPILE_WSCANF
369   /* From now on we use `state' to convert the format string.  */
370   memset (&state, '\0', sizeof (state));
371 #endif
372
373   /* Run through the format string.  */
374   while (*f != '\0')
375     {
376       unsigned int argpos;
377       /* Extract the next argument, which is of type TYPE.
378          For a %N$... spec, this is the Nth argument from the beginning;
379          otherwise it is the next argument after the state now in ARG.  */
380 #ifdef __va_copy
381 # define ARG(type)      (argpos == 0 ? va_arg (arg, type) :                   \
382                          ({ unsigned int pos = argpos;                        \
383                             va_list arg;                                      \
384                             __va_copy (arg, argptr);                          \
385                             while (--pos > 0)                                 \
386                               (void) va_arg (arg, void *);                    \
387                             va_arg (arg, type);                               \
388                           }))
389 #else
390 # if 0
391       /* XXX Possible optimization.  */
392 #  define ARG(type)     (argpos == 0 ? va_arg (arg, type) :                   \
393                          ({ va_list arg = (va_list) argptr;                   \
394                             arg = (va_list) ((char *) arg                     \
395                                              + (argpos - 1)                   \
396                                              * __va_rounded_size (void *));   \
397                             va_arg (arg, type);                               \
398                          }))
399 # else
400 #  define ARG(type)     (argpos == 0 ? va_arg (arg, type) :                   \
401                          ({ unsigned int pos = argpos;                        \
402                             va_list arg = (va_list) argptr;                   \
403                             while (--pos > 0)                                 \
404                               (void) va_arg (arg, void *);                    \
405                             va_arg (arg, type);                               \
406                           }))
407 # endif
408 #endif
409
410 #ifndef COMPILE_WSCANF
411       if (!isascii ((unsigned char) *f))
412         {
413           /* Non-ASCII, may be a multibyte.  */
414           int len = __mbrlen (f, strlen (f), &state);
415           if (len > 0)
416             {
417               do
418                 {
419                   c = inchar ();
420                   if (c == EOF)
421                     input_error ();
422                   else if (c != (unsigned char) *f++)
423                     {
424                       ungetc_not_eof (c, s);
425                       conv_error ();
426                     }
427                 }
428               while (--len > 0);
429               continue;
430             }
431         }
432 #endif
433
434       fc = *f++;
435       if (fc != '%')
436         {
437           /* Remember to skip spaces.  */
438           if (ISSPACE (fc))
439             {
440               skip_space = 1;
441               continue;
442             }
443
444           /* Read a character.  */
445           c = inchar ();
446
447           /* Characters other than format specs must just match.  */
448           if (c == EOF)
449             input_error ();
450
451           /* We saw white space char as the last character in the format
452              string.  Now it's time to skip all leading white space.  */
453           if (skip_space)
454             {
455               while (ISSPACE (c))
456                 if (inchar () == EOF && errno == EINTR)
457                   conv_error ();
458               skip_space = 0;
459             }
460
461           if (c != fc)
462             {
463               ungetc (c, s);
464               conv_error ();
465             }
466
467           continue;
468         }
469
470       /* This is the start of the conversion string. */
471       flags = 0;
472
473       /* Not yet decided whether we read a pointer or not.  */
474       read_pointer = 0;
475
476       /* Initialize state of modifiers.  */
477       argpos = 0;
478
479       /* Prepare temporary buffer.  */
480       wpsize = 0;
481
482       /* Check for a positional parameter specification.  */
483       if (ISDIGIT ((UCHAR_T) *f))
484         {
485           argpos = (UCHAR_T) *f++ - L_('0');
486           while (ISDIGIT ((UCHAR_T) *f))
487             argpos = argpos * 10 + ((UCHAR_T) *f++ - L_('0'));
488           if (*f == L_('$'))
489             ++f;
490           else
491             {
492               /* Oops; that was actually the field width.  */
493               width = argpos;
494               flags |= WIDTH;
495               argpos = 0;
496               goto got_width;
497             }
498         }
499
500       /* Check for the assignment-suppressing, the number grouping flag,
501          and the signal to use the locale's digit representation.  */
502       while (*f == L_('*') || *f == L_('\'') || *f == L_('I'))
503         switch (*f++)
504           {
505           case L_('*'):
506             flags |= SUPPRESS;
507             break;
508           case L_('\''):
509             flags |= GROUP;
510             break;
511           case L_('I'):
512             flags |= I18N;
513             break;
514           }
515
516       /* We have seen width. */
517       if (ISDIGIT ((UCHAR_T) *f))
518         flags |= WIDTH;
519
520       /* Find the maximum field width.  */
521       width = 0;
522       while (ISDIGIT ((UCHAR_T) *f))
523         {
524           width *= 10;
525           width += (UCHAR_T) *f++ - L_('0');
526         }
527     got_width:
528       if (width == 0)
529         width = -1;
530
531       /* Check for type modifiers.  */
532       switch (*f++)
533         {
534         case L_('h'):
535           /* ints are short ints or chars.  */
536           if (*f == L_('h'))
537             {
538               ++f;
539               flags |= CHAR;
540             }
541           else
542             flags |= SHORT;
543           break;
544         case L_('l'):
545           if (*f == L_('l'))
546             {
547               /* A double `l' is equivalent to an `L'.  */
548               ++f;
549               flags |= LONGDBL | LONG;
550             }
551           else
552             /* ints are long ints.  */
553             flags |= LONG;
554           break;
555         case L_('q'):
556         case L_('L'):
557           /* doubles are long doubles, and ints are long long ints.  */
558           flags |= LONGDBL | LONG;
559           break;
560         case L_('a'):
561           /* The `a' is used as a flag only if followed by `s', `S' or
562              `['.  */
563           if (*f != L_('s') && *f != L_('S') && *f != L_('['))
564             {
565               --f;
566               break;
567             }
568           /* String conversions (%s, %[) take a `char **'
569              arg and fill it in with a malloc'd pointer.  */
570           flags |= MALLOC;
571           break;
572         case L_('z'):
573           if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
574             flags |= LONGDBL;
575           else if (sizeof (size_t) > sizeof (unsigned int))
576             flags |= LONG;
577           break;
578         case L_('j'):
579           if (need_longlong && sizeof (uintmax_t) > sizeof (unsigned long int))
580             flags |= LONGDBL;
581           else if (sizeof (uintmax_t) > sizeof (unsigned int))
582             flags |= LONG;
583           break;
584         case L_('t'):
585           if (need_longlong && sizeof (ptrdiff_t) > sizeof (long int))
586             flags |= LONGDBL;
587           else if (sizeof (ptrdiff_t) > sizeof (int))
588             flags |= LONG;
589           break;
590         default:
591           /* Not a recognized modifier.  Backup.  */
592           --f;
593           break;
594         }
595
596       /* End of the format string?  */
597       if (*f == L_('\0'))
598         conv_error ();
599
600       /* Find the conversion specifier.  */
601       fc = *f++;
602       if (skip_space || (fc != L_('[') && fc != L_('c')
603                          && fc != L_('C') && fc != L_('n')))
604         {
605           /* Eat whitespace.  */
606           int save_errno = errno;
607           errno = 0;
608           do
609             if (inchar () == EOF && errno == EINTR)
610               input_error ();
611           while (ISSPACE (c));
612           errno = save_errno;
613           ungetc (c, s);
614           skip_space = 0;
615         }
616
617       switch (fc)
618         {
619         case L_('%'):   /* Must match a literal '%'.  */
620           c = inchar ();
621           if (c == EOF)
622             input_error ();
623           if (c != fc)
624             {
625               ungetc_not_eof (c, s);
626               conv_error ();
627             }
628           break;
629
630         case L_('n'):   /* Answer number of assignments done.  */
631           /* Corrigendum 1 to ISO C 1990 describes the allowed flags
632              with the 'n' conversion specifier.  */
633           if (!(flags & SUPPRESS))
634             {
635               /* Don't count the read-ahead.  */
636               if (need_longlong && (flags & LONGDBL))
637                 *ARG (long long int *) = read_in;
638               else if (need_long && (flags & LONG))
639                 *ARG (long int *) = read_in;
640               else if (flags & SHORT)
641                 *ARG (short int *) = read_in;
642               else if (!(flags & CHAR))
643                 *ARG (int *) = read_in;
644               else
645                 *ARG (char *) = read_in;
646
647 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
648               /* We have a severe problem here.  The ISO C standard
649                  contradicts itself in explaining the effect of the %n
650                  format in `scanf'.  While in ISO C:1990 and the ISO C
651                  Amendement 1:1995 the result is described as
652
653                    Execution of a %n directive does not effect the
654                    assignment count returned at the completion of
655                    execution of the f(w)scanf function.
656
657                  in ISO C Corrigendum 1:1994 the following was added:
658
659                    Subclause 7.9.6.2
660                    Add the following fourth example:
661                      In:
662                        #include <stdio.h>
663                        int d1, d2, n1, n2, i;
664                        i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
665                      the value 123 is assigned to d1 and the value3 to n1.
666                      Because %n can never get an input failure the value
667                      of 3 is also assigned to n2.  The value of d2 is not
668                      affected.  The value 3 is assigned to i.
669
670                  We go for now with the historically correct code from ISO C,
671                  i.e., we don't count the %n assignments.  When it ever
672                  should proof to be wrong just remove the #ifdef above.  */
673               ++done;
674 #endif
675             }
676           break;
677
678         case L_('c'):   /* Match characters.  */
679           if ((flags & LONG) == 0)
680             {
681               if (!(flags & SUPPRESS))
682                 {
683                   str = ARG (char *);
684                   if (str == NULL)
685                     conv_error ();
686                 }
687
688               c = inchar ();
689               if (c == EOF)
690                 input_error ();
691
692               if (width == -1)
693                 width = 1;
694
695 #ifdef COMPILE_WSCANF
696               /* We have to convert the wide character(s) into multibyte
697                  characters and store the result.  */
698               memset (&state, '\0', sizeof (state));
699
700               do
701                 {
702                   size_t n;
703
704                   n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
705                   if (n == (size_t) -1)
706                     /* No valid wide character.  */
707                     input_error ();
708
709                   /* Increment the output pointer.  Even if we don't
710                      write anything.  */
711                   str += n;
712                 }
713               while (--width > 0 && inchar () != EOF);
714 #else
715               if (!(flags & SUPPRESS))
716                 {
717                   do
718                     *str++ = c;
719                   while (--width > 0 && inchar () != EOF);
720                 }
721               else
722                 while (--width > 0 && inchar () != EOF);
723 #endif
724
725               if (!(flags & SUPPRESS))
726                 ++done;
727
728               break;
729             }
730           /* FALLTHROUGH */
731         case L_('C'):
732           if (!(flags & SUPPRESS))
733             {
734               wstr = ARG (wchar_t *);
735               if (wstr == NULL)
736                 conv_error ();
737             }
738
739           c = inchar ();
740           if (c == EOF)
741             input_error ();
742
743 #ifdef COMPILE_WSCANF
744           /* Just store the incoming wide characters.  */
745           if (!(flags & SUPPRESS))
746             {
747               do
748                 *wstr++ = c;
749               while (--width > 0 && inchar () != EOF);
750             }
751           else
752             while (--width > 0 && inchar () != EOF);
753 #else
754           {
755             /* We have to convert the multibyte input sequence to wide
756                characters.  */
757             char buf[MB_LEN_MAX];
758             mbstate_t cstate;
759
760             memset (&cstate, '\0', sizeof (cstate));
761
762             do
763               {
764                 size_t cnt;
765
766                 /* This is what we present the mbrtowc function first.  */
767                 buf[0] = c;
768                 cnt = 1;
769
770                 while (1)
771                   {
772                     size_t n;
773
774                     n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
775                                    buf, cnt, &cstate);
776
777                     if (n == (size_t) -2)
778                       {
779                         /* Possibly correct character, just not enough
780                            input.  */
781                         assert (cnt < MB_CUR_MAX);
782
783                         if (inchar () == EOF)
784                           encode_error ();
785
786                         buf[cnt++] = c;
787                         continue;
788                       }
789
790                     if (n != cnt)
791                       encode_error ();
792
793                     /* We have a match.  */
794                     break;
795                   }
796
797                 /* Advance the result pointer.  */
798                 ++wstr;
799               }
800             while (--width > 0 && inchar () != EOF);
801           }
802 #endif
803
804           if (!(flags & SUPPRESS))
805             ++done;
806
807           break;
808
809         case L_('s'):           /* Read a string.  */
810           if (!(flags & LONG))
811             {
812 #define STRING_ARG(Str, Type)                                                 \
813               do if (!(flags & SUPPRESS))                                     \
814                 {                                                             \
815                   if (flags & MALLOC)                                         \
816                     {                                                         \
817                       /* The string is to be stored in a malloc'd buffer.  */ \
818                       strptr = ARG (char **);                                 \
819                       if (strptr == NULL)                                     \
820                         conv_error ();                                        \
821                       /* Allocate an initial buffer.  */                      \
822                       strsize = 100;                                          \
823                       *strptr = (char *) malloc (strsize * sizeof (Type));    \
824                       Str = (Type *) *strptr;                                 \
825                     }                                                         \
826                   else                                                        \
827                     Str = ARG (Type *);                                       \
828                   if (Str == NULL)                                            \
829                     conv_error ();                                            \
830                 } while (0)
831               STRING_ARG (str, char);
832
833               c = inchar ();
834               if (c == EOF)
835                 input_error ();
836
837 #ifdef COMPILE_WSCANF
838               memset (&state, '\0', sizeof (state));
839 #endif
840
841               do
842                 {
843                   if (ISSPACE (c))
844                     {
845                       ungetc_not_eof (c, s);
846                       break;
847                     }
848
849 #ifdef COMPILE_WSCANF
850                   /* This is quite complicated.  We have to convert the
851                      wide characters into multibyte characters and then
852                      store them.  */
853                   {
854                     size_t n;
855
856                     if (!(flags & SUPPRESS) && (flags & MALLOC)
857                         && str + MB_CUR_MAX >= *strptr + strsize)
858                       {
859                         /* We have to enlarge the buffer if the `a' flag
860                            was given.  */
861                         size_t strleng = str - *strptr;
862                         char *newstr;
863
864                         newstr = (char *) realloc (*strptr, strsize * 2);
865                         if (newstr == NULL)
866                           {
867                             /* Can't allocate that much.  Last-ditch
868                                effort.  */
869                             newstr = (char *) realloc (*strptr,
870                                                        strleng + MB_CUR_MAX);
871                             if (newstr == NULL)
872                               {
873                                 /* We lose.  Oh well.  Terminate the
874                                    string and stop converting,
875                                    so at least we don't skip any input.  */
876                                 ((char *) (*strptr))[strleng] = '\0';
877                                 ++done;
878                                 conv_error ();
879                               }
880                             else
881                               {
882                                 *strptr = newstr;
883                                 str = newstr + strleng;
884                                 strsize = strleng + MB_CUR_MAX;
885                               }
886                           }
887                         else
888                           {
889                             *strptr = newstr;
890                             str = newstr + strleng;
891                             strsize *= 2;
892                           }
893                       }
894
895                     n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c,
896                                    &state);
897                     if (n == (size_t) -1)
898                       encode_error ();
899
900                     assert (n <= MB_CUR_MAX);
901                     str += n;
902                   }
903 #else
904                   /* This is easy.  */
905                   if (!(flags & SUPPRESS))
906                     {
907                       *str++ = c;
908                       if ((flags & MALLOC)
909                           && (char *) str == *strptr + strsize)
910                         {
911                           /* Enlarge the buffer.  */
912                           str = (char *) realloc (*strptr, 2 * strsize);
913                           if (str == NULL)
914                             {
915                               /* Can't allocate that much.  Last-ditch
916                                  effort.  */
917                               str = (char *) realloc (*strptr, strsize + 1);
918                               if (str == NULL)
919                                 {
920                                   /* We lose.  Oh well.  Terminate the
921                                      string and stop converting,
922                                      so at least we don't skip any input.  */
923                                   ((char *) (*strptr))[strsize - 1] = '\0';
924                                   ++done;
925                                   conv_error ();
926                                 }
927                               else
928                                 {
929                                   *strptr = (char *) str;
930                                   str += strsize;
931                                   ++strsize;
932                                 }
933                             }
934                           else
935                             {
936                               *strptr = (char *) str;
937                               str += strsize;
938                               strsize *= 2;
939                             }
940                         }
941                     }
942 #endif
943                 }
944               while ((width <= 0 || --width > 0) && inchar () != EOF);
945
946               if (!(flags & SUPPRESS))
947                 {
948 #ifdef COMPILE_WSCANF
949                   /* We have to emit the code to get into the initial
950                      state.  */
951                   char buf[MB_LEN_MAX];
952                   size_t n = __wcrtomb (buf, L'\0', &state);
953                   if (n > 0 && (flags & MALLOC)
954                       && str + n >= *strptr + strsize)
955                     {
956                       /* Enlarge the buffer.  */
957                       size_t strleng = str - *strptr;
958                       char *newstr;
959
960                       newstr = (char *) realloc (*strptr, strleng + n + 1);
961                       if (newstr == NULL)
962                         {
963                           /* We lose.  Oh well.  Terminate the string
964                              and stop converting, so at least we don't
965                              skip any input.  */
966                           ((char *) (*strptr))[strleng] = '\0';
967                           ++done;
968                           conv_error ();
969                         }
970                       else
971                         {
972                           *strptr = newstr;
973                           str = newstr + strleng;
974                           strsize = strleng + n + 1;
975                         }
976                     }
977
978                   str = __mempcpy (str, buf, n);
979 #endif
980                   *str++ = '\0';
981
982                   if ((flags & MALLOC) && str - *strptr != strsize)
983                     {
984                       char *cp = (char *) realloc (*strptr, str - *strptr);
985                       if (cp != NULL)
986                         *strptr = cp;
987                     }
988
989                   ++done;
990                 }
991               break;
992             }
993           /* FALLTHROUGH */
994
995         case L_('S'):
996           {
997 #ifndef COMPILE_WSCANF
998             mbstate_t cstate;
999 #endif
1000
1001             /* Wide character string.  */
1002             STRING_ARG (wstr, wchar_t);
1003
1004             c = inchar ();
1005             if (c == EOF)
1006               input_error ();
1007
1008 #ifndef COMPILE_WSCANF
1009             memset (&cstate, '\0', sizeof (cstate));
1010 #endif
1011
1012             do
1013               {
1014                 if (ISSPACE (c))
1015                   {
1016                     ungetc_not_eof (c, s);
1017                     break;
1018                   }
1019
1020 #ifdef COMPILE_WSCANF
1021                 /* This is easy.  */
1022                 if (!(flags & SUPPRESS))
1023                   {
1024                     *wstr++ = c;
1025                     if ((flags & MALLOC)
1026                         && wstr == (wchar_t *) *strptr + strsize)
1027                       {
1028                         /* Enlarge the buffer.  */
1029                         wstr = (wchar_t *) realloc (*strptr,
1030                                                     (2 * strsize)
1031                                                     * sizeof (wchar_t));
1032                         if (wstr == NULL)
1033                           {
1034                             /* Can't allocate that much.  Last-ditch
1035                                effort.  */
1036                             wstr = (wchar_t *) realloc (*strptr,
1037                                                         (strsize + 1)
1038                                                         * sizeof (wchar_t));
1039                             if (wstr == NULL)
1040                               {
1041                                 /* We lose.  Oh well.  Terminate the string
1042                                    and stop converting, so at least we don't
1043                                    skip any input.  */
1044                                 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1045                                 ++done;
1046                                 conv_error ();
1047                               }
1048                             else
1049                               {
1050                                 *strptr = (char *) wstr;
1051                                 wstr += strsize;
1052                                 ++strsize;
1053                               }
1054                           }
1055                         else
1056                           {
1057                             *strptr = (char *) wstr;
1058                             wstr += strsize;
1059                             strsize *= 2;
1060                           }
1061                       }
1062                   }
1063 #else
1064                 {
1065                   char buf[MB_LEN_MAX];
1066                   size_t cnt;
1067
1068                   buf[0] = c;
1069                   cnt = 1;
1070
1071                   while (1)
1072                     {
1073                       size_t n;
1074
1075                       n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
1076                                      buf, cnt, &cstate);
1077
1078                       if (n == (size_t) -2)
1079                         {
1080                           /* Possibly correct character, just not enough
1081                              input.  */
1082                           assert (cnt < MB_CUR_MAX);
1083
1084                           if (inchar () == EOF)
1085                             encode_error ();
1086
1087                           buf[cnt++] = c;
1088                           continue;
1089                         }
1090
1091                       if (n != cnt)
1092                         encode_error ();
1093
1094                       /* We have a match.  */
1095                       break;
1096                     }
1097
1098                   if (!(flags & SUPPRESS) && (flags & MALLOC)
1099                       && wstr == (wchar_t *) *strptr + strsize)
1100                     {
1101                       /* Enlarge the buffer.  */
1102                       wstr = (wchar_t *) realloc (*strptr,
1103                                                   (2 * strsize
1104                                                    * sizeof (wchar_t)));
1105                       if (wstr == NULL)
1106                         {
1107                           /* Can't allocate that much.  Last-ditch effort.  */
1108                           wstr = (wchar_t *) realloc (*strptr,
1109                                                       ((strsize + 1)
1110                                                        * sizeof (wchar_t)));
1111                           if (wstr == NULL)
1112                             {
1113                               /* We lose.  Oh well.  Terminate the
1114                                  string and stop converting, so at
1115                                  least we don't skip any input.  */
1116                               ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1117                               ++done;
1118                               conv_error ();
1119                             }
1120                           else
1121                             {
1122                               *strptr = (char *) wstr;
1123                               wstr += strsize;
1124                               ++strsize;
1125                             }
1126                         }
1127                       else
1128                         {
1129                           *strptr = (char *) wstr;
1130                           wstr += strsize;
1131                           strsize *= 2;
1132                         }
1133                     }
1134                 }
1135 #endif
1136               }
1137             while ((width <= 0 || --width > 0) && inchar () != EOF);
1138
1139             if (!(flags & SUPPRESS))
1140               {
1141                 *wstr++ = L'\0';
1142
1143                 if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
1144                   {
1145                     wchar_t *cp = (wchar_t *) realloc (*strptr,
1146                                                        ((wstr
1147                                                          - (wchar_t *) *strptr)
1148                                                         * sizeof(wchar_t)));
1149                     if (cp != NULL)
1150                       *strptr = (char *) cp;
1151                   }
1152
1153                 ++done;
1154               }
1155           }
1156           break;
1157
1158         case L_('x'):   /* Hexadecimal integer.  */
1159         case L_('X'):   /* Ditto.  */
1160           base = 16;
1161           number_signed = 0;
1162           goto number;
1163
1164         case L_('o'):   /* Octal integer.  */
1165           base = 8;
1166           number_signed = 0;
1167           goto number;
1168
1169         case L_('u'):   /* Unsigned decimal integer.  */
1170           base = 10;
1171           number_signed = 0;
1172           goto number;
1173
1174         case L_('d'):   /* Signed decimal integer.  */
1175           base = 10;
1176           number_signed = 1;
1177           goto number;
1178
1179         case L_('i'):   /* Generic number.  */
1180           base = 0;
1181           number_signed = 1;
1182
1183         number:
1184           c = inchar ();
1185           if (c == EOF)
1186             input_error ();
1187
1188           /* Check for a sign.  */
1189           if (c == L_('-') || c == L_('+'))
1190             {
1191               ADDW (c);
1192               if (width > 0)
1193                 --width;
1194               c = inchar ();
1195             }
1196
1197           /* Look for a leading indication of base.  */
1198           if (width != 0 && c == L_('0'))
1199             {
1200               if (width > 0)
1201                 --width;
1202
1203               ADDW (c);
1204               c = inchar ();
1205
1206               if (width != 0 && TOLOWER (c) == L_('x'))
1207                 {
1208                   if (base == 0)
1209                     base = 16;
1210                   if (base == 16)
1211                     {
1212                       if (width > 0)
1213                         --width;
1214                       c = inchar ();
1215                     }
1216                 }
1217               else if (base == 0)
1218                 base = 8;
1219             }
1220
1221           if (base == 0)
1222             base = 10;
1223
1224           if (base == 10 && (flags & I18N) != 0)
1225             {
1226               int from_level;
1227               int to_level;
1228               int level;
1229 #ifdef COMPILE_WSCANF
1230               const wchar_t *wcdigits[10];
1231 #else
1232               const char *mbdigits[10];
1233 #endif
1234               int n;
1235
1236               from_level = 0;
1237 #ifdef COMPILE_WSCANF
1238               to_level = _NL_CURRENT_WORD (LC_CTYPE,
1239                                            _NL_CTYPE_INDIGITS_WC_LEN) - 1;
1240 #else
1241               to_level = _NL_CURRENT_WORD (LC_CTYPE,
1242                                            _NL_CTYPE_INDIGITS_MB_LEN) - 1;
1243 #endif
1244
1245               /* Read the number into workspace.  */
1246               while (c != EOF && width != 0)
1247                 {
1248                   /* In this round we get the pointer to the digit strings
1249                      and also perform the first round of comparisons.  */
1250                   for (n = 0; n < 10; ++n)
1251                     {
1252                       /* Get the string for the digits with value N.  */
1253 #ifdef COMPILE_WSCANF
1254                       wcdigits[n] = (const wchar_t *)
1255                         _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
1256                       wcdigits[n] += from_level;
1257
1258                       if (c == *wcdigits[n])
1259                         {
1260                           to_level = from_level;
1261                           break;
1262                         }
1263
1264                       /* Advance the pointer to the next string.  */
1265                       ++wcdigits[n];
1266 #else
1267                       const char *cmpp;
1268                       int avail = width > 0 ? width : INT_MAX;
1269
1270                       mbdigits[n] = _NL_CURRENT (LC_CTYPE,
1271                                                  _NL_CTYPE_INDIGITS0_MB + n);
1272
1273                       for (level = 0; level < from_level; level++)
1274                         mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1275
1276                       cmpp = mbdigits[n];
1277                       while ((unsigned char) *cmpp == c && avail > 0)
1278                         {
1279                           if (*++cmpp == '\0')
1280                             break;
1281                           else
1282                             {
1283                               if ((c = inchar ()) == EOF)
1284                                 break;
1285                               --avail;
1286                             }
1287                         }
1288
1289                       if (*cmpp == '\0')
1290                         {
1291                           if (width > 0)
1292                             width = avail;
1293                           to_level = from_level;
1294                           break;
1295                         }
1296
1297                       /* We are pushing all read characters back.  */
1298                       if (cmpp > mbdigits[n])
1299                         {
1300                           ungetc (c, s);
1301                           while (--cmpp > mbdigits[n])
1302                             ungetc_not_eof ((unsigned char) *cmpp, s);
1303                           c = (unsigned char) *cmpp;
1304                         }
1305
1306                       /* Advance the pointer to the next string.  */
1307                       mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1308 #endif
1309                     }
1310
1311                   if (n == 10)
1312                     {
1313                       /* Have not yet found the digit.  */
1314                       for (level = from_level + 1; level <= to_level; ++level)
1315                         {
1316                           /* Search all ten digits of this level.  */
1317                           for (n = 0; n < 10; ++n)
1318                             {
1319 #ifdef COMPILE_WSCANF
1320                               if (c == *wcdigits[n])
1321                                 break;
1322
1323                               /* Advance the pointer to the next string.  */
1324                               ++wcdigits[n];
1325 #else
1326                               const char *cmpp;
1327                               int avail = width > 0 ? width : INT_MAX;
1328
1329                               cmpp = mbdigits[n];
1330                               while ((unsigned char) *cmpp == c && avail > 0)
1331                                 {
1332                                   if (*++cmpp == '\0')
1333                                     break;
1334                                   else
1335                                     {
1336                                       if ((c = inchar ()) == EOF)
1337                                         break;
1338                                       --avail;
1339                                     }
1340                                 }
1341
1342                               if (*cmpp == '\0')
1343                                 {
1344                                   if (width > 0)
1345                                     width = avail;
1346                                   break;
1347                                 }
1348
1349                               /* We are pushing all read characters back.  */
1350                               if (cmpp > mbdigits[n])
1351                                 {
1352                                   ungetc (c, s);
1353                                   while (--cmpp > mbdigits[n])
1354                                     ungetc_not_eof ((unsigned char) *cmpp, s);
1355                                   c = (unsigned char) *cmpp;
1356                                 }
1357
1358                               /* Advance the pointer to the next string.  */
1359                               mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1360 #endif
1361                             }
1362
1363                           if (n < 10)
1364                             {
1365                               /* Found it.  */
1366                               from_level = level;
1367                               to_level = level;
1368                               break;
1369                             }
1370                         }
1371                     }
1372
1373                   if (n < 10)
1374                     c = L_('0') + n;
1375                   else if ((flags & GROUP)
1376 #ifdef COMPILE_WSCANF
1377                            && thousands != L'\0'
1378 #else
1379                            && thousands != NULL
1380 #endif
1381                            )
1382                     {
1383                       /* Try matching against the thousands separator.  */
1384 #ifdef COMPILE_WSCANF
1385                       if (c != thousands)
1386                           break;
1387 #else
1388                       const char *cmpp = thousands;
1389                       int avail = width > 0 ? width : INT_MAX;
1390
1391                       while ((unsigned char) *cmpp == c && avail > 0)
1392                         {
1393                           ADDW (c);
1394                           if (*++cmpp == '\0')
1395                             break;
1396                           else
1397                             {
1398                               if ((c = inchar ()) == EOF)
1399                                 break;
1400                               --avail;
1401                             }
1402                         }
1403
1404                       if (*cmpp != '\0')
1405                         {
1406                           /* We are pushing all read characters back.  */
1407                           if (cmpp > thousands)
1408                             {
1409                               wpsize -= cmpp - thousands;
1410                               ungetc (c, s);
1411                               while (--cmpp > thousands)
1412                                 ungetc_not_eof ((unsigned char) *cmpp, s);
1413                               c = (unsigned char) *cmpp;
1414                             }
1415                           break;
1416                         }
1417
1418                       if (width > 0)
1419                         width = avail;
1420
1421                       /* The last thousands character will be added back by
1422                          the ADDW below.  */
1423                         --wpsize;
1424 #endif
1425                     }
1426                   else
1427                     break;
1428
1429                   ADDW (c);
1430                   if (width > 0)
1431                     --width;
1432
1433                   c = inchar ();
1434                 }
1435             }
1436           else
1437             /* Read the number into workspace.  */
1438             while (c != EOF && width != 0)
1439               {
1440                 if (base == 16)
1441                   {
1442                     if (!ISXDIGIT (c))
1443                       break;
1444                   }
1445                 else if (!ISDIGIT (c) || c - L_('0') >= base)
1446                   {
1447                     if (base == 10 && (flags & GROUP)
1448 #ifdef COMPILE_WSCANF
1449                         && thousands != L'\0'
1450 #else
1451                         && thousands != NULL
1452 #endif
1453                         )
1454                       {
1455                         /* Try matching against the thousands separator.  */
1456 #ifdef COMPILE_WSCANF
1457                         if (c != thousands)
1458                           break;
1459 #else
1460                         const char *cmpp = thousands;
1461                         int avail = width > 0 ? width : INT_MAX;
1462
1463                         while ((unsigned char) *cmpp == c && avail > 0)
1464                           {
1465                             ADDW (c);
1466                             if (*++cmpp == '\0')
1467                               break;
1468                             else
1469                               {
1470                                 if ((c = inchar ()) == EOF)
1471                                   break;
1472                                 --avail;
1473                               }
1474                           }
1475
1476                         if (*cmpp != '\0')
1477                           {
1478                             /* We are pushing all read characters back.  */
1479                             if (cmpp > thousands)
1480                               {
1481                                 wpsize -= cmpp - thousands;
1482                                 ungetc (c, s);
1483                                 while (--cmpp > thousands)
1484                                   ungetc_not_eof ((unsigned char) *cmpp, s);
1485                                 c = (unsigned char) *cmpp;
1486                               }
1487                             break;
1488                           }
1489
1490                         if (width > 0)
1491                           width = avail;
1492
1493                         /* The last thousands character will be added back by
1494                            the ADDW below.  */
1495                         --wpsize;
1496 #endif
1497                       }
1498                     else
1499                       break;
1500                   }
1501                 ADDW (c);
1502                 if (width > 0)
1503                   --width;
1504
1505                 c = inchar ();
1506               }
1507
1508           if (wpsize == 0
1509               || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
1510             {
1511               /* There was no number.  If we are supposed to read a pointer
1512                  we must recognize "(nil)" as well.  */
1513               if (wpsize == 0 && read_pointer && (width < 0 || width >= 0)
1514                   && c == '('
1515                   && TOLOWER (inchar ()) == L_('n')
1516                   && TOLOWER (inchar ()) == L_('i')
1517                   && TOLOWER (inchar ()) == L_('l')
1518                   && inchar () == L_(')'))
1519                 /* We must produce the value of a NULL pointer.  A single
1520                    '0' digit is enough.  */
1521                 ADDW (L_('0'));
1522               else
1523                 {
1524                   /* The last read character is not part of the number
1525                      anymore.  */
1526                   ungetc (c, s);
1527
1528                   conv_error ();
1529                 }
1530             }
1531           else
1532             /* The just read character is not part of the number anymore.  */
1533             ungetc (c, s);
1534
1535           /* Convert the number.  */
1536           ADDW (L_('\0'));
1537           if (need_longlong && (flags & LONGDBL))
1538             {
1539               if (number_signed)
1540                 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
1541               else
1542                 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
1543             }
1544           else
1545             {
1546               if (number_signed)
1547                 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
1548               else
1549                 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
1550             }
1551           if (wp == tw)
1552             conv_error ();
1553
1554           if (!(flags & SUPPRESS))
1555             {
1556               if (! number_signed)
1557                 {
1558                   if (need_longlong && (flags & LONGDBL))
1559                     *ARG (unsigned LONGLONG int *) = num.uq;
1560                   else if (need_long && (flags & LONG))
1561                     *ARG (unsigned long int *) = num.ul;
1562                   else if (flags & SHORT)
1563                     *ARG (unsigned short int *)
1564                       = (unsigned short int) num.ul;
1565                   else if (!(flags & CHAR))
1566                     *ARG (unsigned int *) = (unsigned int) num.ul;
1567                   else
1568                     *ARG (unsigned char *) = (unsigned char) num.ul;
1569                 }
1570               else
1571                 {
1572                   if (need_longlong && (flags & LONGDBL))
1573                     *ARG (LONGLONG int *) = num.q;
1574                   else if (need_long && (flags & LONG))
1575                     *ARG (long int *) = num.l;
1576                   else if (flags & SHORT)
1577                     *ARG (short int *) = (short int) num.l;
1578                   else if (!(flags & CHAR))
1579                     *ARG (int *) = (int) num.l;
1580                   else
1581                     *ARG (signed char *) = (signed char) num.ul;
1582                 }
1583               ++done;
1584             }
1585           break;
1586
1587         case L_('e'):   /* Floating-point numbers.  */
1588         case L_('E'):
1589         case L_('f'):
1590         case L_('F'):
1591         case L_('g'):
1592         case L_('G'):
1593         case L_('a'):
1594         case L_('A'):
1595           c = inchar ();
1596           if (c == EOF)
1597             input_error ();
1598
1599           /* Check for a sign.  */
1600           if (c == L_('-') || c == L_('+'))
1601             {
1602               negative = c == L_('-');
1603               if (width == 0 || inchar () == EOF)
1604                 /* EOF is only an input error before we read any chars.  */
1605                 conv_error ();
1606               if (! ISDIGIT (c))
1607                 {
1608 #ifdef COMPILE_WSCANF
1609                   if (c != decimal)
1610                     {
1611                       /* This is no valid number.  */
1612                       ungetc (c, s);
1613                       conv_error ();
1614                     }
1615 #else
1616                   /* Match against the decimal point.  At this point
1617                      we are taking advantage of the fact that we can
1618                      push more than one character back.  This is
1619                      (almost) never necessary since the decimal point
1620                      string hopefully never contains more than one
1621                      byte.  */
1622                   const char *cmpp = decimal;
1623                   int avail = width > 0 ? width : INT_MAX;
1624
1625                   while ((unsigned char) *cmpp == c && avail > 0)
1626                     if (*++cmpp == '\0')
1627                       break;
1628                     else
1629                       {
1630                         if (inchar () == EOF)
1631                           break;
1632                         --avail;
1633                       }
1634
1635                   if (*cmpp != '\0')
1636                     {
1637                       /* This is no valid number.  */
1638                       while (1)
1639                         {
1640                           ungetc (c, s);
1641                           if (cmpp == decimal)
1642                             break;
1643                           c = (unsigned char) *--cmpp;
1644                         }
1645
1646                       conv_error ();
1647                     }
1648                   if (width > 0)
1649                     width = avail;
1650 #endif
1651                 }
1652               if (width > 0)
1653                 --width;
1654             }
1655           else
1656             negative = 0;
1657
1658           /* Take care for the special arguments "nan" and "inf".  */
1659           if (TOLOWER (c) == L_('n'))
1660             {
1661               /* Maybe "nan".  */
1662               ADDW (c);
1663               if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('a'))
1664                 input_error ();
1665               if (width > 0)
1666                 --width;
1667               ADDW (c);
1668               if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1669                 input_error ();
1670               if (width > 0)
1671                 --width;
1672               ADDW (c);
1673               /* It is "nan".  */
1674               goto scan_float;
1675             }
1676           else if (TOLOWER (c) == L_('i'))
1677             {
1678               /* Maybe "inf" or "infinity".  */
1679               ADDW (c);
1680               if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1681                 input_error ();
1682               if (width > 0)
1683                 --width;
1684               ADDW (c);
1685               if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('f'))
1686                 input_error ();
1687               if (width > 0)
1688                 --width;
1689               ADDW (c);
1690               /* It is as least "inf".  */
1691               if (width != 0 && inchar () != EOF)
1692                 {
1693                   if (TOLOWER (c) == L_('i'))
1694                     {
1695                       if (width > 0)
1696                         --width;
1697                       /* Now we have to read the rest as well.  */
1698                       ADDW (c);
1699                       if (width == 0 || inchar () == EOF
1700                           || TOLOWER (c) != L_('n'))
1701                         input_error ();
1702                       if (width > 0)
1703                         --width;
1704                       ADDW (c);
1705                       if (width == 0 || inchar () == EOF
1706                           || TOLOWER (c) != L_('i'))
1707                         input_error ();
1708                       if (width > 0)
1709                         --width;
1710                       ADDW (c);
1711                       if (width == 0 || inchar () == EOF
1712                           || TOLOWER (c) != L_('t'))
1713                         input_error ();
1714                       if (width > 0)
1715                         --width;
1716                       ADDW (c);
1717                       if (width == 0 || inchar () == EOF
1718                           || TOLOWER (c) != L_('y'))
1719                         input_error ();
1720                       if (width > 0)
1721                         --width;
1722                       ADDW (c);
1723                     }
1724                   else
1725                     /* Never mind.  */
1726                     ungetc (c, s);
1727                 }
1728               goto scan_float;
1729             }
1730
1731           is_hexa = 0;
1732           exp_char = L_('e');
1733           if (width != 0 && c == L_('0'))
1734             {
1735               ADDW (c);
1736               c = inchar ();
1737               if (width > 0)
1738                 --width;
1739               if (width != 0 && TOLOWER (c) == L_('x'))
1740                 {
1741                   /* It is a number in hexadecimal format.  */
1742                   ADDW (c);
1743
1744                   is_hexa = 1;
1745                   exp_char = L_('p');
1746
1747                   /* Grouping is not allowed.  */
1748                   flags &= ~GROUP;
1749                   c = inchar ();
1750                   if (width > 0)
1751                     --width;
1752                 }
1753             }
1754
1755           got_dot = got_e = 0;
1756           do
1757             {
1758               if (ISDIGIT (c))
1759                 ADDW (c);
1760               else if (!got_e && is_hexa && ISXDIGIT (c))
1761                 ADDW (c);
1762               else if (got_e && wp[wpsize - 1] == exp_char
1763                        && (c == L_('-') || c == L_('+')))
1764                 ADDW (c);
1765               else if (wpsize > 0 && !got_e && TOLOWER (c) == exp_char)
1766                 {
1767                   ADDW (exp_char);
1768                   got_e = got_dot = 1;
1769                 }
1770               else
1771                 {
1772 #ifdef COMPILE_WSCANF
1773                   if (! got_dot && c == decimal)
1774                     {
1775                       ADDW (c);
1776                       got_dot = 1;
1777                     }
1778                   else if (thousands != L'\0' && ! got_dot && c == thousands)
1779                     ADDW (c);
1780                   else
1781                     {
1782                       /* The last read character is not part of the number
1783                          anymore.  */
1784                       ungetc (c, s);
1785                       break;
1786                     }
1787 #else
1788                   const char *cmpp = decimal;
1789                   int avail = width > 0 ? width : INT_MAX;
1790
1791                   if (! got_dot)
1792                     {
1793                       while ((unsigned char) *cmpp == c && avail > 0)
1794                         if (*++cmpp == '\0')
1795                           break;
1796                         else
1797                           {
1798                             if (inchar () == EOF)
1799                               break;
1800                             --avail;
1801                           }
1802                     }
1803
1804                   if (*cmpp == '\0')
1805                     {
1806                       /* Add all the characters.  */
1807                       for (cmpp = decimal; *cmpp != '\0'; ++cmpp)
1808                         ADDW ((unsigned char) *cmpp);
1809                       if (width > 0)
1810                         width = avail;
1811                       got_dot = 1;
1812                     }
1813                   else
1814                     {
1815                       /* Figure out whether it is a thousands separator.
1816                          There is one problem: we possibly read more than
1817                          one character.  We cannot push them back but since
1818                          we know that parts of the `decimal' string matched,
1819                          we can compare against it.  */
1820                       const char *cmp2p = thousands;
1821
1822                       if (thousands != NULL && ! got_dot)
1823                         {
1824                           while (cmp2p < cmpp
1825                                  && *cmp2p == decimal[cmp2p - thousands])
1826                             ++cmp2p;
1827                           if (cmp2p == cmpp)
1828                             {
1829                               while ((unsigned char) *cmp2p == c && avail > 0)
1830                                 if (*++cmp2p == '\0')
1831                                   break;
1832                                 else
1833                                   {
1834                                     if (inchar () == EOF)
1835                                       break;
1836                                     --avail;
1837                                   }
1838                             }
1839                         }
1840
1841                       if (cmp2p != NULL && *cmp2p == '\0')
1842                         {
1843                           /* Add all the characters.  */
1844                           for (cmpp = thousands; *cmpp != '\0'; ++cmpp)
1845                             ADDW ((unsigned char) *cmpp);
1846                           if (width > 0)
1847                             width = avail;
1848                         }
1849                       else
1850                         {
1851                           /* The last read character is not part of the number
1852                              anymore.  */
1853                           ungetc (c, s);
1854                           break;
1855                         }
1856                     }
1857 #endif
1858                 }
1859               if (width > 0)
1860                 --width;
1861             }
1862           while (width != 0 && inchar () != EOF);
1863
1864           /* Have we read any character?  If we try to read a number
1865              in hexadecimal notation and we have read only the `0x'
1866              prefix or no exponent this is an error.  */
1867           if (wpsize == 0 || (is_hexa && (wpsize == 2 || ! got_e)))
1868             conv_error ();
1869
1870         scan_float:
1871           /* Convert the number.  */
1872           ADDW (L_('\0'));
1873           if (flags & LONGDBL)
1874             {
1875               long double d = __strtold_internal (wp, &tw, flags & GROUP);
1876               if (!(flags & SUPPRESS) && tw != wp)
1877                 *ARG (long double *) = negative ? -d : d;
1878             }
1879           else if (flags & LONG)
1880             {
1881               double d = __strtod_internal (wp, &tw, flags & GROUP);
1882               if (!(flags & SUPPRESS) && tw != wp)
1883                 *ARG (double *) = negative ? -d : d;
1884             }
1885           else
1886             {
1887               float d = __strtof_internal (wp, &tw, flags & GROUP);
1888               if (!(flags & SUPPRESS) && tw != wp)
1889                 *ARG (float *) = negative ? -d : d;
1890             }
1891
1892           if (tw == wp)
1893             conv_error ();
1894
1895           if (!(flags & SUPPRESS))
1896             ++done;
1897           break;
1898
1899         case L_('['):   /* Character class.  */
1900           if (flags & LONG)
1901             STRING_ARG (wstr, wchar_t);
1902           else
1903             STRING_ARG (str, char);
1904
1905           if (*f == L_('^'))
1906             {
1907               ++f;
1908               not_in = 1;
1909             }
1910           else
1911             not_in = 0;
1912
1913           if (width < 0)
1914             /* There is no width given so there is also no limit on the
1915                number of characters we read.  Therefore we set width to
1916                a very high value to make the algorithm easier.  */
1917             width = INT_MAX;
1918
1919 #ifdef COMPILE_WSCANF
1920           /* Find the beginning and the end of the scanlist.  We are not
1921              creating a lookup table since it would have to be too large.
1922              Instead we search each time through the string.  This is not
1923              a constant lookup time but who uses this feature deserves to
1924              be punished.  */
1925           tw = (wchar_t *) f;   /* Marks the beginning.  */
1926
1927           if (*f == ']' || *f == '-')
1928             ++f;
1929
1930           while ((fc = *f++) != L'\0' && fc != L']');
1931
1932           if (fc == L'\0')
1933             conv_error ();
1934           wp = (wchar_t *) f - 1;
1935 #else
1936           /* Fill WP with byte flags indexed by character.
1937              We will use this flag map for matching input characters.  */
1938           if (wpmax < UCHAR_MAX + 1)
1939             {
1940               wpmax = UCHAR_MAX + 1;
1941               wp = (char *) alloca (wpmax);
1942             }
1943           memset (wp, '\0', UCHAR_MAX + 1);
1944
1945           fc = *f;
1946           if (fc == ']' || fc == '-')
1947             {
1948               /* If ] or - appears before any char in the set, it is not
1949                  the terminator or separator, but the first char in the
1950                  set.  */
1951               wp[fc] = 1;
1952               ++f;
1953             }
1954
1955           while ((fc = *f++) != '\0' && fc != ']')
1956             if (fc == '-' && *f != '\0' && *f != ']'
1957                 && (unsigned char) f[-2] <= (unsigned char) *f)
1958               {
1959                 /* Add all characters from the one before the '-'
1960                    up to (but not including) the next format char.  */
1961                 for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc)
1962                   wp[fc] = 1;
1963               }
1964             else
1965               /* Add the character to the flag map.  */
1966               wp[fc] = 1;
1967
1968           if (fc == '\0')
1969             conv_error();
1970 #endif
1971
1972           if (flags & LONG)
1973             {
1974               size_t now = read_in;
1975 #ifdef COMPILE_WSCANF
1976               if (inchar () == WEOF)
1977                 input_error ();
1978
1979               do
1980                 {
1981                   wchar_t *runp;
1982
1983                   /* Test whether it's in the scanlist.  */
1984                   runp = tw;
1985                   while (runp < wp)
1986                     {
1987                       if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
1988                           && runp != tw
1989                           && (unsigned int) runp[-1] <= (unsigned int) runp[1])
1990                         {
1991                           /* Match against all characters in between the
1992                              first and last character of the sequence.  */
1993                           wchar_t wc;
1994
1995                           for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
1996                             if (wc == c)
1997                               break;
1998
1999                           if (wc == runp[1] && !not_in)
2000                             break;
2001                           if (wc == runp[1] && not_in)
2002                             {
2003                               /* The current character is not in the
2004                                  scanset.  */
2005                               ungetwc (c, s);
2006                               goto out;
2007                             }
2008                         }
2009                       else
2010                         {
2011                           if (*runp == runp[1] && !not_in)
2012                             break;
2013                           if (*runp != runp[1] && not_in)
2014                             {
2015                               ungetwc (c ,s);
2016                               goto out;
2017                             }
2018                         }
2019
2020                       ++runp;
2021                     }
2022
2023                   if (!(flags & SUPPRESS))
2024                     {
2025                       *wstr++ = c;
2026
2027                       if ((flags & MALLOC)
2028                           && wstr == (wchar_t *) *strptr + strsize)
2029                         {
2030                           /* Enlarge the buffer.  */
2031                           wstr = (wchar_t *) realloc (*strptr,
2032                                                       (2 * strsize)
2033                                                       * sizeof (wchar_t));
2034                           if (wstr == NULL)
2035                             {
2036                               /* Can't allocate that much.  Last-ditch
2037                                  effort.  */
2038                               wstr = (wchar_t *)
2039                                 realloc (*strptr, (strsize + 1)
2040                                                   * sizeof (wchar_t));
2041                               if (wstr == NULL)
2042                                 {
2043                                   /* We lose.  Oh well.  Terminate the string
2044                                      and stop converting, so at least we don't
2045                                      skip any input.  */
2046                                   ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2047                                   ++done;
2048                                   conv_error ();
2049                                 }
2050                               else
2051                                 {
2052                                   *strptr = (char *) wstr;
2053                                   wstr += strsize;
2054                                   ++strsize;
2055                                 }
2056                             }
2057                           else
2058                             {
2059                               *strptr = (char *) wstr;
2060                               wstr += strsize;
2061                               strsize *= 2;
2062                             }
2063                         }
2064                     }
2065                 }
2066               while (--width > 0 && inchar () != WEOF);
2067             out:
2068 #else
2069               char buf[MB_LEN_MAX];
2070               size_t cnt = 0;
2071               mbstate_t cstate;
2072
2073               if (inchar () == EOF)
2074                 input_error ();
2075
2076               memset (&cstate, '\0', sizeof (cstate));
2077
2078               do
2079                 {
2080                   if (wp[c] == not_in)
2081                     {
2082                       ungetc_not_eof (c, s);
2083                       break;
2084                     }
2085
2086                   /* This is easy.  */
2087                   if (!(flags & SUPPRESS))
2088                     {
2089                       size_t n;
2090
2091                       /* Convert it into a wide character.  */
2092                       n = __mbrtowc (wstr, buf, cnt, &cstate);
2093
2094                       if (n == (size_t) -2)
2095                         {
2096                           /* Possibly correct character, just not enough
2097                              input.  */
2098                           assert (cnt < MB_CUR_MAX);
2099                           continue;
2100                         }
2101
2102                       if (n != cnt)
2103                         encode_error ();
2104
2105                       ++wstr;
2106                       if ((flags & MALLOC)
2107                           && wstr == (wchar_t *) *strptr + strsize)
2108                         {
2109                           /* Enlarge the buffer.  */
2110                           wstr = (wchar_t *) realloc (*strptr,
2111                                                       (2 * strsize
2112                                                        * sizeof (wchar_t)));
2113                           if (wstr == NULL)
2114                             {
2115                               /* Can't allocate that much.  Last-ditch
2116                                  effort.  */
2117                               wstr = (wchar_t *)
2118                                 realloc (*strptr, ((strsize + 1)
2119                                                    * sizeof (wchar_t)));
2120                               if (wstr == NULL)
2121                                 {
2122                                   /* We lose.  Oh well.  Terminate the
2123                                      string and stop converting,
2124                                      so at least we don't skip any input.  */
2125                                   ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2126                                   ++done;
2127                                   conv_error ();
2128                                 }
2129                               else
2130                                 {
2131                                   *strptr = (char *) wstr;
2132                                   wstr += strsize;
2133                                   ++strsize;
2134                                 }
2135                             }
2136                           else
2137                             {
2138                               *strptr = (char *) wstr;
2139                               wstr += strsize;
2140                               strsize *= 2;
2141                             }
2142                         }
2143                     }
2144
2145                   if (--width <= 0)
2146                     break;
2147                 }
2148               while (inchar () != EOF);
2149
2150               if (cnt != 0)
2151                 /* We stopped in the middle of recognizing another
2152                    character.  That's a problem.  */
2153                 encode_error ();
2154 #endif
2155
2156               if (now == read_in)
2157                 /* We haven't succesfully read any character.  */
2158                 conv_error ();
2159
2160               if (!(flags & SUPPRESS))
2161                 {
2162                   *wstr++ = L'\0';
2163
2164                   if ((flags & MALLOC)
2165                       && wstr - (wchar_t *) *strptr != strsize)
2166                     {
2167                       wchar_t *cp = (wchar_t *)
2168                         realloc (*strptr, ((wstr - (wchar_t *) *strptr)
2169                                            * sizeof(wchar_t)));
2170                       if (cp != NULL)
2171                         *strptr = (char *) cp;
2172                     }
2173
2174                   ++done;
2175                 }
2176             }
2177           else
2178             {
2179               size_t now = read_in;
2180
2181               if (inchar () == EOF)
2182                 input_error ();
2183
2184 #ifdef COMPILE_WSCANF
2185
2186               memset (&state, '\0', sizeof (state));
2187
2188               do
2189                 {
2190                   wchar_t *runp;
2191                   size_t n;
2192
2193                   /* Test whether it's in the scanlist.  */
2194                   runp = tw;
2195                   while (runp < wp)
2196                     {
2197                       if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
2198                           && runp != tw
2199                           && (unsigned int) runp[-1] <= (unsigned int) runp[1])
2200                         {
2201                           /* Match against all characters in between the
2202                              first and last character of the sequence.  */
2203                           wchar_t wc;
2204
2205                           for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
2206                             if (wc == c)
2207                               break;
2208
2209                           if (wc == runp[1] && !not_in)
2210                             break;
2211                           if (wc == runp[1] && not_in)
2212                             {
2213                               /* The current character is not in the
2214                                  scanset.  */
2215                               ungetwc (c, s);
2216                               goto out2;
2217                             }
2218                         }
2219                       else
2220                         {
2221                           if (*runp == runp[1] && !not_in)
2222                             break;
2223                           if (*runp != runp[1] && not_in)
2224                             {
2225                               ungetwc (c ,s);
2226                               goto out2;
2227                             }
2228                         }
2229
2230                       ++runp;
2231                     }
2232
2233                   if (!(flags & SUPPRESS))
2234                     {
2235                       if ((flags & MALLOC)
2236                           && str + MB_CUR_MAX >= *strptr + strsize)
2237                         {
2238                           /* Enlarge the buffer.  */
2239                           size_t strleng = str - *strptr;
2240                           char *newstr;
2241
2242                           newstr = (char *) realloc (*strptr, 2 * strsize);
2243                           if (newstr == NULL)
2244                             {
2245                               /* Can't allocate that much.  Last-ditch
2246                                  effort.  */
2247                               newstr = (char *) realloc (*strptr,
2248                                                          strleng + MB_CUR_MAX);
2249                               if (newstr == NULL)
2250                                 {
2251                                   /* We lose.  Oh well.  Terminate the string
2252                                      and stop converting, so at least we don't
2253                                      skip any input.  */
2254                                   ((char *) (*strptr))[strleng] = '\0';
2255                                   ++done;
2256                                   conv_error ();
2257                                 }
2258                               else
2259                                 {
2260                                   *strptr = newstr;
2261                                   str = newstr + strleng;
2262                                   strsize = strleng + MB_CUR_MAX;
2263                                 }
2264                             }
2265                           else
2266                             {
2267                               *strptr = newstr;
2268                               str = newstr + strleng;
2269                               strsize *= 2;
2270                             }
2271                         }
2272                     }
2273
2274                   n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
2275                   if (n == (size_t) -1)
2276                     encode_error ();
2277
2278                   assert (n <= MB_CUR_MAX);
2279                   str += n;
2280                 }
2281               while (--width > 0 && inchar () != WEOF);
2282             out2:
2283 #else
2284               do
2285                 {
2286                   if (wp[c] == not_in)
2287                     {
2288                       ungetc_not_eof (c, s);
2289                       break;
2290                     }
2291
2292                   /* This is easy.  */
2293                   if (!(flags & SUPPRESS))
2294                     {
2295                       *str++ = c;
2296                       if ((flags & MALLOC)
2297                           && (char *) str == *strptr + strsize)
2298                         {
2299                           /* Enlarge the buffer.  */
2300                           str = (char *) realloc (*strptr, 2 * strsize);
2301                           if (str == NULL)
2302                             {
2303                               /* Can't allocate that much.  Last-ditch
2304                                  effort.  */
2305                               str = (char *) realloc (*strptr, strsize + 1);
2306                               if (str == NULL)
2307                                 {
2308                                   /* We lose.  Oh well.  Terminate the
2309                                      string and stop converting,
2310                                      so at least we don't skip any input.  */
2311                                   ((char *) (*strptr))[strsize - 1] = '\0';
2312                                   ++done;
2313                                   conv_error ();
2314                                 }
2315                               else
2316                                 {
2317                                   *strptr = (char *) str;
2318                                   str += strsize;
2319                                   ++strsize;
2320                                 }
2321                             }
2322                           else
2323                             {
2324                               *strptr = (char *) str;
2325                               str += strsize;
2326                               strsize *= 2;
2327                             }
2328                         }
2329                     }
2330                 }
2331               while (--width > 0 && inchar () != EOF);
2332 #endif
2333
2334               if (now == read_in)
2335                 /* We haven't succesfully read any character.  */
2336                 conv_error ();
2337
2338               if (!(flags & SUPPRESS))
2339                 {
2340 #ifdef COMPILE_WSCANF
2341                   /* We have to emit the code to get into the initial
2342                      state.  */
2343                   char buf[MB_LEN_MAX];
2344                   size_t n = __wcrtomb (buf, L'\0', &state);
2345                   if (n > 0 && (flags & MALLOC)
2346                       && str + n >= *strptr + strsize)
2347                     {
2348                       /* Enlarge the buffer.  */
2349                       size_t strleng = str - *strptr;
2350                       char *newstr;
2351
2352                       newstr = (char *) realloc (*strptr, strleng + n + 1);
2353                       if (newstr == NULL)
2354                         {
2355                           /* We lose.  Oh well.  Terminate the string
2356                              and stop converting, so at least we don't
2357                              skip any input.  */
2358                           ((char *) (*strptr))[strleng] = '\0';
2359                           ++done;
2360                           conv_error ();
2361                         }
2362                       else
2363                         {
2364                           *strptr = newstr;
2365                           str = newstr + strleng;
2366                           strsize = strleng + n + 1;
2367                         }
2368                     }
2369
2370                   str = __mempcpy (str, buf, n);
2371 #endif
2372                   *str++ = '\0';
2373
2374                   if ((flags & MALLOC) && str - *strptr != strsize)
2375                     {
2376                       char *cp = (char *) realloc (*strptr, str - *strptr);
2377                       if (cp != NULL)
2378                         *strptr = cp;
2379                     }
2380
2381                   ++done;
2382                 }
2383             }
2384           break;
2385
2386         case L_('p'):   /* Generic pointer.  */
2387           base = 16;
2388           /* A PTR must be the same size as a `long int'.  */
2389           flags &= ~(SHORT|LONGDBL);
2390           if (need_long)
2391             flags |= LONG;
2392           number_signed = 0;
2393           read_pointer = 1;
2394           goto number;
2395
2396         default:
2397           /* If this is an unknown format character punt.  */
2398           conv_error ();
2399         }
2400     }
2401
2402   /* The last thing we saw int the format string was a white space.
2403      Consume the last white spaces.  */
2404   if (skip_space)
2405     {
2406       do
2407         c = inchar ();
2408       while (ISSPACE (c));
2409       ungetc (c, s);
2410     }
2411
2412   /* Unlock stream.  */
2413   UNLOCK_STREAM (s);
2414
2415   return done;
2416 }
2417
2418 #ifdef USE_IN_LIBIO
2419 # ifdef COMPILE_WSCANF
2420 int
2421 __vfwscanf (FILE *s, const wchar_t *format, va_list argptr)
2422 {
2423   return _IO_vfwscanf (s, format, argptr, NULL);
2424 }
2425 # else
2426 int
2427 __vfscanf (FILE *s, const char *format, va_list argptr)
2428 {
2429   return _IO_vfscanf (s, format, argptr, NULL);
2430 }
2431 # endif
2432 #endif
2433
2434 #ifdef COMPILE_WSCANF
2435 weak_alias (__vfwscanf, vfwscanf)
2436 #else
2437 weak_alias (__vfscanf, vfscanf)
2438 #endif