From af60a2f11f574a07ddbb0260ef5f317c056d2675 Mon Sep 17 00:00:00 2001
From: "Paul E. Murphy" <murphyp@linux.vnet.ibm.com>
Date: Fri, 6 May 2016 16:00:39 -0500
Subject: [PATCH 1/3] Refactor bug-strtod.c to better test new types.

This introduces tst-strtod.h to contain some macros
to assist with updating strto{f,d,ld} test code to
support additional variants of this function.

	* stdlib/bug-strtod.c (main):
	refactor into ...
	(TEST_STRTOD): New macro function.
	* stdlib/tst-strtod.h: New file.
---
 stdlib/bug-strtod.c | 104 ++++++++++++++++++++--------------------------------
 stdlib/tst-strtod.h |  50 +++++++++++++++++++++++++
 2 files changed, 89 insertions(+), 65 deletions(-)
 create mode 100644 stdlib/tst-strtod.h

diff --git a/stdlib/bug-strtod.c b/stdlib/bug-strtod.c
index 82e7d30..c8b56aa 100644
--- a/stdlib/bug-strtod.c
+++ b/stdlib/bug-strtod.c
@@ -21,73 +21,47 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "tst-strtod.h"
+
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, FTOSTRM, LSUF, CSUF)		\
+static int								\
+test_strto ## FSUF (void)						\
+{									\
+  char buf[300];							\
+  int cnt;								\
+  int result = 0;							\
+									\
+  for (cnt = 0; cnt < 200; ++cnt)					\
+    {									\
+      ssize_t n;							\
+      FTYPE f;								\
+									\
+      n = sprintf (buf, "%d", cnt);					\
+      memset (buf + n, '0', cnt);					\
+      sprintf (buf + n + cnt, ".000e-%d", cnt);				\
+      f = strto ## FSUF (buf, NULL);					\
+									\
+      if (f != (FTYPE) cnt)						\
+	{								\
+	  char fstr[FSTRLENMAX];					\
+	  char fcntstr[FSTRLENMAX];					\
+	  FTOSTR (fstr, sizeof (fstr), "%" FTOSTRM "g", f);		\
+	  FTOSTR (fcntstr, sizeof (fstr), "%" FTOSTRM "g", (FTYPE) cnt); \
+	  printf ("strto" #FSUF "(\"%s\") "				\
+		  "failed for cnt == %d (%s instead of %s)\n",		\
+		  buf, cnt, fstr, fcntstr);				\
+	  result = 1;							\
+	}								\
+      else								\
+	printf ( "strto" #FSUF "() fine for cnt == %d\n", cnt);		\
+    }									\
+  return result;							\
+}
+
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
 
 int
 main (void)
 {
-  char buf[300];
-  int cnt;
-  int result = 0;
-
-  for (cnt = 0; cnt < 200; ++cnt)
-    {
-      ssize_t n;
-      float f;
-
-      n = sprintf (buf, "%d", cnt);
-      memset (buf + n, '0', cnt);
-      sprintf (buf + n + cnt, ".000e-%d", cnt);
-      f = strtof (buf, NULL);
-
-      if (f != (float) cnt)
-	{
-	  printf ("strtof(\"%s\") failed for cnt == %d (%g instead of %g)\n",
-		  buf, cnt, f, (float) cnt);
-	  result = 1;
-	}
-      else
-	printf ("strtof() fine for cnt == %d\n", cnt);
-    }
-
-  for (cnt = 0; cnt < 200; ++cnt)
-    {
-      ssize_t n;
-      double f;
-
-      n = sprintf (buf, "%d", cnt);
-      memset (buf + n, '0', cnt);
-      sprintf (buf + n + cnt, ".000e-%d", cnt);
-      f = strtod (buf, NULL);
-
-      if (f != (double) cnt)
-	{
-	  printf ("strtod(\"%s\") failed for cnt == %d (%g instead of %g)\n",
-		  buf, cnt, f, (double) cnt);
-	  result = 1;
-	}
-      else
-	printf ("strtod() fine for cnt == %d\n", cnt);
-    }
-
-  for (cnt = 0; cnt < 200; ++cnt)
-    {
-      ssize_t n;
-      long double f;
-
-      n = sprintf (buf, "%d", cnt);
-      memset (buf + n, '0', cnt);
-      sprintf (buf + n + cnt, ".000e-%d", cnt);
-      f = strtold (buf, NULL);
-
-      if (f != (long double) cnt)
-	{
-	  printf ("strtold(\"%s\") failed for cnt == %d (%Lg instead of %Lg)\n",
-		  buf, cnt, f, (long double) cnt);
-	  result = 1;
-	}
-      else
-	printf ("strtold() fine for cnt == %d\n", cnt);
-    }
-
-  return result;
+  return STRTOD_TEST_FOREACH (test_strto);
 }
diff --git a/stdlib/tst-strtod.h b/stdlib/tst-strtod.h
new file mode 100644
index 0000000..d53c1de
--- /dev/null
+++ b/stdlib/tst-strtod.h
@@ -0,0 +1,50 @@
+/* Common utilities for testing strtod and its derivatives.
+   This file is part of the GNU C Library.
+   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/>.  */
+
+#ifndef _TST_STRTOD_H
+#define _TST_STRTOD_H
+
+#define FSTRLENMAX 128
+
+/* Splat n variants of the same test for the various strtod functions.  */
+#define GEN_TEST_STRTOD_FOREACH(mfunc)		  \
+    mfunc (  f,       float, snprintf,  "", f, f) \
+    mfunc (  d,      double, snprintf,  "",  ,  ) \
+    mfunc ( ld, long double, snprintf, "L", L, l)
+/* The arguments to the generated macros are:
+   FSUF - Function suffix
+   FTYPE - float type
+   FTOSTR - float to string func
+   FTOSTRM - Optional modifier for FTOSTR format
+   LSUF - Literal suffix
+   CSUF - C standardish suffix for many of the math functions
+*/
+
+
+
+#define STRTOD_TEST_FOREACH(mfunc, ...)	  \
+({					  \
+   int result = 0;			  \
+   result |= mfunc ## f  (__VA_ARGS__);   \
+   result |= mfunc ## d  (__VA_ARGS__);   \
+   result |= mfunc ## ld (__VA_ARGS__);   \
+   result;				  \
+})
+
+
+#endif
-- 
2.4.11

