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