2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)vfscanf.c 8.1 (Berkeley) 6/4/93
37 * $FreeBSD: /repoman/r/ncvs/src/lib/libc/stdio/vfscanf.c,v 1.35 2004/01/31 23:16:09 das Exp $
38 * $DragonFly: src/lib/libc/stdio/vfscanf.c,v 1.10 2005/12/20 00:21:53 davidxu Exp $
41 #include "namespace.h"
42 #include <sys/types.h>
48 #include "un-namespace.h"
51 #include "libc_private.h"
53 #include "priv_stdio.h"
55 #define FLOATING_POINT
62 #define BUF 513 /* Maximum length of numeric string. */
65 * Flags used during conversion.
67 #define LONG 0x01 /* l: long or double */
68 #define LONGDBL 0x02 /* L: long double */
69 #define SHORT 0x04 /* h: short */
70 #define SUPPRESS 0x08 /* suppress assignment */
71 #define POINTER 0x10 /* weird %p pointer (`fake hex') */
72 #define NOSKIP 0x20 /* do not skip blanks */
76 * The following are used in numeric conversions only:
77 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
78 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
80 #define SIGNOK 0x40 /* +/- is (still) legal */
81 #define NDIGITS 0x80 /* no digits detected */
83 #define DPTOK 0x100 /* (float) decimal point is still legal */
84 #define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */
86 #define PFXOK 0x100 /* 0x prefix is (still) legal */
87 #define NZDIGITS 0x200 /* no zero digits detected */
88 #define HAVESIGN 0x10000 /* sign detected */
93 #define CT_CHAR 0 /* %c conversion */
94 #define CT_CCL 1 /* %[...] conversion */
95 #define CT_STRING 2 /* %s conversion */
96 #define CT_INT 3 /* integer, i.e., strtoq or strtouq */
97 #define CT_FLOAT 4 /* floating, i.e., strtod */
99 #define u_char unsigned char
100 #define u_long unsigned long
102 static u_char *__sccl(char *, u_char *);
105 * __vfscanf MT-safe version
108 __vfscanf(FILE *fp, char const *fmt0, va_list ap)
113 ret = __svfscanf(fp, fmt0, ap);
119 * __svfscanf - non-MT-safe version of __vfscanf
122 __svfscanf(FILE *fp, char const *fmt0, va_list ap)
124 u_char *fmt = (u_char *)fmt0;
125 int c; /* character from format, or conversion */
126 size_t width; /* field width, or 0 */
127 char *p; /* points into all kinds of strings */
128 int n; /* handy integer */
129 int flags; /* flags as defined above */
130 char *p0; /* saves original value of p when necessary */
131 int nassigned; /* number of fields assigned */
132 int nconversions; /* number of conversions */
133 int nread; /* number of characters consumed from fp */
134 int base; /* base argument to strtoq/strtouq */
135 u_quad_t(*ccfn)(); /* conversion function (strtoq/strtouq) */
136 char ccltab[256]; /* character class table for %[...] */
137 char buf[BUF]; /* buffer for numeric conversions */
139 /* `basefix' is used to avoid `if' tests in the integer scanner */
140 static short basefix[17] =
141 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
142 #ifdef FLOATING_POINT
143 char decimal_point = localeconv()->decimal_point[0];
149 base = 0; /* XXX just to keep gcc happy */
150 ccfn = NULL; /* XXX just to keep gcc happy */
156 while ((fp->pub._r > 0 || __srefill(fp) == 0) && isspace(*fp->pub._p))
157 nread++, fp->pub._r--, fp->pub._p++;
165 * switch on the format. continue if done;
166 * break once format type is derived.
172 if (fp->pub._r <= 0 && __srefill(fp))
174 if (*fp->pub._p != c)
176 fp->pub._r--, fp->pub._p++;
196 case '0': case '1': case '2': case '3': case '4':
197 case '5': case '6': case '7': case '8': case '9':
198 width = width * 10 + c - '0';
203 * Those marked `compat' are for 4.[123]BSD compatibility.
205 * (According to ANSI, E and X formats are supposed
206 * to the same as e and x. Sorry about that.)
208 case 'D': /* compat */
213 ccfn = (u_quad_t (*)())strtoq;
219 ccfn = (u_quad_t (*)())strtoq;
223 case 'O': /* compat */
238 case 'X': /* compat XXX */
242 flags |= PFXOK; /* enable 0x prefixing */
248 #ifdef FLOATING_POINT
249 case 'E': /* compat XXX */
250 case 'F': /* compat */
253 case 'e': case 'f': case 'g':
263 fmt = __sccl(ccltab, fmt);
273 case 'p': /* pointer format is like hex */
274 flags |= POINTER | PFXOK;
282 if (flags & SUPPRESS) /* ??? */
285 *va_arg(ap, short *) = nread;
286 else if (flags & LONG)
287 *va_arg(ap, long *) = nread;
288 else if (flags & QUAD)
289 *va_arg(ap, quad_t *) = nread;
291 *va_arg(ap, int *) = nread;
295 * Disgusting backwards compatibility hacks. XXX
297 case '\0': /* compat */
300 default: /* compat */
304 ccfn = (u_quad_t (*)())strtoq;
310 * We have a conversion that requires input.
312 if (fp->pub._r <= 0 && __srefill(fp))
316 * Consume leading white space, except for formats
317 * that suppress this.
319 if ((flags & NOSKIP) == 0) {
320 while (isspace(*fp->pub._p)) {
322 if (--fp->pub._r > 0)
324 else if (__srefill(fp))
328 * Note that there is at least one character in
329 * the buffer, so conversions that do not set NOSKIP
330 * ca no longer result in an input failure.
340 /* scan arbitrary characters (sets NOSKIP) */
343 if (flags & SUPPRESS) {
346 if ((n = fp->pub._r) < width) {
364 size_t r = __fread((void *)va_arg(ap, char *),
376 /* scan a (nonempty) character class (sets NOSKIP) */
378 width = (size_t)~0; /* `infinity' */
379 /* take only those things in the class */
380 if (flags & SUPPRESS) {
382 while (ccltab[*fp->pub._p]) {
383 n++, fp->pub._r--, fp->pub._p++;
386 if (fp->pub._r <= 0 && __srefill(fp)) {
395 p0 = p = va_arg(ap, char *);
396 while (ccltab[*fp->pub._p]) {
398 *p++ = *fp->pub._p++;
401 if (fp->pub._r <= 0 && __srefill(fp)) {
418 /* like CCL, but zero-length string OK, & no NOSKIP */
421 if (flags & SUPPRESS) {
423 while (!isspace(*fp->pub._p)) {
424 n++, fp->pub._r--, fp->pub._p++;
427 if (fp->pub._r <= 0 && __srefill(fp))
432 p0 = p = va_arg(ap, char *);
433 while (!isspace(*fp->pub._p)) {
435 *p++ = *fp->pub._p++;
438 if (fp->pub._r <= 0 && __srefill(fp))
449 /* scan an integer as if by strtoq/strtouq */
451 if (width == 0 || width > sizeof(buf) - 1)
452 width = sizeof(buf) - 1;
454 /* size_t is unsigned, hence this optimisation */
455 if (--width > sizeof(buf) - 2)
456 width = sizeof(buf) - 2;
459 flags |= SIGNOK | NDIGITS | NZDIGITS;
460 for (p = buf; width; width--) {
463 * Switch on the character; `goto ok'
464 * if we accept it as a part of number.
469 * The digit 0 is always legal, but is
470 * special. For %i conversions, if no
471 * digits (zero or nonzero) have been
472 * scanned (only signs), we will have
473 * base==0. In that case, we should set
474 * it to 8 and enable 0x prefixing.
475 * Also, if we have not scanned zero digits
476 * before this, do not turn off prefixing
477 * (someone else will turn it off if we
478 * have scanned any nonzero digits).
485 if (flags & NZDIGITS)
486 flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
488 flags &= ~(SIGNOK|PFXOK|NDIGITS);
491 /* 1 through 7 always legal */
492 case '1': case '2': case '3':
493 case '4': case '5': case '6': case '7':
494 base = basefix[base];
495 flags &= ~(SIGNOK | PFXOK | NDIGITS);
498 /* digits 8 and 9 ok iff decimal or hex */
500 base = basefix[base];
502 break; /* not legal here */
503 flags &= ~(SIGNOK | PFXOK | NDIGITS);
506 /* letters ok iff hex */
507 case 'A': case 'B': case 'C':
508 case 'D': case 'E': case 'F':
509 case 'a': case 'b': case 'c':
510 case 'd': case 'e': case 'f':
511 /* no need to fix base here */
513 break; /* not legal here */
514 flags &= ~(SIGNOK | PFXOK | NDIGITS);
517 /* sign ok only as first character */
519 if (flags & SIGNOK) {
527 * x ok iff flag still set & 2nd char (or
528 * 3rd char if we have a sign).
531 if (flags & PFXOK && p ==
532 buf + 1 + !!(flags & HAVESIGN)) {
533 base = 16; /* if %i */
541 * If we got here, c is not a legal character
542 * for a number. Stop accumulating digits.
547 * c is legal: store it and look at the next.
550 if (--fp->pub._r > 0)
552 else if (__srefill(fp))
556 * If we had only a sign, it is no good; push
557 * back the sign. If the number ends in `x',
558 * it was [sign] '0' 'x', so push back the x
559 * and treat it as [sign] '0'.
561 if (flags & NDIGITS) {
563 __ungetc(*(u_char *)--p, fp);
566 c = ((u_char *)p)[-1];
567 if (c == 'x' || c == 'X') {
571 if ((flags & SUPPRESS) == 0) {
575 res = (*ccfn)(buf, (char **)NULL, base);
577 *va_arg(ap, void **) =
579 else if (flags & SHORT)
580 *va_arg(ap, short *) = res;
581 else if (flags & LONG)
582 *va_arg(ap, long *) = res;
583 else if (flags & QUAD)
584 *va_arg(ap, quad_t *) = res;
586 *va_arg(ap, int *) = res;
593 #ifdef FLOATING_POINT
595 /* scan a floating point number as if by strtod */
597 if (width == 0 || width > sizeof(buf) - 1)
598 width = sizeof(buf) - 1;
600 /* size_t is unsigned, hence this optimisation */
601 if (--width > sizeof(buf) - 2)
602 width = sizeof(buf) - 2;
605 flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
606 for (p = buf; width; width--) {
609 * This code mimicks the integer conversion
610 * code, but is much simpler.
614 case '0': case '1': case '2': case '3':
615 case '4': case '5': case '6': case '7':
617 flags &= ~(SIGNOK | NDIGITS);
621 if (flags & SIGNOK) {
627 /* no exponent without some digits */
628 if ((flags&(NDIGITS|EXPOK)) == EXPOK) {
630 (flags & ~(EXPOK|DPTOK)) |
636 if ((char)c == decimal_point &&
638 flags &= ~(SIGNOK | DPTOK);
646 if (--fp->pub._r > 0)
648 else if (__srefill(fp))
652 * If no digits, might be missing exponent digits
653 * (just give back the exponent) or might be missing
654 * regular digits, but had sign and/or decimal point.
656 if (flags & NDIGITS) {
658 /* no digits at all */
660 __ungetc(*(u_char *)--p, fp);
663 /* just a bad exponent (e and maybe sign) */
665 if (c != 'e' && c != 'E') {
666 __ungetc(c, fp);/* sign */
671 if ((flags & SUPPRESS) == 0) {
675 /* XXX this loses precision for long doubles. */
676 res = strtod(buf, (char **) NULL);
678 *va_arg(ap, long double *) = res;
679 else if (flags & LONG)
680 *va_arg(ap, double *) = res;
682 *va_arg(ap, float *) = res;
688 #endif /* FLOATING_POINT */
692 return (nconversions != 0 ? nassigned : EOF);
698 * Fill in the given table from the scanset at the given format
699 * (just after `['). Return a pointer to the character past the
700 * closing `]'. The table has a 1 wherever characters should be
701 * considered part of the scanset.
704 __sccl(char *tab, u_char *fmt)
708 /* first `clear' the whole table */
709 c = *fmt++; /* first char hat => negated scanset */
711 v = 1; /* default => accept */
712 c = *fmt++; /* get new first char */
714 v = 0; /* default => reject */
716 /* XXX: Will not work if sizeof(tab*) > sizeof(char) */
720 return (fmt - 1);/* format ended before closing ] */
723 * Now set the entries corresponding to the actual scanset
724 * to the opposite of the above.
726 * The first character may be ']' (or '-') without being special;
727 * the last character may be '-'.
731 tab[c] = v; /* take character c */
733 n = *fmt++; /* and examine the next */
736 case 0: /* format ended too soon */
741 * A scanset of the form
743 * is defined as `the digit 0, the digit 1,
744 * the character +, the character -', but
745 * the effect of a scanset such as
747 * is implementation defined. The V7 Unix
748 * scanf treats `a-z' as `the letters a through
749 * z', but treats `a-a' as `the letter a, the
750 * character -, and the letter a'.
752 * For compatibility, the `-' is not considerd
753 * to define a range if the character following
754 * it is either a close bracket (required by ANSI)
755 * or is not numerically greater than the character
756 * we just stored in the table (c).
760 || (__collate_load_error ? n < c :
761 __collate_range_cmp (n, c) < 0
765 break; /* resume the for(;;) */
768 /* fill in the range */
769 if (__collate_load_error) {
774 for (i = 0; i < 256; i ++)
775 if ( __collate_range_cmp (c, i) < 0
776 && __collate_range_cmp (i, n) <= 0
780 #if 1 /* XXX another disgusting compatibility hack */
783 * Alas, the V7 Unix scanf also treats formats
784 * such as [a-c-e] as `the letters a through e'.
785 * This too is permitted by the standard....
797 case ']': /* end of scanset */
800 default: /* just another character */