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