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