Subversion Repositories Kolibri OS

Rev

Rev 4921 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19. FUNCTION
  20. <<vfscanf>>, <<vscanf>>, <<vsscanf>>---format argument list
  21.  
  22. INDEX
  23.         vfscanf
  24. INDEX
  25.         _vfscanf_r
  26. INDEX
  27.         vscanf
  28. INDEX
  29.         _vscanf_r
  30. INDEX
  31.         vsscanf
  32. INDEX
  33.         _vsscanf_r
  34.  
  35. ANSI_SYNOPSIS
  36.         #include <stdio.h>
  37.         #include <stdarg.h>
  38.         int vscanf(const char *<[fmt]>, va_list <[list]>);
  39.         int vfscanf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
  40.         int vsscanf(const char *<[str]>, const char *<[fmt]>, va_list <[list]>);
  41.  
  42.         int _vscanf_r(struct _reent *<[reent]>, const char *<[fmt]>,
  43.                        va_list <[list]>);
  44.         int _vfscanf_r(struct _reent *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
  45.                        va_list <[list]>);
  46.         int _vsscanf_r(struct _reent *<[reent]>, const char *<[str]>,
  47.                        const char *<[fmt]>, va_list <[list]>);
  48.  
  49. TRAD_SYNOPSIS
  50.         #include <stdio.h>
  51.         #include <varargs.h>
  52.         int vscanf( <[fmt]>, <[ist]>)
  53.         char *<[fmt]>;
  54.         va_list <[list]>;
  55.  
  56.         int vfscanf( <[fp]>, <[fmt]>, <[list]>)
  57.         FILE *<[fp]>;
  58.         char *<[fmt]>;
  59.         va_list <[list]>;
  60.  
  61.         int vsscanf( <[str]>, <[fmt]>, <[list]>)
  62.         char *<[str]>;
  63.         char *<[fmt]>;
  64.         va_list <[list]>;
  65.  
  66.         int _vscanf_r( <[reent]>, <[fmt]>, <[ist]>)
  67.         struct _reent *<[reent]>;
  68.         char *<[fmt]>;
  69.         va_list <[list]>;
  70.  
  71.         int _vfscanf_r( <[reent]>, <[fp]>, <[fmt]>, <[list]>)
  72.         struct _reent *<[reent]>;
  73.         FILE *<[fp]>;
  74.         char *<[fmt]>;
  75.         va_list <[list]>;
  76.  
  77.         int _vsscanf_r( <[reent]>, <[str]>, <[fmt]>, <[list]>)
  78.         struct _reent *<[reent]>;
  79.         char *<[str]>;
  80.         char *<[fmt]>;
  81.         va_list <[list]>;
  82.  
  83. DESCRIPTION
  84. <<vscanf>>, <<vfscanf>>, and <<vsscanf>> are (respectively) variants
  85. of <<scanf>>, <<fscanf>>, and <<sscanf>>.  They differ only in
  86. allowing their caller to pass the variable argument list as a
  87. <<va_list>> object (initialized by <<va_start>>) rather than
  88. directly accepting a variable number of arguments.
  89.  
  90. RETURNS
  91. The return values are consistent with the corresponding functions:
  92. <<vscanf>> returns the number of input fields successfully scanned,
  93. converted, and stored; the return value does not include scanned
  94. fields which were not stored.
  95.  
  96. If <<vscanf>> attempts to read at end-of-file, the return value
  97. is <<EOF>>.
  98.  
  99. If no fields were stored, the return value is <<0>>.
  100.  
  101. The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are
  102. reentrant versions which take an additional first parameter which points to the
  103. reentrancy structure.
  104.  
  105. PORTABILITY
  106. These are GNU extensions.
  107.  
  108. Supporting OS subroutines required:
  109. */
  110.  
  111. #include <_ansi.h>
  112. #include <reent.h>
  113. #include <newlib.h>
  114. #include <ctype.h>
  115. #include <wctype.h>
  116. #include <stdio.h>
  117. #include <stdlib.h>
  118. #include <stdint.h>
  119. #include <limits.h>
  120. #include <wchar.h>
  121. #include <string.h>
  122. #include <stdarg.h>
  123. #include <errno.h>
  124. #include "local.h"
  125. #include "../stdlib/local.h"
  126.  
  127. #ifdef INTEGER_ONLY
  128. #define VFSCANF vfiscanf
  129. #define _VFSCANF_R _vfiscanf_r
  130. #define __SVFSCANF __svfiscanf
  131. #ifdef STRING_ONLY
  132. #  define __SVFSCANF_R __ssvfiscanf_r
  133. #else
  134. #  define __SVFSCANF_R __svfiscanf_r
  135. #endif
  136. #else
  137. #define VFSCANF vfscanf
  138. #define _VFSCANF_R _vfscanf_r
  139. #define __SVFSCANF __svfscanf
  140. #ifdef STRING_ONLY
  141. #  define __SVFSCANF_R __ssvfscanf_r
  142. #else
  143. #  define __SVFSCANF_R __svfscanf_r
  144. #endif
  145. #ifndef NO_FLOATING_POINT
  146. #define FLOATING_POINT
  147. #endif
  148. #endif
  149.  
  150. #ifdef STRING_ONLY
  151. #undef _newlib_flockfile_start
  152. #undef _newlib_flockfile_exit
  153. #undef _newlib_flockfile_end
  154. #define _newlib_flockfile_start(x) {}
  155. #define _newlib_flockfile_exit(x) {}
  156. #define _newlib_flockfile_end(x) {}
  157. #define _ungetc_r _sungetc_r
  158. #define __srefill_r __ssrefill_r
  159. #define _fread_r _sfread_r
  160. #endif
  161.  
  162. #ifdef FLOATING_POINT
  163. #include <math.h>
  164. #include <float.h>
  165. #include <locale.h>
  166.  
  167. /* Currently a test is made to see if long double processing is warranted.
  168.    This could be changed in the future should the _ldtoa_r code be
  169.    preferred over _dtoa_r.  */
  170. #define _NO_LONGDBL
  171. #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
  172. #undef _NO_LONGDBL
  173. #endif
  174.  
  175. #include "floatio.h"
  176.  
  177. #define BUF (MAXEXP+MAXFRACT+MB_LEN_MAX+2) /* decimal point + sign + NUL */
  178.  
  179. /* An upper bound for how long a long prints in decimal.  4 / 13 approximates
  180.    log (2).  Add one char for roundoff compensation and one for the sign.  */
  181. #define MAX_LONG_LEN ((CHAR_BIT * sizeof (long)  - 1) * 4 / 13 + 2)
  182. #else
  183. #define BUF     40
  184. #endif
  185.  
  186. #define _NO_LONGLONG
  187. #if defined _WANT_IO_LONG_LONG \
  188.         && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
  189. # undef _NO_LONGLONG
  190. #endif
  191.  
  192. #define _NO_POS_ARGS
  193. #ifdef _WANT_IO_POS_ARGS
  194. # undef _NO_POS_ARGS
  195. # ifdef NL_ARGMAX
  196. #  define MAX_POS_ARGS NL_ARGMAX
  197. # else
  198. #  define MAX_POS_ARGS 32
  199. # endif
  200.  
  201. static void * get_arg (int, va_list *, int *, void **);
  202. #endif /* _WANT_IO_POS_ARGS */
  203.  
  204. /*
  205.  * Flags used during conversion.
  206.  */
  207.  
  208. #define LONG            0x01    /* l: long or double */
  209. #define LONGDBL         0x02    /* L/ll: long double or long long */
  210. #define SHORT           0x04    /* h: short */
  211. #define CHAR            0x08    /* hh: 8 bit integer */
  212. #define SUPPRESS        0x10    /* suppress assignment */
  213. #define POINTER         0x20    /* weird %p pointer (`fake hex') */
  214. #define NOSKIP          0x40    /* do not skip blanks */
  215.  
  216. /*
  217.  * The following are used in numeric conversions only:
  218.  * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
  219.  * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
  220.  */
  221.  
  222. #define SIGNOK          0x80    /* +/- is (still) legal */
  223. #define NDIGITS         0x100   /* no digits detected */
  224.  
  225. #define DPTOK           0x200   /* (float) decimal point is still legal */
  226. #define EXPOK           0x400   /* (float) exponent (e+3, etc) still legal */
  227.  
  228. #define PFXOK           0x200   /* 0x prefix is (still) legal */
  229. #define NZDIGITS        0x400   /* no zero digits detected */
  230. #define NNZDIGITS       0x800   /* no non-zero digits detected */
  231.  
  232. /*
  233.  * Conversion types.
  234.  */
  235.  
  236. #define CT_CHAR         0       /* %c conversion */
  237. #define CT_CCL          1       /* %[...] conversion */
  238. #define CT_STRING       2       /* %s conversion */
  239. #define CT_INT          3       /* integer, i.e., strtol or strtoul */
  240. #define CT_FLOAT        4       /* floating, i.e., strtod */
  241.  
  242. #define u_char unsigned char
  243. #define u_long unsigned long
  244.  
  245. #ifndef _NO_LONGLONG
  246. typedef unsigned long long u_long_long;
  247. #endif
  248.  
  249. /*
  250.  * vfscanf
  251.  */
  252.  
  253. #define BufferEmpty (fp->_r <= 0 && __srefill_r(rptr, fp))
  254.  
  255. #ifndef STRING_ONLY
  256.  
  257. #ifndef _REENT_ONLY
  258.  
  259. int
  260. _DEFUN(VFSCANF, (fp, fmt, ap),
  261.        register FILE *fp _AND
  262.        _CONST char *fmt _AND
  263.        va_list ap)
  264. {
  265.   struct _reent *reent = _REENT;
  266.  
  267.   CHECK_INIT(reent, fp);
  268.   return __SVFSCANF_R (reent, fp, fmt, ap);
  269. }
  270.  
  271. int
  272. _DEFUN(__SVFSCANF, (fp, fmt0, ap),
  273.        register FILE *fp _AND
  274.        char _CONST *fmt0 _AND
  275.        va_list ap)
  276. {
  277.   return __SVFSCANF_R (_REENT, fp, fmt0, ap);
  278. }
  279.  
  280. #endif /* !_REENT_ONLY */
  281.  
  282. int
  283. _DEFUN(_VFSCANF_R, (data, fp, fmt, ap),
  284.        struct _reent *data _AND
  285.        register FILE *fp   _AND
  286.        _CONST char *fmt    _AND
  287.        va_list ap)
  288. {
  289.   CHECK_INIT(data, fp);
  290.   return __SVFSCANF_R (data, fp, fmt, ap);
  291. }
  292. #endif /* !STRING_ONLY */
  293.  
  294. #if defined (STRING_ONLY) && defined (INTEGER_ONLY)
  295. /* When dealing with the sscanf family, we don't want to use the
  296.  * regular ungetc which will drag in file I/O items we don't need.
  297.  * So, we create our own trimmed-down version.  */
  298. int
  299. _DEFUN(_sungetc_r, (data, fp, ch),
  300.         struct _reent *data _AND
  301.         int c               _AND
  302.         register FILE *fp)
  303. {
  304.   if (c == EOF)
  305.     return (EOF);
  306.  
  307.   /* After ungetc, we won't be at eof anymore */
  308.   fp->_flags &= ~__SEOF;
  309.   c = (unsigned char) c;
  310.  
  311.   /*
  312.    * If we are in the middle of ungetc'ing, just continue.
  313.    * This may require expanding the current ungetc buffer.
  314.    */
  315.  
  316.   if (HASUB (fp))
  317.     {
  318.       if (fp->_r >= fp->_ub._size && __submore (data, fp))
  319.         {
  320.           return EOF;
  321.         }
  322.       *--fp->_p = c;
  323.       fp->_r++;
  324.       return c;
  325.     }
  326.  
  327.   /*
  328.    * If we can handle this by simply backing up, do so,
  329.    * but never replace the original character.
  330.    * (This makes sscanf() work when scanning `const' data.)
  331.    */
  332.  
  333.   if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
  334.     {
  335.       fp->_p--;
  336.       fp->_r++;
  337.       return c;
  338.     }
  339.  
  340.   /*
  341.    * Create an ungetc buffer.
  342.    * Initially, we will use the `reserve' buffer.
  343.    */
  344.  
  345.   fp->_ur = fp->_r;
  346.   fp->_up = fp->_p;
  347.   fp->_ub._base = fp->_ubuf;
  348.   fp->_ub._size = sizeof (fp->_ubuf);
  349.   fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
  350.   fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
  351.   fp->_r = 1;
  352.   return c;
  353. }
  354.  
  355. /* String only version of __srefill_r for sscanf family.  */
  356. int
  357. _DEFUN(__ssrefill_r, (ptr, fp),
  358.        struct _reent * ptr _AND
  359.        register FILE * fp)
  360. {
  361.   /*
  362.    * Our only hope of further input is the ungetc buffer.
  363.    * If there is anything in that buffer to read, return.
  364.    */
  365.   if (HASUB (fp))
  366.     {
  367.       FREEUB (ptr, fp);
  368.       if ((fp->_r = fp->_ur) != 0)
  369.         {
  370.           fp->_p = fp->_up;
  371.           return 0;
  372.         }
  373.     }
  374.  
  375.   /* Otherwise we are out of character input.  */
  376.   fp->_p = fp->_bf._base;
  377.   fp->_r = 0;
  378.   fp->_flags |= __SEOF;
  379.   return EOF;
  380. }
  381.  
  382. size_t
  383. _DEFUN(_sfread_r, (ptr, buf, size, count, fp),
  384.        struct _reent * ptr _AND
  385.        _PTR buf _AND
  386.        size_t size _AND
  387.        size_t count _AND
  388.        FILE * fp)
  389. {
  390.   register size_t resid;
  391.   register char *p;
  392.   register int r;
  393.   size_t total;
  394.  
  395.   if ((resid = count * size) == 0)
  396.     return 0;
  397.  
  398.   total = resid;
  399.   p = buf;
  400.  
  401.   while (resid > (r = fp->_r))
  402.     {
  403.       _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) r);
  404.       fp->_p += r;
  405.       fp->_r = 0;
  406.       p += r;
  407.       resid -= r;
  408.       if (__ssrefill_r (ptr, fp))
  409.         {
  410.           /* no more input: return partial result */
  411.           return (total - resid) / size;
  412.         }
  413.     }
  414.   _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, resid);
  415.   fp->_r -= resid;
  416.   fp->_p += resid;
  417.   return count;
  418. }
  419. #else /* !STRING_ONLY || !INTEGER_ONLY */
  420. int _EXFUN (_sungetc_r, (struct _reent *, int, register FILE *));
  421. int _EXFUN (__ssrefill_r, (struct _reent *, register FILE *));
  422. size_t _EXFUN (_sfread_r, (struct _reent *, _PTR buf, size_t, size_t, FILE *));
  423. #endif /* !STRING_ONLY || !INTEGER_ONLY */
  424.  
  425. int
  426. _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
  427.        struct _reent *rptr _AND
  428.        register FILE *fp   _AND
  429.        char _CONST *fmt0   _AND
  430.        va_list ap)
  431. {
  432.   register u_char *fmt = (u_char *) fmt0;
  433.   register int c;               /* character from format, or conversion */
  434.   register size_t width;        /* field width, or 0 */
  435.   register char *p;             /* points into all kinds of strings */
  436.   register int n;               /* handy integer */
  437.   register int flags;           /* flags as defined above */
  438.   register char *p0;            /* saves original value of p when necessary */
  439.   int nassigned;                /* number of fields assigned */
  440.   int nread;                    /* number of characters consumed from fp */
  441. #ifndef _NO_POS_ARGS
  442.   int N;                        /* arg number */
  443.   int arg_index = 0;            /* index into args processed directly */
  444.   int numargs = 0;              /* number of varargs read */
  445.   void *args[MAX_POS_ARGS];     /* positional args read */
  446.   int is_pos_arg;               /* is current format positional? */
  447. #endif
  448.   int base = 0;                 /* base argument to strtol/strtoul */
  449.   int nbytes = 1;               /* number of bytes read from fmt string */
  450.   wchar_t wc;                   /* wchar to use to read format string */
  451.   wchar_t *wcp;                 /* handy wide character pointer */
  452.   size_t mbslen;                /* length of converted multibyte sequence */
  453. #ifdef _MB_CAPABLE
  454.   mbstate_t state;              /* value to keep track of multibyte state */
  455. #endif
  456.  
  457.   #define CCFN_PARAMS   _PARAMS((struct _reent *, const char *, char **, int))
  458.   u_long (*ccfn)CCFN_PARAMS=0;  /* conversion function (strtol/strtoul) */
  459.   char ccltab[256];             /* character class table for %[...] */
  460.   char buf[BUF];                /* buffer for numeric conversions */
  461.   unsigned char *lptr;          /* literal pointer */
  462.  
  463.   char *cp;
  464.   short *sp;
  465.   int *ip;
  466. #ifdef FLOATING_POINT
  467.   float *flp;
  468.   _LONG_DOUBLE *ldp;
  469.   double *dp;
  470. #endif
  471.   long *lp;
  472. #ifndef _NO_LONGLONG
  473.   long long *llp;
  474. #endif
  475.  
  476.   /* `basefix' is used to avoid `if' tests in the integer scanner */
  477.   static _CONST short basefix[17] =
  478.     {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
  479.  
  480.   /* Macro to support positional arguments */
  481. #ifndef _NO_POS_ARGS
  482. # define GET_ARG(n, ap, type)                                   \
  483.   ((type) (is_pos_arg                                           \
  484.            ? (n < numargs                                       \
  485.               ? args[n]                                         \
  486.               : get_arg (n, &ap, &numargs, args))               \
  487.            : (arg_index++ < numargs                             \
  488.               ? args[n]                                         \
  489.               : (numargs < MAX_POS_ARGS                         \
  490.                  ? args[numargs++] = va_arg (ap, void *)        \
  491.                  : va_arg (ap, void *)))))
  492. #else
  493. # define GET_ARG(n, ap, type) (va_arg (ap, type))
  494. #endif
  495.  
  496.   _newlib_flockfile_start (fp);
  497.  
  498.   ORIENT (fp, -1);
  499.  
  500.   nassigned = 0;
  501.   nread = 0;
  502. #ifdef _MB_CAPABLE
  503.   memset (&state, 0, sizeof (state));
  504. #endif
  505.  
  506.   for (;;)
  507.     {
  508. #ifndef _MB_CAPABLE
  509.       wc = *fmt;
  510. #else
  511.       nbytes = __mbtowc (rptr, &wc, (char *) fmt, MB_CUR_MAX,
  512.                          __locale_charset (), &state);
  513.       if (nbytes < 0) {
  514.         wc = 0xFFFD; /* Unicode replacement character */
  515.         nbytes = 1;
  516.         memset (&state, 0, sizeof (state));
  517.       }
  518. #endif
  519.       fmt += nbytes;
  520.  
  521.       if (wc == 0)
  522.         goto all_done;
  523.       if (nbytes == 1 && isspace (wc))
  524.         {
  525.           for (;;)
  526.             {
  527.               if (BufferEmpty || !isspace (*fp->_p))
  528.                 break;
  529.               nread++, fp->_r--, fp->_p++;
  530.             }
  531.           continue;
  532.         }
  533.       if (wc != '%')
  534.         goto literal;
  535.       width = 0;
  536.       flags = 0;
  537. #ifndef _NO_POS_ARGS
  538.       N = arg_index;
  539.       is_pos_arg = 0;
  540. #endif
  541.  
  542.       /*
  543.        * switch on the format.  continue if done; break once format
  544.        * type is derived.
  545.        */
  546.  
  547.     again:
  548.       c = *fmt++;
  549.  
  550.       switch (c)
  551.         {
  552.         case '%':
  553.         literal:
  554.           lptr = fmt - nbytes;
  555.           for (n = 0; n < nbytes; ++n)
  556.             {
  557.               if (BufferEmpty)
  558.                 goto input_failure;
  559.               if (*fp->_p != *lptr)
  560.                 goto match_failure;
  561.               fp->_r--, fp->_p++;
  562.               nread++;
  563.               ++lptr;
  564.             }
  565.           continue;
  566.  
  567.         case '*':
  568.           flags |= SUPPRESS;
  569.           goto again;
  570.         case 'l':
  571. #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
  572.           if (*fmt == 'l')      /* Check for 'll' = long long (SUSv3) */
  573.             {
  574.               ++fmt;
  575.               flags |= LONGDBL;
  576.             }
  577.           else
  578. #endif
  579.             flags |= LONG;
  580.           goto again;
  581.         case 'L':
  582.           flags |= LONGDBL;
  583.           goto again;
  584.         case 'h':
  585. #ifdef _WANT_IO_C99_FORMATS
  586.           if (*fmt == 'h')      /* Check for 'hh' = char int (SUSv3) */
  587.             {
  588.               ++fmt;
  589.               flags |= CHAR;
  590.             }
  591.           else
  592. #endif
  593.             flags |= SHORT;
  594.           goto again;
  595. #ifdef _WANT_IO_C99_FORMATS
  596.         case 'j': /* intmax_t */
  597.           if (sizeof (intmax_t) == sizeof (long))
  598.             flags |= LONG;
  599.           else
  600.             flags |= LONGDBL;
  601.           goto again;
  602.         case 't': /* ptrdiff_t */
  603.           if (sizeof (ptrdiff_t) < sizeof (int))
  604.             /* POSIX states ptrdiff_t is 16 or more bits, as
  605.                is short.  */
  606.             flags |= SHORT;
  607.           else if (sizeof (ptrdiff_t) == sizeof (int))
  608.             /* no flag needed */;
  609.           else if (sizeof (ptrdiff_t) <= sizeof (long))
  610.             flags |= LONG;
  611.           else
  612.             /* POSIX states that at least one programming
  613.                environment must support ptrdiff_t no wider than
  614.                long, but that means other environments can
  615.                have ptrdiff_t as wide as long long.  */
  616.             flags |= LONGDBL;
  617.           goto again;
  618.         case 'z': /* size_t */
  619.           if (sizeof (size_t) < sizeof (int))
  620.             /* POSIX states size_t is 16 or more bits, as is short.  */
  621.             flags |= SHORT;
  622.           else if (sizeof (size_t) == sizeof (int))
  623.             /* no flag needed */;
  624.           else if (sizeof (size_t) <= sizeof (long))
  625.             flags |= LONG;
  626.           else
  627.             /* POSIX states that at least one programming
  628.                environment must support size_t no wider than
  629.                long, but that means other environments can
  630.                have size_t as wide as long long.  */
  631.             flags |= LONGDBL;
  632.           goto again;
  633. #endif /* _WANT_IO_C99_FORMATS */
  634.  
  635.         case '0':
  636.         case '1':
  637.         case '2':
  638.         case '3':
  639.         case '4':
  640.         case '5':
  641.         case '6':
  642.         case '7':
  643.         case '8':
  644.         case '9':
  645.           width = width * 10 + c - '0';
  646.           goto again;
  647.  
  648. #ifndef _NO_POS_ARGS
  649.         case '$':
  650.           if (width <= MAX_POS_ARGS)
  651.             {
  652.               N = width - 1;
  653.               is_pos_arg = 1;
  654.               width = 0;
  655.               goto again;
  656.             }
  657.           rptr->_errno = EINVAL;
  658.           goto input_failure;
  659. #endif /* !_NO_POS_ARGS */
  660.  
  661.           /*
  662.            * Conversions. Those marked `compat' are for
  663.            * 4.[123]BSD compatibility.
  664.            *
  665.            * (According to ANSI, E and X formats are supposed to
  666.            * the same as e and x.  Sorry about that.)
  667.            */
  668.  
  669.         case 'D':               /* compat */
  670.           flags |= LONG;
  671.           /* FALLTHROUGH */
  672.         case 'd':
  673.           c = CT_INT;
  674.           ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
  675.           base = 10;
  676.           break;
  677.  
  678.         case 'i':
  679.           c = CT_INT;
  680.           ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
  681.           base = 0;
  682.           break;
  683.  
  684.         case 'O':               /* compat */
  685.           flags |= LONG;
  686.           /* FALLTHROUGH */
  687.         case 'o':
  688.           c = CT_INT;
  689.           ccfn = _strtoul_r;
  690.           base = 8;
  691.           break;
  692.  
  693.         case 'u':
  694.           c = CT_INT;
  695.           ccfn = _strtoul_r;
  696.           base = 10;
  697.           break;
  698.  
  699.         case 'X':
  700.         case 'x':
  701.           flags |= PFXOK;       /* enable 0x prefixing */
  702.           c = CT_INT;
  703.           ccfn = _strtoul_r;
  704.           base = 16;
  705.           break;
  706.  
  707. #ifdef FLOATING_POINT
  708. # ifdef _WANT_IO_C99_FORMATS
  709.         case 'a':
  710.         case 'A':
  711.         case 'F':
  712. # endif
  713.         case 'E':
  714.         case 'G':
  715.         case 'e':
  716.         case 'f':
  717.         case 'g':
  718.           c = CT_FLOAT;
  719.           break;
  720. #endif
  721.  
  722. #ifdef _WANT_IO_C99_FORMATS
  723.         case 'S':
  724.           flags |= LONG;
  725.           /* FALLTHROUGH */
  726. #endif
  727.  
  728.         case 's':
  729.           c = CT_STRING;
  730.           break;
  731.  
  732.         case '[':
  733.           fmt = (u_char *) __sccl (ccltab, (unsigned char *) fmt);
  734.           flags |= NOSKIP;
  735.           c = CT_CCL;
  736.           break;
  737.  
  738. #ifdef _WANT_IO_C99_FORMATS
  739.         case 'C':
  740.           flags |= LONG;
  741.           /* FALLTHROUGH */
  742. #endif
  743.  
  744.         case 'c':
  745.           flags |= NOSKIP;
  746.           c = CT_CHAR;
  747.           break;
  748.  
  749.         case 'p':               /* pointer format is like hex */
  750.           flags |= POINTER | PFXOK;
  751.           c = CT_INT;
  752.           ccfn = _strtoul_r;
  753.           base = 16;
  754.           break;
  755.  
  756.         case 'n':
  757.           if (flags & SUPPRESS) /* ??? */
  758.             continue;
  759. #ifdef _WANT_IO_C99_FORMATS
  760.           if (flags & CHAR)
  761.             {
  762.               cp = GET_ARG (N, ap, char *);
  763.               *cp = nread;
  764.             }
  765.           else
  766. #endif
  767.           if (flags & SHORT)
  768.             {
  769.               sp = GET_ARG (N, ap, short *);
  770.               *sp = nread;
  771.             }
  772.           else if (flags & LONG)
  773.             {
  774.               lp = GET_ARG (N, ap, long *);
  775.               *lp = nread;
  776.             }
  777. #ifndef _NO_LONGLONG
  778.           else if (flags & LONGDBL)
  779.             {
  780.               llp = GET_ARG (N, ap, long long*);
  781.               *llp = nread;
  782.             }
  783. #endif
  784.           else
  785.             {
  786.               ip = GET_ARG (N, ap, int *);
  787.               *ip = nread;
  788.             }
  789.           continue;
  790.  
  791.           /*
  792.            * Disgusting backwards compatibility hacks.  XXX
  793.            */
  794.         case '\0':              /* compat */
  795.           _newlib_flockfile_exit (fp);
  796.           return EOF;
  797.  
  798.         default:                /* compat */
  799.           if (isupper (c))
  800.             flags |= LONG;
  801.           c = CT_INT;
  802.           ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
  803.           base = 10;
  804.           break;
  805.         }
  806.  
  807.       /*
  808.        * We have a conversion that requires input.
  809.        */
  810.       if (BufferEmpty)
  811.         goto input_failure;
  812.  
  813.       /*
  814.        * Consume leading white space, except for formats that
  815.        * suppress this.
  816.        */
  817.       if ((flags & NOSKIP) == 0)
  818.         {
  819.           while (isspace (*fp->_p))
  820.             {
  821.               nread++;
  822.               if (--fp->_r > 0)
  823.                 fp->_p++;
  824.               else
  825.               if (__srefill_r (rptr, fp))
  826.                 goto input_failure;
  827.             }
  828.           /*
  829.            * Note that there is at least one character in the
  830.            * buffer, so conversions that do not set NOSKIP ca
  831.            * no longer result in an input failure.
  832.            */
  833.         }
  834.  
  835.       /*
  836.        * Do the conversion.
  837.        */
  838.       switch (c)
  839.         {
  840.  
  841.         case CT_CHAR:
  842.           /* scan arbitrary characters (sets NOSKIP) */
  843.           if (width == 0)
  844.             width = 1;
  845. #if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
  846.           if (flags & LONG)
  847.             {
  848.               mbstate_t state;
  849.               memset (&state, 0, sizeof (mbstate_t));
  850.               if ((flags & SUPPRESS) == 0)
  851.                 wcp = GET_ARG (N, ap, wchar_t *);
  852.               else
  853.                 wcp = NULL;
  854.               n = 0;
  855.               while (width != 0)
  856.                 {
  857.                   if (n == MB_CUR_MAX)
  858.                     goto input_failure;
  859.                   buf[n++] = *fp->_p;
  860.                   fp->_r -= 1;
  861.                   fp->_p += 1;
  862.                   if ((mbslen = _mbrtowc_r (rptr, wcp, buf, n, &state))
  863.                                                          == (size_t)-1)
  864.                     goto input_failure; /* Invalid sequence */
  865.                   if (mbslen == 0 && !(flags & SUPPRESS))
  866.                     *wcp = L'\0';
  867.                   if (mbslen != (size_t)-2) /* Incomplete sequence */
  868.                     {
  869.                       nread += n;
  870.                       width -= 1;
  871.                       if (!(flags & SUPPRESS))
  872.                         wcp += 1;
  873.                       n = 0;
  874.                     }
  875.                   if (BufferEmpty)
  876.                     {
  877.                       if (n != 0)
  878.                         goto input_failure;
  879.                       break;
  880.                     }
  881.                 }
  882.               if (!(flags & SUPPRESS))
  883.                 nassigned++;
  884.             }
  885.           else
  886. #endif
  887.                   if (flags & SUPPRESS)
  888.             {
  889.               size_t sum = 0;
  890.               for (;;)
  891.                 {
  892.                   if ((n = fp->_r) < (int)width)
  893.                     {
  894.                       sum += n;
  895.                       width -= n;
  896.                       fp->_p += n;
  897.                       if (__srefill_r (rptr, fp))
  898.                         {
  899.                           if (sum == 0)
  900.                             goto input_failure;
  901.                           break;
  902.                         }
  903.                     }
  904.                   else
  905.                     {
  906.                       sum += width;
  907.                       fp->_r -= width;
  908.                       fp->_p += width;
  909.                       break;
  910.                     }
  911.                 }
  912.               nread += sum;
  913.             }
  914.           else
  915.             {
  916.               size_t r = _fread_r (rptr, (_PTR) GET_ARG (N, ap, char *), 1, width, fp);
  917.  
  918.               if (r == 0)
  919.                 goto input_failure;
  920.               nread += r;
  921.               nassigned++;
  922.             }
  923.           break;
  924.  
  925.         case CT_CCL:
  926.           /* scan a (nonempty) character class (sets NOSKIP) */
  927.           if (width == 0)
  928.             width = ~0;         /* `infinity' */
  929.           /* take only those things in the class */
  930.           if (flags & SUPPRESS)
  931.             {
  932.               n = 0;
  933.               while (ccltab[*fp->_p])
  934.                 {
  935.                   n++, fp->_r--, fp->_p++;
  936.                   if (--width == 0)
  937.                     break;
  938.                   if (BufferEmpty)
  939.                     {
  940.                       if (n == 0)
  941.                         goto input_failure;
  942.                       break;
  943.                     }
  944.                 }
  945.               if (n == 0)
  946.                 goto match_failure;
  947.             }
  948.           else
  949.             {
  950.               p0 = p = GET_ARG (N, ap, char *);
  951.               while (ccltab[*fp->_p])
  952.                 {
  953.                   fp->_r--;
  954.                   *p++ = *fp->_p++;
  955.                   if (--width == 0)
  956.                     break;
  957.                   if (BufferEmpty)
  958.                     {
  959.                       if (p == p0)
  960.                         goto input_failure;
  961.                       break;
  962.                     }
  963.                 }
  964.               n = p - p0;
  965.               if (n == 0)
  966.                 goto match_failure;
  967.               *p = 0;
  968.               nassigned++;
  969.             }
  970.           nread += n;
  971.           break;
  972.  
  973.         case CT_STRING:
  974.           /* like CCL, but zero-length string OK, & no NOSKIP */
  975.           if (width == 0)
  976.             width = (size_t)~0;
  977. #if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
  978.           if (flags & LONG)
  979.             {
  980.               /* Process %S and %ls placeholders */
  981.               mbstate_t state;
  982.               memset (&state, 0, sizeof (mbstate_t));
  983.               if ((flags & SUPPRESS) == 0)
  984.                 wcp = GET_ARG (N, ap, wchar_t *);
  985.               else
  986.                 wcp = &wc;
  987.               n = 0;
  988.               while (!isspace (*fp->_p) && width != 0)
  989.                 {
  990.                   if (n == MB_CUR_MAX)
  991.                     goto input_failure;
  992.                   buf[n++] = *fp->_p;
  993.                   fp->_r -= 1;
  994.                   fp->_p += 1;
  995.                   if ((mbslen = _mbrtowc_r (rptr, wcp, buf, n, &state))
  996.                                                         == (size_t)-1)
  997.                     goto input_failure;
  998.                   if (mbslen == 0)
  999.                     *wcp = L'\0';
  1000.                   if (mbslen != (size_t)-2) /* Incomplete sequence */
  1001.                     {
  1002.                       if (iswspace(*wcp))
  1003.                         {
  1004.                           while (n != 0)
  1005.                             _ungetc_r (rptr, (unsigned char) buf[--n], fp);
  1006.                           break;
  1007.                         }
  1008.                       nread += n;
  1009.                       width -= 1;
  1010.                       if ((flags & SUPPRESS) == 0)
  1011.                         wcp += 1;
  1012.                       n = 0;
  1013.                     }
  1014.                   if (BufferEmpty)
  1015.                     {
  1016.                       if (n != 0)
  1017.                         goto input_failure;
  1018.                       break;
  1019.                     }
  1020.                 }
  1021.               if (!(flags & SUPPRESS))
  1022.                 {
  1023.                   *wcp = L'\0';
  1024.                   nassigned++;
  1025.                 }
  1026.             }
  1027.           else
  1028. #endif
  1029.                   if (flags & SUPPRESS)
  1030.             {
  1031.               n = 0;
  1032.               while (!isspace (*fp->_p))
  1033.                 {
  1034.                   n++, fp->_r--, fp->_p++;
  1035.                   if (--width == 0)
  1036.                     break;
  1037.                   if (BufferEmpty)
  1038.                     break;
  1039.                 }
  1040.               nread += n;
  1041.             }
  1042.           else
  1043.             {
  1044.               p0 = p = GET_ARG (N, ap, char *);
  1045.               while (!isspace (*fp->_p))
  1046.                 {
  1047.                   fp->_r--;
  1048.                   *p++ = *fp->_p++;
  1049.                   if (--width == 0)
  1050.                     break;
  1051.                   if (BufferEmpty)
  1052.                     break;
  1053.                 }
  1054.               *p = 0;
  1055.               nread += p - p0;
  1056.               nassigned++;
  1057.             }
  1058.           continue;
  1059.  
  1060.         case CT_INT:
  1061.         {
  1062.           /* scan an integer as if by strtol/strtoul */
  1063.           unsigned width_left = 0;
  1064.           int skips = 0;
  1065. #ifdef hardway
  1066.           if (width == 0 || width > sizeof (buf) - 1)
  1067. #else
  1068.           /* size_t is unsigned, hence this optimisation */
  1069.           if (width - 1 > sizeof (buf) - 2)
  1070. #endif
  1071.             {
  1072.               width_left = width - (sizeof (buf) - 1);
  1073.               width = sizeof (buf) - 1;
  1074.             }
  1075.           flags |= SIGNOK | NDIGITS | NZDIGITS | NNZDIGITS;
  1076.           for (p = buf; width; width--)
  1077.             {
  1078.               c = *fp->_p;
  1079.               /*
  1080.                * Switch on the character; `goto ok' if we
  1081.                * accept it as a part of number.
  1082.                */
  1083.               switch (c)
  1084.                 {
  1085.                   /*
  1086.                    * The digit 0 is always legal, but is special.
  1087.                    * For %i conversions, if no digits (zero or nonzero)
  1088.                    * have been scanned (only signs), we will have base==0.
  1089.                    * In that case, we should set it to 8 and enable 0x
  1090.                    * prefixing. Also, if we have not scanned zero digits
  1091.                    * before this, do not turn off prefixing (someone else
  1092.                    * will turn it off if we have scanned any nonzero digits).
  1093.                    */
  1094.                 case '0':
  1095.                   if (! (flags & NNZDIGITS))
  1096.                     goto ok;
  1097.                   if (base == 0)
  1098.                     {
  1099.                       base = 8;
  1100.                       flags |= PFXOK;
  1101.                     }
  1102.                   if (flags & NZDIGITS)
  1103.                     {
  1104.                       flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
  1105.                       goto ok;
  1106.                     }
  1107.                   flags &= ~(SIGNOK | PFXOK | NDIGITS);
  1108.                   if (width_left)
  1109.                     {
  1110.                       width_left--;
  1111.                       width++;
  1112.                     }
  1113.                   ++skips;
  1114.                   goto skip;
  1115.  
  1116.                   /* 1 through 7 always legal */
  1117.                 case '1':
  1118.                 case '2':
  1119.                 case '3':
  1120.                 case '4':
  1121.                 case '5':
  1122.                 case '6':
  1123.                 case '7':
  1124.                   base = basefix[base];
  1125.                   flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
  1126.                   goto ok;
  1127.  
  1128.                   /* digits 8 and 9 ok iff decimal or hex */
  1129.                 case '8':
  1130.                 case '9':
  1131.                   base = basefix[base];
  1132.                   if (base <= 8)
  1133.                     break;      /* not legal here */
  1134.                   flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
  1135.                   goto ok;
  1136.  
  1137.                   /* letters ok iff hex */
  1138.                 case 'A':
  1139.                 case 'B':
  1140.                 case 'C':
  1141.                 case 'D':
  1142.                 case 'E':
  1143.                 case 'F':
  1144.                 case 'a':
  1145.                 case 'b':
  1146.                 case 'c':
  1147.                 case 'd':
  1148.                 case 'e':
  1149.                 case 'f':
  1150.                   /* no need to fix base here */
  1151.                   if (base <= 10)
  1152.                     break;      /* not legal here */
  1153.                   flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
  1154.                   goto ok;
  1155.  
  1156.                   /* sign ok only as first character */
  1157.                 case '+':
  1158.                 case '-':
  1159.                   if (flags & SIGNOK)
  1160.                     {
  1161.                       flags &= ~SIGNOK;
  1162.                       goto ok;
  1163.                     }
  1164.                   break;
  1165.  
  1166.                   /* x ok iff flag still set & single 0 seen */
  1167.                 case 'x':
  1168.                 case 'X':
  1169.                   if ((flags & (PFXOK | NZDIGITS)) == PFXOK)
  1170.                     {
  1171.                       base = 16;/* if %i */
  1172.                       flags &= ~PFXOK;
  1173.                       /* We must reset the NZDIGITS and NDIGITS
  1174.                          flags that would have been unset by seeing
  1175.                          the zero that preceded the X or x.  */
  1176.                       flags |= NZDIGITS | NDIGITS;
  1177.                       goto ok;
  1178.                     }
  1179.                   break;
  1180.                 }
  1181.  
  1182.               /*
  1183.                * If we got here, c is not a legal character
  1184.                * for a number.  Stop accumulating digits.
  1185.                */
  1186.               break;
  1187.             ok:
  1188.               /*
  1189.                * c is legal: store it and look at the next.
  1190.                */
  1191.               *p++ = c;
  1192.             skip:
  1193.               if (--fp->_r > 0)
  1194.                 fp->_p++;
  1195.               else
  1196.               if (__srefill_r (rptr, fp))
  1197.                 break;          /* EOF */
  1198.             }
  1199.           /*
  1200.            * If we had only a sign, it is no good; push back the sign.
  1201.            * If the number ends in `x', it was [sign] '0' 'x', so push back
  1202.            * the x and treat it as [sign] '0'.
  1203.            * Use of ungetc here and below assumes ASCII encoding; we are only
  1204.            * pushing back 7-bit characters, so casting to unsigned char is
  1205.            * not necessary.
  1206.            */
  1207.           if (flags & NDIGITS)
  1208.             {
  1209.               if (p > buf)
  1210.                 _ungetc_r (rptr, *--p, fp); /* [-+xX] */
  1211.               if (p == buf)
  1212.                 goto match_failure;
  1213.             }
  1214.           if ((flags & SUPPRESS) == 0)
  1215.             {
  1216.               u_long res;
  1217.  
  1218.               *p = 0;
  1219.               res = (*ccfn) (rptr, buf, (char **) NULL, base);
  1220.               if (flags & POINTER)
  1221.                 {
  1222.                   void **vp = GET_ARG (N, ap, void **);
  1223. #ifndef _NO_LONGLONG
  1224.                   if (sizeof (uintptr_t) > sizeof (u_long))
  1225.                     {
  1226.                       u_long_long resll;
  1227.                       resll = _strtoull_r (rptr, buf, (char **) NULL, base);
  1228.                       *vp = (void *) (uintptr_t) resll;
  1229.                     }
  1230.                   else
  1231. #endif /* !_NO_LONGLONG */
  1232.                     *vp = (void *) (uintptr_t) res;
  1233.                 }
  1234. #ifdef _WANT_IO_C99_FORMATS
  1235.               else if (flags & CHAR)
  1236.                 {
  1237.                   cp = GET_ARG (N, ap, char *);
  1238.                   *cp = res;
  1239.                 }
  1240. #endif
  1241.               else if (flags & SHORT)
  1242.                 {
  1243.                   sp = GET_ARG (N, ap, short *);
  1244.                   *sp = res;
  1245.                 }
  1246.               else if (flags & LONG)
  1247.                 {
  1248.                   lp = GET_ARG (N, ap, long *);
  1249.                   *lp = res;
  1250.                 }
  1251. #ifndef _NO_LONGLONG
  1252.               else if (flags & LONGDBL)
  1253.                 {
  1254.                   u_long_long resll;
  1255.                   if (ccfn == _strtoul_r)
  1256.                     resll = _strtoull_r (rptr, buf, (char **) NULL, base);
  1257.                   else
  1258.                     resll = _strtoll_r (rptr, buf, (char **) NULL, base);
  1259.                   llp = GET_ARG (N, ap, long long*);
  1260.                   *llp = resll;
  1261.                 }
  1262. #endif
  1263.               else
  1264.                 {
  1265.                   ip = GET_ARG (N, ap, int *);
  1266.                   *ip = res;
  1267.                 }
  1268.               nassigned++;
  1269.             }
  1270.           nread += p - buf + skips;
  1271.           break;
  1272.         }
  1273. #ifdef FLOATING_POINT
  1274.         case CT_FLOAT:
  1275.         {
  1276.           /* scan a floating point number as if by strtod */
  1277.           /* This code used to assume that the number of digits is reasonable.
  1278.              However, ANSI / ISO C makes no such stipulation; we have to get
  1279.              exact results even when there is an unreasonable amount of
  1280.              leading zeroes.  */
  1281.           long leading_zeroes = 0;
  1282.           long zeroes, exp_adjust;
  1283.           char *exp_start = NULL;
  1284.           unsigned width_left = 0;
  1285.           char nancount = 0;
  1286.           char infcount = 0;
  1287.           const char *decpt = _localeconv_r (rptr)->decimal_point;
  1288. #ifdef _MB_CAPABLE
  1289.           int decptpos = 0;
  1290. #endif
  1291. #ifdef hardway
  1292.           if (width == 0 || width > sizeof (buf) - 1)
  1293. #else
  1294.           /* size_t is unsigned, hence this optimisation */
  1295.           if (width - 1 > sizeof (buf) - 2)
  1296. #endif
  1297.             {
  1298.               width_left = width - (sizeof (buf) - 1);
  1299.               width = sizeof (buf) - 1;
  1300.             }
  1301.           flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
  1302.           zeroes = 0;
  1303.           exp_adjust = 0;
  1304.           for (p = buf; width; )
  1305.             {
  1306.               c = *fp->_p;
  1307.               /*
  1308.                * This code mimicks the integer conversion
  1309.                * code, but is much simpler.
  1310.                */
  1311.               switch (c)
  1312.                 {
  1313.                 case '0':
  1314.                   if (flags & NDIGITS)
  1315.                     {
  1316.                       flags &= ~SIGNOK;
  1317.                       zeroes++;
  1318.                       if (width_left)
  1319.                         {
  1320.                           width_left--;
  1321.                           width++;
  1322.                         }
  1323.                       goto fskip;
  1324.                     }
  1325.                   /* Fall through.  */
  1326.                 case '1':
  1327.                 case '2':
  1328.                 case '3':
  1329.                 case '4':
  1330.                 case '5':
  1331.                 case '6':
  1332.                 case '7':
  1333.                 case '8':
  1334.                 case '9':
  1335.                   if (nancount + infcount == 0)
  1336.                     {
  1337.                       flags &= ~(SIGNOK | NDIGITS);
  1338.                       goto fok;
  1339.                     }
  1340.                   break;
  1341.  
  1342.                 case '+':
  1343.                 case '-':
  1344.                   if (flags & SIGNOK)
  1345.                     {
  1346.                       flags &= ~SIGNOK;
  1347.                       goto fok;
  1348.                     }
  1349.                   break;
  1350.                 case 'n':
  1351.                 case 'N':
  1352.                   if (nancount == 0 && zeroes == 0
  1353.                       && (flags & (NDIGITS | DPTOK | EXPOK)) ==
  1354.                                   (NDIGITS | DPTOK | EXPOK))
  1355.                     {
  1356.                       flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
  1357.                       nancount = 1;
  1358.                       goto fok;
  1359.                     }
  1360.                   if (nancount == 2)
  1361.                     {
  1362.                       nancount = 3;
  1363.                       goto fok;
  1364.                     }
  1365.                   if (infcount == 1 || infcount == 4)
  1366.                     {
  1367.                       infcount++;
  1368.                       goto fok;
  1369.                     }
  1370.                   break;
  1371.                 case 'a':
  1372.                 case 'A':
  1373.                   if (nancount == 1)
  1374.                     {
  1375.                       nancount = 2;
  1376.                       goto fok;
  1377.                     }
  1378.                   break;
  1379.                 case 'i':
  1380.                 case 'I':
  1381.                   if (infcount == 0 && zeroes == 0
  1382.                       && (flags & (NDIGITS | DPTOK | EXPOK)) ==
  1383.                                   (NDIGITS | DPTOK | EXPOK))
  1384.                     {
  1385.                       flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
  1386.                       infcount = 1;
  1387.                       goto fok;
  1388.                     }
  1389.                   if (infcount == 3 || infcount == 5)
  1390.                     {
  1391.                       infcount++;
  1392.                       goto fok;
  1393.                     }
  1394.                   break;
  1395.                 case 'f':
  1396.                 case 'F':
  1397.                   if (infcount == 2)
  1398.                     {
  1399.                       infcount = 3;
  1400.                       goto fok;
  1401.                     }
  1402.                   break;
  1403.                 case 't':
  1404.                 case 'T':
  1405.                   if (infcount == 6)
  1406.                     {
  1407.                       infcount = 7;
  1408.                       goto fok;
  1409.                     }
  1410.                   break;
  1411.                 case 'y':
  1412.                 case 'Y':
  1413.                   if (infcount == 7)
  1414.                     {
  1415.                       infcount = 8;
  1416.                       goto fok;
  1417.                     }
  1418.                   break;
  1419.                 case 'e':
  1420.                 case 'E':
  1421.                   /* no exponent without some digits */
  1422.                   if ((flags & (NDIGITS | EXPOK)) == EXPOK
  1423.                       || ((flags & EXPOK) && zeroes))
  1424.                     {
  1425.                       if (! (flags & DPTOK))
  1426.                         {
  1427.                           exp_adjust = zeroes - leading_zeroes;
  1428.                           exp_start = p;
  1429.                         }
  1430.                       flags =
  1431.                         (flags & ~(EXPOK | DPTOK)) |
  1432.                         SIGNOK | NDIGITS;
  1433.                       zeroes = 0;
  1434.                       goto fok;
  1435.                     }
  1436.                   break;
  1437.                 default:
  1438. #ifndef _MB_CAPABLE
  1439.                   if ((unsigned char) c == (unsigned char) decpt[0]
  1440.                       && (flags & DPTOK))
  1441.                     {
  1442.                       flags &= ~(SIGNOK | DPTOK);
  1443.                       leading_zeroes = zeroes;
  1444.                       goto fok;
  1445.                     }
  1446.                   break;
  1447. #else
  1448.                   if (flags & DPTOK)
  1449.                     {
  1450.                       while ((unsigned char) c
  1451.                              == (unsigned char) decpt[decptpos])
  1452.                         {
  1453.                           if (decpt[++decptpos] == '\0')
  1454.                             {
  1455.                               /* We read the complete decpt seq. */
  1456.                               flags &= ~(SIGNOK | DPTOK);
  1457.                               leading_zeroes = zeroes;
  1458.                               p = stpncpy (p, decpt, decptpos);
  1459.                               decptpos = 0;
  1460.                               goto fskip;
  1461.                             }
  1462.                           ++nread;
  1463.                           if (--fp->_r > 0)
  1464.                             fp->_p++;
  1465.                           else if (__srefill_r (rptr, fp))
  1466.                             break;              /* EOF */
  1467.                           c = *fp->_p;
  1468.                         }
  1469.                       if (decptpos > 0)
  1470.                         {
  1471.                           /* We read part of a multibyte decimal point,
  1472.                              but the rest is invalid or we're at EOF,
  1473.                              so back off. */
  1474.                           while (decptpos-- > 0)
  1475.                             {
  1476.                               _ungetc_r (rptr, (unsigned char) decpt[decptpos],
  1477.                                          fp);
  1478.                               --nread;
  1479.                             }
  1480.                         }
  1481.                     }
  1482.                   break;
  1483. #endif
  1484.                 }
  1485.               break;
  1486.             fok:
  1487.               *p++ = c;
  1488.             fskip:
  1489.               width--;
  1490.               ++nread;
  1491.               if (--fp->_r > 0)
  1492.                 fp->_p++;
  1493.               else
  1494.               if (__srefill_r (rptr, fp))
  1495.                 break;          /* EOF */
  1496.             }
  1497.           if (zeroes)
  1498.             flags &= ~NDIGITS;
  1499.           /* We may have a 'N' or possibly even [sign] 'N' 'a' as the
  1500.              start of 'NaN', only to run out of chars before it was
  1501.              complete (or having encountered a non-matching char).  So
  1502.              check here if we have an outstanding nancount, and if so
  1503.              put back the chars we did swallow and treat as a failed
  1504.              match.
  1505.  
  1506.              FIXME - we still don't handle NAN([0xdigits]).  */
  1507.           if (nancount - 1U < 2U) /* nancount && nancount < 3 */
  1508.             {
  1509.               /* Newlib's ungetc works even if we called __srefill in
  1510.                  the middle of a partial parse, but POSIX does not
  1511.                  guarantee that in all implementations of ungetc.  */
  1512.               while (p > buf)
  1513.                 {
  1514.                   _ungetc_r (rptr, *--p, fp); /* [-+nNaA] */
  1515.                   --nread;
  1516.                 }
  1517.               goto match_failure;
  1518.             }
  1519.           /* Likewise for 'inf' and 'infinity'.  But be careful that
  1520.              'infinite' consumes only 3 characters, leaving the stream
  1521.              at the second 'i'.  */
  1522.           if (infcount - 1U < 7U) /* infcount && infcount < 8 */
  1523.             {
  1524.               if (infcount >= 3) /* valid 'inf', but short of 'infinity' */
  1525.                 while (infcount-- > 3)
  1526.                   {
  1527.                     _ungetc_r (rptr, *--p, fp); /* [iInNtT] */
  1528.                     --nread;
  1529.                   }
  1530.               else
  1531.                 {
  1532.                   while (p > buf)
  1533.                     {
  1534.                       _ungetc_r (rptr, *--p, fp); /* [-+iInN] */
  1535.                       --nread;
  1536.                     }
  1537.                   goto match_failure;
  1538.                 }
  1539.             }
  1540.           /*
  1541.            * If no digits, might be missing exponent digits
  1542.            * (just give back the exponent) or might be missing
  1543.            * regular digits, but had sign and/or decimal point.
  1544.            */
  1545.           if (flags & NDIGITS)
  1546.             {
  1547.               if (flags & EXPOK)
  1548.                 {
  1549.                   /* no digits at all */
  1550.                   while (p > buf)
  1551.                     {
  1552.                       _ungetc_r (rptr, *--p, fp); /* [-+.] */
  1553.                       --nread;
  1554.                     }
  1555.                   goto match_failure;
  1556.                 }
  1557.               /* just a bad exponent (e and maybe sign) */
  1558.               c = *--p;
  1559.               --nread;
  1560.               if (c != 'e' && c != 'E')
  1561.                 {
  1562.                   _ungetc_r (rptr, c, fp); /* [-+] */
  1563.                   c = *--p;
  1564.                   --nread;
  1565.                 }
  1566.               _ungetc_r (rptr, c, fp); /* [eE] */
  1567.             }
  1568.           if ((flags & SUPPRESS) == 0)
  1569.             {
  1570.               double res = 0;
  1571. #ifdef _NO_LONGDBL
  1572. #define QUAD_RES res;
  1573. #else  /* !_NO_LONG_DBL */
  1574.               long double qres = 0;
  1575. #define QUAD_RES qres;
  1576. #endif /* !_NO_LONG_DBL */
  1577.               long new_exp = 0;
  1578.  
  1579.               *p = 0;
  1580.               if ((flags & (DPTOK | EXPOK)) == EXPOK)
  1581.                 {
  1582.                   exp_adjust = zeroes - leading_zeroes;
  1583.                   new_exp = -exp_adjust;
  1584.                   exp_start = p;
  1585.                 }
  1586.               else if (exp_adjust)
  1587.                 new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust;
  1588.               if (exp_adjust)
  1589.                 {
  1590.  
  1591.                   /* If there might not be enough space for the new exponent,
  1592.                      truncate some trailing digits to make room.  */
  1593.                   if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN)
  1594.                     exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;
  1595.                  sprintf (exp_start, "e%ld", new_exp);
  1596.                 }
  1597.  
  1598.               /* FIXME: Is that still true?
  1599.                  Current _strtold routine is markedly slower than
  1600.                  _strtod_r.  Only use it if we have a long double
  1601.                  result.  */
  1602. #ifndef _NO_LONGDBL /* !_NO_LONGDBL */
  1603.               if (flags & LONGDBL)
  1604.                 qres = _strtold_r (rptr, buf, NULL);
  1605.               else
  1606. #endif
  1607.                 res = _strtod_r (rptr, buf, NULL);
  1608.  
  1609.               if (flags & LONG)
  1610.                 {
  1611.                   dp = GET_ARG (N, ap, double *);
  1612.                   *dp = res;
  1613.                 }
  1614.               else if (flags & LONGDBL)
  1615.                 {
  1616.                   ldp = GET_ARG (N, ap, _LONG_DOUBLE *);
  1617.                   *ldp = QUAD_RES;
  1618.                 }
  1619.               else
  1620.                 {
  1621.                   flp = GET_ARG (N, ap, float *);
  1622.                   if (isnan (res))
  1623.                     *flp = nanf (NULL);
  1624.                   else
  1625.                     *flp = res;
  1626.                 }
  1627.               nassigned++;
  1628.             }
  1629.           break;
  1630.         }
  1631. #endif /* FLOATING_POINT */
  1632.         }
  1633.     }
  1634. input_failure:
  1635.   /* On read failure, return EOF failure regardless of matches; errno
  1636.      should have been set prior to here.  On EOF failure (including
  1637.      invalid format string), return EOF if no matches yet, else number
  1638.      of matches made prior to failure.  */
  1639.   _newlib_flockfile_exit (fp);
  1640.   return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
  1641. match_failure:
  1642. all_done:
  1643.   /* Return number of matches, which can be 0 on match failure.  */
  1644.   _newlib_flockfile_end (fp);
  1645.   return nassigned;
  1646. }
  1647.  
  1648. #ifndef _NO_POS_ARGS
  1649. /* Process all intermediate arguments.  Fortunately, with scanf, all
  1650.    intermediate arguments are sizeof(void*), so we don't need to scan
  1651.    ahead in the format string.  */
  1652. static void *
  1653. get_arg (int n, va_list *ap, int *numargs_p, void **args)
  1654. {
  1655.   int numargs = *numargs_p;
  1656.   while (n >= numargs)
  1657.     args[numargs++] = va_arg (*ap, void *);
  1658.   *numargs_p = numargs;
  1659.   return args[n];
  1660. }
  1661. #endif /* !_NO_POS_ARGS */
  1662.