2 * Copyright (c) 1990 The Regents of the University of California.
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.
20 <<vfwscanf>>, <<vwscanf>>, <<vswscanf>>---scan and format argument list from wide character input
38 int vwscanf(const wchar_t *__restrict <[fmt]>, va_list <[list]>);
39 int vfwscanf(FILE *__restrict <[fp]>,
40 const wchar_t *__restrict <[fmt]>, va_list <[list]>);
41 int vswscanf(const wchar_t *__restrict <[str]>,
42 const wchar_t *__restrict <[fmt]>, va_list <[list]>);
44 int _vwscanf(struct _reent *<[reent]>, const wchar_t *<[fmt]>,
46 int _vfwscanf(struct _reent *<[reent]>, FILE *<[fp]>,
47 const wchar_t *<[fmt]>, va_list <[list]>);
48 int _vswscanf(struct _reent *<[reent]>, const wchar_t *<[str]>,
49 const wchar_t *<[fmt]>, va_list <[list]>);
52 <<vwscanf>>, <<vfwscanf>>, and <<vswscanf>> are (respectively) variants
53 of <<wscanf>>, <<fwscanf>>, and <<swscanf>>. They differ only in
54 allowing their caller to pass the variable argument list as a
55 <<va_list>> object (initialized by <<va_start>>) rather than
56 directly accepting a variable number of arguments.
59 The return values are consistent with the corresponding functions:
60 <<vwscanf>> returns the number of input fields successfully scanned,
61 converted, and stored; the return value does not include scanned
62 fields which were not stored.
64 If <<vwscanf>> attempts to read at end-of-file, the return value
67 If no fields were stored, the return value is <<0>>.
69 The routines <<_vwscanf>>, <<_vfwscanf>>, and <<_vswscanf>> are
70 reentrant versions which take an additional first parameter which points
71 to the reentrancy structure.
93 #define VFWSCANF vfiwscanf
94 #define _VFWSCANF_R _vfiwscanf_r
95 #define __SVFWSCANF __svfiwscanf
97 # define __SVFWSCANF_R __ssvfiwscanf_r
99 # define __SVFWSCANF_R __svfiwscanf_r
102 #define VFWSCANF vfwscanf
103 #define _VFWSCANF_R _vfwscanf_r
104 #define __SVFWSCANF __svfwscanf
106 # define __SVFWSCANF_R __ssvfwscanf_r
108 # define __SVFWSCANF_R __svfwscanf_r
110 #ifndef NO_FLOATING_POINT
111 #define FLOATING_POINT
116 #undef _newlib_flockfile_start
117 #undef _newlib_flockfile_exit
118 #undef _newlib_flockfile_end
119 #define _newlib_flockfile_start(x) {}
120 #define _newlib_flockfile_exit(x) {}
121 #define _newlib_flockfile_end(x) {}
122 #define _ungetwc_r _sungetwc_r
123 #define __srefill_r __ssrefill_r
124 #define _fgetwc_r _sfgetwc_r
127 #ifdef FLOATING_POINT
131 #ifdef __HAVE_LOCALE_INFO_EXTENDED__
132 #include "../locale/setlocale.h"
135 /* Currently a test is made to see if long double processing is warranted.
136 This could be changed in the future should the _ldtoa_r code be
137 preferred over _dtoa_r. */
139 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
141 extern _LONG_DOUBLE
_wcstold_r (wchar_t *s
, wchar_t **sptr
);
146 #if ((MAXEXP+MAXFRACT+3) > MB_LEN_MAX)
147 # define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
149 # define BUF MB_LEN_MAX
152 /* An upper bound for how long a long prints in decimal. 4 / 13 approximates
153 log (2). Add one char for roundoff compensation and one for the sign. */
154 #define MAX_LONG_LEN ((CHAR_BIT * sizeof (long) - 1) * 4 / 13 + 2)
160 #if defined _WANT_IO_LONG_LONG \
161 && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
166 #ifdef _WANT_IO_POS_ARGS
169 # define MAX_POS_ARGS NL_ARGMAX
171 # define MAX_POS_ARGS 32
174 static void * get_arg (int, va_list *, int *, void **);
175 #endif /* _WANT_IO_POS_ARGS */
178 * Flags used during conversion.
181 #define LONG 0x01 /* l: long or double */
182 #define LONGDBL 0x02 /* L/ll: long double or long long */
183 #define SHORT 0x04 /* h: short */
184 #define CHAR 0x08 /* hh: 8 bit integer */
185 #define SUPPRESS 0x10 /* suppress assignment */
186 #define POINTER 0x20 /* weird %p pointer (`fake hex') */
187 #define NOSKIP 0x40 /* do not skip blanks */
188 #define MALLOC 0x80 /* handle 'm' modifier */
191 * The following are used in numeric conversions only:
192 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
193 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
196 #define SIGNOK 0x80 /* +/- is (still) legal */
197 #define NDIGITS 0x100 /* no digits detected */
199 #define DPTOK 0x200 /* (float) decimal point is still legal */
200 #define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */
202 #define PFXOK 0x200 /* 0x prefix is (still) legal */
203 #define NZDIGITS 0x400 /* no zero digits detected */
204 #define HAVESIGN 0x10000 /* sign detected */
210 #define CT_CHAR 0 /* %c conversion */
211 #define CT_CCL 1 /* %[...] conversion */
212 #define CT_STRING 2 /* %s conversion */
213 #define CT_INT 3 /* integer, i.e., wcstol or wcstoul */
214 #define CT_FLOAT 4 /* floating, i.e., wcstod */
217 (cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL) : \
218 (wmemchr(ccls, (_c), ccle - ccls) != NULL))
229 VFWSCANF (register FILE *__restrict fp
,
230 const wchar_t *__restrict fmt
,
233 struct _reent
*reent
= _REENT
;
235 CHECK_INIT(reent
, fp
);
236 return __SVFWSCANF_R (reent
, fp
, fmt
, ap
);
240 __SVFWSCANF (register FILE *fp
,
244 return __SVFWSCANF_R (_REENT
, fp
, fmt0
, ap
);
247 #endif /* !_REENT_ONLY */
250 _VFWSCANF_R (struct _reent
*data
,
255 CHECK_INIT(data
, fp
);
256 return __SVFWSCANF_R (data
, fp
, fmt
, ap
);
258 #endif /* !STRING_ONLY */
261 /* When dealing with the swscanf family, we don't want to use the
262 * regular ungetwc which will drag in file I/O items we don't need.
263 * So, we create our own trimmed-down version. */
265 _sungetwc_r (struct _reent
*data
,
272 /* After ungetc, we won't be at eof anymore */
273 fp
->_flags
&= ~__SEOF
;
275 /* All ungetwc usage in scanf un-gets the current character, so
276 * just back up over the string if we aren't at the start
278 if (fp
->_bf
._base
!= NULL
&& fp
->_p
> fp
->_bf
._base
)
280 fp
->_p
-= sizeof (wchar_t);
281 fp
->_r
+= sizeof (wchar_t);
287 extern int __ssrefill_r (struct _reent
*ptr
, register FILE * fp
);
290 _sfgetwc_r (struct _reent
* ptr
,
295 if (fp
->_r
<= 0 && __ssrefill_r (ptr
, fp
))
297 wc
= *(wchar_t *) fp
->_p
;
298 fp
->_p
+= sizeof (wchar_t);
299 fp
->_r
-= sizeof (wchar_t);
302 #endif /* STRING_ONLY */
305 __SVFWSCANF_R (struct _reent
*rptr
,
310 register wchar_t *fmt
= (wchar_t *) fmt0
;
311 register wint_t c
; /* character from format, or conversion */
312 register size_t width
; /* field width, or 0 */
313 register wchar_t *p
= NULL
; /* points into all kinds of strings */
314 register int n
; /* handy integer */
315 register int flags
; /* flags as defined above */
316 register wchar_t *p0
; /* saves original value of p when necessary */
317 int nassigned
; /* number of fields assigned */
318 int nread
; /* number of characters consumed from fp */
320 int N
; /* arg number */
321 int arg_index
= 0; /* index into args processed directly */
322 int numargs
= 0; /* number of varargs read */
323 void *args
[MAX_POS_ARGS
]; /* positional args read */
324 int is_pos_arg
; /* is current format positional? */
326 int base
= 0; /* base argument to wcstol/wcstoul */
328 mbstate_t mbs
; /* value to keep track of multibyte state */
330 #define CCFN_PARAMS (struct _reent *, const wchar_t *, wchar_t **, int)
331 unsigned long (*ccfn
)CCFN_PARAMS
=0; /* conversion function (wcstol/wcstoul) */
332 wchar_t buf
[BUF
]; /* buffer for numeric conversions */
333 const wchar_t *ccls
; /* character class start */
334 const wchar_t *ccle
; /* character class end */
335 int cclcompl
= 0; /* ccl is complemented? */
336 wint_t wi
; /* handy wint_t */
337 char *mbp
= NULL
; /* multibyte string pointer for %c %s %[ */
338 size_t nconv
; /* number of bytes in mb. conversion */
339 char mbbuf
[MB_LEN_MAX
]; /* temporary mb. character buffer */
344 #ifdef FLOATING_POINT
354 #ifdef _WANT_IO_C99_FORMATS
355 #define _WANT_IO_POSIX_EXTENSIONS
357 #ifdef _WANT_IO_POSIX_EXTENSIONS
358 /* POSIX requires that fwscanf frees all allocated strings from 'm'
359 conversions in case it returns EOF. m_ptr is used to keep track.
360 It will be allocated on the stack the first time an 'm' conversion
361 takes place, and it will be free'd on return from the function.
362 This implementation tries to save space by only allocating 8
363 pointer slots at a time. Most scenarios should never have to call
364 realloc again. This implementation allows only up to 65528 'm'
365 conversions per fwscanf invocation for now. That should be enough
366 for almost all scenarios, right? */
368 void ***m_arr
; /* Array of pointer args to 'm' conversion */
369 uint16_t m_siz
; /* Number of slots in m_arr */
370 uint16_t m_cnt
; /* Number of valid entries in m_arr */
372 #define init_m_ptr() \
377 m_ptr = (struct m_ptrs *) alloca (sizeof *m_ptr); \
378 m_ptr->m_arr = NULL; \
384 #define push_m_ptr(arg) \
387 if (m_ptr->m_cnt >= m_ptr->m_siz) \
391 if (m_ptr->m_siz + 8 > 0 && m_ptr->m_siz + 8 < UINT16_MAX) \
392 n = (void ***) realloc (m_ptr->m_arr, \
393 (m_ptr->m_siz + 8) * \
398 goto match_failure; \
403 m_ptr->m_arr[m_ptr->m_cnt++] = (void **) (arg); \
406 #define alloc_m_ptr(_type, _p, _p0, _p_p, _w) \
408 _p_p = GET_ARG (N, ap, _type **); \
410 goto match_failure; \
411 _p0 = (_type *) malloc ((_w) * sizeof (_type)); \
415 goto match_failure; \
422 /* For char output, check if there's room for at least MB_CUR_MAX
424 #define realloc_m_ptr(_type, _p, _p0, _p_p, _w) \
427 ptrdiff_t _dif = _p - _p0; \
429 ((sizeof (_type) == 1 && _dif >= _nw - MB_CUR_MAX) \
432 _p0 = (_type *) realloc (_p0, (_nw << 1) * sizeof (_type)); \
436 goto match_failure; \
444 #define shrink_m_ptr(_type, _p_p, _w, _cw) \
447 if (_p_p && _nw < _cw) \
449 _type *_np_p = (_type *) \
450 realloc (*_p_p, _nw * sizeof (_type)); \
455 #define free_m_ptr() \
460 if (nassigned == EOF) \
463 for (i = 0; i < m_ptr->m_cnt; ++i) \
465 free (*m_ptr->m_arr[i]); \
466 *m_ptr->m_arr[i] = NULL; \
470 free (m_ptr->m_arr); \
476 /* `basefix' is used to avoid `if' tests in the integer scanner */
477 static const short basefix
[17] =
478 {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
480 /* Macro to support positional arguments */
482 # define GET_ARG(n, ap, type) \
483 ((type) (is_pos_arg \
486 : get_arg (n, &ap, &numargs, args)) \
487 : (arg_index++ < numargs \
489 : (numargs < MAX_POS_ARGS \
490 ? args[numargs++] = va_arg (ap, void *) \
491 : va_arg (ap, void *)))))
493 # define GET_ARG(n, ap, type) (va_arg (ap, type))
496 #ifdef FLOATING_POINT
498 #ifdef __HAVE_LOCALE_INFO_EXTENDED__
499 decpt
= *__get_current_numeric_locale ()->wdecimal_point
;
504 memset (&mbs
, '\0', sizeof (mbs
));
505 nconv
= _mbrtowc_r (rptr
, &decpt
,
506 _localeconv_r (rptr
)->decimal_point
,
508 if (nconv
== (size_t) -1 || nconv
== (size_t) -2)
511 #endif /* !__HAVE_LOCALE_INFO_EXTENDED__ */
513 decpt
= (wchar_t) *_localeconv_r (rptr
)->decimal_point
;
514 #endif /* !_MB_CAPABLE */
515 #endif /* FLOATING_POINT */
517 _newlib_flockfile_start (fp
);
519 if (ORIENT (fp
, 1) != 1)
535 while ((c
= _fgetwc_r (rptr
, fp
)) != WEOF
&& iswspace(c
))
538 _ungetwc_r (rptr
, c
, fp
);
551 * switch on the format. continue if done; break once format
562 if ((wi
= _fgetwc_r (rptr
, fp
)) == WEOF
)
566 _ungetwc_r (rptr
, wi
, fp
);
573 if ((flags
& (CHAR
| SHORT
| LONG
| LONGDBL
| SUPPRESS
| MALLOC
))
579 if (flags
& (CHAR
| SHORT
| LONG
| LONGDBL
))
581 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
582 if (*fmt
== L
'l') /* Check for 'll' = long long (SUSv3) */
592 if (flags
& (CHAR
| SHORT
| LONG
| LONGDBL
))
597 #ifdef _WANT_IO_C99_FORMATS
598 if (flags
& (CHAR
| SHORT
| LONG
| LONGDBL
))
600 if (*fmt
== 'h') /* Check for 'hh' = char int (SUSv3) */
609 #ifdef _WANT_IO_C99_FORMATS
610 case L
'j': /* intmax_t */
611 if (flags
& (CHAR
| SHORT
| LONG
| LONGDBL
))
613 if (sizeof (intmax_t) == sizeof (long))
618 case L
't': /* ptrdiff_t */
619 if (flags
& (CHAR
| SHORT
| LONG
| LONGDBL
))
621 if (sizeof (ptrdiff_t) < sizeof (int))
622 /* POSIX states ptrdiff_t is 16 or more bits, as
625 else if (sizeof (ptrdiff_t) == sizeof (int))
626 /* no flag needed */;
627 else if (sizeof (ptrdiff_t) <= sizeof (long))
630 /* POSIX states that at least one programming
631 environment must support ptrdiff_t no wider than
632 long, but that means other environments can
633 have ptrdiff_t as wide as long long. */
636 case L
'z': /* size_t */
637 if (flags
& (CHAR
| SHORT
| LONG
| LONGDBL
))
639 if (sizeof (size_t) < sizeof (int))
640 /* POSIX states size_t is 16 or more bits, as is short. */
642 else if (sizeof (size_t) == sizeof (int))
643 /* no flag needed */;
644 else if (sizeof (size_t) <= sizeof (long))
647 /* POSIX states that at least one programming
648 environment must support size_t no wider than
649 long, but that means other environments can
650 have size_t as wide as long long. */
653 #endif /* _WANT_IO_C99_FORMATS */
654 #ifdef _WANT_IO_POSIX_EXTENSIONS
656 if (flags
& (CHAR
| SHORT
| LONG
| LONGDBL
| MALLOC
))
673 if (flags
& (CHAR
| SHORT
| LONG
| LONGDBL
| MALLOC
))
675 width
= width
* 10 + c
- L
'0';
680 if (flags
& (CHAR
| SHORT
| LONG
| LONGDBL
| SUPPRESS
| MALLOC
))
682 if (width
<= MAX_POS_ARGS
)
689 _REENT_ERRNO(rptr
) = EINVAL
;
691 #endif /* !_NO_POS_ARGS */
695 ccfn
= (unsigned long (*)CCFN_PARAMS
)_wcstol_r
;
701 ccfn
= (unsigned long (*)CCFN_PARAMS
)_wcstol_r
;
719 flags
|= PFXOK
; /* enable 0x prefixing */
725 #ifdef FLOATING_POINT
726 # ifdef _WANT_IO_C99_FORMATS
740 #ifdef _WANT_IO_C99_FORMATS
761 while (*fmt
!= '\0' && *fmt
!= ']')
769 #ifdef _WANT_IO_C99_FORMATS
780 case 'p': /* pointer format is like hex */
781 flags
|= POINTER
| PFXOK
;
788 if (flags
& SUPPRESS
) /* ??? */
790 #ifdef _WANT_IO_C99_FORMATS
793 cp
= GET_ARG (N
, ap
, char *);
800 sp
= GET_ARG (N
, ap
, short *);
803 else if (flags
& LONG
)
805 lp
= GET_ARG (N
, ap
, long *);
809 else if (flags
& LONGDBL
)
811 llp
= GET_ARG (N
, ap
, long long*);
817 ip
= GET_ARG (N
, ap
, int *);
827 * Consume leading white space, except for formats that
830 if ((flags
& NOSKIP
) == 0)
832 while ((wi
= _fgetwc_r (rptr
, fp
)) != WEOF
&& iswspace (wi
))
836 _ungetwc_r (rptr
, wi
, fp
);
846 /* scan arbitrary characters (sets NOSKIP) */
851 #ifdef _WANT_IO_POSIX_EXTENSIONS
852 wchar_t **p_p
= NULL
;
857 if (flags
& SUPPRESS
)
859 #ifdef _WANT_IO_POSIX_EXTENSIONS
860 else if (flags
& MALLOC
)
861 p_siz
= alloc_m_ptr (wchar_t, p
, p0
, p_p
, 32);
864 p
= GET_ARG(N
, ap
, wchar_t *);
866 while (width
-- != 0 && (wi
= _fgetwc_r (rptr
, fp
)) != WEOF
)
868 if (!(flags
& SUPPRESS
))
870 #ifdef _WANT_IO_POSIX_EXTENSIONS
871 /* Check before ++ because we never add a \0 */
872 p_siz
= realloc_m_ptr (wchar_t, p
, p0
, p_p
, p_siz
);
881 #ifdef _WANT_IO_POSIX_EXTENSIONS
882 shrink_m_ptr (wchar_t, p_p
, p
- p0
, p_siz
);
884 if (!(flags
& SUPPRESS
))
889 #ifdef _WANT_IO_POSIX_EXTENSIONS
895 if (flags
& SUPPRESS
)
897 #ifdef _WANT_IO_POSIX_EXTENSIONS
898 else if (flags
& MALLOC
)
899 mbp_siz
= alloc_m_ptr (char, mbp
, mbp0
, mbp_p
, 32);
902 mbp
= GET_ARG(N
, ap
, char *);
904 memset ((void *)&mbs
, '\0', sizeof (mbstate_t));
905 while (width
!= 0 && (wi
= _fgetwc_r (rptr
, fp
)) != WEOF
)
907 nconv
= _wcrtomb_r (rptr
, mbp
, wi
, &mbs
);
908 if (nconv
== (size_t) -1)
910 /* Ignore high surrogate in width counting */
911 if (nconv
!= 0 || mbs
.__count
!= -4)
913 if (!(flags
& SUPPRESS
))
915 #ifdef _WANT_IO_POSIX_EXTENSIONS
916 mbp_siz
= realloc_m_ptr (char, mbp
, mbp0
, mbp_p
, mbp_siz
);
925 #ifdef _WANT_IO_POSIX_EXTENSIONS
926 shrink_m_ptr (char, mbp_p
, mbp
- mbp0
, mbp_siz
);
928 if (!(flags
& SUPPRESS
))
934 /* scan a (nonempty) character class (sets NOSKIP) */
936 width
= SIZE_MAX
; /* `infinity' */
937 /* take only those things in the class */
938 if ((flags
& SUPPRESS
) && (flags
& LONG
))
941 while ((wi
= _fgetwc_r (rptr
, fp
)) != WEOF
942 && width
-- != 0 && INCCL (wi
))
945 _ungetwc_r (rptr
, wi
, fp
);
949 else if (flags
& LONG
)
951 #ifdef _WANT_IO_POSIX_EXTENSIONS
952 wchar_t **p_p
= NULL
;
956 p_siz
= alloc_m_ptr (wchar_t, p
, p0
, p_p
, 32);
959 p0
= p
= GET_ARG(N
, ap
, wchar_t *);
960 while ((wi
= _fgetwc_r (rptr
, fp
)) != WEOF
961 && width
-- != 0 && INCCL (wi
))
964 #ifdef _WANT_IO_POSIX_EXTENSIONS
965 p_siz
= realloc_m_ptr (wchar_t, p
, p0
, p_p
, p_siz
);
969 _ungetwc_r (rptr
, wi
, fp
);
974 #ifdef _WANT_IO_POSIX_EXTENSIONS
975 shrink_m_ptr (wchar_t, p_p
, n
+ 1, p_siz
);
981 #ifdef _WANT_IO_POSIX_EXTENSIONS
987 if (flags
& SUPPRESS
)
989 #ifdef _WANT_IO_POSIX_EXTENSIONS
990 else if (flags
& MALLOC
)
991 mbp_siz
= alloc_m_ptr (char, mbp
, mbp0
, mbp_p
, 32);
994 mbp
= GET_ARG(N
, ap
, char *);
996 memset ((void *) &mbs
, '\0', sizeof (mbstate_t));
997 while ((wi
= _fgetwc_r (rptr
, fp
)) != WEOF
998 && width
!= 0 && INCCL (wi
))
1000 nconv
= _wcrtomb_r (rptr
, mbp
, wi
, &mbs
);
1001 if (nconv
== (size_t) -1)
1003 /* Ignore high surrogate in width counting */
1004 if (nconv
!= 0 || mbs
.__count
!= -4)
1006 if (!(flags
& SUPPRESS
))
1009 #ifdef _WANT_IO_POSIX_EXTENSIONS
1010 mbp_siz
= realloc_m_ptr (char, mbp
, mbp0
, mbp_p
, mbp_siz
);
1016 _ungetwc_r (rptr
, wi
, fp
);
1017 if (!(flags
& SUPPRESS
))
1020 #ifdef _WANT_IO_POSIX_EXTENSIONS
1021 shrink_m_ptr (char, mbp_p
, mbp
- mbp0
+ 1, mbp_siz
);
1030 /* like CCL, but zero-length string OK, & no NOSKIP */
1033 if ((flags
& SUPPRESS
) && (flags
& LONG
))
1035 while ((wi
= _fgetwc_r (rptr
, fp
)) != WEOF
1036 && width
-- != 0 && !iswspace (wi
))
1039 _ungetwc_r (rptr
, wi
, fp
);
1041 else if (flags
& LONG
)
1043 #ifdef _WANT_IO_POSIX_EXTENSIONS
1044 wchar_t **p_p
= NULL
;
1048 p_siz
= alloc_m_ptr (wchar_t, p
, p0
, p_p
, 32);
1051 p0
= p
= GET_ARG(N
, ap
, wchar_t *);
1052 while ((wi
= _fgetwc_r (rptr
, fp
)) != WEOF
1053 && width
-- != 0 && !iswspace (wi
))
1055 *p
++ = (wchar_t) wi
;
1056 #ifdef _WANT_IO_POSIX_EXTENSIONS
1057 p_siz
= realloc_m_ptr (wchar_t, p
, p0
, p_p
, p_siz
);
1062 _ungetwc_r (rptr
, wi
, fp
);
1064 #ifdef _WANT_IO_POSIX_EXTENSIONS
1065 shrink_m_ptr (wchar_t, p_p
, p
- p0
+ 1, p_siz
);
1071 #ifdef _WANT_IO_POSIX_EXTENSIONS
1072 char **mbp_p
= NULL
;
1077 if (flags
& SUPPRESS
)
1079 #ifdef _WANT_IO_POSIX_EXTENSIONS
1080 else if (flags
& MALLOC
)
1081 mbp_siz
= alloc_m_ptr (char, mbp
, mbp0
, mbp_p
, 32);
1084 mbp
= GET_ARG(N
, ap
, char *);
1085 memset ((void *) &mbs
, '\0', sizeof (mbstate_t));
1086 while ((wi
= _fgetwc_r (rptr
, fp
)) != WEOF
1087 && width
!= 0 && !iswspace (wi
))
1089 nconv
= wcrtomb(mbp
, wi
, &mbs
);
1090 if (nconv
== (size_t)-1)
1092 /* Ignore high surrogate in width counting */
1093 if (nconv
!= 0 || mbs
.__count
!= -4)
1095 if (!(flags
& SUPPRESS
))
1098 #ifdef _WANT_IO_POSIX_EXTENSIONS
1099 mbp_siz
= realloc_m_ptr (char, mbp
, mbp0
, mbp_p
, mbp_siz
);
1105 _ungetwc_r (rptr
, wi
, fp
);
1106 if (!(flags
& SUPPRESS
))
1109 #ifdef _WANT_IO_POSIX_EXTENSIONS
1110 shrink_m_ptr (char, mbp_p
, mbp
- mbp0
+ 1, mbp_siz
);
1119 /* scan an integer as if by wcstol/wcstoul */
1120 if (width
== 0 || width
> sizeof (buf
) / sizeof (*buf
) - 1)
1121 width
= sizeof(buf
) / sizeof (*buf
) - 1;
1122 flags
|= SIGNOK
| NDIGITS
| NZDIGITS
;
1123 for (p
= buf
; width
; width
--)
1125 c
= _fgetwc_r (rptr
, fp
);
1127 * Switch on the character; `goto ok' if we
1128 * accept it as a part of number.
1133 * The digit 0 is always legal, but is special.
1134 * For %i conversions, if no digits (zero or nonzero)
1135 * have been scanned (only signs), we will have base==0.
1136 * In that case, we should set it to 8 and enable 0x
1137 * prefixing. Also, if we have not scanned zero digits
1138 * before this, do not turn off prefixing (someone else
1139 * will turn it off if we have scanned any nonzero digits).
1147 if (flags
& NZDIGITS
)
1148 flags
&= ~(SIGNOK
| NZDIGITS
| NDIGITS
);
1150 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
);
1153 /* 1 through 7 always legal */
1161 base
= basefix
[base
];
1162 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
);
1165 /* digits 8 and 9 ok iff decimal or hex */
1168 base
= basefix
[base
];
1170 break; /* not legal here */
1171 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
);
1174 /* letters ok iff hex */
1187 /* no need to fix base here */
1189 break; /* not legal here */
1190 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
);
1193 /* sign ok only as first character */
1204 /* x ok iff flag still set & single 0 seen */
1207 if ((flags
& PFXOK
) && p
== buf
+ 1 + !!(flags
& HAVESIGN
))
1209 base
= 16;/* if %i */
1217 * If we got here, c is not a legal character
1218 * for a number. Stop accumulating digits.
1221 _ungetwc_r (rptr
, c
, fp
);
1225 * c is legal: store it and look at the next.
1230 * If we had only a sign, it is no good; push back the sign.
1231 * If the number ends in `x', it was [sign] '0' 'x', so push back
1232 * the x and treat it as [sign] '0'.
1233 * Use of ungetc here and below assumes ASCII encoding; we are only
1234 * pushing back 7-bit characters, so casting to unsigned char is
1237 if (flags
& NDIGITS
)
1240 _ungetwc_r (rptr
, *--p
, fp
); /* [-+xX] */
1244 if (c
== L
'x' || c
== L
'X')
1247 _ungetwc_r (rptr
, c
, fp
);
1249 if ((flags
& SUPPRESS
) == 0)
1254 res
= (*ccfn
) (rptr
, buf
, (wchar_t **) NULL
, base
);
1255 if (flags
& POINTER
)
1257 void **vp
= GET_ARG (N
, ap
, void **);
1258 #ifndef _NO_LONGLONG
1259 if (sizeof (uintptr_t) > sizeof (unsigned long))
1261 unsigned long long resll
;
1262 resll
= _wcstoull_r (rptr
, buf
, (wchar_t **) NULL
, base
);
1263 *vp
= (void *) (uintptr_t) resll
;
1266 #endif /* !_NO_LONGLONG */
1267 *vp
= (void *) (uintptr_t) res
;
1269 #ifdef _WANT_IO_C99_FORMATS
1270 else if (flags
& CHAR
)
1272 cp
= GET_ARG (N
, ap
, char *);
1276 else if (flags
& SHORT
)
1278 sp
= GET_ARG (N
, ap
, short *);
1281 else if (flags
& LONG
)
1283 lp
= GET_ARG (N
, ap
, long *);
1286 #ifndef _NO_LONGLONG
1287 else if (flags
& LONGDBL
)
1289 unsigned long long resll
;
1290 if (ccfn
== _wcstoul_r
)
1291 resll
= _wcstoull_r (rptr
, buf
, (wchar_t **) NULL
, base
);
1293 resll
= _wcstoll_r (rptr
, buf
, (wchar_t **) NULL
, base
);
1294 llp
= GET_ARG (N
, ap
, long long*);
1300 ip
= GET_ARG (N
, ap
, int *);
1308 #ifdef FLOATING_POINT
1311 /* scan a floating point number as if by wcstod */
1312 /* This code used to assume that the number of digits is reasonable.
1313 However, ANSI / ISO C makes no such stipulation; we have to get
1314 exact results even when there is an unreasonable amount of
1316 long leading_zeroes
= 0;
1317 long zeroes
, exp_adjust
;
1318 wchar_t *exp_start
= NULL
;
1319 unsigned width_left
= 0;
1323 if (width
== 0 || width
> sizeof (buf
) / sizeof (*buf
) - 1)
1325 /* size_t is unsigned, hence this optimisation */
1326 if (width
- 1 > sizeof (buf
) / sizeof (*buf
) - 2)
1329 width_left
= width
- (sizeof (buf
) / sizeof (*buf
) - 1);
1330 width
= sizeof (buf
) / sizeof (*buf
) - 1;
1332 flags
|= SIGNOK
| NDIGITS
| DPTOK
| EXPOK
;
1335 for (p
= buf
; width
; )
1337 c
= _fgetwc_r (rptr
, fp
);
1339 * This code mimicks the integer conversion
1340 * code, but is much simpler.
1345 if (flags
& NDIGITS
)
1366 if (nancount
+ infcount
== 0)
1368 flags
&= ~(SIGNOK
| NDIGITS
);
1383 if (nancount
== 0 && zeroes
== 0
1384 && (flags
& (NDIGITS
| DPTOK
| EXPOK
)) ==
1385 (NDIGITS
| DPTOK
| EXPOK
))
1387 flags
&= ~(SIGNOK
| DPTOK
| EXPOK
| NDIGITS
);
1396 if (infcount
== 1 || infcount
== 4)
1411 if (infcount
== 0 && zeroes
== 0
1412 && (flags
& (NDIGITS
| DPTOK
| EXPOK
)) ==
1413 (NDIGITS
| DPTOK
| EXPOK
))
1415 flags
&= ~(SIGNOK
| DPTOK
| EXPOK
| NDIGITS
);
1419 if (infcount
== 3 || infcount
== 5)
1451 /* no exponent without some digits */
1452 if ((flags
& (NDIGITS
| EXPOK
)) == EXPOK
1453 || ((flags
& EXPOK
) && zeroes
))
1455 if (! (flags
& DPTOK
))
1457 exp_adjust
= zeroes
- leading_zeroes
;
1461 (flags
& ~(EXPOK
| DPTOK
)) |
1468 if ((wchar_t) c
== decpt
&& (flags
& DPTOK
))
1470 flags
&= ~(SIGNOK
| DPTOK
);
1471 leading_zeroes
= zeroes
;
1477 _ungetwc_r (rptr
, c
, fp
);
1487 /* We may have a 'N' or possibly even [sign] 'N' 'a' as the
1488 start of 'NaN', only to run out of chars before it was
1489 complete (or having encountered a non-matching char). So
1490 check here if we have an outstanding nancount, and if so
1491 put back the chars we did swallow and treat as a failed
1494 FIXME - we still don't handle NAN([0xdigits]). */
1495 if (nancount
- 1U < 2U) /* nancount && nancount < 3 */
1497 /* Newlib's ungetc works even if we called __srefill in
1498 the middle of a partial parse, but POSIX does not
1499 guarantee that in all implementations of ungetc. */
1502 _ungetwc_r (rptr
, *--p
, fp
); /* [-+nNaA] */
1507 /* Likewise for 'inf' and 'infinity'. But be careful that
1508 'infinite' consumes only 3 characters, leaving the stream
1509 at the second 'i'. */
1510 if (infcount
- 1U < 7U) /* infcount && infcount < 8 */
1512 if (infcount
>= 3) /* valid 'inf', but short of 'infinity' */
1513 while (infcount
-- > 3)
1515 _ungetwc_r (rptr
, *--p
, fp
); /* [iInNtT] */
1522 _ungetwc_r (rptr
, *--p
, fp
); /* [-+iInN] */
1529 * If no digits, might be missing exponent digits
1530 * (just give back the exponent) or might be missing
1531 * regular digits, but had sign and/or decimal point.
1533 if (flags
& NDIGITS
)
1537 /* no digits at all */
1540 _ungetwc_r (rptr
, *--p
, fp
); /* [-+.] */
1545 /* just a bad exponent (e and maybe sign) */
1548 if (c
!= L
'e' && c
!= L
'E')
1550 _ungetwc_r (rptr
, c
, fp
); /* [-+] */
1554 _ungetwc_r (rptr
, c
, fp
); /* [eE] */
1556 if ((flags
& SUPPRESS
) == 0)
1560 #define QUAD_RES res;
1561 #else /* !_NO_LONG_DBL */
1562 long double qres
= 0;
1563 #define QUAD_RES qres;
1564 #endif /* !_NO_LONG_DBL */
1568 if ((flags
& (DPTOK
| EXPOK
)) == EXPOK
)
1570 exp_adjust
= zeroes
- leading_zeroes
;
1571 new_exp
= -exp_adjust
;
1574 else if (exp_adjust
)
1575 new_exp
= _wcstol_r (rptr
, (exp_start
+ 1), NULL
, 10) - exp_adjust
;
1579 /* If there might not be enough space for the new exponent,
1580 truncate some trailing digits to make room. */
1581 if (exp_start
>= buf
+ sizeof (buf
) / sizeof (*buf
)
1583 exp_start
= buf
+ sizeof (buf
) / sizeof (*buf
)
1585 swprintf (exp_start
, MAX_LONG_LEN
, L
"e%ld", new_exp
);
1588 /* FIXME: We don't have wcstold yet. */
1589 #if 0//ndef _NO_LONGDBL /* !_NO_LONGDBL */
1590 if (flags
& LONGDBL
)
1591 qres
= _wcstold_r (rptr
, buf
, NULL
);
1594 res
= _wcstod_r (rptr
, buf
, NULL
);
1598 dp
= GET_ARG (N
, ap
, double *);
1601 else if (flags
& LONGDBL
)
1603 ldp
= GET_ARG (N
, ap
, _LONG_DOUBLE
*);
1608 flp
= GET_ARG (N
, ap
, float *);
1618 #endif /* FLOATING_POINT */
1622 /* On read failure, return EOF failure regardless of matches; errno
1623 should have been set prior to here. On EOF failure (including
1624 invalid format string), return EOF if no matches yet, else number
1625 of matches made prior to failure. */
1626 nassigned
= nassigned
&& !(fp
->_flags
& __SERR
) ? nassigned
: EOF
;
1629 /* Return number of matches, which can be 0 on match failure. */
1630 _newlib_flockfile_end (fp
);
1631 #ifdef _WANT_IO_POSIX_EXTENSIONS
1637 #ifndef _NO_POS_ARGS
1638 /* Process all intermediate arguments. Fortunately, with wscanf, all
1639 intermediate arguments are sizeof(void*), so we don't need to scan
1640 ahead in the format string. */
1642 get_arg (int n
, va_list *ap
, int *numargs_p
, void **args
)
1644 int numargs
= *numargs_p
;
1645 while (n
>= numargs
)
1646 args
[numargs
++] = va_arg (*ap
, void *);
1647 *numargs_p
= numargs
;
1650 #endif /* !_NO_POS_ARGS */