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