scanf: allow hex float input per POSIX
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
a648c15309
commit
9c6c2fb0f6
|
@ -182,7 +182,7 @@ static void * get_arg (int, va_list *, int *, void **);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following are used in numeric conversions only:
|
* The following are used in numeric conversions only:
|
||||||
* SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
|
* SIGNOK, NDIGITS, DPTOK, EXPOK and HEXFLT are for floating point;
|
||||||
* SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
|
* SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -191,6 +191,7 @@ static void * get_arg (int, va_list *, int *, void **);
|
||||||
|
|
||||||
#define DPTOK 0x200 /* (float) decimal point is still legal */
|
#define DPTOK 0x200 /* (float) decimal point is still legal */
|
||||||
#define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */
|
#define EXPOK 0x400 /* (float) exponent (e+3, etc) still legal */
|
||||||
|
#define HEXFLT 0x800 /* (float) hex prefix found, expect hex float */
|
||||||
|
|
||||||
#define PFXOK 0x200 /* 0x prefix is (still) legal */
|
#define PFXOK 0x200 /* 0x prefix is (still) legal */
|
||||||
#define NZDIGITS 0x400 /* no zero digits detected */
|
#define NZDIGITS 0x400 /* no zero digits detected */
|
||||||
|
@ -1605,6 +1606,37 @@ __SVFSCANF_R (struct _reent *rptr,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Chars a, e and f have various special meanings apart from
|
||||||
|
their hex value. They are handled separately, see below. */
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
if ((flags & HEXFLT) && nancount + infcount == 0)
|
||||||
|
{
|
||||||
|
flags &= ~(SIGNOK | NDIGITS);
|
||||||
|
goto fok;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
/* Did we have exactly one leading zero yet? */
|
||||||
|
if ((flags & (SIGNOK | NDIGITS | HEXFLT)) == NDIGITS
|
||||||
|
&& zeroes == 1)
|
||||||
|
{
|
||||||
|
flags |= HEXFLT;
|
||||||
|
/* We skipped the first zero, so we have to add
|
||||||
|
it now to the buffer. */
|
||||||
|
*p++ = '0';
|
||||||
|
width--;
|
||||||
|
zeroes = 0;
|
||||||
|
goto fok;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
case '-':
|
case '-':
|
||||||
if (flags & SIGNOK)
|
if (flags & SIGNOK)
|
||||||
|
@ -1636,6 +1668,11 @@ __SVFSCANF_R (struct _reent *rptr,
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'A':
|
case 'A':
|
||||||
|
if ((flags & HEXFLT) && nancount + infcount == 0)
|
||||||
|
{
|
||||||
|
flags &= ~(SIGNOK | NDIGITS);
|
||||||
|
goto fok;
|
||||||
|
}
|
||||||
if (nancount == 1)
|
if (nancount == 1)
|
||||||
{
|
{
|
||||||
nancount = 2;
|
nancount = 2;
|
||||||
|
@ -1660,6 +1697,11 @@ __SVFSCANF_R (struct _reent *rptr,
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'F':
|
case 'F':
|
||||||
|
if ((flags & HEXFLT) && nancount + infcount == 0)
|
||||||
|
{
|
||||||
|
flags &= ~(SIGNOK | NDIGITS);
|
||||||
|
goto fok;
|
||||||
|
}
|
||||||
if (infcount == 2)
|
if (infcount == 2)
|
||||||
{
|
{
|
||||||
infcount = 3;
|
infcount = 3;
|
||||||
|
@ -1682,8 +1724,27 @@ __SVFSCANF_R (struct _reent *rptr,
|
||||||
goto fok;
|
goto fok;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
case 'P':
|
||||||
|
/* p is the exponent marker in hex case. */
|
||||||
|
if (!(flags & HEXFLT))
|
||||||
|
break;
|
||||||
|
goto fexp;
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
|
/* e is just a digit in hex case, not the exponent marker. */
|
||||||
|
if (flags & HEXFLT)
|
||||||
|
{
|
||||||
|
if (nancount + infcount == 0)
|
||||||
|
{
|
||||||
|
flags &= ~(SIGNOK | NDIGITS);
|
||||||
|
goto fok;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fexp:
|
||||||
/* no exponent without some digits */
|
/* no exponent without some digits */
|
||||||
if ((flags & (NDIGITS | EXPOK)) == EXPOK
|
if ((flags & (NDIGITS | EXPOK)) == EXPOK
|
||||||
|| ((flags & EXPOK) && zeroes))
|
|| ((flags & EXPOK) && zeroes))
|
||||||
|
@ -1694,7 +1755,7 @@ __SVFSCANF_R (struct _reent *rptr,
|
||||||
exp_start = p;
|
exp_start = p;
|
||||||
}
|
}
|
||||||
flags =
|
flags =
|
||||||
(flags & ~(EXPOK | DPTOK)) |
|
(flags & ~(EXPOK | DPTOK | HEXFLT)) |
|
||||||
SIGNOK | NDIGITS;
|
SIGNOK | NDIGITS;
|
||||||
zeroes = 0;
|
zeroes = 0;
|
||||||
goto fok;
|
goto fok;
|
||||||
|
|
Loading…
Reference in New Issue