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