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 FUNCTION
20 <<vfscanf>>, <<vscanf>>, <<vsscanf>>---format argument list
21
22 INDEX
23 vfscanf
24 INDEX
25 _vfscanf_r
26 INDEX
27 vscanf
28 INDEX
29 _vscanf_r
30 INDEX
31 vsscanf
32 INDEX
33 _vsscanf_r
34
35 SYNOPSIS
36 #include <stdio.h>
37 #include <stdarg.h>
38 int vscanf(const char *<[fmt]>, va_list <[list]>);
39 int vfscanf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
40 int vsscanf(const char *<[str]>, const char *<[fmt]>, va_list <[list]>);
41
42 int vscanf( const char *<[fmt]>,
43 va_list <[list]>);
44 int vfscanf( FILE *<[fp]>, const char *<[fmt]>,
45 va_list <[list]>);
46 int vsscanf( const char *<[str]>,
47 const char *<[fmt]>, va_list <[list]>);
48
49 DESCRIPTION
50 <<vscanf>>, <<vfscanf>>, and <<vsscanf>> are (respectively) variants
51 of <<scanf>>, <<fscanf>>, and <<sscanf>>. They differ only in
52 allowing their caller to pass the variable argument list as a
53 <<va_list>> object (initialized by <<va_start>>) rather than
54 directly accepting a variable number of arguments.
55
56 RETURNS
57 The return values are consistent with the corresponding functions:
58 <<vscanf>> returns the number of input fields successfully scanned,
59 converted, and stored; the return value does not include scanned
60 fields which were not stored.
61
62 If <<vscanf>> attempts to read at end-of-file, the return value
63 is <<EOF>>.
64
65 If no fields were stored, the return value is <<0>>.
66
67 The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are
68 reentrant versions which take an additional first parameter which points to the
69 reentrancy structure.
70
71 PORTABILITY
72 These are GNU extensions.
73
74 Supporting OS subroutines required:
75 */
76
77 #define _DEFAULT_SOURCE
78 #include <ctype.h>
79 #include <wctype.h>
80 #include <stdio.h>
81 #include <stdlib.h>
82 #include <stdint.h>
83 #include <limits.h>
84 #include <wchar.h>
85 #include <string.h>
86 #include <stdarg.h>
87 #include <errno.h>
88 #include "local.h"
89 #include "../stdlib/local.h"
90
91 #ifdef INTEGER_ONLY
92 #define VFSCANF vfiscanf
93 #ifdef STRING_ONLY
94 # define _SVFSCANF _ssvfiscanf
95 #else
96 # define _SVFSCANF _svfiscanf
97 #endif
98 #else
99 #define VFSCANF vfscanf
100 #ifdef STRING_ONLY
101 # define _SVFSCANF _ssvfscanf
102 #else
103 # define _SVFSCANF _svfscanf
104 #endif
105 #ifndef NO_FLOATING_POINT
106 #define FLOATING_POINT
107 #endif
108 #endif
109
110 #ifdef STRING_ONLY
111 #undef _newlib_flockfile_start
112 #undef _newlib_flockfile_exit
113 #undef _newlib_flockfile_end
114 #define _newlib_flockfile_start(x) {}
115 #define _newlib_flockfile_exit(x) {}
116 #define _newlib_flockfile_end(x) {}
117 #define _ungetc_r _sungetc_r
118 #define __srefill_r __ssrefill_r
119 #define _fread_r _sfread_r
120 #endif
121
122 #ifdef FLOATING_POINT
123 #include <math.h>
124 #include <float.h>
125 #include <locale.h>
126
127 /* Currently a test is made to see if long double processing is warranted.
128 This could be changed in the future should the __ldtoa code be
129 preferred over __dtoa. */
130 #define _NO_LONGDBL
131 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG == 64)
132 #undef _NO_LONGDBL
133 #endif
134
135 #include "floatio.h"
136
137 #define BUF (MAXEXP+MAXFRACT+MB_LEN_MAX+2) /* decimal point + sign + NUL */
138
139 /* An upper bound for how long a long prints in decimal. 4 / 13 approximates
140 log (2). Add one char for roundoff compensation and one for the sign. */
141 #define MAX_LONG_LEN ((CHAR_BIT * sizeof (long) - 1) * 4 / 13 + 2)
142 #else
143 #define BUF 40
144 #endif
145
146 #define _NO_LONGLONG
147 #if defined _WANT_IO_LONG_LONG \
148 && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
149 # undef _NO_LONGLONG
150 #endif
151
152 #define _NO_POS_ARGS
153 #ifdef _WANT_IO_POS_ARGS
154 # undef _NO_POS_ARGS
155 # ifdef NL_ARGMAX
156 # define MAX_POS_ARGS NL_ARGMAX
157 # else
158 # define MAX_POS_ARGS 32
159 # endif
160
161 typedef struct {
162 va_list ap;
163 } my_va_list;
164
165 static void * get_arg (int, my_va_list *, int *, void **);
166 #endif /* _WANT_IO_POS_ARGS */
167
168 /*
169 * Flags used during conversion.
170 */
171
172 #define LONG 0x01 /* l: long or double */
173 #define LONGDBL 0x02 /* L/ll: long double or long long */
174 #define SHORT 0x04 /* h: short */
175 #define CHAR 0x08 /* hh: 8 bit integer */
176 #define SUPPRESS 0x10 /* suppress assignment */
177 #define POINTER 0x20 /* weird %p pointer (`fake hex') */
178 #define NOSKIP 0x40 /* do not skip blanks */
179 #define MALLOC 0x80 /* handle 'm' modifier */
180
181 /*
182 * The following are used in numeric conversions only:
183 * SIGNOK, NDIGITS, DPTOK, EXPOK and HEXFLT are for floating point;
184 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
185 */
186
187 #define SIGNOK 0x80 /* +/- is (still) legal */
188 #define NDIGITS 0x100 /* no digits detected */
189
190 #define DPTOK 0x200 /* (float) decimal point is still legal */
191 #define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */
192 #define HEXFLT 0x800 /* (float) hex prefix found, expect hex float */
193
194 #define PFXOK 0x200 /* 0x prefix is (still) legal */
195 #define NZDIGITS 0x400 /* no zero digits detected */
196 #define NNZDIGITS 0x800 /* no non-zero digits detected */
197
198 /*
199 * Conversion types.
200 */
201
202 #define CT_CHAR 0 /* %c conversion */
203 #define CT_CCL 1 /* %[...] conversion */
204 #define CT_STRING 2 /* %s conversion */
205 #define CT_INT 3 /* integer, i.e., strtol or strtoul */
206 #define CT_FLOAT 4 /* floating, i.e., strtod */
207
208 #define u_char unsigned char
209 #define u_long unsigned long
210
211 #ifndef _NO_LONGLONG
212 typedef unsigned long long u_long_long;
213 #endif
214
215 /*
216 * vfscanf
217 */
218
219 #define BufferEmpty (fp->_r <= 0 && _srefill( fp))
220
221 #ifndef STRING_ONLY
222
223 int
VFSCANF(register FILE * fp,const char * fmt,va_list ap)224 VFSCANF (
225 register FILE *fp,
226 const char *fmt,
227 va_list ap)
228 {
229 CHECK_INIT(data, fp);
230 return _SVFSCANF (fp, fmt, ap);
231 }
232 #endif /* !STRING_ONLY */
233
234 #if defined (STRING_ONLY) && defined (INTEGER_ONLY)
235 /* When dealing with the sscanf family, we don't want to use the
236 * regular ungetc which will drag in file I/O items we don't need.
237 * So, we create our own trimmed-down version. */
238 int
sungetc(int c,register FILE * fp)239 sungetc (
240 int c,
241 register FILE *fp)
242 {
243 if (c == EOF)
244 return (EOF);
245
246 /* After ungetc, we won't be at eof anymore */
247 fp->_flags &= ~__SEOF;
248 c = (unsigned char) c;
249
250 /*
251 * If we are in the middle of ungetc'ing, just continue.
252 * This may require expanding the current ungetc buffer.
253 */
254
255 if (HASUB (fp))
256 {
257 if (fp->_r >= fp->_ub._size && __submore (fp))
258 {
259 return EOF;
260 }
261 *--fp->_p = c;
262 fp->_r++;
263 return c;
264 }
265
266 /*
267 * If we can handle this by simply backing up, do so,
268 * but never replace the original character.
269 * (This makes sscanf() work when scanning `const' data.)
270 */
271
272 if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
273 {
274 fp->_p--;
275 fp->_r++;
276 return c;
277 }
278
279 /*
280 * Create an ungetc buffer.
281 * Initially, we will use the `reserve' buffer.
282 */
283
284 fp->_ur = fp->_r;
285 fp->_up = fp->_p;
286 fp->_ub._base = fp->_ubuf;
287 fp->_ub._size = sizeof (fp->_ubuf);
288 fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
289 fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
290 fp->_r = 1;
291 return c;
292 }
293
294 /* String only version of __srefill_r for sscanf family. */
295 int
_ssrefill(register FILE * fp)296 _ssrefill (
297 register FILE * fp)
298 {
299 /*
300 * Our only hope of further input is the ungetc buffer.
301 * If there is anything in that buffer to read, return.
302 */
303 if (HASUB (fp))
304 {
305 FREEUB (ptr, fp);
306 if ((fp->_r = fp->_ur) != 0)
307 {
308 fp->_p = fp->_up;
309 return 0;
310 }
311 }
312
313 /* Otherwise we are out of character input. */
314 fp->_p = fp->_bf._base;
315 fp->_r = 0;
316 fp->_flags |= __SEOF;
317 return EOF;
318 }
319
320 size_t
_sfread(void * buf,size_t size,size_t count,FILE * fp)321 _sfread (
322 void *buf,
323 size_t size,
324 size_t count,
325 FILE * fp)
326 {
327 register size_t resid;
328 register char *p;
329 register int r;
330 size_t total;
331
332 if ((resid = count * size) == 0)
333 return 0;
334
335 total = resid;
336 p = buf;
337
338 while (resid > (size_t) (r = fp->_r))
339 {
340 (void) memcpy ((void *) p, (void *) fp->_p, (size_t) r);
341 fp->_p += r;
342 fp->_r = 0;
343 p += r;
344 resid -= r;
345 if (_ssrefill ( fp))
346 {
347 /* no more input: return partial result */
348 return (total - resid) / size;
349 }
350 }
351 (void) memcpy ((void *) p, (void *) fp->_p, resid);
352 fp->_r -= resid;
353 fp->_p += resid;
354 return count;
355 }
356 #else /* !STRING_ONLY || !INTEGER_ONLY */
357 int sungetc ( int, register FILE *);
358 int _ssrefill ( register FILE *);
359 size_t sfread ( void *buf, size_t, size_t, FILE *);
360 #endif /* !STRING_ONLY || !INTEGER_ONLY */
361
362 static inline int
__wctob(wint_t wc)363 __wctob (wint_t wc)
364 {
365 mbstate_t mbs;
366 unsigned char pmb[MB_LEN_MAX];
367
368 if (wc == WEOF)
369 return EOF;
370 memset (&mbs, '\0', sizeof (mbs));
371 return __WCTOMB ((char *) pmb, wc, &mbs) == 1 ? (int) pmb[0] : 0;
372 }
373
374 int
_SVFSCANF(register FILE * fp,char const * fmt0,va_list ap)375 _SVFSCANF (
376 register FILE *fp,
377 char const *fmt0,
378 va_list ap)
379 {
380 register u_char *fmt = (u_char *) fmt0;
381 register int c; /* character from format, or conversion */
382 register size_t width; /* field width, or 0 */
383 register char *p; /* points into all kinds of strings */
384 register int n; /* handy integer */
385 register int flags; /* flags as defined above */
386 register char *p0; /* saves original value of p when necessary */
387 int nassigned; /* number of fields assigned */
388 int nread; /* number of characters consumed from fp */
389 #ifndef _NO_POS_ARGS
390 int N; /* arg number */
391 int arg_index = 0; /* index into args processed directly */
392 int numargs = 0; /* number of varargs read */
393 my_va_list my_ap;
394 va_copy(my_ap.ap, ap);
395 void *args[MAX_POS_ARGS]; /* positional args read */
396 int is_pos_arg; /* is current format positional? */
397 #endif
398 int base = 0; /* base argument to strtol/strtoul */
399 int nbytes = 1; /* number of bytes read from fmt string */
400 wchar_t wc; /* wchar to use to read format string */
401 wchar_t *wcp; /* handy wide character pointer */
402 size_t mbslen = 0; /* length of converted multibyte sequence */
403 #ifdef _MB_CAPABLE
404 mbstate_t state; /* value to keep track of multibyte state */
405 #endif
406 #ifdef _WANT_IO_C99_FORMATS
407 #define _WANT_IO_POSIX_EXTENSIONS
408 #endif
409 #ifdef _WANT_IO_POSIX_EXTENSIONS
410 #ifdef __GNUC__
411 #pragma GCC diagnostic ignored "-Wpragmas"
412 #pragma GCC diagnostic ignored "-Wunknown-warning-option"
413 #pragma GCC diagnostic ignored "-Wanalyzer-null-dereference"
414 #endif
415
416 /* POSIX requires that fscanf frees all allocated strings from 'm'
417 conversions in case it returns EOF. m_ptr is used to keep track.
418 It will be allocated on the stack the first time an 'm' conversion
419 takes place, and it will be free'd on return from the function.
420 This implementation tries to save space by only allocating 8
421 pointer slots at a time. Most scenarios should never have to call
422 realloc again. This implementation allows only up to 65528 'm'
423 conversions per fscanf invocation for now. That should be enough
424 for almost all scenarios, right? */
425 struct m_ptrs {
426 void ***m_arr; /* Array of pointer args to 'm' conversion */
427 uint16_t m_siz; /* Number of slots in m_arr */
428 uint16_t m_cnt; /* Number of valid entries in m_arr */
429 } *m_ptr = NULL, m_store;
430 #define init_m_ptr() \
431 do \
432 { \
433 if (!m_ptr) \
434 { \
435 m_ptr = &m_store; \
436 m_ptr->m_arr = NULL; \
437 m_ptr->m_siz = 0; \
438 m_ptr->m_cnt = 0; \
439 } \
440 } \
441 while (0)
442 #define push_m_ptr(arg) \
443 do \
444 { \
445 if (m_ptr->m_cnt >= m_ptr->m_siz) \
446 { \
447 void ***n = NULL; \
448 \
449 if (m_ptr->m_siz + 8 > 0 && m_ptr->m_siz + 8 < UINT16_MAX) \
450 n = (void ***) realloc (m_ptr->m_arr, \
451 (m_ptr->m_siz + 8) * \
452 sizeof (void **)); \
453 if (!n) \
454 { \
455 nassigned = EOF; \
456 goto match_failure; \
457 } \
458 m_ptr->m_arr = n; \
459 m_ptr->m_siz += 8; \
460 } \
461 m_ptr->m_arr[m_ptr->m_cnt++] = (void **) (arg); \
462 } \
463 while (0)
464 #define alloc_m_ptr(_type, _p, _p0, _p_p, _w) \
465 ({ \
466 _p_p = GET_ARG (N, ap, _type **); \
467 if (!_p_p) \
468 goto match_failure; \
469 _p0 = (_type *) malloc ((_w) * sizeof (_type)); \
470 if (!_p0) \
471 { \
472 nassigned = EOF; \
473 goto match_failure; \
474 } \
475 *_p_p = _p0; \
476 push_m_ptr (_p_p); \
477 _p = _p0; \
478 _w; \
479 })
480 /* For systems with wchar_t == 2 (UTF-16) check if there's room for
481 at least 2 wchar_t's (surrogate pairs). */
482 #define realloc_m_ptr(_type, _p, _p0, _p_p, _w) \
483 ({ \
484 size_t _nw = (_w); \
485 ptrdiff_t _dif = _p - _p0; \
486 if (_p_p && \
487 ((sizeof (_type) == 2 && (size_t) _dif >= _nw - 1) \
488 || (size_t) _dif >= _nw)) \
489 { \
490 _p0 = (_type *) realloc (_p0, (_nw << 1) * sizeof (_type)); \
491 if (!_p0) \
492 { \
493 nassigned = EOF; \
494 goto match_failure; \
495 } \
496 _p = _p0 + _dif; \
497 *_p_p = _p0; \
498 _nw <<= 1; \
499 } \
500 _nw; \
501 })
502 #define shrink_m_ptr(_type, _p_p, _w, _cw) \
503 ({ \
504 size_t _nw = (_w); \
505 if (_p_p && _nw < _cw) \
506 { \
507 _type *_np_p = (_type *) \
508 realloc (*_p_p, _nw * sizeof (_type)); \
509 if (_np_p) \
510 *_p_p = _np_p; \
511 } \
512 })
513 #define free_m_ptr() \
514 do \
515 { \
516 if (m_ptr) \
517 { \
518 if (nassigned == EOF) \
519 { \
520 unsigned i; \
521 for (i = 0; i < m_ptr->m_cnt; ++i) \
522 { \
523 free (*m_ptr->m_arr[i]); \
524 *m_ptr->m_arr[i] = NULL; \
525 } \
526 } \
527 if (m_ptr->m_arr) \
528 free (m_ptr->m_arr); \
529 } \
530 } \
531 while (0)
532 #endif
533
534 #define CCFN_PARAMS (const char *, char **, int)
535 u_long (*ccfn)CCFN_PARAMS=0; /* conversion function (strtol/strtoul) */
536 char ccltab[256]; /* character class table for %[...] */
537 char buf[BUF]; /* buffer for numeric conversions */
538 unsigned char *lptr; /* literal pointer */
539
540 char *cp;
541 short *sp;
542 int *ip;
543 #ifdef FLOATING_POINT
544 float *flp;
545 _LONG_DOUBLE *ldp;
546 double *dp;
547 #endif
548 long *lp;
549 #ifndef _NO_LONGLONG
550 long long *llp;
551 #endif
552
553 /* `basefix' is used to avoid `if' tests in the integer scanner */
554 static const short basefix[17] =
555 {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
556
557 /* Macro to support positional arguments */
558 #ifndef _NO_POS_ARGS
559 # define GET_ARG(n, ap, type) \
560 ((type) (is_pos_arg \
561 ? (n < numargs \
562 ? args[n] \
563 : get_arg (n, &my_ap, &numargs, args)) \
564 : (arg_index++ < numargs \
565 ? args[n] \
566 : (numargs < MAX_POS_ARGS \
567 ? args[numargs++] = va_arg (my_ap.ap, void *) \
568 : va_arg (my_ap.ap, void *)))))
569 #else
570 # define GET_ARG(n, ap, type) (va_arg (ap, type))
571 #endif
572
573 _newlib_flockfile_start (fp);
574
575 if (ORIENT (fp, -1) != -1)
576 {
577 nassigned = EOF;
578 goto all_done;
579 }
580
581 nassigned = 0;
582 nread = 0;
583 #ifdef _MB_CAPABLE
584 memset (&state, 0, sizeof (state));
585 #endif
586
587 for (;;)
588 {
589 #ifndef _MB_CAPABLE
590 wc = *fmt;
591 #else
592 nbytes = __MBTOWC (&wc, (char *) fmt, MB_CUR_MAX, &state);
593 if (nbytes < 0) {
594 wc = 0xFFFD; /* Unicode replacement character */
595 nbytes = 1;
596 memset (&state, 0, sizeof (state));
597 }
598 #endif
599 fmt += nbytes;
600
601 if (wc == 0)
602 goto all_done;
603 if (nbytes == 1 && isspace (wc))
604 {
605 for (;;)
606 {
607 if (BufferEmpty || !isspace (*fp->_p))
608 break;
609 nread++, fp->_r--, fp->_p++;
610 }
611 continue;
612 }
613 if (wc != '%')
614 goto literal;
615 width = 0;
616 flags = 0;
617 #ifndef _NO_POS_ARGS
618 N = arg_index;
619 is_pos_arg = 0;
620 #endif
621
622 /*
623 * switch on the format. continue if done; break once format
624 * type is derived.
625 */
626
627 again:
628 c = *fmt++;
629
630 switch (c)
631 {
632 case '%':
633 literal:
634 lptr = fmt - nbytes;
635 for (n = 0; n < nbytes; ++n)
636 {
637 if (BufferEmpty)
638 goto input_failure;
639 if (*fp->_p != *lptr)
640 goto match_failure;
641 fp->_r--, fp->_p++;
642 nread++;
643 ++lptr;
644 }
645 continue;
646
647 case '*':
648 if ((flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS | MALLOC))
649 || width)
650 goto match_failure;
651 flags |= SUPPRESS;
652 goto again;
653 case 'l':
654 if (flags & (CHAR | SHORT | LONG | LONGDBL))
655 goto match_failure;
656 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
657 if (*fmt == 'l') /* Check for 'll' = long long (SUSv3) */
658 {
659 ++fmt;
660 flags |= LONGDBL;
661 }
662 else
663 #endif
664 flags |= LONG;
665 goto again;
666 case 'L':
667 if (flags & (CHAR | SHORT | LONG | LONGDBL))
668 goto match_failure;
669 flags |= LONGDBL;
670 goto again;
671 case 'h':
672 if (flags & (CHAR | SHORT | LONG | LONGDBL))
673 goto match_failure;
674 #ifdef _WANT_IO_C99_FORMATS
675 if (*fmt == 'h') /* Check for 'hh' = char int (SUSv3) */
676 {
677 ++fmt;
678 flags |= CHAR;
679 }
680 else
681 #endif
682 flags |= SHORT;
683 goto again;
684 #ifdef _WANT_IO_C99_FORMATS
685 case 'j': /* intmax_t */
686 if (flags & (CHAR | SHORT | LONG | LONGDBL))
687 goto match_failure;
688 if (sizeof (intmax_t) == sizeof (long))
689 flags |= LONG;
690 else
691 flags |= LONGDBL;
692 goto again;
693 case 't': /* ptrdiff_t */
694 if (flags & (CHAR | SHORT | LONG | LONGDBL))
695 goto match_failure;
696 if (sizeof (ptrdiff_t) < sizeof (int))
697 /* POSIX states ptrdiff_t is 16 or more bits, as
698 is short. */
699 flags |= SHORT;
700 else if (sizeof (ptrdiff_t) == sizeof (int))
701 /* no flag needed */;
702 else if (sizeof (ptrdiff_t) <= sizeof (long))
703 flags |= LONG;
704 else
705 /* POSIX states that at least one programming
706 environment must support ptrdiff_t no wider than
707 long, but that means other environments can
708 have ptrdiff_t as wide as long long. */
709 flags |= LONGDBL;
710 goto again;
711 case 'z': /* size_t */
712 if (flags & (CHAR | SHORT | LONG | LONGDBL))
713 goto match_failure;
714 if (sizeof (size_t) < sizeof (int))
715 /* POSIX states size_t is 16 or more bits, as is short. */
716 flags |= SHORT;
717 else if (sizeof (size_t) == sizeof (int))
718 /* no flag needed */;
719 else if (sizeof (size_t) <= sizeof (long))
720 flags |= LONG;
721 else
722 /* POSIX states that at least one programming
723 environment must support size_t no wider than
724 long, but that means other environments can
725 have size_t as wide as long long. */
726 flags |= LONGDBL;
727 goto again;
728 #endif /* _WANT_IO_C99_FORMATS */
729 #ifdef _WANT_IO_POSIX_EXTENSIONS
730 case 'm':
731 if (flags & (CHAR | SHORT | LONG | LONGDBL | MALLOC))
732 goto match_failure;
733 init_m_ptr ();
734 flags |= MALLOC;
735 goto again;
736 #endif
737
738 case '0':
739 case '1':
740 case '2':
741 case '3':
742 case '4':
743 case '5':
744 case '6':
745 case '7':
746 case '8':
747 case '9':
748 if (flags & (CHAR | SHORT | LONG | LONGDBL | MALLOC))
749 goto match_failure;
750 width = width * 10 + c - '0';
751 goto again;
752
753 #ifndef _NO_POS_ARGS
754 case '$':
755 if (flags & (CHAR | SHORT | LONG | LONGDBL | SUPPRESS | MALLOC))
756 goto match_failure;
757 if (width <= MAX_POS_ARGS)
758 {
759 N = width - 1;
760 is_pos_arg = 1;
761 width = 0;
762 goto again;
763 }
764 _REENT_ERRNO(rptr) = EINVAL;
765 goto input_failure;
766 #endif /* !_NO_POS_ARGS */
767
768 /*
769 * Conversions. Those marked `compat' are for
770 * 4.[123]BSD compatibility.
771 *
772 * (According to ANSI, E and X formats are supposed to
773 * the same as e and x. Sorry about that.)
774 */
775
776 case 'D': /* compat */
777 flags |= LONG;
778 __PICOLIBC_FALLTHROUGH;
779 case 'd':
780 c = CT_INT;
781 ccfn = (u_long (*)CCFN_PARAMS)strtol;
782 base = 10;
783 break;
784
785 case 'i':
786 c = CT_INT;
787 ccfn = (u_long (*)CCFN_PARAMS)strtol;
788 base = 0;
789 break;
790
791 case 'O': /* compat */
792 flags |= LONG;
793 __PICOLIBC_FALLTHROUGH;
794 case 'o':
795 c = CT_INT;
796 ccfn = strtoul;
797 base = 8;
798 break;
799
800 case 'u':
801 c = CT_INT;
802 ccfn = strtoul;
803 base = 10;
804 break;
805
806 case 'X':
807 case 'x':
808 flags |= PFXOK; /* enable 0x prefixing */
809 c = CT_INT;
810 ccfn = strtoul;
811 base = 16;
812 break;
813
814 #ifdef FLOATING_POINT
815 # ifdef _WANT_IO_C99_FORMATS
816 case 'a':
817 case 'A':
818 case 'F':
819 # endif
820 case 'E':
821 case 'G':
822 case 'e':
823 case 'f':
824 case 'g':
825 c = CT_FLOAT;
826 break;
827 #endif
828
829 #ifdef _WANT_IO_C99_FORMATS
830 case 'S':
831 flags |= LONG;
832 __PICOLIBC_FALLTHROUGH;
833 #endif
834
835 case 's':
836 c = CT_STRING;
837 break;
838
839 case '[':
840 fmt = (u_char *) __sccl (ccltab, (unsigned char *) fmt);
841 flags |= NOSKIP;
842 c = CT_CCL;
843 break;
844
845 #ifdef _WANT_IO_C99_FORMATS
846 case 'C':
847 flags |= LONG;
848 __PICOLIBC_FALLTHROUGH;
849 #endif
850
851 case 'c':
852 flags |= NOSKIP;
853 c = CT_CHAR;
854 break;
855
856 case 'p': /* pointer format is like hex */
857 flags |= POINTER | PFXOK;
858 c = CT_INT;
859 ccfn = strtoul;
860 base = 16;
861 break;
862
863 case 'n':
864 if (flags & SUPPRESS) /* ??? */
865 continue;
866 #ifdef _WANT_IO_C99_FORMATS
867 if (flags & CHAR)
868 {
869 cp = GET_ARG (N, ap, char *);
870 *cp = nread;
871 }
872 else
873 #endif
874 if (flags & SHORT)
875 {
876 sp = GET_ARG (N, ap, short *);
877 *sp = nread;
878 }
879 else if (flags & LONG)
880 {
881 lp = GET_ARG (N, ap, long *);
882 *lp = nread;
883 }
884 #ifndef _NO_LONGLONG
885 else if (flags & LONGDBL)
886 {
887 llp = GET_ARG (N, ap, long long*);
888 *llp = nread;
889 }
890 #endif
891 else
892 {
893 ip = GET_ARG (N, ap, int *);
894 *ip = nread;
895 }
896 continue;
897
898 default:
899 goto match_failure;
900 }
901
902 /*
903 * We have a conversion that requires input.
904 */
905 if (BufferEmpty)
906 goto input_failure;
907
908 /*
909 * Consume leading white space, except for formats that
910 * suppress this.
911 */
912 if ((flags & NOSKIP) == 0)
913 {
914 while (isspace (*fp->_p))
915 {
916 nread++;
917 if (--fp->_r > 0)
918 fp->_p++;
919 else
920 if (_srefill ( fp))
921 goto input_failure;
922 }
923 /*
924 * Note that there is at least one character in the
925 * buffer, so conversions that do not set NOSKIP ca
926 * no longer result in an input failure.
927 */
928 }
929
930 /*
931 * Do the conversion.
932 */
933 switch (c)
934 {
935
936 case CT_CHAR:
937 /* scan arbitrary characters (sets NOSKIP) */
938 if (width == 0)
939 width = 1;
940 #if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
941 if (flags & LONG)
942 {
943 #ifdef _WANT_IO_POSIX_EXTENSIONS
944 wchar_t **wcp_p = NULL;
945 wchar_t *wcp0 = NULL;
946 size_t wcp_siz = 0;
947 #endif
948 mbstate_t state;
949 if (flags & SUPPRESS)
950 wcp = NULL;
951 #ifdef _WANT_IO_POSIX_EXTENSIONS
952 else if (flags & MALLOC)
953 wcp_siz = alloc_m_ptr (wchar_t, wcp, wcp0, wcp_p, 32);
954 #endif
955 else
956 wcp = GET_ARG (N, ap, wchar_t *);
957 size_t s = 0;
958 while (width != 0)
959 {
960 if (s == MB_CUR_MAX)
961 goto input_failure;
962 buf[s++] = *fp->_p;
963 fp->_r -= 1;
964 fp->_p += 1;
965 /* Got a high surrogate, allow low surrogate to slip
966 through */
967 if (mbslen != 3 || state.__count != 4)
968 memset (&state, 0, sizeof (mbstate_t));
969 if ((mbslen = mbrtowc (wcp, buf, s, &state))
970 == (size_t)-1)
971 goto input_failure; /* Invalid sequence */
972 if (mbslen == 0 && !(flags & SUPPRESS))
973 *wcp = L'\0';
974 if (mbslen != (size_t)-2) /* Incomplete sequence */
975 {
976 nread += s;
977 /* Handle high surrogate */
978 if (mbslen != 3 || state.__count != 4)
979 width -= 1;
980 if (!(flags & SUPPRESS))
981 {
982 #ifdef _WANT_IO_POSIX_EXTENSIONS
983 wcp_siz = realloc_m_ptr (wchar_t, wcp, wcp0, wcp_p,
984 wcp_siz);
985 #endif
986 wcp++;
987 }
988 s = 0;
989 }
990 if (BufferEmpty)
991 {
992 if (s != 0)
993 goto input_failure;
994 break;
995 }
996 }
997 #ifdef _WANT_IO_POSIX_EXTENSIONS
998 shrink_m_ptr (wchar_t, wcp_p, wcp - wcp0, wcp_siz);
999 #endif
1000 if (!(flags & SUPPRESS))
1001 nassigned++;
1002 }
1003 else
1004 #endif /* ELIX_LEVEL */
1005 if (flags & SUPPRESS)
1006 {
1007 size_t sum = 0;
1008 for (;;)
1009 {
1010 if ((n = fp->_r) < (int)width)
1011 {
1012 sum += n;
1013 width -= n;
1014 fp->_p += n;
1015 if (_srefill ( fp))
1016 {
1017 if (sum == 0)
1018 goto input_failure;
1019 break;
1020 }
1021 }
1022 else
1023 {
1024 sum += width;
1025 fp->_r -= width;
1026 fp->_p += width;
1027 break;
1028 }
1029 }
1030 nread += sum;
1031 }
1032 else
1033 {
1034 size_t r;
1035 #ifdef _WANT_IO_POSIX_EXTENSIONS
1036 char **p_p = NULL;
1037 if (flags & MALLOC)
1038 alloc_m_ptr (char, p, p0, p_p, width);
1039 else
1040 #endif
1041 p = GET_ARG (N, ap, char *);
1042 r = fread ( p, 1, width, fp);
1043 if (r == 0)
1044 goto input_failure;
1045 #ifdef _WANT_IO_POSIX_EXTENSIONS
1046 shrink_m_ptr (char, p_p, r, width);
1047 #endif
1048 nread += r;
1049 nassigned++;
1050 }
1051 break;
1052
1053 case CT_CCL:
1054 /* scan a (nonempty) character class (sets NOSKIP) */
1055 if (width == 0)
1056 width = SIZE_MAX;
1057 /* take only those things in the class */
1058 #if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
1059 if (flags & LONG)
1060 {
1061 #ifdef _WANT_IO_POSIX_EXTENSIONS
1062 wchar_t **wcp_p = NULL;
1063 wchar_t *wcp0 = NULL;
1064 size_t wcp_siz = 0;
1065 #endif
1066 mbstate_t state;
1067 if (flags & SUPPRESS)
1068 wcp = &wc;
1069 #ifdef _WANT_IO_POSIX_EXTENSIONS
1070 else if (flags & MALLOC)
1071 wcp_siz = alloc_m_ptr (wchar_t, wcp, wcp0, wcp_p, 32);
1072 #endif
1073 else
1074 wcp = GET_ARG (N, ap, wchar_t *);
1075 size_t s = 0;
1076 while (width != 0) {
1077 if (s == MB_CUR_MAX)
1078 goto input_failure;
1079 buf[s++] = *fp->_p;
1080 fp->_r -= 1;
1081 fp->_p += 1;
1082 /* Got a high surrogate, allow low surrogate to slip
1083 through */
1084 if (mbslen != 3 || state.__count != 4)
1085 memset (&state, 0, sizeof (mbstate_t));
1086 if ((mbslen = mbrtowc (wcp, buf, s, &state))
1087 == (size_t)-1)
1088 goto input_failure;
1089 if (mbslen == 0)
1090 *wcp = L'\0';
1091 if (mbslen != (size_t)-2) /* Incomplete sequence */
1092 {
1093 int wcb = __wctob(*wcp);
1094 if (wcb == EOF || !ccltab[wcb])
1095 {
1096 while (s != 0)
1097 ungetc ( (unsigned char) buf[--s], fp);
1098 break;
1099 }
1100 nread += s;
1101 /* Handle high surrogate */
1102 if (mbslen != 3 || state.__count != 4)
1103 width -= 1;
1104 if ((flags & SUPPRESS) == 0)
1105 {
1106 wcp += 1;
1107 #ifdef _WANT_IO_POSIX_EXTENSIONS
1108 wcp_siz = realloc_m_ptr (wchar_t, wcp, wcp0, wcp_p,
1109 wcp_siz);
1110 #endif
1111 }
1112 s = 0;
1113 }
1114 if (BufferEmpty)
1115 {
1116 if (s != 0)
1117 goto input_failure;
1118 break;
1119 }
1120 }
1121 if (!(flags & SUPPRESS))
1122 {
1123 *wcp = L'\0';
1124 #ifdef _WANT_IO_POSIX_EXTENSIONS
1125 shrink_m_ptr (wchar_t, wcp_p, wcp - wcp0 + 1, wcp_siz);
1126 #endif
1127 nassigned++;
1128 }
1129 }
1130 else
1131 #endif /* ELIX_LEVEL */
1132 if (flags & SUPPRESS)
1133 {
1134 n = 0;
1135 while (ccltab[*fp->_p])
1136 {
1137 n++, fp->_r--, fp->_p++;
1138 if (--width == 0)
1139 break;
1140 if (BufferEmpty)
1141 {
1142 if (n == 0)
1143 goto input_failure;
1144 break;
1145 }
1146 }
1147 if (n == 0)
1148 goto match_failure;
1149 nread += n;
1150 }
1151 else
1152 {
1153 #ifdef _WANT_IO_POSIX_EXTENSIONS
1154 char **p_p = NULL;
1155 size_t p_siz = 0;
1156
1157 if (flags & MALLOC)
1158 p_siz = alloc_m_ptr (char, p, p0, p_p, 32);
1159 else
1160 #endif
1161 p0 = p = GET_ARG (N, ap, char *);
1162 while (ccltab[*fp->_p])
1163 {
1164 fp->_r--;
1165 *p++ = *fp->_p++;
1166 #ifdef _WANT_IO_POSIX_EXTENSIONS
1167 p_siz = realloc_m_ptr (char, p, p0, p_p, p_siz);
1168 #endif
1169 if (--width == 0)
1170 break;
1171 if (BufferEmpty)
1172 {
1173 if (p == p0)
1174 goto input_failure;
1175 break;
1176 }
1177 }
1178 n = p - p0;
1179 if (n == 0)
1180 goto match_failure;
1181 *p = 0;
1182 #ifdef _WANT_IO_POSIX_EXTENSIONS
1183 shrink_m_ptr (char, p_p, n + 1, p_siz);
1184 #endif
1185 nassigned++;
1186 nread += n;
1187 }
1188 break;
1189
1190 case CT_STRING:
1191 /* like CCL, but zero-length string OK, & no NOSKIP */
1192 if (width == 0)
1193 width = SIZE_MAX;
1194 #if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
1195 if (flags & LONG)
1196 {
1197 #ifdef _WANT_IO_POSIX_EXTENSIONS
1198 wchar_t **wcp_p = NULL;
1199 wchar_t *wcp0 = NULL;
1200 size_t wcp_siz = 0;
1201 #endif
1202 /* Process %S and %ls placeholders */
1203 mbstate_t state;
1204 if (flags & SUPPRESS)
1205 wcp = &wc;
1206 #ifdef _WANT_IO_POSIX_EXTENSIONS
1207 else if (flags & MALLOC)
1208 wcp_siz = alloc_m_ptr (wchar_t, wcp, wcp0, wcp_p, 32);
1209 #endif
1210 else
1211 wcp = GET_ARG (N, ap, wchar_t *);
1212 size_t s = 0;
1213 while (!isspace (*fp->_p) && width != 0)
1214 {
1215 if (s == MB_CUR_MAX)
1216 goto input_failure;
1217 buf[s++] = *fp->_p;
1218 fp->_r -= 1;
1219 fp->_p += 1;
1220 /* Got a high surrogate, allow low surrogate to slip
1221 through */
1222 if (mbslen != 3 || state.__count != 4)
1223 memset (&state, 0, sizeof (mbstate_t));
1224 if ((mbslen = mbrtowc (wcp, buf, s, &state))
1225 == (size_t)-1)
1226 goto input_failure;
1227 if (mbslen == 0)
1228 *wcp = L'\0';
1229 if (mbslen != (size_t)-2) /* Incomplete sequence */
1230 {
1231 if (iswspace(*wcp))
1232 {
1233 while (s != 0)
1234 ungetc ( (unsigned char) buf[--s], fp);
1235 break;
1236 }
1237 nread += s;
1238 /* Handle high surrogate */
1239 if (mbslen != 3 || state.__count != 4)
1240 width -= 1;
1241 if ((flags & SUPPRESS) == 0)
1242 {
1243 wcp += 1;
1244 #ifdef _WANT_IO_POSIX_EXTENSIONS
1245 wcp_siz = realloc_m_ptr (wchar_t, wcp, wcp0, wcp_p,
1246 wcp_siz);
1247 #endif
1248 }
1249 s = 0;
1250 }
1251 if (BufferEmpty)
1252 {
1253 if (s != 0)
1254 goto input_failure;
1255 break;
1256 }
1257 }
1258 if (!(flags & SUPPRESS))
1259 {
1260 *wcp = L'\0';
1261 #ifdef _WANT_IO_POSIX_EXTENSIONS
1262 shrink_m_ptr (wchar_t, wcp_p, wcp - wcp0 + 1, wcp_siz);
1263 #endif
1264 nassigned++;
1265 }
1266 }
1267 else
1268 #endif
1269 if (flags & SUPPRESS)
1270 {
1271 n = 0;
1272 while (!isspace (*fp->_p))
1273 {
1274 n++, fp->_r--, fp->_p++;
1275 if (--width == 0)
1276 break;
1277 if (BufferEmpty)
1278 break;
1279 }
1280 nread += n;
1281 }
1282 else
1283 {
1284 #ifdef _WANT_IO_POSIX_EXTENSIONS
1285 char **p_p = NULL;
1286 size_t p_siz = 0;
1287
1288 if (flags & MALLOC)
1289 p_siz = alloc_m_ptr (char, p, p0, p_p, 32);
1290 else
1291 #endif
1292 p0 = GET_ARG (N, ap, char *);
1293 p = p0;
1294 while (!isspace (*fp->_p))
1295 {
1296 fp->_r--;
1297 *p++ = *fp->_p++;
1298 #ifdef _WANT_IO_POSIX_EXTENSIONS
1299 p_siz = realloc_m_ptr (char, p, p0, p_p, p_siz);
1300 #endif
1301 if (--width == 0)
1302 break;
1303 if (BufferEmpty)
1304 break;
1305 }
1306 *p = 0;
1307 #ifdef _WANT_IO_POSIX_EXTENSIONS
1308 shrink_m_ptr (char, p_p, p - p0 + 1, p_siz);
1309 #endif
1310 nread += p - p0;
1311 nassigned++;
1312 }
1313 continue;
1314
1315 case CT_INT:
1316 {
1317 /* scan an integer as if by strtol/strtoul */
1318 unsigned width_left = 0;
1319 int skips = 0;
1320 #ifdef hardway
1321 if (width == 0 || width > sizeof (buf) - 1)
1322 #else
1323 /* size_t is unsigned, hence this optimisation */
1324 if (width - 1 > sizeof (buf) - 2)
1325 #endif
1326 {
1327 width_left = width - (sizeof (buf) - 1);
1328 width = sizeof (buf) - 1;
1329 }
1330 flags |= SIGNOK | NDIGITS | NZDIGITS | NNZDIGITS;
1331 for (p = buf; width; width--)
1332 {
1333 c = *fp->_p;
1334 /*
1335 * Switch on the character; `goto ok' if we
1336 * accept it as a part of number.
1337 */
1338 switch (c)
1339 {
1340 /*
1341 * The digit 0 is always legal, but is special.
1342 * For %i conversions, if no digits (zero or nonzero)
1343 * have been scanned (only signs), we will have base==0.
1344 * In that case, we should set it to 8 and enable 0x
1345 * prefixing. Also, if we have not scanned zero digits
1346 * before this, do not turn off prefixing (someone else
1347 * will turn it off if we have scanned any nonzero digits).
1348 */
1349 case '0':
1350 if (! (flags & NNZDIGITS))
1351 goto ok;
1352 if (base == 0)
1353 {
1354 base = 8;
1355 flags |= PFXOK;
1356 }
1357 if (flags & NZDIGITS)
1358 {
1359 flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
1360 goto ok;
1361 }
1362 flags &= ~(SIGNOK | PFXOK | NDIGITS);
1363 if (width_left)
1364 {
1365 width_left--;
1366 width++;
1367 }
1368 ++skips;
1369 goto skip;
1370
1371 /* 1 through 7 always legal */
1372 case '1':
1373 case '2':
1374 case '3':
1375 case '4':
1376 case '5':
1377 case '6':
1378 case '7':
1379 base = basefix[base];
1380 flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
1381 goto ok;
1382
1383 /* digits 8 and 9 ok iff decimal or hex */
1384 case '8':
1385 case '9':
1386 base = basefix[base];
1387 if (base <= 8)
1388 break; /* not legal here */
1389 flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
1390 goto ok;
1391
1392 /* letters ok iff hex */
1393 case 'A':
1394 case 'B':
1395 case 'C':
1396 case 'D':
1397 case 'E':
1398 case 'F':
1399 case 'a':
1400 case 'b':
1401 case 'c':
1402 case 'd':
1403 case 'e':
1404 case 'f':
1405 /* no need to fix base here */
1406 if (base <= 10)
1407 break; /* not legal here */
1408 flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
1409 goto ok;
1410
1411 /* sign ok only as first character */
1412 case '+':
1413 case '-':
1414 if (flags & SIGNOK)
1415 {
1416 flags &= ~SIGNOK;
1417 goto ok;
1418 }
1419 break;
1420
1421 /* x ok iff flag still set & single 0 seen */
1422 case 'x':
1423 case 'X':
1424 if ((flags & (PFXOK | NZDIGITS)) == PFXOK)
1425 {
1426 base = 16;/* if %i */
1427 flags &= ~PFXOK;
1428 /* We must reset the NZDIGITS and NDIGITS
1429 flags that would have been unset by seeing
1430 the zero that preceded the X or x. */
1431 flags |= NZDIGITS | NDIGITS;
1432 goto ok;
1433 }
1434 break;
1435 }
1436
1437 /*
1438 * If we got here, c is not a legal character
1439 * for a number. Stop accumulating digits.
1440 */
1441 break;
1442 ok:
1443 /*
1444 * c is legal: store it and look at the next.
1445 */
1446 *p++ = c;
1447 skip:
1448 if (--fp->_r > 0)
1449 fp->_p++;
1450 else
1451 if (_srefill ( fp))
1452 break; /* EOF */
1453 }
1454 /*
1455 * If we had only a sign, it is no good; push back the sign.
1456 * If the number ends in `x', it was [sign] '0' 'x', so push back
1457 * the x and treat it as [sign] '0'.
1458 * Use of ungetc here and below assumes ASCII encoding; we are only
1459 * pushing back 7-bit characters, so casting to unsigned char is
1460 * not necessary.
1461 */
1462 if (flags & NDIGITS)
1463 {
1464 if (p > buf)
1465 ungetc ( *--p, fp); /* [-+xX] */
1466 if (p == buf)
1467 goto match_failure;
1468 }
1469 if ((flags & SUPPRESS) == 0)
1470 {
1471 u_long res;
1472
1473 *p = 0;
1474 res = (*ccfn) (buf, (char **) NULL, base);
1475 if (flags & POINTER)
1476 {
1477 void **vp = GET_ARG (N, ap, void **);
1478 #ifndef _NO_LONGLONG
1479 if (sizeof (uintptr_t) > sizeof (u_long))
1480 {
1481 u_long_long resll;
1482 resll = strtoull (buf, (char **) NULL, base);
1483 *vp = (void *) (uintptr_t) resll;
1484 }
1485 else
1486 #endif /* !_NO_LONGLONG */
1487 *vp = (void *) (uintptr_t) res;
1488 }
1489 #ifdef _WANT_IO_C99_FORMATS
1490 else if (flags & CHAR)
1491 {
1492 cp = GET_ARG (N, ap, char *);
1493 *cp = res;
1494 }
1495 #endif
1496 else if (flags & SHORT)
1497 {
1498 sp = GET_ARG (N, ap, short *);
1499 *sp = res;
1500 }
1501 else if (flags & LONG)
1502 {
1503 lp = GET_ARG (N, ap, long *);
1504 *lp = res;
1505 }
1506 #ifndef _NO_LONGLONG
1507 else if (flags & LONGDBL)
1508 {
1509 u_long_long resll;
1510 if (ccfn == strtoul)
1511 resll = strtoull (buf, (char **) NULL, base);
1512 else
1513 resll = strtoll (buf, (char **) NULL, base);
1514 llp = GET_ARG (N, ap, long long*);
1515 *llp = resll;
1516 }
1517 #endif
1518 else
1519 {
1520 ip = GET_ARG (N, ap, int *);
1521 *ip = res;
1522 }
1523 nassigned++;
1524 }
1525 nread += p - buf + skips;
1526 break;
1527 }
1528 #ifdef FLOATING_POINT
1529 case CT_FLOAT:
1530 {
1531 /* scan a floating point number as if by strtod */
1532 /* This code used to assume that the number of digits is reasonable.
1533 However, ANSI / ISO C makes no such stipulation; we have to get
1534 exact results even when there is an unreasonable amount of
1535 leading zeroes. */
1536 long leading_zeroes = 0;
1537 long zeroes, exp_adjust;
1538 char *exp_start = NULL;
1539 unsigned width_left = 0;
1540 char nancount = 0;
1541 char infcount = 0;
1542 const char *decpt = localeconv ()->decimal_point;
1543 #ifdef _MB_CAPABLE
1544 int decptpos = 0;
1545 #endif
1546 #ifdef hardway
1547 if (width == 0 || width > sizeof (buf) - 1)
1548 #else
1549 /* size_t is unsigned, hence this optimisation */
1550 if (width - 1 > sizeof (buf) - 2)
1551 #endif
1552 {
1553 width_left = width - (sizeof (buf) - 1);
1554 width = sizeof (buf) - 1;
1555 }
1556 flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
1557 zeroes = 0;
1558 exp_adjust = 0;
1559 for (p = buf; width; )
1560 {
1561 c = *fp->_p;
1562 /*
1563 * This code mimicks the integer conversion
1564 * code, but is much simpler.
1565 */
1566 switch (c)
1567 {
1568 case '0':
1569 if (flags & NDIGITS)
1570 {
1571 flags &= ~SIGNOK;
1572 zeroes++;
1573 if (width_left)
1574 {
1575 width_left--;
1576 width++;
1577 }
1578 goto fskip;
1579 }
1580 __PICOLIBC_FALLTHROUGH;
1581 case '1':
1582 case '2':
1583 case '3':
1584 case '4':
1585 case '5':
1586 case '6':
1587 case '7':
1588 case '8':
1589 case '9':
1590 if (nancount + infcount == 0)
1591 {
1592 flags &= ~(SIGNOK | NDIGITS);
1593 goto fok;
1594 }
1595 break;
1596
1597 /* Chars a, e and f have various special meanings apart from
1598 their hex value. They are handled separately, see below. */
1599 case 'b':
1600 case 'B':
1601 case 'c':
1602 case 'C':
1603 case 'd':
1604 case 'D':
1605 if ((flags & HEXFLT) && nancount + infcount == 0)
1606 {
1607 flags &= ~(SIGNOK | NDIGITS);
1608 goto fok;
1609 }
1610 break;
1611
1612 case 'x':
1613 case 'X':
1614 /* Did we have exactly one leading zero yet? */
1615 if ((flags & (SIGNOK | NDIGITS | HEXFLT)) == NDIGITS
1616 && zeroes == 1)
1617 {
1618 flags |= HEXFLT;
1619 flags &= ~NDIGITS;
1620 /* We skipped the first zero, so we have to add
1621 it now to the buffer. */
1622 *p++ = '0';
1623 width--;
1624 zeroes = 0;
1625 goto fok;
1626 }
1627 break;
1628
1629 case '+':
1630 case '-':
1631 if (flags & SIGNOK)
1632 {
1633 flags &= ~SIGNOK;
1634 goto fok;
1635 }
1636 break;
1637 case 'n':
1638 case 'N':
1639 if (nancount == 0 && zeroes == 0
1640 && (flags & (NDIGITS | DPTOK | EXPOK)) ==
1641 (NDIGITS | DPTOK | EXPOK))
1642 {
1643 flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
1644 nancount = 1;
1645 goto fok;
1646 }
1647 if (nancount == 2)
1648 {
1649 nancount = 3;
1650 goto fok;
1651 }
1652 if (infcount == 1 || infcount == 4)
1653 {
1654 infcount++;
1655 goto fok;
1656 }
1657 break;
1658 case 'a':
1659 case 'A':
1660 if ((flags & HEXFLT) && nancount + infcount == 0)
1661 {
1662 flags &= ~(SIGNOK | NDIGITS);
1663 goto fok;
1664 }
1665 if (nancount == 1)
1666 {
1667 nancount = 2;
1668 goto fok;
1669 }
1670 break;
1671 case 'i':
1672 case 'I':
1673 if (infcount == 0 && zeroes == 0
1674 && (flags & (NDIGITS | DPTOK | EXPOK)) ==
1675 (NDIGITS | DPTOK | EXPOK))
1676 {
1677 flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
1678 infcount = 1;
1679 goto fok;
1680 }
1681 if (infcount == 3 || infcount == 5)
1682 {
1683 infcount++;
1684 goto fok;
1685 }
1686 break;
1687 case 'f':
1688 case 'F':
1689 if ((flags & HEXFLT) && nancount + infcount == 0)
1690 {
1691 flags &= ~(SIGNOK | NDIGITS);
1692 goto fok;
1693 }
1694 if (infcount == 2)
1695 {
1696 infcount = 3;
1697 goto fok;
1698 }
1699 break;
1700 case 't':
1701 case 'T':
1702 if (infcount == 6)
1703 {
1704 infcount = 7;
1705 goto fok;
1706 }
1707 break;
1708 case 'y':
1709 case 'Y':
1710 if (infcount == 7)
1711 {
1712 infcount = 8;
1713 goto fok;
1714 }
1715 break;
1716
1717 case 'p':
1718 case 'P':
1719 /* p is the exponent marker in hex case. */
1720 if (!(flags & HEXFLT))
1721 break;
1722 goto fexp;
1723 case 'e':
1724 case 'E':
1725 /* e is just a digit in hex case, not the exponent marker. */
1726 if (flags & HEXFLT)
1727 {
1728 if (nancount + infcount == 0)
1729 {
1730 flags &= ~(SIGNOK | NDIGITS);
1731 goto fok;
1732 }
1733 break;
1734 }
1735
1736 fexp:
1737 /* no exponent without some digits */
1738 if ((flags & (NDIGITS | EXPOK)) == EXPOK
1739 || ((flags & EXPOK) && zeroes))
1740 {
1741 if (! (flags & DPTOK))
1742 {
1743 exp_adjust = zeroes - leading_zeroes;
1744 exp_start = p;
1745 }
1746 flags =
1747 (flags & ~(EXPOK | DPTOK | HEXFLT)) |
1748 SIGNOK | NDIGITS;
1749 zeroes = 0;
1750 goto fok;
1751 }
1752 break;
1753 default:
1754 #ifndef _MB_CAPABLE
1755 if ((unsigned char) c == (unsigned char) decpt[0]
1756 && (flags & DPTOK))
1757 {
1758 flags &= ~(SIGNOK | DPTOK);
1759 leading_zeroes = zeroes;
1760 goto fok;
1761 }
1762 break;
1763 #else
1764 if (flags & DPTOK)
1765 {
1766 while ((unsigned char) c
1767 == (unsigned char) decpt[decptpos])
1768 {
1769 if (decpt[++decptpos] == '\0')
1770 {
1771 /* We read the complete decpt seq. */
1772 flags &= ~(SIGNOK | DPTOK);
1773 leading_zeroes = zeroes;
1774 p = stpncpy (p, decpt, decptpos);
1775 decptpos = 0;
1776 goto fskip;
1777 }
1778 ++nread;
1779 if (--fp->_r > 0)
1780 fp->_p++;
1781 else if (_srefill ( fp))
1782 break; /* EOF */
1783 c = *fp->_p;
1784 }
1785 if (decptpos > 0)
1786 {
1787 /* We read part of a multibyte decimal point,
1788 but the rest is invalid or we're at EOF,
1789 so back off. */
1790 while (decptpos-- > 0)
1791 {
1792 ungetc ( (unsigned char) decpt[decptpos],
1793 fp);
1794 --nread;
1795 }
1796 }
1797 }
1798 break;
1799 #endif
1800 }
1801 break;
1802 fok:
1803 *p++ = c;
1804 fskip:
1805 width--;
1806 ++nread;
1807 if (--fp->_r > 0)
1808 fp->_p++;
1809 else
1810 if (_srefill ( fp))
1811 break; /* EOF */
1812 }
1813 if (zeroes)
1814 flags &= ~NDIGITS;
1815 /* We may have a 'N' or possibly even [sign] 'N' 'a' as the
1816 start of 'NaN', only to run out of chars before it was
1817 complete (or having encountered a non-matching char). So
1818 check here if we have an outstanding nancount, and if so
1819 put back the chars we did swallow and treat as a failed
1820 match.
1821
1822 FIXME - we still don't handle NAN([0xdigits]). */
1823 if (nancount - 1U < 2U) /* nancount && nancount < 3 */
1824 {
1825 /* Newlib's ungetc works even if we called __srefill in
1826 the middle of a partial parse, but POSIX does not
1827 guarantee that in all implementations of ungetc. */
1828 while (p > buf)
1829 {
1830 ungetc ( *--p, fp); /* [-+nNaA] */
1831 --nread;
1832 }
1833 goto match_failure;
1834 }
1835 /* Likewise for 'inf' and 'infinity'. But be careful that
1836 'infinite' consumes only 3 characters, leaving the stream
1837 at the second 'i'. */
1838 if (infcount - 1U < 7U) /* infcount && infcount < 8 */
1839 {
1840 if (infcount >= 3) /* valid 'inf', but short of 'infinity' */
1841 while (infcount-- > 3)
1842 {
1843 ungetc ( *--p, fp); /* [iInNtT] */
1844 --nread;
1845 }
1846 else
1847 {
1848 while (p > buf)
1849 {
1850 ungetc ( *--p, fp); /* [-+iInN] */
1851 --nread;
1852 }
1853 goto match_failure;
1854 }
1855 }
1856 /*
1857 * If no digits, might be missing exponent digits
1858 * (just give back the exponent) or might be missing
1859 * regular digits, but had sign and/or decimal point.
1860 */
1861 if (flags & NDIGITS)
1862 {
1863 if (flags & EXPOK)
1864 {
1865 /* no digits at all */
1866 while (p > buf)
1867 {
1868 ungetc ( *--p, fp); /* [-+.] */
1869 --nread;
1870 }
1871 goto match_failure;
1872 }
1873 /* just a bad exponent (e and maybe sign) */
1874 c = *--p;
1875 --nread;
1876 if (c != 'e' && c != 'E')
1877 {
1878 ungetc ( c, fp); /* [-+] */
1879 c = *--p;
1880 --nread;
1881 }
1882 ungetc ( c, fp); /* [eE] */
1883 }
1884 if ((flags & SUPPRESS) == 0)
1885 {
1886 double res = 0;
1887 #ifdef _NO_LONGDBL
1888 #define QUAD_RES res;
1889 #else /* !_NO_LONG_DBL */
1890 long double qres = 0;
1891 #define QUAD_RES qres;
1892 #endif /* !_NO_LONG_DBL */
1893 long new_exp = 0;
1894
1895 *p = 0;
1896 if ((flags & (DPTOK | EXPOK)) == EXPOK)
1897 {
1898 exp_adjust = zeroes - leading_zeroes;
1899 new_exp = -exp_adjust;
1900 exp_start = p;
1901 }
1902 else if (exp_adjust)
1903 new_exp = strtol ((exp_start + 1), NULL, 10) - exp_adjust;
1904 if (exp_adjust)
1905 {
1906
1907 /* If there might not be enough space for the new exponent,
1908 truncate some trailing digits to make room. */
1909 if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN)
1910 exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;
1911 sprintf (exp_start, "e%ld", new_exp);
1912 }
1913
1914 /* FIXME: Is that still true?
1915 Current strtold routine is markedly slower than
1916 strtod. Only use it if we have a long double
1917 result. */
1918 #ifndef _NO_LONGDBL /* !_NO_LONGDBL */
1919 if (flags & LONGDBL)
1920 qres = strtold (buf, NULL);
1921 else
1922 #endif
1923 res = strtod (buf, NULL);
1924
1925 if (flags & LONG)
1926 {
1927 dp = GET_ARG (N, ap, double *);
1928 *dp = res;
1929 }
1930 else if (flags & LONGDBL)
1931 {
1932 ldp = GET_ARG (N, ap, _LONG_DOUBLE *);
1933 *ldp = (_LONG_DOUBLE) QUAD_RES;
1934 }
1935 else
1936 {
1937 flp = GET_ARG (N, ap, float *);
1938 if (isnan (res))
1939 *flp = nanf ("");
1940 else
1941 *flp = res;
1942 }
1943 nassigned++;
1944 }
1945 break;
1946 }
1947 #endif /* FLOATING_POINT */
1948 }
1949 }
1950 input_failure:
1951 /* On read failure, return EOF failure regardless of matches; errno
1952 should have been set prior to here. On EOF failure (including
1953 invalid format string), return EOF if no matches yet, else number
1954 of matches made prior to failure. */
1955 nassigned = nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
1956 match_failure:
1957 all_done:
1958 /* Return number of matches, which can be 0 on match failure. */
1959 _newlib_flockfile_end (fp);
1960 #ifdef _WANT_IO_POSIX_EXTENSIONS
1961 free_m_ptr ();
1962 #endif
1963 return nassigned;
1964 }
1965
1966 #ifndef _NO_POS_ARGS
1967 /* Process all intermediate arguments. Fortunately, with scanf, all
1968 intermediate arguments are sizeof(void*), so we don't need to scan
1969 ahead in the format string. */
1970 static void *
get_arg(int n,my_va_list * ap,int * numargs_p,void ** args)1971 get_arg (int n, my_va_list *ap, int *numargs_p, void **args)
1972 {
1973 int numargs = *numargs_p;
1974 while (n >= numargs)
1975 args[numargs++] = va_arg (ap->ap, void *);
1976 *numargs_p = numargs;
1977 return args[n];
1978 }
1979 #endif /* !_NO_POS_ARGS */
1980