diff options
author | Jeff Johnston <jjohnstn@redhat.com> | 2004-04-23 21:30:04 +0000 |
---|---|---|
committer | Jeff Johnston <jjohnstn@redhat.com> | 2004-04-23 21:30:04 +0000 |
commit | 27c7566ca4f436cc6184fdaf568dd84ca9c501f1 (patch) | |
tree | 2a2ab8c329d86a34c32863a8083ce4d2d2e5e506 /newlib/libc | |
parent | c00f9719339d5193c9df2dd384f64374bf3acc03 (diff) | |
download | newlib-27c7566ca4f436cc6184fdaf568dd84ca9c501f1.zip newlib-27c7566ca4f436cc6184fdaf568dd84ca9c501f1.tar.gz newlib-27c7566ca4f436cc6184fdaf568dd84ca9c501f1.tar.bz2 |
2004-04-23 Jeff Johnston <jjohnstn@redhat.com>
* libc/machine/powerpc/vfscanf.c (NNZDIGITS): New define.
(__svfscanf_r): In integer conversions, leave out leading zeroes
which are not part of a base prefix.
Keep track of width truncation to fit into buf, not counting left-out
zeroes against width till the truncation has been compensated for.
This is based on Joern's patch of 04/21 for libc/stdio/vfscanf.c.
Diffstat (limited to 'newlib/libc')
-rw-r--r-- | newlib/libc/machine/powerpc/vfscanf.c | 79 |
1 files changed, 49 insertions, 30 deletions
diff --git a/newlib/libc/machine/powerpc/vfscanf.c b/newlib/libc/machine/powerpc/vfscanf.c index 37d2da7..add1211 100644 --- a/newlib/libc/machine/powerpc/vfscanf.c +++ b/newlib/libc/machine/powerpc/vfscanf.c @@ -153,9 +153,9 @@ extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr)); #define LONG 0x01 /* l: long or double */ #define LONGDBL 0x02 /* L: long double or long long */ #define SHORT 0x04 /* h: short */ -#define SUPPRESS 0x08 /* suppress assignment */ -#define POINTER 0x10 /* weird %p pointer (`fake hex') */ -#define NOSKIP 0x20 /* do not skip blanks */ +#define SUPPRESS 0x10 /* suppress assignment */ +#define POINTER 0x20 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x40 /* do not skip blanks */ /* * The following are used in numeric conversions only: @@ -163,18 +163,19 @@ extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr)); * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. */ -#define SIGNOK 0x40 /* +/- is (still) legal */ -#define NDIGITS 0x80 /* no digits detected */ +#define SIGNOK 0x80 /* +/- is (still) legal */ +#define NDIGITS 0x100 /* no digits detected */ -#define DPTOK 0x100 /* (float) decimal point is still legal */ -#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */ +#define DPTOK 0x200 /* (float) decimal point is still legal */ +#define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */ -#define PFXOK 0x100 /* 0x prefix is (still) legal */ -#define NZDIGITS 0x200 /* no zero digits detected */ +#define PFXOK 0x200 /* 0x prefix is (still) legal */ +#define NZDIGITS 0x400 /* no zero digits detected */ +#define NNZDIGITS 0x800 /* no non-zero digits detected */ -#define VECTOR 0x400 /* v: vector */ -#define FIXEDPOINT 0x800 /* r/R: fixed-point */ -#define SIGNED 0x1000 /* r: signed fixed-point */ +#define VECTOR 0x2000 /* v: vector */ +#define FIXEDPOINT 0x4000 /* r/R: fixed-point */ +#define SIGNED 0x8000 /* r: signed fixed-point */ /* * Conversion types. @@ -798,18 +799,19 @@ __svfscanf_r (rptr, fp, fmt0, ap) continue; case CT_INT: - /* scan an integer as if by strtol/strtoul */ + unsigned int_width_left = 0; int_width = width; #ifdef hardway if (int_width == 0 || int_width > sizeof (buf) - 1) - int_width = sizeof (buf) - 1; #else /* size_t is unsigned, hence this optimisation */ - if (--int_width > sizeof (buf) - 2) - int_width = sizeof (buf) - 2; - int_width++; + if (int_width - 1 > sizeof (buf) - 2) #endif - flags |= SIGNOK | NDIGITS | NZDIGITS; + { + int_width_left = width - (sizeof (buf) - 1); + int_width = sizeof (buf) - 1; + } + flags |= SIGNOK | NDIGITS | NZDIGITS | NNZDIGITS; for (p = buf; int_width; int_width--) { c = *fp->_p; @@ -829,16 +831,25 @@ __svfscanf_r (rptr, fp, fmt0, ap) * will turn it off if we have scanned any nonzero digits). */ case '0': + if (! (flags & NNZDIGITS)) + goto ok; if (base == 0) { base = 8; flags |= PFXOK; } if (flags & NZDIGITS) - flags &= ~(SIGNOK | NZDIGITS | NDIGITS); - else - flags &= ~(SIGNOK | PFXOK | NDIGITS); - goto ok; + { + flags &= ~(SIGNOK | NZDIGITS | NDIGITS); + goto ok; + } + flags &= ~(SIGNOK | PFXOK | NDIGITS); + if (int_width_left) + { + int_width_left--; + int_width++; + } + goto skip; /* 1 through 7 always legal */ case '1': @@ -849,7 +860,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) case '6': case '7': base = basefix[base]; - flags &= ~(SIGNOK | PFXOK | NDIGITS); + flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS); goto ok; /* digits 8 and 9 ok iff decimal or hex */ @@ -858,7 +869,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) base = basefix[base]; if (base <= 8) break; /* not legal here */ - flags &= ~(SIGNOK | PFXOK | NDIGITS); + flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS); goto ok; /* letters ok iff hex */ @@ -877,7 +888,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) /* no need to fix base here */ if (base <= 10) break; /* not legal here */ - flags &= ~(SIGNOK | PFXOK | NDIGITS); + flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS); goto ok; /* sign ok only as first character */ @@ -912,6 +923,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) * c is legal: store it and look at the next. */ *p++ = c; + skip: if (--fp->_r > 0) fp->_p++; else @@ -1004,16 +1016,18 @@ __svfscanf_r (rptr, fp, fmt0, ap) long leading_zeroes = 0; long zeroes, exp_adjust; char *exp_start = NULL; - int fl_width = width; + unsigned fl_width = width; + unsigned width_left = 0; #ifdef hardway if (fl_width == 0 || fl_width > sizeof (buf) - 1) - fl_width = sizeof (buf) - 1; #else /* size_t is unsigned, hence this optimisation */ - if (--fl_width > sizeof (buf) - 2) - fl_width = sizeof (buf) - 2; - fl_width++; + if (fl_width - 1 > sizeof (buf) - 2) #endif + { + width_left = fl_width - (sizeof (buf) - 1); + fl_width = sizeof (buf) - 1; + } flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; zeroes = 0; exp_adjust = 0; @@ -1032,6 +1046,11 @@ __svfscanf_r (rptr, fp, fmt0, ap) { flags &= ~SIGNOK; zeroes++; + if (width_left) + { + width_left--; + fl_width++; + } goto fskip; } /* Fall through. */ |