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