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           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