aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/stdlib/strtod.c
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2016-08-10 16:30:46 +0200
committerCorinna Vinschen <corinna@vinschen.de>2016-08-15 17:35:21 +0200
commit238455adfab4f8070ac65400aac22bb8a9e502fc (patch)
tree68dbe978bc7250338ba2de4bab0db5f2feb81b32 /newlib/libc/stdlib/strtod.c
parent5ef60b7e6a0abad86fe637197f738f8a90b525c8 (diff)
downloadnewlib-238455adfab4f8070ac65400aac22bb8a9e502fc.zip
newlib-238455adfab4f8070ac65400aac22bb8a9e502fc.tar.gz
newlib-238455adfab4f8070ac65400aac22bb8a9e502fc.tar.bz2
Implement strto[dflu]_l/wcsto[dflu]_l
Implement GNU extensions strtod_l, strtof_l, strtol_l, strtold_l, strtoll_l, strtoul_l, strtoull_l, wcstod_l, wcstof_l, wcstol_l, wcstold_l, wcstoll_l, wcstoul_l, wcstoull_l. Export from Cygwin, fix posix.xml. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'newlib/libc/stdlib/strtod.c')
-rw-r--r--newlib/libc/stdlib/strtod.c110
1 files changed, 85 insertions, 25 deletions
diff --git a/newlib/libc/stdlib/strtod.c b/newlib/libc/stdlib/strtod.c
index 433dc7f..e908fcb 100644
--- a/newlib/libc/stdlib/strtod.c
+++ b/newlib/libc/stdlib/strtod.c
@@ -1,18 +1,43 @@
/*
FUNCTION
- <<strtod>>, <<strtof>>---string to double or float
+ <<strtod>>, <<strtof>>, <<strtold>>, <<strtod_l>>, <<strtof_l>>, <<strtold_l>>---string to double or float
INDEX
strtod
-INDEX
- _strtod_r
+
INDEX
strtof
+INDEX
+ strtold
+
+INDEX
+ strtod_l
+
+INDEX
+ strtof_l
+
+INDEX
+ strtold_l
+
+INDEX
+ _strtod_r
+
ANSI_SYNOPSIS
#include <stdlib.h>
double strtod(const char *restrict <[str]>, char **restrict <[tail]>);
float strtof(const char *restrict <[str]>, char **restrict <[tail]>);
+ long double strtold(const char *restrict <[str]>,
+ char **restrict <[tail]>);
+
+ #include <stdlib.h>
+ double strtod_l(const char *restrict <[str]>, char **restrict <[tail]>,
+ locale_t <[locale]>);
+ float strtof_l(const char *restrict <[str]>, char **restrict <[tail]>,
+ locale_t <[locale]>);
+ long double strtold_l(const char *restrict <[str]>,
+ char **restrict <[tail]>,
+ locale_t <[locale]>);
double _strtod_r(void *<[reent]>,
const char *restrict <[str]>, char **restrict <[tail]>);
@@ -33,11 +58,11 @@ TRAD_SYNOPSIS
char **<[tail]>;
DESCRIPTION
- The function <<strtod>> parses the character string <[str]>,
- producing a substring which can be converted to a double
- value. The substring converted is the longest initial
- subsequence of <[str]>, beginning with the first
- non-whitespace character, that has one of these formats:
+ <<strtod>>, <<strtof>>, <<strtold>> parse the character string
+ <[str]>, producing a substring which can be converted to a double,
+ float, or long double value, respectively. The substring converted
+ is the longest initial subsequence of <[str]>, beginning with the
+ first non-whitespace character, that has one of these formats:
.[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>]
.[+|-].<[digits]>[(e|E)[+|-]<[digits]>]
.[+|-](i|I)(n|N)(f|F)[(i|I)(n|N)(i|I)(t|T)(y|Y)]
@@ -55,23 +80,33 @@ DESCRIPTION
(which will contain at least the terminating null character of
<[str]>) is stored in <<*<[tail]>>>. If you want no
assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>.
- <<strtof>> is identical to <<strtod>> except for its return type.
This implementation returns the nearest machine number to the
input decimal string. Ties are broken by using the IEEE
round-even rule. However, <<strtof>> is currently subject to
double rounding errors.
+ <<strtod_l>>, <<strtof_l>>, <<strtold_l>> are like <<strtod>>,
+ <<strtof>>, <<strtold>> but perform the conversion based on the
+ locale specified by the locale object locale. If <[locale]> is
+ LC_GLOBAL_LOCALE or not a valid locale object, the behaviour is
+ undefined.
+
The alternate function <<_strtod_r>> is a reentrant version.
The extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
- <<strtod>> returns the converted substring value, if any. If
- no conversion could be performed, 0 is returned. If the
- correct value is out of the range of representable values,
- plus or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is
- stored in errno. If the correct value would cause underflow, 0
- is returned and <<ERANGE>> is stored in errno.
+ These functions return the converted substring value, if any. If
+ no conversion could be performed, 0 is returned. If the correct
+ value is out of the range of representable values, plus or minus
+ <<HUGE_VAL>> (<<HUGE_VALF>>, <<HUGE_VALL>>) is returned, and
+ <<ERANGE>> is stored in errno. If the correct value would cause
+ underflow, 0 is returned and <<ERANGE>> is stored in errno.
+
+PORTABILITY
+<<strtod>> is ANSI.
+<<strtof>>, <<strtold>> are C99.
+<<strtod_l>>, <<strtof_l>>, <<strtold_l>> are GNU extensions.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
@@ -110,6 +145,7 @@ THIS SOFTWARE.
/* Original file gdtoa-strtod.c Modified 06-21-2006 by Jeff Johnston to work within newlib. */
+#define _GNU_SOURCE
#include <_ansi.h>
#include <errno.h>
#include <stdlib.h>
@@ -117,6 +153,7 @@ THIS SOFTWARE.
#include "mprec.h"
#include "gdtoa.h"
#include "gd_qnan.h"
+#include "../locale/setlocale.h"
/* #ifndef NO_FENV_H */
/* #include <fenv.h> */
@@ -213,10 +250,8 @@ _DEFUN (ULtod, (L, bits, exp, k),
#endif /* !NO_HEX_FP */
double
-_DEFUN (_strtod_r, (ptr, s00, se),
- struct _reent *ptr _AND
- _CONST char *__restrict s00 _AND
- char **__restrict se)
+_strtod_l (struct _reent *ptr, const char *__restrict s00, char **__restrict se,
+ locale_t loc)
{
#ifdef Avoid_Underflow
int scale;
@@ -238,6 +273,8 @@ _DEFUN (_strtod_r, (ptr, s00, se),
#ifdef Honor_FLT_ROUNDS
int rounding;
#endif
+ struct lconv *lconv = __localeconv_l (loc);
+ int dec_len = strlen (lconv->decimal_point);
delta = bs = bd = NULL;
sign = nz0 = nz = decpt = 0;
@@ -286,7 +323,7 @@ _DEFUN (_strtod_r, (ptr, s00, se),
#else
#define fpi1 fpi
#endif
- switch((i = gethex(ptr, &s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
+ switch((i = gethex(ptr, &s, &fpi1, &exp, &bb, sign, loc)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
sign = 0;
@@ -317,11 +354,10 @@ _DEFUN (_strtod_r, (ptr, s00, se),
else
z = 10*z + c - '0';
nd0 = nd;
- if (strncmp (s, _localeconv_r (ptr)->decimal_point,
- strlen (_localeconv_r (ptr)->decimal_point)) == 0)
+ if (strncmp (s, lconv->decimal_point, dec_len) == 0)
{
decpt = 1;
- c = *(s += strlen (_localeconv_r (ptr)->decimal_point));
+ c = *(s += dec_len);
if (!nd) {
for(; c == '0'; c = *++s)
nz++;
@@ -1230,13 +1266,37 @@ _DEFUN (_strtod_r, (ptr, s00, se),
return sign ? -dval(rv) : dval(rv);
}
+double
+_DEFUN (_strtod_r, (ptr, s00, se),
+ struct _reent *ptr _AND
+ _CONST char *__restrict s00 _AND
+ char **__restrict se)
+{
+ return _strtod_l (ptr, s00, se, __get_current_locale ());
+}
+
#ifndef _REENT_ONLY
double
+strtod_l (const char *__restrict s00, char **__restrict se, locale_t loc)
+{
+ return _strtod_l (_REENT, s00, se, loc);
+}
+
+double
_DEFUN (strtod, (s00, se),
_CONST char *__restrict s00 _AND char **__restrict se)
{
- return _strtod_r (_REENT, s00, se);
+ return _strtod_l (_REENT, s00, se, __get_current_locale ());
+}
+
+float
+strtof_l (const char *__restrict s00, char **__restrict se, locale_t loc)
+{
+ double retval = _strtod_l (_REENT, s00, se, loc);
+ if (isnan (retval))
+ return nanf (NULL);
+ return (float)retval;
}
float
@@ -1244,7 +1304,7 @@ _DEFUN (strtof, (s00, se),
_CONST char *__restrict s00 _AND
char **__restrict se)
{
- double retval = _strtod_r (_REENT, s00, se);
+ double retval = _strtod_l (_REENT, s00, se, __get_current_locale ());
if (isnan (retval))
return nanf (NULL);
return (float)retval;