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