This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
RFA: wcstold implementation for ! LDBL_EQ_DBL
- From: Nick Clifton <nickc at redhat dot com>
- To: newlib at sourceware dot org
- Date: Tue, 27 Jan 2015 21:16:48 +0000
- Subject: RFA: wcstold implementation for ! LDBL_EQ_DBL
- Authentication-results: sourceware.org; auth=none
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 */
+}