public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/2] New strfrom functions
@ 2016-08-23 15:44 Gabriel F. T. Gomes
  2016-08-23 15:44 ` [PATCH 2/2] Add tests for " Gabriel F. T. Gomes
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Gabriel F. T. Gomes @ 2016-08-23 15:44 UTC (permalink / raw)
  To: libc-alpha

The following patches add the functions strfromd, strfromf, and strfroml, as
well as their wide character counterparts, wcsfromd, wcsfromf, and wcsfroml.

This is being done in preparation for strfromf128.

Tested on ppc, ppc64, ppc64le, s390, and x86_64.

Gabriel F. T. Gomes (1):
  Add strfrom{d,f,l} and wcsfrom{d,f,l} functions

Rajalakshmi Srinivasaraghavan (1):
  Add tests for strfrom functions

 NEWS                                               |   4 +
 include/stdlib.h                                   |  41 ++++
 include/wchar.h                                    |  41 ++++
 locale/Versions                                    |   4 +
 localedata/Makefile                                |   2 +-
 localedata/tests-mbwc/dat_wcsfrom.c                |  82 +++++++
 localedata/tests-mbwc/tgn_funcdef.h                |   2 +
 localedata/tests-mbwc/tst_types.h                  |  25 +++
 localedata/tests-mbwc/tst_wcsfrom.c                |  75 +++++++
 manual/arith.texi                                  |  72 ++++++
 stdlib/Makefile                                    |  14 +-
 stdlib/Versions                                    |   4 +
 stdlib/bug-strtod.c                                |  10 +-
 stdlib/bug-strtod2.c                               |   2 +-
 stdlib/stdlib.h                                    |  33 +++
 stdlib/strfrom-skeleton.c                          |  60 +++++
 stdlib/strfrom_l-skeleton.c                        | 248 +++++++++++++++++++++
 stdlib/strfromd.c                                  |  29 +++
 stdlib/strfromd_l.c                                |  29 +++
 stdlib/strfromf.c                                  |  29 +++
 stdlib/strfromf_l.c                                |  29 +++
 stdlib/strfroml.c                                  |  29 +++
 stdlib/strfroml_l.c                                |  29 +++
 stdlib/tst-strfrom.c                               | 173 ++++++++++++++
 stdlib/tst-strtod-round-skeleton.c                 |  16 +-
 stdlib/tst-strtod.h                                |   9 +-
 stdlib/tst-strtod6.c                               |   2 +-
 sysdeps/arm/nacl/libc.abilist                      |  12 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |  12 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |  12 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |  12 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |  12 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |  12 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |  12 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |  12 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |  12 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |  12 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |  12 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |  12 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |  12 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |  12 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |  12 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |  12 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |  12 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |  12 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |  12 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |  12 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |  12 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |  12 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |  12 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |  12 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |  12 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |  12 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |  12 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |  12 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |  12 +
 wcsmbs/Makefile                                    |  14 +-
 wcsmbs/Versions                                    |   3 +
 wcsmbs/tst-wcsfrom.c                               |  30 +++
 wcsmbs/wchar.h                                     |  23 ++
 wcsmbs/wcsfromd.c                                  |  25 +++
 wcsmbs/wcsfromd_l.c                                |  25 +++
 wcsmbs/wcsfromf.c                                  |  25 +++
 wcsmbs/wcsfromf_l.c                                |  25 +++
 wcsmbs/wcsfroml.c                                  |  25 +++
 wcsmbs/wcsfroml_l.c                                |  25 +++
 66 files changed, 1640 insertions(+), 21 deletions(-)
 create mode 100644 localedata/tests-mbwc/dat_wcsfrom.c
 create mode 100644 localedata/tests-mbwc/tst_wcsfrom.c
 create mode 100644 stdlib/strfrom-skeleton.c
 create mode 100644 stdlib/strfrom_l-skeleton.c
 create mode 100644 stdlib/strfromd.c
 create mode 100644 stdlib/strfromd_l.c
 create mode 100644 stdlib/strfromf.c
 create mode 100644 stdlib/strfromf_l.c
 create mode 100644 stdlib/strfroml.c
 create mode 100644 stdlib/strfroml_l.c
 create mode 100644 stdlib/tst-strfrom.c
 create mode 100644 wcsmbs/tst-wcsfrom.c
 create mode 100644 wcsmbs/wcsfromd.c
 create mode 100644 wcsmbs/wcsfromd_l.c
 create mode 100644 wcsmbs/wcsfromf.c
 create mode 100644 wcsmbs/wcsfromf_l.c
 create mode 100644 wcsmbs/wcsfroml.c
 create mode 100644 wcsmbs/wcsfroml_l.c

-- 
2.4.11

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/2] Add strfrom{d,f,l} and wcsfrom{d,f,l} functions
  2016-08-23 15:44 [PATCH 0/2] New strfrom functions Gabriel F. T. Gomes
  2016-08-23 15:44 ` [PATCH 2/2] Add tests for " Gabriel F. T. Gomes
@ 2016-08-23 15:44 ` Gabriel F. T. Gomes
  2016-08-23 17:21   ` Joseph Myers
  2016-08-23 17:58 ` [PATCH 0/2] New strfrom functions Joseph Myers
  2016-08-25 11:41 ` Florian Weimer
  3 siblings, 1 reply; 14+ messages in thread
From: Gabriel F. T. Gomes @ 2016-08-23 15:44 UTC (permalink / raw)
  To: libc-alpha

ISO/IEC TS 18661-1 adds several functions in the strfrom family to stdlib.
This patch adds strfromd, strfromf, and strfroml, as well as their wide
character counterparts (wcsfromd, wcsfromf, and wcsfroml).  This is being done
in preparation for the new floating-point type, float128.  The added functions
convert a floating-point value into a string, with configurable format.

2016-06-23  Gabriel F. T. Gomes  <gftg@linux.vnet.ibm.com>

	* NEWS: Mention the addition of strfromd, strfromf, and strfroml.
	* manual/arith.texi: Document strfromd, strfromf, strfroml, wcsfromd,
	wcsfromf, and wcsfroml.
	* include/stdlib.h (__strfromd_l): New hidden declaration.
	(__strfromf_l): Likewise.
	(__strfroml_l): Likewise.
	(__strfromd_internal): Likewise.
	(__strfromf_internal): Likewise.
	(__strfroml_internal): Likewise.
	* include/wchar.h (____wcsfromd_l_internal): New hidden declaration.
	(____wcsfromf_l_internal): Likewise.
	(____wcsfroml_l_internal): Likewise.
	(__wcsfromd_internal): Likewise.
	(__wcsfromf_internal): Likewise.
	(__wcsfroml_internal): Likewise.
	(wcsfromd): Set to hidden.
	(wcsfromf): Likewise.
	(wcsfroml): Likewise.
	* locale/Versions (GLIBC_2.25): Add entries for strfromd_l, strfromf_l,
	strfroml_l, wcsfromd_l, wcsfromf_, and wcsfroml_l.
	* stdlib/Makefile: Add strfromd, strfromf, strfroml, strfromd_l,
	strfromf_l, and strfroml_l build rules and flags.
	* stdlib/Versions (GLIBC_2.25): Add entries for strfromd, strfromf,
	and strfroml.
	* stdlib/stdlib.h (strfromd): New declaration.
	(strfromf): Likewise.
	(strfroml): Likewise.
	(strfromd_l): Likewise.
	(strfromf_l): Likewise.
	(strfroml_l): Likewise.
	* stdlib/strfrom-skeleton.c: New file.  Generic implementation for
	strfrom.
	* stdlib/strfrom_l-skeleton.c: Likewise.
	* stdlib/strfromd.c: New file.
	* stdlib/strfromf.c: Likewise.
	* stdlib/strfroml.c: Likewise.
	* stdlib/strfromd_l.c: Likewise.
	* stdlib/strfromf_l.c: Likewise.
	* stdlib/strfroml_l.c: Likewise.
	* stdlib/strfrom_defaults.h: Likewise.
	* sysdeps/arm/nacl/libc.abilist: Update.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
	* wcsmbs/Makefile: Add wcsfromd, wcsfromf, wcsfroml, wcsfromd_l,
	wcsfromf_l, and wcsfroml_l build rules and flags.
	* wcsmbs/Versions (GLIBC_2.25): Add entries for wcsfromd, wcsfromf,
	and wcsfroml.
	* wcsmbs/wchar.h (wcsfromd): New declaration.
	(wcsfromf): Likewise.
	(wcsfroml): Likewise.
	(wcsfromd_l): Likewise.
	(wcsfromf_l): Likewise.
	(wcsfroml_l): Likewise.
	* wcsmbs/wcsfromd.c: New file.
	* wcsmbs/wcsfromd_l.c: Likewise.
	* wcsmbs/wcsfromf.c: Likewise.
	* wcsmbs/wcsfromf_l.c: Likewise.
	* wcsmbs/wcsfroml.c: Likewise.
	* wcsmbs/wcsfroml_l.c: Likewise.
---
 NEWS                                               |   4 +
 include/stdlib.h                                   |  41 ++++
 include/wchar.h                                    |  41 ++++
 locale/Versions                                    |   4 +
 manual/arith.texi                                  |  72 ++++++
 stdlib/Makefile                                    |  11 +
 stdlib/Versions                                    |   4 +
 stdlib/stdlib.h                                    |  33 +++
 stdlib/strfrom-skeleton.c                          |  60 +++++
 stdlib/strfrom_l-skeleton.c                        | 248 +++++++++++++++++++++
 stdlib/strfromd.c                                  |  29 +++
 stdlib/strfromd_l.c                                |  29 +++
 stdlib/strfromf.c                                  |  29 +++
 stdlib/strfromf_l.c                                |  29 +++
 stdlib/strfroml.c                                  |  29 +++
 stdlib/strfroml_l.c                                |  29 +++
 sysdeps/arm/nacl/libc.abilist                      |  12 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |  12 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |  12 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |  12 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |  12 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |  12 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |  12 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |  12 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |  12 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |  12 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |  12 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |  12 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |  12 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |  12 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |  12 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |  12 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |  12 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |  12 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |  12 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |  12 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |  12 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |  12 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |  12 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |  12 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |  12 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |  12 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |  12 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |  12 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |  12 +
 wcsmbs/Makefile                                    |  11 +
 wcsmbs/Versions                                    |   3 +
 wcsmbs/wchar.h                                     |  23 ++
 wcsmbs/wcsfromd.c                                  |  25 +++
 wcsmbs/wcsfromd_l.c                                |  25 +++
 wcsmbs/wcsfromf.c                                  |  25 +++
 wcsmbs/wcsfromf_l.c                                |  25 +++
 wcsmbs/wcsfroml.c                                  |  25 +++
 wcsmbs/wcsfroml_l.c                                |  25 +++
 54 files changed, 1227 insertions(+)
 create mode 100644 stdlib/strfrom-skeleton.c
 create mode 100644 stdlib/strfrom_l-skeleton.c
 create mode 100644 stdlib/strfromd.c
 create mode 100644 stdlib/strfromd_l.c
 create mode 100644 stdlib/strfromf.c
 create mode 100644 stdlib/strfromf_l.c
 create mode 100644 stdlib/strfroml.c
 create mode 100644 stdlib/strfroml_l.c
 create mode 100644 wcsmbs/wcsfromd.c
 create mode 100644 wcsmbs/wcsfromd_l.c
 create mode 100644 wcsmbs/wcsfromf.c
 create mode 100644 wcsmbs/wcsfromf_l.c
 create mode 100644 wcsmbs/wcsfroml.c
 create mode 100644 wcsmbs/wcsfroml_l.c

diff --git a/NEWS b/NEWS
index fdcd7e7..bf5a307 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,10 @@ using `glibc' in the "product" field.
 \f
 Version 2.25
 
+* The functions strfromd, strfromf, and strfroml, as well as their
+  wide-character counterparts are present in libc.  These functions are defined
+  in ISO/IEC TS 18661-1:2014 and convert a floating-point number into string.
+
 * The feature test macro __STDC_WANT_LIB_EXT2__, from ISO/IEC TR
   24731-2:2010, is supported to enable declarations of functions from that
   TR.  Note that not all functions from that TR are supported by the GNU C
diff --git a/include/stdlib.h b/include/stdlib.h
index 352339e..973a5da 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -30,6 +30,13 @@ libc_hidden_proto (__strtod_l)
 libc_hidden_proto (__strtof_l)
 libc_hidden_proto (__strtold_l)
 
+extern __typeof (strfromd_l) __strfromd_l;
+extern __typeof (strfromf_l) __strfromf_l;
+extern __typeof (strfroml_l) __strfroml_l;
+libc_hidden_proto (__strfromd_l);
+libc_hidden_proto (__strfromf_l);
+libc_hidden_proto (__strfroml_l);
+
 libc_hidden_proto (exit)
 libc_hidden_proto (abort)
 libc_hidden_proto (getenv)
@@ -203,6 +210,40 @@ libc_hidden_proto (strtoll)
 libc_hidden_proto (strtoul)
 libc_hidden_proto (strtoull)
 
+
+extern int __strfromf_internal (char * __dest, size_t __size,
+				const char * __format, float __f, int __group)
+     __THROW __nonnull ((3));
+extern int __strfromd_internal (char * __dest, size_t __size,
+				const char * __format, double __f, int __group)
+     __THROW __nonnull ((3));
+extern int __strfroml_internal (char * __dest, size_t __size,
+				const char * __format, long double __f,
+				int __group)
+     __THROW __nonnull ((3));
+
+libc_hidden_proto (__strfromf_internal)
+libc_hidden_proto (__strfromd_internal)
+libc_hidden_proto (__strfroml_internal)
+
+extern int ____strfromf_l_internal (char * __dest, size_t __size,
+				    const char * __format, float __f,
+				    int __group, __locale_t __loc);
+extern int ____strfromd_l_internal (char * __dest, size_t __size,
+				    const char * __format, double __f,
+				    int __group, __locale_t __loc);
+extern int ____strfroml_l_internal (char * __dest, size_t __size,
+				    const char * __format, long double __f,
+				    int __group, __locale_t __loc);
+
+libc_hidden_proto (____strfromf_l_internal)
+libc_hidden_proto (____strfromd_l_internal)
+libc_hidden_proto (____strfroml_l_internal)
+
+libc_hidden_proto (strfromf)
+libc_hidden_proto (strfromd)
+libc_hidden_proto (strfroml)
+
 extern float __strtof_nan (const char *, char **, char) internal_function;
 extern double __strtod_nan (const char *, char **, char) internal_function;
 extern long double __strtold_nan (const char *, char **, char)
diff --git a/include/wchar.h b/include/wchar.h
index 6272130..b700f1a 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -70,6 +70,46 @@ libc_hidden_proto (wcstoll)
 libc_hidden_proto (wcstoul)
 libc_hidden_proto (wcstoull)
 
+extern __typeof (wcsfromd_l) __wcsfromd_l;
+extern __typeof (wcsfromf_l) __wcsfromf_l;
+extern __typeof (wcsfroml_l) __wcsfroml_l;
+libc_hidden_proto (__wcsfromd_l)
+libc_hidden_proto (__wcsfromf_l)
+libc_hidden_proto (__wcsfroml_l)
+
+extern int __wcsfromf_internal (wchar_t *__restrict __dest, size_t __size,
+				const char * __format, float __f, int __group)
+     __THROW;
+extern int __wcsfromd_internal (wchar_t *__restrict __dest, size_t __size,
+				const char * __format, double __f, int __group)
+     __THROW;
+extern int __wcsfroml_internal (wchar_t *__restrict __dest, size_t __size,
+				const char * __format, long double __f,
+				int __group)
+     __THROW;
+
+libc_hidden_proto (__wcsfromf_internal)
+libc_hidden_proto (__wcsfromd_internal)
+libc_hidden_proto (__wcsfroml_internal)
+
+extern int ____wcsfromf_l_internal (wchar_t * __dest, size_t __size,
+				    const char * __format, float __f,
+				    int __group, __locale_t __loc);
+extern int ____wcsfromd_l_internal (wchar_t * __dest, size_t __size,
+				    const char * __format, double __f,
+				    int __group, __locale_t __loc);
+extern int ____wcsfroml_l_internal (wchar_t * __dest, size_t __size,
+				    const char * __format, long double __f,
+				    int __group, __locale_t __loc);
+
+libc_hidden_proto (____wcsfromf_l_internal)
+libc_hidden_proto (____wcsfromd_l_internal)
+libc_hidden_proto (____wcsfroml_l_internal)
+
+libc_hidden_proto (wcsfromf)
+libc_hidden_proto (wcsfromd)
+libc_hidden_proto (wcsfroml)
+
 libc_hidden_proto (__wcscasecmp_l)
 libc_hidden_proto (__wcsncasecmp_l)
 
@@ -172,6 +212,7 @@ extern int __vfwprintf (__FILE *__restrict __s,
 			const wchar_t *__restrict __format,
 			__gnuc_va_list __arg)
      /* __attribute__ ((__format__ (__wprintf__, 2, 0))) */;
+extern int __swprintf (wchar_t *s, size_t n, const wchar_t *format, ...);
 #ifndef __cplusplus
 extern int __vfwprintf_chk (FILE *__restrict __s, int __flag,
 			    const wchar_t *__restrict __format,
diff --git a/locale/Versions b/locale/Versions
index 7211934..42b7df4 100644
--- a/locale/Versions
+++ b/locale/Versions
@@ -66,6 +66,10 @@ libc {
     wcstoll_l; wcstoul_l; wcstoull_l; wcsxfrm_l; wctype_l;
     wctrans_l; nl_langinfo_l;
   }
+  GLIBC_2.25 {
+    strfromd_l; strfromf_l; strfroml_l;
+    wcsfromd_l; wcsfromf_l; wcsfroml_l;
+  }
   GLIBC_PRIVATE {
     # global variables
     __collate_element_hash; __collate_element_strings;
diff --git a/manual/arith.texi b/manual/arith.texi
index 8dcd409..39c5e44 100644
--- a/manual/arith.texi
+++ b/manual/arith.texi
@@ -20,6 +20,7 @@ These functions are declared in the header files @file{math.h} and
 * Complex Numbers::             The types.  Writing complex constants.
 * Operations on Complex::       Projection, conjugation, decomposition.
 * Parsing of Numbers::          Converting strings to numbers.
+* Printing of Floats::          Converting floating-point numbers to strings.
 * System V Number Conversion::  An archaic way to convert numbers to strings.
 @end menu
 
@@ -2652,6 +2653,77 @@ is provided mostly for compatibility with existing code; using
 @code{strtod} is more robust.
 @end deftypefun
 
+@node Printing of Floats
+@section Printing of Floats
+
+@pindex stdlib.h
+@pindex wchar.h
+The @samp{str} functions are declared in @file{stdlib.h} and those
+beginning with @samp{wcs} are declared in @file{wchar.h}.
+
+@comment stdlib.h
+@comment ISO/IEC TS 18661-1
+@deftypefun int strfromd (char *restrict @var{string}, size_t @var{size}, const char *restrict @var{format}, double @var{value})
+@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
+@comment strfromd depends on __printf_fp and __printf_fphex, which are
+@comment AS-unsafe (ascuheap) and AC-unsafe (acsmem).
+The @code{strfromd} (``string-from-double'') function converts the
+floating-point number in @var{value} to a string of characters and stores
+them into the area pointed to by @var{string}.  The conversion writes at
+most @var{size} characters and respects the format specified by
+@var{format}.
+
+The @var{format} string must start with the character @samp{%}.  An
+optional precision follows, which starts with a period ,@samp{.}, and may
+be followed by a decimal integer, representing the precision.  If a decimal
+integer is not specified after the period, the precision is taken to be
+zero.  The character @samp{*} is not allowed.  Finally, the @var{format}
+string ends with one of the following conversion specifiers: @samp{a},
+@samp{A}, @samp{e}, @samp{E}, @samp{f}, @samp{F}, @samp{g}, @samp{G}.  The
+meaning of each conversion specifier is described at @ref{Table of Output
+Conversions}.
+
+The return of this function is the number of characters that would have been
+written to @var{string} had @var{size} been sufficiently large, not
+counting the terminating null character.  Thus, the null-terminated output
+has been completely written if and only if the returned value is less than
+@var{size}.
+@end deftypefun
+
+@comment stdlib.h
+@comment ISO/IEC TS 18661-1
+@deftypefun int strfromf (char *restrict @var{string}, size_t @var{size}, const char *restrict @var{format}, float @var{value})
+@comment stdlib.h
+@comment ISO/IEC TS 18661-1
+@deftypefunx int strfroml (char *restrict @var{string}, size_t @var{size}, const char *restrict @var{format}, long double @var{value})
+@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
+These functions are analogous to @code{strfromd}, but accept @code{float},
+and @code{long double}, respectively, as the last argument.
+
+These functions have been introduced by ISO/IEC TS 18661-1.
+
+@comment wchar.h
+@comment ISO/IEC TS 18661-1
+@deftypefun int wcsfromd (wchar_t *restrict @var{string}, size_t @var{size}, const char *restrict @var{format}, double @var{value})
+@comment wchar.h
+@comment ISO/IEC TS 18661-1
+@deftypefun int wcsfromf (wchar_t *restrict @var{string}, size_t @var{size}, const char *restrict @var{format}, float @var{value})
+@comment wchar.h
+@comment ISO/IEC TS 18661-1
+@deftypefun int wcsfroml (wchar_t *restrict @var{string}, size_t @var{size}, const char *restrict @var{format}, long double @var{value})
+@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
+These functions are analogous to @code{strfromd}, @code{strfromf}, and
+@code{strfroml}, respectively, but print to wide character strings
+(@code{wchar_t *}), instead of to regular character strings (@code{char *}).
+
+These functions return the number of characters that have been written to
+@var{string} if @var{size} was large enough and no encoding errors have
+occurred.  Otherwise, they return a negative number.
+
+These functions are GNU extensions.
+
+@end deftypefun
+
 @Theglibc{} also provides @samp{_l} versions of these functions,
 which take an additional argument, the locale to use in conversion.
 
diff --git a/stdlib/Makefile b/stdlib/Makefile
index fc6f23d..67969aa 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -46,6 +46,8 @@ routines	:=							      \
 	drand48_r erand48_r lrand48_r nrand48_r mrand48_r jrand48_r	      \
 	srand48_r seed48_r lcong48_r					      \
 	drand48-iter							      \
+	strfromf strfromd strfroml					      \
+	strfromf_l strfromd_l strfroml_l				      \
 	strtol strtoul strtoll strtoull					      \
 	strtol_l strtoul_l strtoll_l strtoull_l				      \
 	strtof strtod strtold						      \
@@ -121,6 +123,15 @@ CFLAGS-fmtmsg.c = -fexceptions
 CFLAGS-strfmon.c = $(libio-mtsafe)
 CFLAGS-strfmon_l.c = $(libio-mtsafe)
 
+# The strfrom class of functions call __printf_fp in order to convert the
+# floating-point value to characters.  This requires the value of IO_MTSAFE_IO.
+CFLAGS-strfromd.c = $(libio-mtsafe)
+CFLAGS-strfromd_l.c = $(libio-mtsafe)
+CFLAGS-strfromf.c = $(libio-mtsafe)
+CFLAGS-strfromf_l.c = $(libio-mtsafe)
+CFLAGS-strfroml.c = $(libio-mtsafe)
+CFLAGS-strfroml_l.c = $(libio-mtsafe)
+
 CFLAGS-tst-bsearch.c = $(stack-align-test-flags)
 CFLAGS-tst-qsort.c = $(stack-align-test-flags)
 CFLAGS-tst-makecontext.c += -funwind-tables
diff --git a/stdlib/Versions b/stdlib/Versions
index 9c06b43..54416b7 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -112,6 +112,10 @@ libc {
   GLIBC_2.24 {
     quick_exit;
   }
+  GLIBC_2.25 {
+    # s*
+    strfromd; strfromf; strfroml;
+  }
   GLIBC_PRIVATE {
     # functions which have an additional interface since they are
     # are cancelable.
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index f0dc951..399e3b2 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -21,6 +21,9 @@
 
 #ifndef	_STDLIB_H
 
+#define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION
+#include <bits/libc-header-start.h>
+
 #include <features.h>
 
 /* Get size_t, wchar_t and NULL from <stddef.h>.  */
@@ -125,6 +128,12 @@ __BEGIN_NAMESPACE_STD
 extern double strtod (const char *__restrict __nptr,
 		      char **__restrict __endptr)
      __THROW __nonnull ((1));
+/* Convert a floating-point number to a string.  */
+#if __GLIBC_USE (IEC_60559_BFP_EXT)
+extern int strfromd (char * __dest, size_t __size, const char * __format,
+		     double __f)
+     __THROW __nonnull ((3));
+#endif
 __END_NAMESPACE_STD
 
 #ifdef	__USE_ISOC99
@@ -136,6 +145,16 @@ extern float strtof (const char *__restrict __nptr,
 extern long double strtold (const char *__restrict __nptr,
 			    char **__restrict __endptr)
      __THROW __nonnull ((1));
+
+#if __GLIBC_USE (IEC_60559_BFP_EXT)
+extern int strfromf (char * __dest, size_t __size, const char * __format,
+		     float __f)
+     __THROW __nonnull ((3));
+
+extern int strfroml (char * __dest, size_t __size, const char * __format,
+		     long double __f)
+     __THROW __nonnull ((3));
+#endif
 __END_NAMESPACE_C99
 #endif
 
@@ -230,6 +249,20 @@ extern long double strtold_l (const char *__restrict __nptr,
 			      char **__restrict __endptr,
 			      __locale_t __loc)
      __THROW __nonnull ((1, 3));
+
+# if __GLIBC_USE (IEC_60559_BFP_EXT)
+extern int strfromd_l (char * __dest, size_t __size, const char * __format,
+		       double __f, __locale_t __loc)
+     __THROW __nonnull ((3));
+
+extern int strfromf_l (char * __dest, size_t __size, const char * __format,
+		       float __f, __locale_t __loc)
+     __THROW __nonnull ((3));
+
+extern int strfroml_l (char * __dest, size_t __size, const char * __format,
+		       long double __f, __locale_t __loc)
+     __THROW __nonnull ((3));
+# endif
 #endif /* GNU */
 
 
diff --git a/stdlib/strfrom-skeleton.c b/stdlib/strfrom-skeleton.c
new file mode 100644
index 0000000..c3c8a4d
--- /dev/null
+++ b/stdlib/strfrom-skeleton.c
@@ -0,0 +1,60 @@
+/* Generic implementation for strfrom functions.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <wchar.h>
+#include <locale/localeinfo.h>
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define STRING_TYPE wchar_t
+#else
+# define STRING_TYPE char
+#endif
+
+#define INTERNAL(x) INTERNAL1(x)
+#define INTERNAL1(x) __##x##_internal
+
+
+/* Prototype for the internal implementation.  */
+#include <xlocale.h>
+extern int INTERNAL (STRFROMF_L) (
+	STRING_TYPE *, size_t, const char *, FLOAT, int, __locale_t);
+
+int
+INTERNAL (STRFROMF) (STRING_TYPE *dest, size_t size, const char * format,
+		     FLOAT f, int group)
+{
+  return INTERNAL(STRFROMF_L) (dest, size, format, f, group, _NL_CURRENT_LOCALE);
+}
+#if defined _LIBC
+libc_hidden_def (INTERNAL (STRFROMF))
+#endif
+
+
+int
+#ifdef weak_function
+weak_function
+#endif
+STRFROMF (STRING_TYPE *dest, size_t size, const char * format, FLOAT f)
+{
+  return INTERNAL(STRFROMF_L) (dest, size, format, f, 0, _NL_CURRENT_LOCALE);
+}
+#if defined _LIBC
+libc_hidden_def (STRFROMF)
+#endif
diff --git a/stdlib/strfrom_l-skeleton.c b/stdlib/strfrom_l-skeleton.c
new file mode 100644
index 0000000..8fb55d5
--- /dev/null
+++ b/stdlib/strfrom_l-skeleton.c
@@ -0,0 +1,248 @@
+/* Convert a floating-point number to string.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Generic implementation for strfrom functions.  The implementation is generic
+   for several floating-point types (e.g.: float, double), and for char type
+   (i.e.: char or wchar_t), so that each function, such as strfromf and
+   wcsfroml, share the same code, thus avoiding code duplication.  */
+
+#if defined _LIBC || defined HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define STRING_TYPE wchar_t
+#else
+# define STRING_TYPE char
+#endif
+
+#define INTERNAL(x) INTERNAL1(x)
+#define INTERNAL1(x) __##x##_internal
+#ifndef ____STRFROMF_INTERNAL
+# define ____STRFROMF_INTERNAL INTERNAL (__STRFROMF)
+#endif
+
+#include <ctype.h>
+#include "../libio/libioP.h"
+#include "../libio/strfile.h"
+#include <stdio.h>
+#include <printf.h>
+#include <string.h>
+
+
+#define to_digit(Ch) ((Ch) - '0')
+
+int
+____STRFROMF_INTERNAL (STRING_TYPE *dest, size_t size, const char * format,
+		       FLOAT f, int group, __locale_t loc)
+{
+#ifdef USE_WIDE_CHAR
+  _IO_wstrnfile sfile;
+  struct _IO_wide_data wd;
+#else
+  _IO_strnfile sfile;
+#endif
+
+#ifdef _IO_MTSAFE_IO
+  sfile.f._sbf._f._lock = NULL;
+#endif
+
+  int done;
+
+  /* Single-precision values need to be stored in a double type, because
+     __printf_fp_l and __printf_fphex do not accept the float type.  */
+  union {
+    double flt;
+    FLOAT value;
+  } fpnum;
+  const void *fpptr;
+  fpptr = &fpnum;
+
+  /* Variables to control the output format.  Default format is ±x.yyyyyy.  */
+  int precision = -1;
+  int specifier = 'f';
+  struct printf_info info;
+
+  /* Single-precision values need to be converted into double-precision,
+     because __printf_fp and __printf_fphex only accept double and long double
+     as the floating-point argument.  */
+  if (__builtin_types_compatible_p (FLOAT, float))
+    fpnum.flt = f;
+  else
+    fpnum.value = f;
+
+  /* Check if the format string is not null, even though TS-18661-1 does not
+     mention that the format string cannot be null.  */
+  if (format == NULL)
+    {
+      MAYBE_SET_EINVAL;
+      return -1;
+    }
+  /* Check if the first character in the format string is indeed the '%'
+     character.  Otherwise, proceed with the default format.  */
+  if (*format == '%')
+    format++;
+  else
+    goto skip_format;
+
+  /* The optional precision specification always starts with a '.'.  If such
+     character is present, read the precision.  */
+  if (*format == '.')
+    {
+      format++;
+
+      /* According to ISO/IEC 9899:201x, Section 7.21.6.1, 5th paragraph, a
+	 negative precision is taken as if the precision were omitted.  Thus,
+	 parse a potential minus sign.  If the minus sign is present, ignore
+	 the following precision digits.  */
+      if (*format == '-')
+	{
+	  format++;
+	  while (isdigit (*format))
+	    format++;
+	}
+      /* Otherwise, parse the precision.  */
+      else if (isdigit (*format))
+	{
+	  precision = 0;
+	  while (isdigit (*format))
+	    {
+	      precision *= 10;
+	      precision += to_digit(*format);
+	      format++;
+	    }
+	}
+      /* If only the period is specified, the precision is taken as zero, as
+	 described in ISO/IEC 9899:201x, section 7.21.6.1, 4th paragraph, 3rd
+	 item.  */
+      else
+	{
+	  precision = 0;
+	}
+    }
+
+  /* Now there is only the conversion specifier to be read.  */
+  switch (*format)
+    {
+    case 'a':
+    case 'A':
+    case 'e':
+    case 'E':
+    case 'f':
+    case 'F':
+    case 'g':
+    case 'G':
+      specifier = *format;
+      break;
+    default:
+      specifier = 'f';
+      break;
+    }
+
+skip_format:
+
+  /* The following code to prepare the virtual file has been adapted from the
+     functions _IO_vsnprintf and _IO_vswprintf from libio.  */
+
+  if (size == 0)
+    {
+#ifdef USE_WIDE_CHAR
+    /* ISO/IEC 9899:201x, Section 7.29.2.3, in the third paragraph, specifies
+       that swprintf returns a negative value if n or more characters would
+       have been written.  Thus, if size (n) is zero, return a negative number,
+       so that wcsfrom functions behave similar to swprintf.  */
+      return -1;
+#else
+    /* When size is zero, nothing is written and dest may be a null pointer.
+       This is specified for snprintf in ISO/IEC 9899:201x, Section 7.21.6.5,
+       in the second paragraph.  Thus, if size is zero, prepare to use the
+       overflow buffer right from the start.  */
+      dest = sfile.overflow_buf;
+      size = sizeof (sfile.overflow_buf);
+#endif
+    }
+
+  /* Prepare the virtual string file.  */
+#ifdef USE_WIDE_CHAR
+  _IO_no_init (&sfile.f._sbf._f, _IO_USER_LOCK, 0, &wd, &_IO_wstrn_jumps);
+  _IO_fwide (&sfile.f._sbf._f, 1);
+  _IO_wstr_init_static (&sfile.f._sbf._f, dest, size - 1, dest);
+#else
+  _IO_no_init (&sfile.f._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
+  _IO_JUMPS (&sfile.f._sbf) = &_IO_strn_jumps;
+  _IO_str_init_static_internal (&sfile.f, dest, size - 1, dest);
+#endif
+
+  /* Prepare the format specification for printf_fp.  */
+  memset (&info, '\0', sizeof (info));
+
+  /* Grouping has been received as a parameter.  */
+  info.group = group;
+
+  /* The functions strfromd and strfromf pass a floating-point number with
+     double precision to printf_fp, whereas strfroml passes a floating-point
+     number with long double precision.  The following line informs printf_fp
+     which type of floating-point number is being passed.  */
+  info.is_long_double = __builtin_types_compatible_p (FLOAT, long double);
+
+  /* Set info according to the format string.  */
+  info.prec = precision;
+  info.spec = specifier;
+  info.wide = sizeof (STRING_TYPE) != 1;
+
+  if (info.spec != 'a' && info.spec != 'A')
+      done = __printf_fp_l (&sfile.f._sbf._f, loc, &info, &fpptr);
+  else
+      done = __printf_fphex (&sfile.f._sbf._f, &info, &fpptr);
+
+  /* Terminate the string.  */
+#ifdef USE_WIDE_CHAR
+  if (sfile.f._sbf._f._wide_data->_IO_buf_base == sfile.overflow_buf)
+    /* ISO C99 requires swprintf to return an error if the output does not fit
+       in the provided buffer.  The wcsfrom functions mimic this behavior.  */
+    return -1;
+  *sfile.f._sbf._f._wide_data->_IO_write_ptr = L'\0';
+#else
+  if (sfile.f._sbf._f._IO_buf_base != sfile.overflow_buf)
+    *sfile.f._sbf._f._IO_write_ptr = '\0';
+#endif
+
+  return done;
+}
+#if defined _LIBC && !defined USE_WIDE_CHAR
+libc_hidden_def (____STRFROMF_INTERNAL)
+#endif
+
+/* External user entry point.  */
+
+int
+#ifdef weak_function
+weak_function
+#endif
+__STRFROMF (STRING_TYPE * dest, size_t size, const char * format, FLOAT f,
+	    __locale_t loc)
+{
+  return ____STRFROMF_INTERNAL (dest, size, format, f, 0, loc);
+}
+#if defined _LIBC
+libc_hidden_def (__STRFROMF)
+libc_hidden_ver (__STRFROMF, STRFROMF)
+#endif
+weak_alias (__STRFROMF, STRFROMF)
diff --git a/stdlib/strfromd.c b/stdlib/strfromd.c
new file mode 100644
index 0000000..cebe9d5
--- /dev/null
+++ b/stdlib/strfromd.c
@@ -0,0 +1,29 @@
+/* Definitions for strfromd.  Implementation in stdlib/strfrom-skeleton.c.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define	FLOAT		double
+#define	FLT		DBL
+#ifdef USE_WIDE_CHAR
+#define STRFROMF	wcsfromd
+#define STRFROMF_L	__wcsfromd_l
+#else
+# define STRFROMF	strfromd
+# define STRFROMF_L	__strfromd_l
+#endif
+
+#include "strfrom-skeleton.c"
diff --git a/stdlib/strfromd_l.c b/stdlib/strfromd_l.c
new file mode 100644
index 0000000..c927d31
--- /dev/null
+++ b/stdlib/strfromd_l.c
@@ -0,0 +1,29 @@
+/* Definitions for strfromd_l.  Implementation in stdlib/strfrom-skeleton_l.c.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define FLOAT			double
+#ifdef USE_WIDE_CHAR
+# define STRFROMF		wcsfromd_l
+# define __STRFROMF		__wcsfromd_l
+#else
+# define STRFROMF		strfromd_l
+# define __STRFROMF		__strfromd_l
+#endif
+
+#include "strfrom_l-skeleton.c"
diff --git a/stdlib/strfromf.c b/stdlib/strfromf.c
new file mode 100644
index 0000000..bebdaab
--- /dev/null
+++ b/stdlib/strfromf.c
@@ -0,0 +1,29 @@
+/* Definitions for strfromf.  Implementation in stdlib/strfrom-skeleton.c.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define	FLOAT		float
+#define	FLT		FLT
+#ifdef USE_WIDE_CHAR
+#define STRFROMF	wcsfromf
+#define STRFROMF_L	__wcsfromf_l
+#else
+# define STRFROMF	strfromf
+# define STRFROMF_L	__strfromf_l
+#endif
+
+#include "strfrom-skeleton.c"
diff --git a/stdlib/strfromf_l.c b/stdlib/strfromf_l.c
new file mode 100644
index 0000000..a935916
--- /dev/null
+++ b/stdlib/strfromf_l.c
@@ -0,0 +1,29 @@
+/* Definitions for strfromf_l.  Implementation in stdlib/strfrom-skeleton_l.c.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define FLOAT			float
+#ifdef USE_WIDE_CHAR
+# define STRFROMF		wcsfromf_l
+# define __STRFROMF		__wcsfromf_l
+#else
+# define STRFROMF		strfromf_l
+# define __STRFROMF		__strfromf_l
+#endif
+
+#include "strfrom_l-skeleton.c"
diff --git a/stdlib/strfroml.c b/stdlib/strfroml.c
new file mode 100644
index 0000000..1685341
--- /dev/null
+++ b/stdlib/strfroml.c
@@ -0,0 +1,29 @@
+/* Definitions for strfroml.  Implementation in stdlib/strfrom-skeleton.c.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define	FLOAT		long double
+#define	FLT		LDBL
+#ifdef USE_WIDE_CHAR
+#define STRFROMF	wcsfroml
+#define STRFROMF_L	__wcsfroml_l
+#else
+# define STRFROMF	strfroml
+# define STRFROMF_L	__strfroml_l
+#endif
+
+#include "strfrom-skeleton.c"
diff --git a/stdlib/strfroml_l.c b/stdlib/strfroml_l.c
new file mode 100644
index 0000000..79043f0
--- /dev/null
+++ b/stdlib/strfroml_l.c
@@ -0,0 +1,29 @@
+/* Definitions for strfroml_l.  Implementation in stdlib/strfrom-skeleton_l.c.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define FLOAT			long double
+#ifdef USE_WIDE_CHAR
+# define STRFROMF		wcsfroml_l
+# define __STRFROMF		__wcsfroml_l
+#else
+# define STRFROMF		strfroml_l
+# define __STRFROMF		__strfroml_l
+#endif
+
+#include "strfrom_l-skeleton.c"
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index 4d3b0b9..2197975 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1846,3 +1846,15 @@ GLIBC_2.25 GLIBC_2.25 A
 GLIBC_2.25 gnu_dev_major F
 GLIBC_2.25 gnu_dev_makedev F
 GLIBC_2.25 gnu_dev_minor F
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 2c2f49e..14ae2ad 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2090,3 +2090,15 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 8afba47..e11af7a 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2001,6 +2001,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index de3bdf4..abbfa63 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -91,6 +91,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3261b93..7fee6d7 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1855,6 +1855,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 6465a55..ebe80cb 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2013,6 +2013,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 4536271..fadc5f7 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1877,6 +1877,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 287d7a5..f789237 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -92,6 +92,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index c9229fa..b955449 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1969,6 +1969,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 0409791..6463972 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2090,3 +2090,15 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index f31653e..4908cdb 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1944,6 +1944,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index a56bd99..c04c6be 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1942,6 +1942,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 44552df..c09a9de 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1940,6 +1940,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 8d2a09d..5b0272c 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1935,6 +1935,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 0443b92..a8286f2 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2131,3 +2131,15 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index ba9a29a..67ac0af 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1973,6 +1973,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index f19534c..12693a4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1978,6 +1978,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index f8de1ab..f5ebd66 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2178,3 +2178,15 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 6819133..309f3e2 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -92,6 +92,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 4cd5d85..e017e7a 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1973,6 +1973,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 8cdb9df..7ef691e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1874,6 +1874,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 69791b4..0787cbb 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1859,6 +1859,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index fce58a8..00f5511 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1965,6 +1965,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 16ce739..af67301 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1903,6 +1903,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index f99c298..4b4ea6b 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2097,3 +2097,15 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index c601ab0..18fe905 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2097,3 +2097,15 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index f99c298..4b4ea6b 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2097,3 +2097,15 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 8e6fa57..ef7d746 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1854,6 +1854,18 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 1e12f48..e987e29 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2097,3 +2097,15 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 strfromd F
+GLIBC_2.25 strfromd_l F
+GLIBC_2.25 strfromf F
+GLIBC_2.25 strfromf_l F
+GLIBC_2.25 strfroml F
+GLIBC_2.25 strfroml_l F
+GLIBC_2.25 wcsfromd F
+GLIBC_2.25 wcsfromd_l F
+GLIBC_2.25 wcsfromf F
+GLIBC_2.25 wcsfromf_l F
+GLIBC_2.25 wcsfroml F
+GLIBC_2.25 wcsfroml_l F
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
index 9384a10..0244743 100644
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -30,6 +30,8 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
 	    btowc wctob mbsinit \
 	    mbrlen mbrtowc wcrtomb mbsrtowcs wcsrtombs \
 	    mbsnrtowcs wcsnrtombs wcsnlen wcschrnul \
+	    wcsfromd wcsfromf wcsfroml \
+	    wcsfromd_l wcsfromf_l wcsfroml_l \
 	    wcstol wcstoul wcstoll wcstoull wcstod wcstold wcstof \
 	    wcstol_l wcstoul_l wcstoll_l wcstoull_l \
 	    wcstod_l wcstold_l wcstof_l \
@@ -91,6 +93,15 @@ CFLAGS-wcstold_l.c = $(strtox-CFLAGS)
 CFLAGS-wcstof_l.c = $(strtox-CFLAGS)
 CPPFLAGS-tst-wchar-h.c = -D_FORTIFY_SOURCE=2
 
+# The strfrom class of functions call __printf_fp in order to convert the
+# floating-point value to characters.  This requires the value of IO_MTSAFE_IO.
+CFLAGS-wcsfromd.c = $(libio-mtsafe)
+CFLAGS-wcsfromd_l.c = $(libio-mtsafe)
+CFLAGS-wcsfromf.c = $(libio-mtsafe)
+CFLAGS-wcsfromf_l.c = $(libio-mtsafe)
+CFLAGS-wcsfroml.c = $(libio-mtsafe)
+CFLAGS-wcsfroml_l.c = $(libio-mtsafe)
+
 CFLAGS-isoc99_wscanf.c += -fexceptions
 CFLAGS-isoc99_fwscanf.c += -fexceptions
 CFLAGS-isoc99_vwscanf.c += -fexceptions
diff --git a/wcsmbs/Versions b/wcsmbs/Versions
index 1ff5ff3..b29a303 100644
--- a/wcsmbs/Versions
+++ b/wcsmbs/Versions
@@ -31,4 +31,7 @@ libc {
   GLIBC_2.16 {
     c16rtomb; c32rtomb; mbrtoc16; mbrtoc32;
   }
+  GLIBC_2.25 {
+    wcsfromd; wcsfromf; wcsfroml;
+  }
 }
diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
index 9686fcd..87ad0f5 100644
--- a/wcsmbs/wchar.h
+++ b/wcsmbs/wchar.h
@@ -453,6 +453,12 @@ __BEGIN_NAMESPACE_STD
    representation.  */
 extern double wcstod (const wchar_t *__restrict __nptr,
 		      wchar_t **__restrict __endptr) __THROW;
+/* Convert the floating-point value f, in `double' representation, to the wide
+   string `dest'.  */
+#if __GLIBC_USE (IEC_60559_BFP_EXT)
+extern int wcsfromd (wchar_t * __dest, size_t __size, const char * __format,
+		     double __f) __THROW __nonnull ((3));
+#endif
 __END_NAMESPACE_STD
 
 #ifdef __USE_ISOC99
@@ -462,6 +468,12 @@ extern float wcstof (const wchar_t *__restrict __nptr,
 		     wchar_t **__restrict __endptr) __THROW;
 extern long double wcstold (const wchar_t *__restrict __nptr,
 			    wchar_t **__restrict __endptr) __THROW;
+#if __GLIBC_USE (IEC_60559_BFP_EXT)
+extern int wcsfromf (wchar_t * __dest, size_t __size, const char * __format,
+		     float __f) __THROW __nonnull ((3));
+extern int wcsfroml (wchar_t * __dest, size_t __size, const char * __format,
+		     long double __f) __THROW __nonnull ((3));
+#endif
 __END_NAMESPACE_C99
 #endif /* C99 */
 
@@ -561,6 +573,17 @@ extern float wcstof_l (const wchar_t *__restrict __nptr,
 extern long double wcstold_l (const wchar_t *__restrict __nptr,
 			      wchar_t **__restrict __endptr,
 			      __locale_t __loc) __THROW;
+
+/* Same thing for wcsfrom functions.  */
+extern int wcsfromd_l (wchar_t *__restrict __dest, size_t __size,
+		       const char *__format, double __f, __locale_t __loc)
+     __THROW __nonnull ((3));
+extern int wcsfromf_l (wchar_t *__restrict __dest, size_t __size,
+		       const char *, float __f, __locale_t __loc)
+     __THROW __nonnull ((3));
+extern int wcsfroml_l (wchar_t *__restrict __dest, size_t __size,
+		       const char *__format, long double __f, __locale_t __loc)
+     __THROW __nonnull ((3));
 #endif	/* use GNU */
 
 
diff --git a/wcsmbs/wcsfromd.c b/wcsmbs/wcsfromd.c
new file mode 100644
index 0000000..b9ac076
--- /dev/null
+++ b/wcsmbs/wcsfromd.c
@@ -0,0 +1,25 @@
+/* Convert double to string representation.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <xlocale.h>
+
+#define USE_WIDE_CHAR	1
+
+#include <stdlib/strfromd.c>
diff --git a/wcsmbs/wcsfromd_l.c b/wcsmbs/wcsfromd_l.c
new file mode 100644
index 0000000..824ee23
--- /dev/null
+++ b/wcsmbs/wcsfromd_l.c
@@ -0,0 +1,25 @@
+/* Convert double to string representation, using given locale.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <xlocale.h>
+
+#define USE_WIDE_CHAR	1
+
+#include <stdlib/strfromd_l.c>
diff --git a/wcsmbs/wcsfromf.c b/wcsmbs/wcsfromf.c
new file mode 100644
index 0000000..1ca0980
--- /dev/null
+++ b/wcsmbs/wcsfromf.c
@@ -0,0 +1,25 @@
+/* Convert float to string representation.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <xlocale.h>
+
+#define USE_WIDE_CHAR	1
+
+#include <stdlib/strfromf.c>
diff --git a/wcsmbs/wcsfromf_l.c b/wcsmbs/wcsfromf_l.c
new file mode 100644
index 0000000..7827061
--- /dev/null
+++ b/wcsmbs/wcsfromf_l.c
@@ -0,0 +1,25 @@
+/* Convert float to string representation, using given locale.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <xlocale.h>
+
+#define USE_WIDE_CHAR	1
+
+#include <stdlib/strfromf_l.c>
diff --git a/wcsmbs/wcsfroml.c b/wcsmbs/wcsfroml.c
new file mode 100644
index 0000000..8225937
--- /dev/null
+++ b/wcsmbs/wcsfroml.c
@@ -0,0 +1,25 @@
+/* Convert long double to string representation.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <xlocale.h>
+
+#define USE_WIDE_CHAR	1
+
+#include <stdlib/strfroml.c>
diff --git a/wcsmbs/wcsfroml_l.c b/wcsmbs/wcsfroml_l.c
new file mode 100644
index 0000000..b2183fd
--- /dev/null
+++ b/wcsmbs/wcsfroml_l.c
@@ -0,0 +1,25 @@
+/* Convert long double to string representation, using given locale.
+
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <xlocale.h>
+
+#define USE_WIDE_CHAR	1
+
+#include <stdlib/strfroml_l.c>
-- 
2.4.11

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 2/2] Add tests for strfrom functions
  2016-08-23 15:44 [PATCH 0/2] New strfrom functions Gabriel F. T. Gomes
@ 2016-08-23 15:44 ` Gabriel F. T. Gomes
  2016-08-23 17:27   ` Joseph Myers
  2016-08-23 15:44 ` [PATCH 1/2] Add strfrom{d,f,l} and wcsfrom{d,f,l} functions Gabriel F. T. Gomes
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: Gabriel F. T. Gomes @ 2016-08-23 15:44 UTC (permalink / raw)
  To: libc-alpha

From: Rajalakshmi Srinivasaraghavan <raji@linux.vnet.ibm.com>

This patch adds tests for strfrom and wcsfrom functions.

2016-08-23  Rajalakshmi Srinivasaraghavan  <raji@linux.vnet.ibm.com>

	* localedata/Makefile (locale_test_suite): Add tst_wcsfrom.
	* localedata/tests-mbwc/dat_wcsfrom.c: New file.
	* localedata/tests-mbwc/tgn_funcdef.h (Twcsfrom): New macro.
	(tst_wcsfrom): Declare.
	* localedata/tests-mbwc/tst_types.h: New struct TEX_WCSFROM_REC
	and TIN_WCSFROM_REC.
	* localedata/tests-mbwc/tst_wcsfrom.c: New file.
	* stdlib/Makefile (tests): Add tst-strfrom.
	* stdlib/tst-strfrom.c: New file.
	* stdlib/bug-strtod.c: Refactor based on GEN_TEST_STRTOD_FOREACH.
	* stdlib/bug-strtod2.c: Likewise.
	* stdlib/tst-strtod-round-skeleton.c: Likewise.
	* stdlib/tst-strtod6.c: Likewise.
	* stdlib/tst-strtod.h (GEN_TEST_STRTOD_FOREACH): New field for
	strfrom function suffix.
	* wcsmbs/Makefile (tests): Add tst-wcsfrom.
	* wcsmbs/tst-wcsfrom.c: New file.
---
 localedata/Makefile                 |   2 +-
 localedata/tests-mbwc/dat_wcsfrom.c |  82 +++++++++++++++++
 localedata/tests-mbwc/tgn_funcdef.h |   2 +
 localedata/tests-mbwc/tst_types.h   |  25 ++++++
 localedata/tests-mbwc/tst_wcsfrom.c |  75 ++++++++++++++++
 stdlib/Makefile                     |   3 +-
 stdlib/bug-strtod.c                 |  10 ++-
 stdlib/bug-strtod2.c                |   2 +-
 stdlib/tst-strfrom.c                | 173 ++++++++++++++++++++++++++++++++++++
 stdlib/tst-strtod-round-skeleton.c  |  16 ++--
 stdlib/tst-strtod.h                 |   9 +-
 stdlib/tst-strtod6.c                |   2 +-
 wcsmbs/Makefile                     |   3 +-
 wcsmbs/tst-wcsfrom.c                |  30 +++++++
 14 files changed, 413 insertions(+), 21 deletions(-)
 create mode 100644 localedata/tests-mbwc/dat_wcsfrom.c
 create mode 100644 localedata/tests-mbwc/tst_wcsfrom.c
 create mode 100644 stdlib/tst-strfrom.c
 create mode 100644 wcsmbs/tst-wcsfrom.c

diff --git a/localedata/Makefile b/localedata/Makefile
index 4ecb192..2c506d0 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -69,7 +69,7 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl            \
 		     tst_wcspbrk tst_wcsrtombs tst_wcsspn tst_wcsstr   \
 		     tst_wcstod tst_wcstok tst_wcstombs tst_wcswidth   \
 		     tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans      \
-		     tst_wctype tst_wcwidth
+		     tst_wctype tst_wcwidth tst_wcsfrom
 
 tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
 	tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \
diff --git a/localedata/tests-mbwc/dat_wcsfrom.c b/localedata/tests-mbwc/dat_wcsfrom.c
new file mode 100644
index 0000000..b805d69
--- /dev/null
+++ b/localedata/tests-mbwc/dat_wcsfrom.c
@@ -0,0 +1,82 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *	 FILE:	dat_wcsfrom.c
+ *
+ * int wcsfromf (wchar_t *__restrict dest, size_t size,
+ *		 const char * format, float f)
+ * int wcsfromd (wchar_t *__restrict dest, size_t size,
+ *		 const char * format, double f)
+ * int wcsfroml (wchar_t *__restrict dest, size_t size,
+ *		 const char * format, long double f)
+ */
+
+
+TST_WCSFROM tst_wcsfrom_loc [] = {
+  {
+    { Twcsfrom, TST_LOC_de },
+    {
+      {
+	/*01*/
+	/*I*/
+	{0.0},
+	/*E*/
+	{0, 0, 0, { 0x0030,0x002C,0x0030,0x0030,0x0030,0x0030,0x0030,0x0030,0x0000 },
+	{ 0x0030,0x0000 },
+	{ 0x0030,0x0000 }},
+      },
+      {
+	/*02*/
+	/*I*/
+	{123.45645},
+	/*E*/
+	{0, 0, 0, { 0x0031,0x0032,0x0033,0x002C,0x0034,0x0035,0x0036,0x0034,0x0035,0x0031,0x0000 },
+	{ 0x0031,0x0032,0x0033,0x002C,0x0034,0x0035,0x0036,0x0000 },
+	{ 0x0031,0x0032,0x0033,0x002C,0x0034,0x0035,0x0036,0x0000 }},
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsfrom, TST_LOC_enUS },
+    {
+      {
+	/*01*/
+	/*I*/
+	{0.0},
+	/*E*/
+	{0, 0, 0, { 0x0030,0x002E,0x0030,0x0030,0x0030,0x0030,0x0030,0x0030,0x0000 },
+	{ 0x0030,0x0000 },
+	{ 0x0030,0x0000 }},
+      },
+      {
+	/*02*/
+	/*I*/
+	{123.45645},
+	/*E*/
+	{0, 0, 0, { 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0034,0x0035,0x0031,0x0000 },
+	{ 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0000 },
+	{ 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0000 }},
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsfrom, TST_LOC_eucJP },
+    {
+      {
+	/*01*/
+	/*I*/
+	{123.45645},
+	/*E*/
+	{0, 0, 0, { 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0034,0x0035,0x0031,0x0000 },
+	{ 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0000 },
+	{ 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0000 }},
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsfrom, TST_LOC_end }
+  }
+};
diff --git a/localedata/tests-mbwc/tgn_funcdef.h b/localedata/tests-mbwc/tgn_funcdef.h
index ec24792..c3b5634 100644
--- a/localedata/tests-mbwc/tgn_funcdef.h
+++ b/localedata/tests-mbwc/tgn_funcdef.h
@@ -52,6 +52,7 @@
 #define	 Twctrans		48
 #define	 Twctype		49
 #define	 Twcwidth		50
+#define	 Twcsfrom		51
 
 /* Name of each test.  */
 #define	 S_ISWALNUM	"iswalnum"
@@ -156,5 +157,6 @@ extern int tst_wctomb (FILE *, int);
 extern int tst_wctrans (FILE *, int);
 extern int tst_wctype (FILE *, int);
 extern int tst_wcwidth (FILE *, int);
+extern int tst_wcsfrom (FILE *, int);
 
 #endif /* TGN_FUNCDEF_H */
diff --git a/localedata/tests-mbwc/tst_types.h b/localedata/tests-mbwc/tst_types.h
index 7a5db4f..346798f 100644
--- a/localedata/tests-mbwc/tst_types.h
+++ b/localedata/tests-mbwc/tst_types.h
@@ -575,6 +575,31 @@ TEX_WCSTOD_REC;
 
 TMD_RECHEAD (WCSTOD);
 
+/*----------------------------------------------------------------------*/
+/*  WCSFROM: int wcsfromf (wchar_t * dest, size_t size,			*/
+/*			   const char * format, float f)		*/
+/*  WCSFROM: int wcsfromd (wchar_t * dest, size_t size,			*/
+/*			   const char * format, double d)		*/
+/*  WCSFROM: int wcsfroml (wchar_t * dest, size_t size,			*/
+/*			   const char * format, long double l)		*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  float val;
+}
+TIN_WCSFROM_REC;
+
+typedef struct
+{
+  TMD_ERRET (int);
+  wchar_t f[WCSSIZE];
+  wchar_t d[WCSSIZE];
+  wchar_t l[WCSSIZE];
+}
+TEX_WCSFROM_REC;
+
+TMD_RECHEAD (WCSFROM);
 
 /*----------------------------------------------------------------------*/
 /*  WCSTOK: wchar_t *wcstok (wchar_t *ws, const wchar_t *dlm,		*/
diff --git a/localedata/tests-mbwc/tst_wcsfrom.c b/localedata/tests-mbwc/tst_wcsfrom.c
new file mode 100644
index 0000000..57202c5
--- /dev/null
+++ b/localedata/tests-mbwc/tst_wcsfrom.c
@@ -0,0 +1,75 @@
+/*
+ * int wcsfromf (wchar_t * dest, size_t size,
+ *		 const char * format, float f)
+ * int wcsfromd (wchar_t * dest, size_t size,
+ *		 const char * format, double d)
+ * int wcsfroml (wchar_t * dest, size_t size,
+ *		 const char * format, long double l)
+*/
+
+#define TST_FUNCTION wcsfrom
+
+#include "tsp_common.c"
+#include "dat_wcsfrom.c"
+
+/* Splat n variants of the same test for the various strfrom functions.  */
+#define GEN_TEST_STRFROM_FOREACH(mfunc, ...) \
+    mfunc ( f, float, "%f", ##__VA_ARGS__) \
+    mfunc ( d, double, "%g", ##__VA_ARGS__) \
+    mfunc ( l, long double, "%g", ##__VA_ARGS__)
+/* The arguments to the generated macros are:
+ * FSUF - Function suffix
+ * FTYPE - float type
+ * FMT - format specifier
+ */
+
+#define STRFROM_TEST_FOREACH(mfunc, ...)	\
+({ 						\
+   int result = 0;				\
+   result |= mfunc ## f (__VA_ARGS__);		\
+   result |= mfunc ## d (__VA_ARGS__);		\
+   result |= mfunc ## l (__VA_ARGS__);		\
+   result;					\
+})
+
+#define TEST_STRFROM(FSUF, FTYPE, FMT)					\
+static int								\
+test_strfrom ## FSUF (FILE *fp)						\
+{									\
+  wchar_t buf[WCSSIZE];							\
+  TST_DECL_VARS (int);							\
+  TST_DO_TEST (wcsfrom)							\
+  {									\
+    TST_HEAD_LOCALE (wcsfrom, "wcsfrom"# FSUF);				\
+    TST_DO_REC (wcsfrom)						\
+    {									\
+      TST_GET_ERRET (wcsfrom);						\
+      TST_CLEAR_ERRNO;							\
+      ret_exp = 0;							\
+      TST_SAVE_ERRNO;							\
+      ret = wcsfrom ## FSUF (buf, WCSSIZE, FMT,				\
+			     TST_INPUT (wcsfrom).val);			\
+      TST_IF_RETURN ("wcsfrom"# FSUF)					\
+      {									\
+      };								\
+      ret = wcscmp (buf, TST_EXPECT (wcsfrom).FSUF);			\
+      if (ret != 0)							\
+	{								\
+	  err_count++;							\
+	  Result (C_FAILURE, "wcsfrom"# FSUF, CASE_3,			\
+		  "return value is wrong");				\
+	}								\
+      else								\
+	Result (C_SUCCESS, "wcsfrom"# FSUF, CASE_3, MS_PASSED);		\
+    }									\
+  }									\
+  return err_count;							\
+}
+
+GEN_TEST_STRFROM_FOREACH (TEST_STRFROM)
+
+int
+tst_wcsfrom (FILE *fp, int debug_flg)
+{
+  return STRFROM_TEST_FOREACH (test_strfrom, fp);
+}
diff --git a/stdlib/Makefile b/stdlib/Makefile
index 67969aa..0db42d5 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -79,7 +79,7 @@ tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
 		   tst-tininess tst-strtod-underflow tst-tls-atexit	    \
 		   tst-setcontext3 tst-tls-atexit-nodelete		    \
 		   tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l    \
-		   tst-quick_exit tst-thread-quick_exit
+		   tst-quick_exit tst-thread-quick_exit tst-strfrom
 tests-static	:= tst-secure-getenv
 ifeq ($(have-cxx-thread_local),yes)
 CFLAGS-tst-quick_exit.o = -std=c++11
@@ -161,6 +161,7 @@ $(objpfx)tst-strtod5.out: $(gen-locales)
 $(objpfx)tst-strtol-locale.out: $(gen-locales)
 $(objpfx)tst-strtod-nan-locale.out: $(gen-locales)
 $(objpfx)tst-strfmon_l.out: $(gen-locales)
+$(objpfx)tst-strfrom.out: $(gen-locales)
 endif
 
 # Testdir has to be named stdlib and needs to be writable
diff --git a/stdlib/bug-strtod.c b/stdlib/bug-strtod.c
index c8b56aa..2e8b5e0 100644
--- a/stdlib/bug-strtod.c
+++ b/stdlib/bug-strtod.c
@@ -22,8 +22,12 @@
 #include <string.h>
 
 #include "tst-strtod.h"
+#define _CONCAT(a, b) a ## b
+#define CONCAT(a, b) _CONCAT (a, b)
+#define FNPFX   str
+#define STRFROM(x) CONCAT (CONCAT (FNPFX, from), x)
 
-#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF)		\
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF)			\
 static int								\
 test_strto ## FSUF (void)						\
 {									\
@@ -45,8 +49,8 @@ test_strto ## FSUF (void)						\
 	{								\
 	  char fstr[FSTRLENMAX];					\
 	  char fcntstr[FSTRLENMAX];					\
-	  FTOSTR (fstr, sizeof (fstr), "%" FTOSTRM "g", f);		\
-	  FTOSTR (fcntstr, sizeof (fstr), "%" FTOSTRM "g", (FTYPE) cnt); \
+	  STRFROM(FTOSTR) (fstr, sizeof (fstr), "%g", f);		\
+	  STRFROM(FTOSTR) (fcntstr, sizeof (fstr), "%g", (FTYPE) cnt);	\
 	  printf ("strto" #FSUF "(\"%s\") "				\
 		  "failed for cnt == %d (%s instead of %s)\n",		\
 		  buf, cnt, fstr, fcntstr);				\
diff --git a/stdlib/bug-strtod2.c b/stdlib/bug-strtod2.c
index cd13e9a..6128f2d 100644
--- a/stdlib/bug-strtod2.c
+++ b/stdlib/bug-strtod2.c
@@ -12,7 +12,7 @@ static const char *tests[] =
   };
 #define ntests (sizeof (tests) / sizeof (tests[0]))
 
-#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF)		\
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF)			\
 static int								\
 test_strto ## FSUF (void)						\
 {									\
diff --git a/stdlib/tst-strfrom.c b/stdlib/tst-strfrom.c
new file mode 100644
index 0000000..d85b640
--- /dev/null
+++ b/stdlib/tst-strfrom.c
@@ -0,0 +1,173 @@
+/* Tests for strfromf, strfromd, strfroml functions.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#include <locale/localeinfo.h>
+
+#include "tst-strtod.h"
+
+#ifndef WIDE
+# define STR_CMP strcmp
+# define STR_TO_LD strtold
+# define CHAR_T char
+# define PRINT printf
+# define L_(Str) Str
+# define S "%s"
+# define FNPFX   str
+#endif
+
+#define STRX(x) #x
+#define STR(x) STRX (x)
+#define FNPFXS STR (FNPFX)
+
+#define _CONCAT(a, b) a ## b
+#define CONCAT(a, b) _CONCAT (a, b)
+#define STRFROM(x) CONCAT (CONCAT (FNPFX, from), x)
+
+struct ltest
+{
+  const CHAR_T *expect;
+  double val;
+  const char *fmt;
+  int size;
+  int rc;
+};
+static const struct ltest ltests[] = {
+  {L_("12345.3"), 12345.345, "%g", 50, 7},
+  {L_("1.000001"), 0x80000Ap-23, "%f", 50, 8},
+  {L_("inf"), HUGE_VAL, "%f", 50, 3},
+  {L_("-inf"), -HUGE_VAL, "%g", 50, 4},
+  {L_("12.345"), 12.345, "%g", 50, 6},
+  {L_("1.2345e+20"), 12.345e19, "%g", 50, 10},
+  {L_("-1e+08"), -.1e+9, "%g", 50, 6},
+  {L_("0.125000"), .125, "%f", 50, 8},
+  {L_("100000"), 1e5, "%g", 50, 6},
+  {L_("9.999"), 9.999, "%.3f", 50, 5},
+  {L_("0.000000"), 0.0, "%f", 50, 8},
+  {L_("0"), 0.0, "%g", 50, 1},
+  {L_("8.000000"), 0x10p-1, "%f", 50, 8},
+  {L_("8"), 0x10p-1, "%g", 50, 1},
+  {L_("INF"), DBL_MAX * DBL_MAX, "%F", 50, 3},
+  {L_("-INF"), -DBL_MAX * DBL_MAX, "%G", 50, 4},
+  {L_("9.900000"), 9.9, "%f", 50, 8},
+  {L_("9.900"), 9.9, "%.3f", 50, 5},
+  {L_("1"), 10.000e-1, "%.f", 50, 1},
+  {L_("2"), 200.000e-2, "%g", 50, 1},
+  {L_("9.912346"), 9.91234567812345678, "%f", 50, 8},
+  {L_("7.987654e+01"), 79.87654321, "%e", 50, 12},
+  {L_("7.987654E+01"), 79.87654321, "%E", 50, 12},
+  {L_("7.988e+01"), 79.87654321, "%.3e", 50, 9},
+  {L_("7.987654e+01"), 79.87654321, "%.6e", 50, 12},
+  {L_("79.8765"), 79.87654321, "%g", 50, 7},
+  {L_("79.8765"), 79.87654321, "%G", 50, 7},
+  {L_("5.070602e+30"), 0x1p102, "%e", 50, 12},
+  {L_("1.038459e+34"), 0x1000p101, "%e", 50, 12},
+  {L_("2.097152e+06"), 0x2p020, "%e", 50, 12},
+  {L_("1.000000e+38"), 1e+38, "%e", 50, 12},
+  {L_("1.000000e+38"), 1e38, "%e", 50, 12},
+  {L_("1.000000e-37"), 1e-37, "%e", 50, 12},
+  {L_("1.000000e-37"), 0.00000001e-29, "%e", 50, 12},
+  {L_("1.000000e-37"), 1.000000e-37, "%e", 50, 12},
+  {L_("3.761582e-37"), 0x1p-121, "%e", 50, 12},
+  {L_("3.761582e-37"), 0x0.0001p-105, "%e", 50, 12},
+  {L_("5.900000e-16"), 5.9e-16, "%e", 50, 12},
+  {L_("1.000001"), 0x80000Ap-23, "%f", 50, 8},
+  {L_("inf"), HUGE_VAL, "%f", 50, 3},
+  {L_("-INF"), -HUGE_VAL, "%G", 50, 4},
+  {L_("1.2345e+20"), 12.345e19, "%g", 50, 10},
+  {L_("0.125000"), .125, "%f", 50, 8},
+  {L_("100000"), 1e5, "%g", 50, 6},
+  {L_("0x1.8p-11"), 0x0.0030p+0, "%a", 50, 9},
+  {L_("0x1p-10"), 0x0.0040p+0, "%a", 50, 7},
+  {L_("0x1.08p+56"), 0x1.08p56, "%a", 50, 10},
+  {L_("0x1p+61"), 0x1p61, "%a", 50, 7},
+  {L_("0x1.0001p+61"), 0x1.0001p61, "%a", 50, 12},
+  {L_("0x1.4p+3"), 10.0, "%a", 50, 8},
+  {L_("0X1.4P+3"), 10.0, "%A", 50, 8},
+  {L_("nan"), NAN, "%e", 50, 3},
+  {L_("-NAN"), -NAN, "%G", 50, 4},
+  {L_("1.79769e+38"), 1.79769e+38, "%g", 50, 11},
+  {L_("nan"), __builtin_nan (""), "%f", 50, 3},
+  {L_("NAN"), __builtin_nans (""), "%G", 50, 3},
+#ifndef WIDE
+  {L_("9.1"), 9.123456, "%.5f", 4, 7},
+#else
+  {L_("9.1"), 9.123456, "%.5f", 4, -1},
+#endif
+  {NULL, 0, "%f", 50, 0},
+};
+
+#define NTESTS (sizeof (tests) / sizeof (tests[0]))
+
+#define TEST_STRFROM(STRTOF, FTYPE, FTOSTR, LSUF, CSUF)			\
+static int								\
+test_ ## STRTOF (void)							\
+{									\
+  CHAR_T buf[50];							\
+  const struct ltest *lt;						\
+  int status = 0;							\
+  int rc = 0, rc1 = 0;							\
+  for (lt = ltests; lt->expect != NULL; ++lt)				\
+    {									\
+      rc = STRFROM(FTOSTR)(buf, lt->size, lt->fmt, lt->val);		\
+      if (strcmp(lt->fmt, "%a") == 0 || strcmp(lt->fmt, "%A") == 0)	\
+	rc1 = (STR_TO_LD(lt->expect, NULL) == STR_TO_LD(buf, NULL))	\
+	      ? 0 : 1;							\
+      else								\
+	rc1 = (STR_CMP(buf, lt->expect) != 0) || (rc != lt->rc);	\
+      if (rc1)								\
+	{								\
+	  PRINT(L_(""FNPFXS "from" #FTOSTR ": got " S "(%d), expected " \
+		   S "(%d)\n"), buf, rc, lt->expect, lt->rc);		\
+	  status++;							\
+	}								\
+    }									\
+  return status;							\
+}
+
+GEN_TEST_STRTOD_FOREACH (TEST_STRFROM)
+
+static int
+test_locale (const char *locale)
+{
+  PRINT (L_("Testing in locale: %s\n"), locale);
+  if (setlocale (LC_CTYPE, locale) == NULL)
+    {
+      PRINT (L_("Cannot set locale %s\n"), locale);
+    }
+  return STRTOD_TEST_FOREACH (test_);
+}
+static int
+do_test (void)
+{
+  int result = 0;
+  result += test_locale ("C");
+  result += test_locale ("de_DE.UTF-8");
+  result += test_locale ("en_US.ISO-8859-1");
+  result += test_locale ("en_US.UTF-8");
+  result += test_locale ("tr_TR.ISO-8859-9");
+  result += test_locale ("tr_TR.UTF-8");
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdlib/tst-strtod-round-skeleton.c b/stdlib/tst-strtod-round-skeleton.c
index 1853c52..a55c201 100644
--- a/stdlib/tst-strtod-round-skeleton.c
+++ b/stdlib/tst-strtod-round-skeleton.c
@@ -47,6 +47,7 @@
 #define CONCAT(a, b) _CONCAT (a, b)
 
 #define STRTO(x) CONCAT (CONCAT (FNPFX, to), x)
+#define STRFROM(x) CONCAT (CONCAT (FNPFX, from), x)
 
 #if LDBL_MANT_DIG == 106 && LDBL_MAX_EXP == 1024
 /* This is a stupid hack for IBM long double.  This test ignores
@@ -58,11 +59,11 @@
 
 /* Generator to create an FTYPE member variabled named FSUF
    used to populate struct member variables.  */
-#define FTYPE_MEMBER(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF)  \
+#define FTYPE_MEMBER(FSUF, FTYPE, FTOSTR, LSUF, CSUF)  \
        FTYPE FSUF;
 
 /* Likewise, but each member is of type bool.  */
-#define BOOL_MEMBER(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF)  \
+#define BOOL_MEMBER(FSUF, FTYPE, FTOSTR, LSUF, CSUF)  \
        bool FSUF;
 
 #define STRUCT_FOREACH_FLOAT_FTYPE GEN_TEST_STRTOD_FOREACH (FTYPE_MEMBER)
@@ -96,13 +97,13 @@
 /* long double is special, and handled above.  */
 
 /* Selector for expected result field of a given type.  */
-#define _ENTRY(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF, ...)  \
+#define _ENTRY(FSUF, FTYPE, FTOSTR, LSUF, CSUF, ...)  \
   CONCAT (CHOOSE_ ## FSUF (__VA_ARGS__), LSUF),
 #define ENTRY(...) \
   GEN_TEST_STRTOD_FOREACH (_ENTRY, __VA_ARGS__)
 
 /* Selector for boolean exact tag of expected results.  */
-#define _XNTRY(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF, ...)  \
+#define _XNTRY(FSUF, FTYPE, FTOSTR, LSUF, CSUF, ...)  \
   CHOOSE_ ## FSUF (__VA_ARGS__),
 #define XNTRY(...) \
   GEN_TEST_STRTOD_FOREACH (_XNTRY, __VA_ARGS__)
@@ -157,7 +158,7 @@ struct test {
 #define STR(x) STRX (x)
 #define FNPFXS STR (FNPFX)
 
-#define GEN_ONE_TEST(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF)	\
+#define GEN_ONE_TEST(FSUF, FTYPE, FTOSTR, LSUF, CSUF)		\
 {								\
   FTYPE f = STRTO (FSUF) (s, NULL);				\
   if (f != expected->FSUF					\
@@ -166,9 +167,8 @@ struct test {
     {								\
       CHAR efstr[FSTRLENMAX];					\
       CHAR fstr[FSTRLENMAX];					\
-      FTOSTR (efstr, FSTRLENMAX, L_("%") L_(FTOSTRM) L_("a"),   \
-	      expected->FSUF);    				\
-      FTOSTR (fstr, FSTRLENMAX, L_("%") L_(FTOSTRM) L_("a"), f);\
+      STRFROM(FTOSTR)(efstr, FSTRLENMAX, "%a", expected->FSUF); \
+      STRFROM(FTOSTR)(fstr, FSTRLENMAX, "%a", f);		\
       printf (FNPFXS "to" #FSUF  " (" STRM ") returned " STRM   \
 	      " not " STRM " (%s)\n",				\
 	      s, fstr, efstr, mode_name);			\
diff --git a/stdlib/tst-strtod.h b/stdlib/tst-strtod.h
index 607cf39..8184b7f 100644
--- a/stdlib/tst-strtod.h
+++ b/stdlib/tst-strtod.h
@@ -23,14 +23,13 @@
 
 /* Splat n variants of the same test for the various strtod functions.  */
 #define GEN_TEST_STRTOD_FOREACH(mfunc, ...)			 \
-    mfunc (  f,       float, snprintf,  "", f, f, ##__VA_ARGS__) \
-    mfunc (  d,      double, snprintf,  "",  ,  , ##__VA_ARGS__) \
-    mfunc ( ld, long double, snprintf, "L", L, l, ##__VA_ARGS__)
+    mfunc (  f,       float, f, f, f, ##__VA_ARGS__)		 \
+    mfunc (  d,      double, d,  ,  , ##__VA_ARGS__)		 \
+    mfunc ( ld, long double, l, L, l, ##__VA_ARGS__)
 /* The arguments to the generated macros are:
    FSUF - Function suffix
    FTYPE - float type
-   FTOSTR - float to string func
-   FTOSTRM - Optional modifier for FTOSTR format
+   FTOSTR - float to string func suffix
    LSUF - Literal suffix
    CSUF - C standardish suffix for many of the math functions
 */
diff --git a/stdlib/tst-strtod6.c b/stdlib/tst-strtod6.c
index 6b3bb84..9bfbdc2 100644
--- a/stdlib/tst-strtod6.c
+++ b/stdlib/tst-strtod6.c
@@ -5,7 +5,7 @@
 
 #include "tst-strtod.h"
 
-#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF) \
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF)	  \
 static int						  \
 test_strto ## FSUF (const char str[])			  \
 {							  \
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
index 0244743..df9ff44 100644
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -51,7 +51,7 @@ strop-tests :=  wcscmp wcsncmp wmemcmp wcslen wcschr wcsrchr wcscpy wcsnlen \
 tests := tst-wcstof wcsmbs-tst1 tst-wcsnlen tst-btowc tst-mbrtowc \
 	 tst-wcrtomb tst-wcpncpy tst-mbsrtowcs tst-wchar-h tst-mbrtowc2 \
 	 tst-c16c32-1 wcsatcliff tst-wcstol-locale tst-wcstod-nan-locale \
-	 tst-wcstod-round \
+	 tst-wcstod-round tst-wcsfrom \
 	 $(addprefix test-,$(strop-tests))
 
 include ../Rules
@@ -69,6 +69,7 @@ $(objpfx)tst-wcrtomb.out: $(gen-locales)
 $(objpfx)wcsmbs-tst1.out: $(gen-locales)
 $(objpfx)tst-wcstol-locale.out: $(gen-locales)
 $(objpfx)tst-wcstod-nan-locale.out: $(gen-locales)
+$(objpfx)tst-wcsfrom.out: $(gen-locales)
 endif
 
 $(objpfx)tst-wcstod-round: $(libm)
diff --git a/wcsmbs/tst-wcsfrom.c b/wcsmbs/tst-wcsfrom.c
new file mode 100644
index 0000000..0f5524a
--- /dev/null
+++ b/wcsmbs/tst-wcsfrom.c
@@ -0,0 +1,30 @@
+/* Test wcsfromf, wcsfromd and wcsfroml functions.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <wchar.h>
+
+#define WIDE 1
+#define L_(str) L ## str
+#define FNPFX wcs
+#define STR_TO_LD wcstold
+#define STR_CMP wcscmp
+#define CHAR_T wchar_t
+#define PRINT wprintf
+#define S "%ls"
+
+#include "../stdlib/tst-strfrom.c"
-- 
2.4.11

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] Add strfrom{d,f,l} and wcsfrom{d,f,l} functions
  2016-08-23 15:44 ` [PATCH 1/2] Add strfrom{d,f,l} and wcsfrom{d,f,l} functions Gabriel F. T. Gomes
@ 2016-08-23 17:21   ` Joseph Myers
  0 siblings, 0 replies; 14+ messages in thread
From: Joseph Myers @ 2016-08-23 17:21 UTC (permalink / raw)
  To: Gabriel F. T. Gomes; +Cc: libc-alpha

On Tue, 23 Aug 2016, Gabriel F. T. Gomes wrote:

> diff --git a/NEWS b/NEWS
> index fdcd7e7..bf5a307 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -7,6 +7,10 @@ using `glibc' in the "product" field.
>  \f
>  Version 2.25
>  
> +* The functions strfromd, strfromf, and strfroml, as well as their
> +  wide-character counterparts are present in libc.  These functions are defined
> +  in ISO/IEC TS 18661-1:2014 and convert a floating-point number into string.

I think the NEWS entry should be consecutive with other NEWS entries for 
features from TS 18661-1, not at the top, and it also needs to mention the 
*_l functions added as GNU extensions.  You also need to say that the 
wide-character versions are GNU extensions, not standard.

> +extern int __strfromf_internal (char * __dest, size_t __size,
> +				const char * __format, float __f, int __group)
> +     __THROW __nonnull ((3));

Why do you need these functions at all?  Grouping should never be involved 
at all, since there is no way to specify it with strfrom.

I'd expect: __strfromf_l (internal name, used in implementing strfromf); 
strfromf_l (weak alias); strfromf (which calls __strfromf_l).  No 
_internal functions, no __strfromf because nothing else in libc calls it 
and you only need __* names when there are other calls and namespace 
issues arise.  hidden_proto/hidden_def only for __strfromf_l because it's 
the only one that gets called from within libc.  And then the same for 
other types and for wide-character functions.  That's all.

> @@ -172,6 +212,7 @@ extern int __vfwprintf (__FILE *__restrict __s,
>  			const wchar_t *__restrict __format,
>  			__gnuc_va_list __arg)
>       /* __attribute__ ((__format__ (__wprintf__, 2, 0))) */;
> +extern int __swprintf (wchar_t *s, size_t n, const wchar_t *format, ...);

I don't see any calls to this function in this patch, so it shouldn't be 
adding a prototype for it.

> +@node Printing of Floats
> +@section Printing of Floats
> +
> +@pindex stdlib.h
> +@pindex wchar.h
> +The @samp{str} functions are declared in @file{stdlib.h} and those
> +beginning with @samp{wcs} are declared in @file{wchar.h}.
> +
> +@comment stdlib.h
> +@comment ISO/IEC TS 18661-1
> +@deftypefun int strfromd (char *restrict @var{string}, size_t @var{size}, const char *restrict @var{format}, double @var{value})

I think all three functions should be covered here (with @deftypefunx for 
the float and long double ones) rather than separating out the float and 
long double ones (the only reason for them to be separated out for strtod 
is probably that strtof and strtold were added in C99).  Or maybe six or 
twelve functions all together.  In any case, the *_l functions are missing 
documentation in this patch.  And the "@comment ISO/IEC TS 18661-1" on the 
wcs* functions is wrong, since they are GNU extensions.

> diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
> index f0dc951..399e3b2 100644
> --- a/stdlib/stdlib.h
> +++ b/stdlib/stdlib.h
> @@ -21,6 +21,9 @@
>  
>  #ifndef	_STDLIB_H
>  
> +#define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION
> +#include <bits/libc-header-start.h>
> +
>  #include <features.h>

This replaces an include of <features.h>, rather than going before it.

> @@ -230,6 +249,20 @@ extern long double strtold_l (const char *__restrict __nptr,
>  			      char **__restrict __endptr,
>  			      __locale_t __loc)
>       __THROW __nonnull ((1, 3));
> +
> +# if __GLIBC_USE (IEC_60559_BFP_EXT)
> +extern int strfromd_l (char * __dest, size_t __size, const char * __format,
> +		       double __f, __locale_t __loc)
> +     __THROW __nonnull ((3));
> +
> +extern int strfromf_l (char * __dest, size_t __size, const char * __format,
> +		       float __f, __locale_t __loc)
> +     __THROW __nonnull ((3));
> +
> +extern int strfroml_l (char * __dest, size_t __size, const char * __format,
> +		       long double __f, __locale_t __loc)
> +     __THROW __nonnull ((3));
> +# endif

This is inside __USE_GNU, which implies __GLIBC_USE (IEC_60559_BFP_EXT), 
so don't put any conditional here.

> +/* Prototype for the internal implementation.  */
> +#include <xlocale.h>
> +extern int INTERNAL (STRFROMF_L) (
> +	STRING_TYPE *, size_t, const char *, FLOAT, int, __locale_t);

Parenthesis at end of line is not GNU style.  Please fix throughout the 
patch series.

> +INTERNAL (STRFROMF) (STRING_TYPE *dest, size_t size, const char * format,

No space after '*' in pointer declarations like this.

> +  return INTERNAL(STRFROMF_L) (dest, size, format, f, group, _NL_CURRENT_LOCALE);

Missing space before '('.  Please fix throughout this series.

> +  /* Check if the format string is not null, even though TS-18661-1 does not
> +     mention that the format string cannot be null.  */
> +  if (format == NULL)
> +    {
> +      MAYBE_SET_EINVAL;
> +      return -1;
> +    }

No.  We don't include random checks for NULL like that.  Standard glibc 
practice is that it's appropriate for such undefined behavior to crash the 
program, so just dereference the format string without checking.

> +      /* According to ISO/IEC 9899:201x, Section 7.21.6.1, 5th paragraph, a
> +	 negative precision is taken as if the precision were omitted.  Thus,
> +	 parse a potential minus sign.  If the minus sign is present, ignore
> +	 the following precision digits.  */
> +      if (*format == '-')

No, that's wrong.  A negative precision specified with '*' is ignored.  A 
precision in the string must be a decimal integer.

Also: throughout this code, you should be comparing with wide character 
such as L'%' if using a wide string; see how the printf code uses a macro 
L_.  I advise using read_int from printf-parse.h (and note that it uses a 
macro ISDIGIT not the function), not hardcoded reading of a precision 
here.

> +      /* If only the period is specified, the precision is taken as zero, as
> +	 described in ISO/IEC 9899:201x, section 7.21.6.1, 4th paragraph, 3rd
> +	 item.  */

It's not 201x.  It's 2011.

> +      else
> +	{
> +	  precision = 0;
> +	}

No redundant braces around single statements.  Please fix anywhere else in 
the patch series as well.

> +  /* The following code to prepare the virtual file has been adapted from the
> +     functions _IO_vsnprintf and _IO_vswprintf from libio.  */
> +
> +  if (size == 0)
> +    {
> +#ifdef USE_WIDE_CHAR
> +    /* ISO/IEC 9899:201x, Section 7.29.2.3, in the third paragraph, specifies
> +       that swprintf returns a negative value if n or more characters would
> +       have been written.  Thus, if size (n) is zero, return a negative number,
> +       so that wcsfrom functions behave similar to swprintf.  */
> +      return -1;

No, this legacy peculiarity of how swprintf was originally specified in 
C90 Amendment 1, before snprintf was added, should not be replicated.  
Wide-character strfrom should act just like narrow-character strfrom as 
regards the return value, and the documentation should make that clear.  
(If you look at the Linux snprintf manpage, you'll see a discussion of how 
pre-C99 versions of snprintf did things like swprintf, then this was 
changed.)

> +#else
> +    /* When size is zero, nothing is written and dest may be a null pointer.
> +       This is specified for snprintf in ISO/IEC 9899:201x, Section 7.21.6.5,
> +       in the second paragraph.  Thus, if size is zero, prepare to use the
> +       overflow buffer right from the start.  */

Again, 2011, not 201x.

> +  /* Terminate the string.  */
> +#ifdef USE_WIDE_CHAR
> +  if (sfile.f._sbf._f._wide_data->_IO_buf_base == sfile.overflow_buf)
> +    /* ISO C99 requires swprintf to return an error if the output does not fit
> +       in the provided buffer.  The wcsfrom functions mimic this behavior.  */
> +    return -1;

Again, don't replicate legacy behavior; snprintf semantics are preferred 
to those of swprintf.

> +/* Convert the floating-point value f, in `double' representation, to the wide
> +   string `dest'.  */
> +#if __GLIBC_USE (IEC_60559_BFP_EXT)
> +extern int wcsfromd (wchar_t * __dest, size_t __size, const char * __format,
> +		     double __f) __THROW __nonnull ((3));
> +#endif
>  __END_NAMESPACE_STD
>  
>  #ifdef __USE_ISOC99
> @@ -462,6 +468,12 @@ extern float wcstof (const wchar_t *__restrict __nptr,
>  		     wchar_t **__restrict __endptr) __THROW;
>  extern long double wcstold (const wchar_t *__restrict __nptr,
>  			    wchar_t **__restrict __endptr) __THROW;
> +#if __GLIBC_USE (IEC_60559_BFP_EXT)
> +extern int wcsfromf (wchar_t * __dest, size_t __size, const char * __format,
> +		     float __f) __THROW __nonnull ((3));
> +extern int wcsfroml (wchar_t * __dest, size_t __size, const char * __format,
> +		     long double __f) __THROW __nonnull ((3));
> +#endif

These conditions are wrong.  These functions are GNU extensions, so you 
need to use #ifdef __USE_GNU.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] Add tests for strfrom functions
  2016-08-23 15:44 ` [PATCH 2/2] Add tests for " Gabriel F. T. Gomes
@ 2016-08-23 17:27   ` Joseph Myers
  0 siblings, 0 replies; 14+ messages in thread
From: Joseph Myers @ 2016-08-23 17:27 UTC (permalink / raw)
  To: Gabriel F. T. Gomes; +Cc: libc-alpha

On Tue, 23 Aug 2016, Gabriel F. T. Gomes wrote:

> +++ b/localedata/tests-mbwc/dat_wcsfrom.c
> @@ -0,0 +1,82 @@
> +/*
> + *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
> + *
> + *	 FILE:	dat_wcsfrom.c
> + *
> + * int wcsfromf (wchar_t *__restrict dest, size_t size,
> + *		 const char * format, float f)
> + * int wcsfromd (wchar_t *__restrict dest, size_t size,
> + *		 const char * format, double f)
> + * int wcsfroml (wchar_t *__restrict dest, size_t size,
> + *		 const char * format, long double f)
> + */

This formatting is particularly strange.  Please ensure all new files / 
blocks of new code are properly formatted following GNU standards, which 
includes having a descriptive comment on the first line followed by a 
copyright notice, and no '*' at the start of individual lines of comments 
(and not having anything from this comment at all apart from the 
description, properly in mixed case, on the first line).

> +	/*01*/
> +	/*I*/
> +	{0.0},

Bad formatting for comments, missing spaces after '{' and before '}'.

> +	  STRFROM(FTOSTR) (fstr, sizeof (fstr), "%g", f);		\
> +	  STRFROM(FTOSTR) (fcntstr, sizeof (fstr), "%g", (FTYPE) cnt);	\

Missing spaces before '(', as in many places in this patch, and I'm 
doubtful that refactoring existing tests belongs in this patch; it would 
better be separated.

> diff --git a/stdlib/tst-strfrom.c b/stdlib/tst-strfrom.c

> +#include <locale/localeinfo.h>

Why is this internal header used in a test?

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] New strfrom functions
  2016-08-23 15:44 [PATCH 0/2] New strfrom functions Gabriel F. T. Gomes
  2016-08-23 15:44 ` [PATCH 2/2] Add tests for " Gabriel F. T. Gomes
  2016-08-23 15:44 ` [PATCH 1/2] Add strfrom{d,f,l} and wcsfrom{d,f,l} functions Gabriel F. T. Gomes
@ 2016-08-23 17:58 ` Joseph Myers
  2016-08-24 16:42   ` Paul E. Murphy
  2016-08-25 11:41 ` Florian Weimer
  3 siblings, 1 reply; 14+ messages in thread
From: Joseph Myers @ 2016-08-23 17:58 UTC (permalink / raw)
  To: Gabriel F. T. Gomes; +Cc: libc-alpha

On Tue, 23 Aug 2016, Gabriel F. T. Gomes wrote:

> The following patches add the functions strfromd, strfromf, and strfroml, as
> well as their wide character counterparts, wcsfromd, wcsfromf, and wcsfroml.

What is the rationale for (a) the *_l functions and (b) the wide-character 
functions?  Patch submissions need to include self-contained rationale for 
such API additions.

What's the locale dependence anyway?  Is it just the decimal point 
character?  You don't seem to have any tests of strfrom*_l, and the 
strfrom test sets only LC_CTYPE not LC_NUMERIC meaning it doesn't exercise 
different decimal point values.

The argument for not having those extra functions, just the three standard 
ones, is that the strfrom API is deliberately designed to be minimal.  It 
doesn't include any of the flags that are available with snprintf, or the 
option to specify field width, or the option to use '*' for precision.  
That is, the idea of the API is: the floating-point aspects of the 
conversions are tricky and specialized, especially when you want correctly 
rounded results, but once you've got a result rounded to the correct 
number of digits, everything else is just routine string manipulation from 
there.  Converting a narrow string to a wide one is certainly easy, so in 
line with that principle you don't need the wcs* functions (and avoiding 
them avoids questions about whether the API follows snprintf or swprintf).  
And we've said before for some suggestions of *_l functions that we don't 
need *_l versions of all functions because for ones where it's likely to 
be less useful it's OK to expect users to use uselocale to set the 
thread-locale locale before calling a function.

So I think there's actually a strong case for just adding the three 
standard functions.  Users wanting to use grouping or outdigits would need 
to manipulate the results of strfrom anyway; it doesn't seem bad for those 
wanting a decimal point from a locale other than the current one to need 
to do so or to use uselocale, or for users wanting wide strings to need to 
convert.

(Testing that those three functions do use the locale-specific decimal 
point, like snprintf, is still desirable.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] New strfrom functions
  2016-08-23 17:58 ` [PATCH 0/2] New strfrom functions Joseph Myers
@ 2016-08-24 16:42   ` Paul E. Murphy
  2016-08-24 22:35     ` Joseph Myers
  0 siblings, 1 reply; 14+ messages in thread
From: Paul E. Murphy @ 2016-08-24 16:42 UTC (permalink / raw)
  To: Joseph Myers, Gabriel F. T. Gomes; +Cc: libc-alpha



On 08/23/2016 12:58 PM, Joseph Myers wrote:
> The argument for not having those extra functions, just the three standard 
> ones, is that the strfrom API is deliberately designed to be minimal.  It 
> doesn't include any of the flags that are available with snprintf, or the 
> option to specify field width, or the option to use '*' for precision.  
> That is, the idea of the API is: the floating-point aspects of the 
> conversions are tricky and specialized, especially when you want correctly 
> rounded results, but once you've got a result rounded to the correct 
> number of digits, everything else is just routine string manipulation from 
> there.  Converting a narrow string to a wide one is certainly easy, so in 
> line with that principle you don't need the wcs* functions (and avoiding 
> them avoids questions about whether the API follows snprintf or swprintf).  
> And we've said before for some suggestions of *_l functions that we don't 
> need *_l versions of all functions because for ones where it's likely to 
> be less useful it's OK to expect users to use uselocale to set the 
> thread-locale locale before calling a function.

Should we also avoid adding wcsfromfN* functions for the same reasons too?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] New strfrom functions
  2016-08-24 16:42   ` Paul E. Murphy
@ 2016-08-24 22:35     ` Joseph Myers
  2016-08-25 14:22       ` Paul E. Murphy
  0 siblings, 1 reply; 14+ messages in thread
From: Joseph Myers @ 2016-08-24 22:35 UTC (permalink / raw)
  To: Paul E. Murphy; +Cc: Gabriel F. T. Gomes, libc-alpha

On Wed, 24 Aug 2016, Paul E. Murphy wrote:

> On 08/23/2016 12:58 PM, Joseph Myers wrote:
> > The argument for not having those extra functions, just the three standard 
> > ones, is that the strfrom API is deliberately designed to be minimal.  It 
> > doesn't include any of the flags that are available with snprintf, or the 
> > option to specify field width, or the option to use '*' for precision.  
> > That is, the idea of the API is: the floating-point aspects of the 
> > conversions are tricky and specialized, especially when you want correctly 
> > rounded results, but once you've got a result rounded to the correct 
> > number of digits, everything else is just routine string manipulation from 
> > there.  Converting a narrow string to a wide one is certainly easy, so in 
> > line with that principle you don't need the wcs* functions (and avoiding 
> > them avoids questions about whether the API follows snprintf or swprintf).  
> > And we've said before for some suggestions of *_l functions that we don't 
> > need *_l versions of all functions because for ones where it's likely to 
> > be less useful it's OK to expect users to use uselocale to set the 
> > thread-locale locale before calling a function.
> 
> Should we also avoid adding wcsfromfN* functions for the same reasons too?

I think so.

The previous discussion of _FloatN functions was saying essentially that 
for each of these functions that you have for float / double / long 
double, you should have a corresponding _FloatN function.  And I think 
that's clearly correct - if we have strfromf_l, we should have 
strfromf128_l; if we have wcsfromf, we should have wcsfromf128.  But it 
wasn't really addressing the question of whether we should have the 
functions for float / double / long double, beyond those in TS 18661-1, at 
all.  And on careful consideration of the minimality of the interface and 
what this implies about how it is intended to be used, it seems 
appropriate not to have the extra functions for any type, just strfromf, 
strfromd, strfroml and the corresponding _FloatN / _FloatNx functions for 
any _FloatN / _FloatNx types supported in glibc.

Wide-string versions of narrow-string functions usually tend to be a 
committee invention - cf. how TR 24731-2 defines some that glibc doesn't 
have, where we do have the narrow string versions.  In this case, the 
committee didn't include such versions, for whatever reason, so it's 
doubtful whether inventing them would really accord with normal glibc 
practice.  *_l may have originated in glibc before being adopted in POSIX 
- at least, I don't think they originated in committee - but the value of 
strfrom_l seeems low.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] New strfrom functions
  2016-08-23 15:44 [PATCH 0/2] New strfrom functions Gabriel F. T. Gomes
                   ` (2 preceding siblings ...)
  2016-08-23 17:58 ` [PATCH 0/2] New strfrom functions Joseph Myers
@ 2016-08-25 11:41 ` Florian Weimer
  2016-08-25 15:07   ` Paul Eggert
  2016-08-26  0:03   ` Joseph Myers
  3 siblings, 2 replies; 14+ messages in thread
From: Florian Weimer @ 2016-08-25 11:41 UTC (permalink / raw)
  To: Gabriel F. T. Gomes; +Cc: libc-alpha

* Gabriel F. T. Gomes:

> The following patches add the functions strfromd, strfromf, and strfroml, as
> well as their wide character counterparts, wcsfromd, wcsfromf, and wcsfroml.
>
> This is being done in preparation for strfromf128.
>
> Tested on ppc, ppc64, ppc64le, s390, and x86_64.
>
> Gabriel F. T. Gomes (1):
>   Add strfrom{d,f,l} and wcsfrom{d,f,l} functions

Does the standard also contain some gdtoa-like functionality (string
formatting which results in the shortest possible representation and
converts back to the original number)?

This seems to be lacking from the standard library, and it is rather
non-trivial to implement efficiently.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] New strfrom functions
  2016-08-24 22:35     ` Joseph Myers
@ 2016-08-25 14:22       ` Paul E. Murphy
  2016-08-26  0:14         ` Joseph Myers
  0 siblings, 1 reply; 14+ messages in thread
From: Paul E. Murphy @ 2016-08-25 14:22 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Gabriel F. T. Gomes, libc-alpha



On 08/24/2016 05:35 PM, Joseph Myers wrote:
> On Wed, 24 Aug 2016, Paul E. Murphy wrote:
> 
>> On 08/23/2016 12:58 PM, Joseph Myers wrote:
>>> The argument for not having those extra functions, just the three standard 
>>> ones, is that the strfrom API is deliberately designed to be minimal.  It 
>>> doesn't include any of the flags that are available with snprintf, or the 
>>> option to specify field width, or the option to use '*' for precision.  
>>> That is, the idea of the API is: the floating-point aspects of the 
>>> conversions are tricky and specialized, especially when you want correctly 
>>> rounded results, but once you've got a result rounded to the correct 
>>> number of digits, everything else is just routine string manipulation from 
>>> there.  Converting a narrow string to a wide one is certainly easy, so in 
>>> line with that principle you don't need the wcs* functions (and avoiding 
>>> them avoids questions about whether the API follows snprintf or swprintf).  
>>> And we've said before for some suggestions of *_l functions that we don't 
>>> need *_l versions of all functions because for ones where it's likely to 
>>> be less useful it's OK to expect users to use uselocale to set the 
>>> thread-locale locale before calling a function.
>>
>> Should we also avoid adding wcsfromfN* functions for the same reasons too?
> 
> I think so.
> 
> The previous discussion of _FloatN functions was saying essentially that 
> for each of these functions that you have for float / double / long 
> double, you should have a corresponding _FloatN function.  And I think 
> that's clearly correct - if we have strfromf_l, we should have 
> strfromf128_l; if we have wcsfromf, we should have wcsfromf128.  But it 
> wasn't really addressing the question of whether we should have the 
> functions for float / double / long double, beyond those in TS 18661-1, at 
> all.  And on careful consideration of the minimality of the interface and 
> what this implies about how it is intended to be used, it seems 
> appropriate not to have the extra functions for any type, just strfromf, 
> strfromd, strfroml and the corresponding _FloatN / _FloatNx functions for 
> any _FloatN / _FloatNx types supported in glibc.
> 
> Wide-string versions of narrow-string functions usually tend to be a 
> committee invention - cf. how TR 24731-2 defines some that glibc doesn't 
> have, where we do have the narrow string versions.  In this case, the 
> committee didn't include such versions, for whatever reason, so it's 
> doubtful whether inventing them would really accord with normal glibc 
> practice.  *_l may have originated in glibc before being adopted in POSIX 
> - at least, I don't think they originated in committee - but the value of 
> strfrom_l seeems low.

Should we redact wcstofN* from the list of new _Float128 API too?  Or, is
the existing wcsto* API sufficient reason to keep it?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] New strfrom functions
  2016-08-25 11:41 ` Florian Weimer
@ 2016-08-25 15:07   ` Paul Eggert
  2016-08-25 15:53     ` Gabriel F. T. Gomes
  2016-08-26  0:03   ` Joseph Myers
  1 sibling, 1 reply; 14+ messages in thread
From: Paul Eggert @ 2016-08-25 15:07 UTC (permalink / raw)
  To: Florian Weimer, Gabriel F. T. Gomes; +Cc: libc-alpha

Florian Weimer wrote:
> Does the standard also contain some gdtoa-like functionality (string
> formatting which results in the shortest possible representation and
> converts back to the original number)?

I don't see anything about it in the latest draft I could find, at:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1778.pdf

The actual ISO/IEC TS 18661-1 standard costs too much for me.

> This seems to be lacking from the standard library, and it is rather
> non-trivial to implement efficiently.

It would be nice to have this capability in glibc. Emacs would use it. Currently 
Emacs uses an inefficient algorithm to print floating-point numbers.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] New strfrom functions
  2016-08-25 15:07   ` Paul Eggert
@ 2016-08-25 15:53     ` Gabriel F. T. Gomes
  0 siblings, 0 replies; 14+ messages in thread
From: Gabriel F. T. Gomes @ 2016-08-25 15:53 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Florian Weimer, libc-alpha

On Thu, 25 Aug 2016 08:07:17 -0700
Paul Eggert <eggert@cs.ucla.edu> wrote:

> Florian Weimer wrote:
> > Does the standard also contain some gdtoa-like functionality (string
> > formatting which results in the shortest possible representation and
> > converts back to the original number)?  
> 
> I don't see anything about it in the latest draft I could find, at:
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1778.pdf

It is also my understanding that this is not in the standard.

> 
> The actual ISO/IEC TS 18661-1 standard costs too much for me.
> 
> > This seems to be lacking from the standard library, and it is rather
> > non-trivial to implement efficiently.  
> 
> It would be nice to have this capability in glibc. Emacs would use it. Currently 
> Emacs uses an inefficient algorithm to print floating-point numbers.
> 

I don't have plans to start working on it... My current priority is the
enabling of float128.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] New strfrom functions
  2016-08-25 11:41 ` Florian Weimer
  2016-08-25 15:07   ` Paul Eggert
@ 2016-08-26  0:03   ` Joseph Myers
  1 sibling, 0 replies; 14+ messages in thread
From: Joseph Myers @ 2016-08-26  0:03 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Gabriel F. T. Gomes, libc-alpha

On Thu, 25 Aug 2016, Florian Weimer wrote:

> Does the standard also contain some gdtoa-like functionality (string
> formatting which results in the shortest possible representation and
> converts back to the original number)?

Such an operation is not an IEEE 754-2008 operation, and the purpose of TS 
18661 is to provide bindings to IEEE 754-2008 (although it sometimes goes 
beyond what IEEE 754 has - for example, 18661-4 includes a tanpi function 
where IEEE 754 only has sinpi and cospi).

> This seems to be lacking from the standard library, and it is rather
> non-trivial to implement efficiently.

It seems rather underspecified (is it the shortest input to strtod that 
returns the original result in round-to-nearest? in the rounding mode used 
when calling the function producing the string? restricted to decimal 
strings rather than hex? restricted to decimal strings with a particular 
format, such as with or without an exponent? required to be the closest 
string with that number of digits in the decimal mantissa even when you 
could get a shorter result by allowing a string that is not closest for 
its number of digits? what should be done for infinities and NaNs? what 
are requirements regarding raising "inexact"?).

But whatever specification you take for such an operation (and it's not 
clear there is a consensus one suitable for all users, given all the 
choices to be made), clearly you can (for IEEE formats) bound the internal 
precision needed to not much more than twice the precision of the input; 
you never need to calculate anything with precision on the order of the 
maximum exponent as you can for worst cases of printf and strtod.  (And 
you can trade off between speed and space used for precomputed data.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 0/2] New strfrom functions
  2016-08-25 14:22       ` Paul E. Murphy
@ 2016-08-26  0:14         ` Joseph Myers
  0 siblings, 0 replies; 14+ messages in thread
From: Joseph Myers @ 2016-08-26  0:14 UTC (permalink / raw)
  To: Paul E. Murphy; +Cc: Gabriel F. T. Gomes, libc-alpha

On Thu, 25 Aug 2016, Paul E. Murphy wrote:

> Should we redact wcstofN* from the list of new _Float128 API too?  Or, is
> the existing wcsto* API sufficient reason to keep it?

I think that since wcstof etc. are non-deprecated functions for all 
existing floating-point types, it's appropriate to add versions for 
_Float128.  And, likewise, for strtof128_l, wcstof128_l.  Rather than 
adding a wide-character function without precedent for it in a standard, 
that's adding a _Float128 version of a non-deprecated API set (just like 
we want clog10f128 when clog10 is a GNU API, j0f128 when POSIX only has j0 
for double not float and long double, etc.).  (And not having them 
wouldn't actually save any space in the libraries for powerpc64le when you 
get onto support for long double being binary128, because the 
implementations of those functions would be needed anyway at that point to 
be what you get when calling wcstold etc. for binary128 long double.  And 
you don't have the questions of how to define the API that arise for 
wcsfrom*.)

WG14 reflector message 12851 (7 Mar 2013) said regarding wide-string 
functions "I believe these were discussed but haven't found the rationale 
for omitting them.".  So there might be something in early minutes of the 
floating-point group, but I don't think it affects adding those functions 
as part of the GNU API.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2016-08-26  0:14 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-23 15:44 [PATCH 0/2] New strfrom functions Gabriel F. T. Gomes
2016-08-23 15:44 ` [PATCH 2/2] Add tests for " Gabriel F. T. Gomes
2016-08-23 17:27   ` Joseph Myers
2016-08-23 15:44 ` [PATCH 1/2] Add strfrom{d,f,l} and wcsfrom{d,f,l} functions Gabriel F. T. Gomes
2016-08-23 17:21   ` Joseph Myers
2016-08-23 17:58 ` [PATCH 0/2] New strfrom functions Joseph Myers
2016-08-24 16:42   ` Paul E. Murphy
2016-08-24 22:35     ` Joseph Myers
2016-08-25 14:22       ` Paul E. Murphy
2016-08-26  0:14         ` Joseph Myers
2016-08-25 11:41 ` Florian Weimer
2016-08-25 15:07   ` Paul Eggert
2016-08-25 15:53     ` Gabriel F. T. Gomes
2016-08-26  0:03   ` Joseph Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).