Prepare vfscanf to use __strtof128_internal
authorGabriel F. T. Gomes <gabriel@inconstante.eti.br>
Mon, 11 Jun 2018 01:42:34 +0000 (22:42 -0300)
committerGabriel F. T. Gomes <gabriel@inconstante.eti.br>
Fri, 7 Dec 2018 19:28:26 +0000 (17:28 -0200)
On powerpc64le, long double can currently take two formats: the same as
double (-mlong-double-64) or IBM Extended Precision (default with
-mlong-double-128 or explicitly with -mabi=ibmlongdouble).  The internal
implementation of scanf-like functions is aware of these possibilites
and, based on the format in use, properly calls __strtold_internal or
__strtod_internal, saving the return to a variable of type double or
long double.

When library support for TS 18661-3 was added to glibc, a new function,
__strtof128_internal, was added to enable reading of floating-point
values with IEEE binary128 format into the _Float128 type.  Now that
powerpc64le is getting support for its third long double format, and
taking into account that this format is the same as the format of
_Float128, this patch extends __vfscanf_internal and __vfwscanf_internal
to call __strtof128_internal or __wcstof128_internal when appropriate.
The result gets saved into a variable of _Float128 type.

Tested for powerpc64le.

ChangeLog
libio/libioP.h
stdio-common/vfscanf-internal.c

index 998f4c1..c6ad912 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2018-12-07  Gabriel F. T. Gomes  <gabriel@inconstante.eti.br>
+
+       * libio/libioP.h (SCANF_LDBL_USES_FLOAT128): New macro to be
+       used as a mask for the mode argument of __vfscanf_internal and
+       __vfwscanf_internal.
+       * stdio-common/vfscanf-internal.c
+       [defined COMPILE_WSCANF && __HAVE_FLOAT128_UNLIKE_LDBL]
+       (__strtof128_internal): Define to __wcstof128_internal.
+       [__HAVE_FLOAT128_UNLIKE_LDBL] (__vfscanf_internal): Call
+       __strtof128_internal or __wcstof128_internal when the format of
+       long double is the same as _Float128.
+
 2018-12-05  Samuel Thibault  <samuel.thibault@ens-lyon.org>
 
        * include/unistd.h (__confstr): Add prototype and hidden prototype.
index ce5228e..958ef9b 100644 (file)
@@ -759,9 +759,21 @@ extern off64_t _IO_seekpos_unlocked (FILE *, off64_t, int)
    allocation for input strings with %as, %aS and %a[, a GNU extension,
    is disabled. This is the behavior that the __isoc99_scanf family of
    functions use.  When the flag is set to zero, automatic allocation is
-   enabled.  */
-#define SCANF_LDBL_IS_DBL 0x0001
-#define SCANF_ISOC99_A    0x0002
+   enabled.
+
+   SCANF_LDBL_USES_FLOAT128 is used on platforms where the long double
+   format used to be different from the IEC 60559 double format *and*
+   also different from the Quadruple 128-bits IEC 60559 format (such as
+   the IBM Extended Precision format on powerpc or the 80-bits IEC 60559
+   format on x86), but was later converted to the Quadruple 128-bits IEC
+   60559 format, which is the same format that the _Float128 always has
+   (hence the `USES_FLOAT128' suffix in the name of the flag).  When set
+   to one, this macros indicates that long double values are to be
+   handled as having this new format.  Otherwise, they should be handled
+   as the previous format on that platform.  */
+#define SCANF_LDBL_IS_DBL              0x0001
+#define SCANF_ISOC99_A                 0x0002
+#define SCANF_LDBL_USES_FLOAT128       0x0004
 
 extern int __vfscanf_internal (FILE *fp, const char *format, va_list argp,
                               unsigned int flags)
index 19cfef0..5d00207 100644 (file)
@@ -98,6 +98,9 @@
 # define __strtold_internal    __wcstold_internal
 # define __strtod_internal     __wcstod_internal
 # define __strtof_internal     __wcstof_internal
+# if __HAVE_FLOAT128_UNLIKE_LDBL
+#  define __strtof128_internal __wcstof128_internal
+# endif
 
 # define L_(Str)       L##Str
 # define CHAR_T                wchar_t
@@ -2420,6 +2423,17 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
              done = EOF;
              goto errout;
            }
+#if __HAVE_FLOAT128_UNLIKE_LDBL
+         if ((flags & LONGDBL) \
+              && (mode_flags & SCANF_LDBL_USES_FLOAT128) != 0)
+           {
+             _Float128 d = __strtof128_internal
+               (char_buffer_start (&charbuf), &tw, flags & GROUP);
+             if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf))
+               *ARG (_Float128 *) = d;
+           }
+         else
+#endif
          if ((flags & LONGDBL) \
              && __glibc_likely ((mode_flags & SCANF_LDBL_IS_DBL) == 0))
            {