This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: wcstold implementation for ! LDBL_EQ_DBL


Hi Guys,

  I would like permission to apply the patch below to add an
  implementation of wcstold() for targets where long double is not the
  same as double.  This version does not support reentrancy because
  there is no _strtold_r() function available in newlib.  If/when one
  does become available however it will be relatively easy to update
  this patch.

  OK to apply ?

Cheers
  Nick

newlib/ChangeLog
2015-01-27  Nick Clifton  <nickc@redhat.com>

	* libc/stdlib/wcstold.c (wcstold): Add implementation for when
	long double is not the same as double.

Index: newlib/libc/stdlib/wcstold.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/wcstold.c,v
retrieving revision 1.3
diff -u -3 -p -r1.3 wcstold.c
--- newlib/libc/stdlib/wcstold.c	26 Nov 2013 17:21:01 -0000	1.3
+++ newlib/libc/stdlib/wcstold.c	27 Jan 2015 21:07:51 -0000
@@ -29,14 +29,83 @@ POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <locale.h>
 #include "local.h"
 
-/* On platforms where long double is as wide as double.  */
-#ifdef _LDBL_EQ_DBL
+extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr));
+
 long double
 wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr)
 {
+#ifdef _LDBL_EQ_DBL
+/* On platforms where long double is as wide as double.  */
   return wcstod(nptr, endptr);
-}
+
+#else /* This is a duplicate of the code in wcstod.c, but converted to long double.  */
+
+  static const mbstate_t initial;
+  mbstate_t mbs;
+  long double val;
+  char *buf, *end;
+  const wchar_t *wcp;
+  size_t len;
+
+  while (iswspace (*nptr))
+    nptr++;
+
+  /* Convert the supplied numeric wide char. string to multibyte.  */
+  wcp = nptr;
+  mbs = initial;
+  if ((len = wcsrtombs (NULL, &wcp, 0, &mbs)) == (size_t)-1)
+    {
+      if (endptr != NULL)
+	*endptr = (wchar_t *) nptr;
+      return 0.0L;
+    }
+
+  if ((buf = malloc (len + 1)) == NULL)
+    return 0.0L;
+
+  mbs = initial;
+  wcsrtombs (buf, &wcp, len + 1, &mbs);
+
+  val = _strtold (buf, &end);
+
+  /* We only know where the number ended in the _multibyte_
+     representation of the string. If the caller wants to know
+     where it ended, count multibyte characters to find the
+     corresponding position in the wide char string.  */
+
+  if (endptr != NULL)
+    {
+      /* The only valid multibyte char in a float converted by
+	 strtold/wcstold is the radix char.  What we do here is,
+	 figure out if the radix char was in the valid leading
+	 float sequence in the incoming string.  If so, the
+	 multibyte float string is strlen (radix char) - 1 bytes
+	 longer than the incoming wide char string has characters.
+	 To fix endptr, reposition end as if the radix char was
+	 just one byte long.  The resulting difference (end - buf)
+	 is then equivalent to the number of valid wide characters
+	 in the input string.  */
+      len = strlen (localeconv ()->decimal_point);
+      if (len > 1)
+	{
+	  char *d = strstr (buf, localeconv ()->decimal_point);
+
+	  if (d && d < end)
+	    end -= len - 1;
+	}
+
+      *endptr = (wchar_t *) nptr + (end - buf);
+    }
+
+  free (buf);
+  return val;
 #endif /* _LDBL_EQ_DBL */
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]