Recognize nan and inf in floating-point formats.
[kopensolaris-gnu/glibc.git] / stdio-common / vfscanf.c
1 /* Copyright (C) 1991,92,93,94,95,96,97,98 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with the GNU C Library; see the file COPYING.LIB.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18
19 #include <errno.h>
20 #include <limits.h>
21 #include <ctype.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <wctype.h>
27 #include <bits/libc-lock.h>
28 #include <locale/localeinfo.h>
29
30 #ifdef  __GNUC__
31 # define HAVE_LONGLONG
32 # define LONGLONG       long long
33 #else
34 # define LONGLONG       long
35 #endif
36
37 /* Those are flags in the conversion format. */
38 # define LONG           0x001   /* l: long or double */
39 # define LONGDBL        0x002   /* L: long long or long double */
40 # define SHORT          0x004   /* h: short */
41 # define SUPPRESS       0x008   /* *: suppress assignment */
42 # define POINTER        0x010   /* weird %p pointer (`fake hex') */
43 # define NOSKIP         0x020   /* do not skip blanks */
44 # define WIDTH          0x040   /* width was given */
45 # define GROUP          0x080   /* ': group numbers */
46 # define MALLOC         0x100   /* a: malloc strings */
47 # define CHAR           0x200   /* hh: char */
48
49 # define TYPEMOD        (LONG|LONGDBL|SHORT|CHAR)
50
51
52 #ifdef USE_IN_LIBIO
53 # include <libioP.h>
54 # include <libio.h>
55
56 # undef va_list
57 # define va_list        _IO_va_list
58 # define ungetc(c, s)   ((void) ((int) c != EOF && --read_in),                \
59                          _IO_ungetc (c, s))
60 # define inchar()       (c == EOF ? EOF                                       \
61                          : ((c = _IO_getc_unlocked (s)),                      \
62                             (void) (c != EOF && ++read_in), c))
63 # define encode_error() do {                                                  \
64                           if (errp != NULL) *errp |= 4;                       \
65                           _IO_funlockfile (s);                                \
66                           __set_errno (EILSEQ);                               \
67                           return done;                                        \
68                         } while (0)
69 # define conv_error()   do {                                                  \
70                           if (errp != NULL) *errp |= 2;                       \
71                           _IO_funlockfile (s);                                \
72                           return done;                                        \
73                         } while (0)
74 # define input_error()  do {                                                  \
75                           _IO_funlockfile (s);                                \
76                           if (errp != NULL) *errp |= 1;                       \
77                           return done ?: EOF;                                 \
78                         } while (0)
79 # define memory_error() do {                                                  \
80                           _IO_funlockfile (s);                                \
81                           __set_errno (ENOMEM);                               \
82                           return EOF;                                         \
83                         } while (0)
84 # define ARGCHECK(s, format)                                                  \
85   do                                                                          \
86     {                                                                         \
87       /* Check file argument for consistence.  */                             \
88       CHECK_FILE (s, EOF);                                                    \
89       if (s->_flags & _IO_NO_READS)                                           \
90         {                                                                     \
91           __set_errno (EBADF);                                                \
92           return EOF;                                                         \
93         }                                                                     \
94       else if (format == NULL)                                                \
95         {                                                                     \
96           MAYBE_SET_EINVAL;                                                   \
97           return EOF;                                                         \
98         }                                                                     \
99     } while (0)
100 # define LOCK_STREAM(S)                                                       \
101   __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S));    \
102   _IO_flockfile (S)
103 # define UNLOCK_STREAM __libc_cleanup_region_end (1)
104 #else
105 # define ungetc(c, s)   ((void) (c != EOF && --read_in), ungetc (c, s))
106 # define inchar()       (c == EOF ? EOF                                       \
107                          : ((c = getc (s)), (void) (c != EOF && ++read_in), c))
108 # define encode_error() do {                                                  \
109                           funlockfile (s);                                    \
110                           __set_errno (EILSEQ);                               \
111                           return done;                                        \
112                         } while (0)
113 # define conv_error()   do {                                                  \
114                           funlockfile (s);                                    \
115                           return done;                                        \
116                         } while (0)
117 # define input_error()  do {                                                  \
118                           funlockfile (s);                                    \
119                           return done ?: EOF;                                 \
120                         } while (0)
121 # define memory_error() do {                                                  \
122                           funlockfile (s);                                    \
123                           __set_errno (ENOMEM);                               \
124                           return EOF;                                         \
125                         } while (0)
126 # define ARGCHECK(s, format)                                                  \
127   do                                                                          \
128     {                                                                         \
129       /* Check file argument for consistence.  */                             \
130       if (!__validfp (s) || !s->__mode.__read)                                \
131         {                                                                     \
132           __set_errno (EBADF);                                                \
133           return EOF;                                                         \
134         }                                                                     \
135       else if (format == NULL)                                                \
136         {                                                                     \
137           __set_errno (EINVAL);                                               \
138           return EOF;                                                         \
139         }                                                                     \
140     } while (0)
141 #if 1
142       /* XXX For now !!! */
143 # define flockfile(S) /* nothing */
144 # define funlockfile(S) /* nothing */
145 # define LOCK_STREAM(S)
146 # define UNLOCK_STREAM
147 #else
148 # define LOCK_STREAM(S)                                                       \
149   __libc_cleanup_region_start (&__funlockfile, (S));                          \
150   __flockfile (S)
151 # define UNLOCK_STREAM __libc_cleanup_region_end (1)
152 #endif
153 #endif
154
155
156 /* Read formatted input from S according to the format string
157    FORMAT, using the argument list in ARG.
158    Return the number of assignments made, or -1 for an input error.  */
159 #ifdef USE_IN_LIBIO
160 int
161 _IO_vfscanf (s, format, argptr, errp)
162      _IO_FILE *s;
163      const char *format;
164      _IO_va_list argptr;
165      int *errp;
166 #else
167 int
168 __vfscanf (FILE *s, const char *format, va_list argptr)
169 #endif
170 {
171   va_list arg;
172   register const char *f = format;
173   register unsigned char fc;    /* Current character of the format.  */
174   register size_t done = 0;     /* Assignments done.  */
175   register size_t read_in = 0;  /* Chars read in.  */
176   register int c = 0;           /* Last char read.  */
177   register int width;           /* Maximum field width.  */
178   register int flags;           /* Modifiers for current format element.  */
179
180   /* Status for reading F-P nums.  */
181   char got_dot, got_e, negative;
182   /* If a [...] is a [^...].  */
183   char not_in;
184 #define exp_char not_in
185   /* Base for integral numbers.  */
186   int base;
187   /* Signedness for integral numbers.  */
188   int number_signed;
189 #define is_hexa number_signed
190   /* Decimal point character.  */
191   wchar_t decimal;
192   /* The thousands character of the current locale.  */
193   wchar_t thousands;
194   /* Integral holding variables.  */
195   union
196     {
197       long long int q;
198       unsigned long long int uq;
199       long int l;
200       unsigned long int ul;
201     } num;
202   /* Character-buffer pointer.  */
203   char *str = NULL;
204   wchar_t *wstr = NULL;
205   char **strptr = NULL;
206   size_t strsize = 0;
207   /* We must not react on white spaces immediately because they can
208      possibly be matched even if in the input stream no character is
209      available anymore.  */
210   int skip_space = 0;
211   /* Workspace.  */
212   char *tw;                     /* Temporary pointer.  */
213   char *wp = NULL;              /* Workspace.  */
214   size_t wpmax = 0;             /* Maximal size of workspace.  */
215   size_t wpsize;                /* Currently used bytes in workspace.  */
216 #define ADDW(Ch)                                                            \
217   do                                                                        \
218     {                                                                       \
219       if (wpsize == wpmax)                                                  \
220         {                                                                   \
221           char *old = wp;                                                   \
222           wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax;            \
223           wp = (char *) alloca (wpmax);                                     \
224           if (old != NULL)                                                  \
225             memcpy (wp, old, wpsize);                                       \
226         }                                                                   \
227       wp[wpsize++] = (Ch);                                                  \
228     }                                                                       \
229   while (0)
230
231 #ifdef __va_copy
232   __va_copy (arg, argptr);
233 #else
234   arg = (va_list) argptr;
235 #endif
236
237   ARGCHECK (s, format);
238
239   /* Figure out the decimal point character.  */
240   if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
241               strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
242     decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
243   /* Figure out the thousands separator character.  */
244   if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
245               strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
246     thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
247
248   /* Lock the stream.  */
249   LOCK_STREAM (s);
250
251   /* Run through the format string.  */
252   while (*f != '\0')
253     {
254       unsigned int argpos;
255       /* Extract the next argument, which is of type TYPE.
256          For a %N$... spec, this is the Nth argument from the beginning;
257          otherwise it is the next argument after the state now in ARG.  */
258 #ifdef __va_copy
259 # define ARG(type)      (argpos == 0 ? va_arg (arg, type) :                   \
260                          ({ unsigned int pos = argpos;                        \
261                             va_list arg;                                      \
262                             __va_copy (arg, argptr);                          \
263                             while (--pos > 0)                                 \
264                               (void) va_arg (arg, void *);                    \
265                             va_arg (arg, type);                               \
266                           }))
267 #else
268 # if 0
269       /* XXX Possible optimization.  */
270 #  define ARG(type)     (argpos == 0 ? va_arg (arg, type) :                   \
271                          ({ va_list arg = (va_list) argptr;                   \
272                             arg = (va_list) ((char *) arg                     \
273                                              + (argpos - 1)                   \
274                                              * __va_rounded_size (void *));   \
275                             va_arg (arg, type);                               \
276                          }))
277 # else
278 #  define ARG(type)     (argpos == 0 ? va_arg (arg, type) :                   \
279                          ({ unsigned int pos = argpos;                        \
280                             va_list arg = (va_list) argptr;                   \
281                             while (--pos > 0)                                 \
282                               (void) va_arg (arg, void *);                    \
283                             va_arg (arg, type);                               \
284                           }))
285 # endif
286 #endif
287
288       if (!isascii (*f))
289         {
290           /* Non-ASCII, may be a multibyte.  */
291           int len = mblen (f, strlen (f));
292           if (len > 0)
293             {
294               do
295                 {
296                   c = inchar ();
297                   if (c == EOF)
298                     input_error ();
299                   else if (c != *f++)
300                     {
301                       ungetc (c, s);
302                       conv_error ();
303                     }
304                 }
305               while (--len > 0);
306               continue;
307             }
308         }
309
310       fc = *f++;
311       if (fc != '%')
312         {
313           /* Remember to skip spaces.  */
314           if (isspace (fc))
315             {
316               skip_space = 1;
317               continue;
318             }
319
320           /* Read a character.  */
321           c = inchar ();
322
323           /* Characters other than format specs must just match.  */
324           if (c == EOF)
325             input_error ();
326
327           /* We saw white space char as the last character in the format
328              string.  Now it's time to skip all leading white space.  */
329           if (skip_space)
330             {
331               while (isspace (c))
332                 if (inchar () == EOF && errno == EINTR)
333                   conv_error ();
334               skip_space = 0;
335             }
336
337           if (c != fc)
338             {
339               ungetc (c, s);
340               conv_error ();
341             }
342
343           continue;
344         }
345
346       /* This is the start of the conversion string. */
347       flags = 0;
348
349       /* Initialize state of modifiers.  */
350       argpos = 0;
351
352       /* Prepare temporary buffer.  */
353       wpsize = 0;
354
355       /* Check for a positional parameter specification.  */
356       if (isdigit (*f))
357         {
358           argpos = *f++ - '0';
359           while (isdigit (*f))
360             argpos = argpos * 10 + (*f++ - '0');
361           if (*f == '$')
362             ++f;
363           else
364             {
365               /* Oops; that was actually the field width.  */
366               width = argpos;
367               flags |= WIDTH;
368               argpos = 0;
369               goto got_width;
370             }
371         }
372
373       /* Check for the assignment-suppressing and the number grouping flag.  */
374       while (*f == '*' || *f == '\'')
375         switch (*f++)
376           {
377           case '*':
378             flags |= SUPPRESS;
379             break;
380           case '\'':
381             flags |= GROUP;
382             break;
383           }
384
385       /* We have seen width. */
386       if (isdigit (*f))
387         flags |= WIDTH;
388
389       /* Find the maximum field width.  */
390       width = 0;
391       while (isdigit (*f))
392         {
393           width *= 10;
394           width += *f++ - '0';
395         }
396     got_width:
397       if (width == 0)
398         width = -1;
399
400       /* Check for type modifiers.  */
401       while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q')
402         switch (*f++)
403           {
404           case 'h':
405             /* int's are short int's.  */
406             if (flags & (LONG|LONGDBL|CHAR))
407               /* Signal illegal format element.  */
408               conv_error ();
409             if (flags & SHORT)
410               {
411                 flags &= ~SHORT;
412                 flags |= CHAR;
413               }
414             else
415               flags |= SHORT;
416             break;
417           case 'l':
418             if (flags & (SHORT|LONGDBL|CHAR))
419               conv_error ();
420             else if (flags & LONG)
421               {
422                 /* A double `l' is equivalent to an `L'.  */
423                 flags &= ~LONG;
424                 flags |= LONGDBL;
425               }
426             else
427               /* int's are long int's.  */
428               flags |= LONG;
429             break;
430           case 'q':
431           case 'L':
432             /* double's are long double's, and int's are long long int's.  */
433             if (flags & TYPEMOD)
434               /* Signal illegal format element.  */
435               conv_error ();
436             flags |= LONGDBL;
437             break;
438           case 'a':
439             /* The `a' is used as a flag only if followed by `s', `S' or
440                `['.  */
441             if (*f != 's' && *f != 'S' && *f != '[')
442               {
443                 --f;
444                 break;
445               }
446             if (flags & TYPEMOD)
447               /* Signal illegal format element.  */
448               conv_error ();
449             /* String conversions (%s, %[) take a `char **'
450                arg and fill it in with a malloc'd pointer.  */
451             flags |= MALLOC;
452             break;
453           }
454
455       /* End of the format string?  */
456       if (*f == '\0')
457         conv_error ();
458
459       /* Find the conversion specifier.  */
460       fc = *f++;
461       if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
462         {
463           /* Eat whitespace.  */
464           int save_errno = errno;
465           errno = 0;
466           do
467             if (inchar () == EOF && errno == EINTR)
468               input_error ();
469           while (isspace (c));
470           errno = save_errno;
471           ungetc (c, s);
472           skip_space = 0;
473         }
474
475       switch (fc)
476         {
477         case '%':       /* Must match a literal '%'.  */
478           c = inchar ();
479           if (c == EOF)
480             input_error ();
481           if (c != fc)
482             {
483               ungetc (c, s);
484               conv_error ();
485             }
486           break;
487
488         case 'n':       /* Answer number of assignments done.  */
489           /* Corrigendum 1 to ISO C 1990 describes the allowed flags
490              with the 'n' conversion specifier.  */
491           if (!(flags & SUPPRESS))
492             {
493               /* Don't count the read-ahead.  */
494               if (flags & LONGDBL)
495                 *ARG (long long int *) = read_in;
496               else if (flags & LONG)
497                 *ARG (long int *) = read_in;
498               else if (flags & SHORT)
499                 *ARG (short int *) = read_in;
500               else
501                 *ARG (int *) = read_in;
502
503 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
504               /* We have a severe problem here.  The ISO C standard
505                  contradicts itself in explaining the effect of the %n
506                  format in `scanf'.  While in ISO C:1990 and the ISO C
507                  Amendement 1:1995 the result is described as
508
509                    Execution of a %n directive does not effect the
510                    assignment count returned at the completion of
511                    execution of the f(w)scanf function.
512
513                  in ISO C Corrigendum 1:1994 the following was added:
514
515                    Subclause 7.9.6.2
516                    Add the following fourth example:
517                      In:
518                        #include <stdio.h>
519                        int d1, d2, n1, n2, i;
520                        i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
521                      the value 123 is assigned to d1 and the value3 to n1.
522                      Because %n can never get an input failure the value
523                      of 3 is also assigned to n2.  The value of d2 is not
524                      affected.  The value 3 is assigned to i.
525
526                  We go for now with the historically correct code from ISO C,
527                  i.e., we don't count the %n assignments.  When it ever
528                  should proof to be wrong just remove the #ifdef above.  */
529               ++done;
530 #endif
531             }
532           break;
533
534         case 'c':       /* Match characters.  */
535           if ((flags & LONG) == 0)
536             {
537               if (!(flags & SUPPRESS))
538                 {
539                   str = ARG (char *);
540                   if (str == NULL)
541                     conv_error ();
542                 }
543
544               c = inchar ();
545               if (c == EOF)
546                 input_error ();
547
548               if (width == -1)
549                 width = 1;
550
551               if (!(flags & SUPPRESS))
552                 {
553                   do
554                     *str++ = c;
555                   while (--width > 0 && inchar () != EOF);
556                 }
557               else
558                 while (--width > 0 && inchar () != EOF);
559
560               if (!(flags & SUPPRESS))
561                 ++done;
562
563               break;
564             }
565           /* FALLTHROUGH */
566         case 'C':
567           /* Get UTF-8 encoded wide character.  Here we assume (as in
568              other parts of the libc) that we only have to handle
569              UTF-8.  */
570           {
571             wint_t val;
572             size_t cnt = 0;
573             int first = 1;
574
575             if (!(flags & SUPPRESS))
576               {
577                 wstr = ARG (wchar_t *);
578                 if (str == NULL)
579                   conv_error ();
580               }
581
582             do
583               {
584 #define NEXT_WIDE_CHAR(First)                                                 \
585                 c = inchar ();                                                \
586                 if (c == EOF)                                                 \
587                   /* EOF is only an error for the first character.  */        \
588                   if (First)                                                  \
589                     input_error ();                                           \
590                   else                                                        \
591                     break;                                                    \
592                 val = c;                                                      \
593                 if (val >= 0x80)                                              \
594                   {                                                           \
595                     if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe)             \
596                       encode_error ();                                        \
597                     if ((c & 0xe0) == 0xc0)                                   \
598                       {                                                       \
599                         /* We expect two bytes.  */                           \
600                         cnt = 1;                                              \
601                         val &= 0x1f;                                          \
602                       }                                                       \
603                     else if ((c & 0xf0) == 0xe0)                              \
604                       {                                                       \
605                         /* We expect three bytes.  */                         \
606                         cnt = 2;                                              \
607                         val &= 0x0f;                                          \
608                       }                                                       \
609                     else if ((c & 0xf8) == 0xf0)                              \
610                       {                                                       \
611                         /* We expect four bytes.  */                          \
612                         cnt = 3;                                              \
613                         val &= 0x07;                                          \
614                       }                                                       \
615                     else if ((c & 0xfc) == 0xf8)                              \
616                       {                                                       \
617                         /* We expect five bytes.  */                          \
618                         cnt = 4;                                              \
619                         val &= 0x03;                                          \
620                       }                                                       \
621                     else                                                      \
622                       {                                                       \
623                         /* We expect six bytes.  */                           \
624                         cnt = 5;                                              \
625                         val &= 0x01;                                          \
626                       }                                                       \
627                                                                               \
628                     do                                                        \
629                       {                                                       \
630                         c = inchar ();                                        \
631                         if (c == EOF                                          \
632                             || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe)      \
633                           encode_error ();                                    \
634                         val <<= 6;                                            \
635                         val |= c & 0x3f;                                      \
636                       }                                                       \
637                     while (--cnt > 0);                                        \
638                   }                                                           \
639                                                                               \
640                 if (!(flags & SUPPRESS))                                      \
641                   *wstr++ = val;                                              \
642                 First = 0
643
644                 NEXT_WIDE_CHAR (first);
645               }
646             while (--width > 0);
647
648             if (!(flags & SUPPRESS))
649               ++done;
650           }
651           break;
652
653         case 's':               /* Read a string.  */
654           if (flags & LONG)
655             /* We have to process a wide character string.  */
656             goto wide_char_string;
657
658 #define STRING_ARG(Str, Type)                                                 \
659           if (!(flags & SUPPRESS))                                            \
660             {                                                                 \
661               if (flags & MALLOC)                                             \
662                 {                                                             \
663                   /* The string is to be stored in a malloc'd buffer.  */     \
664                   strptr = ARG (char **);                                     \
665                   if (strptr == NULL)                                         \
666                     conv_error ();                                            \
667                   /* Allocate an initial buffer.  */                          \
668                   strsize = 100;                                              \
669                   *strptr = malloc (strsize * sizeof (Type));                 \
670                   Str = (Type *) *strptr;                                     \
671                 }                                                             \
672               else                                                            \
673                 Str = ARG (Type *);                                           \
674               if (Str == NULL)                                                \
675                 conv_error ();                                                \
676             }
677           STRING_ARG (str, char);
678
679           c = inchar ();
680           if (c == EOF)
681             input_error ();
682
683           do
684             {
685               if (isspace (c))
686                 {
687                   ungetc (c, s);
688                   break;
689                 }
690 #define STRING_ADD_CHAR(Str, c, Type)                                         \
691               if (!(flags & SUPPRESS))                                        \
692                 {                                                             \
693                   *Str++ = c;                                                 \
694                   if ((flags & MALLOC) && (char *) Str == *strptr + strsize)  \
695                     {                                                         \
696                       /* Enlarge the buffer.  */                              \
697                       Str = realloc (*strptr, strsize * 2 * sizeof (Type));   \
698                       if (Str == NULL)                                        \
699                         {                                                     \
700                           /* Can't allocate that much.  Last-ditch effort.  */\
701                           Str = realloc (*strptr,                             \
702                                          (strsize + 1) * sizeof (Type));      \
703                           if (Str == NULL)                                    \
704                             {                                                 \
705                               /* We lose.  Oh well.                           \
706                                  Terminate the string and stop converting,    \
707                                  so at least we don't skip any input.  */     \
708                               ((Type *) (*strptr))[strsize] = '\0';           \
709                               ++done;                                         \
710                               conv_error ();                                  \
711                             }                                                 \
712                           else                                                \
713                             {                                                 \
714                               *strptr = (char *) Str;                         \
715                               Str = ((Type *) *strptr) + strsize;             \
716                               ++strsize;                                      \
717                             }                                                 \
718                         }                                                     \
719                       else                                                    \
720                         {                                                     \
721                           *strptr = (char *) Str;                             \
722                           Str = ((Type *) *strptr) + strsize;                 \
723                           strsize *= 2;                                       \
724                         }                                                     \
725                     }                                                         \
726                 }
727               STRING_ADD_CHAR (str, c, char);
728             } while ((width <= 0 || --width > 0) && inchar () != EOF);
729
730           if (!(flags & SUPPRESS))
731             {
732               *str = '\0';
733               ++done;
734             }
735           break;
736
737         case 'S':
738           /* Wide character string.  */
739         wide_char_string:
740           {
741             wint_t val;
742             int first = 1;
743             STRING_ARG (wstr, wchar_t);
744
745             do
746               {
747                 size_t cnt = 0;
748                 NEXT_WIDE_CHAR (first);
749
750                 if (iswspace (val))
751                   {
752                     /* XXX We would have to push back the whole wide char
753                        with possibly many bytes.  But since scanf does
754                        not make a difference for white space characters
755                        we can simply push back a simple <SP> which is
756                        guaranteed to be in the [:space:] class.  */
757                     ungetc (' ', s);
758                     break;
759                   }
760
761                 STRING_ADD_CHAR (wstr, val, wchar_t);
762                 first = 0;
763               }
764             while (width <= 0 || --width > 0);
765
766             if (!(flags & SUPPRESS))
767               {
768                 *wstr = L'\0';
769                 ++done;
770               }
771           }
772           break;
773
774         case 'x':       /* Hexadecimal integer.  */
775         case 'X':       /* Ditto.  */
776           base = 16;
777           number_signed = 0;
778           goto number;
779
780         case 'o':       /* Octal integer.  */
781           base = 8;
782           number_signed = 0;
783           goto number;
784
785         case 'u':       /* Unsigned decimal integer.  */
786           base = 10;
787           number_signed = 0;
788           goto number;
789
790         case 'd':       /* Signed decimal integer.  */
791           base = 10;
792           number_signed = 1;
793           goto number;
794
795         case 'i':       /* Generic number.  */
796           base = 0;
797           number_signed = 1;
798
799         number:
800           c = inchar ();
801           if (c == EOF)
802             input_error ();
803
804           /* Check for a sign.  */
805           if (c == '-' || c == '+')
806             {
807               ADDW (c);
808               if (width > 0)
809                 --width;
810               c = inchar ();
811             }
812
813           /* Look for a leading indication of base.  */
814           if (width != 0 && c == '0')
815             {
816               if (width > 0)
817                 --width;
818
819               ADDW (c);
820               c = inchar ();
821
822               if (width != 0 && tolower (c) == 'x')
823                 {
824                   if (base == 0)
825                     base = 16;
826                   if (base == 16)
827                     {
828                       if (width > 0)
829                         --width;
830                       c = inchar ();
831                     }
832                 }
833               else if (base == 0)
834                 base = 8;
835             }
836
837           if (base == 0)
838             base = 10;
839
840           /* Read the number into workspace.  */
841           while (c != EOF && width != 0)
842             {
843               if (base == 16 ? !isxdigit (c) :
844                   ((!isdigit (c) || c - '0' >= base) &&
845                    !((flags & GROUP) && base == 10 && c == thousands)))
846                 break;
847               ADDW (c);
848               if (width > 0)
849                 --width;
850
851               c = inchar ();
852             }
853
854           /* The just read character is not part of the number anymore.  */
855           ungetc (c, s);
856
857           if (wpsize == 0 ||
858               (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
859             /* There was no number.  */
860             conv_error ();
861
862           /* Convert the number.  */
863           ADDW ('\0');
864           if (flags & LONGDBL)
865             {
866               if (number_signed)
867                 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
868               else
869                 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
870             }
871           else
872             {
873               if (number_signed)
874                 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
875               else
876                 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
877             }
878           if (wp == tw)
879             conv_error ();
880
881           if (!(flags & SUPPRESS))
882             {
883               if (! number_signed)
884                 {
885                   if (flags & LONGDBL)
886                     *ARG (unsigned LONGLONG int *) = num.uq;
887                   else if (flags & LONG)
888                     *ARG (unsigned long int *) = num.ul;
889                   else if (flags & SHORT)
890                     *ARG (unsigned short int *)
891                       = (unsigned short int) num.ul;
892                   else if (flags & CHAR)
893                     *ARG (unsigned char *) = (unsigned char) num.ul;
894                   else
895                     *ARG (unsigned int *) = (unsigned int) num.ul;
896                 }
897               else
898                 {
899                   if (flags & LONGDBL)
900                     *ARG (LONGLONG int *) = num.q;
901                   else if (flags & LONG)
902                     *ARG (long int *) = num.l;
903                   else if (flags & SHORT)
904                     *ARG (short int *) = (short int) num.l;
905                   else if (flags & CHAR)
906                     *ARG (signed char *) = (signed char) num.ul;
907                   else
908                     *ARG (int *) = (int) num.l;
909                 }
910               ++done;
911             }
912           break;
913
914         case 'e':       /* Floating-point numbers.  */
915         case 'E':
916         case 'f':
917         case 'g':
918         case 'G':
919         case 'a':
920         case 'A':
921           c = inchar ();
922           if (c == EOF)
923             input_error ();
924
925           /* Check for a sign.  */
926           if (c == '-' || c == '+')
927             {
928               negative = c == '-';
929               if (inchar () == EOF)
930                 /* EOF is only an input error before we read any chars.  */
931                 conv_error ();
932               if (width > 0)
933                 --width;
934             }
935           else
936             negative = 0;
937
938           /* Take care for the special arguments "nan" and "inf".  */
939           if (tolower (c) == 'n')
940             {
941               /* Maybe "nan".  */
942               ADDW (c);
943               if (inchar () == EOF || tolower (c) != 'a')
944                 input_error ();
945               ADDW (c);
946               if (inchar () == EOF || tolower (c) != 'n')
947                 input_error ();
948               ADDW (c);
949               /* It is "nan".  */
950               goto scan_float;
951             }
952           else if (tolower (c) == 'i')
953             {
954               /* Maybe "inf" or "infinity".  */
955               ADDW (c);
956               if (inchar () == EOF || tolower (c) != 'n')
957                 input_error ();
958               ADDW (c);
959               if (inchar () == EOF || tolower (c) != 'f')
960                 input_error ();
961               ADDW (c);
962               /* It is as least "inf".  */
963               if (inchar () != EOF)
964                 {
965                   if (tolower (c) == 'i')
966                     {
967                       /* No we have to read the rest as well.  */
968                       ADDW (c);
969                       if (inchar () == EOF || tolower (c) != 'n')
970                         input_error ();
971                       ADDW (c);
972                       if (inchar () == EOF || tolower (c) != 'i')
973                         input_error ();
974                       ADDW (c);
975                       if (inchar () == EOF || tolower (c) != 't')
976                         input_error ();
977                       ADDW (c);
978                       if (inchar () == EOF || tolower (c) != 'y')
979                         input_error ();
980                       ADDW (c);
981                     }
982                   else
983                     /* Never mind.  */
984                     ungetc (c, s);
985                 }
986               goto scan_float;
987             }
988
989           is_hexa = 0;
990           exp_char = 'e';
991           if (c == '0')
992             {
993               ADDW (c);
994               c = inchar ();
995               if (tolower (c) == 'x')
996                 {
997                   /* It is a number in hexadecimal format.  */
998                   ADDW (c);
999
1000                   is_hexa = 1;
1001                   exp_char = 'p';
1002
1003                   /* Grouping is not allowed.  */
1004                   flags &= ~GROUP;
1005                   c = inchar ();
1006                 }
1007             }
1008
1009           got_dot = got_e = 0;
1010           do
1011             {
1012               if (isdigit (c))
1013                 ADDW (c);
1014               else if (!got_e && is_hexa && isxdigit (c))
1015                 ADDW (c);
1016               else if (got_e && wp[wpsize - 1] == exp_char
1017                        && (c == '-' || c == '+'))
1018                 ADDW (c);
1019               else if (wpsize > 0 && !got_e && tolower (c) == exp_char)
1020                 {
1021                   ADDW (exp_char);
1022                   got_e = got_dot = 1;
1023                 }
1024               else if (c == decimal && !got_dot)
1025                 {
1026                   ADDW (c);
1027                   got_dot = 1;
1028                 }
1029               else if ((flags & GROUP) && c == thousands && !got_dot)
1030                 ADDW (c);
1031               else
1032                 {
1033                   /* The last read character is not part of the number
1034                      anymore.  */
1035                   ungetc (c, s);
1036                   break;
1037                 }
1038               if (width > 0)
1039                 --width;
1040             }
1041           while (width != 0 && inchar () != EOF);
1042
1043           /* Have we read any character?  If we try to read a number
1044              in hexadecimal notation and we have read only the `0x'
1045              prefix this is an error.  */
1046           if (wpsize == 0 || (is_hexa && wpsize == 2))
1047             conv_error ();
1048
1049         scan_float:
1050           /* Convert the number.  */
1051           ADDW ('\0');
1052           if (flags & LONGDBL)
1053             {
1054               long double d = __strtold_internal (wp, &tw, flags & GROUP);
1055               if (!(flags & SUPPRESS) && tw != wp)
1056                 *ARG (long double *) = negative ? -d : d;
1057             }
1058           else if (flags & LONG)
1059             {
1060               double d = __strtod_internal (wp, &tw, flags & GROUP);
1061               if (!(flags & SUPPRESS) && tw != wp)
1062                 *ARG (double *) = negative ? -d : d;
1063             }
1064           else
1065             {
1066               float d = __strtof_internal (wp, &tw, flags & GROUP);
1067               if (!(flags & SUPPRESS) && tw != wp)
1068                 *ARG (float *) = negative ? -d : d;
1069             }
1070
1071           if (tw == wp)
1072             conv_error ();
1073
1074           if (!(flags & SUPPRESS))
1075             ++done;
1076           break;
1077
1078         case '[':       /* Character class.  */
1079           if (flags & LONG)
1080             {
1081               STRING_ARG (wstr, wchar_t);
1082               c = '\0';         /* This is to keep gcc quiet.  */
1083             }
1084           else
1085             {
1086               STRING_ARG (str, char);
1087
1088               c = inchar ();
1089               if (c == EOF)
1090                 input_error ();
1091             }
1092
1093           if (*f == '^')
1094             {
1095               ++f;
1096               not_in = 1;
1097             }
1098           else
1099             not_in = 0;
1100
1101           /* Fill WP with byte flags indexed by character.
1102              We will use this flag map for matching input characters.  */
1103           if (wpmax < UCHAR_MAX)
1104             {
1105               wpmax = UCHAR_MAX;
1106               wp = (char *) alloca (wpmax);
1107             }
1108           memset (wp, 0, UCHAR_MAX);
1109
1110           fc = *f;
1111           if (fc == ']' || fc == '-')
1112             {
1113               /* If ] or - appears before any char in the set, it is not
1114                  the terminator or separator, but the first char in the
1115                  set.  */
1116               wp[fc] = 1;
1117               ++f;
1118             }
1119
1120           while ((fc = *f++) != '\0' && fc != ']')
1121             {
1122               if (fc == '-' && *f != '\0' && *f != ']' &&
1123                   (unsigned char) f[-2] <= (unsigned char) *f)
1124                 {
1125                   /* Add all characters from the one before the '-'
1126                      up to (but not including) the next format char.  */
1127                   for (fc = f[-2]; fc < *f; ++fc)
1128                     wp[fc] = 1;
1129                 }
1130               else
1131                 /* Add the character to the flag map.  */
1132                 wp[fc] = 1;
1133             }
1134           if (fc == '\0')
1135             {
1136               if (!(flags & LONG))
1137                 ungetc (c, s);
1138               conv_error();
1139             }
1140
1141           if (flags & LONG)
1142             {
1143               wint_t val;
1144               int first = 1;
1145
1146               do
1147                 {
1148                   size_t cnt = 0;
1149                   NEXT_WIDE_CHAR (first);
1150                   if (val <= 255 && wp[val] == not_in)
1151                     {
1152                       ungetc (val, s);
1153                       break;
1154                     }
1155                   STRING_ADD_CHAR (wstr, val, wchar_t);
1156                   if (width > 0)
1157                     --width;
1158                   first = 0;
1159                 }
1160               while (width != 0);
1161
1162               if (first)
1163                 conv_error ();
1164
1165               if (!(flags & SUPPRESS))
1166                 {
1167                   *wstr = L'\0';
1168                   ++done;
1169                 }
1170             }
1171           else
1172             {
1173               num.ul = read_in - 1; /* -1 because we already read one char.  */
1174               do
1175                 {
1176                   if (wp[c] == not_in)
1177                     {
1178                       ungetc (c, s);
1179                       break;
1180                     }
1181                   STRING_ADD_CHAR (str, c, char);
1182                   if (width > 0)
1183                     --width;
1184                 }
1185               while (width != 0 && inchar () != EOF);
1186
1187               if (read_in == num.ul)
1188                 conv_error ();
1189
1190               if (!(flags & SUPPRESS))
1191                 {
1192                   *str = '\0';
1193                   ++done;
1194                 }
1195             }
1196           break;
1197
1198         case 'p':       /* Generic pointer.  */
1199           base = 16;
1200           /* A PTR must be the same size as a `long int'.  */
1201           flags &= ~(SHORT|LONGDBL);
1202           flags |= LONG;
1203           number_signed = 0;
1204           goto number;
1205         }
1206     }
1207
1208   /* The last thing we saw int the format string was a white space.
1209      Consume the last white spaces.  */
1210   if (skip_space)
1211     {
1212       do
1213         c = inchar ();
1214       while (isspace (c));
1215       ungetc (c, s);
1216     }
1217
1218   /* Unlock stream.  */
1219   UNLOCK_STREAM;
1220
1221   return done;
1222 }
1223
1224 #ifdef USE_IN_LIBIO
1225 int
1226 __vfscanf (FILE *s, const char *format, va_list argptr)
1227 {
1228   return _IO_vfscanf (s, format, argptr, NULL);
1229 }
1230 #endif
1231
1232 weak_alias (__vfscanf, vfscanf)