3 <<vscanf>>, <<vfscanf>>, <<vsscanf>>---format argument list
15 int vscanf(const char *restrict <[fmt]>, va_list <[list]>);
16 int vfscanf(FILE *restrict <[fp]>, const char *restrict <[fmt]>, va_list <[list]>);
17 int vsscanf(const char *restrict <[str]>, const char *restrict <[fmt]>, va_list <[list]>);
19 int _vscanf_r(void *<[reent]>, const char *restrict <[fmt]>,
21 int _vfscanf_r(void *<[reent]>, FILE *restrict <[fp]>, const char *restrict <[fmt]>,
23 int _vsscanf_r(void *<[reent]>, const char *restrict <[str]>, const char *restrict <[fmt]>,
27 <<vscanf>>, <<vfscanf>>, and <<vsscanf>> are (respectively) variants
28 of <<scanf>>, <<fscanf>>, and <<sscanf>>. They differ only in
29 allowing their caller to pass the variable argument list as a
30 <<va_list>> object (initialized by <<va_start>>) rather than
31 directly accepting a variable number of arguments.
34 The return values are consistent with the corresponding functions:
35 <<vscanf>> returns the number of input fields successfully scanned,
36 converted, and stored; the return value does not include scanned
37 fields which were not stored.
39 If <<vscanf>> attempts to read at end-of-file, the return value
42 If no fields were stored, the return value is <<0>>.
44 The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are
45 reentrant versions which take an additional first parameter which points to the
49 These are GNU extensions.
51 Supporting OS subroutines required:
55 * Copyright (c) 1990 The Regents of the University of California.
56 * All rights reserved.
58 * Redistribution and use in source and binary forms are permitted
59 * provided that the above copyright notice and this paragraph are
60 * duplicated in all such forms and that any documentation,
61 * and/or other materials related to such
62 * distribution and use acknowledge that the software was developed
63 * by the University of California, Berkeley. The name of the
64 * University may not be used to endorse or promote products derived
65 * from this software without specific prior written permission.
66 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
67 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
68 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
83 #ifndef NO_FLOATING_POINT
84 #define FLOATING_POINT
90 /* Currently a test is made to see if long double processing is warranted.
91 This could be changed in the future should the _ldtoa_r code be
92 preferred over _dtoa_r. */
94 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
99 #if defined _WANT_IO_LONG_LONG && defined __GNUC__
104 #define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
105 /* An upper bound for how long a long prints in decimal. 4 / 13 approximates
106 log (2). Add one char for roundoff compensation and one for the sign. */
107 #define MAX_LONG_LEN ((CHAR_BIT * sizeof (long) - 1) * 4 / 13 + 2)
113 * Flags used during conversion.
116 #define LONG 0x01 /* l: long or double */
117 #define LONGDBL 0x02 /* L: long double or long long */
118 #define SHORT 0x04 /* h: short */
119 #define SUPPRESS 0x10 /* suppress assignment */
120 #define POINTER 0x20 /* weird %p pointer (`fake hex') */
121 #define NOSKIP 0x40 /* do not skip blanks */
124 * The following are used in numeric conversions only:
125 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
126 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
129 #define SIGNOK 0x80 /* +/- is (still) legal */
130 #define NDIGITS 0x100 /* no digits detected */
132 #define DPTOK 0x200 /* (float) decimal point is still legal */
133 #define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */
135 #define PFXOK 0x200 /* 0x prefix is (still) legal */
136 #define NZDIGITS 0x400 /* no zero digits detected */
137 #define NNZDIGITS 0x800 /* no non-zero digits detected */
139 #define VECTOR 0x2000 /* v: vector */
140 #define FIXEDPOINT 0x4000 /* r/R: fixed-point */
141 #define SIGNED 0x8000 /* r: signed fixed-point */
147 #define CT_CHAR 0 /* %c conversion */
148 #define CT_CCL 1 /* %[...] conversion */
149 #define CT_STRING 2 /* %s conversion */
150 #define CT_INT 3 /* integer, i.e., strtol or strtoul */
151 #define CT_FLOAT 4 /* floating, i.e., strtod */
154 #define u_char unsigned char
157 #define u_long unsigned long
160 typedef unsigned long long u_long_long
;
165 char c
[16] __attribute__ ((__aligned__ (16)));
176 #define BufferEmpty (fp->_r <= 0 && __srefill(fp))
181 vfscanf (register FILE *__restrict fp
,
182 const char *__restrict fmt
,
185 CHECK_INIT(_REENT
, fp
);
186 return __svfscanf_r (_REENT
, fp
, fmt
, ap
);
190 __svfscanf (fp
, fmt0
, ap
)
195 return __svfscanf_r (_REENT
, fp
, fmt0
, ap
);
198 #endif /* !_REENT_ONLY */
201 _vfscanf_r (struct _reent
*data
,
202 register FILE *__restrict fp
,
203 const char *__restrict fmt
,
206 return __svfscanf_r (data
, fp
, fmt
, ap
);
211 __svfscanf_r (rptr
, fp
, fmt0
, ap
)
217 register u_char
*fmt
= (u_char
*) fmt0
;
218 register int c
; /* character from format, or conversion */
219 register int type
; /* conversion type */
220 register size_t width
; /* field width, or 0 */
221 register char *p
; /* points into all kinds of strings */
222 register int n
; /* handy integer */
223 register int flags
; /* flags as defined above */
224 register char *p0
; /* saves original value of p when necessary */
225 int orig_flags
; /* saved flags used when processing vector */
226 int int_width
; /* tmp area to store width when processing int */
227 int nassigned
; /* number of fields assigned */
228 int nread
; /* number of characters consumed from fp */
229 int base
= 0; /* base argument to strtol/strtoul */
230 int nbytes
= 1; /* number of bytes read from fmt string */
231 wchar_t wc
; /* wchar to use to read format string */
232 char vec_sep
; /* vector separator char */
233 char last_space_char
; /* last white-space char eaten - needed for vec support */
234 int vec_read_count
; /* number of vector items to read separately */
235 int looped
; /* has vector processing looped */
236 u_long (*ccfn
) () = 0; /* conversion function (strtol/strtoul) */
237 char ccltab
[256]; /* character class table for %[...] */
238 char buf
[BUF
]; /* buffer for numeric conversions */
240 char *lptr
; /* literal pointer */
242 mbstate_t state
; /* value to keep track of multibyte state */
258 /* `basefix' is used to avoid `if' tests in the integer scanner */
259 static const short basefix
[17] =
260 {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
269 memset (&state
, '\0', sizeof (state
));
270 nbytes
= _mbtowc_r (rptr
, &wc
, fmt
, MB_CUR_MAX
, &state
);
275 if (nbytes
== 1 && isspace (wc
))
281 if (!isspace (*fp
->_p
))
283 nread
++, fp
->_r
--, fp
->_p
++;
296 * switch on the format. continue if done; break once format
308 for (n
= 0; n
< nbytes
; ++n
)
312 if (*fp
->_p
!= *lptr
)
327 if (flags
== SUPPRESS
|| flags
== 0)
332 continue; /* invalid format, don't process any further */
353 continue; /* invalid format, don't process any further */
360 vec_read_count
= (flags
& SHORT
) ? 8 : ((flags
& LONG
) ? 4 : 16);
373 width
= width
* 10 + c
- '0';
377 * Conversions. Those marked `compat' are for
378 * 4.[123]BSD compatibility.
380 * (According to ANSI, E and X formats are supposed to
381 * the same as e and x. Sorry about that.)
384 case 'D': /* compat */
389 ccfn
= (u_long (*)())_strtol_r
;
395 ccfn
= (u_long (*)())_strtol_r
;
399 case 'O': /* compat */
414 case 'X': /* compat XXX */
416 flags
|= PFXOK
; /* enable 0x prefixing */
422 #ifdef FLOATING_POINT
423 case 'E': /* compat XXX */
424 case 'G': /* compat XXX */
425 /* ANSI says that E,G and X behave the same way as e,g,x */
436 /* treat fixed-point like %f floating point */
453 fmt
= __sccl (ccltab
, fmt
);
464 /* not allowed to have h or l with c specifier */
465 if (flags
& (LONG
| SHORT
))
466 continue; /* invalid format don't process any further */
472 case 'p': /* pointer format is like hex */
473 flags
|= POINTER
| PFXOK
;
480 if (flags
& SUPPRESS
) /* ??? */
485 sp
= va_arg (ap
, short *);
488 else if (flags
& LONG
)
490 lp
= va_arg (ap
, long *);
494 else if (flags
& LONGDBL
)
496 llp
= va_arg (ap
, long long*);
502 ip
= va_arg (ap
, int *);
508 * Disgusting backwards compatibility hacks. XXX
510 case '\0': /* compat */
513 default: /* compat */
517 ccfn
= (u_long (*)())_strtol_r
;
524 * We have a conversion that requires input.
530 * Consume leading white space, except for formats that
533 last_space_char
= '\0';
535 if ((flags
& NOSKIP
) == 0)
537 while (isspace (*fp
->_p
))
539 last_space_char
= *fp
->_p
;
550 * Note that there is at least one character in the
551 * buffer, so conversions that do not set NOSKIP ca
552 * no longer result in an input failure.
556 /* for vector formats process separator characters after first loop */
557 if (looped
&& (flags
& VECTOR
))
560 /* all formats other than default char have a separator char */
561 if (vec_sep
!= ' ' || type
!= CT_CHAR
)
563 if (vec_sep
== ' ' && last_space_char
!= ' ' ||
564 vec_sep
!= ' ' && *fp
->_p
!= vec_sep
)
578 /* after eating the separator char, we must eat any white-space
579 after the separator char that precedes the data to convert */
580 if ((flags
& NOSKIP
) == 0)
582 while (isspace (*fp
->_p
))
584 last_space_char
= *fp
->_p
;
597 else /* save to counter-act changes made to flags when processing */
607 /* scan arbitrary characters (sets NOSKIP) */
610 if (flags
& SUPPRESS
)
616 if ((n
= fp
->_r
) < (int)width
)
650 ch_dest
= va_arg (ap
, char *);
653 /* Kludge city for the moment */
659 *ch_dest
++ = *(fp
->_p
++);
665 size_t r
= fread (ch_dest
, 1, width
, fp
);
672 if (!(flags
& VECTOR
))
678 /* scan a (nonempty) character class (sets NOSKIP) */
680 width
= ~0; /* `infinity' */
681 /* take only those things in the class */
682 if (flags
& SUPPRESS
)
685 while (ccltab
[*fp
->_p
])
687 n
++, fp
->_r
--, fp
->_p
++;
702 p0
= p
= va_arg (ap
, char *);
703 while (ccltab
[*fp
->_p
])
726 /* like CCL, but zero-length string OK, & no NOSKIP */
729 if (flags
& SUPPRESS
)
732 while (!isspace (*fp
->_p
))
734 n
++, fp
->_r
--, fp
->_p
++;
744 p0
= p
= va_arg (ap
, char *);
745 while (!isspace (*fp
->_p
))
762 unsigned int_width_left
= 0;
766 if (int_width
== 0 || int_width
> sizeof (buf
) - 1)
768 /* size_t is unsigned, hence this optimisation */
769 if (int_width
- 1 > sizeof (buf
) - 2)
772 int_width_left
= width
- (sizeof (buf
) - 1);
773 int_width
= sizeof (buf
) - 1;
775 flags
|= SIGNOK
| NDIGITS
| NZDIGITS
| NNZDIGITS
;
776 for (p
= buf
; int_width
; int_width
--)
780 * Switch on the character; `goto ok' if we
781 * accept it as a part of number.
786 * The digit 0 is always legal, but is special.
787 * For %i conversions, if no digits (zero or nonzero)
788 * have been scanned (only signs), we will have base==0.
789 * In that case, we should set it to 8 and enable 0x
790 * prefixing. Also, if we have not scanned zero digits
791 * before this, do not turn off prefixing (someone else
792 * will turn it off if we have scanned any nonzero digits).
795 if (! (flags
& NNZDIGITS
))
802 if (flags
& NZDIGITS
)
804 flags
&= ~(SIGNOK
| NZDIGITS
| NDIGITS
);
807 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
);
816 /* 1 through 7 always legal */
824 base
= basefix
[base
];
825 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
| NNZDIGITS
);
828 /* digits 8 and 9 ok iff decimal or hex */
831 base
= basefix
[base
];
833 break; /* not legal here */
834 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
| NNZDIGITS
);
837 /* letters ok iff hex */
850 /* no need to fix base here */
852 break; /* not legal here */
853 flags
&= ~(SIGNOK
| PFXOK
| NDIGITS
| NNZDIGITS
);
856 /* sign ok only as first character */
866 /* x ok iff flag still set & 2nd char */
869 if (flags
& PFXOK
&& p
== buf
+ 1)
871 base
= 16;/* if %i */
873 /* We must reset the NZDIGITS and NDIGITS
874 flags that would have been unset by seeing
875 the zero that preceded the X or x. */
876 flags
|= NZDIGITS
| NDIGITS
;
883 * If we got here, c is not a legal character
884 * for a number. Stop accumulating digits.
889 * c is legal: store it and look at the next.
902 * If we had only a sign, it is no good; push back the sign.
903 * If the number ends in `x', it was [sign] '0' 'x', so push back
904 * the x and treat it as [sign] '0'.
909 (void) ungetc (*(u_char
*)-- p
, fp
);
912 c
= ((u_char
*) p
)[-1];
913 if (c
== 'x' || c
== 'X')
916 /*(void)*/ ungetc (c
, fp
);
918 if ((flags
& SUPPRESS
) == 0)
923 res
= (*ccfn
) (rptr
, buf
, (char **) NULL
, base
);
924 if ((flags
& POINTER
) && !(flags
& VECTOR
))
925 *(va_arg (ap
, void **)) = (void *) (unsigned _POINTER_INT
) res
;
926 else if (flags
& SHORT
)
928 if (!(flags
& VECTOR
))
929 sp
= va_arg (ap
, short *);
934 else if (flags
& LONG
)
936 if (!(flags
& VECTOR
))
937 lp
= va_arg (ap
, long *);
943 else if (flags
& LONGDBL
)
946 if (ccfn
== _strtoul_r
)
947 resll
= _strtoull_r (rptr
, buf
, (char **) NULL
, base
);
949 resll
= _strtoll_r (rptr
, buf
, (char **) NULL
, base
);
950 llp
= va_arg (ap
, long long*);
956 if (!(flags
& VECTOR
))
958 ip
= va_arg (ap
, int *);
965 *ch_dest
++ = (char)res
;
968 if (!(flags
& VECTOR
))
971 nread
+= p
- buf
+ skips
;
975 #ifdef FLOATING_POINT
978 /* scan a floating point number as if by strtod */
979 /* This code used to assume that the number of digits is reasonable.
980 However, ANSI / ISO C makes no such stipulation; we have to get
981 exact results even when there is an unreasonable amount of
983 long leading_zeroes
= 0;
984 long zeroes
, exp_adjust
;
985 char *exp_start
= NULL
;
986 unsigned fl_width
= width
;
987 unsigned width_left
= 0;
989 if (fl_width
== 0 || fl_width
> sizeof (buf
) - 1)
991 /* size_t is unsigned, hence this optimisation */
992 if (fl_width
- 1 > sizeof (buf
) - 2)
995 width_left
= fl_width
- (sizeof (buf
) - 1);
996 fl_width
= sizeof (buf
) - 1;
998 flags
|= SIGNOK
| NDIGITS
| DPTOK
| EXPOK
;
1001 for (p
= buf
; fl_width
; )
1005 * This code mimicks the integer conversion
1006 * code, but is much simpler.
1012 if (flags
& NDIGITS
)
1033 flags
&= ~(SIGNOK
| NDIGITS
);
1047 flags
&= ~(SIGNOK
| DPTOK
);
1048 leading_zeroes
= zeroes
;
1054 /* no exponent without some digits */
1055 if ((flags
& (NDIGITS
| EXPOK
)) == EXPOK
1056 || ((flags
& EXPOK
) && zeroes
))
1058 if (! (flags
& DPTOK
))
1060 exp_adjust
= zeroes
- leading_zeroes
;
1064 (flags
& ~(EXPOK
| DPTOK
)) |
1088 * If no digits, might be missing exponent digits
1089 * (just give back the exponent) or might be missing
1090 * regular digits, but had sign and/or decimal point.
1092 if (flags
& NDIGITS
)
1096 /* no digits at all */
1099 ungetc (*(u_char
*)-- p
, fp
);
1104 /* just a bad exponent (e and maybe sign) */
1105 c
= *(u_char
*)-- p
;
1107 if (c
!= 'e' && c
!= 'E')
1109 (void) ungetc (c
, fp
); /* sign */
1110 c
= *(u_char
*)-- p
;
1113 (void) ungetc (c
, fp
);
1115 if ((flags
& SUPPRESS
) == 0)
1119 #else /* !_NO_LONG_DBL */
1121 #endif /* !_NO_LONG_DBL */
1125 if ((flags
& (DPTOK
| EXPOK
)) == EXPOK
)
1127 exp_adjust
= zeroes
- leading_zeroes
;
1128 new_exp
= -exp_adjust
;
1131 else if (exp_adjust
)
1132 new_exp
= _strtol_r (rptr
, (exp_start
+ 1), NULL
, 10) - exp_adjust
;
1136 /* If there might not be enough space for the new exponent,
1137 truncate some trailing digits to make room. */
1138 if (exp_start
>= buf
+ sizeof (buf
) - MAX_LONG_LEN
)
1139 exp_start
= buf
+ sizeof (buf
) - MAX_LONG_LEN
- 1;
1140 sprintf (exp_start
, "e%ld", new_exp
);
1143 if (flags
& FIXEDPOINT
)
1147 ufix64
= (__uint64_t
)_strtosfix64_r (rptr
, buf
, NULL
);
1149 ufix64
= _strtoufix64_r (rptr
, buf
, NULL
);
1152 __uint16_t
*sp
= va_arg (ap
, __uint16_t
*);
1153 *sp
= (__uint16_t
)(ufix64
>> 48);
1155 else if (flags
& LONG
)
1157 __uint64_t
*llp
= va_arg (ap
, __uint64_t
*);
1162 __uint32_t
*lp
= va_arg (ap
, __uint32_t
*);
1163 *lp
= (__uint32_t
)(ufix64
>> 32);
1169 #endif /* __SPE__ */
1171 res
= _strtod_r (rptr
, buf
, NULL
);
1172 #else /* !_NO_LONGDBL */
1173 res
= _strtold_r (rptr
, buf
, NULL
);
1174 #endif /* !_NO_LONGDBL */
1177 dp
= va_arg (ap
, double *);
1180 else if (flags
& LONGDBL
)
1182 ldp
= va_arg (ap
, _LONG_DOUBLE
*);
1187 if (!(flags
& VECTOR
))
1188 flp
= va_arg (ap
, float *);
1193 if (!(flags
& VECTOR
))
1198 #endif /* FLOATING_POINT */
1200 if (vec_read_count
-- > 1)
1208 unsigned long *vp
= va_arg (ap
, unsigned long *);
1209 for (i
= 0; i
< 4; ++i
)
1210 *vp
++ = vec_buf
.l
[i
];
1215 return nassigned
? nassigned
: -1;