From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id 97E833851C1B; Mon, 19 Apr 2021 20:03:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 97E833851C1B Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Corinna Vinschen To: newlib-cvs@sourceware.org Subject: [newlib-cygwin] scanf: allow hex float input per POSIX X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/master X-Git-Oldrev: a648c15309544d72d21b1d06eb9d0712a34220ae X-Git-Newrev: 9c6c2fb0f697e70f1d1eacad915ea5f76bb123e6 Message-Id: <20210419200305.97E833851C1B@sourceware.org> Date: Mon, 19 Apr 2021 20:03:05 +0000 (GMT) X-BeenThere: newlib-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Newlib GIT logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Apr 2021 20:03:05 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=9c6c2fb0f697e70f1d1eacad915ea5f76bb123e6 commit 9c6c2fb0f697e70f1d1eacad915ea5f76bb123e6 Author: Corinna Vinschen Date: Mon Apr 19 21:59:56 2021 +0200 scanf: allow hex float input per POSIX Signed-off-by: Corinna Vinschen Diff: --- newlib/libc/stdio/vfscanf.c | 65 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c index 994cee7fc..1d5e6512a 100644 --- a/newlib/libc/stdio/vfscanf.c +++ b/newlib/libc/stdio/vfscanf.c @@ -182,7 +182,7 @@ static void * get_arg (int, va_list *, int *, void **); /* * 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. */ @@ -191,6 +191,7 @@ static void * get_arg (int, va_list *, int *, void **); #define DPTOK 0x200 /* (float) decimal point is 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 NZDIGITS 0x400 /* no zero digits detected */ @@ -1605,6 +1606,37 @@ __SVFSCANF_R (struct _reent *rptr, } 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 '-': if (flags & SIGNOK) @@ -1636,6 +1668,11 @@ __SVFSCANF_R (struct _reent *rptr, break; case 'a': case 'A': + if ((flags & HEXFLT) && nancount + infcount == 0) + { + flags &= ~(SIGNOK | NDIGITS); + goto fok; + } if (nancount == 1) { nancount = 2; @@ -1660,6 +1697,11 @@ __SVFSCANF_R (struct _reent *rptr, break; case 'f': case 'F': + if ((flags & HEXFLT) && nancount + infcount == 0) + { + flags &= ~(SIGNOK | NDIGITS); + goto fok; + } if (infcount == 2) { infcount = 3; @@ -1682,8 +1724,27 @@ __SVFSCANF_R (struct _reent *rptr, goto fok; } break; + + case 'p': + case 'P': + /* p is the exponent marker in hex case. */ + if (!(flags & HEXFLT)) + break; + goto fexp; 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 */ if ((flags & (NDIGITS | EXPOK)) == EXPOK || ((flags & EXPOK) && zeroes)) @@ -1694,7 +1755,7 @@ __SVFSCANF_R (struct _reent *rptr, exp_start = p; } flags = - (flags & ~(EXPOK | DPTOK)) | + (flags & ~(EXPOK | DPTOK | HEXFLT)) | SIGNOK | NDIGITS; zeroes = 0; goto fok;