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