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