Subversion Repositories Kolibri OS

Rev

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