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.
19 * Copyright (c) 2012-2014 ARM Ltd
20 * All rights reserved.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
25 * 1. Redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. The name of the company may not be used to endorse or promote
31 * products derived from this software without specific prior written
34 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
35 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
37 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
39 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
40 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
41 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
42 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
43 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 <<vfscanf>>, <<vscanf>>, <<vsscanf>>---format argument list
66 int vscanf(const char *<[fmt]>, va_list <[list]>);
67 int vfscanf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
68 int vsscanf(const char *<[str]>, const char *<[fmt]>, va_list <[list]>);
70 int _vscanf_r(struct _reent *<[reent]>, const char *<[fmt]>,
72 int _vfscanf_r(struct _reent *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
74 int _vsscanf_r(struct _reent *<[reent]>, const char *<[str]>,
75 const char *<[fmt]>, va_list <[list]>);
78 <<vscanf>>, <<vfscanf>>, and <<vsscanf>> are (respectively) variants
79 of <<scanf>>, <<fscanf>>, and <<sscanf>>. They differ only in
80 allowing their caller to pass the variable argument list as a
81 <<va_list>> object (initialized by <<va_start>>) rather than
82 directly accepting a variable number of arguments.
85 The return values are consistent with the corresponding functions:
86 <<vscanf>> returns the number of input fields successfully scanned,
87 converted, and stored; the return value does not include scanned
88 fields which were not stored.
90 If <<vscanf>> attempts to read at end-of-file, the return value
93 If no fields were stored, the return value is <<0>>.
95 The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are
96 reentrant versions which take an additional first parameter which points to the
100 These are GNU extensions.
102 Supporting OS subroutines required:
119 #include "../stdlib/local.h"
120 #include "nano-vfscanf_local.h"
122 #define VFSCANF vfscanf
123 #define _VFSCANF_R _vfscanf_r
124 #define __SVFSCANF __svfscanf
126 # define __SVFSCANF_R __ssvfscanf_r
128 # define __SVFSCANF_R __svfscanf_r
138 VFSCANF (register FILE *fp
,
142 CHECK_INIT(_REENT
, fp
);
143 return __SVFSCANF_R (_REENT
, fp
, fmt
, ap
);
147 vfiscanf (FILE *, const char *, __VALIST
)
148 _ATTRIBUTE ((__alias__("vfscanf")));
151 __SVFSCANF (register FILE *fp
,
155 return __SVFSCANF_R (_REENT
, fp
, fmt0
, ap
);
161 _VFSCANF_R (struct _reent
*data
,
166 CHECK_INIT(data
, fp
);
167 return __SVFSCANF_R (data
, fp
, fmt
, ap
);
171 _vfiscanf_r (struct _reent
*, FILE *, const char *, __VALIST
)
172 _ATTRIBUTE ((__alias__("_vfscanf_r")));
173 #endif /* !STRING_ONLY. */
175 #if defined (STRING_ONLY)
176 /* When dealing with the sscanf family, we don't want to use the
177 regular ungetc which will drag in file I/O items we don't need.
178 So, we create our own trimmed-down version. */
180 _sungetc_r (struct _reent
*data
,
187 /* After ungetc, we won't be at eof anymore. */
188 fp
->_flags
&= ~__SEOF
;
189 c
= (unsigned char) c
;
191 /* If we are in the middle of ungetc'ing, just continue.
192 This may require expanding the current ungetc buffer. */
196 if (fp
->_r
>= fp
->_ub
._size
&& __submore (data
, fp
))
204 /* If we can handle this by simply backing up, do so,
205 but never replace the original character.
206 (This makes sscanf() work when scanning `const' data). */
207 if (fp
->_bf
._base
!= NULL
&& fp
->_p
> fp
->_bf
._base
&& fp
->_p
[-1] == c
)
214 /* Create an ungetc buffer.
215 Initially, we will use the `reserve' buffer. */
218 fp
->_ub
._base
= fp
->_ubuf
;
219 fp
->_ub
._size
= sizeof (fp
->_ubuf
);
220 fp
->_ubuf
[sizeof (fp
->_ubuf
) - 1] = c
;
221 fp
->_p
= &fp
->_ubuf
[sizeof (fp
->_ubuf
) - 1];
226 /* String only version of __srefill_r for sscanf family. */
228 __ssrefill_r (struct _reent
* ptr
,
231 /* Our only hope of further input is the ungetc buffer.
232 If there is anything in that buffer to read, return. */
236 if ((fp
->_r
= fp
->_ur
) != 0)
243 /* Otherwise we are out of character input. */
244 fp
->_p
= fp
->_bf
._base
;
246 fp
->_flags
|= __SEOF
;
251 int _sungetc_r (struct _reent
*, int, register FILE *);
252 int __ssrefill_r (struct _reent
*, register FILE *);
253 size_t _sfread_r (struct _reent
*, void *buf
, size_t, size_t, FILE *);
254 #endif /* !STRING_ONLY. */
257 __SVFSCANF_R (struct _reent
*rptr
,
262 register u_char
*fmt
= (u_char
*) fmt0
;
263 register int c
; /* Character from format, or conversion. */
264 register char *p
; /* Points into all kinds of strings. */
265 char ccltab
[256]; /* Character class table for %[...]. */
271 struct _scan_data_t scan_data
;
272 int (*scan_func
)(struct _reent
*, struct _scan_data_t
*, FILE *, va_list *);
274 _newlib_flockfile_start (fp
);
276 scan_data
.nassigned
= 0;
278 scan_data
.ccltab
= ccltab
;
279 scan_data
.pfn_ungetc
= _ungetc_r
;
280 scan_data
.pfn_refill
= __srefill_r
;
282 /* GCC PR 14577 at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 */
283 va_copy (ap_copy
, ap
);
292 while ((fp
->_r
> 0 || !scan_data
.pfn_refill(rptr
, fp
))
293 && isspace (*fp
->_p
))
302 if ((c
= *fmt
++) != '%')
310 scan_data
.flags
|= SUPPRESS
;
314 for (; is_digit (*fmt
); fmt
++)
315 scan_data
.width
= 10 * scan_data
.width
+ to_digit (*fmt
);
317 /* The length modifiers. */
319 if ((cp
= memchr (p
, *fmt
, 3)) != NULL
) {
320 scan_data
.flags
|= (SHORT
<< (cp
- p
));
324 /* Switch on the format. continue if done; break once format
331 if ((fp
->_r
<= 0 && scan_data
.pfn_refill(rptr
, fp
)))
340 scan_data
.flags
|= POINTER
;
343 scan_data
.flags
|= PFXOK
;
356 scan_data
.code
= (c
< 'o') ? CT_INT
: CT_UINT
;
360 fmt
= (u_char
*) __sccl (ccltab
, (unsigned char *) fmt
);
361 scan_data
.flags
|= NOSKIP
;
362 scan_data
.code
= CT_CCL
;
365 scan_data
.flags
|= NOSKIP
;
366 scan_data
.code
= CT_CHAR
;
369 scan_data
.code
= CT_STRING
;
373 if (scan_data
.flags
& SUPPRESS
) /* ??? */
376 if (scan_data
.flags
& SHORT
)
377 *GET_ARG (N
, ap_copy
, short *) = scan_data
.nread
;
378 else if (scan_data
.flags
& LONG
)
379 *GET_ARG (N
, ap_copy
, long *) = scan_data
.nread
;
381 *GET_ARG (N
, ap_copy
, int *) = scan_data
.nread
;
385 /* Disgusting backwards compatibility hacks. XXX. */
386 case '\0': /* compat. */
387 _newlib_flockfile_exit (fp
);
391 #ifdef FLOATING_POINT
395 scan_data
.code
= CT_FLOAT
;
398 default: /* compat. */
399 scan_data
.code
= CT_INT
;
404 /* We have a conversion that requires input. */
405 if ((fp
->_r
<= 0 && scan_data
.pfn_refill (rptr
, fp
)))
408 /* Consume leading white space, except for formats that
410 if ((scan_data
.flags
& NOSKIP
) == 0)
412 while (isspace (*fp
->_p
))
417 else if (scan_data
.pfn_refill (rptr
, fp
))
420 /* Note that there is at least one character in the
421 buffer, so conversions that do not set NOSKIP ca
422 no longer result in an input failure. */
425 if (scan_data
.code
< CT_INT
)
426 ret
= _scanf_chars (rptr
, &scan_data
, fp
, &ap_copy
);
427 else if (scan_data
.code
< CT_FLOAT
)
428 ret
= _scanf_i (rptr
, &scan_data
, fp
, &ap_copy
);
429 #ifdef FLOATING_POINT
430 else if (_scanf_float
)
431 ret
= _scanf_float (rptr
, &scan_data
, fp
, &ap_copy
);
434 if (ret
== MATCH_FAILURE
)
436 else if (ret
== INPUT_FAILURE
)
440 /* On read failure, return EOF failure regardless of matches; errno
441 should have been set prior to here. On EOF failure (including
442 invalid format string), return EOF if no matches yet, else number
443 of matches made prior to failure. */
444 _newlib_flockfile_exit (fp
);
446 return scan_data
.nassigned
&& !(fp
->_flags
& __SERR
) ? scan_data
.nassigned
450 /* Return number of matches, which can be 0 on match failure. */
451 _newlib_flockfile_end (fp
);
453 return scan_data
.nassigned
;
458 __ssvfiscanf_r (struct _reent
*, FILE *, const char *, __VALIST
)
459 _ATTRIBUTE ((__alias__("__ssvfscanf_r")));
462 __svfiscanf_r (struct _reent
*, FILE *, const char *, __VALIST
)
463 _ATTRIBUTE ((__alias__("__svfscanf_r")));