7b1b3f6cf487a7db7ed844f72d940a10001d6e27
[platform/upstream/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 (s->_vtable_offset == 0 && _IO_fwide (s, 1) != 1)\
91                             return WEOF
92 #  define __strtoll_internal    __wcstoll_internal
93 #  define __strtoull_internal   __wcstoull_internal
94 #  define __strtol_internal     __wcstol_internal
95 #  define __strtoul_internal    __wcstoul_internal
96 #  define __strtold_internal    __wcstold_internal
97 #  define __strtod_internal     __wcstod_internal
98 #  define __strtof_internal     __wcstof_internal
99
100 #  define L_(Str)         L##Str
101 #  define CHAR_T          wchar_t
102 #  define UCHAR_T         unsigned int
103 #  define WINT_T          wint_t
104 #  undef EOF
105 #  define EOF             WEOF
106 # else
107 #  define ungetc(c, s)  ((void) ((int) c == EOF                               \
108                                  || (--read_in,                               \
109                                      _IO_sputbackc (s, (unsigned char) c))))
110 #  define ungetc_not_eof(c, s)  ((void) (--read_in,                           \
111                                          _IO_sputbackc (s, (unsigned char) c)))
112 #  define inchar()      (c == EOF ? EOF                                       \
113                          : ((c = _IO_getc_unlocked (s)),                      \
114                             (void) (c != EOF && ++read_in), c))
115 #  define MEMCPY(d, s, n) memcpy (d, s, n)
116 #  define ISSPACE(Ch)     isspace (Ch)
117 #  define ISDIGIT(Ch)     isdigit (Ch)
118 #  define ISXDIGIT(Ch)    isxdigit (Ch)
119 #  define TOLOWER(Ch)     tolower (Ch)
120 #  define ORIENT          if (_IO_fwide (s, -1) != -1) 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                         str = (char *) realloc (*strptr, strsize * 2);
862                         if (str == NULL)
863                           {
864                             /* Can't allocate that much.  Last-ditch
865                                effort.  */
866                             str = (char *) realloc (*strptr, strsize + 1);
867                             if (str == NULL)
868                               {
869                                 /* We lose.  Oh well.  Terminate the
870                                    string and stop converting,
871                                    so at least we don't skip any input.  */
872                                 ((char *) (*strptr))[strsize - 1] = '\0';
873                                 ++done;
874                                 conv_error ();
875                               }
876                             else
877                               {
878                                 *strptr = (char *) str;
879                                 str += strsize;
880                                 ++strsize;
881                               }
882                           }
883                         else
884                           {
885                             *strptr = (char *) str;
886                             str += strsize;
887                             strsize *= 2;
888                           }
889                       }
890
891                     n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c,
892                                    &state);
893                     if (n == (size_t) -1)
894                       encode_error ();
895
896                     assert (n <= MB_CUR_MAX);
897                     str += n;
898                   }
899 #else
900                   /* This is easy.  */
901                   if (!(flags & SUPPRESS))
902                     {
903                       *str++ = c;
904                       if ((flags & MALLOC)
905                           && (char *) str == *strptr + strsize)
906                         {
907                           /* Enlarge the buffer.  */
908                           str = (char *) realloc (*strptr, 2 * strsize);
909                           if (str == NULL)
910                             {
911                               /* Can't allocate that much.  Last-ditch
912                                  effort.  */
913                               str = (char *) realloc (*strptr, strsize + 1);
914                               if (str == NULL)
915                                 {
916                                   /* We lose.  Oh well.  Terminate the
917                                      string and stop converting,
918                                      so at least we don't skip any input.  */
919                                   ((char *) (*strptr))[strsize - 1] = '\0';
920                                   ++done;
921                                   conv_error ();
922                                 }
923                               else
924                                 {
925                                   *strptr = (char *) str;
926                                   str += strsize;
927                                   ++strsize;
928                                 }
929                             }
930                           else
931                             {
932                               *strptr = (char *) str;
933                               str += strsize;
934                               strsize *= 2;
935                             }
936                         }
937                     }
938 #endif
939                 }
940               while ((width <= 0 || --width > 0) && inchar () != EOF);
941
942               if (!(flags & SUPPRESS))
943                 {
944 #ifdef COMPILE_WSCANF
945                   /* We have to emit the code to get into the initial
946                      state.  */
947                   char buf[MB_LEN_MAX];
948                   size_t n = __wcrtomb (buf, L'\0', &state);
949                   if (n > 0 && (flags & MALLOC)
950                       && str + n >= *strptr + strsize)
951                     {
952                       /* Enlarge the buffer.  */
953                       str = (char *) realloc (*strptr,
954                                               (str + n + 1) - *strptr);
955                       if (str == NULL)
956                         {
957                           /* We lose.  Oh well.  Terminate the string
958                              and stop converting, so at least we don't
959                              skip any input.  */
960                           ((char *) (*strptr))[strsize - 1] = '\0';
961                           ++done;
962                           conv_error ();
963                         }
964                       else
965                         {
966                           *strptr = (char *) str;
967                           str = ((char *) *strptr) + strsize;
968                           strsize = (str + n + 1) - *strptr;
969                         }
970                     }
971
972                   str = __mempcpy (str, buf, n);
973 #endif
974                   *str = '\0';
975
976                   if ((flags & MALLOC) && str - *strptr != strsize)
977                     {
978                       char *cp = (char *) realloc (*strptr, str - *strptr);
979                       if (cp != NULL)
980                         *strptr = cp;
981                     }
982
983                   ++done;
984                 }
985               break;
986             }
987           /* FALLTHROUGH */
988
989         case L_('S'):
990           {
991 #ifndef COMPILE_WSCANF
992             mbstate_t cstate;
993 #endif
994
995             /* Wide character string.  */
996             STRING_ARG (wstr, wchar_t);
997
998             c = inchar ();
999             if (c == EOF)
1000               input_error ();
1001
1002 #ifndef COMPILE_WSCANF
1003             memset (&cstate, '\0', sizeof (cstate));
1004 #endif
1005
1006             do
1007               {
1008                 if (ISSPACE (c))
1009                   {
1010                     ungetc_not_eof (c, s);
1011                     break;
1012                   }
1013
1014 #ifdef COMPILE_WSCANF
1015                 /* This is easy.  */
1016                 if (!(flags & SUPPRESS))
1017                   {
1018                     *wstr++ = c;
1019                     if ((flags & MALLOC)
1020                         && wstr == (wchar_t *) *strptr + strsize)
1021                       {
1022                         /* Enlarge the buffer.  */
1023                         wstr = (wchar_t *) realloc (*strptr,
1024                                                     (2 * strsize)
1025                                                     * sizeof (wchar_t));
1026                         if (wstr == NULL)
1027                           {
1028                             /* Can't allocate that much.  Last-ditch
1029                                effort.  */
1030                             wstr = (wchar_t *) realloc (*strptr,
1031                                                         (strsize
1032                                                          + sizeof (wchar_t)));
1033                             if (wstr == NULL)
1034                               {
1035                                 /* We lose.  Oh well.  Terminate the string
1036                                    and stop converting, so at least we don't
1037                                    skip any input.  */
1038                                 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1039                                 ++done;
1040                                 conv_error ();
1041                               }
1042                             else
1043                               {
1044                                 *strptr = (char *) wstr;
1045                                 wstr += strsize;
1046                                 ++strsize;
1047                               }
1048                           }
1049                         else
1050                           {
1051                             *strptr = (char *) wstr;
1052                             wstr += strsize;
1053                             strsize *= 2;
1054                           }
1055                       }
1056                   }
1057 #else
1058                 {
1059                   char buf[MB_LEN_MAX];
1060                   size_t cnt;
1061
1062                   buf[0] = c;
1063                   cnt = 1;
1064
1065                   while (1)
1066                     {
1067                       size_t n;
1068
1069                       n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
1070                                      buf, cnt, &cstate);
1071
1072                       if (n == (size_t) -2)
1073                         {
1074                           /* Possibly correct character, just not enough
1075                              input.  */
1076                           assert (cnt < MB_CUR_MAX);
1077
1078                           if (inchar () == EOF)
1079                             encode_error ();
1080
1081                           buf[cnt++] = c;
1082                           continue;
1083                         }
1084
1085                       if (n != cnt)
1086                         encode_error ();
1087
1088                       /* We have a match.  */
1089                       break;
1090                     }
1091
1092                   if (!(flags & SUPPRESS) && (flags & MALLOC)
1093                       && wstr == (wchar_t *) *strptr + strsize)
1094                     {
1095                       /* Enlarge the buffer.  */
1096                       wstr = (wchar_t *) realloc (*strptr,
1097                                                   (2 * strsize
1098                                                    * sizeof (wchar_t)));
1099                       if (wstr == NULL)
1100                         {
1101                           /* Can't allocate that much.  Last-ditch effort.  */
1102                           wstr = (wchar_t *) realloc (*strptr,
1103                                                       ((strsize + 1)
1104                                                        * sizeof (wchar_t)));
1105                           if (wstr == NULL)
1106                             {
1107                               /* We lose.  Oh well.  Terminate the
1108                                  string and stop converting, so at
1109                                  least we don't skip any input.  */
1110                               ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1111                               ++done;
1112                               conv_error ();
1113                             }
1114                           else
1115                             {
1116                               *strptr = (char *) wstr;
1117                               wstr += strsize;
1118                               ++strsize;
1119                             }
1120                         }
1121                       else
1122                         {
1123                           *strptr = (char *) wstr;
1124                           wstr += strsize;
1125                           strsize *= 2;
1126                         }
1127                     }
1128                 }
1129 #endif
1130               }
1131             while ((width <= 0 || --width > 0) && inchar () != EOF);
1132
1133             if (!(flags & SUPPRESS))
1134               {
1135                 *wstr++ = L'\0';
1136
1137                 if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
1138                   {
1139                     wchar_t *cp = (wchar_t *) realloc (*strptr,
1140                                                        ((wstr
1141                                                          - (wchar_t *) *strptr)
1142                                                         * sizeof(wchar_t)));
1143                     if (cp != NULL)
1144                       *strptr = (char *) cp;
1145                   }
1146
1147                 ++done;
1148               }
1149           }
1150           break;
1151
1152         case L_('x'):   /* Hexadecimal integer.  */
1153         case L_('X'):   /* Ditto.  */
1154           base = 16;
1155           number_signed = 0;
1156           goto number;
1157
1158         case L_('o'):   /* Octal integer.  */
1159           base = 8;
1160           number_signed = 0;
1161           goto number;
1162
1163         case L_('u'):   /* Unsigned decimal integer.  */
1164           base = 10;
1165           number_signed = 0;
1166           goto number;
1167
1168         case L_('d'):   /* Signed decimal integer.  */
1169           base = 10;
1170           number_signed = 1;
1171           goto number;
1172
1173         case L_('i'):   /* Generic number.  */
1174           base = 0;
1175           number_signed = 1;
1176
1177         number:
1178           c = inchar ();
1179           if (c == EOF)
1180             input_error ();
1181
1182           /* Check for a sign.  */
1183           if (c == L_('-') || c == L_('+'))
1184             {
1185               ADDW (c);
1186               if (width > 0)
1187                 --width;
1188               c = inchar ();
1189             }
1190
1191           /* Look for a leading indication of base.  */
1192           if (width != 0 && c == L_('0'))
1193             {
1194               if (width > 0)
1195                 --width;
1196
1197               ADDW (c);
1198               c = inchar ();
1199
1200               if (width != 0 && TOLOWER (c) == L_('x'))
1201                 {
1202                   if (base == 0)
1203                     base = 16;
1204                   if (base == 16)
1205                     {
1206                       if (width > 0)
1207                         --width;
1208                       c = inchar ();
1209                     }
1210                 }
1211               else if (base == 0)
1212                 base = 8;
1213             }
1214
1215           if (base == 0)
1216             base = 10;
1217
1218           if (base == 10 && (flags & I18N) != 0)
1219             {
1220               int from_level;
1221               int to_level;
1222               int level;
1223 #ifdef COMPILE_WSCANF
1224               const wchar_t *wcdigits[10];
1225 #else
1226               const char *mbdigits[10];
1227 #endif
1228               int n;
1229
1230               from_level = 0;
1231 #ifdef COMPILE_WSCANF
1232               to_level = _NL_CURRENT_WORD (LC_CTYPE,
1233                                            _NL_CTYPE_INDIGITS_WC_LEN) - 1;
1234 #else
1235               to_level = _NL_CURRENT_WORD (LC_CTYPE,
1236                                            _NL_CTYPE_INDIGITS_MB_LEN) - 1;
1237 #endif
1238
1239               /* Read the number into workspace.  */
1240               while (c != EOF && width != 0)
1241                 {
1242                   /* In this round we get the pointer to the digit strings
1243                      and also perform the first round of comparisons.  */
1244                   for (n = 0; n < 10; ++n)
1245                     {
1246                       /* Get the string for the digits with value N.  */
1247 #ifdef COMPILE_WSCANF
1248                       wcdigits[n] = (const wchar_t *)
1249                         _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
1250                       wcdigits[n] += from_level;
1251
1252                       if (c == *wcdigits[n])
1253                         {
1254                           to_level = from_level;
1255                           break;
1256                         }
1257
1258                       /* Advance the pointer to the next string.  */
1259                       ++wcdigits[n];
1260 #else
1261                       const char *cmpp;
1262                       int avail = width > 0 ? width : INT_MAX;
1263
1264                       mbdigits[n] = _NL_CURRENT (LC_CTYPE,
1265                                                  _NL_CTYPE_INDIGITS0_MB + n);
1266
1267                       for (level = 0; level < from_level; level++)
1268                         mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1269
1270                       cmpp = mbdigits[n];
1271                       while ((unsigned char) *cmpp == c && avail > 0)
1272                         {
1273                           if (*++cmpp == '\0')
1274                             break;
1275                           else
1276                             {
1277                               if ((c = inchar ()) == EOF)
1278                                 break;
1279                               --avail;
1280                             }
1281                         }
1282
1283                       if (*cmpp == '\0')
1284                         {
1285                           if (width > 0)
1286                             width = avail;
1287                           to_level = from_level;
1288                           break;
1289                         }
1290
1291                       /* We are pushing all read characters back.  */
1292                       if (cmpp > mbdigits[n])
1293                         {
1294                           ungetc (c, s);
1295                           while (--cmpp > mbdigits[n])
1296                             ungetc_not_eof ((unsigned char) *cmpp, s);
1297                           c = (unsigned char) *cmpp;
1298                         }
1299
1300                       /* Advance the pointer to the next string.  */
1301                       mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1302 #endif
1303                     }
1304
1305                   if (n == 10)
1306                     {
1307                       /* Have not yet found the digit.  */
1308                       for (level = from_level + 1; level <= to_level; ++level)
1309                         {
1310                           /* Search all ten digits of this level.  */
1311                           for (n = 0; n < 10; ++n)
1312                             {
1313 #ifdef COMPILE_WSCANF
1314                               if (c == *wcdigits[n])
1315                                 break;
1316
1317                               /* Advance the pointer to the next string.  */
1318                               ++wcdigits[n];
1319 #else
1320                               const char *cmpp;
1321                               int avail = width > 0 ? width : INT_MAX;
1322
1323                               cmpp = mbdigits[n];
1324                               while ((unsigned char) *cmpp == c && avail > 0)
1325                                 {
1326                                   if (*++cmpp == '\0')
1327                                     break;
1328                                   else
1329                                     {
1330                                       if ((c = inchar ()) == EOF)
1331                                         break;
1332                                       --avail;
1333                                     }
1334                                 }
1335
1336                               if (*cmpp == '\0')
1337                                 {
1338                                   if (width > 0)
1339                                     width = avail;
1340                                   break;
1341                                 }
1342
1343                               /* We are pushing all read characters back.  */
1344                               if (cmpp > mbdigits[n])
1345                                 {
1346                                   ungetc (c, s);
1347                                   while (--cmpp > mbdigits[n])
1348                                     ungetc_not_eof ((unsigned char) *cmpp, s);
1349                                   c = (unsigned char) *cmpp;
1350                                 }
1351
1352                               /* Advance the pointer to the next string.  */
1353                               mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1354 #endif
1355                             }
1356
1357                           if (n < 10)
1358                             {
1359                               /* Found it.  */
1360                               from_level = level;
1361                               to_level = level;
1362                               break;
1363                             }
1364                         }
1365                     }
1366
1367                   if (n < 10)
1368                     c = L_('0') + n;
1369                   else if ((flags & GROUP)
1370 #ifdef COMPILE_WSCANF
1371                            && thousands != L'\0'
1372 #else
1373                            && thousands != NULL
1374 #endif
1375                            )
1376                     {
1377                       /* Try matching against the thousands separator.  */
1378 #ifdef COMPILE_WSCANF
1379                       if (c != thousands)
1380                           break;
1381 #else
1382                       const char *cmpp = thousands;
1383                       int avail = width > 0 ? width : INT_MAX;
1384
1385                       while ((unsigned char) *cmpp == c && avail > 0)
1386                         {
1387                           ADDW (c);
1388                           if (*++cmpp == '\0')
1389                             break;
1390                           else
1391                             {
1392                               if ((c = inchar ()) == EOF)
1393                                 break;
1394                               --avail;
1395                             }
1396                         }
1397
1398                       if (*cmpp != '\0')
1399                         {
1400                           /* We are pushing all read characters back.  */
1401                           if (cmpp > thousands)
1402                             {
1403                               wpsize -= cmpp - thousands;
1404                               ungetc (c, s);
1405                               while (--cmpp > thousands)
1406                                 ungetc_not_eof ((unsigned char) *cmpp, s);
1407                               c = (unsigned char) *cmpp;
1408                             }
1409                           break;
1410                         }
1411
1412                       if (width > 0)
1413                         width = avail;
1414
1415                       /* The last thousands character will be added back by
1416                          the ADDW below.  */
1417                         --wpsize;
1418 #endif
1419                     }
1420                   else
1421                     break;
1422
1423                   ADDW (c);
1424                   if (width > 0)
1425                     --width;
1426
1427                   c = inchar ();
1428                 }
1429             }
1430           else
1431             /* Read the number into workspace.  */
1432             while (c != EOF && width != 0)
1433               {
1434                 if (base == 16)
1435                   {
1436                     if (!ISXDIGIT (c))
1437                       break;
1438                   }
1439                 else if (!ISDIGIT (c) || c - L_('0') >= base)
1440                   {
1441                     if (base == 10 && (flags & GROUP)
1442 #ifdef COMPILE_WSCANF
1443                         && thousands != L'\0'
1444 #else
1445                         && thousands != NULL
1446 #endif
1447                         )
1448                       {
1449                         /* Try matching against the thousands separator.  */
1450 #ifdef COMPILE_WSCANF
1451                         if (c != thousands)
1452                           break;
1453 #else
1454                         const char *cmpp = thousands;
1455                         int avail = width > 0 ? width : INT_MAX;
1456
1457                         while ((unsigned char) *cmpp == c && avail > 0)
1458                           {
1459                             ADDW (c);
1460                             if (*++cmpp == '\0')
1461                               break;
1462                             else
1463                               {
1464                                 if ((c = inchar ()) == EOF)
1465                                   break;
1466                                 --avail;
1467                               }
1468                           }
1469
1470                         if (*cmpp != '\0')
1471                           {
1472                             /* We are pushing all read characters back.  */
1473                             if (cmpp > thousands)
1474                               {
1475                                 wpsize -= cmpp - thousands;
1476                                 ungetc (c, s);
1477                                 while (--cmpp > thousands)
1478                                   ungetc_not_eof ((unsigned char) *cmpp, s);
1479                                 c = (unsigned char) *cmpp;
1480                               }
1481                             break;
1482                           }
1483
1484                         if (width > 0)
1485                           width = avail;
1486
1487                         /* The last thousands character will be added back by
1488                            the ADDW below.  */
1489                         --wpsize;
1490 #endif
1491                       }
1492                     else
1493                       break;
1494                   }
1495                 ADDW (c);
1496                 if (width > 0)
1497                   --width;
1498
1499                 c = inchar ();
1500               }
1501
1502           if (wpsize == 0
1503               || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
1504             {
1505               /* There was no number.  If we are supposed to read a pointer
1506                  we must recognize "(nil)" as well.  */
1507               if (wpsize == 0 && read_pointer && (width < 0 || width >= 0)
1508                   && c == '('
1509                   && TOLOWER (inchar ()) == L_('n')
1510                   && TOLOWER (inchar ()) == L_('i')
1511                   && TOLOWER (inchar ()) == L_('l')
1512                   && inchar () == L_(')'))
1513                 /* We must produce the value of a NULL pointer.  A single
1514                    '0' digit is enough.  */
1515                 ADDW (L_('0'));
1516               else
1517                 {
1518                   /* The last read character is not part of the number
1519                      anymore.  */
1520                   ungetc (c, s);
1521
1522                   conv_error ();
1523                 }
1524             }
1525           else
1526             /* The just read character is not part of the number anymore.  */
1527             ungetc (c, s);
1528
1529           /* Convert the number.  */
1530           ADDW (L_('\0'));
1531           if (need_longlong && (flags & LONGDBL))
1532             {
1533               if (number_signed)
1534                 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
1535               else
1536                 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
1537             }
1538           else
1539             {
1540               if (number_signed)
1541                 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
1542               else
1543                 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
1544             }
1545           if (wp == tw)
1546             conv_error ();
1547
1548           if (!(flags & SUPPRESS))
1549             {
1550               if (! number_signed)
1551                 {
1552                   if (need_longlong && (flags & LONGDBL))
1553                     *ARG (unsigned LONGLONG int *) = num.uq;
1554                   else if (need_long && (flags & LONG))
1555                     *ARG (unsigned long int *) = num.ul;
1556                   else if (flags & SHORT)
1557                     *ARG (unsigned short int *)
1558                       = (unsigned short int) num.ul;
1559                   else if (!(flags & CHAR))
1560                     *ARG (unsigned int *) = (unsigned int) num.ul;
1561                   else
1562                     *ARG (unsigned char *) = (unsigned char) num.ul;
1563                 }
1564               else
1565                 {
1566                   if (need_longlong && (flags & LONGDBL))
1567                     *ARG (LONGLONG int *) = num.q;
1568                   else if (need_long && (flags & LONG))
1569                     *ARG (long int *) = num.l;
1570                   else if (flags & SHORT)
1571                     *ARG (short int *) = (short int) num.l;
1572                   else if (!(flags & CHAR))
1573                     *ARG (int *) = (int) num.l;
1574                   else
1575                     *ARG (signed char *) = (signed char) num.ul;
1576                 }
1577               ++done;
1578             }
1579           break;
1580
1581         case L_('e'):   /* Floating-point numbers.  */
1582         case L_('E'):
1583         case L_('f'):
1584         case L_('F'):
1585         case L_('g'):
1586         case L_('G'):
1587         case L_('a'):
1588         case L_('A'):
1589           c = inchar ();
1590           if (c == EOF)
1591             input_error ();
1592
1593           /* Check for a sign.  */
1594           if (c == L_('-') || c == L_('+'))
1595             {
1596               negative = c == L_('-');
1597               if (width == 0 || inchar () == EOF)
1598                 /* EOF is only an input error before we read any chars.  */
1599                 conv_error ();
1600               if (! ISDIGIT (c))
1601                 {
1602 #ifdef COMPILE_WSCANF
1603                   if (c != decimal)
1604                     {
1605                       /* This is no valid number.  */
1606                       ungetc (c, s);
1607                       conv_error ();
1608                     }
1609 #else
1610                   /* Match against the decimal point.  At this point
1611                      we are taking advantage of the fact that we can
1612                      push more than one character back.  This is
1613                      (almost) never necessary since the decimal point
1614                      string hopefully never contains more than one
1615                      byte.  */
1616                   const char *cmpp = decimal;
1617                   int avail = width > 0 ? width : INT_MAX;
1618
1619                   while ((unsigned char) *cmpp == c && avail > 0)
1620                     if (*++cmpp == '\0')
1621                       break;
1622                     else
1623                       {
1624                         if (inchar () == EOF)
1625                           break;
1626                         --avail;
1627                       }
1628
1629                   if (*cmpp != '\0')
1630                     {
1631                       /* This is no valid number.  */
1632                       while (1)
1633                         {
1634                           ungetc (c, s);
1635                           if (cmpp == decimal)
1636                             break;
1637                           c = (unsigned char) *--cmpp;
1638                         }
1639
1640                       conv_error ();
1641                     }
1642                   if (width > 0)
1643                     width = avail;
1644 #endif
1645                 }
1646               if (width > 0)
1647                 --width;
1648             }
1649           else
1650             negative = 0;
1651
1652           /* Take care for the special arguments "nan" and "inf".  */
1653           if (TOLOWER (c) == L_('n'))
1654             {
1655               /* Maybe "nan".  */
1656               ADDW (c);
1657               if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('a'))
1658                 input_error ();
1659               if (width > 0)
1660                 --width;
1661               ADDW (c);
1662               if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1663                 input_error ();
1664               if (width > 0)
1665                 --width;
1666               ADDW (c);
1667               /* It is "nan".  */
1668               goto scan_float;
1669             }
1670           else if (TOLOWER (c) == L_('i'))
1671             {
1672               /* Maybe "inf" or "infinity".  */
1673               ADDW (c);
1674               if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1675                 input_error ();
1676               if (width > 0)
1677                 --width;
1678               ADDW (c);
1679               if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('f'))
1680                 input_error ();
1681               if (width > 0)
1682                 --width;
1683               ADDW (c);
1684               /* It is as least "inf".  */
1685               if (width != 0 && inchar () != EOF)
1686                 {
1687                   if (TOLOWER (c) == L_('i'))
1688                     {
1689                       if (width > 0)
1690                         --width;
1691                       /* Now we have to read the rest as well.  */
1692                       ADDW (c);
1693                       if (width == 0 || inchar () == EOF
1694                           || TOLOWER (c) != L_('n'))
1695                         input_error ();
1696                       if (width > 0)
1697                         --width;
1698                       ADDW (c);
1699                       if (width == 0 || inchar () == EOF
1700                           || TOLOWER (c) != L_('i'))
1701                         input_error ();
1702                       if (width > 0)
1703                         --width;
1704                       ADDW (c);
1705                       if (width == 0 || inchar () == EOF
1706                           || TOLOWER (c) != L_('t'))
1707                         input_error ();
1708                       if (width > 0)
1709                         --width;
1710                       ADDW (c);
1711                       if (width == 0 || inchar () == EOF
1712                           || TOLOWER (c) != L_('y'))
1713                         input_error ();
1714                       if (width > 0)
1715                         --width;
1716                       ADDW (c);
1717                     }
1718                   else
1719                     /* Never mind.  */
1720                     ungetc (c, s);
1721                 }
1722               goto scan_float;
1723             }
1724
1725           is_hexa = 0;
1726           exp_char = L_('e');
1727           if (width != 0 && c == L_('0'))
1728             {
1729               ADDW (c);
1730               c = inchar ();
1731               if (width > 0)
1732                 --width;
1733               if (width != 0 && TOLOWER (c) == L_('x'))
1734                 {
1735                   /* It is a number in hexadecimal format.  */
1736                   ADDW (c);
1737
1738                   is_hexa = 1;
1739                   exp_char = L_('p');
1740
1741                   /* Grouping is not allowed.  */
1742                   flags &= ~GROUP;
1743                   c = inchar ();
1744                   if (width > 0)
1745                     --width;
1746                 }
1747             }
1748
1749           got_dot = got_e = 0;
1750           do
1751             {
1752               if (ISDIGIT (c))
1753                 ADDW (c);
1754               else if (!got_e && is_hexa && ISXDIGIT (c))
1755                 ADDW (c);
1756               else if (got_e && wp[wpsize - 1] == exp_char
1757                        && (c == L_('-') || c == L_('+')))
1758                 ADDW (c);
1759               else if (wpsize > 0 && !got_e && TOLOWER (c) == exp_char)
1760                 {
1761                   ADDW (exp_char);
1762                   got_e = got_dot = 1;
1763                 }
1764               else
1765                 {
1766 #ifdef COMPILE_WSCANF
1767                   if (! got_dot && c == decimal)
1768                     {
1769                       ADDW (c);
1770                       got_dot = 1;
1771                     }
1772                   else if (thousands != L'\0' && ! got_dot && c == thousands)
1773                     ADDW (c);
1774                   else
1775                     {
1776                       /* The last read character is not part of the number
1777                          anymore.  */
1778                       ungetc (c, s);
1779                       break;
1780                     }
1781 #else
1782                   const char *cmpp = decimal;
1783                   int avail = width > 0 ? width : INT_MAX;
1784
1785                   if (! got_dot)
1786                     {
1787                       while ((unsigned char) *cmpp == c && avail > 0)
1788                         if (*++cmpp == '\0')
1789                           break;
1790                         else
1791                           {
1792                             if (inchar () == EOF)
1793                               break;
1794                             --avail;
1795                           }
1796                     }
1797
1798                   if (*cmpp == '\0')
1799                     {
1800                       /* Add all the characters.  */
1801                       for (cmpp = decimal; *cmpp != '\0'; ++cmpp)
1802                         ADDW ((unsigned char) *cmpp);
1803                       if (width > 0)
1804                         width = avail;
1805                       got_dot = 1;
1806                     }
1807                   else
1808                     {
1809                       /* Figure out whether it is a thousands separator.
1810                          There is one problem: we possibly read more than
1811                          one character.  We cannot push them back but since
1812                          we know that parts of the `decimal' string matched,
1813                          we can compare against it.  */
1814                       const char *cmp2p = thousands;
1815
1816                       if (thousands != NULL && ! got_dot)
1817                         {
1818                           while (cmp2p < cmpp
1819                                  && *cmp2p == decimal[cmp2p - thousands])
1820                             ++cmp2p;
1821                           if (cmp2p == cmpp)
1822                             {
1823                               while ((unsigned char) *cmp2p == c && avail > 0)
1824                                 if (*++cmp2p == '\0')
1825                                   break;
1826                                 else
1827                                   {
1828                                     if (inchar () == EOF)
1829                                       break;
1830                                     --avail;
1831                                   }
1832                             }
1833                         }
1834
1835                       if (cmp2p != NULL && *cmp2p == '\0')
1836                         {
1837                           /* Add all the characters.  */
1838                           for (cmpp = thousands; *cmpp != '\0'; ++cmpp)
1839                             ADDW ((unsigned char) *cmpp);
1840                           if (width > 0)
1841                             width = avail;
1842                         }
1843                       else
1844                         {
1845                           /* The last read character is not part of the number
1846                              anymore.  */
1847                           ungetc (c, s);
1848                           break;
1849                         }
1850                     }
1851 #endif
1852                 }
1853               if (width > 0)
1854                 --width;
1855             }
1856           while (width != 0 && inchar () != EOF);
1857
1858           /* Have we read any character?  If we try to read a number
1859              in hexadecimal notation and we have read only the `0x'
1860              prefix or no exponent this is an error.  */
1861           if (wpsize == 0 || (is_hexa && (wpsize == 2 || ! got_e)))
1862             conv_error ();
1863
1864         scan_float:
1865           /* Convert the number.  */
1866           ADDW (L_('\0'));
1867           if (flags & LONGDBL)
1868             {
1869               long double d = __strtold_internal (wp, &tw, flags & GROUP);
1870               if (!(flags & SUPPRESS) && tw != wp)
1871                 *ARG (long double *) = negative ? -d : d;
1872             }
1873           else if (flags & LONG)
1874             {
1875               double d = __strtod_internal (wp, &tw, flags & GROUP);
1876               if (!(flags & SUPPRESS) && tw != wp)
1877                 *ARG (double *) = negative ? -d : d;
1878             }
1879           else
1880             {
1881               float d = __strtof_internal (wp, &tw, flags & GROUP);
1882               if (!(flags & SUPPRESS) && tw != wp)
1883                 *ARG (float *) = negative ? -d : d;
1884             }
1885
1886           if (tw == wp)
1887             conv_error ();
1888
1889           if (!(flags & SUPPRESS))
1890             ++done;
1891           break;
1892
1893         case L_('['):   /* Character class.  */
1894           if (flags & LONG)
1895             STRING_ARG (wstr, wchar_t);
1896           else
1897             STRING_ARG (str, char);
1898
1899           if (*f == L_('^'))
1900             {
1901               ++f;
1902               not_in = 1;
1903             }
1904           else
1905             not_in = 0;
1906
1907           if (width < 0)
1908             /* There is no width given so there is also no limit on the
1909                number of characters we read.  Therefore we set width to
1910                a very high value to make the algorithm easier.  */
1911             width = INT_MAX;
1912
1913 #ifdef COMPILE_WSCANF
1914           /* Find the beginning and the end of the scanlist.  We are not
1915              creating a lookup table since it would have to be too large.
1916              Instead we search each time through the string.  This is not
1917              a constant lookup time but who uses this feature deserves to
1918              be punished.  */
1919           tw = (wchar_t *) f;   /* Marks the beginning.  */
1920
1921           if (*f == ']' || *f == '-')
1922             ++f;
1923
1924           while ((fc = *f++) != L'\0' && fc != L']');
1925
1926           if (fc == L'\0')
1927             conv_error ();
1928           wp = (wchar_t *) f - 1;
1929 #else
1930           /* Fill WP with byte flags indexed by character.
1931              We will use this flag map for matching input characters.  */
1932           if (wpmax < UCHAR_MAX + 1)
1933             {
1934               wpmax = UCHAR_MAX + 1;
1935               wp = (char *) alloca (wpmax);
1936             }
1937           memset (wp, '\0', UCHAR_MAX + 1);
1938
1939           fc = *f;
1940           if (fc == ']' || fc == '-')
1941             {
1942               /* If ] or - appears before any char in the set, it is not
1943                  the terminator or separator, but the first char in the
1944                  set.  */
1945               wp[fc] = 1;
1946               ++f;
1947             }
1948
1949           while ((fc = *f++) != '\0' && fc != ']')
1950             if (fc == '-' && *f != '\0' && *f != ']'
1951                 && (unsigned char) f[-2] <= (unsigned char) *f)
1952               {
1953                 /* Add all characters from the one before the '-'
1954                    up to (but not including) the next format char.  */
1955                 for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc)
1956                   wp[fc] = 1;
1957               }
1958             else
1959               /* Add the character to the flag map.  */
1960               wp[fc] = 1;
1961
1962           if (fc == '\0')
1963             conv_error();
1964 #endif
1965
1966           if (flags & LONG)
1967             {
1968               size_t now = read_in;
1969 #ifdef COMPILE_WSCANF
1970               do
1971                 {
1972                   wchar_t *runp;
1973
1974                   if (inchar () == WEOF)
1975                     break;
1976
1977                   /* Test whether it's in the scanlist.  */
1978                   runp = tw;
1979                   while (runp < wp)
1980                     {
1981                       if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
1982                           && runp != tw
1983                           && (unsigned int) runp[-1] <= (unsigned int) runp[1])
1984                         {
1985                           /* Match against all characters in between the
1986                              first and last character of the sequence.  */
1987                           wchar_t wc;
1988
1989                           for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
1990                             if (wc == c)
1991                               break;
1992
1993                           if (wc == runp[1] && !not_in)
1994                             break;
1995                           if (wc == runp[1] && not_in)
1996                             {
1997                               /* The current character is not in the
1998                                  scanset.  */
1999                               ungetwc (c, s);
2000                               goto out;
2001                             }
2002                         }
2003                       else
2004                         {
2005                           if (*runp == runp[1] && !not_in)
2006                             break;
2007                           if (*runp != runp[1] && not_in)
2008                             {
2009                               ungetwc (c ,s);
2010                               goto out;
2011                             }
2012                         }
2013
2014                       ++runp;
2015                     }
2016
2017                   if (!(flags & SUPPRESS))
2018                     {
2019                       *wstr++ = c;
2020
2021                       if ((flags & MALLOC)
2022                           && wstr == (wchar_t *) *strptr + strsize)
2023                         {
2024                           /* Enlarge the buffer.  */
2025                           wstr = (wchar_t *) realloc (*strptr,
2026                                                       (2 * strsize)
2027                                                       * sizeof (wchar_t));
2028                           if (wstr == NULL)
2029                             {
2030                               /* Can't allocate that much.  Last-ditch
2031                                  effort.  */
2032                               wstr = (wchar_t *)
2033                                 realloc (*strptr, (strsize
2034                                                    + sizeof (wchar_t)));
2035                               if (wstr == NULL)
2036                                 {
2037                                   /* We lose.  Oh well.  Terminate the string
2038                                      and stop converting, so at least we don't
2039                                      skip any input.  */
2040                                   ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2041                                   ++done;
2042                                   conv_error ();
2043                                 }
2044                               else
2045                                 {
2046                                   *strptr = (char *) wstr;
2047                                   wstr += strsize;
2048                                   ++strsize;
2049                                 }
2050                             }
2051                           else
2052                             {
2053                               *strptr = (char *) wstr;
2054                               wstr += strsize;
2055                               strsize *= 2;
2056                             }
2057                         }
2058                     }
2059                 }
2060               while (--width > 0);
2061             out:
2062 #else
2063               char buf[MB_LEN_MAX];
2064               size_t cnt = 0;
2065               mbstate_t cstate;
2066
2067               memset (&cstate, '\0', sizeof (cstate));
2068
2069               do
2070                 {
2071                 again:
2072                   if (inchar () == EOF)
2073                     break;
2074
2075                   if (wp[c] == not_in)
2076                     {
2077                       ungetc_not_eof (c, s);
2078                       break;
2079                     }
2080
2081                   /* This is easy.  */
2082                   if (!(flags & SUPPRESS))
2083                     {
2084                       size_t n;
2085
2086                       /* Convert it into a wide character.  */
2087                       n = __mbrtowc (wstr, buf, cnt, &cstate);
2088
2089                       if (n == (size_t) -2)
2090                         {
2091                           /* Possibly correct character, just not enough
2092                              input.  */
2093                           assert (cnt < MB_CUR_MAX);
2094                           goto again;
2095                         }
2096
2097                       if (n != cnt)
2098                         encode_error ();
2099
2100                       ++wstr;
2101                       if ((flags & MALLOC)
2102                           && wstr == (wchar_t *) *strptr + strsize)
2103                         {
2104                           /* Enlarge the buffer.  */
2105                           wstr = (wchar_t *) realloc (*strptr,
2106                                                       (2 * strsize
2107                                                        * sizeof (wchar_t)));
2108                           if (wstr == NULL)
2109                             {
2110                               /* Can't allocate that much.  Last-ditch
2111                                  effort.  */
2112                               wstr = (wchar_t *)
2113                                 realloc (*strptr, ((strsize + 1)
2114                                                    * sizeof (wchar_t)));
2115                               if (wstr == NULL)
2116                                 {
2117                                   /* We lose.  Oh well.  Terminate the
2118                                      string and stop converting,
2119                                      so at least we don't skip any input.  */
2120                                   ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2121                                   ++done;
2122                                   conv_error ();
2123                                 }
2124                               else
2125                                 {
2126                                   *strptr = (char *) wstr;
2127                                   wstr += strsize;
2128                                   ++strsize;
2129                                 }
2130                             }
2131                           else
2132                             {
2133                               *strptr = (char *) wstr;
2134                               wstr += strsize;
2135                               strsize *= 2;
2136                             }
2137                         }
2138                     }
2139                 }
2140               while (--width > 0);
2141
2142               if (cnt != 0)
2143                 /* We stopped in the middle of recognizing another
2144                    character.  That's a problem.  */
2145                 encode_error ();
2146 #endif
2147
2148               if (now == read_in)
2149                 /* We haven't succesfully read any character.  */
2150                 conv_error ();
2151
2152               if (!(flags & SUPPRESS))
2153                 {
2154                   *wstr++ = L'\0';
2155
2156                   if ((flags & MALLOC)
2157                       && wstr - (wchar_t *) *strptr != strsize)
2158                     {
2159                       wchar_t *cp = (wchar_t *)
2160                         realloc (*strptr, ((wstr - (wchar_t *) *strptr)
2161                                            * sizeof(wchar_t)));
2162                       if (cp != NULL)
2163                         *strptr = (char *) cp;
2164                     }
2165
2166                   ++done;
2167                 }
2168             }
2169           else
2170             {
2171               size_t now = read_in;
2172 #ifdef COMPILE_WSCANF
2173
2174               memset (&state, '\0', sizeof (state));
2175
2176               do
2177                 {
2178                   wchar_t *runp;
2179                   size_t n;
2180
2181                   if (inchar () == WEOF)
2182                     break;
2183
2184                   /* Test whether it's in the scanlist.  */
2185                   runp = tw;
2186                   while (runp < wp)
2187                     {
2188                       if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
2189                           && runp != tw
2190                           && (unsigned int) runp[-1] <= (unsigned int) runp[1])
2191                         {
2192                           /* Match against all characters in between the
2193                              first and last character of the sequence.  */
2194                           wchar_t wc;
2195
2196                           for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
2197                             if (wc == c)
2198                               break;
2199
2200                           if (wc == runp[1] && !not_in)
2201                             break;
2202                           if (wc == runp[1] && not_in)
2203                             {
2204                               /* The current character is not in the
2205                                  scanset.  */
2206                               ungetwc (c, s);
2207                               goto out2;
2208                             }
2209                         }
2210                       else
2211                         {
2212                           if (*runp == runp[1] && !not_in)
2213                             break;
2214                           if (*runp != runp[1] && not_in)
2215                             {
2216                               ungetwc (c ,s);
2217                               goto out2;
2218                             }
2219                         }
2220
2221                       ++runp;
2222                     }
2223
2224                   if (!(flags & SUPPRESS))
2225                     {
2226                       if ((flags & MALLOC)
2227                           && str + MB_CUR_MAX >= *strptr + strsize)
2228                         {
2229                           /* Enlarge the buffer.  */
2230                           str = (char *) realloc (*strptr, 2 * strsize);
2231                           if (str == NULL)
2232                             {
2233                               /* Can't allocate that much.  Last-ditch
2234                                  effort.  */
2235                               str = (char *) realloc (*strptr, strsize + 1);
2236                               if (str == NULL)
2237                                 {
2238                                   /* We lose.  Oh well.  Terminate the string
2239                                      and stop converting, so at least we don't
2240                                      skip any input.  */
2241                                   (*strptr)[strsize - 1] = '\0';
2242                                   ++done;
2243                                   conv_error ();
2244                                 }
2245                               else
2246                                 {
2247                                   *strptr = str;
2248                                   str += strsize;
2249                                   ++strsize;
2250                                 }
2251                             }
2252                           else
2253                             {
2254                               *strptr = str;
2255                               str += strsize;
2256                               strsize *= 2;
2257                             }
2258                         }
2259                     }
2260
2261                   n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
2262                   if (n == (size_t) -1)
2263                     encode_error ();
2264
2265                   assert (n <= MB_CUR_MAX);
2266                   str += n;
2267                 }
2268               while (--width > 0);
2269             out2:
2270 #else
2271               do
2272                 {
2273                   if (inchar () == EOF)
2274                     break;
2275
2276                   if (wp[c] == not_in)
2277                     {
2278                       ungetc_not_eof (c, s);
2279                       break;
2280                     }
2281
2282                   /* This is easy.  */
2283                   if (!(flags & SUPPRESS))
2284                     {
2285                       *str++ = c;
2286                       if ((flags & MALLOC)
2287                           && (char *) str == *strptr + strsize)
2288                         {
2289                           /* Enlarge the buffer.  */
2290                           str = (char *) realloc (*strptr, 2 * strsize);
2291                           if (str == NULL)
2292                             {
2293                               /* Can't allocate that much.  Last-ditch
2294                                  effort.  */
2295                               str = (char *) realloc (*strptr, strsize + 1);
2296                               if (str == NULL)
2297                                 {
2298                                   /* We lose.  Oh well.  Terminate the
2299                                      string and stop converting,
2300                                      so at least we don't skip any input.  */
2301                                   ((char *) (*strptr))[strsize - 1] = '\0';
2302                                   ++done;
2303                                   conv_error ();
2304                                 }
2305                               else
2306                                 {
2307                                   *strptr = (char *) str;
2308                                   str += strsize;
2309                                   ++strsize;
2310                                 }
2311                             }
2312                           else
2313                             {
2314                               *strptr = (char *) str;
2315                               str += strsize;
2316                               strsize *= 2;
2317                             }
2318                         }
2319                     }
2320                 }
2321               while (--width > 0);
2322 #endif
2323
2324               if (now == read_in)
2325                 /* We haven't succesfully read any character.  */
2326                 conv_error ();
2327
2328               if (!(flags & SUPPRESS))
2329                 {
2330 #ifdef COMPILE_WSCANF
2331                   /* We have to emit the code to get into the initial
2332                      state.  */
2333                   char buf[MB_LEN_MAX];
2334                   size_t n = __wcrtomb (buf, L'\0', &state);
2335                   if (n > 0 && (flags & MALLOC)
2336                       && str + n >= *strptr + strsize)
2337                     {
2338                       /* Enlarge the buffer.  */
2339                       str = (char *) realloc (*strptr,
2340                                               (str + n + 1) - *strptr);
2341                       if (str == NULL)
2342                         {
2343                           /* We lose.  Oh well.  Terminate the string
2344                              and stop converting, so at least we don't
2345                              skip any input.  */
2346                           ((char *) (*strptr))[strsize - 1] = '\0';
2347                           ++done;
2348                           conv_error ();
2349                         }
2350                       else
2351                         {
2352                           *strptr = (char *) str;
2353                           str = ((char *) *strptr) + strsize;
2354                           strsize = (str + n + 1) - *strptr;
2355                         }
2356                     }
2357
2358                   str = __mempcpy (str, buf, n);
2359 #endif
2360                   *str = '\0';
2361
2362                   if ((flags & MALLOC) && str - *strptr != strsize)
2363                     {
2364                       char *cp = (char *) realloc (*strptr, str - *strptr);
2365                       if (cp != NULL)
2366                         *strptr = cp;
2367                     }
2368
2369                   ++done;
2370                 }
2371             }
2372           break;
2373
2374         case L_('p'):   /* Generic pointer.  */
2375           base = 16;
2376           /* A PTR must be the same size as a `long int'.  */
2377           flags &= ~(SHORT|LONGDBL);
2378           if (need_long)
2379             flags |= LONG;
2380           number_signed = 0;
2381           read_pointer = 1;
2382           goto number;
2383
2384         default:
2385           /* If this is an unknown format character punt.  */
2386           conv_error ();
2387         }
2388     }
2389
2390   /* The last thing we saw int the format string was a white space.
2391      Consume the last white spaces.  */
2392   if (skip_space)
2393     {
2394       do
2395         c = inchar ();
2396       while (ISSPACE (c));
2397       ungetc (c, s);
2398     }
2399
2400   /* Unlock stream.  */
2401   UNLOCK_STREAM (s);
2402
2403   return done;
2404 }
2405
2406 #ifdef USE_IN_LIBIO
2407 # ifdef COMPILE_WSCANF
2408 int
2409 __vfwscanf (FILE *s, const wchar_t *format, va_list argptr)
2410 {
2411   return _IO_vfwscanf (s, format, argptr, NULL);
2412 }
2413 # else
2414 int
2415 __vfscanf (FILE *s, const char *format, va_list argptr)
2416 {
2417   return _IO_vfscanf (s, format, argptr, NULL);
2418 }
2419 # endif
2420 #endif
2421
2422 #ifdef COMPILE_WSCANF
2423 weak_alias (__vfwscanf, vfwscanf)
2424 #else
2425 weak_alias (__vfscanf, vfscanf)
2426 #endif