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