Back to index

glibc  2.9
vfscanf.c
Go to the documentation of this file.
00001 /* Copyright (C) 1991-2006, 2007 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <assert.h>
00020 #include <errno.h>
00021 #include <limits.h>
00022 #include <ctype.h>
00023 #include <stdarg.h>
00024 #include <stdio.h>
00025 #include <stdint.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <wchar.h>
00029 #include <wctype.h>
00030 #include <bits/libc-lock.h>
00031 #include <locale/localeinfo.h>
00032 
00033 #ifdef __GNUC__
00034 # define HAVE_LONGLONG
00035 # define LONGLONG    long long
00036 #else
00037 # define LONGLONG    long
00038 #endif
00039 
00040 /* Determine whether we have to handle `long long' at all.  */
00041 #if LONG_MAX == LONG_LONG_MAX
00042 # define need_longlong      0
00043 #else
00044 # define need_longlong      1
00045 #endif
00046 
00047 /* Determine whether we have to handle `long'.  */
00048 #if INT_MAX == LONG_MAX
00049 # define need_long   0
00050 #else
00051 # define need_long   1
00052 #endif
00053 
00054 /* Those are flags in the conversion format. */
00055 #define LONG         0x0001 /* l: long or double */
00056 #define LONGDBL             0x0002 /* L: long long or long double */
00057 #define SHORT        0x0004 /* h: short */
00058 #define SUPPRESS     0x0008 /* *: suppress assignment */
00059 #define POINTER             0x0010 /* weird %p pointer (`fake hex') */
00060 #define NOSKIP              0x0020 /* do not skip blanks */
00061 #define NUMBER_SIGNED       0x0040 /* signed integer */
00062 #define GROUP        0x0080 /* ': group numbers */
00063 #define GNU_MALLOC   0x0100 /* a: malloc strings */
00064 #define CHAR         0x0200 /* hh: char */
00065 #define I18N         0x0400 /* I: use locale's digits */
00066 #define HEXA_FLOAT   0x0800 /* hexadecimal float */
00067 #define READ_POINTER 0x1000 /* this is a pointer value */
00068 #define POSIX_MALLOC 0x2000 /* m: malloc strings */
00069 #define MALLOC              (GNU_MALLOC | POSIX_MALLOC)
00070 
00071 #include <locale/localeinfo.h>
00072 #include <libioP.h>
00073 #include <libio.h>
00074 
00075 #undef va_list
00076 #define va_list      _IO_va_list
00077 
00078 #ifdef COMPILE_WSCANF
00079 # define ungetc(c, s)       ((void) (c == WEOF                              \
00080                              || (--read_in,                                 \
00081                                  INTUSE(_IO_sputbackwc) (s, c))))
00082 # define ungetc_not_eof(c, s)      ((void) (--read_in,                      \
00083                                     INTUSE(_IO_sputbackwc) (s, c)))
00084 # define inchar()    (c == WEOF ? ((errno = inchar_errno), WEOF)            \
00085                       : ((c = _IO_getwc_unlocked (s)),               \
00086                          (void) (c != WEOF                                  \
00087                                 ? ++read_in                                 \
00088                                 : (size_t) (inchar_errno = errno)), c))
00089 
00090 # define MEMCPY(d, s, n) __wmemcpy (d, s, n)
00091 # define ISSPACE(Ch)   iswspace (Ch)
00092 # define ISDIGIT(Ch)   iswdigit (Ch)
00093 # define ISXDIGIT(Ch)         iswxdigit (Ch)
00094 # define TOLOWER(Ch)   towlower (Ch)
00095 # define ORIENT        if (_IO_fwide (s, 1) != 1) return WEOF
00096 # define __strtoll_internal __wcstoll_internal
00097 # define __strtoull_internal       __wcstoull_internal
00098 # define __strtol_internal  __wcstol_internal
00099 # define __strtoul_internal __wcstoul_internal
00100 # define __strtold_internal __wcstold_internal
00101 # define __strtod_internal  __wcstod_internal
00102 # define __strtof_internal  __wcstof_internal
00103 
00104 # define L_(Str)     L##Str
00105 # define CHAR_T             wchar_t
00106 # define UCHAR_T     unsigned int
00107 # define WINT_T             wint_t
00108 # undef EOF
00109 # define EOF         WEOF
00110 #else
00111 # define ungetc(c, s)       ((void) ((int) c == EOF                                \
00112                              || (--read_in,                                 \
00113                                  INTUSE(_IO_sputbackc) (s, (unsigned char) c))))
00114 # define ungetc_not_eof(c, s)      ((void) (--read_in,                      \
00115                                     INTUSE(_IO_sputbackc) (s, (unsigned char) c)))
00116 # define inchar()    (c == EOF ? ((errno = inchar_errno), EOF)       \
00117                       : ((c = _IO_getc_unlocked (s)),                \
00118                          (void) (c != EOF                            \
00119                                 ? ++read_in                                 \
00120                                 : (size_t) (inchar_errno = errno)), c))
00121 # define MEMCPY(d, s, n) memcpy (d, s, n)
00122 # define ISSPACE(Ch)   __isspace_l (Ch, loc)
00123 # define ISDIGIT(Ch)   __isdigit_l (Ch, loc)
00124 # define ISXDIGIT(Ch)         __isxdigit_l (Ch, loc)
00125 # define TOLOWER(Ch)   __tolower_l ((unsigned char) (Ch), loc)
00126 # define ORIENT        if (_IO_vtable_offset (s) == 0                       \
00127                            && _IO_fwide (s, -1) != -1)               \
00128                          return EOF
00129 
00130 # define L_(Str)     Str
00131 # define CHAR_T             char
00132 # define UCHAR_T     unsigned char
00133 # define WINT_T             int
00134 #endif
00135 
00136 #define encode_error() do {                                          \
00137                        errval = 4;                                   \
00138                        __set_errno (EILSEQ);                                \
00139                        goto errout;                                         \
00140                      } while (0)
00141 #define conv_error() do {                                            \
00142                        errval = 2;                                   \
00143                        goto errout;                                         \
00144                      } while (0)
00145 #define input_error()       do {                                            \
00146                        errval = 1;                                   \
00147                        if (done == 0) done = EOF;                           \
00148                        goto errout;                                         \
00149                      } while (0)
00150 #define add_ptr_to_free(ptr)                                                \
00151   do                                                                 \
00152     {                                                                \
00153       if (ptrs_to_free == NULL                                              \
00154          || ptrs_to_free->count == (sizeof (ptrs_to_free->ptrs)             \
00155                                  / sizeof (ptrs_to_free->ptrs[0])))         \
00156        {                                                             \
00157          struct ptrs_to_free *new_ptrs = alloca (sizeof (*ptrs_to_free));    \
00158          new_ptrs->count = 0;                                               \
00159          new_ptrs->next = ptrs_to_free;                              \
00160          ptrs_to_free = new_ptrs;                                    \
00161        }                                                             \
00162       ptrs_to_free->ptrs[ptrs_to_free->count++] = (ptr);                    \
00163     }                                                                \
00164   while (0)
00165 #define ARGCHECK(s, format)                                          \
00166   do                                                                 \
00167     {                                                                \
00168       /* Check file argument for consistence.  */                           \
00169       CHECK_FILE (s, EOF);                                           \
00170       if (s->_flags & _IO_NO_READS)                                         \
00171        {                                                             \
00172          __set_errno (EBADF);                                               \
00173          return EOF;                                                 \
00174        }                                                             \
00175       else if (format == NULL)                                              \
00176        {                                                             \
00177          MAYBE_SET_EINVAL;                                           \
00178          return EOF;                                                 \
00179        }                                                             \
00180     } while (0)
00181 #define LOCK_STREAM(S)                                                      \
00182   __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, (S)); \
00183   _IO_flockfile (S)
00184 #define UNLOCK_STREAM(S)                                             \
00185   _IO_funlockfile (S);                                                      \
00186   __libc_cleanup_region_end (0)
00187 
00188 struct ptrs_to_free
00189 {
00190   size_t count;
00191   struct ptrs_to_free *next;
00192   char **ptrs[32];
00193 };
00194 
00195 /* Read formatted input from S according to the format string
00196    FORMAT, using the argument list in ARG.
00197    Return the number of assignments made, or -1 for an input error.  */
00198 #ifdef COMPILE_WSCANF
00199 int
00200 _IO_vfwscanf (_IO_FILE *s, const wchar_t *format, _IO_va_list argptr,
00201              int *errp)
00202 #else
00203 int
00204 _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
00205                     int *errp)
00206 #endif
00207 {
00208   va_list arg;
00209   register const CHAR_T *f = format;
00210   register UCHAR_T fc;      /* Current character of the format.  */
00211   register WINT_T done = 0; /* Assignments done.  */
00212   register size_t read_in = 0;     /* Chars read in.  */
00213   register WINT_T c = 0;    /* Last char read.  */
00214   register int width;              /* Maximum field width.  */
00215   register int flags;              /* Modifiers for current format element.  */
00216   int errval = 0;
00217 #ifndef COMPILE_WSCANF
00218   __locale_t loc = _NL_CURRENT_LOCALE;
00219   struct locale_data *const curctype = loc->__locales[LC_CTYPE];
00220 #endif
00221 
00222   /* Errno of last failed inchar call.  */
00223   int inchar_errno = 0;
00224   /* Status for reading F-P nums.  */
00225   char got_dot, got_e, negative;
00226   /* If a [...] is a [^...].  */
00227   CHAR_T not_in;
00228 #define exp_char not_in
00229   /* Base for integral numbers.  */
00230   int base;
00231   /* Decimal point character.  */
00232 #ifdef COMPILE_WSCANF
00233   wint_t decimal;
00234 #else
00235   const char *decimal;
00236 #endif
00237   /* The thousands character of the current locale.  */
00238 #ifdef COMPILE_WSCANF
00239   wint_t thousands;
00240 #else
00241   const char *thousands;
00242 #endif
00243   struct ptrs_to_free *ptrs_to_free = NULL;
00244   /* State for the conversions.  */
00245   mbstate_t state;
00246   /* Integral holding variables.  */
00247   union
00248     {
00249       long long int q;
00250       unsigned long long int uq;
00251       long int l;
00252       unsigned long int ul;
00253     } num;
00254   /* Character-buffer pointer.  */
00255   char *str = NULL;
00256   wchar_t *wstr = NULL;
00257   char **strptr = NULL;
00258   ssize_t strsize = 0;
00259   /* We must not react on white spaces immediately because they can
00260      possibly be matched even if in the input stream no character is
00261      available anymore.  */
00262   int skip_space = 0;
00263   /* Workspace.  */
00264   CHAR_T *tw;               /* Temporary pointer.  */
00265   CHAR_T *wp = NULL;        /* Workspace.  */
00266   size_t wpmax = 0;         /* Maximal size of workspace.  */
00267   size_t wpsize;            /* Currently used bytes in workspace.  */
00268 #define ADDW(Ch)                                                   \
00269   do                                                               \
00270     {                                                              \
00271       if (wpsize == wpmax)                                         \
00272        {                                                           \
00273          CHAR_T *old = wp;                                         \
00274          wpmax = (UCHAR_MAX + 1 > 2 * wpmax ? UCHAR_MAX + 1 : 2 * wpmax);  \
00275          wp = (CHAR_T *) alloca (wpmax * sizeof (CHAR_T));                \
00276          if (old != NULL)                                          \
00277            MEMCPY (wp, old, wpsize);                                      \
00278        }                                                           \
00279       wp[wpsize++] = (Ch);                                         \
00280     }                                                              \
00281   while (0)
00282 
00283 #ifdef __va_copy
00284   __va_copy (arg, argptr);
00285 #else
00286   arg = (va_list) argptr;
00287 #endif
00288 
00289 #ifdef ORIENT
00290   ORIENT;
00291 #endif
00292 
00293   ARGCHECK (s, format);
00294 
00295  {
00296 #ifndef COMPILE_WSCANF
00297    struct locale_data *const curnumeric = loc->__locales[LC_NUMERIC];
00298 #endif
00299 
00300    /* Figure out the decimal point character.  */
00301 #ifdef COMPILE_WSCANF
00302    decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
00303 #else
00304    decimal = curnumeric->values[_NL_ITEM_INDEX (DECIMAL_POINT)].string;
00305 #endif
00306    /* Figure out the thousands separator character.  */
00307 #ifdef COMPILE_WSCANF
00308    thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
00309 #else
00310    thousands = curnumeric->values[_NL_ITEM_INDEX (THOUSANDS_SEP)].string;
00311    if (*thousands == '\0')
00312      thousands = NULL;
00313 #endif
00314  }
00315 
00316   /* Lock the stream.  */
00317   LOCK_STREAM (s);
00318 
00319 
00320 #ifndef COMPILE_WSCANF
00321   /* From now on we use `state' to convert the format string.  */
00322   memset (&state, '\0', sizeof (state));
00323 #endif
00324 
00325   /* Run through the format string.  */
00326   while (*f != '\0')
00327     {
00328       unsigned int argpos;
00329       /* Extract the next argument, which is of type TYPE.
00330         For a %N$... spec, this is the Nth argument from the beginning;
00331         otherwise it is the next argument after the state now in ARG.  */
00332 #ifdef __va_copy
00333 # define ARG(type)   (argpos == 0 ? va_arg (arg, type) :                    \
00334                       ({ unsigned int pos = argpos;                         \
00335                          va_list arg;                                \
00336                          __va_copy (arg, argptr);                           \
00337                          while (--pos > 0)                                  \
00338                            (void) va_arg (arg, void *);              \
00339                          va_arg (arg, type);                                \
00340                        }))
00341 #else
00342 # if 0
00343       /* XXX Possible optimization.  */
00344 #  define ARG(type)  (argpos == 0 ? va_arg (arg, type) :                    \
00345                       ({ va_list arg = (va_list) argptr;                    \
00346                          arg = (va_list) ((char *) arg               \
00347                                         + (argpos - 1)               \
00348                                         * __va_rounded_size (void *));   \
00349                          va_arg (arg, type);                                \
00350                       }))
00351 # else
00352 #  define ARG(type)  (argpos == 0 ? va_arg (arg, type) :                    \
00353                       ({ unsigned int pos = argpos;                         \
00354                          va_list arg = (va_list) argptr;                    \
00355                          while (--pos > 0)                                  \
00356                            (void) va_arg (arg, void *);              \
00357                          va_arg (arg, type);                                \
00358                        }))
00359 # endif
00360 #endif
00361 
00362 #ifndef COMPILE_WSCANF
00363       if (!isascii ((unsigned char) *f))
00364        {
00365          /* Non-ASCII, may be a multibyte.  */
00366          int len = __mbrlen (f, strlen (f), &state);
00367          if (len > 0)
00368            {
00369              do
00370               {
00371                 c = inchar ();
00372                 if (__builtin_expect (c == EOF, 0))
00373                   input_error ();
00374                 else if (c != (unsigned char) *f++)
00375                   {
00376                     ungetc_not_eof (c, s);
00377                     conv_error ();
00378                   }
00379               }
00380              while (--len > 0);
00381              continue;
00382            }
00383        }
00384 #endif
00385 
00386       fc = *f++;
00387       if (fc != '%')
00388        {
00389          /* Remember to skip spaces.  */
00390          if (ISSPACE (fc))
00391            {
00392              skip_space = 1;
00393              continue;
00394            }
00395 
00396          /* Read a character.  */
00397          c = inchar ();
00398 
00399          /* Characters other than format specs must just match.  */
00400          if (__builtin_expect (c == EOF, 0))
00401            input_error ();
00402 
00403          /* We saw white space char as the last character in the format
00404             string.  Now it's time to skip all leading white space.  */
00405          if (skip_space)
00406            {
00407              while (ISSPACE (c))
00408               if (__builtin_expect (inchar () == EOF, 0))
00409                 input_error ();
00410              skip_space = 0;
00411            }
00412 
00413          if (__builtin_expect (c != fc, 0))
00414            {
00415              ungetc (c, s);
00416              conv_error ();
00417            }
00418 
00419          continue;
00420        }
00421 
00422       /* This is the start of the conversion string. */
00423       flags = 0;
00424 
00425       /* Initialize state of modifiers.  */
00426       argpos = 0;
00427 
00428       /* Prepare temporary buffer.  */
00429       wpsize = 0;
00430 
00431       /* Check for a positional parameter specification.  */
00432       if (ISDIGIT ((UCHAR_T) *f))
00433        {
00434          argpos = (UCHAR_T) *f++ - L_('0');
00435          while (ISDIGIT ((UCHAR_T) *f))
00436            argpos = argpos * 10 + ((UCHAR_T) *f++ - L_('0'));
00437          if (*f == L_('$'))
00438            ++f;
00439          else
00440            {
00441              /* Oops; that was actually the field width.  */
00442              width = argpos;
00443              argpos = 0;
00444              goto got_width;
00445            }
00446        }
00447 
00448       /* Check for the assignment-suppressing, the number grouping flag,
00449         and the signal to use the locale's digit representation.  */
00450       while (*f == L_('*') || *f == L_('\'') || *f == L_('I'))
00451        switch (*f++)
00452          {
00453          case L_('*'):
00454            flags |= SUPPRESS;
00455            break;
00456          case L_('\''):
00457 #ifdef COMPILE_WSCANF
00458            if (thousands != L'\0')
00459 #else
00460            if (thousands != NULL)
00461 #endif
00462              flags |= GROUP;
00463            break;
00464          case L_('I'):
00465            flags |= I18N;
00466            break;
00467          }
00468 
00469       /* Find the maximum field width.  */
00470       width = 0;
00471       while (ISDIGIT ((UCHAR_T) *f))
00472        {
00473          width *= 10;
00474          width += (UCHAR_T) *f++ - L_('0');
00475        }
00476     got_width:
00477       if (width == 0)
00478        width = -1;
00479 
00480       /* Check for type modifiers.  */
00481       switch (*f++)
00482        {
00483        case L_('h'):
00484          /* ints are short ints or chars.  */
00485          if (*f == L_('h'))
00486            {
00487              ++f;
00488              flags |= CHAR;
00489            }
00490          else
00491            flags |= SHORT;
00492          break;
00493        case L_('l'):
00494          if (*f == L_('l'))
00495            {
00496              /* A double `l' is equivalent to an `L'.  */
00497              ++f;
00498              flags |= LONGDBL | LONG;
00499            }
00500          else
00501            /* ints are long ints.  */
00502            flags |= LONG;
00503          break;
00504        case L_('q'):
00505        case L_('L'):
00506          /* doubles are long doubles, and ints are long long ints.  */
00507          flags |= LONGDBL | LONG;
00508          break;
00509        case L_('a'):
00510          /* The `a' is used as a flag only if followed by `s', `S' or
00511             `['.  */
00512          if (*f != L_('s') && *f != L_('S') && *f != L_('['))
00513            {
00514              --f;
00515              break;
00516            }
00517          /* In __isoc99_*scanf %as, %aS and %a[ extension is not
00518             supported at all.  */
00519          if (s->_flags2 & _IO_FLAGS2_SCANF_STD)
00520            {
00521              --f;
00522              break;
00523            }
00524          /* String conversions (%s, %[) take a `char **'
00525             arg and fill it in with a malloc'd pointer.  */
00526          flags |= GNU_MALLOC;
00527          break;
00528        case L_('m'):
00529          flags |= POSIX_MALLOC;
00530          if (*f == L_('l'))
00531            {
00532              ++f;
00533              flags |= LONG;
00534            }
00535          break;
00536        case L_('z'):
00537          if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
00538            flags |= LONGDBL;
00539          else if (sizeof (size_t) > sizeof (unsigned int))
00540            flags |= LONG;
00541          break;
00542        case L_('j'):
00543          if (need_longlong && sizeof (uintmax_t) > sizeof (unsigned long int))
00544            flags |= LONGDBL;
00545          else if (sizeof (uintmax_t) > sizeof (unsigned int))
00546            flags |= LONG;
00547          break;
00548        case L_('t'):
00549          if (need_longlong && sizeof (ptrdiff_t) > sizeof (long int))
00550            flags |= LONGDBL;
00551          else if (sizeof (ptrdiff_t) > sizeof (int))
00552            flags |= LONG;
00553          break;
00554        default:
00555          /* Not a recognized modifier.  Backup.  */
00556          --f;
00557          break;
00558        }
00559 
00560       /* End of the format string?  */
00561       if (__builtin_expect (*f == L_('\0'), 0))
00562        conv_error ();
00563 
00564       /* Find the conversion specifier.  */
00565       fc = *f++;
00566       if (skip_space || (fc != L_('[') && fc != L_('c')
00567                       && fc != L_('C') && fc != L_('n')))
00568        {
00569          /* Eat whitespace.  */
00570          int save_errno = errno;
00571          __set_errno (0);
00572          do
00573            /* We add the additional test for EOF here since otherwise
00574               inchar will restore the old errno value which might be
00575               EINTR but does not indicate an interrupt since nothing
00576               was read at this time.  */
00577            if (__builtin_expect ((c == EOF || inchar () == EOF)
00578                               && errno == EINTR, 0))
00579              input_error ();
00580          while (ISSPACE (c));
00581          __set_errno (save_errno);
00582          ungetc (c, s);
00583          skip_space = 0;
00584        }
00585 
00586       switch (fc)
00587        {
00588        case L_('%'): /* Must match a literal '%'.  */
00589          c = inchar ();
00590          if (__builtin_expect (c == EOF, 0))
00591            input_error ();
00592          if (__builtin_expect (c != fc, 0))
00593            {
00594              ungetc_not_eof (c, s);
00595              conv_error ();
00596            }
00597          break;
00598 
00599        case L_('n'): /* Answer number of assignments done.  */
00600          /* Corrigendum 1 to ISO C 1990 describes the allowed flags
00601             with the 'n' conversion specifier.  */
00602          if (!(flags & SUPPRESS))
00603            {
00604              /* Don't count the read-ahead.  */
00605              if (need_longlong && (flags & LONGDBL))
00606               *ARG (long long int *) = read_in;
00607              else if (need_long && (flags & LONG))
00608               *ARG (long int *) = read_in;
00609              else if (flags & SHORT)
00610               *ARG (short int *) = read_in;
00611              else if (!(flags & CHAR))
00612               *ARG (int *) = read_in;
00613              else
00614               *ARG (char *) = read_in;
00615 
00616 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
00617              /* We have a severe problem here.  The ISO C standard
00618                contradicts itself in explaining the effect of the %n
00619                format in `scanf'.  While in ISO C:1990 and the ISO C
00620                Amendement 1:1995 the result is described as
00621 
00622                  Execution of a %n directive does not effect the
00623                  assignment count returned at the completion of
00624                  execution of the f(w)scanf function.
00625 
00626                in ISO C Corrigendum 1:1994 the following was added:
00627 
00628                  Subclause 7.9.6.2
00629                  Add the following fourth example:
00630                    In:
00631                      #include <stdio.h>
00632                      int d1, d2, n1, n2, i;
00633                      i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
00634                    the value 123 is assigned to d1 and the value3 to n1.
00635                    Because %n can never get an input failure the value
00636                    of 3 is also assigned to n2.  The value of d2 is not
00637                    affected.  The value 3 is assigned to i.
00638 
00639                We go for now with the historically correct code from ISO C,
00640                i.e., we don't count the %n assignments.  When it ever
00641                should proof to be wrong just remove the #ifdef above.  */
00642              ++done;
00643 #endif
00644            }
00645          break;
00646 
00647        case L_('c'): /* Match characters.  */
00648          if ((flags & LONG) == 0)
00649            {
00650              if (width == -1)
00651               width = 1;
00652 
00653 #define STRING_ARG(Str, Type, Width)                                        \
00654              do if (!(flags & SUPPRESS))                             \
00655               {                                                      \
00656                 if (flags & MALLOC)                                         \
00657                   {                                                  \
00658                     /* The string is to be stored in a malloc'd buffer.  */ \
00659                     /* For %mS using char ** is actually wrong, but         \
00660                       shouldn't make a difference on any arch glibc         \
00661                       supports and would unnecessarily complicate           \
00662                       things. */                                     \
00663                     strptr = ARG (char **);                                 \
00664                     if (strptr == NULL)                              \
00665                      conv_error ();                                         \
00666                     /* Allocate an initial buffer.  */               \
00667                     strsize = Width;                                        \
00668                     *strptr = (char *) malloc (strsize * sizeof (Type));    \
00669                     Str = (Type *) *strptr;                                 \
00670                     if (Str != NULL)                                        \
00671                      add_ptr_to_free (strptr);                       \
00672                     else if (flags & POSIX_MALLOC)                          \
00673                      goto reteof;                                    \
00674                   }                                                  \
00675                 else                                                 \
00676                   Str = ARG (Type *);                                       \
00677                 if (Str == NULL)                                     \
00678                   conv_error ();                                     \
00679               } while (0)
00680 #ifdef COMPILE_WSCANF
00681              STRING_ARG (str, char, 100);
00682 #else
00683              STRING_ARG (str, char, (width > 1024 ? 1024 : width));
00684 #endif
00685 
00686              c = inchar ();
00687              if (__builtin_expect (c == EOF, 0))
00688               input_error ();
00689 
00690 #ifdef COMPILE_WSCANF
00691              /* We have to convert the wide character(s) into multibyte
00692                characters and store the result.  */
00693              memset (&state, '\0', sizeof (state));
00694 
00695              do
00696               {
00697                 size_t n;
00698 
00699                 if (!(flags & SUPPRESS) && (flags & POSIX_MALLOC)
00700                     && str + MB_CUR_MAX >= *strptr + strsize)
00701                   {
00702                     /* We have to enlarge the buffer if the `m' flag
00703                       was given.  */
00704                     size_t strleng = str - *strptr;
00705                     char *newstr;
00706 
00707                     newstr = (char *) realloc (*strptr, strsize * 2);
00708                     if (newstr == NULL)
00709                      {
00710                        /* Can't allocate that much.  Last-ditch effort.  */
00711                        newstr = (char *) realloc (*strptr,
00712                                                strleng + MB_CUR_MAX);
00713                        if (newstr == NULL)
00714                          /* c can't have `a' flag, only `m'.  */
00715                          goto reteof;
00716                        else
00717                          {
00718                            *strptr = newstr;
00719                            str = newstr + strleng;
00720                            strsize = strleng + MB_CUR_MAX;
00721                          }
00722                      }
00723                     else
00724                      {
00725                        *strptr = newstr;
00726                        str = newstr + strleng;
00727                        strsize *= 2;
00728                      }
00729                   }
00730 
00731                 n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
00732                 if (__builtin_expect (n == (size_t) -1, 0))
00733                   /* No valid wide character.  */
00734                   input_error ();
00735 
00736                 /* Increment the output pointer.  Even if we don't
00737                    write anything.  */
00738                 str += n;
00739               }
00740              while (--width > 0 && inchar () != EOF);
00741 #else
00742              if (!(flags & SUPPRESS))
00743               {
00744                 do
00745                   {
00746                     if ((flags & MALLOC)
00747                        && (char *) str == *strptr + strsize)
00748                      {
00749                        /* Enlarge the buffer.  */
00750                        size_t newsize
00751                          = strsize
00752                            + (strsize >= width ? width - 1 : strsize);
00753 
00754                        str = (char *) realloc (*strptr, newsize);
00755                        if (str == NULL)
00756                          {
00757                            /* Can't allocate that much.  Last-ditch
00758                              effort.  */
00759                            str = (char *) realloc (*strptr, strsize + 1);
00760                            if (str == NULL)
00761                             /* c can't have `a' flag, only `m'.  */
00762                             goto reteof;
00763                            else
00764                             {
00765                               *strptr = (char *) str;
00766                               str += strsize;
00767                               ++strsize;
00768                             }
00769                          }
00770                        else
00771                          {
00772                            *strptr = (char *) str;
00773                            str += strsize;
00774                            strsize = newsize;
00775                          }
00776                      }
00777                     *str++ = c;
00778                   }
00779                 while (--width > 0 && inchar () != EOF);
00780               }
00781              else
00782               while (--width > 0 && inchar () != EOF);
00783 #endif
00784 
00785              if (!(flags & SUPPRESS))
00786               {
00787                 if ((flags & MALLOC) && str - *strptr != strsize)
00788                   {
00789                     char *cp = (char *) realloc (*strptr, str - *strptr);
00790                     if (cp != NULL)
00791                      *strptr = cp;
00792                   }
00793                 strptr = NULL;
00794                 ++done;
00795               }
00796 
00797              break;
00798            }
00799          /* FALLTHROUGH */
00800        case L_('C'):
00801          if (width == -1)
00802            width = 1;
00803 
00804          STRING_ARG (wstr, wchar_t, (width > 1024 ? 1024 : width));
00805 
00806          c = inchar ();
00807          if (__builtin_expect (c == EOF, 0))
00808            input_error ();
00809 
00810 #ifdef COMPILE_WSCANF
00811          /* Just store the incoming wide characters.  */
00812          if (!(flags & SUPPRESS))
00813            {
00814              do
00815               {
00816                 if ((flags & MALLOC)
00817                     && wstr == (wchar_t *) *strptr + strsize)
00818                   {
00819                     size_t newsize
00820                      = strsize + (strsize > width ? width - 1 : strsize);
00821                     /* Enlarge the buffer.  */
00822                     wstr = (wchar_t *) realloc (*strptr,
00823                                             newsize * sizeof (wchar_t));
00824                     if (wstr == NULL)
00825                      {
00826                        /* Can't allocate that much.  Last-ditch effort.  */
00827                        wstr = (wchar_t *) realloc (*strptr,
00828                                                 (strsize + 1)
00829                                                 * sizeof (wchar_t));
00830                        if (wstr == NULL)
00831                          /* C or lc can't have `a' flag, only `m' flag.  */
00832                          goto reteof;
00833                        else
00834                          {
00835                            *strptr = (char *) wstr;
00836                            wstr += strsize;
00837                            ++strsize;
00838                          }
00839                      }
00840                     else
00841                      {
00842                        *strptr = (char *) wstr;
00843                        wstr += strsize;
00844                        strsize = newsize;
00845                      }
00846                   }
00847                 *wstr++ = c;
00848               }
00849              while (--width > 0 && inchar () != EOF);
00850            }
00851          else
00852            while (--width > 0 && inchar () != EOF);
00853 #else
00854          {
00855            /* We have to convert the multibyte input sequence to wide
00856               characters.  */
00857            char buf[1];
00858            mbstate_t cstate;
00859 
00860            memset (&cstate, '\0', sizeof (cstate));
00861 
00862            do
00863              {
00864               /* This is what we present the mbrtowc function first.  */
00865               buf[0] = c;
00866 
00867               if (!(flags & SUPPRESS) && (flags & MALLOC)
00868                   && wstr == (wchar_t *) *strptr + strsize)
00869                 {
00870                   size_t newsize
00871                     = strsize + (strsize > width ? width - 1 : strsize);
00872                   /* Enlarge the buffer.  */
00873                   wstr = (wchar_t *) realloc (*strptr,
00874                                           newsize * sizeof (wchar_t));
00875                   if (wstr == NULL)
00876                     {
00877                      /* Can't allocate that much.  Last-ditch effort.  */
00878                      wstr = (wchar_t *) realloc (*strptr,
00879                                               ((strsize + 1)
00880                                                * sizeof (wchar_t)));
00881                      if (wstr == NULL)
00882                        /* C or lc can't have `a' flag, only `m' flag.  */
00883                        goto reteof;
00884                      else
00885                        {
00886                          *strptr = (char *) wstr;
00887                          wstr += strsize;
00888                          ++strsize;
00889                        }
00890                     }
00891                   else
00892                     {
00893                      *strptr = (char *) wstr;
00894                      wstr += strsize;
00895                      strsize = newsize;
00896                     }
00897                 }
00898 
00899               while (1)
00900                 {
00901                   size_t n;
00902 
00903                   n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
00904                                buf, 1, &cstate);
00905 
00906                   if (n == (size_t) -2)
00907                     {
00908                      /* Possibly correct character, just not enough
00909                         input.  */
00910                      if (__builtin_expect (inchar () == EOF, 0))
00911                        encode_error ();
00912 
00913                      buf[0] = c;
00914                      continue;
00915                     }
00916 
00917                   if (__builtin_expect (n != 1, 0))
00918                     encode_error ();
00919 
00920                   /* We have a match.  */
00921                   break;
00922                 }
00923 
00924               /* Advance the result pointer.  */
00925               ++wstr;
00926              }
00927            while (--width > 0 && inchar () != EOF);
00928          }
00929 #endif
00930 
00931          if (!(flags & SUPPRESS))
00932            {
00933              if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
00934               {
00935                 wchar_t *cp = (wchar_t *) realloc (*strptr,
00936                                                ((wstr
00937                                                  - (wchar_t *) *strptr)
00938                                                 * sizeof (wchar_t)));
00939                 if (cp != NULL)
00940                   *strptr = (char *) cp;
00941               }
00942              strptr = NULL;
00943 
00944              ++done;
00945            }
00946 
00947          break;
00948 
00949        case L_('s'):        /* Read a string.  */
00950          if (!(flags & LONG))
00951            {
00952              STRING_ARG (str, char, 100);
00953 
00954              c = inchar ();
00955              if (__builtin_expect (c == EOF, 0))
00956               input_error ();
00957 
00958 #ifdef COMPILE_WSCANF
00959              memset (&state, '\0', sizeof (state));
00960 #endif
00961 
00962              do
00963               {
00964                 if (ISSPACE (c))
00965                   {
00966                     ungetc_not_eof (c, s);
00967                     break;
00968                   }
00969 
00970 #ifdef COMPILE_WSCANF
00971                 /* This is quite complicated.  We have to convert the
00972                    wide characters into multibyte characters and then
00973                    store them.  */
00974                 {
00975                   size_t n;
00976 
00977                   if (!(flags & SUPPRESS) && (flags & MALLOC)
00978                      && str + MB_CUR_MAX >= *strptr + strsize)
00979                     {
00980                      /* We have to enlarge the buffer if the `a' or `m'
00981                         flag was given.  */
00982                      size_t strleng = str - *strptr;
00983                      char *newstr;
00984 
00985                      newstr = (char *) realloc (*strptr, strsize * 2);
00986                      if (newstr == NULL)
00987                        {
00988                          /* Can't allocate that much.  Last-ditch
00989                             effort.  */
00990                          newstr = (char *) realloc (*strptr,
00991                                                  strleng + MB_CUR_MAX);
00992                          if (newstr == NULL)
00993                            {
00994                             if (flags & POSIX_MALLOC)
00995                               goto reteof;
00996                             /* We lose.  Oh well.  Terminate the
00997                                string and stop converting,
00998                                so at least we don't skip any input.  */
00999                             ((char *) (*strptr))[strleng] = '\0';
01000                             strptr = NULL;
01001                             ++done;
01002                             conv_error ();
01003                            }
01004                          else
01005                            {
01006                             *strptr = newstr;
01007                             str = newstr + strleng;
01008                             strsize = strleng + MB_CUR_MAX;
01009                            }
01010                        }
01011                      else
01012                        {
01013                          *strptr = newstr;
01014                          str = newstr + strleng;
01015                          strsize *= 2;
01016                        }
01017                     }
01018 
01019                   n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c,
01020                                &state);
01021                   if (__builtin_expect (n == (size_t) -1, 0))
01022                     encode_error ();
01023 
01024                   assert (n <= MB_CUR_MAX);
01025                   str += n;
01026                 }
01027 #else
01028                 /* This is easy.  */
01029                 if (!(flags & SUPPRESS))
01030                   {
01031                     *str++ = c;
01032                     if ((flags & MALLOC)
01033                        && (char *) str == *strptr + strsize)
01034                      {
01035                        /* Enlarge the buffer.  */
01036                        str = (char *) realloc (*strptr, 2 * strsize);
01037                        if (str == NULL)
01038                          {
01039                            /* Can't allocate that much.  Last-ditch
01040                              effort.  */
01041                            str = (char *) realloc (*strptr, strsize + 1);
01042                            if (str == NULL)
01043                             {
01044                               if (flags & POSIX_MALLOC)
01045                                 goto reteof;
01046                               /* We lose.  Oh well.  Terminate the
01047                                  string and stop converting,
01048                                  so at least we don't skip any input.  */
01049                               ((char *) (*strptr))[strsize - 1] = '\0';
01050                               strptr = NULL;
01051                               ++done;
01052                               conv_error ();
01053                             }
01054                            else
01055                             {
01056                               *strptr = (char *) str;
01057                               str += strsize;
01058                               ++strsize;
01059                             }
01060                          }
01061                        else
01062                          {
01063                            *strptr = (char *) str;
01064                            str += strsize;
01065                            strsize *= 2;
01066                          }
01067                      }
01068                   }
01069 #endif
01070               }
01071              while ((width <= 0 || --width > 0) && inchar () != EOF);
01072 
01073              if (!(flags & SUPPRESS))
01074               {
01075 #ifdef COMPILE_WSCANF
01076                 /* We have to emit the code to get into the initial
01077                    state.  */
01078                 char buf[MB_LEN_MAX];
01079                 size_t n = __wcrtomb (buf, L'\0', &state);
01080                 if (n > 0 && (flags & MALLOC)
01081                     && str + n >= *strptr + strsize)
01082                   {
01083                     /* Enlarge the buffer.  */
01084                     size_t strleng = str - *strptr;
01085                     char *newstr;
01086 
01087                     newstr = (char *) realloc (*strptr, strleng + n + 1);
01088                     if (newstr == NULL)
01089                      {
01090                        if (flags & POSIX_MALLOC)
01091                          goto reteof;
01092                        /* We lose.  Oh well.  Terminate the string
01093                           and stop converting, so at least we don't
01094                           skip any input.  */
01095                        ((char *) (*strptr))[strleng] = '\0';
01096                        strptr = NULL;
01097                        ++done;
01098                        conv_error ();
01099                      }
01100                     else
01101                      {
01102                        *strptr = newstr;
01103                        str = newstr + strleng;
01104                        strsize = strleng + n + 1;
01105                      }
01106                   }
01107 
01108                 str = __mempcpy (str, buf, n);
01109 #endif
01110                 *str++ = '\0';
01111 
01112                 if ((flags & MALLOC) && str - *strptr != strsize)
01113                   {
01114                     char *cp = (char *) realloc (*strptr, str - *strptr);
01115                     if (cp != NULL)
01116                      *strptr = cp;
01117                   }
01118                 strptr = NULL;
01119 
01120                 ++done;
01121               }
01122              break;
01123            }
01124          /* FALLTHROUGH */
01125 
01126        case L_('S'):
01127          {
01128 #ifndef COMPILE_WSCANF
01129            mbstate_t cstate;
01130 #endif
01131 
01132            /* Wide character string.  */
01133            STRING_ARG (wstr, wchar_t, 100);
01134 
01135            c = inchar ();
01136            if (__builtin_expect (c == EOF,  0))
01137              input_error ();
01138 
01139 #ifndef COMPILE_WSCANF
01140            memset (&cstate, '\0', sizeof (cstate));
01141 #endif
01142 
01143            do
01144              {
01145               if (ISSPACE (c))
01146                 {
01147                   ungetc_not_eof (c, s);
01148                   break;
01149                 }
01150 
01151 #ifdef COMPILE_WSCANF
01152               /* This is easy.  */
01153               if (!(flags & SUPPRESS))
01154                 {
01155                   *wstr++ = c;
01156                   if ((flags & MALLOC)
01157                      && wstr == (wchar_t *) *strptr + strsize)
01158                     {
01159                      /* Enlarge the buffer.  */
01160                      wstr = (wchar_t *) realloc (*strptr,
01161                                               (2 * strsize)
01162                                               * sizeof (wchar_t));
01163                      if (wstr == NULL)
01164                        {
01165                          /* Can't allocate that much.  Last-ditch
01166                             effort.  */
01167                          wstr = (wchar_t *) realloc (*strptr,
01168                                                  (strsize + 1)
01169                                                  * sizeof (wchar_t));
01170                          if (wstr == NULL)
01171                            {
01172                             if (flags & POSIX_MALLOC)
01173                               goto reteof;
01174                             /* We lose.  Oh well.  Terminate the string
01175                                and stop converting, so at least we don't
01176                                skip any input.  */
01177                             ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
01178                             strptr = NULL;
01179                             ++done;
01180                             conv_error ();
01181                            }
01182                          else
01183                            {
01184                             *strptr = (char *) wstr;
01185                             wstr += strsize;
01186                             ++strsize;
01187                            }
01188                        }
01189                      else
01190                        {
01191                          *strptr = (char *) wstr;
01192                          wstr += strsize;
01193                          strsize *= 2;
01194                        }
01195                     }
01196                 }
01197 #else
01198               {
01199                 char buf[1];
01200 
01201                 buf[0] = c;
01202 
01203                 while (1)
01204                   {
01205                     size_t n;
01206 
01207                     n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
01208                                  buf, 1, &cstate);
01209 
01210                     if (n == (size_t) -2)
01211                      {
01212                        /* Possibly correct character, just not enough
01213                           input.  */
01214                        if (__builtin_expect (inchar () == EOF, 0))
01215                          encode_error ();
01216 
01217                        buf[0] = c;
01218                        continue;
01219                      }
01220 
01221                     if (__builtin_expect (n != 1, 0))
01222                      encode_error ();
01223 
01224                     /* We have a match.  */
01225                     ++wstr;
01226                     break;
01227                   }
01228 
01229                 if (!(flags & SUPPRESS) && (flags & MALLOC)
01230                     && wstr == (wchar_t *) *strptr + strsize)
01231                   {
01232                     /* Enlarge the buffer.  */
01233                     wstr = (wchar_t *) realloc (*strptr,
01234                                             (2 * strsize
01235                                              * sizeof (wchar_t)));
01236                     if (wstr == NULL)
01237                      {
01238                        /* Can't allocate that much.  Last-ditch effort.  */
01239                        wstr = (wchar_t *) realloc (*strptr,
01240                                                 ((strsize + 1)
01241                                                  * sizeof (wchar_t)));
01242                        if (wstr == NULL)
01243                          {
01244                            if (flags & POSIX_MALLOC)
01245                             goto reteof;
01246                            /* We lose.  Oh well.  Terminate the
01247                              string and stop converting, so at
01248                              least we don't skip any input.  */
01249                            ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
01250                            strptr = NULL;
01251                            ++done;
01252                            conv_error ();
01253                          }
01254                        else
01255                          {
01256                            *strptr = (char *) wstr;
01257                            wstr += strsize;
01258                            ++strsize;
01259                          }
01260                      }
01261                     else
01262                      {
01263                        *strptr = (char *) wstr;
01264                        wstr += strsize;
01265                        strsize *= 2;
01266                      }
01267                   }
01268               }
01269 #endif
01270              }
01271            while ((width <= 0 || --width > 0) && inchar () != EOF);
01272 
01273            if (!(flags & SUPPRESS))
01274              {
01275               *wstr++ = L'\0';
01276 
01277               if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
01278                 {
01279                   wchar_t *cp = (wchar_t *) realloc (*strptr,
01280                                                  ((wstr
01281                                                   - (wchar_t *) *strptr)
01282                                                  * sizeof(wchar_t)));
01283                   if (cp != NULL)
01284                     *strptr = (char *) cp;
01285                 }
01286               strptr = NULL;
01287 
01288               ++done;
01289              }
01290          }
01291          break;
01292 
01293        case L_('x'): /* Hexadecimal integer.  */
01294        case L_('X'): /* Ditto.  */
01295          base = 16;
01296          goto number;
01297 
01298        case L_('o'): /* Octal integer.  */
01299          base = 8;
01300          goto number;
01301 
01302        case L_('u'): /* Unsigned decimal integer.  */
01303          base = 10;
01304          goto number;
01305 
01306        case L_('d'): /* Signed decimal integer.  */
01307          base = 10;
01308          flags |= NUMBER_SIGNED;
01309          goto number;
01310 
01311        case L_('i'): /* Generic number.  */
01312          base = 0;
01313          flags |= NUMBER_SIGNED;
01314 
01315        number:
01316          c = inchar ();
01317          if (__builtin_expect (c == EOF, 0))
01318            input_error ();
01319 
01320          /* Check for a sign.  */
01321          if (c == L_('-') || c == L_('+'))
01322            {
01323              ADDW (c);
01324              if (width > 0)
01325               --width;
01326              c = inchar ();
01327            }
01328 
01329          /* Look for a leading indication of base.  */
01330          if (width != 0 && c == L_('0'))
01331            {
01332              if (width > 0)
01333               --width;
01334 
01335              ADDW (c);
01336              c = inchar ();
01337 
01338              if (width != 0 && TOLOWER (c) == L_('x'))
01339               {
01340                 if (base == 0)
01341                   base = 16;
01342                 if (base == 16)
01343                   {
01344                     if (width > 0)
01345                      --width;
01346                     c = inchar ();
01347                   }
01348               }
01349              else if (base == 0)
01350               base = 8;
01351            }
01352 
01353          if (base == 0)
01354            base = 10;
01355 
01356          if (base == 10 && __builtin_expect ((flags & I18N) != 0, 0))
01357            {
01358              int from_level;
01359              int to_level;
01360              int level;
01361 #ifdef COMPILE_WSCANF
01362              const wchar_t *wcdigits[10];
01363              const wchar_t *wcdigits_extended[10];
01364 #else
01365              const char *mbdigits[10];
01366              const char *mbdigits_extended[10];
01367 #endif
01368              /*  "to_inpunct" is a map from ASCII digits to their
01369                 equivalent in locale. This is defined for locales
01370                 which use an extra digits set.  */
01371              wctrans_t map = __wctrans ("to_inpunct");
01372              int n;
01373 
01374              from_level = 0;
01375 #ifdef COMPILE_WSCANF
01376              to_level = _NL_CURRENT_WORD (LC_CTYPE,
01377                                       _NL_CTYPE_INDIGITS_WC_LEN) - 1;
01378 #else
01379              to_level = (uint32_t) curctype->values[_NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_MB_LEN)].word - 1;
01380 #endif
01381 
01382              /* Get the alternative digit forms if there are any.  */
01383              if (__builtin_expect (map != NULL, 0))
01384               {
01385                 /*  Adding new level for extra digits set in locale file.  */
01386                 ++to_level;
01387 
01388                 for (n = 0; n < 10; ++n)
01389                   {
01390 #ifdef COMPILE_WSCANF
01391                     wcdigits[n] = (const wchar_t *)
01392                         _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
01393 
01394                     wchar_t *wc_extended = (wchar_t *)
01395                      alloca ((to_level + 2) * sizeof (wchar_t));
01396                     __wmemcpy (wc_extended, wcdigits[n], to_level);
01397                     wc_extended[to_level] = __towctrans (L'0' + n, map);
01398                     wc_extended[to_level + 1] = '\0';
01399                     wcdigits_extended[n] = wc_extended;
01400 #else
01401                     mbdigits[n]
01402                         = curctype->values[_NL_CTYPE_INDIGITS0_MB + n].string;
01403 
01404                     /*  Get the equivalent wide char in map.  */
01405                     wint_t extra_wcdigit = __towctrans (L'0' + n, map);
01406 
01407                     /*  Convert it to multibyte representation.  */
01408                     mbstate_t state;
01409                     memset (&state, '\0', sizeof (state));
01410 
01411                     char extra_mbdigit[MB_LEN_MAX];
01412                     size_t mblen
01413                      = __wcrtomb (extra_mbdigit, extra_wcdigit, &state);
01414 
01415                     if (mblen == (size_t) -1)
01416                      {
01417                        /*  Ignore this new level.  */
01418                        map = NULL;
01419                        break;
01420                      }
01421 
01422                     /*  Calculate the length of mbdigits[n].  */
01423                     const char *last_char = mbdigits[n];
01424                     for (level = 0; level < to_level; ++level)
01425                      last_char = strchr (last_char, '\0') + 1;
01426 
01427                     size_t mbdigits_len = last_char - mbdigits[n];
01428 
01429                     /*  Allocate memory for extended multibyte digit.  */
01430                     char *mb_extended;
01431                     mb_extended = (char *) alloca (mbdigits_len + mblen + 1);
01432 
01433                     /*  And get the mbdigits + extra_digit string.  */
01434                     *(char *) __mempcpy (__mempcpy (mb_extended, mbdigits[n],
01435                                                 mbdigits_len),
01436                                       extra_mbdigit, mblen) = '\0';
01437                     mbdigits_extended[n] = mb_extended;
01438 #endif
01439                   }
01440               }
01441 
01442              /* Read the number into workspace.  */
01443              while (c != EOF && width != 0)
01444               {
01445                 /* In this round we get the pointer to the digit strings
01446                    and also perform the first round of comparisons.  */
01447                 for (n = 0; n < 10; ++n)
01448                   {
01449                     /* Get the string for the digits with value N.  */
01450 #ifdef COMPILE_WSCANF
01451                     if (__builtin_expect (map != NULL, 0))
01452                      wcdigits[n] = wcdigits_extended[n];
01453                     else
01454                      wcdigits[n] = (const wchar_t *)
01455                        _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
01456                     wcdigits[n] += from_level;
01457 
01458                     if (c == (wint_t) *wcdigits[n])
01459                      {
01460                        to_level = from_level;
01461                        break;
01462                      }
01463 
01464                     /* Advance the pointer to the next string.  */
01465                     ++wcdigits[n];
01466 #else
01467                     const char *cmpp;
01468                     int avail = width > 0 ? width : INT_MAX;
01469 
01470                     if (__builtin_expect (map != NULL, 0))
01471                      mbdigits[n] = mbdigits_extended[n];
01472                     else
01473                      mbdigits[n]
01474                        = curctype->values[_NL_CTYPE_INDIGITS0_MB + n].string;
01475 
01476                     for (level = 0; level < from_level; level++)
01477                      mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
01478 
01479                     cmpp = mbdigits[n];
01480                     while ((unsigned char) *cmpp == c && avail >= 0)
01481                      {
01482                        if (*++cmpp == '\0')
01483                          break;
01484                        else
01485                          {
01486                            if (avail == 0 || inchar () == EOF)
01487                             break;
01488                            --avail;
01489                          }
01490                      }
01491 
01492                     if (*cmpp == '\0')
01493                      {
01494                        if (width > 0)
01495                          width = avail;
01496                        to_level = from_level;
01497                        break;
01498                      }
01499 
01500                     /* We are pushing all read characters back.  */
01501                     if (cmpp > mbdigits[n])
01502                      {
01503                        ungetc (c, s);
01504                        while (--cmpp > mbdigits[n])
01505                          ungetc_not_eof ((unsigned char) *cmpp, s);
01506                        c = (unsigned char) *cmpp;
01507                      }
01508 
01509                     /* Advance the pointer to the next string.  */
01510                     mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
01511 #endif
01512                   }
01513 
01514                 if (n == 10)
01515                   {
01516                     /* Have not yet found the digit.  */
01517                     for (level = from_level + 1; level <= to_level; ++level)
01518                      {
01519                        /* Search all ten digits of this level.  */
01520                        for (n = 0; n < 10; ++n)
01521                          {
01522 #ifdef COMPILE_WSCANF
01523                            if (c == (wint_t) *wcdigits[n])
01524                             break;
01525 
01526                            /* Advance the pointer to the next string.  */
01527                            ++wcdigits[n];
01528 #else
01529                            const char *cmpp;
01530                            int avail = width > 0 ? width : INT_MAX;
01531 
01532                            cmpp = mbdigits[n];
01533                            while ((unsigned char) *cmpp == c && avail >= 0)
01534                             {
01535                               if (*++cmpp == '\0')
01536                                 break;
01537                               else
01538                                 {
01539                                   if (avail == 0 || inchar () == EOF)
01540                                    break;
01541                                   --avail;
01542                                 }
01543                             }
01544 
01545                            if (*cmpp == '\0')
01546                             {
01547                               if (width > 0)
01548                                 width = avail;
01549                               break;
01550                             }
01551 
01552                            /* We are pushing all read characters back.  */
01553                            if (cmpp > mbdigits[n])
01554                             {
01555                               ungetc (c, s);
01556                               while (--cmpp > mbdigits[n])
01557                                 ungetc_not_eof ((unsigned char) *cmpp, s);
01558                               c = (unsigned char) *cmpp;
01559                             }
01560 
01561                            /* Advance the pointer to the next string.  */
01562                            mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
01563 #endif
01564                          }
01565 
01566                        if (n < 10)
01567                          {
01568                            /* Found it.  */
01569                            from_level = level;
01570                            to_level = level;
01571                            break;
01572                          }
01573                      }
01574                   }
01575 
01576                 if (n < 10)
01577                   c = L_('0') + n;
01578                 else if (flags & GROUP)
01579                   {
01580                     /* Try matching against the thousands separator.  */
01581 #ifdef COMPILE_WSCANF
01582                     if (c != thousands)
01583                        break;
01584 #else
01585                     const char *cmpp = thousands;
01586                     int avail = width > 0 ? width : INT_MAX;
01587 
01588                     while ((unsigned char) *cmpp == c && avail >= 0)
01589                      {
01590                        ADDW (c);
01591                        if (*++cmpp == '\0')
01592                          break;
01593                        else
01594                          {
01595                            if (avail == 0 || inchar () == EOF)
01596                             break;
01597                            --avail;
01598                          }
01599                      }
01600 
01601                     if (*cmpp != '\0')
01602                      {
01603                        /* We are pushing all read characters back.  */
01604                        if (cmpp > thousands)
01605                          {
01606                            wpsize -= cmpp - thousands;
01607                            ungetc (c, s);
01608                            while (--cmpp > thousands)
01609                             ungetc_not_eof ((unsigned char) *cmpp, s);
01610                            c = (unsigned char) *cmpp;
01611                          }
01612                        break;
01613                      }
01614 
01615                     if (width > 0)
01616                      width = avail;
01617 
01618                     /* The last thousands character will be added back by
01619                       the ADDW below.  */
01620                      --wpsize;
01621 #endif
01622                   }
01623                 else
01624                   break;
01625 
01626                 ADDW (c);
01627                 if (width > 0)
01628                   --width;
01629 
01630                 c = inchar ();
01631               }
01632            }
01633          else
01634            /* Read the number into workspace.  */
01635            while (c != EOF && width != 0)
01636              {
01637               if (base == 16)
01638                 {
01639                   if (!ISXDIGIT (c))
01640                     break;
01641                 }
01642               else if (!ISDIGIT (c) || (int) (c - L_('0')) >= base)
01643                 {
01644                   if (base == 10 && (flags & GROUP))
01645                     {
01646                      /* Try matching against the thousands separator.  */
01647 #ifdef COMPILE_WSCANF
01648                      if (c != thousands)
01649                        break;
01650 #else
01651                      const char *cmpp = thousands;
01652                      int avail = width > 0 ? width : INT_MAX;
01653 
01654                      while ((unsigned char) *cmpp == c && avail >= 0)
01655                        {
01656                          ADDW (c);
01657                          if (*++cmpp == '\0')
01658                            break;
01659                          else
01660                            {
01661                             if (avail == 0 || inchar () == EOF)
01662                               break;
01663                             --avail;
01664                            }
01665                        }
01666 
01667                      if (*cmpp != '\0')
01668                        {
01669                          /* We are pushing all read characters back.  */
01670                          if (cmpp > thousands)
01671                            {
01672                             wpsize -= cmpp - thousands;
01673                             ungetc (c, s);
01674                             while (--cmpp > thousands)
01675                               ungetc_not_eof ((unsigned char) *cmpp, s);
01676                             c = (unsigned char) *cmpp;
01677                            }
01678                          break;
01679                        }
01680 
01681                      if (width > 0)
01682                        width = avail;
01683 
01684                      /* The last thousands character will be added back by
01685                         the ADDW below.  */
01686                      --wpsize;
01687 #endif
01688                     }
01689                   else
01690                     break;
01691                 }
01692               ADDW (c);
01693               if (width > 0)
01694                 --width;
01695 
01696               c = inchar ();
01697              }
01698 
01699          if (wpsize == 0
01700              || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
01701            {
01702              /* There was no number.  If we are supposed to read a pointer
01703                we must recognize "(nil)" as well.  */
01704              if (__builtin_expect (wpsize == 0
01705                                 && (flags & READ_POINTER)
01706                                 && (width < 0 || width >= 0)
01707                                 && c == '('
01708                                 && TOLOWER (inchar ()) == L_('n')
01709                                 && TOLOWER (inchar ()) == L_('i')
01710                                 && TOLOWER (inchar ()) == L_('l')
01711                                 && inchar () == L_(')'), 1))
01712               /* We must produce the value of a NULL pointer.  A single
01713                  '0' digit is enough.  */
01714               ADDW (L_('0'));
01715              else
01716               {
01717                 /* The last read character is not part of the number
01718                    anymore.  */
01719                 ungetc (c, s);
01720 
01721                 conv_error ();
01722               }
01723            }
01724          else
01725            /* The just read character is not part of the number anymore.  */
01726            ungetc (c, s);
01727 
01728          /* Convert the number.  */
01729          ADDW (L_('\0'));
01730          if (need_longlong && (flags & LONGDBL))
01731            {
01732              if (flags & NUMBER_SIGNED)
01733               num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
01734              else
01735               num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
01736            }
01737          else
01738            {
01739              if (flags & NUMBER_SIGNED)
01740               num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
01741              else
01742               num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
01743            }
01744          if (__builtin_expect (wp == tw, 0))
01745            conv_error ();
01746 
01747          if (!(flags & SUPPRESS))
01748            {
01749              if (flags & NUMBER_SIGNED)
01750               {
01751                 if (need_longlong && (flags & LONGDBL))
01752                   *ARG (LONGLONG int *) = num.q;
01753                 else if (need_long && (flags & LONG))
01754                   *ARG (long int *) = num.l;
01755                 else if (flags & SHORT)
01756                   *ARG (short int *) = (short int) num.l;
01757                 else if (!(flags & CHAR))
01758                   *ARG (int *) = (int) num.l;
01759                 else
01760                   *ARG (signed char *) = (signed char) num.ul;
01761               }
01762              else
01763               {
01764                 if (need_longlong && (flags & LONGDBL))
01765                   *ARG (unsigned LONGLONG int *) = num.uq;
01766                 else if (need_long && (flags & LONG))
01767                   *ARG (unsigned long int *) = num.ul;
01768                 else if (flags & SHORT)
01769                   *ARG (unsigned short int *)
01770                     = (unsigned short int) num.ul;
01771                 else if (!(flags & CHAR))
01772                   *ARG (unsigned int *) = (unsigned int) num.ul;
01773                 else
01774                   *ARG (unsigned char *) = (unsigned char) num.ul;
01775               }
01776              ++done;
01777            }
01778          break;
01779 
01780        case L_('e'): /* Floating-point numbers.  */
01781        case L_('E'):
01782        case L_('f'):
01783        case L_('F'):
01784        case L_('g'):
01785        case L_('G'):
01786        case L_('a'):
01787        case L_('A'):
01788          c = inchar ();
01789          if (width > 0)
01790            --width;
01791          if (__builtin_expect (c == EOF, 0))
01792            input_error ();
01793 
01794          got_dot = got_e = 0;
01795 
01796          /* Check for a sign.  */
01797          if (c == L_('-') || c == L_('+'))
01798            {
01799              negative = c == L_('-');
01800              if (__builtin_expect (width == 0 || inchar () == EOF, 0))
01801               /* EOF is only an input error before we read any chars.  */
01802               conv_error ();
01803              if (width > 0)
01804               --width;
01805            }
01806          else
01807            negative = 0;
01808 
01809          /* Take care for the special arguments "nan" and "inf".  */
01810          if (TOLOWER (c) == L_('n'))
01811            {
01812              /* Maybe "nan".  */
01813              ADDW (c);
01814              if (__builtin_expect (width == 0
01815                                 || inchar () == EOF
01816                                 || TOLOWER (c) != L_('a'), 0))
01817               conv_error ();
01818              if (width > 0)
01819               --width;
01820              ADDW (c);
01821              if (__builtin_expect (width == 0
01822                                 || inchar () == EOF
01823                                 || TOLOWER (c) != L_('n'), 0))
01824               conv_error ();
01825              if (width > 0)
01826               --width;
01827              ADDW (c);
01828              /* It is "nan".  */
01829              goto scan_float;
01830            }
01831          else if (TOLOWER (c) == L_('i'))
01832            {
01833              /* Maybe "inf" or "infinity".  */
01834              ADDW (c);
01835              if (__builtin_expect (width == 0
01836                                 || inchar () == EOF
01837                                 || TOLOWER (c) != L_('n'), 0))
01838               conv_error ();
01839              if (width > 0)
01840               --width;
01841              ADDW (c);
01842              if (__builtin_expect (width == 0
01843                                 || inchar () == EOF
01844                                 || TOLOWER (c) != L_('f'), 0))
01845               conv_error ();
01846              if (width > 0)
01847               --width;
01848              ADDW (c);
01849              /* It is as least "inf".  */
01850              if (width != 0 && inchar () != EOF)
01851               {
01852                 if (TOLOWER (c) == L_('i'))
01853                   {
01854                     if (width > 0)
01855                      --width;
01856                     /* Now we have to read the rest as well.  */
01857                     ADDW (c);
01858                     if (__builtin_expect (width == 0
01859                                        || inchar () == EOF
01860                                        || TOLOWER (c) != L_('n'), 0))
01861                      conv_error ();
01862                     if (width > 0)
01863                      --width;
01864                     ADDW (c);
01865                     if (__builtin_expect (width == 0
01866                                        || inchar () == EOF
01867                                        || TOLOWER (c) != L_('i'), 0))
01868                      conv_error ();
01869                     if (width > 0)
01870                      --width;
01871                     ADDW (c);
01872                     if (__builtin_expect (width == 0
01873                                        || inchar () == EOF
01874                                        || TOLOWER (c) != L_('t'), 0))
01875                      conv_error ();
01876                     if (width > 0)
01877                      --width;
01878                     ADDW (c);
01879                     if (__builtin_expect (width == 0
01880                                        || inchar () == EOF
01881                                        || TOLOWER (c) != L_('y'), 0))
01882                      conv_error ();
01883                     if (width > 0)
01884                      --width;
01885                     ADDW (c);
01886                   }
01887                 else
01888                   /* Never mind.  */
01889                   ungetc (c, s);
01890               }
01891              goto scan_float;
01892            }
01893 
01894          exp_char = L_('e');
01895          if (width != 0 && c == L_('0'))
01896            {
01897              ADDW (c);
01898              c = inchar ();
01899              if (width > 0)
01900               --width;
01901              if (width != 0 && TOLOWER (c) == L_('x'))
01902               {
01903                 /* It is a number in hexadecimal format.  */
01904                 ADDW (c);
01905 
01906                 flags |= HEXA_FLOAT;
01907                 exp_char = L_('p');
01908 
01909                 /* Grouping is not allowed.  */
01910                 flags &= ~GROUP;
01911                 c = inchar ();
01912                 if (width > 0)
01913                   --width;
01914               }
01915            }
01916 
01917          while (1)
01918            {
01919              if (ISDIGIT (c))
01920               ADDW (c);
01921              else if (!got_e && (flags & HEXA_FLOAT) && ISXDIGIT (c))
01922               ADDW (c);
01923              else if (got_e && wp[wpsize - 1] == exp_char
01924                      && (c == L_('-') || c == L_('+')))
01925               ADDW (c);
01926              else if (wpsize > 0 && !got_e
01927                      && (CHAR_T) TOLOWER (c) == exp_char)
01928               {
01929                 ADDW (exp_char);
01930                 got_e = got_dot = 1;
01931               }
01932              else
01933               {
01934 #ifdef COMPILE_WSCANF
01935                 if (! got_dot && c == decimal)
01936                   {
01937                     ADDW (c);
01938                     got_dot = 1;
01939                   }
01940                 else if ((flags & GROUP) != 0 && ! got_dot && c == thousands)
01941                   ADDW (c);
01942                 else
01943                   {
01944                     /* The last read character is not part of the number
01945                       anymore.  */
01946                     ungetc (c, s);
01947                     break;
01948                   }
01949 #else
01950                 const char *cmpp = decimal;
01951                 int avail = width > 0 ? width : INT_MAX;
01952 
01953                 if (! got_dot)
01954                   {
01955                     while ((unsigned char) *cmpp == c && avail >= 0)
01956                      if (*++cmpp == '\0')
01957                        break;
01958                      else
01959                        {
01960                          if (avail == 0 || inchar () == EOF)
01961                            break;
01962                          --avail;
01963                        }
01964                   }
01965 
01966                 if (*cmpp == '\0')
01967                   {
01968                     /* Add all the characters.  */
01969                     for (cmpp = decimal; *cmpp != '\0'; ++cmpp)
01970                      ADDW ((unsigned char) *cmpp);
01971                     if (width > 0)
01972                      width = avail;
01973                     got_dot = 1;
01974                   }
01975                 else
01976                   {
01977                     /* Figure out whether it is a thousands separator.
01978                       There is one problem: we possibly read more than
01979                       one character.  We cannot push them back but since
01980                       we know that parts of the `decimal' string matched,
01981                       we can compare against it.  */
01982                     const char *cmp2p = thousands;
01983 
01984                     if ((flags & GROUP) != 0 && ! got_dot)
01985                      {
01986                        while (cmp2p - thousands < cmpp - decimal
01987                              && *cmp2p == decimal[cmp2p - thousands])
01988                          ++cmp2p;
01989                        if (cmp2p - thousands == cmpp - decimal)
01990                          {
01991                            while ((unsigned char) *cmp2p == c && avail >= 0)
01992                             if (*++cmp2p == '\0')
01993                               break;
01994                             else
01995                               {
01996                                 if (avail == 0 || inchar () == EOF)
01997                                   break;
01998                                 --avail;
01999                               }
02000                          }
02001                      }
02002 
02003                     if (cmp2p != NULL && *cmp2p == '\0')
02004                      {
02005                        /* Add all the characters.  */
02006                        for (cmpp = thousands; *cmpp != '\0'; ++cmpp)
02007                          ADDW ((unsigned char) *cmpp);
02008                        if (width > 0)
02009                          width = avail;
02010                      }
02011                     else
02012                      {
02013                        /* The last read character is not part of the number
02014                           anymore.  */
02015                        ungetc (c, s);
02016                        break;
02017                      }
02018                   }
02019 #endif
02020               }
02021 
02022              if (width == 0 || inchar () == EOF)
02023               break;
02024 
02025              if (width > 0)
02026               --width;
02027            }
02028 
02029          wctrans_t map;
02030          if (__builtin_expect ((flags & I18N) != 0, 0)
02031              /* Hexadecimal floats make no sense, fixing localized
02032                digits with ASCII letters.  */
02033              && !(flags & HEXA_FLOAT)
02034              /* Minimum requirement.  */
02035              && (wpsize == 0 || got_dot)
02036              && (map = __wctrans ("to_inpunct")) != NULL)
02037            {
02038              /* Reget the first character.  */
02039              inchar ();
02040 
02041              /* Localized digits, decimal points, and thousands
02042                separator.  */
02043              wint_t wcdigits[12];
02044 
02045              /* First get decimal equivalent to check if we read it
02046                or not.  */
02047              wcdigits[11] = __towctrans (L'.', map);
02048 
02049              /* If we have not read any character or have just read
02050                 locale decimal point which matches the decimal point
02051                 for localized FP numbers, then we may have localized
02052                 digits.  Note, we test GOT_DOT above.  */
02053 #ifdef COMPILE_WSCANF
02054              if (wpsize == 0 || (wpsize == 1 && wcdigits[11] == decimal))
02055 #else
02056              char mbdigits[12][MB_LEN_MAX + 1];
02057 
02058              mbstate_t state;
02059              memset (&state, '\0', sizeof (state));
02060 
02061              bool match_so_far = wpsize == 0;
02062              size_t mblen = __wcrtomb (mbdigits[11], wcdigits[11], &state);
02063              if (mblen != (size_t) -1)
02064               {
02065                 mbdigits[11][mblen] = '\0';
02066                 match_so_far |= (wpsize == strlen (decimal)
02067                                && strcmp (decimal, mbdigits[11]) == 0);
02068               }
02069              else
02070               {
02071                 size_t decimal_len = strlen (decimal);
02072                 /* This should always be the case but the data comes
02073                    from a file.  */
02074                 if (decimal_len <= MB_LEN_MAX)
02075                   {
02076                     match_so_far |= wpsize == decimal_len;
02077                     memcpy (mbdigits[11], decimal, decimal_len + 1);
02078                   }
02079                 else
02080                   match_so_far = false;
02081               }
02082 
02083              if (match_so_far)
02084 #endif
02085               {
02086                 bool have_locthousands = (flags & GROUP) != 0;
02087 
02088                 /* Now get the digits and the thousands-sep equivalents.  */
02089                  for (int n = 0; n < 11; ++n)
02090                   {
02091                     if (n < 10)
02092                      wcdigits[n] = __towctrans (L'0' + n, map);
02093                     else if (n == 10)
02094                      {
02095                        wcdigits[10] = __towctrans (L',', map);
02096                        have_locthousands &= wcdigits[10] != L'\0';
02097                      }
02098 
02099 #ifndef COMPILE_WSCANF
02100                     memset (&state, '\0', sizeof (state));
02101 
02102                     size_t mblen = __wcrtomb (mbdigits[n], wcdigits[n],
02103                                           &state);
02104                     if (mblen == (size_t) -1)
02105                      {
02106                        if (n == 10)
02107                          {
02108                            if (have_locthousands)
02109                             {
02110                               size_t thousands_len = strlen (thousands);
02111                               if (thousands_len <= MB_LEN_MAX)
02112                                 memcpy (mbdigits[10], thousands,
02113                                        thousands_len + 1);
02114                               else
02115                                 have_locthousands = false;
02116                             }
02117                          }
02118                        else
02119                          /* Ignore checking against localized digits.  */
02120                          goto no_i18nflt;
02121                      }
02122                     else
02123                      mbdigits[n][mblen] = '\0';
02124 #endif
02125                   }
02126 
02127                 /* Start checking against localized digits, if
02128                    convertion is done correctly. */
02129                 while (1)
02130                   {
02131                     if (got_e && wp[wpsize - 1] == exp_char
02132                        && (c == L_('-') || c == L_('+')))
02133                      ADDW (c);
02134                     else if (wpsize > 0 && !got_e
02135                             && (CHAR_T) TOLOWER (c) == exp_char)
02136                      {
02137                        ADDW (exp_char);
02138                        got_e = got_dot = 1;
02139                      }
02140                     else
02141                      {
02142                        /* Check against localized digits, decimal point,
02143                           and thousands separator.  */
02144                        int n;
02145                        for (n = 0; n < 12; ++n)
02146                          {
02147 #ifdef COMPILE_WSCANF
02148                            if (c == wcdigits[n])
02149                             {
02150                               if (n < 10)
02151                                 ADDW (L_('0') + n);
02152                               else if (n == 11 && !got_dot)
02153                                 {
02154                                   ADDW (decimal);
02155                                   got_dot = 1;
02156                                 }
02157                               else if (n == 10 && have_locthousands
02158                                       && ! got_dot)
02159                                 ADDW (thousands);
02160                               else
02161                                 /* The last read character is not part
02162                                    of the number anymore.  */
02163                                 n = 12;
02164 
02165                               break;
02166                             }
02167 #else
02168                            const char *cmpp = mbdigits[n];
02169                            int avail = width > 0 ? width : INT_MAX;
02170 
02171                            while ((unsigned char) *cmpp == c && avail >= 0)
02172                             if (*++cmpp == '\0')
02173                               break;
02174                             else
02175                               {
02176                                 if (avail == 0 || inchar () == EOF)
02177                                   break;
02178                                 --avail;
02179                               }
02180                            if (*cmpp == '\0')
02181                             {
02182                               if (width > 0)
02183                                 width = avail;
02184 
02185                               if (n < 10)
02186                                 ADDW (L_('0') + n);
02187                               else if (n == 11 && !got_dot)
02188                                 {
02189                                   /* Add all the characters.  */
02190                                   for (cmpp = decimal; *cmpp != '\0';
02191                                       ++cmpp)
02192                                    ADDW ((unsigned char) *cmpp);
02193 
02194                                   got_dot = 1;
02195                                 }
02196                               else if (n == 10 && (flags & GROUP) != 0
02197                                       && ! got_dot)
02198                                 {
02199                                   /* Add all the characters.  */
02200                                   for (cmpp = thousands; *cmpp != '\0';
02201                                       ++cmpp)
02202                                    ADDW ((unsigned char) *cmpp);
02203                                 }
02204                               else
02205                                 /* The last read character is not part
02206                                    of the number anymore.  */
02207                                   n = 12;
02208 
02209                               break;
02210                             }
02211 
02212                            /* We are pushing all read characters back.  */
02213                            if (cmpp > mbdigits[n])
02214                             {
02215                               ungetc (c, s);
02216                               while (--cmpp > mbdigits[n])
02217                                 ungetc_not_eof ((unsigned char) *cmpp, s);
02218                               c = (unsigned char) *cmpp;
02219                             }
02220 #endif
02221                          }
02222 
02223                        if (n >= 12)
02224                          {
02225                            /* The last read character is not part
02226                              of the number anymore.  */
02227                            ungetc (c, s);
02228                            break;
02229                          }
02230                      }
02231 
02232                     if (width == 0 || inchar () == EOF)
02233                      break;
02234 
02235                     if (width > 0)
02236                      --width;
02237                   }
02238               }
02239 
02240 #ifndef COMPILE_WSCANF
02241            no_i18nflt:
02242              ;
02243 #endif
02244            }
02245 
02246          /* Have we read any character?  If we try to read a number
02247             in hexadecimal notation and we have read only the `0x'
02248             prefix this is an error.  */
02249          if (__builtin_expect (wpsize == 0
02250                             || ((flags & HEXA_FLOAT) && wpsize == 2), 0))
02251            conv_error ();
02252 
02253        scan_float:
02254          /* Convert the number.  */
02255          ADDW (L_('\0'));
02256          if ((flags & LONGDBL) && !__ldbl_is_dbl)
02257            {
02258              long double d = __strtold_internal (wp, &tw, flags & GROUP);
02259              if (!(flags & SUPPRESS) && tw != wp)
02260               *ARG (long double *) = negative ? -d : d;
02261            }
02262          else if (flags & (LONG | LONGDBL))
02263            {
02264              double d = __strtod_internal (wp, &tw, flags & GROUP);
02265              if (!(flags & SUPPRESS) && tw != wp)
02266               *ARG (double *) = negative ? -d : d;
02267            }
02268          else
02269            {
02270              float d = __strtof_internal (wp, &tw, flags & GROUP);
02271              if (!(flags & SUPPRESS) && tw != wp)
02272               *ARG (float *) = negative ? -d : d;
02273            }
02274 
02275          if (__builtin_expect (tw == wp, 0))
02276            conv_error ();
02277 
02278          if (!(flags & SUPPRESS))
02279            ++done;
02280          break;
02281 
02282        case L_('['): /* Character class.  */
02283          if (flags & LONG)
02284            STRING_ARG (wstr, wchar_t, 100);
02285          else
02286            STRING_ARG (str, char, 100);
02287 
02288          if (*f == L_('^'))
02289            {
02290              ++f;
02291              not_in = 1;
02292            }
02293          else
02294            not_in = 0;
02295 
02296          if (width < 0)
02297            /* There is no width given so there is also no limit on the
02298               number of characters we read.  Therefore we set width to
02299               a very high value to make the algorithm easier.  */
02300            width = INT_MAX;
02301 
02302 #ifdef COMPILE_WSCANF
02303          /* Find the beginning and the end of the scanlist.  We are not
02304             creating a lookup table since it would have to be too large.
02305             Instead we search each time through the string.  This is not
02306             a constant lookup time but who uses this feature deserves to
02307             be punished.  */
02308          tw = (wchar_t *) f;       /* Marks the beginning.  */
02309 
02310          if (*f == L']')
02311            ++f;
02312 
02313          while ((fc = *f++) != L'\0' && fc != L']');
02314 
02315          if (__builtin_expect (fc == L'\0', 0))
02316            conv_error ();
02317          wchar_t *twend = (wchar_t *) f - 1;
02318 #else
02319          /* Fill WP with byte flags indexed by character.
02320             We will use this flag map for matching input characters.  */
02321          if (wpmax < UCHAR_MAX + 1)
02322            {
02323              wpmax = UCHAR_MAX + 1;
02324              wp = (char *) alloca (wpmax);
02325            }
02326          memset (wp, '\0', UCHAR_MAX + 1);
02327 
02328          fc = *f;
02329          if (fc == ']' || fc == '-')
02330            {
02331              /* If ] or - appears before any char in the set, it is not
02332                the terminator or separator, but the first char in the
02333                set.  */
02334              wp[fc] = 1;
02335              ++f;
02336            }
02337 
02338          while ((fc = *f++) != '\0' && fc != ']')
02339            if (fc == '-' && *f != '\0' && *f != ']'
02340               && (unsigned char) f[-2] <= (unsigned char) *f)
02341              {
02342               /* Add all characters from the one before the '-'
02343                  up to (but not including) the next format char.  */
02344               for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc)
02345                 wp[fc] = 1;
02346              }
02347            else
02348              /* Add the character to the flag map.  */
02349              wp[fc] = 1;
02350 
02351          if (__builtin_expect (fc == '\0', 0))
02352            conv_error();
02353 #endif
02354 
02355          if (flags & LONG)
02356            {
02357              size_t now = read_in;
02358 #ifdef COMPILE_WSCANF
02359              if (__builtin_expect (inchar () == WEOF, 0))
02360               input_error ();
02361 
02362              do
02363               {
02364                 wchar_t *runp;
02365 
02366                 /* Test whether it's in the scanlist.  */
02367                 runp = tw;
02368                 while (runp < twend)
02369                   {
02370                     if (runp[0] == L'-' && runp[1] != '\0'
02371                        && runp + 1 != twend
02372                        && runp != tw
02373                        && (unsigned int) runp[-1] <= (unsigned int) runp[1])
02374                      {
02375                        /* Match against all characters in between the
02376                           first and last character of the sequence.  */
02377                        wchar_t wc;
02378 
02379                        for (wc = runp[-1] + 1; wc <= runp[1]; ++wc)
02380                          if ((wint_t) wc == c)
02381                            break;
02382 
02383                        if (wc <= runp[1] && !not_in)
02384                          break;
02385                        if (wc <= runp[1] && not_in)
02386                          {
02387                            /* The current character is not in the
02388                                  scanset.  */
02389                            ungetc (c, s);
02390                            goto out;
02391                          }
02392 
02393                        runp += 2;
02394                      }
02395                     else
02396                      {
02397                        if ((wint_t) *runp == c && !not_in)
02398                          break;
02399                        if ((wint_t) *runp == c && not_in)
02400                          {
02401                            ungetc (c, s);
02402                            goto out;
02403                          }
02404 
02405                        ++runp;
02406                      }
02407                   }
02408 
02409                 if (runp == twend && !not_in)
02410                   {
02411                     ungetc (c, s);
02412                     goto out;
02413                   }
02414 
02415                 if (!(flags & SUPPRESS))
02416                   {
02417                     *wstr++ = c;
02418 
02419                     if ((flags & MALLOC)
02420                        && wstr == (wchar_t *) *strptr + strsize)
02421                      {
02422                        /* Enlarge the buffer.  */
02423                        wstr = (wchar_t *) realloc (*strptr,
02424                                                 (2 * strsize)
02425                                                 * sizeof (wchar_t));
02426                        if (wstr == NULL)
02427                          {
02428                            /* Can't allocate that much.  Last-ditch
02429                              effort.  */
02430                            wstr = (wchar_t *)
02431                             realloc (*strptr, (strsize + 1)
02432                                             * sizeof (wchar_t));
02433                            if (wstr == NULL)
02434                             {
02435                               if (flags & POSIX_MALLOC)
02436                                 goto reteof;
02437                               /* We lose.  Oh well.  Terminate the string
02438                                  and stop converting, so at least we don't
02439                                  skip any input.  */
02440                               ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
02441                               strptr = NULL;
02442                               ++done;
02443                               conv_error ();
02444                             }
02445                            else
02446                             {
02447                               *strptr = (char *) wstr;
02448                               wstr += strsize;
02449                               ++strsize;
02450                             }
02451                          }
02452                        else
02453                          {
02454                            *strptr = (char *) wstr;
02455                            wstr += strsize;
02456                            strsize *= 2;
02457                          }
02458                      }
02459                   }
02460               }
02461              while (--width > 0 && inchar () != WEOF);
02462            out:
02463 #else
02464              char buf[MB_LEN_MAX];
02465              size_t cnt = 0;
02466              mbstate_t cstate;
02467 
02468              if (__builtin_expect (inchar () == EOF, 0))
02469               input_error ();
02470 
02471              memset (&cstate, '\0', sizeof (cstate));
02472 
02473              do
02474               {
02475                 if (wp[c] == not_in)
02476                   {
02477                     ungetc_not_eof (c, s);
02478                     break;
02479                   }
02480 
02481                 /* This is easy.  */
02482                 if (!(flags & SUPPRESS))
02483                   {
02484                     size_t n;
02485 
02486                     /* Convert it into a wide character.  */
02487                     buf[0] = c;
02488                     n = __mbrtowc (wstr, buf, 1, &cstate);
02489 
02490                     if (n == (size_t) -2)
02491                      {
02492                        /* Possibly correct character, just not enough
02493                           input.  */
02494                        ++cnt;
02495                        assert (cnt < MB_CUR_MAX);
02496                        continue;
02497                      }
02498                     cnt = 0;
02499 
02500                     ++wstr;
02501                     if ((flags & MALLOC)
02502                        && wstr == (wchar_t *) *strptr + strsize)
02503                      {
02504                        /* Enlarge the buffer.  */
02505                        wstr = (wchar_t *) realloc (*strptr,
02506                                                 (2 * strsize
02507                                                  * sizeof (wchar_t)));
02508                        if (wstr == NULL)
02509                          {
02510                            /* Can't allocate that much.  Last-ditch
02511                              effort.  */
02512                            wstr = (wchar_t *)
02513                             realloc (*strptr, ((strsize + 1)
02514                                              * sizeof (wchar_t)));
02515                            if (wstr == NULL)
02516                             {
02517                               if (flags & POSIX_MALLOC)
02518                                 goto reteof;
02519                               /* We lose.  Oh well.  Terminate the
02520                                  string and stop converting,
02521                                  so at least we don't skip any input.  */
02522                               ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
02523                               strptr = NULL;
02524                               ++done;
02525                               conv_error ();
02526                             }
02527                            else
02528                             {
02529                               *strptr = (char *) wstr;
02530                               wstr += strsize;
02531                               ++strsize;
02532                             }
02533                          }
02534                        else
02535                          {
02536                            *strptr = (char *) wstr;
02537                            wstr += strsize;
02538                            strsize *= 2;
02539                          }
02540                      }
02541                   }
02542 
02543                 if (--width <= 0)
02544                   break;
02545               }
02546              while (inchar () != EOF);
02547 
02548              if (__builtin_expect (cnt != 0, 0))
02549               /* We stopped in the middle of recognizing another
02550                  character.  That's a problem.  */
02551               encode_error ();
02552 #endif
02553 
02554              if (__builtin_expect (now == read_in, 0))
02555               /* We haven't succesfully read any character.  */
02556               conv_error ();
02557 
02558              if (!(flags & SUPPRESS))
02559               {
02560                 *wstr++ = L'\0';
02561 
02562                 if ((flags & MALLOC)
02563                     && wstr - (wchar_t *) *strptr != strsize)
02564                   {
02565                     wchar_t *cp = (wchar_t *)
02566                      realloc (*strptr, ((wstr - (wchar_t *) *strptr)
02567                                       * sizeof(wchar_t)));
02568                     if (cp != NULL)
02569                      *strptr = (char *) cp;
02570                   }
02571                 strptr = NULL;
02572 
02573                 ++done;
02574               }
02575            }
02576          else
02577            {
02578              size_t now = read_in;
02579 
02580              if (__builtin_expect (inchar () == EOF, 0))
02581               input_error ();
02582 
02583 #ifdef COMPILE_WSCANF
02584 
02585              memset (&state, '\0', sizeof (state));
02586 
02587              do
02588               {
02589                 wchar_t *runp;
02590                 size_t n;
02591 
02592                 /* Test whether it's in the scanlist.  */
02593                 runp = tw;
02594                 while (runp < twend)
02595                   {
02596                     if (runp[0] == L'-' && runp[1] != '\0'
02597                        && runp + 1 != twend
02598                        && runp != tw
02599                        && (unsigned int) runp[-1] <= (unsigned int) runp[1])
02600                      {
02601                        /* Match against all characters in between the
02602                           first and last character of the sequence.  */
02603                        wchar_t wc;
02604 
02605                        for (wc = runp[-1] + 1; wc <= runp[1]; ++wc)
02606                          if ((wint_t) wc == c)
02607                            break;
02608 
02609                        if (wc <= runp[1] && !not_in)
02610                          break;
02611                        if (wc <= runp[1] && not_in)
02612                          {
02613                            /* The current character is not in the
02614                                  scanset.  */
02615                            ungetc (c, s);
02616                            goto out2;
02617                          }
02618 
02619                        runp += 2;
02620                      }
02621                     else
02622                      {
02623                        if ((wint_t) *runp == c && !not_in)
02624                          break;
02625                        if ((wint_t) *runp == c && not_in)
02626                          {
02627                            ungetc (c, s);
02628                            goto out2;
02629                          }
02630 
02631                        ++runp;
02632                      }
02633                   }
02634 
02635                 if (runp == twend && !not_in)
02636                   {
02637                     ungetc (c, s);
02638                     goto out2;
02639                   }
02640 
02641                 if (!(flags & SUPPRESS))
02642                   {
02643                     if ((flags & MALLOC)
02644                        && str + MB_CUR_MAX >= *strptr + strsize)
02645                      {
02646                        /* Enlarge the buffer.  */
02647                        size_t strleng = str - *strptr;
02648                        char *newstr;
02649 
02650                        newstr = (char *) realloc (*strptr, 2 * strsize);
02651                        if (newstr == NULL)
02652                          {
02653                            /* Can't allocate that much.  Last-ditch
02654                              effort.  */
02655                            newstr = (char *) realloc (*strptr,
02656                                                   strleng + MB_CUR_MAX);
02657                            if (newstr == NULL)
02658                             {
02659                               if (flags & POSIX_MALLOC)
02660                                 goto reteof;
02661                               /* We lose.  Oh well.  Terminate the string
02662                                  and stop converting, so at least we don't
02663                                  skip any input.  */
02664                               ((char *) (*strptr))[strleng] = '\0';
02665                               strptr = NULL;
02666                               ++done;
02667                               conv_error ();
02668                             }
02669                            else
02670                             {
02671                               *strptr = newstr;
02672                               str = newstr + strleng;
02673                               strsize = strleng + MB_CUR_MAX;
02674                             }
02675                          }
02676                        else
02677                          {
02678                            *strptr = newstr;
02679                            str = newstr + strleng;
02680                            strsize *= 2;
02681                          }
02682                      }
02683                   }
02684 
02685                 n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
02686                 if (__builtin_expect (n == (size_t) -1, 0))
02687                   encode_error ();
02688 
02689                 assert (n <= MB_CUR_MAX);
02690                 str += n;
02691               }
02692              while (--width > 0 && inchar () != WEOF);
02693            out2:
02694 #else
02695              do
02696               {
02697                 if (wp[c] == not_in)
02698                   {
02699                     ungetc_not_eof (c, s);
02700                     break;
02701                   }
02702 
02703                 /* This is easy.  */
02704                 if (!(flags & SUPPRESS))
02705                   {
02706                     *str++ = c;
02707                     if ((flags & MALLOC)
02708                        && (char *) str == *strptr + strsize)
02709                      {
02710                        /* Enlarge the buffer.  */
02711                        size_t newsize = 2 * strsize;
02712 
02713                      allocagain:
02714                        str = (char *) realloc (*strptr, newsize);
02715                        if (str == NULL)
02716                          {
02717                            /* Can't allocate that much.  Last-ditch
02718                              effort.  */
02719                            if (newsize > strsize + 1)
02720                             {
02721                               newsize = strsize + 1;
02722                               goto allocagain;
02723                             }
02724                            if (flags & POSIX_MALLOC)
02725                             goto reteof;
02726                            /* We lose.  Oh well.  Terminate the
02727                              string and stop converting,
02728                              so at least we don't skip any input.  */
02729                            ((char *) (*strptr))[strsize - 1] = '\0';
02730                            strptr = NULL;
02731                            ++done;
02732                            conv_error ();
02733                          }
02734                        else
02735                          {
02736                            *strptr = (char *) str;
02737                            str += strsize;
02738                            strsize = newsize;
02739                          }
02740                      }
02741                   }
02742               }
02743              while (--width > 0 && inchar () != EOF);
02744 #endif
02745 
02746              if (__builtin_expect (now == read_in, 0))
02747               /* We haven't succesfully read any character.  */
02748               conv_error ();
02749 
02750              if (!(flags & SUPPRESS))
02751               {
02752 #ifdef COMPILE_WSCANF
02753                 /* We have to emit the code to get into the initial
02754                    state.  */
02755                 char buf[MB_LEN_MAX];
02756                 size_t n = __wcrtomb (buf, L'\0', &state);
02757                 if (n > 0 && (flags & MALLOC)
02758                     && str + n >= *strptr + strsize)
02759                   {
02760                     /* Enlarge the buffer.  */
02761                     size_t strleng = str - *strptr;
02762                     char *newstr;
02763 
02764                     newstr = (char *) realloc (*strptr, strleng + n + 1);
02765                     if (newstr == NULL)
02766                      {
02767                        if (flags & POSIX_MALLOC)
02768                          goto reteof;
02769                        /* We lose.  Oh well.  Terminate the string
02770                           and stop converting, so at least we don't
02771                           skip any input.  */
02772                        ((char *) (*strptr))[strleng] = '\0';
02773                        strptr = NULL;
02774                        ++done;
02775                        conv_error ();
02776                      }
02777                     else
02778                      {
02779                        *strptr = newstr;
02780                        str = newstr + strleng;
02781                        strsize = strleng + n + 1;
02782                      }
02783                   }
02784 
02785                 str = __mempcpy (str, buf, n);
02786 #endif
02787                 *str++ = '\0';
02788 
02789                 if ((flags & MALLOC) && str - *strptr != strsize)
02790                   {
02791                     char *cp = (char *) realloc (*strptr, str - *strptr);
02792                     if (cp != NULL)
02793                      *strptr = cp;
02794                   }
02795                 strptr = NULL;
02796 
02797                 ++done;
02798               }
02799            }
02800          break;
02801 
02802        case L_('p'): /* Generic pointer.  */
02803          base = 16;
02804          /* A PTR must be the same size as a `long int'.  */
02805          flags &= ~(SHORT|LONGDBL);
02806          if (need_long)
02807            flags |= LONG;
02808          flags |= READ_POINTER;
02809          goto number;
02810 
02811        default:
02812          /* If this is an unknown format character punt.  */
02813          conv_error ();
02814        }
02815     }
02816 
02817   /* The last thing we saw int the format string was a white space.
02818      Consume the last white spaces.  */
02819   if (skip_space)
02820     {
02821       do
02822        c = inchar ();
02823       while (ISSPACE (c));
02824       ungetc (c, s);
02825     }
02826 
02827  errout:
02828   /* Unlock stream.  */
02829   UNLOCK_STREAM (s);
02830 
02831   if (errp != NULL)
02832     *errp |= errval;
02833 
02834   if (done == EOF)
02835     {
02836   reteof:
02837       if (__builtin_expect (ptrs_to_free != NULL, 0))
02838        {
02839          struct ptrs_to_free *p = ptrs_to_free;
02840          while (p != NULL)
02841            {
02842              for (size_t cnt = 0; cnt < p->count; ++cnt)
02843               {
02844                 free (*p->ptrs[cnt]);
02845                 *p->ptrs[cnt] = NULL;
02846               }
02847              p = p->next;
02848              ptrs_to_free = p;
02849            }
02850        }
02851       return EOF;
02852     }
02853   else if (__builtin_expect (strptr != NULL, 0))
02854     {
02855       free (*strptr);
02856       *strptr = NULL;
02857     }
02858   return done;
02859 }
02860 
02861 #ifdef COMPILE_WSCANF
02862 int
02863 __vfwscanf (FILE *s, const wchar_t *format, va_list argptr)
02864 {
02865   return _IO_vfwscanf (s, format, argptr, NULL);
02866 }
02867 ldbl_weak_alias (__vfwscanf, vfwscanf)
02868 #else
02869 int
02870 ___vfscanf (FILE *s, const char *format, va_list argptr)
02871 {
02872   return _IO_vfscanf_internal (s, format, argptr, NULL);
02873 }
02874 ldbl_strong_alias (_IO_vfscanf_internal, _IO_vfscanf)
02875 ldbl_strong_alias (___vfscanf, __vfscanf)
02876 ldbl_hidden_def (___vfscanf, __vfscanf)
02877 ldbl_weak_alias (___vfscanf, vfscanf)
02878 #endif