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