diff options
Diffstat (limited to 'newlib/libc/stdio/vfscanf.c')
-rw-r--r-- | newlib/libc/stdio/vfscanf.c | 203 |
1 files changed, 122 insertions, 81 deletions
diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c index 4788938c9..76561fe4a 100644 --- a/newlib/libc/stdio/vfscanf.c +++ b/newlib/libc/stdio/vfscanf.c @@ -37,8 +37,8 @@ ANSI_SYNOPSIS va_list <[list]>); int _vfscanf_r(struct _reent *<[reent]>, FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>); - int _vsscanf_r(struct _reent *<[reent]>, const char *<[str]>, - const char *<[fmt]>, va_list <[list]>); + int _vsscanf_r(struct _reent *<[reent]>, const char *<[str]>, const char *<[fmt]>, + va_list <[list]>); TRAD_SYNOPSIS #include <stdio.h> @@ -119,23 +119,11 @@ Supporting OS subroutines required: #endif #include "local.h" -#ifdef INTEGER_ONLY -#define VFSCANF vfiscanf -#define _VFSCANF_R _vfiscanf_r -#define __SVFSCANF __svfiscanf -#define __SVFSCANF_R __svfiscanf_r -#else -#define VFSCANF vfscanf -#define _VFSCANF_R _vfscanf_r -#define __SVFSCANF __svfscanf -#define __SVFSCANF_R __svfscanf_r -#ifndef NO_FLOATING_POINT +#ifndef NO_FLOATING_POINT #define FLOATING_POINT #endif -#endif #ifdef FLOATING_POINT -#include <math.h> #include <float.h> /* Currently a test is made to see if long double processing is warranted. @@ -226,40 +214,39 @@ typedef unsigned long long u_long_long; #ifndef _REENT_ONLY int -_DEFUN(VFSCANF, (fp, fmt, ap), +_DEFUN(vfscanf, (fp, fmt, ap), register FILE *fp _AND _CONST char *fmt _AND va_list ap) { - CHECK_INIT(_REENT); - return __SVFSCANF_R (_REENT, fp, fmt, ap); + CHECK_INIT(fp); + return __svfscanf_r (_REENT, fp, fmt, ap); } int -_DEFUN(__SVFSCANF, (fp, fmt0, ap), +_DEFUN(__svfscanf, (fp, fmt0, ap), register FILE *fp _AND char _CONST *fmt0 _AND va_list ap) { - return __SVFSCANF_R (_REENT, fp, fmt0, ap); + return __svfscanf_r (_REENT, fp, fmt0, ap); } #endif /* !_REENT_ONLY */ int -_DEFUN(_VFSCANF_R, (data, fp, fmt, ap), +_DEFUN(_vfscanf_r, (data, fp, fmt, ap), struct _reent *data _AND register FILE *fp _AND _CONST char *fmt _AND va_list ap) { - CHECK_INIT(data); - return __SVFSCANF_R (data, fp, fmt, ap); + return __svfscanf_r (data, fp, fmt, ap); } int -_DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), +_DEFUN(__svfscanf_r, (rptr, fp, fmt0, ap), struct _reent *rptr _AND register FILE *fp _AND char _CONST *fmt0 _AND @@ -778,7 +765,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), { /* scan an integer as if by strtol/strtoul */ unsigned width_left = 0; - int skips = 0; #ifdef hardway if (width == 0 || width > sizeof (buf) - 1) #else @@ -827,7 +813,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), width_left--; width++; } - ++skips; goto skip; /* 1 through 7 always legal */ @@ -972,7 +957,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), } nassigned++; } - nread += p - buf + skips; + nread += p - buf; break; } #ifdef FLOATING_POINT @@ -987,7 +972,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), long zeroes, exp_adjust; char *exp_start = NULL; unsigned width_left = 0; - int nancount = 0; #ifdef hardway if (width == 0 || width > sizeof (buf) - 1) #else @@ -1010,6 +994,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), */ switch (c) { + case '0': if (flags & NDIGITS) { @@ -1032,12 +1017,8 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), case '7': case '8': case '9': - if (nancount == 0) - { - flags &= ~(SIGNOK | NDIGITS); - goto fok; - } - break; + flags &= ~(SIGNOK | NDIGITS); + goto fok; case '+': case '-': @@ -1047,30 +1028,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), goto fok; } break; - case 'n': - case 'N': - if (nancount == 0 - && (flags & (SIGNOK | NDIGITS | DPTOK | EXPOK)) == - (SIGNOK | NDIGITS | DPTOK | EXPOK)) - { - flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS); - nancount = 1; - goto fok; - } - else if (nancount == 2) - { - nancount = 3; - goto fok; - } - break; - case 'a': - case 'A': - if (nancount == 1) - { - nancount = 2; - goto fok; - } - break; case '.': if (flags & DPTOK) { @@ -1112,24 +1069,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), } if (zeroes) flags &= ~NDIGITS; - /* We may have a 'N' or possibly even a 'Na' as the start of 'NaN', - only to run out of chars before it was complete (or having - encountered a non- matching char). So check here if we have an - outstanding nancount, and if so put back the chars we did - swallow and treat as a failed match. */ - if (nancount && nancount != 3) - { - /* Ok... what are we supposed to do in the event that the - __srefill call above was triggered in the middle of the partial - 'NaN' and so we can't put it all back? */ - while (nancount-- && (p > buf)) - { - ungetc (*(u_char *)--p, fp); - --nread; - } - goto match_failure; - } - /* + /* * If no digits, might be missing exponent digits * (just give back the exponent) or might be missing * regular digits, but had sign and/or decimal point. @@ -1141,7 +1081,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), /* no digits at all */ while (p > buf) { - ungetc (*(u_char *)--p, fp); + ungetc (*(u_char *)-- p, fp); --nread; } goto match_failure; @@ -1210,10 +1150,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), else { flp = va_arg (ap, float *); - if (isnan (res)) - *flp = nanf (NULL); - else - *flp = res; + *flp = res; } nassigned++; } @@ -1230,3 +1167,107 @@ all_done: _funlockfile (fp); return nassigned; } + +/* + * Fill in the given table from the scanset at the given format + * (just after `['). Return a pointer to the character past the + * closing `]'. The table has a 1 wherever characters should be + * considered part of the scanset. + */ + +/*static*/ +u_char * +_DEFUN(__sccl, (tab, fmt), + register char *tab _AND + register u_char *fmt) +{ + register int c, n, v; + + /* first `clear' the whole table */ + c = *fmt++; /* first char hat => negated scanset */ + if (c == '^') + { + v = 1; /* default => accept */ + 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; + if (c == 0) + return fmt - 1; /* format ended before closing ] */ + + /* + * Now set the entries corresponding to the actual scanset to the + * opposite of the above. + * + * The first character may be ']' (or '-') without being special; the + * last character may be '-'. + */ + + v = 1 - v; + for (;;) + { + tab[c] = v; /* take character c */ + doswitch: + n = *fmt++; /* and examine the next */ + switch (n) + { + + case 0: /* format ended too soon */ + return fmt - 1; + + case '-': + /* + * A scanset of the form [01+-] is defined as `the digit 0, the + * digit 1, the character +, the character -', but the effect of a + * scanset such as [a-zA-Z0-9] is implementation defined. The V7 + * Unix scanf treats `a-z' as `the letters a through z', but treats + * `a-a' as `the letter a, the character -, and the letter a'. + * + * For compatibility, the `-' is not considerd to define a range if + * the character following it is either a close bracket (required by + * ANSI) or is not numerically greater than the character we just + * stored in the table (c). + */ + n = *fmt; + if (n == ']' || n < c) + { + c = '-'; + break; /* resume the for(;;) */ + } + fmt++; + do + { /* fill in the range */ + tab[++c] = v; + } + while (c < n); +#if 1 /* XXX another disgusting compatibility hack */ + /* + * Alas, the V7 Unix scanf also treats formats such + * as [a-c-e] as `the letters a through e'. This too + * is permitted by the standard.... + */ + goto doswitch; +#else + c = *fmt++; + if (c == 0) + return fmt - 1; + if (c == ']') + return fmt; +#endif + + break; + + + case ']': /* end of scanset */ + return fmt; + + default: /* just another character */ + c = n; + break; + } + } + /* NOTREACHED */ +} |