diff options
Diffstat (limited to 'lib/libc/stdio/vfscanf.c')
-rw-r--r-- | lib/libc/stdio/vfscanf.c | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c index 22ed5a0..54cf776 100644 --- a/lib/libc/stdio/vfscanf.c +++ b/lib/libc/stdio/vfscanf.c @@ -35,7 +35,11 @@ */ #if defined(LIBC_SCCS) && !defined(lint) +#if 0 static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93"; +#endif +static const char rcsid[] = + "$Id: vfscanf.c,v 1.7 1997/02/22 15:02:41 peter Exp $"; #endif /* LIBC_SCCS and not lint */ #include <stdio.h> @@ -46,6 +50,9 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93"; #else #include <varargs.h> #endif +#include <string.h> + +#include "collate.h" #include "local.h" #define FLOATING_POINT @@ -89,11 +96,12 @@ static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93"; #define u_char unsigned char #define u_long unsigned long -static u_char *__sccl(); +static u_char *__sccl(char *, u_char *); /* * vfscanf */ +int __svfscanf(fp, fmt0, ap) register FILE *fp; char const *fmt0; @@ -107,6 +115,7 @@ __svfscanf(fp, fmt0, ap) register int flags; /* flags as defined above */ register char *p0; /* saves original value of p when necessary */ int nassigned; /* number of fields assigned */ + int nconversions; /* number of conversions */ int nread; /* number of characters consumed from fp */ int base; /* base argument to strtol/strtoul */ u_long (*ccfn)(); /* conversion function (strtol/strtoul) */ @@ -118,6 +127,7 @@ __svfscanf(fp, fmt0, ap) { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; nassigned = 0; + nconversions = 0; nread = 0; base = 0; /* XXX just to keep gcc happy */ ccfn = NULL; /* XXX just to keep gcc happy */ @@ -128,7 +138,7 @@ __svfscanf(fp, fmt0, ap) if (isspace(c)) { for (;;) { if (fp->_r <= 0 && __srefill(fp)) - return (nassigned); + goto input_failure; if (!isspace(*fp->_p)) break; nread++, fp->_r--, fp->_p++; @@ -253,6 +263,7 @@ literal: break; case 'n': + nconversions++; if (flags & SUPPRESS) /* ??? */ continue; if (flags & SHORT) @@ -341,12 +352,13 @@ literal: nread += r; nassigned++; } + nconversions++; break; case CT_CCL: /* scan a (nonempty) character class (sets NOSKIP) */ if (width == 0) - width = ~0; /* `infinity' */ + width = (size_t)~0; /* `infinity' */ /* take only those things in the class */ if (flags & SUPPRESS) { n = 0; @@ -382,12 +394,13 @@ literal: nassigned++; } nread += n; + nconversions++; break; case CT_STRING: /* like CCL, but zero-length string OK, & no NOSKIP */ if (width == 0) - width = ~0; + width = (size_t)~0; if (flags & SUPPRESS) { n = 0; while (!isspace(*fp->_p)) { @@ -412,6 +425,7 @@ literal: nread += p - p0; nassigned++; } + nconversions++; continue; case CT_INT: @@ -548,6 +562,7 @@ literal: nassigned++; } nread += p - buf; + nconversions++; break; #ifdef FLOATING_POINT @@ -639,12 +654,13 @@ literal: nassigned++; } nread += p - buf; + nconversions++; break; #endif /* FLOATING_POINT */ } } input_failure: - return (nassigned ? nassigned : -1); + return (nconversions != 0 ? nassigned : EOF); match_failure: return (nassigned); } @@ -660,7 +676,7 @@ __sccl(tab, fmt) register char *tab; register u_char *fmt; { - register int c, n, v; + register int c, n, v, i; /* first `clear' the whole table */ c = *fmt++; /* first char hat => negated scanset */ @@ -669,9 +685,10 @@ __sccl(tab, fmt) c = *fmt++; /* get new first char */ } else v = 0; /* default => reject */ - /* should probably use memset here */ - for (n = 0; n < 256; n++) - tab[n] = v; + + /* XXX: Will not work if sizeof(tab*) > sizeof(char) */ + (void) memset(tab, v, 256); + if (c == 0) return (fmt - 1);/* format ended before closing ] */ @@ -712,15 +729,19 @@ doswitch: * we just stored in the table (c). */ n = *fmt; - if (n == ']' || n < c) { + if (n == ']' || __collate_range_cmp (n, c) < 0) { c = '-'; break; /* resume the for(;;) */ } fmt++; - do { /* fill in the range */ - tab[++c] = v; - } while (c < n); + /* fill in the range */ + for (i = 0; i < 256; i ++) + if ( __collate_range_cmp (c, i) < 0 + && __collate_range_cmp (i, n) <= 0 + ) + tab[i] = v; #if 1 /* XXX another disgusting compatibility hack */ + c = n; /* * Alas, the V7 Unix scanf also treats formats * such as [a-c-e] as `the letters a through e'. |