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 * Copyright (c) 2012-2014 ARM Ltd
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
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
32 * permission.
33 *
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.
44 */
45
46 /*
47 FUNCTION
48 <<vfscanf>>, <<vscanf>>, <<vsscanf>>---format argument list
49
50 INDEX
51 vfscanf
52 INDEX
53 _vfscanf_r
54 INDEX
55 vscanf
56 INDEX
57 _vscanf_r
58 INDEX
59 vsscanf
60 INDEX
61 _vsscanf_r
62
63 SYNOPSIS
64 #include <stdio.h>
65 #include <stdarg.h>
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]>);
69
70 int vscanf( const char *<[fmt]>,
71 va_list <[list]>);
72 int vfscanf( FILE *<[fp]>, const char *<[fmt]>,
73 va_list <[list]>);
74 int vsscanf( const char *<[str]>,
75 const char *<[fmt]>, va_list <[list]>);
76
77 DESCRIPTION
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.
83
84 RETURNS
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.
89
90 If <<vscanf>> attempts to read at end-of-file, the return value
91 is <<EOF>>.
92
93 If no fields were stored, the return value is <<0>>.
94
95 The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are
96 reentrant versions which take an additional first parameter which points to the
97 reentrancy structure.
98
99 PORTABILITY
100 These are GNU extensions.
101
102 Supporting OS subroutines required:
103 */
104
105 #define _DEFAULT_SOURCE
106 #include <ctype.h>
107 #include <wctype.h>
108 #include <stdio.h>
109 #include <stdlib.h>
110 #include <stdint.h>
111 #include <limits.h>
112 #include <wchar.h>
113 #include <string.h>
114 #include <stdarg.h>
115 #include <errno.h>
116 #include "local.h"
117 #include "../stdlib/local.h"
118 #include "nano-vfscanf_local.h"
119
120 #define VFSCANF vfscanf
121 #ifdef STRING_ONLY
122 # define _SVFSCANF _ssvfscanf
123 #else
124 # define _SVFSCANF _svfscanf
125 #endif
126
127 /* vfscanf. */
128
129 #ifndef STRING_ONLY
130
131 int
VFSCANF(register FILE * fp,const char * fmt,va_list ap)132 VFSCANF (
133 register FILE *fp,
134 const char *fmt,
135 va_list ap)
136 {
137 CHECK_INIT(data, fp);
138 return _SVFSCANF (fp, fmt, ap);
139 }
140
141 int __nonnull((2))
142 vfiscanf ( FILE *, const char *, __VALIST)
143 _ATTRIBUTE ((__alias__("vfscanf")));
144 #endif /* !STRING_ONLY. */
145
146 #if defined (STRING_ONLY)
147 /* When dealing with the sscanf family, we don't want to use the
148 regular ungetc which will drag in file I/O items we don't need.
149 So, we create our own trimmed-down version. */
150 int
sungetc(int c,register FILE * fp)151 sungetc (
152 int c,
153 register FILE *fp)
154 {
155 if (c == EOF)
156 return (EOF);
157
158 /* After ungetc, we won't be at eof anymore. */
159 fp->_flags &= ~__SEOF;
160 c = (unsigned char) c;
161
162 /* If we are in the middle of ungetc'ing, just continue.
163 This may require expanding the current ungetc buffer. */
164
165 if (HASUB (fp))
166 {
167 if (fp->_r >= fp->_ub._size && __submore (fp))
168 return EOF;
169
170 *--fp->_p = c;
171 fp->_r++;
172 return c;
173 }
174
175 /* If we can handle this by simply backing up, do so,
176 but never replace the original character.
177 (This makes sscanf() work when scanning `const' data). */
178 if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
179 {
180 fp->_p--;
181 fp->_r++;
182 return c;
183 }
184
185 /* Create an ungetc buffer.
186 Initially, we will use the `reserve' buffer. */
187 fp->_ur = fp->_r;
188 fp->_up = fp->_p;
189 fp->_ub._base = fp->_ubuf;
190 fp->_ub._size = sizeof (fp->_ubuf);
191 fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
192 fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
193 fp->_r = 1;
194 return c;
195 }
196
197 /* String only version of __srefill_r for sscanf family. */
198 int
_ssrefill(register FILE * fp)199 _ssrefill (
200 register FILE * fp)
201 {
202 /* Our only hope of further input is the ungetc buffer.
203 If there is anything in that buffer to read, return. */
204 if (HASUB (fp))
205 {
206 FREEUB (ptr, fp);
207 if ((fp->_r = fp->_ur) != 0)
208 {
209 fp->_p = fp->_up;
210 return 0;
211 }
212 }
213
214 /* Otherwise we are out of character input. */
215 fp->_p = fp->_bf._base;
216 fp->_r = 0;
217 fp->_flags |= __SEOF;
218 return EOF;
219 }
220
221 #else
222 int sungetc ( int, register FILE *);
223 int _ssrefill ( register FILE *);
224 size_t sfread ( void *buf, size_t, size_t, FILE *);
225 #endif /* !STRING_ONLY. */
226
227 int
_SVFSCANF(register FILE * fp,char const * fmt0,va_list ap)228 _SVFSCANF (
229 register FILE *fp,
230 char const *fmt0,
231 va_list ap)
232 {
233 register u_char *fmt = (u_char *) fmt0;
234 register int c; /* Character from format, or conversion. */
235 register char *p; /* Points into all kinds of strings. */
236 char ccltab[256]; /* Character class table for %[...]. */
237 va_list ap_copy;
238
239 int ret;
240 char *cp;
241
242 struct _scan_data_t scan_data;
243
244 _newlib_flockfile_start (fp);
245
246 scan_data.nassigned = 0;
247 scan_data.nread = 0;
248 scan_data.ccltab = ccltab;
249 scan_data.pfn_ungetc = ungetc;
250 scan_data.pfn_refill = _srefill;
251
252 /* GCC PR 14577 at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 */
253 va_copy (ap_copy, ap);
254
255 for (;;)
256 {
257 if (*fmt == 0)
258 goto all_done;
259
260 if (isspace (*fmt))
261 {
262 while ((fp->_r > 0 || !scan_data.pfn_refill(fp))
263 && isspace (*fp->_p))
264 {
265 scan_data.nread++;
266 fp->_r--;
267 fp->_p++;
268 }
269 fmt++;
270 continue;
271 }
272 if ((c = *fmt++) != '%')
273 goto literal;
274
275 scan_data.width = 0;
276 scan_data.flags = 0;
277
278 if (*fmt == '*')
279 {
280 scan_data.flags |= SUPPRESS;
281 fmt++;
282 }
283
284 for (; is_digit (*fmt); fmt++)
285 scan_data.width = 10 * scan_data.width + to_digit (*fmt);
286
287 /* The length modifiers. */
288 p = "hlL";
289 if ((cp = memchr (p, *fmt, 3)) != NULL) {
290 scan_data.flags |= (SHORT << (cp - p));
291 fmt++;
292 }
293
294 /* Switch on the format. continue if done; break once format
295 type is derived. */
296 c = *fmt++;
297 switch (c)
298 {
299 case '%':
300 literal:
301 if ((fp->_r <= 0 && scan_data.pfn_refill(fp)))
302 goto input_failure;
303 if (*fp->_p != c)
304 goto match_failure;
305 fp->_r--, fp->_p++;
306 scan_data.nread++;
307 continue;
308
309 case 'p':
310 scan_data.flags |= POINTER;
311 __PICOLIBC_FALLTHROUGH;
312 case 'x':
313 case 'X':
314 scan_data.flags |= PFXOK;
315 scan_data.base = 16;
316 goto number;
317 case 'd':
318 case 'u':
319 scan_data.base = 10;
320 goto number;
321 case 'i':
322 scan_data.base = 0;
323 goto number;
324 case 'o':
325 scan_data.base = 8;
326 number:
327 scan_data.code = (c < 'o') ? CT_INT : CT_UINT;
328 break;
329
330 case '[':
331 fmt = (u_char *) __sccl (ccltab, (unsigned char *) fmt);
332 scan_data.flags |= NOSKIP;
333 scan_data.code = CT_CCL;
334 break;
335 case 'c':
336 scan_data.flags |= NOSKIP;
337 scan_data.code = CT_CHAR;
338 break;
339 case 's':
340 scan_data.code = CT_STRING;
341 break;
342
343 case 'n':
344 if (scan_data.flags & SUPPRESS) /* ??? */
345 continue;
346
347 if (scan_data.flags & SHORT)
348 *GET_ARG (N, ap_copy, short *) = scan_data.nread;
349 else if (scan_data.flags & LONG)
350 *GET_ARG (N, ap_copy, long *) = scan_data.nread;
351 else
352 *GET_ARG (N, ap_copy, int *) = scan_data.nread;
353
354 continue;
355
356 /* Disgusting backwards compatibility hacks. XXX. */
357 case '\0': /* compat. */
358 _newlib_flockfile_exit (fp);
359 va_end (ap_copy);
360 return EOF;
361
362 #ifdef FLOATING_POINT
363 case 'e': case 'E':
364 case 'f': case 'F':
365 case 'g': case 'G':
366 scan_data.code = CT_FLOAT;
367 break;
368 #endif
369 default: /* compat. */
370 scan_data.code = CT_INT;
371 scan_data.base = 10;
372 break;
373 }
374
375 /* We have a conversion that requires input. */
376 if ((fp->_r <= 0 && scan_data.pfn_refill (fp)))
377 goto input_failure;
378
379 /* Consume leading white space, except for formats that
380 suppress this. */
381 if ((scan_data.flags & NOSKIP) == 0)
382 {
383 while (isspace (*fp->_p))
384 {
385 scan_data.nread++;
386 if (--fp->_r > 0)
387 fp->_p++;
388 else if (scan_data.pfn_refill (fp))
389 goto input_failure;
390 }
391 /* Note that there is at least one character in the
392 buffer, so conversions that do not set NOSKIP ca
393 no longer result in an input failure. */
394 }
395 ret = 0;
396 if (scan_data.code < CT_INT)
397 ret = _scanf_chars (&scan_data, fp, &ap_copy);
398 else if (scan_data.code < CT_FLOAT)
399 ret = _scanf_i (&scan_data, fp, &ap_copy);
400 #ifdef FLOATING_POINT
401 else if (_scanf_float)
402 ret = _scanf_float (rptr, &scan_data, fp, &ap_copy);
403 #endif
404
405 if (ret == MATCH_FAILURE)
406 goto match_failure;
407 else if (ret == INPUT_FAILURE)
408 goto input_failure;
409 }
410 input_failure:
411 /* On read failure, return EOF failure regardless of matches; errno
412 should have been set prior to here. On EOF failure (including
413 invalid format string), return EOF if no matches yet, else number
414 of matches made prior to failure. */
415 _newlib_flockfile_exit (fp);
416 va_end (ap_copy);
417 return scan_data.nassigned && !(fp->_flags & __SERR) ? scan_data.nassigned
418 : EOF;
419 match_failure:
420 all_done:
421 /* Return number of matches, which can be 0 on match failure. */
422 _newlib_flockfile_end (fp);
423 va_end (ap_copy);
424 return scan_data.nassigned;
425 }
426
427 #ifdef STRING_ONLY
428 int
429 _ssvfiscanf ( FILE *, const char *, __VALIST)
430 _ATTRIBUTE ((__alias__("_ssvfscanf")));
431 #else
432 int
433 _svfiscanf ( FILE *, const char *, __VALIST)
434 _ATTRIBUTE ((__alias__("_svfscanf")));
435 #endif
436
437