Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libc / stdio / nano-vfscanf.c
blob57d25b82aa9297c4676157c1bbb94355970c278c
1 /*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
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
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.
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.
47 FUNCTION
48 <<vfscanf>>, <<vscanf>>, <<vsscanf>>---format argument list
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
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]>);
70 int _vscanf_r(struct _reent *<[reent]>, const char *<[fmt]>,
71 va_list <[list]>);
72 int _vfscanf_r(struct _reent *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
73 va_list <[list]>);
74 int _vsscanf_r(struct _reent *<[reent]>, const char *<[str]>,
75 const char *<[fmt]>, va_list <[list]>);
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.
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.
90 If <<vscanf>> attempts to read at end-of-file, the return value
91 is <<EOF>>.
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
97 reentrancy structure.
99 PORTABILITY
100 These are GNU extensions.
102 Supporting OS subroutines required:
105 #include <_ansi.h>
106 #include <reent.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"
122 #define VFSCANF vfscanf
123 #define _VFSCANF_R _vfscanf_r
124 #define __SVFSCANF __svfscanf
125 #ifdef STRING_ONLY
126 # define __SVFSCANF_R __ssvfscanf_r
127 #else
128 # define __SVFSCANF_R __svfscanf_r
129 #endif
131 /* vfscanf. */
133 #ifndef STRING_ONLY
135 #ifndef _REENT_ONLY
138 VFSCANF (register FILE *fp,
139 const char *fmt,
140 va_list ap)
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,
152 char const *fmt0,
153 va_list ap)
155 return __SVFSCANF_R (_REENT, fp, fmt0, ap);
158 #endif
161 _VFSCANF_R (struct _reent *data,
162 register FILE *fp,
163 const char *fmt,
164 va_list ap)
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,
181 int c,
182 register FILE *fp)
184 if (c == EOF)
185 return (EOF);
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. */
194 if (HASUB (fp))
196 if (fp->_r >= fp->_ub._size && __submore (data, fp))
197 return EOF;
199 *--fp->_p = c;
200 fp->_r++;
201 return c;
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)
209 fp->_p--;
210 fp->_r++;
211 return c;
214 /* Create an ungetc buffer.
215 Initially, we will use the `reserve' buffer. */
216 fp->_ur = fp->_r;
217 fp->_up = fp->_p;
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];
222 fp->_r = 1;
223 return c;
226 /* String only version of __srefill_r for sscanf family. */
228 __ssrefill_r (struct _reent * ptr,
229 register FILE * fp)
231 /* Our only hope of further input is the ungetc buffer.
232 If there is anything in that buffer to read, return. */
233 if (HASUB (fp))
235 FREEUB (ptr, fp);
236 if ((fp->_r = fp->_ur) != 0)
238 fp->_p = fp->_up;
239 return 0;
243 /* Otherwise we are out of character input. */
244 fp->_p = fp->_bf._base;
245 fp->_r = 0;
246 fp->_flags |= __SEOF;
247 return EOF;
250 #else
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,
258 register FILE *fp,
259 char const *fmt0,
260 va_list ap)
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 %[...]. */
266 va_list ap_copy;
268 int ret;
269 char *cp;
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;
277 scan_data.nread = 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);
285 for (;;)
287 if (*fmt == 0)
288 goto all_done;
290 if (isspace (*fmt))
292 while ((fp->_r > 0 || !scan_data.pfn_refill(rptr, fp))
293 && isspace (*fp->_p))
295 scan_data.nread++;
296 fp->_r--;
297 fp->_p++;
299 fmt++;
300 continue;
302 if ((c = *fmt++) != '%')
303 goto literal;
305 scan_data.width = 0;
306 scan_data.flags = 0;
308 if (*fmt == '*')
310 scan_data.flags |= SUPPRESS;
311 fmt++;
314 for (; is_digit (*fmt); fmt++)
315 scan_data.width = 10 * scan_data.width + to_digit (*fmt);
317 /* The length modifiers. */
318 p = "hlL";
319 if ((cp = memchr (p, *fmt, 3)) != NULL) {
320 scan_data.flags |= (SHORT << (cp - p));
321 fmt++;
324 /* Switch on the format. continue if done; break once format
325 type is derived. */
326 c = *fmt++;
327 switch (c)
329 case '%':
330 literal:
331 if ((fp->_r <= 0 && scan_data.pfn_refill(rptr, fp)))
332 goto input_failure;
333 if (*fp->_p != c)
334 goto match_failure;
335 fp->_r--, fp->_p++;
336 scan_data.nread++;
337 continue;
339 case 'p':
340 scan_data.flags |= POINTER;
341 case 'x':
342 case 'X':
343 scan_data.flags |= PFXOK;
344 scan_data.base = 16;
345 goto number;
346 case 'd':
347 case 'u':
348 scan_data.base = 10;
349 goto number;
350 case 'i':
351 scan_data.base = 0;
352 goto number;
353 case 'o':
354 scan_data.base = 8;
355 number:
356 scan_data.code = (c < 'o') ? CT_INT : CT_UINT;
357 break;
359 case '[':
360 fmt = (u_char *) __sccl (ccltab, (unsigned char *) fmt);
361 scan_data.flags |= NOSKIP;
362 scan_data.code = CT_CCL;
363 break;
364 case 'c':
365 scan_data.flags |= NOSKIP;
366 scan_data.code = CT_CHAR;
367 break;
368 case 's':
369 scan_data.code = CT_STRING;
370 break;
372 case 'n':
373 if (scan_data.flags & SUPPRESS) /* ??? */
374 continue;
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;
380 else
381 *GET_ARG (N, ap_copy, int *) = scan_data.nread;
383 continue;
385 /* Disgusting backwards compatibility hacks. XXX. */
386 case '\0': /* compat. */
387 _newlib_flockfile_exit (fp);
388 va_end (ap_copy);
389 return EOF;
391 #ifdef FLOATING_POINT
392 case 'e': case 'E':
393 case 'f': case 'F':
394 case 'g': case 'G':
395 scan_data.code = CT_FLOAT;
396 break;
397 #endif
398 default: /* compat. */
399 scan_data.code = CT_INT;
400 scan_data.base = 10;
401 break;
404 /* We have a conversion that requires input. */
405 if ((fp->_r <= 0 && scan_data.pfn_refill (rptr, fp)))
406 goto input_failure;
408 /* Consume leading white space, except for formats that
409 suppress this. */
410 if ((scan_data.flags & NOSKIP) == 0)
412 while (isspace (*fp->_p))
414 scan_data.nread++;
415 if (--fp->_r > 0)
416 fp->_p++;
417 else if (scan_data.pfn_refill (rptr, fp))
418 goto input_failure;
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. */
424 ret = 0;
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);
432 #endif
434 if (ret == MATCH_FAILURE)
435 goto match_failure;
436 else if (ret == INPUT_FAILURE)
437 goto input_failure;
439 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);
445 va_end (ap_copy);
446 return scan_data.nassigned && !(fp->_flags & __SERR) ? scan_data.nassigned
447 : EOF;
448 match_failure:
449 all_done:
450 /* Return number of matches, which can be 0 on match failure. */
451 _newlib_flockfile_end (fp);
452 va_end (ap_copy);
453 return scan_data.nassigned;
456 #ifdef STRING_ONLY
458 __ssvfiscanf_r (struct _reent *, FILE *, const char *, __VALIST)
459 _ATTRIBUTE ((__alias__("__ssvfscanf_r")));
460 #else
462 __svfiscanf_r (struct _reent *, FILE *, const char *, __VALIST)
463 _ATTRIBUTE ((__alias__("__svfscanf_r")));
464 #endif