* libc/stdlib/wcstold.c (wcstold): Add implementation for when

long double is not the same as double.
This commit is contained in:
Nick Clifton 2015-01-29 08:37:26 +00:00
parent 3e4183d15b
commit 1f3dd90552
2 changed files with 77 additions and 4 deletions

View File

@ -1,3 +1,8 @@
2015-01-29 Nick Clifton <nickc@redhat.com>
* libc/stdlib/wcstold.c (wcstold): Add implementation for when
long double is not the same as double.
2015-01-28 Christian Eggers <ceggers@gmx.de>
* libc/include/sys/time.h: #include <sys/cdefs.h> for __BSD_VISIBLE.

View File

@ -29,14 +29,82 @@ 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);
}
#endif /* _LDBL_EQ_DBL */
#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 */
}