3 <<vscanf>>, <<vfscanf>>, <<vsscanf>>---format argument list
15 int vscanf(const char *<[fmt]>, va_list <[list]>);
16 int vfscanf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
17 int vsscanf(const char *<[str]>, const char *<[fmt]>, va_list <[list]>);
19 int _vscanf_r(void *<[reent]>, const char *<[fmt]>,
21 int _vfscanf_r(void *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
23 int _vsscanf_r(void *<[reent]>, const char *<[str]>, const char *<[fmt]>,
29 int vscanf( <[fmt]>, <[ist]>)
33 int vfscanf( <[fp]>, <[fmt]>, <[list]>)
38 int vsscanf( <[str]>, <[fmt]>, <[list]>)
43 int _vscanf_r( <[reent]>, <[fmt]>, <[ist]>)
48 int _vfscanf_r( <[reent]>, <[fp]>, <[fmt]>, <[list]>)
54 int _vsscanf_r( <[reent]>, <[str]>, <[fmt]>, <[list]>)
61 <<vscanf>>, <<vfscanf>>, and <<vsscanf>> are (respectively) variants
62 of <<scanf>>, <<fscanf>>, and <<sscanf>>. They differ only in
63 allowing their caller to pass the variable argument list as a
64 <<va_list>> object (initialized by <<va_start>>) rather than
65 directly accepting a variable number of arguments.
68 The return values are consistent with the corresponding functions:
69 <<vscanf>> returns the number of input fields successfully scanned,
70 converted, and stored; the return value does not include scanned
71 fields which were not stored.
73 If <<vscanf>> attempts to read at end-of-file, the return value
76 If no fields were stored, the return value is <<0>>.
78 The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are
79 reentrant versions which take an additional first parameter which points to the
83 These are GNU extensions.
85 Supporting OS subroutines required:
89 * Copyright (c) 1990 The Regents of the University of California.
90 * All rights reserved.
92 * Redistribution and use in source and binary forms are permitted
93 * provided that the above copyright notice and this paragraph are
94 * duplicated in all such forms and that any documentation,
95 * advertising materials, and other materials related to such
96 * distribution and use acknowledge that the software was developed
97 * by the University of California, Berkeley. The name of the
98 * University may not be used to endorse or promote products derived
99 * from this software without specific prior written permission.
100 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
101 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
102 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
119 #ifndef NO_FLOATING_POINT
120 #define FLOATING_POINT
123 #ifdef FLOATING_POINT
126 /* Currently a test is made to see if long double processing is warranted.
127 This could be changed in the future should the _ldtoa_r code be
128 preferred over _dtoa_r. */
130 #if defined WANT_IO_LONG_DBL && (LDBL_MANT_DIG > DBL_MANT_DIG)
132 extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr));
136 extern __int64_t _strtosfix64_r _PARAMS((struct _reent *, char *s, char **sptr));
137 extern __uint64_t _strtoufix64_r _PARAMS((struct _reent *, char *s, char **sptr));
141 #if defined WANT_PRINTF_LONG_LONG && defined __GNUC__
146 #define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
147 /* An upper bound for how long a long prints in decimal. 4 / 13 approximates
148 log (2). Add one char for roundoff compensation and one for the sign. */
149 #define MAX_LONG_LEN ((CHAR_BIT * sizeof (long) - 1) * 4 / 13 + 2)
155 * Flags used during conversion.
158 #define LONG 0x01 /* l: long or double */
159 #define LONGDBL 0x02 /* L: long double or long long */
160 #define SHORT 0x04 /* h: short */
161 #define SUPPRESS 0x08 /* suppress assignment */
162 #define POINTER 0x10 /* weird %p pointer (`fake hex') */
163 #define NOSKIP 0x20 /* do not skip blanks */
166 * The following are used in numeric conversions only:
167 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
168 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
171 #define SIGNOK 0x40 /* +/- is (still) legal */
172 #define NDIGITS 0x80 /* no digits detected */
174 #define DPTOK 0x100 /* (float) decimal point is still legal */
175 #define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */
177 #define PFXOK 0x100 /* 0x prefix is (still) legal */
178 #define NZDIGITS 0x200 /* no zero digits detected */
180 #define VECTOR 0x400 /* v: vector */
181 #define FIXEDPOINT 0x800 /* r/R: fixed-point */
182 #define SIGNED 0x1000 /* r: signed fixed-point */
188 #define CT_CHAR 0 /* %c conversion */
189 #define CT_CCL 1 /* %[...] conversion */
190 #define CT_STRING 2 /* %s conversion */
191 #define CT_INT 3 /* integer, i.e., strtol or strtoul */
192 #define CT_FLOAT 4 /* floating, i.e., strtod */
195 #define u_char unsigned char
198 #define u_long unsigned long
201 typedef unsigned long long u_long_long;
206 char c[16] __attribute__ ((__aligned__ (16)));
213 /*static*/ u_char *__sccl ();
219 #define BufferEmpty (fp->_r <= 0 && __srefill(fp))
224 _DEFUN (vfscanf, (fp, fmt, ap),
225 register FILE *fp _AND
226 _CONST char *fmt _AND
230 return __svfscanf_r (fp->_data, fp, fmt, ap);
234 __svfscanf (fp, fmt0, ap)
239 return __svfscanf_r (_REENT, fp, fmt0, ap);
242 #endif /* !_REENT_ONLY */
245 _DEFUN (_vfscanf_r, (data, fp, fmt, ap),
246 struct _reent *data _AND
247 register FILE *fp _AND
248 _CONST char *fmt _AND
251 return __svfscanf_r (data, fp, fmt, ap);
256 __svfscanf_r (rptr, fp, fmt0, ap)
262 register u_char *fmt = (u_char *) fmt0;
263 register int c; /* character from format, or conversion */
264 register int type; /* conversion type */
265 register size_t width; /* field width, or 0 */
266 register char *p; /* points into all kinds of strings */
267 register int n; /* handy integer */
268 register int flags; /* flags as defined above */
269 register char *p0; /* saves original value of p when necessary */
270 int orig_flags; /* saved flags used when processing vector */
271 int int_width; /* tmp area to store width when processing int */
272 int nassigned; /* number of fields assigned */
273 int nread; /* number of characters consumed from fp */
274 int base = 0; /* base argument to strtol/strtoul */
275 int nbytes = 1; /* number of bytes read from fmt string */
276 wchar_t wc; /* wchar to use to read format string */
277 char vec_sep; /* vector separator char */
278 char last_space_char; /* last white-space char eaten - needed for vec support */
279 int vec_read_count; /* number of vector items to read separately */
280 int looped; /* has vector processing looped */
281 u_long (*ccfn) () = 0; /* conversion function (strtol/strtoul) */
282 char ccltab[256]; /* character class table for %[...] */
283 char buf[BUF]; /* buffer for numeric conversions */
285 char *lptr; /* literal pointer */
287 mbstate_t state; /* value to keep track of multibyte state */
303 /* `basefix' is used to avoid `if' tests in the integer scanner */
304 static _CONST short basefix[17] =
305 {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
314 memset (&state, '\0', sizeof (state));
315 nbytes = _mbtowc_r (rptr, &wc, fmt, MB_CUR_MAX, &state);
320 if (nbytes == 1 && isspace (wc))
326 if (!isspace (*fp->_p))
328 nread++, fp->_r--, fp->_p++;
341 * switch on the format. continue if done; break once format
353 for (n = 0; n < nbytes; ++n)
357 if (*fp->_p != *lptr)
372 if (flags == SUPPRESS || flags == 0)
377 continue; /* invalid format, don't process any further */
398 continue; /* invalid format, don't process any further */
405 vec_read_count = (flags & SHORT) ? 8 : ((flags & LONG) ? 4 : 16);
418 width = width * 10 + c - '0';
422 * Conversions. Those marked `compat' are for
423 * 4.[123]BSD compatibility.
425 * (According to ANSI, E and X formats are supposed to
426 * the same as e and x. Sorry about that.)
429 case 'D': /* compat */
434 ccfn = (u_long (*)())_strtol_r;
440 ccfn = (u_long (*)())_strtol_r;
444 case 'O': /* compat */
459 case 'X': /* compat XXX */
461 flags |= PFXOK; /* enable 0x prefixing */
467 #ifdef FLOATING_POINT
468 case 'E': /* compat XXX */
469 case 'G': /* compat XXX */
470 /* ANSI says that E,G and X behave the same way as e,g,x */
481 /* treat fixed-point like %f floating point */
498 fmt = __sccl (ccltab, fmt);
509 /* not allowed to have h or l with c specifier */
510 if (flags & (LONG | SHORT))
511 continue; /* invalid format don't process any further */
517 case 'p': /* pointer format is like hex */
518 flags |= POINTER | PFXOK;
525 if (flags & SUPPRESS) /* ??? */
530 sp = va_arg (ap, short *);
533 else if (flags & LONG)
535 lp = va_arg (ap, long *);
539 else if (flags & LONGDBL)
541 llp = va_arg (ap, long long*);
547 ip = va_arg (ap, int *);
553 * Disgusting backwards compatibility hacks. XXX
555 case '\0': /* compat */
558 default: /* compat */
562 ccfn = (u_long (*)())_strtol_r;
569 * We have a conversion that requires input.
575 * Consume leading white space, except for formats that
578 last_space_char = '\0';
580 if ((flags & NOSKIP) == 0)
582 while (isspace (*fp->_p))
584 last_space_char = *fp->_p;
595 * Note that there is at least one character in the
596 * buffer, so conversions that do not set NOSKIP ca
597 * no longer result in an input failure.
601 /* for vector formats process separator characters after first loop */
602 if (looped && (flags & VECTOR))
605 /* all formats other than default char have a separator char */
606 if (vec_sep != ' ' || type != CT_CHAR)
608 if (vec_sep == ' ' && last_space_char != ' ' ||
609 vec_sep != ' ' && *fp->_p != vec_sep)
623 /* after eating the separator char, we must eat any white-space
624 after the separator char that precedes the data to convert */
625 if ((flags & NOSKIP) == 0)
627 while (isspace (*fp->_p))
629 last_space_char = *fp->_p;
642 else /* save to counter-act changes made to flags when processing */
652 /* scan arbitrary characters (sets NOSKIP) */
655 if (flags & SUPPRESS)
661 if ((n = fp->_r) < (int)width)
695 ch_dest = va_arg (ap, char *);
698 /* Kludge city for the moment */
704 *ch_dest++ = *(fp->_p++);
710 size_t r = fread (ch_dest, 1, width, fp);
717 if (!(flags & VECTOR))
723 /* scan a (nonempty) character class (sets NOSKIP) */
725 width = ~0; /* `infinity' */
726 /* take only those things in the class */
727 if (flags & SUPPRESS)
730 while (ccltab[*fp->_p])
732 n++, fp->_r--, fp->_p++;
747 p0 = p = va_arg (ap, char *);
748 while (ccltab[*fp->_p])
771 /* like CCL, but zero-length string OK, & no NOSKIP */
774 if (flags & SUPPRESS)
777 while (!isspace (*fp->_p))
779 n++, fp->_r--, fp->_p++;
789 p0 = p = va_arg (ap, char *);
790 while (!isspace (*fp->_p))
806 /* scan an integer as if by strtol/strtoul */
809 if (int_width == 0 || int_width > sizeof (buf) - 1)
810 int_width = sizeof (buf) - 1;
812 /* size_t is unsigned, hence this optimisation */
813 if (--int_width > sizeof (buf) - 2)
814 int_width = sizeof (buf) - 2;
817 flags |= SIGNOK | NDIGITS | NZDIGITS;
818 for (p = buf; int_width; int_width--)
822 * Switch on the character; `goto ok' if we
823 * accept it as a part of number.
828 * The digit 0 is always legal, but is special.
829 * For %i conversions, if no digits (zero or nonzero)
830 * have been scanned (only signs), we will have base==0.
831 * In that case, we should set it to 8 and enable 0x
832 * prefixing. Also, if we have not scanned zero digits
833 * before this, do not turn off prefixing (someone else
834 * will turn it off if we have scanned any nonzero digits).
842 if (flags & NZDIGITS)
843 flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
845 flags &= ~(SIGNOK | PFXOK | NDIGITS);
848 /* 1 through 7 always legal */
856 base = basefix[base];
857 flags &= ~(SIGNOK | PFXOK | NDIGITS);
860 /* digits 8 and 9 ok iff decimal or hex */
863 base = basefix[base];
865 break; /* not legal here */
866 flags &= ~(SIGNOK | PFXOK | NDIGITS);
869 /* letters ok iff hex */
882 /* no need to fix base here */
884 break; /* not legal here */
885 flags &= ~(SIGNOK | PFXOK | NDIGITS);
888 /* sign ok only as first character */
898 /* x ok iff flag still set & 2nd char */
901 if (flags & PFXOK && p == buf + 1)
903 base = 16;/* if %i */
911 * If we got here, c is not a legal character
912 * for a number. Stop accumulating digits.
917 * c is legal: store it and look at the next.
929 * If we had only a sign, it is no good; push back the sign.
930 * If the number ends in `x', it was [sign] '0' 'x', so push back
931 * the x and treat it as [sign] '0'.
936 _CAST_VOID ungetc (*(u_char *)-- p, fp);
939 c = ((u_char *) p)[-1];
940 if (c == 'x' || c == 'X')
943 /*(void)*/ ungetc (c, fp);
945 if ((flags & SUPPRESS) == 0)
950 res = (*ccfn) (rptr, buf, (char **) NULL, base);
951 if ((flags & POINTER) && !(flags & VECTOR))
952 *(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res;
953 else if (flags & SHORT)
955 if (!(flags & VECTOR))
956 sp = va_arg (ap, short *);
961 else if (flags & LONG)
963 if (!(flags & VECTOR))
964 lp = va_arg (ap, long *);
970 else if (flags & LONGDBL)
973 if (ccfn == _strtoul_r)
974 resll = _strtoull_r (rptr, buf, (char **) NULL, base);
976 resll = _strtoll_r (rptr, buf, (char **) NULL, base);
977 llp = va_arg (ap, long long*);
983 if (!(flags & VECTOR))
985 ip = va_arg (ap, int *);
992 *ch_dest++ = (char)res;
995 if (!(flags & VECTOR))
1001 #ifdef FLOATING_POINT
1004 /* scan a floating point number as if by strtod */
1005 /* This code used to assume that the number of digits is reasonable.
1006 However, ANSI / ISO C makes no such stipulation; we have to get
1007 exact results even when there is an unreasonable amount of
1009 long leading_zeroes = 0;
1010 long zeroes, exp_adjust;
1011 char *exp_start = NULL;
1012 int fl_width = width;
1014 if (fl_width == 0 || fl_width > sizeof (buf) - 1)
1015 fl_width = sizeof (buf) - 1;
1017 /* size_t is unsigned, hence this optimisation */
1018 if (--fl_width > sizeof (buf) - 2)
1019 fl_width = sizeof (buf) - 2;
1022 flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
1025 for (p = buf; fl_width; )
1029 * This code mimicks the integer conversion
1030 * code, but is much simpler.
1036 if (flags & NDIGITS)
1052 flags &= ~(SIGNOK | NDIGITS);
1066 flags &= ~(SIGNOK | DPTOK);
1067 leading_zeroes = zeroes;
1073 /* no exponent without some digits */
1074 if ((flags & (NDIGITS | EXPOK)) == EXPOK
1075 || ((flags & EXPOK) && zeroes))
1077 if (! (flags & DPTOK))
1079 exp_adjust = zeroes - leading_zeroes;
1083 (flags & ~(EXPOK | DPTOK)) |
1107 * If no digits, might be missing exponent digits
1108 * (just give back the exponent) or might be missing
1109 * regular digits, but had sign and/or decimal point.
1111 if (flags & NDIGITS)
1115 /* no digits at all */
1118 ungetc (*(u_char *)-- p, fp);
1123 /* just a bad exponent (e and maybe sign) */
1124 c = *(u_char *)-- p;
1126 if (c != 'e' && c != 'E')
1128 _CAST_VOID ungetc (c, fp); /* sign */
1129 c = *(u_char *)-- p;
1132 _CAST_VOID ungetc (c, fp);
1134 if ((flags & SUPPRESS) == 0)
1138 #else /* !_NO_LONG_DBL */
1140 #endif /* !_NO_LONG_DBL */
1144 if ((flags & (DPTOK | EXPOK)) == EXPOK)
1146 exp_adjust = zeroes - leading_zeroes;
1147 new_exp = -exp_adjust;
1150 else if (exp_adjust)
1151 new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust;
1155 /* If there might not be enough space for the new exponent,
1156 truncate some trailing digits to make room. */
1157 if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN)
1158 exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;
1159 sprintf (exp_start, "e%ld", new_exp);
1162 if (flags & FIXEDPOINT)
1166 ufix64 = (__uint64_t)_strtosfix64_r (rptr, buf, NULL);
1168 ufix64 = _strtoufix64_r (rptr, buf, NULL);
1171 __uint16_t *sp = va_arg (ap, __uint16_t *);
1172 *sp = (__uint16_t)(ufix64 >> 48);
1174 else if (flags & LONG)
1176 __uint64_t *llp = va_arg (ap, __uint64_t *);
1181 __uint32_t *lp = va_arg (ap, __uint32_t *);
1182 *lp = (__uint32_t)(ufix64 >> 32);
1188 #endif /* __SPE__ */
1190 res = _strtod_r (rptr, buf, NULL);
1191 #else /* !_NO_LONGDBL */
1192 res = _strtold (buf, NULL);
1193 #endif /* !_NO_LONGDBL */
1196 dp = va_arg (ap, double *);
1199 else if (flags & LONGDBL)
1201 ldp = va_arg (ap, _LONG_DOUBLE *);
1206 if (!(flags & VECTOR))
1207 flp = va_arg (ap, float *);
1212 if (!(flags & VECTOR))
1217 #endif /* FLOATING_POINT */
1219 if (vec_read_count-- > 1)
1227 unsigned long *vp = va_arg (ap, unsigned long *);
1228 for (i = 0; i < 4; ++i)
1229 *vp++ = vec_buf.l[i];
1234 return nassigned ? nassigned : -1;
1240 * Fill in the given table from the scanset at the given format
1241 * (just after `['). Return a pointer to the character past the
1242 * closing `]'. The table has a 1 wherever characters should be
1243 * considered part of the scanset.
1250 register u_char *fmt;
1252 register int c, n, v;
1254 /* first `clear' the whole table */
1255 c = *fmt++; /* first char hat => negated scanset */
1258 v = 1; /* default => accept */
1259 c = *fmt++; /* get new first char */
1262 v = 0; /* default => reject */
1263 /* should probably use memset here */
1264 for (n = 0; n < 256; n++)
1267 return fmt - 1; /* format ended before closing ] */
1270 * Now set the entries corresponding to the actual scanset to the
1271 * opposite of the above.
1273 * The first character may be ']' (or '-') without being special; the
1274 * last character may be '-'.
1280 tab[c] = v; /* take character c */
1282 n = *fmt++; /* and examine the next */
1286 case 0: /* format ended too soon */
1291 * A scanset of the form [01+-] is defined as `the digit 0, the
1292 * digit 1, the character +, the character -', but the effect of a
1293 * scanset such as [a-zA-Z0-9] is implementation defined. The V7
1294 * Unix scanf treats `a-z' as `the letters a through z', but treats
1295 * `a-a' as `the letter a, the character -, and the letter a'.
1297 * For compatibility, the `-' is not considerd to define a range if
1298 * the character following it is either a close bracket (required by
1299 * ANSI) or is not numerically greater than the character we just
1300 * stored in the table (c).
1303 if (n == ']' || n < c)
1306 break; /* resume the for(;;) */
1310 { /* fill in the range */
1314 #if 1 /* XXX another disgusting compatibility hack */
1316 * Alas, the V7 Unix scanf also treats formats such
1317 * as [a-c-e] as `the letters a through e'. This too
1318 * is permitted by the standard....
1332 case ']': /* end of scanset */
1335 default: /* just another character */