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