Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2016-08-10 17:30:46 +0300
committerCorinna Vinschen <corinna@vinschen.de>2016-08-15 18:35:21 +0300
commit238455adfab4f8070ac65400aac22bb8a9e502fc (patch)
tree68dbe978bc7250338ba2de4bab0db5f2feb81b32
parent5ef60b7e6a0abad86fe637197f738f8a90b525c8 (diff)
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>
-rw-r--r--newlib/libc/include/stdlib.h19
-rw-r--r--newlib/libc/include/wchar.h13
-rw-r--r--newlib/libc/locale/setlocale.h3
-rw-r--r--newlib/libc/stdlib/gdtoa-gethex.c13
-rw-r--r--newlib/libc/stdlib/mprec.h12
-rw-r--r--newlib/libc/stdlib/strtod.c110
-rw-r--r--newlib/libc/stdlib/strtodg.c89
-rw-r--r--newlib/libc/stdlib/strtol.c75
-rw-r--r--newlib/libc/stdlib/strtold.c28
-rw-r--r--newlib/libc/stdlib/strtoll.c137
-rw-r--r--newlib/libc/stdlib/strtoll_r.c141
-rw-r--r--newlib/libc/stdlib/strtorx.c7
-rw-r--r--newlib/libc/stdlib/strtoul.c74
-rw-r--r--newlib/libc/stdlib/strtoull.c117
-rw-r--r--newlib/libc/stdlib/strtoull_r.c121
-rw-r--r--newlib/libc/stdlib/wcsnrtombs.c28
-rw-r--r--newlib/libc/stdlib/wcstod.c110
-rw-r--r--newlib/libc/stdlib/wcstol.c73
-rw-r--r--newlib/libc/stdlib/wcstold.c28
-rw-r--r--newlib/libc/stdlib/wcstoll.c137
-rw-r--r--newlib/libc/stdlib/wcstoll_r.c141
-rw-r--r--newlib/libc/stdlib/wcstoul.c68
-rw-r--r--newlib/libc/stdlib/wcstoull.c131
-rw-r--r--newlib/libc/stdlib/wcstoull_r.c131
-rw-r--r--winsup/cygwin/common.din14
-rw-r--r--winsup/cygwin/include/cygwin/version.h5
-rw-r--r--winsup/doc/posix.xml22
27 files changed, 1035 insertions, 812 deletions
diff --git a/newlib/libc/include/stdlib.h b/newlib/libc/include/stdlib.h
index 3d1b8a9b0..7b62e004f 100644
--- a/newlib/libc/include/stdlib.h
+++ b/newlib/libc/include/stdlib.h
@@ -26,6 +26,10 @@
#include <cygwin/stdlib.h>
#endif
+#if __GNU_VISIBLE
+#include <sys/_locale.h>
+#endif
+
_BEGIN_STD_C
typedef struct
@@ -164,6 +168,21 @@ long _EXFUN(_strtol_r,(struct _reent *,const char *__restrict __n, char **__rest
unsigned long _EXFUN(strtoul,(const char *__restrict __n, char **__restrict __end_PTR, int __base));
unsigned long _EXFUN(_strtoul_r,(struct _reent *,const char *__restrict __n, char **__restrict __end_PTR, int __base));
+#if __GNU_VISIBLE
+double strtod_l (const char *__restrict, char **__restrict, locale_t);
+float strtof_l (const char *__restrict, char **__restrict, locale_t);
+#ifdef _HAVE_LONG_DOUBLE
+extern long double strtold_l (const char *__restrict, char **__restrict,
+ locale_t);
+#endif /* _HAVE_LONG_DOUBLE */
+long strtol_l (const char *__restrict, char **__restrict, int, locale_t);
+unsigned long strtoul_l (const char *__restrict, char **__restrict, int,
+ locale_t __loc);
+long long strtoll_l (const char *__restrict, char **__restrict, int, locale_t);
+unsigned long long strtoull_l (const char *__restrict, char **__restrict, int,
+ locale_t __loc);
+#endif
+
int _EXFUN(system,(const char *__string));
#if __SVID_VISIBLE || __XSI_VISIBLE >= 4
diff --git a/newlib/libc/include/wchar.h b/newlib/libc/include/wchar.h
index 4df60b4c2..b7f8374e5 100644
--- a/newlib/libc/include/wchar.h
+++ b/newlib/libc/include/wchar.h
@@ -203,6 +203,19 @@ unsigned long long _EXFUN(_wcstoull_r, (struct _reent *, const wchar_t *, wchar_
long double _EXFUN(wcstold, (const wchar_t *, wchar_t **));
#endif
+#if __GNU_VISIBLE
+long wcstol_l (const wchar_t *__restrict, wchar_t **__restrict, int, locale_t);
+long long wcstoll_l (const wchar_t *__restrict, wchar_t **__restrict, int,
+ locale_t);
+unsigned long wcstoul_l (const wchar_t *__restrict, wchar_t **__restrict, int,
+ locale_t);
+unsigned long long wcstoull_l (const wchar_t *__restrict, wchar_t **__restrict,
+ int, locale_t);
+double wcstod_l (const wchar_t *, wchar_t **, locale_t);
+float wcstof_l (const wchar_t *, wchar_t **, locale_t);
+long double wcstold_l (const wchar_t *, wchar_t **, locale_t);
+#endif
+
wint_t _EXFUN(fgetwc, (__FILE *));
wchar_t *_EXFUN(fgetws, (wchar_t *__restrict, int, __FILE *__restrict));
wint_t _EXFUN(fputwc, (wchar_t, __FILE *));
diff --git a/newlib/libc/locale/setlocale.h b/newlib/libc/locale/setlocale.h
index b528ab92f..de2bd6733 100644
--- a/newlib/libc/locale/setlocale.h
+++ b/newlib/libc/locale/setlocale.h
@@ -202,6 +202,9 @@ extern const char *__get_locale_env(struct _reent *, int);
extern struct lconv *__localeconv_l (struct __locale_t *locale);
+extern size_t _wcsnrtombs_l (struct _reent *, char *, const wchar_t **,
+ size_t, size_t, mbstate_t *, locale_t);
+
/* In POSIX terms the global locale is the process-wide locale. Use this
function to always refer to the global locale. */
_ELIDABLE_INLINE struct __locale_t *
diff --git a/newlib/libc/stdlib/gdtoa-gethex.c b/newlib/libc/stdlib/gdtoa-gethex.c
index 3449c989e..fd3903c4f 100644
--- a/newlib/libc/stdlib/gdtoa-gethex.c
+++ b/newlib/libc/stdlib/gdtoa-gethex.c
@@ -32,10 +32,10 @@ THIS SOFTWARE.
#include <_ansi.h>
#include <reent.h>
#include <string.h>
+#include <locale.h>
#include "mprec.h"
#include "gdtoa.h"
#include "gd_qnan.h"
-#include "locale.h"
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && !defined(_SMALL_HEXDIG)
_CONST unsigned char __hexdig[256]=
@@ -145,13 +145,8 @@ _DEFUN (increment, (ptr, b),
int
-_DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
- struct _reent *ptr _AND
- _CONST char **sp _AND
- _CONST FPI *fpi _AND
- Long *exp _AND
- _Bigint **bp _AND
- int sign)
+gethex (struct _reent *ptr, const char **sp, const FPI *fpi,
+ Long *exp, _Bigint **bp, int sign, locale_t loc)
{
_Bigint *b;
_CONST unsigned char *decpt, *s0, *s, *s1;
@@ -159,7 +154,7 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
__ULong L, lostbits, *x;
Long e, e1;
unsigned char *decimalpoint = (unsigned char *)
- _localeconv_r (ptr)->decimal_point;
+ __localeconv_l (loc)->decimal_point;
size_t decp_len = strlen ((const char *) decimalpoint);
unsigned char decp_end = decimalpoint[decp_len - 1];
diff --git a/newlib/libc/stdlib/mprec.h b/newlib/libc/stdlib/mprec.h
index afda63e73..330c3981b 100644
--- a/newlib/libc/stdlib/mprec.h
+++ b/newlib/libc/stdlib/mprec.h
@@ -32,6 +32,7 @@
#include <errno.h>
#include <sys/config.h>
#include <sys/types.h>
+#include "../locale/setlocale.h"
#ifdef __IEEE_LITTLE_ENDIAN
#define IEEE_8087
@@ -400,13 +401,18 @@ _Bigint * _EXFUN(lshift,(struct _reent *p, _Bigint *b, int k));
int _EXFUN(match,(const char**, char*));
_Bigint * _EXFUN(diff,(struct _reent *p, _Bigint *a, _Bigint *b));
int _EXFUN(cmp,(_Bigint *a, _Bigint *b));
-int _EXFUN(gethex,(struct _reent *p, _CONST char **sp, _CONST struct FPI *fpi, Long *exp, _Bigint **bp, int sign));
+int _EXFUN(gethex,(struct _reent *p, _CONST char **sp, _CONST struct FPI *fpi, Long *exp, _Bigint **bp, int sign, locale_t loc));
double _EXFUN(ratio,(_Bigint *a, _Bigint *b));
__ULong _EXFUN(any_on,(_Bigint *b, int k));
void _EXFUN(copybits,(__ULong *c, int n, _Bigint *b));
+double _strtod_l (struct _reent *ptr, const char *__restrict s00,
+ char **__restrict se, locale_t loc);
#if defined (_HAVE_LONG_DOUBLE) && !defined (_LDBL_EQ_DBL)
-int _EXFUN(_strtorx_r,(struct _reent *, _CONST char *, char **, int, void *));
-int _EXFUN(_strtodg_r,(struct _reent *p, _CONST char *s00, char **se, struct FPI *fpi, Long *exp, __ULong *bits));
+int _strtorx_l (struct _reent *, const char *, char **, int,
+ void *, locale_t);
+int _strtodg_l (struct _reent *p, const char *s00, char **se,
+ struct FPI *fpi, Long *exp, __ULong *bits,
+ locale_t);
#endif /* _HAVE_LONG_DOUBLE && !_LDBL_EQ_DBL */
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) || defined(_SMALL_HEXDIG)
diff --git a/newlib/libc/stdlib/strtod.c b/newlib/libc/stdlib/strtod.c
index 433dc7f32..e908fcbbc 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;
diff --git a/newlib/libc/stdlib/strtodg.c b/newlib/libc/stdlib/strtodg.c
index a6b32908b..d8546c336 100644
--- a/newlib/libc/stdlib/strtodg.c
+++ b/newlib/libc/stdlib/strtodg.c
@@ -53,11 +53,7 @@ fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21,
};
static _Bigint *
-#ifdef KR_headers
-sum(p, a, b) struct _reent *p; _Bigint *a; _Bigint *b;
-#else
-sum(struct _reent *p, _Bigint *a, _Bigint *b)
-#endif
+sum (struct _reent *p, _Bigint *a, _Bigint *b)
{
_Bigint *c;
__ULong carry, *xc, *xa, *xb, *xe, y;
@@ -119,11 +115,7 @@ sum(struct _reent *p, _Bigint *a, _Bigint *b)
}
static void
-#ifdef KR_headers
-rshift(b, k) _Bigint *b; int k;
-#else
-rshift(_Bigint *b, int k)
-#endif
+rshift (_Bigint *b, int k)
{
__ULong *x, *x1, *xe, y;
int n;
@@ -152,11 +144,7 @@ rshift(_Bigint *b, int k)
}
static int
-#ifdef KR_headers
-trailz(b) _Bigint *b;
-#else
-trailz(_Bigint *b)
-#endif
+trailz (_Bigint *b)
{
__ULong L, *x, *xe;
int n = 0;
@@ -172,12 +160,8 @@ trailz(_Bigint *b)
return n;
}
- _Bigint *
-#ifdef KR_headers
-increment(p, b) struct _reent *p; _Bigint *b;
-#else
-increment(struct _reent *p, _Bigint *b)
-#endif
+_Bigint *
+increment (struct _reent *p, _Bigint *b)
{
__ULong *x, *xe;
_Bigint *b1;
@@ -217,12 +201,8 @@ increment(struct _reent *p, _Bigint *b)
return b;
}
- int
-#ifdef KR_headers
-decrement(b) _Bigint *b;
-#else
-decrement(_Bigint *b)
-#endif
+int
+decrement (_Bigint *b)
{
__ULong *x, *xe;
#ifdef Pack_16
@@ -250,12 +230,8 @@ decrement(_Bigint *b)
return STRTOG_Inexlo;
}
- static int
-#ifdef KR_headers
-all_on(b, n) _Bigint *b; int n;
-#else
-all_on(_Bigint *b, int n)
-#endif
+static int
+all_on (_Bigint *b, int n)
{
__ULong *x, *xe;
@@ -269,12 +245,8 @@ all_on(_Bigint *b, int n)
return 1;
}
- _Bigint *
-#ifdef KR_headers
-set_ones(p, b, n) struct _reent *p; _Bigint *b; int n;
-#else
-set_ones(struct _reent *p, _Bigint *b, int n)
-#endif
+_Bigint *
+set_ones (struct _reent *p, _Bigint *b, int n)
{
int k;
__ULong *x, *xe;
@@ -297,14 +269,9 @@ set_ones(struct _reent *p, _Bigint *b, int n)
return b;
}
- static int
-rvOK
-#ifdef KR_headers
- (p, d, fpi, exp, bits, exact, rd, irv)
- struct _reent *p; double d; FPI *fpi; Long *exp; __ULong *bits; int exact, rd, *irv;
-#else
- (struct _reent *p, double d, FPI *fpi, Long *exp, __ULong *bits, int exact, int rd, int *irv)
-#endif
+static int
+rvOK (struct _reent *p, double d, FPI *fpi, Long *exp, __ULong *bits, int exact,
+ int rd, int *irv)
{
_Bigint *b;
__ULong carry, inex, lostbits;
@@ -418,12 +385,8 @@ rvOK
return rv;
}
- static int
-#ifdef KR_headers
-mantbits(d) double d;
-#else
-mantbits(U d)
-#endif
+static int
+mantbits (U d)
{
__ULong L;
#ifdef VAX
@@ -441,14 +404,9 @@ mantbits(U d)
return P - 32 - lo0bits(&L);
}
- int
-_strtodg_r
-#ifdef KR_headers
- (p, s00, se, fpi, exp, bits)
- struct _reent *p; const char *s00; char **se; FPI *fpi; Long *exp; __ULong *bits;
-#else
- (struct _reent *p, const char *s00, char **se, FPI *fpi, Long *exp, __ULong *bits)
-#endif
+int
+_strtodg_l (struct _reent *p, const char *s00, char **se, FPI *fpi, Long *exp,
+ __ULong *bits, locale_t loc)
{
int abe, abits, asub;
int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
@@ -462,6 +420,8 @@ _strtodg_r
Long L;
__ULong y, z;
_Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
+ struct lconv *lconv = __localeconv_l (loc);
+ int dec_len = strlen (lconv->decimal_point);
irv = STRTOG_Zero;
denorm = sign = nz0 = nz = 0;
@@ -497,7 +457,7 @@ _strtodg_r
switch(s[1]) {
case 'x':
case 'X':
- irv = gethex(p, &s, fpi, exp, &rvb, sign);
+ irv = gethex(p, &s, fpi, exp, &rvb, sign, loc);
if (irv == STRTOG_NoNumber) {
s = s00;
sign = 0;
@@ -520,15 +480,14 @@ _strtodg_r
z = 10*z + c - '0';
nd0 = nd;
#ifdef USE_LOCALE
- if (strncmp (s, _localeconv_r (p)->decimal_point,
- strlen (_localeconv_r (p)->decimal_point)) == 0)
+ if (strncmp (s, lconv->decimal_point, dec_len) == 0)
#else
if (c == '.')
#endif
{
decpt = 1;
#ifdef USE_LOCALE
- c = *(s += strlen (_localeconv_r (p)->decimal_point));
+ c = *(s += dec_len);
#else
c = *++s;
#endif
diff --git a/newlib/libc/stdlib/strtol.c b/newlib/libc/stdlib/strtol.c
index 7273c7d4b..276ad1340 100644
--- a/newlib/libc/stdlib/strtol.c
+++ b/newlib/libc/stdlib/strtol.c
@@ -1,18 +1,27 @@
/*
FUNCTION
- <<strtol>>---string to long
+ <<strtol>>, <<strtol_l>>---string to long
INDEX
strtol
+
+INDEX
+ strtol_l
+
INDEX
_strtol_r
ANSI_SYNOPSIS
#include <stdlib.h>
- long strtol(const char *restrict <[s]>, char **restrict <[ptr]>,int <[base]>);
+ long strtol(const char *restrict <[s]>, char **restrict <[ptr]>,
+ int <[base]>);
- long _strtol_r(void *<[reent]>,
- const char *restrict <[s]>, char **restrict <[ptr]>,int <[base]>);
+ #include <stdlib.h>
+ long strtol_l(const char *restrict <[s]>, char **restrict <[ptr]>,
+ int <[base]>, locale_t <[locale]>);
+
+ long _strtol_r(void *<[reent]>, const char *restrict <[s]>,
+ char **restrict <[ptr]>,int <[base]>);
TRAD_SYNOPSIS
#include <stdlib.h>
@@ -67,18 +76,24 @@ If the subject string is empty (or not in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
+<<strtol_l>> is like <<strtol>> but performs 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 <<_strtol_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
-<<strtol>> returns the converted value, if any. If no conversion was
-made, 0 is returned.
+<<strtol>>, <<strtol_l>> return the converted value, if any. If no
+conversion was made, 0 is returned.
-<<strtol>> returns <<LONG_MAX>> or <<LONG_MIN>> if the magnitude of
-the converted value is too large, and sets <<errno>> to <<ERANGE>>.
+<<strtol>>, <<strtol_l>> return <<LONG_MAX>> or <<LONG_MIN>> if the
+magnitude of the converted value is too large, and sets <<errno>>
+to <<ERANGE>>.
PORTABILITY
<<strtol>> is ANSI.
+<<strtol_l>> is a GNU extension.
No supporting OS subroutines are required.
*/
@@ -116,26 +131,21 @@ No supporting OS subroutines are required.
* SUCH DAMAGE.
*/
-
+#define _GNU_SOURCE
#include <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
+#include "../locale/setlocale.h"
/*
* Convert a string to a long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
*/
-long
-_DEFUN (_strtol_r, (rptr, nptr, endptr, base),
- struct _reent *rptr _AND
- _CONST char *__restrict nptr _AND
- char **__restrict endptr _AND
- int base)
+static long
+_strtol_l (struct _reent *rptr, const char *__restrict nptr,
+ char **__restrict endptr, int base, locale_t loc)
{
register const unsigned char *s = (const unsigned char *)nptr;
register unsigned long acc;
@@ -150,7 +160,7 @@ _DEFUN (_strtol_r, (rptr, nptr, endptr, base),
*/
do {
c = *s++;
- } while (isspace(c));
+ } while (isspace_l(c, loc));
if (c == '-') {
neg = 1;
c = *s++;
@@ -186,10 +196,12 @@ _DEFUN (_strtol_r, (rptr, nptr, endptr, base),
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
+ if (c >= '0' && c <= '9')
c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
else
break;
if (c >= base)
@@ -212,15 +224,32 @@ _DEFUN (_strtol_r, (rptr, nptr, endptr, base),
return (acc);
}
+long
+_DEFUN (_strtol_r, (rptr, nptr, endptr, base),
+ struct _reent *rptr _AND
+ _CONST char *__restrict nptr _AND
+ char **__restrict endptr _AND
+ int base)
+{
+ return _strtol_l (rptr, nptr, endptr, base, __get_current_locale ());
+}
+
#ifndef _REENT_ONLY
long
+strtol_l (const char *__restrict s, char **__restrict ptr, int base,
+ locale_t loc)
+{
+ return _strtol_l (_REENT, s, ptr, base, loc);
+}
+
+long
_DEFUN (strtol, (s, ptr, base),
_CONST char *__restrict s _AND
char **__restrict ptr _AND
int base)
{
- return _strtol_r (_REENT, s, ptr, base);
+ return _strtol_l (_REENT, s, ptr, base, __get_current_locale ());
}
#endif
diff --git a/newlib/libc/stdlib/strtold.c b/newlib/libc/stdlib/strtold.c
index 1128b747a..6bd1c2cbb 100644
--- a/newlib/libc/stdlib/strtold.c
+++ b/newlib/libc/stdlib/strtold.c
@@ -64,11 +64,25 @@ _strtold_r (struct _reent *ptr, const char *__restrict s00,
{
#ifdef _LDBL_EQ_DBL
/* On platforms where long double is as wide as double. */
- return _strtod_r (ptr, s00, se);
+ return _strtod_l (ptr, s00, se, __get_current_locale ());
#else
long double result;
- _strtorx_r (ptr, s00, se, FLT_ROUNDS, &result);
+ _strtorx_l (ptr, s00, se, FLT_ROUNDS, &result, __get_current_locale ());
+ return result;
+#endif
+}
+
+long double
+strtold_l (const char *__restrict s00, char **__restrict se, locale_t loc)
+{
+#ifdef _LDBL_EQ_DBL
+ /* On platforms where long double is as wide as double. */
+ return _strtod_l (_REENT, s00, se, loc);
+#else
+ long double result;
+
+ _strtorx_l (_REENT, s00, se, FLT_ROUNDS, &result, loc);
return result;
#endif
}
@@ -76,7 +90,15 @@ _strtold_r (struct _reent *ptr, const char *__restrict s00,
long double
strtold (const char *__restrict s00, char **__restrict se)
{
- return _strtold_r (_REENT, s00, se);
+#ifdef _LDBL_EQ_DBL
+ /* On platforms where long double is as wide as double. */
+ return _strtod_l (_REENT, s00, se, __get_current_locale ());
+#else
+ long double result;
+
+ _strtorx_l (_REENT, s00, se, FLT_ROUNDS, &result, __get_current_locale ());
+ return result;
+#endif
}
#endif /* _HAVE_LONG_DOUBLE */
diff --git a/newlib/libc/stdlib/strtoll.c b/newlib/libc/stdlib/strtoll.c
index 3ad8199a0..e61a62a7d 100644
--- a/newlib/libc/stdlib/strtoll.c
+++ b/newlib/libc/stdlib/strtoll.c
@@ -1,18 +1,29 @@
/*
FUNCTION
- <<strtoll>>---string to long long
+ <<strtoll>>, <<strtoll_l>>---string to long long
INDEX
strtoll
+
+INDEX
+ strtoll_l
+
INDEX
_strtoll_r
ANSI_SYNOPSIS
#include <stdlib.h>
- long long strtoll(const char *restrict <[s]>, char **restrict <[ptr]>,int <[base]>);
+ long long strtoll(const char *restrict <[s]>, char **restrict <[ptr]>,
+ int <[base]>);
+
+ #include <stdlib.h>
+ long long strtoll_l(const char *restrict <[s]>,
+ char **restrict <[ptr]>, int <[base]>,
+ locale_t <[locale]>);
long long _strtoll_r(void *<[reent]>,
- const char *restrict <[s]>, char **restrict <[ptr]>,int <[base]>);
+ const char *restrict <[s]>,
+ char **restrict <[ptr]>, int <[base]>);
TRAD_SYNOPSIS
#include <stdlib.h>
@@ -67,18 +78,24 @@ If the subject string is empty (or not in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
+<<strtoll_l>> is like <<strtoll>> but performs 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 <<_strtoll_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS
-<<strtoll>> returns the converted value, if any. If no conversion was
-made, 0 is returned.
+<<strtoll>>, <<strtoll_l>> return the converted value, if any. If no
+conversion was made, 0 is returned.
-<<strtoll>> returns <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>> if the magnitude of
-the converted value is too large, and sets <<errno>> to <<ERANGE>>.
+<<strtoll>>, <<strtoll_l>> return <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>>
+if the magnitude of the converted value is too large, and sets <<errno>>
+to <<ERANGE>>.
PORTABILITY
<<strtoll>> is ANSI.
+<<strtoll_l>> is a GNU extension.
No supporting OS subroutines are required.
*/
@@ -116,23 +133,125 @@ No supporting OS subroutines are required.
* SUCH DAMAGE.
*/
-
+#define _GNU_SOURCE
#include <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
+#include "../locale/setlocale.h"
+
+/*
+ * Convert a string to a long long integer.
+ */
+static long long
+_strtoll_l (struct _reent *rptr, _CONST char *__restrict nptr,
+ char **__restrict endptr, int base, locale_t loc)
+{
+ register const unsigned char *s = (const unsigned char *)nptr;
+ register unsigned long long acc;
+ register int c;
+ register unsigned long long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (isspace_l(c, loc));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX;
+ cutlim = cutoff % (unsigned long long)base;
+ cutoff /= (unsigned long long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX;
+ rptr->_errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? (char *)s - 1 : nptr);
+ return (acc);
+}
+
+long long
+_DEFUN (_strtoll_r, (rptr, nptr, endptr, base),
+ struct _reent *rptr _AND
+ _CONST char *__restrict nptr _AND
+ char **__restrict endptr _AND
+ int base)
+{
+ return _strtoll_l (rptr, nptr, endptr, base, __get_current_locale ());
+}
#ifndef _REENT_ONLY
long long
+strtoll_l (const char *__restrict s, char **__restrict ptr, int base,
+ locale_t loc)
+{
+ return _strtoll_l (_REENT, s, ptr, base, loc);
+}
+
+long long
_DEFUN (strtoll, (s, ptr, base),
_CONST char *__restrict s _AND
char **__restrict ptr _AND
int base)
{
- return _strtoll_r (_REENT, s, ptr, base);
+ return _strtoll_l (_REENT, s, ptr, base, __get_current_locale ());
}
#endif
diff --git a/newlib/libc/stdlib/strtoll_r.c b/newlib/libc/stdlib/strtoll_r.c
index 515464db1..2997587d8 100644
--- a/newlib/libc/stdlib/strtoll_r.c
+++ b/newlib/libc/stdlib/strtoll_r.c
@@ -1,140 +1 @@
-/*
- This code is based on strtoul.c which has the following copyright.
- It is used to convert a string into a signed long long.
-
- long long _strtoll_r (struct _reent *rptr, const char *s,
- char **ptr, int base);
-*/
-
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifdef __GNUC__
-
-#define _GNU_SOURCE
-#include <_ansi.h>
-#include <limits.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <reent.h>
-
-/*
- * Convert a string to a long long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-long long
-_DEFUN (_strtoll_r, (rptr, nptr, endptr, base),
- struct _reent *rptr _AND
- _CONST char *__restrict nptr _AND
- char **__restrict endptr _AND
- int base)
-{
- register const unsigned char *s = (const unsigned char *)nptr;
- register unsigned long long acc;
- register int c;
- register unsigned long long cutoff;
- register int neg = 0, any, cutlim;
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- do {
- c = *s++;
- } while (isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else if (c == '+')
- c = *s++;
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
-
- /*
- * Compute the cutoff value between legal numbers and illegal
- * numbers. That is the largest legal value, divided by the
- * base. An input number that is greater than this value, if
- * followed by a legal input character, is too big. One that
- * is equal to this value may be valid or not; the limit
- * between valid and invalid numbers is then based on the last
- * digit. For instance, if the range for longs is
- * [-2147483648..2147483647] and the input base is 10,
- * cutoff will be set to 214748364 and cutlim to either
- * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
- * a value > 214748364, or equal but the next digit is > 7 (or 8),
- * the number is too big, and we will return a range error.
- *
- * Set any if any `digits' consumed; make it negative to indicate
- * overflow.
- */
- cutoff = neg ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX;
- cutlim = cutoff % (unsigned long long)base;
- cutoff /= (unsigned long long)base;
- for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX;
- rptr->_errno = ERANGE;
- } else if (neg)
- acc = -acc;
- if (endptr != 0)
- *endptr = (char *) (any ? (char *)s - 1 : nptr);
- return (acc);
-}
-
-#endif /* __GNUC__ */
+/* dummy */
diff --git a/newlib/libc/stdlib/strtorx.c b/newlib/libc/stdlib/strtorx.c
index 961ecd2f2..aeeb25066 100644
--- a/newlib/libc/stdlib/strtorx.c
+++ b/newlib/libc/stdlib/strtorx.c
@@ -105,9 +105,10 @@ ULtox(__UShort *L, __ULong *bits, Long exp, int k)
int
#ifdef KR_headers
-_strtorx_r(p, s, sp, rounding, L) struct _reent *p; const char *s; char **sp; int rounding; void *L;
+_strtorx_l(p, s, sp, rounding, L, loc) struct _reent *p; const char *s; char **sp; int rounding; void *L; locale_t loc;
#else
-_strtorx_r(struct _reent *p, const char *s, char **sp, int rounding, void *L)
+_strtorx_l(struct _reent *p, const char *s, char **sp, int rounding, void *L,
+ locale_t loc)
#endif
{
static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
@@ -122,7 +123,7 @@ _strtorx_r(struct _reent *p, const char *s, char **sp, int rounding, void *L)
fpi1.rounding = rounding;
fpi = &fpi1;
}
- k = _strtodg_r(p, s, sp, fpi, &exp, bits);
+ k = _strtodg_l(p, s, sp, fpi, &exp, bits, loc);
ULtox((__UShort*)L, bits, exp, k);
return k;
}
diff --git a/newlib/libc/stdlib/strtoul.c b/newlib/libc/stdlib/strtoul.c
index 12c6834dc..062606f4e 100644
--- a/newlib/libc/stdlib/strtoul.c
+++ b/newlib/libc/stdlib/strtoul.c
@@ -1,19 +1,28 @@
/*
FUNCTION
- <<strtoul>>---string to unsigned long
+ <<strtoul>>, <<strtoul_l>>---string to unsigned long
INDEX
strtoul
+
+INDEX
+ strtoul_l
+
INDEX
_strtoul_r
ANSI_SYNOPSIS
#include <stdlib.h>
- unsigned long strtoul(const char *restrict <[s]>, char **restrict <[ptr]>,
- int <[base]>);
+ unsigned long strtoul(const char *restrict <[s]>,
+ char **restrict <[ptr]>, int <[base]>);
+
+ #include <stdlib.h>
+ unsigned long strtoul_l(const char *restrict <[s]>,
+ char **restrict <[ptr]>, int <[base]>,
+ locale_t <[locale]>);
unsigned long _strtoul_r(void *<[reent]>, const char *restrict <[s]>,
- char **restrict <[ptr]>, int <[base]>);
+ char **restrict <[ptr]>, int <[base]>);
TRAD_SYNOPSIS
#include <stdlib.h>
@@ -68,19 +77,23 @@ with a substring in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
+<<strtoul_l>> is like <<strtoul>> but performs 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 <<_strtoul_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
-
RETURNS
-<<strtoul>> returns the converted value, if any. If no conversion was
-made, <<0>> is returned.
+<<strtoul>>, <strtoul_l>> return the converted value, if any. If no
+conversion was made, <<0>> is returned.
-<<strtoul>> returns <<ULONG_MAX>> if the magnitude of the converted
-value is too large, and sets <<errno>> to <<ERANGE>>.
+<<strtoul>>, <strtoul_l>> return <<ULONG_MAX>> if the magnitude of the
+converted value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY
<<strtoul>> is ANSI.
+<<strtoul_l>> is a GNU extension.
<<strtoul>> requires no supporting OS subroutines.
*/
@@ -118,25 +131,21 @@ PORTABILITY
* SUCH DAMAGE.
*/
+#define _GNU_SOURCE
#include <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
+#include "../locale/setlocale.h"
/*
* Convert a string to an unsigned long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
*/
-unsigned long
-_DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
- struct _reent *rptr _AND
- _CONST char *__restrict nptr _AND
- char **__restrict endptr _AND
- int base)
+static unsigned long
+_strtoul_l (struct _reent *rptr, const char *__restrict nptr,
+ char **__restrict endptr, int base, locale_t loc)
{
register const unsigned char *s = (const unsigned char *)nptr;
register unsigned long acc;
@@ -149,7 +158,7 @@ _DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
*/
do {
c = *s++;
- } while (isspace(c));
+ } while (isspace_l(c, loc));
if (c == '-') {
neg = 1;
c = *s++;
@@ -166,10 +175,12 @@ _DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
+ if (c >= '0' && c <= '9')
c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
else
break;
if (c >= base)
@@ -192,15 +203,32 @@ _DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
return (acc);
}
+unsigned long
+_DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
+ struct _reent *rptr _AND
+ _CONST char *__restrict nptr _AND
+ char **__restrict endptr _AND
+ int base)
+{
+ return _strtoul_l (rptr, nptr, endptr, base, __get_current_locale ());
+}
+
#ifndef _REENT_ONLY
unsigned long
+strtoul_l (const char *__restrict s, char **__restrict ptr, int base,
+ locale_t loc)
+{
+ return _strtoul_l (_REENT, s, ptr, base, loc);
+}
+
+unsigned long
_DEFUN (strtoul, (s, ptr, base),
_CONST char *__restrict s _AND
char **__restrict ptr _AND
int base)
{
- return _strtoul_r (_REENT, s, ptr, base);
+ return _strtoul_l (_REENT, s, ptr, base, __get_current_locale ());
}
#endif
diff --git a/newlib/libc/stdlib/strtoull.c b/newlib/libc/stdlib/strtoull.c
index 13a54dbb4..ba6452e62 100644
--- a/newlib/libc/stdlib/strtoull.c
+++ b/newlib/libc/stdlib/strtoull.c
@@ -1,19 +1,26 @@
/*
FUNCTION
- <<strtoull>>---string to unsigned long long
+ <<strtoull>>, <<strtoull_l>>---string to unsigned long long
INDEX
strtoull
+
INDEX
- _strtoull_r
+ strtoull_l
ANSI_SYNOPSIS
#include <stdlib.h>
- unsigned long long strtoull(const char *restrict <[s]>, char **restrict <[ptr]>,
- int <[base]>);
+ unsigned long long strtoull(const char *restrict <[s]>,
+ char **restrict <[ptr]>, int <[base]>);
+
+ #include <stdlib.h>
+ unsigned long long strtoull_l(const char *restrict <[s]>,
+ char **restrict <[ptr]>, int <[base]>,
+ locale_t <[locale]>);
- unsigned long long _strtoull_r(void *<[reent]>, const char *restrict <[s]>,
- char **restrict <[ptr]>, int <[base]>);
+ unsigned long long _strtoull_r(void *<[reent]>,
+ const char *restrict <[s]>,
+ char **restrict <[ptr]>, int <[base]>);
TRAD_SYNOPSIS
#include <stdlib.h>
@@ -68,19 +75,23 @@ with a substring in acceptable form), no conversion
is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>).
+<<strtoull_l>> is like <<strtoull>> but performs 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 <<_strtoull_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
-
RETURNS
-<<strtoull>> returns the converted value, if any. If no conversion was
-made, <<0>> is returned.
+<<strtoull>>, <<strtoull_l>> return the converted value, if any. If no
+conversion was made, <<0>> is returned.
-<<strtoull>> returns <<ULONG_LONG_MAX>> if the magnitude of the converted
-value is too large, and sets <<errno>> to <<ERANGE>>.
+<<strtoull>>, <<strtoull_l>> return <<ULONG_LONG_MAX>> if the magnitude
+of the converted value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY
<<strtoull>> is ANSI.
+<<strtoull_l>> is a GNU extension.
<<strtoull>> requires no supporting OS subroutines.
*/
@@ -118,22 +129,104 @@ PORTABILITY
* SUCH DAMAGE.
*/
+#define _GNU_SOURCE
#include <_ansi.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
+#include "../locale/setlocale.h"
+
+/*
+ * Convert a string to an unsigned long long integer.
+ */
+static unsigned long long
+_strtoull_l (struct _reent *rptr, const char *__restrict nptr,
+ char **__restrict endptr, int base, locale_t loc)
+{
+ register const unsigned char *s = (const unsigned char *)nptr;
+ register unsigned long long acc;
+ register int c;
+ register unsigned long long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ do {
+ c = *s++;
+ } while (isspace_l(c, loc));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long long)ULONG_LONG_MAX / (unsigned long long)base;
+ cutlim = (unsigned long long)ULONG_LONG_MAX % (unsigned long long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_LONG_MAX;
+ rptr->_errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? (char *)s - 1 : nptr);
+ return (acc);
+}
+
+unsigned long long
+_DEFUN (_strtoull_r, (rptr, nptr, endptr, base),
+ struct _reent *rptr _AND
+ _CONST char *__restrict nptr _AND
+ char **__restrict endptr _AND
+ int base)
+{
+ return _strtoull_l (rptr, nptr, endptr, base, __get_current_locale ());
+}
#ifndef _REENT_ONLY
unsigned long long
+strtoull_l (const char *__restrict s, char **__restrict ptr, int base,
+ locale_t loc)
+{
+ return _strtoull_l (_REENT, s, ptr, base, loc);
+}
+
+unsigned long long
_DEFUN (strtoull, (s, ptr, base),
_CONST char *__restrict s _AND
char **__restrict ptr _AND
int base)
{
- return _strtoull_r (_REENT, s, ptr, base);
+ return _strtoull_l (_REENT, s, ptr, base, __get_current_locale ());
}
#endif
diff --git a/newlib/libc/stdlib/strtoull_r.c b/newlib/libc/stdlib/strtoull_r.c
index d0868adf2..2997587d8 100644
--- a/newlib/libc/stdlib/strtoull_r.c
+++ b/newlib/libc/stdlib/strtoull_r.c
@@ -1,120 +1 @@
-/*
- This code is based on strtoul.c which has the following copyright.
- It is used to convert a string into an unsigned long long.
-
- long long _strtoull_r (struct _reent *rptr, const char *s,
- char **ptr, int base);
-
-*/
-
-/*
- * Copyright (c) 1990 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifdef __GNUC__
-
-#define _GNU_SOURCE
-#include <_ansi.h>
-#include <limits.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <reent.h>
-
-/*
- * Convert a string to an unsigned long long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-unsigned long long
-_DEFUN (_strtoull_r, (rptr, nptr, endptr, base),
- struct _reent *rptr _AND
- _CONST char *__restrict nptr _AND
- char **__restrict endptr _AND
- int base)
-{
- register const unsigned char *s = (const unsigned char *)nptr;
- register unsigned long long acc;
- register int c;
- register unsigned long long cutoff;
- register int neg = 0, any, cutlim;
-
- /*
- * See strtol for comments as to the logic used.
- */
- do {
- c = *s++;
- } while (isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else if (c == '+')
- c = *s++;
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
- cutoff = (unsigned long long)ULONG_LONG_MAX / (unsigned long long)base;
- cutlim = (unsigned long long)ULONG_LONG_MAX % (unsigned long long)base;
- for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = ULONG_LONG_MAX;
- rptr->_errno = ERANGE;
- } else if (neg)
- acc = -acc;
- if (endptr != 0)
- *endptr = (char *) (any ? (char *)s - 1 : nptr);
- return (acc);
-}
-
-#endif /* __GNUC__ */
+/* dummy */
diff --git a/newlib/libc/stdlib/wcsnrtombs.c b/newlib/libc/stdlib/wcsnrtombs.c
index b09f7e19e..8ad8bcd2c 100644
--- a/newlib/libc/stdlib/wcsnrtombs.c
+++ b/newlib/libc/stdlib/wcsnrtombs.c
@@ -103,15 +103,11 @@ PORTABILITY
#include <stdio.h>
#include <errno.h>
#include "local.h"
+#include "../locale/setlocale.h"
size_t
-_DEFUN (_wcsnrtombs_r, (r, dst, src, nwc, len, ps),
- struct _reent *r _AND
- char *dst _AND
- const wchar_t **src _AND
- size_t nwc _AND
- size_t len _AND
- mbstate_t *ps)
+_wcsnrtombs_l (struct _reent *r, char *dst, const wchar_t **src, size_t nwc,
+ size_t len, mbstate_t *ps, locale_t loc)
{
char *ptr = dst;
char buff[10];
@@ -138,7 +134,7 @@ _DEFUN (_wcsnrtombs_r, (r, dst, src, nwc, len, ps),
{
int count = ps->__count;
wint_t wch = ps->__value.__wch;
- int bytes = __WCTOMB (r, buff, *pwcs, ps);
+ int bytes = loc->wctomb (r, buff, *pwcs, ps);
if (bytes == -1)
{
r->_errno = EILSEQ;
@@ -174,6 +170,19 @@ _DEFUN (_wcsnrtombs_r, (r, dst, src, nwc, len, ps),
return n;
}
+size_t
+_DEFUN (_wcsnrtombs_r, (r, dst, src, nwc, len, ps),
+ struct _reent *r _AND
+ char *dst _AND
+ const wchar_t **src _AND
+ size_t nwc _AND
+ size_t len _AND
+ mbstate_t *ps)
+{
+ return _wcsnrtombs_l (_REENT, dst, src, nwc, len, ps,
+ __get_current_locale ());
+}
+
#ifndef _REENT_ONLY
size_t
_DEFUN (wcsnrtombs, (dst, src, nwc, len, ps),
@@ -183,6 +192,7 @@ _DEFUN (wcsnrtombs, (dst, src, nwc, len, ps),
size_t len _AND
mbstate_t *__restrict ps)
{
- return _wcsnrtombs_r (_REENT, dst, src, nwc, len, ps);
+ return _wcsnrtombs_l (_REENT, dst, src, nwc, len, ps,
+ __get_current_locale ());
}
#endif /* !_REENT_ONLY */
diff --git a/newlib/libc/stdlib/wcstod.c b/newlib/libc/stdlib/wcstod.c
index c91ecf2fe..43f7b4eec 100644
--- a/newlib/libc/stdlib/wcstod.c
+++ b/newlib/libc/stdlib/wcstod.c
@@ -1,22 +1,48 @@
/*
FUNCTION
- <<wcstod>>, <<wcstof>>---wide char string to double or float
+ <<wcstod>>, <<wcstof>>, <<wcstold>>, <<wcstod_l>>, <<wcstof_l>>, <<wcstold_l>>---wide char string to double or float
INDEX
wcstod
-INDEX
- _wcstod_r
+
INDEX
wcstof
+
+INDEX
+ wcstold
+
+INDEX
+ wcstod_l
+
+INDEX
+ wcstof_l
+
+INDEX
+ wcstold_l
+
+INDEX
+ _wcstod_r
+
INDEX
_wcstof_r
ANSI_SYNOPSIS
#include <stdlib.h>
double wcstod(const wchar_t *__restrict <[str]>,
- wchar_t **__restrict <[tail]>);
+ wchar_t **__restrict <[tail]>);
float wcstof(const wchar_t *__restrict <[str]>,
- wchar_t **__restrict <[tail]>);
+ wchar_t **__restrict <[tail]>);
+ long double wcstold(const wchar_t *__restrict <[str]>,
+ wchar_t **__restrict <[tail]>);
+
+ #include <stdlib.h>
+ double wcstod_l(const wchar_t *__restrict <[str]>,
+ wchar_t **__restrict <[tail]>, locale_t <[locale]>);
+ float wcstof_l(const wchar_t *__restrict <[str]>,
+ wchar_t **__restrict <[tail]>, locale_t <[locale]>);
+ long double wcstold_l(const wchar_t *__restrict <[str]>,
+ wchar_t **__restrict <[tail]>,
+ locale_t <[locale]>);
double _wcstod_r(void *<[reent]>,
const wchar_t *<[str]>, wchar_t **<[tail]>);
@@ -44,11 +70,11 @@ TRAD_SYNOPSIS
wchar_t **<[tail]>;
DESCRIPTION
- The function <<wcstod>> parses the wide 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:
+ <<wcstod>>, <<wcstof>>, <<wcstold>> parse the wide-character string
+ <[str]>, producing a substring which can be converted to a double,
+ float, or long 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:
.[+|-]<[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)]
@@ -66,13 +92,18 @@ 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]>.
- <<wcstof>> is identical to <<wcstod>> 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, <<wcstof>> is currently subject to
double rounding errors.
+ <<wcstod_l>>, <<wcstof_l>>, <<wcstold_l>> are like <<wcstod>>,
+ <<wcstof>>, <<wcstold>> 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 functions <<_wcstod_r>> and <<_wcstof_r>> are
reentrant versions of <<wcstod>> and <<wcstof>>, respectively.
The extra argument <[reent]> is a pointer to a reentrancy structure.
@@ -85,6 +116,11 @@ RETURNS
stored in errno. If the correct value would cause underflow, 0
is returned and <<ERANGE>> is stored in errno.
+PORTABILITY
+<<wcstod>> is ANSI.
+<<wcstof>>, <<wcstold>> are C99.
+<<wcstod_l>>, <<wcstof_l>>, <<wcstold_l>> are GNU extensions.
+
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/
@@ -123,12 +159,11 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
#include <wctype.h>
#include <locale.h>
#include <math.h>
+#include "mprec.h"
double
-_DEFUN (_wcstod_r, (ptr, nptr, endptr),
- struct _reent *ptr _AND
- _CONST wchar_t *nptr _AND
- wchar_t **endptr)
+_wcstod_l (struct _reent *ptr, const wchar_t *nptr, wchar_t **endptr,
+ locale_t loc)
{
static const mbstate_t initial;
mbstate_t mbs;
@@ -137,7 +172,7 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
const wchar_t *wcp;
size_t len;
- while (iswspace(*nptr))
+ while (iswspace_l(*nptr, loc))
nptr++;
/*
@@ -152,7 +187,8 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
*/
wcp = nptr;
mbs = initial;
- if ((len = _wcsrtombs_r(ptr, NULL, &wcp, 0, &mbs)) == (size_t)-1) {
+ if ((len = _wcsnrtombs_l(ptr, NULL, &wcp, (size_t) -1, 0, &mbs, loc))
+ == (size_t) -1) {
if (endptr != NULL)
*endptr = (wchar_t *)nptr;
return (0.0);
@@ -160,10 +196,10 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
if ((buf = _malloc_r(ptr, len + 1)) == NULL)
return (0.0);
mbs = initial;
- _wcsrtombs_r(ptr, buf, &wcp, len + 1, &mbs);
+ _wcsnrtombs_l(ptr, buf, &wcp, (size_t) -1, len + 1, &mbs, loc);
/* Let strtod() do most of the work for us. */
- val = _strtod_r(ptr, buf, &end);
+ val = _strtod_l(ptr, buf, &end, loc);
/*
* We only know where the number ended in the _multibyte_
@@ -182,10 +218,10 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
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_r (ptr)->decimal_point);
+ len = strlen (__localeconv_l (loc)->decimal_point);
if (len > 1) {
char *d = strstr (buf,
- _localeconv_r (ptr)->decimal_point);
+ __localeconv_l (loc)->decimal_point);
if (d && d < end)
end -= len - 1;
}
@@ -197,13 +233,22 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
return (val);
}
+double
+_DEFUN (_wcstod_r, (ptr, nptr, endptr),
+ struct _reent *ptr _AND
+ _CONST wchar_t *nptr _AND
+ wchar_t **endptr)
+{
+ return _wcstod_l (ptr, nptr, endptr, __get_current_locale ());
+}
+
float
_DEFUN (_wcstof_r, (ptr, nptr, endptr),
struct _reent *ptr _AND
_CONST wchar_t *nptr _AND
wchar_t **endptr)
{
- double retval = _wcstod_r (ptr, nptr, endptr);
+ double retval = _wcstod_l (ptr, nptr, endptr, __get_current_locale ());
if (isnan (retval))
return nanf (NULL);
return (float)retval;
@@ -212,10 +257,27 @@ _DEFUN (_wcstof_r, (ptr, nptr, endptr),
#ifndef _REENT_ONLY
double
+wcstod_l (const wchar_t *__restrict nptr, wchar_t **__restrict endptr,
+ locale_t loc)
+{
+ return _wcstod_l (_REENT, nptr, endptr, loc);
+}
+
+double
_DEFUN (wcstod, (nptr, endptr),
_CONST wchar_t *__restrict nptr _AND wchar_t **__restrict endptr)
{
- return _wcstod_r (_REENT, nptr, endptr);
+ return _wcstod_l (_REENT, nptr, endptr, __get_current_locale ());
+}
+
+float
+wcstof_l (const wchar_t *__restrict nptr, wchar_t **__restrict endptr,
+ locale_t loc)
+{
+ double retval = _wcstod_l (_REENT, nptr, endptr, loc);
+ if (isnan (retval))
+ return nanf (NULL);
+ return (float)retval;
}
float
@@ -223,7 +285,7 @@ _DEFUN (wcstof, (nptr, endptr),
_CONST wchar_t *__restrict nptr _AND
wchar_t **__restrict endptr)
{
- double retval = _wcstod_r (_REENT, nptr, endptr);
+ double retval = _wcstod_l (_REENT, nptr, endptr, __get_current_locale ());
if (isnan (retval))
return nanf (NULL);
return (float)retval;
diff --git a/newlib/libc/stdlib/wcstol.c b/newlib/libc/stdlib/wcstol.c
index adda9c296..4c7480594 100644
--- a/newlib/libc/stdlib/wcstol.c
+++ b/newlib/libc/stdlib/wcstol.c
@@ -1,19 +1,28 @@
/*
FUNCTION
- <<wcstol>>---wide string to long
+ <<wcstol>>, <<wcstol_l>>---wide string to long
INDEX
wcstol
+
+INDEX
+ wcstol_l
+
INDEX
_wcstol_r
ANSI_SYNOPSIS
#include <wchar.h>
long wcstol(const wchar_t *__restrict <[s]>,
- wchar_t **__restrict <[ptr]>,int <[base]>);
+ wchar_t **__restrict <[ptr]>, int <[base]>);
- long _wcstol_r(void *<[reent]>,
- const wchar_t *<[s]>, wchar_t **<[ptr]>,int <[base]>);
+ #include <wchar.h>
+ long wcstol_l(const wchar_t *__restrict <[s]>,
+ wchar_t **__restrict <[ptr]>, int <[base]>,
+ locale_t <[locale]>);
+
+ long _wcstol_r(void *<[reent]>, const wchar_t *<[s]>,
+ wchar_t **<[ptr]>, int <[base]>);
TRAD_SYNOPSIS
#include <stdlib.h>
@@ -71,15 +80,21 @@ not <<NULL>>).
The alternate function <<_wcstol_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
+<<wcstol_l>> is like <<wcstol>> but performs 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.
+
RETURNS
-<<wcstol>> returns the converted value, if any. If no conversion was
-made, 0 is returned.
+<<wcstol>>, <<wcstol_l>> return the converted value, if any. If no
+conversion was made, 0 is returned.
-<<wcstol>> returns <<LONG_MAX>> or <<LONG_MIN>> if the magnitude of
-the converted value is too large, and sets <<errno>> to <<ERANGE>>.
+<<wcstol>>, <<wcstol_l>> return <<LONG_MAX>> or <<LONG_MIN>> if the
+magnitude of the converted value is too large, and sets <<errno>>
+to <<ERANGE>>.
PORTABILITY
<<wcstol>> is ANSI.
+<<wcstol_l>> is a GNU extension.
No supporting OS subroutines are required.
*/
@@ -124,19 +139,14 @@ No supporting OS subroutines are required.
#include <errno.h>
#include <wchar.h>
#include <reent.h>
+#include "../locale/setlocale.h"
/*
* Convert a wide string to a long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
*/
-long
-_DEFUN (_wcstol_r, (rptr, nptr, endptr, base),
- struct _reent *rptr _AND
- _CONST wchar_t *nptr _AND
- wchar_t **endptr _AND
- int base)
+static long
+_wcstol_l (struct _reent *rptr, const wchar_t *nptr, wchar_t **endptr,
+ int base, locale_t loc)
{
register const wchar_t *s = nptr;
register unsigned long acc;
@@ -151,7 +161,7 @@ _DEFUN (_wcstol_r, (rptr, nptr, endptr, base),
*/
do {
c = *s++;
- } while (iswspace(c));
+ } while (iswspace_l(c, loc));
if (c == L'-') {
neg = 1;
c = *s++;
@@ -187,10 +197,12 @@ _DEFUN (_wcstol_r, (rptr, nptr, endptr, base),
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
- if (iswdigit(c))
+ if (c >= L'0' && c <= L'9')
c -= L'0';
- else if (iswalpha(c))
- c -= iswupper(c) ? L'A' - 10 : L'a' - 10;
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= L'a' && c <= L'z')
+ c -= L'a' - 10;
else
break;
if (c >= base)
@@ -213,15 +225,32 @@ _DEFUN (_wcstol_r, (rptr, nptr, endptr, base),
return (acc);
}
+long
+_DEFUN (_wcstol_r, (rptr, nptr, endptr, base),
+ struct _reent *rptr _AND
+ _CONST wchar_t *nptr _AND
+ wchar_t **endptr _AND
+ int base)
+{
+ return _wcstol_l (rptr, nptr, endptr, base, __get_current_locale ());
+}
+
#ifndef _REENT_ONLY
long
+wcstol_l (const wchar_t *__restrict s, wchar_t **__restrict ptr, int base,
+ locale_t loc)
+{
+ return _wcstol_l (_REENT, s, ptr, base, loc);
+}
+
+long
_DEFUN (wcstol, (s, ptr, base),
_CONST wchar_t *__restrict s _AND
wchar_t **__restrict ptr _AND
int base)
{
- return _wcstol_r (_REENT, s, ptr, base);
+ return _wcstol_l (_REENT, s, ptr, base, __get_current_locale ());
}
#endif
diff --git a/newlib/libc/stdlib/wcstold.c b/newlib/libc/stdlib/wcstold.c
index e94aca919..c57def21d 100644
--- a/newlib/libc/stdlib/wcstold.c
+++ b/newlib/libc/stdlib/wcstold.c
@@ -34,13 +34,15 @@ POSSIBILITY OF SUCH DAMAGE.
#include <wctype.h>
#include <locale.h>
#include "local.h"
+#include "../locale/setlocale.h"
long double
-wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr)
+wcstold_l (const wchar_t *__restrict nptr, wchar_t **__restrict endptr,
+ locale_t loc)
{
#ifdef _LDBL_EQ_DBL
/* On platforms where long double is as wide as double. */
- return wcstod(nptr, endptr);
+ return wcstod_l(nptr, endptr, loc);
#else /* This is a duplicate of the code in wcstod.c, but converted to long double. */
@@ -57,7 +59,8 @@ wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr)
/* Convert the supplied numeric wide char string to multibyte. */
wcp = nptr;
mbs = initial;
- if ((len = wcsrtombs (NULL, &wcp, 0, &mbs)) == (size_t)-1)
+ if ((len = _wcsnrtombs_l (_REENT, NULL, &wcp, (size_t) -1, 0, &mbs, loc))
+ == (size_t) -1)
{
if (endptr != NULL)
*endptr = (wchar_t *) nptr;
@@ -68,9 +71,9 @@ wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr)
return 0.0L;
mbs = initial;
- wcsrtombs (buf, &wcp, len + 1, &mbs);
+ _wcsnrtombs_l (_REENT, buf, &wcp, (size_t) -1, len + 1, &mbs, loc);
- val = strtold (buf, &end);
+ val = strtold_l (buf, &end, loc);
/* We only know where the number ended in the _multibyte_
representation of the string. If the caller wants to know
@@ -89,10 +92,10 @@ wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr)
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);
+ len = strlen (__localeconv_l (loc)->decimal_point);
if (len > 1)
{
- char *d = strstr (buf, localeconv ()->decimal_point);
+ char *d = strstr (buf, __localeconv_l (loc)->decimal_point);
if (d && d < end)
end -= len - 1;
@@ -106,3 +109,14 @@ wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr)
return val;
#endif /* _LDBL_EQ_DBL */
}
+
+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_l(nptr, endptr, __get_current_locale ());
+#else
+ return wcstold_l(nptr, endptr, __get_current_locale ());
+#endif
+}
diff --git a/newlib/libc/stdlib/wcstoll.c b/newlib/libc/stdlib/wcstoll.c
index 2c36d6d00..2996b11a6 100644
--- a/newlib/libc/stdlib/wcstoll.c
+++ b/newlib/libc/stdlib/wcstoll.c
@@ -1,19 +1,28 @@
/*
FUNCTION
- <<wcstoll>>---wide string to long long
+ <<wcstoll>>, <<wcstoll_l>>---wide string to long long
INDEX
wcstoll
+
+INDEX
+ wcstoll_l
+
INDEX
_wcstoll_r
ANSI_SYNOPSIS
#include <wchar.h>
long long wcstoll(const wchar_t *__restrict <[s]>,
- wchar_t **__restrict <[ptr]>,int <[base]>);
+ wchar_t **__restrict <[ptr]>,int <[base]>);
- long long _wcstoll_r(void *<[reent]>,
- const wchar_t *<[s]>, wchar_t **<[ptr]>,int <[base]>);
+ #include <wchar.h>
+ long long wcstoll_l(const wchar_t *__restrict <[s]>,
+ wchar_t **__restrict <[ptr]>, int <[base]>,
+ locale_t <[locale]>);
+
+ long long _wcstoll_r(void *<[reent]>, const wchar_t *<[s]>,
+ wchar_t **<[ptr]>, int <[base]>);
TRAD_SYNOPSIS
#include <stdlib.h>
@@ -71,15 +80,21 @@ not <<NULL>>).
The alternate function <<_wcstoll_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
+<<wcstoll_l>> is like <<wcstoll>> but performs 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.
+
RETURNS
-<<wcstoll>> returns the converted value, if any. If no conversion was
-made, 0 is returned.
+<<wcstoll>>, <<wcstoll_l>> return the converted value, if any. If no
+conversion was made, 0 is returned.
-<<wcstoll>> returns <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>> if the magnitude of
-the converted value is too large, and sets <<errno>> to <<ERANGE>>.
+<<wcstoll>>, <<wcstoll_l>> return <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>>
+if the magnitude of the converted value is too large, and sets <<errno>>
+to <<ERANGE>>.
PORTABILITY
<<wcstoll>> is ANSI.
+<<wcstoll_l>> is a GNU extension.
No supporting OS subroutines are required.
*/
@@ -117,23 +132,125 @@ No supporting OS subroutines are required.
* SUCH DAMAGE.
*/
-
+#define _GNU_SOURCE
#include <_ansi.h>
#include <limits.h>
#include <wctype.h>
#include <errno.h>
#include <wchar.h>
#include <reent.h>
+#include "../locale/setlocale.h"
+
+/*
+ * Convert a wide string to a long long integer.
+ */
+long long
+_wcstoll_l (struct _reent *rptr, const wchar_t *nptr, wchar_t **endptr,
+ int base, locale_t loc)
+{
+ register const wchar_t *s = nptr;
+ register unsigned long long acc;
+ register int c;
+ register unsigned long long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (iswspace_l(c, loc));
+ if (c == L'-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == L'+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == L'0' && (*s == L'x' || *s == L'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == L'0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX;
+ cutlim = cutoff % (unsigned long long)base;
+ cutoff /= (unsigned long long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (c >= L'0' && c <= L'9')
+ c -= L'0';
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= L'a' && c <= L'z')
+ c -= L'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX;
+ rptr->_errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (wchar_t *) (any ? s - 1 : nptr);
+ return (acc);
+}
+
+long long
+_DEFUN (_wcstoll_r, (rptr, nptr, endptr, base),
+ struct _reent *rptr _AND
+ _CONST wchar_t *nptr _AND
+ wchar_t **endptr _AND
+ int base)
+{
+ return _wcstoll_l (rptr, nptr, endptr, base, __get_current_locale ());
+}
#ifndef _REENT_ONLY
long long
+wcstoll_l (const wchar_t *__restrict s, wchar_t **__restrict ptr, int base,
+ locale_t loc)
+{
+ return _wcstoll_l (_REENT, s, ptr, base, loc);
+}
+
+long long
_DEFUN (wcstoll, (s, ptr, base),
_CONST wchar_t *__restrict s _AND
wchar_t **__restrict ptr _AND
int base)
{
- return _wcstoll_r (_REENT, s, ptr, base);
+ return _wcstoll_l (_REENT, s, ptr, base, __get_current_locale ());
}
#endif
diff --git a/newlib/libc/stdlib/wcstoll_r.c b/newlib/libc/stdlib/wcstoll_r.c
index d6baacaf5..2997587d8 100644
--- a/newlib/libc/stdlib/wcstoll_r.c
+++ b/newlib/libc/stdlib/wcstoll_r.c
@@ -1,140 +1 @@
-/*
- This code is based on strtoul.c which has the following copyright.
- It is used to convert a wide string into a signed long long.
-
- long long _wcstoll_r (struct _reent *rptr, const wchar_t *s,
- wchar_t **ptr, int base);
-*/
-
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifdef __GNUC__
-
-#define _GNU_SOURCE
-#include <_ansi.h>
-#include <limits.h>
-#include <wctype.h>
-#include <errno.h>
-#include <wchar.h>
-#include <reent.h>
-
-/*
- * Convert a wide string to a long long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-long long
-_DEFUN (_wcstoll_r, (rptr, nptr, endptr, base),
- struct _reent *rptr _AND
- _CONST wchar_t *nptr _AND
- wchar_t **endptr _AND
- int base)
-{
- register const wchar_t *s = nptr;
- register unsigned long long acc;
- register int c;
- register unsigned long long cutoff;
- register int neg = 0, any, cutlim;
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- do {
- c = *s++;
- } while (iswspace(c));
- if (c == L'-') {
- neg = 1;
- c = *s++;
- } else if (c == L'+')
- c = *s++;
- if ((base == 0 || base == 16) &&
- c == L'0' && (*s == L'x' || *s == L'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == L'0' ? 8 : 10;
-
- /*
- * Compute the cutoff value between legal numbers and illegal
- * numbers. That is the largest legal value, divided by the
- * base. An input number that is greater than this value, if
- * followed by a legal input character, is too big. One that
- * is equal to this value may be valid or not; the limit
- * between valid and invalid numbers is then based on the last
- * digit. For instance, if the range for longs is
- * [-2147483648..2147483647] and the input base is 10,
- * cutoff will be set to 214748364 and cutlim to either
- * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
- * a value > 214748364, or equal but the next digit is > 7 (or 8),
- * the number is too big, and we will return a range error.
- *
- * Set any if any `digits' consumed; make it negative to indicate
- * overflow.
- */
- cutoff = neg ? -(unsigned long long)LONG_LONG_MIN : LONG_LONG_MAX;
- cutlim = cutoff % (unsigned long long)base;
- cutoff /= (unsigned long long)base;
- for (acc = 0, any = 0;; c = *s++) {
- if (iswdigit(c))
- c -= L'0';
- else if (iswalpha(c))
- c -= iswupper(c) ? L'A' - 10 : L'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = neg ? LONG_LONG_MIN : LONG_LONG_MAX;
- rptr->_errno = ERANGE;
- } else if (neg)
- acc = -acc;
- if (endptr != 0)
- *endptr = (wchar_t *) (any ? s - 1 : nptr);
- return (acc);
-}
-
-#endif /* __GNUC__ */
+/* dummy */
diff --git a/newlib/libc/stdlib/wcstoul.c b/newlib/libc/stdlib/wcstoul.c
index 4b0a95031..e87b2ecc9 100644
--- a/newlib/libc/stdlib/wcstoul.c
+++ b/newlib/libc/stdlib/wcstoul.c
@@ -1,19 +1,28 @@
/*
FUNCTION
- <<wcstoul>>---wide string to unsigned long
+ <<wcstoul>>, <<wcstoul_l>>---wide string to unsigned long
INDEX
wcstoul
+
+INDEX
+ wcstoul_l
+
INDEX
_wcstoul_r
ANSI_SYNOPSIS
#include <wchar.h>
unsigned long wcstoul(const wchar_t *__restrict <[s]>,
- wchar_t **__restrict <[ptr]>, int <[base]>);
+ wchar_t **__restrict <[ptr]>, int <[base]>);
+
+ #include <wchar.h>
+ unsigned long wcstoul_l(const wchar_t *__restrict <[s]>,
+ wchar_t **__restrict <[ptr]>, int <[base]>,
+ locale_t <[locale]>);
unsigned long _wcstoul_r(void *<[reent]>, const wchar_t *<[s]>,
- wchar_t **<[ptr]>, int <[base]>);
+ wchar_t **<[ptr]>, int <[base]>);
TRAD_SYNOPSIS
#include <wchar.h>
@@ -72,15 +81,20 @@ The alternate function <<_wcstoul_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
+<<wcstoul_l>> is like <<wcstoul>> but performs 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.
+
RETURNS
-<<wcstoul>> returns the converted value, if any. If no conversion was
-made, <<0>> is returned.
+<<wcstoul>>, <<wcstoul_l>> return the converted value, if any. If no
+conversion was made, <<0>> is returned.
-<<wcstoul>> returns <<ULONG_MAX>> if the magnitude of the converted
-value is too large, and sets <<errno>> to <<ERANGE>>.
+<<wcstoul>>, <<wcstoul_l>> return <<ULONG_MAX>> if the magnitude of the
+converted value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY
<<wcstoul>> is ANSI.
+<<wcstoul_l>> is a GNU extension.
<<wcstoul>> requires no supporting OS subroutines.
*/
@@ -125,19 +139,14 @@ PORTABILITY
#include <errno.h>
#include <stdlib.h>
#include <reent.h>
+#include "../locale/setlocale.h"
/*
* Convert a wide string to an unsigned long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
*/
unsigned long
-_DEFUN (_wcstoul_r, (rptr, nptr, endptr, base),
- struct _reent *rptr _AND
- _CONST wchar_t *nptr _AND
- wchar_t **endptr _AND
- int base)
+_wcstoul_l (struct _reent *rptr, const wchar_t *nptr, wchar_t **endptr,
+ int base, locale_t loc)
{
register const wchar_t *s = nptr;
register unsigned long acc;
@@ -150,7 +159,7 @@ _DEFUN (_wcstoul_r, (rptr, nptr, endptr, base),
*/
do {
c = *s++;
- } while (iswspace(c));
+ } while (iswspace_l(c, loc));
if (c == L'-') {
neg = 1;
c = *s++;
@@ -167,10 +176,12 @@ _DEFUN (_wcstoul_r, (rptr, nptr, endptr, base),
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
- if (iswdigit(c))
+ if (c >= L'0' && c <= L'9')
c -= L'0';
- else if (iswalpha(c))
- c -= iswupper(c) ? L'A' - 10 : L'a' - 10;
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= L'a' && c <= L'z')
+ c -= L'a' - 10;
else
break;
if (c >= base)
@@ -193,15 +204,32 @@ _DEFUN (_wcstoul_r, (rptr, nptr, endptr, base),
return (acc);
}
+unsigned long
+_DEFUN (_wcstoul_r, (rptr, nptr, endptr, base),
+ struct _reent *rptr _AND
+ _CONST wchar_t *nptr _AND
+ wchar_t **endptr _AND
+ int base)
+{
+ return _wcstoul_l (rptr, nptr, endptr, base, __get_current_locale ());
+}
+
#ifndef _REENT_ONLY
unsigned long
+wcstoul_l (const wchar_t *__restrict s, wchar_t **__restrict ptr, int base,
+ locale_t loc)
+{
+ return _wcstoul_l (_REENT, s, ptr, base, loc);
+}
+
+unsigned long
_DEFUN (wcstoul, (s, ptr, base),
_CONST wchar_t *__restrict s _AND
wchar_t **__restrict ptr _AND
int base)
{
- return _wcstoul_r (_REENT, s, ptr, base);
+ return _wcstoul_l (_REENT, s, ptr, base, __get_current_locale ());
}
#endif
diff --git a/newlib/libc/stdlib/wcstoull.c b/newlib/libc/stdlib/wcstoull.c
index 206bb3428..131a83795 100644
--- a/newlib/libc/stdlib/wcstoull.c
+++ b/newlib/libc/stdlib/wcstoull.c
@@ -1,19 +1,30 @@
/*
FUNCTION
- <<wcstoull>>---wide string to unsigned long long
+ <<wcstoull>>, <<wcstoull_l>>---wide string to unsigned long long
INDEX
wcstoull
+
+INDEX
+ wcstoull_l
+
INDEX
_wcstoull_r
ANSI_SYNOPSIS
#include <wchar.h>
unsigned long long wcstoull(const wchar_t *__restrict <[s]>,
- wchar_t **__restrict <[ptr]>, int <[base]>);
+ wchar_t **__restrict <[ptr]>,
+ int <[base]>);
+
+ #include <wchar.h>
+ unsigned long long wcstoull_l(const wchar_t *__restrict <[s]>,
+ wchar_t **__restrict <[ptr]>,
+ int <[base]>,
+ locale_t <[locale]>);
unsigned long long _wcstoull_r(void *<[reent]>, const wchar_t *<[s]>,
- wchar_t **<[ptr]>, int <[base]>);
+ wchar_t **<[ptr]>, int <[base]>);
TRAD_SYNOPSIS
#include <wchar.h>
@@ -73,18 +84,23 @@ The alternate function <<_wcstoull_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure.
+<<wcstoull_l>> is like <<wcstoull>> but performs 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.
+
RETURNS
-<<wcstoull>> returns <<0>> and sets <<errno>> to <<EINVAL>> if the value of
-<[base]> is not supported.
+<<wcstoull>>, <<wcstoull_l>> return <<0>> and sets <<errno>> to <<EINVAL>>
+if the value of <[base]> is not supported.
-<<wcstoull>> returns the converted value, if any. If no conversion was
-made, <<0>> is returned.
+<<wcstoull>>, <<wcstoull_l>> return the converted value, if any. If no
+conversion was made, <<0>> is returned.
-<<wcstoull>> returns <<ULLONG_MAX>> if the magnitude of the converted
-value is too large, and sets <<errno>> to <<ERANGE>>.
+<<wcstoull>>, <<wcstoull_l>> return <<ULLONG_MAX>> if the magnitude of
+the converted value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY
<<wcstoull>> is ANSI.
+<<wcstoull_l>> is a GNU extension.
<<wcstoull>> requires no supporting OS subroutines.
*/
@@ -122,19 +138,114 @@ PORTABILITY
* SUCH DAMAGE.
*/
+#define _GNU_SOURCE
#include <_ansi.h>
+#include <limits.h>
#include <wchar.h>
+#include <wctype.h>
+#include <errno.h>
#include <reent.h>
+#include "../locale/setlocale.h"
+
+/* Make up for older non-compliant limits.h. (This is a C99/POSIX function,
+ * and both require ULLONG_MAX in limits.h.) */
+#if !defined(ULLONG_MAX)
+# define ULLONG_MAX ULONG_LONG_MAX
+#endif
+
+/*
+ * Convert a wide string to an unsigned long long integer.
+ */
+unsigned long long
+_wcstoull_l (struct _reent *rptr, const wchar_t *nptr, wchar_t **endptr,
+ int base, locale_t loc)
+{
+ register const wchar_t *s = nptr;
+ register unsigned long long acc;
+ register int c;
+ register unsigned long long cutoff;
+ register int neg = 0, any, cutlim;
+
+ if(base < 0 || base == 1 || base > 36) {
+ rptr->_errno = EINVAL;
+ return(0ULL);
+ }
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ do {
+ c = *s++;
+ } while (iswspace_l(c, loc));
+ if (c == L'-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == L'+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == L'0' && (*s == L'x' || *s == L'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == L'0' ? 8 : 10;
+ cutoff = (unsigned long long)ULLONG_MAX / (unsigned long long)base;
+ cutlim = (unsigned long long)ULLONG_MAX % (unsigned long long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (c >= L'0' && c <= L'9')
+ c -= L'0';
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= L'a' && c <= L'z')
+ c -= L'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULLONG_MAX;
+ rptr->_errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (wchar_t *) (any ? s - 1 : nptr);
+ return (acc);
+}
+
+unsigned long long
+_DEFUN (_wcstoull_r, (rptr, nptr, endptr, base),
+ struct _reent *rptr _AND
+ _CONST wchar_t *nptr _AND
+ wchar_t **endptr _AND
+ int base)
+{
+ return _wcstoull_l (rptr, nptr, endptr, base, __get_current_locale ());
+}
#ifndef _REENT_ONLY
unsigned long long
+wcstoull_l (const wchar_t *__restrict s, wchar_t **__restrict ptr, int base,
+ locale_t loc)
+{
+ return _wcstoull_l (_REENT, s, ptr, base, loc);
+}
+
+unsigned long long
_DEFUN (wcstoull, (s, ptr, base),
_CONST wchar_t *__restrict s _AND
wchar_t **__restrict ptr _AND
int base)
{
- return _wcstoull_r (_REENT, s, ptr, base);
+ return _wcstoull_l (_REENT, s, ptr, base, __get_current_locale ());
}
#endif
diff --git a/newlib/libc/stdlib/wcstoull_r.c b/newlib/libc/stdlib/wcstoull_r.c
index abad681a3..2997587d8 100644
--- a/newlib/libc/stdlib/wcstoull_r.c
+++ b/newlib/libc/stdlib/wcstoull_r.c
@@ -1,130 +1 @@
-/*
- This code is based on wcstoul.c which has the following copyright.
- It is used to convert a wide string into an unsigned long long.
-
- unsigned long long _wcstoull_r (struct _reent *rptr, const wchar_t *s,
- wchar_t **ptr, int base);
-
-*/
-
-/*
- * Copyright (c) 1990 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifdef __GNUC__
-
-#define _GNU_SOURCE
-#include <_ansi.h>
-#include <limits.h>
-#include <wchar.h>
-#include <wctype.h>
-#include <errno.h>
-#include <reent.h>
-
-/* Make up for older non-compliant limits.h. (This is a C99/POSIX function,
- * and both require ULLONG_MAX in limits.h.) */
-#if !defined(ULLONG_MAX)
-# define ULLONG_MAX ULONG_LONG_MAX
-#endif
-
-/*
- * Convert a wide string to an unsigned long long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-unsigned long long
-_DEFUN (_wcstoull_r, (rptr, nptr, endptr, base),
- struct _reent *rptr _AND
- _CONST wchar_t *nptr _AND
- wchar_t **endptr _AND
- int base)
-{
- register const wchar_t *s = nptr;
- register unsigned long long acc;
- register int c;
- register unsigned long long cutoff;
- register int neg = 0, any, cutlim;
-
- if(base < 0 || base == 1 || base > 36) {
- rptr->_errno = EINVAL;
- return(0ULL);
- }
- /*
- * See strtol for comments as to the logic used.
- */
- do {
- c = *s++;
- } while (iswspace(c));
- if (c == L'-') {
- neg = 1;
- c = *s++;
- } else if (c == L'+')
- c = *s++;
- if ((base == 0 || base == 16) &&
- c == L'0' && (*s == L'x' || *s == L'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == L'0' ? 8 : 10;
- cutoff = (unsigned long long)ULLONG_MAX / (unsigned long long)base;
- cutlim = (unsigned long long)ULLONG_MAX % (unsigned long long)base;
- for (acc = 0, any = 0;; c = *s++) {
- if (iswdigit(c))
- c -= L'0';
- else if (iswalpha(c))
- c -= iswupper(c) ? L'A' - 10 : L'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = ULLONG_MAX;
- rptr->_errno = ERANGE;
- } else if (neg)
- acc = -acc;
- if (endptr != 0)
- *endptr = (wchar_t *) (any ? s - 1 : nptr);
- return (acc);
-}
-
-#endif /* __GNUC__ */
+/* dummy */
diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din
index 2cc826459..f945078df 100644
--- a/winsup/cygwin/common.din
+++ b/winsup/cygwin/common.din
@@ -1366,16 +1366,23 @@ strsignal SIGFE
strspn NOSIGFE
strstr NOSIGFE
strtod SIGFE
+strtod_l SIGFE
strtof SIGFE
+strtof_l SIGFE
strtoimax = strtoll NOSIGFE
strtok NOSIGFE
strtok_r NOSIGFE
strtol NOSIGFE
+strtol_l NOSIGFE
strtold SIGFE
+strtold_l SIGFE
strtoll NOSIGFE
+strtoll_l NOSIGFE
strtosigno NOSIGFE
strtoul NOSIGFE
+strtoul_l NOSIGFE
strtoull NOSIGFE
+strtoull_l NOSIGFE
strtoumax = strtoull NOSIGFE
strupr NOSIGFE
strxfrm NOSIGFE
@@ -1527,15 +1534,22 @@ wcsrtombs NOSIGFE
wcsspn NOSIGFE
wcsstr NOSIGFE
wcstod NOSIGFE
+wcstod_l NOSIGFE
wcstof NOSIGFE
+wcstof_l NOSIGFE
wcstoimax = wcstoll NOSIGFE
wcstok NOSIGFE
wcstol NOSIGFE
+wcstol_l NOSIGFE
wcstold NOSIGFE
+wcstold_l NOSIGFE
wcstoll NOSIGFE
+wcstoll_l NOSIGFE
wcstombs NOSIGFE
wcstoul NOSIGFE
+wcstoul_l NOSIGFE
wcstoull NOSIGFE
+wcstoull_l NOSIGFE
wcstoumax = wcstoull NOSIGFE
wcswidth NOSIGFE
wcsxfrm NOSIGFE
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index ee8011de8..0e00ae1a7 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -463,12 +463,15 @@ details. */
toupper_l, towctrans_l, towlower_l, towupper_l, wctrans_l, wctype_l.
300: Export strcasecmp_l, strcoll_l, strfmon_l, strftime_l, strncasecmp_l,
strxfrm_l, wcscasecmp_l, wcscoll_l, wcstrncasecmp_l, wcstrxfrm_l.
+ 301: Export 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.
Note that we forgot to bump the api for ualarm, strtoll, strtoull,
sigaltstack, sethostname. */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 300
+#define CYGWIN_VERSION_API_MINOR 301
/* There is also a compatibity version number associated with the shared memory
regions. It is incremented when incompatible changes are made to the shared
diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml
index 48499fb4e..5a1e0406c 100644
--- a/winsup/doc/posix.xml
+++ b/winsup/doc/posix.xml
@@ -1290,11 +1290,11 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
exp10l
fcloseall
fcloseall_r
- fegetprec
- fesetprec
- feenableexcept
fedisableexcept
+ feenableexcept
fegetexcept
+ fegetprec
+ fesetprec
ffsl
ffsll
fgets_unlocked
@@ -1310,9 +1310,9 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
fsetxattr
get_avphys_pages
get_current_dir_name
- get_phys_pages
get_nprocs
get_nprocs_conf
+ get_phys_pages
getmntent_r
getopt_long
getopt_long_only
@@ -1350,6 +1350,13 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
sincosf
sincosl
strchrnul
+ strtod_l
+ strtof_l
+ strtol_l
+ strtold_l
+ strtoll_l
+ strtoul_l
+ strtoull_l
sysinfo
tdestroy
timegm
@@ -1360,6 +1367,13 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
vasnprintf
vasprintf
vasprintf_r
+ wcstod_l
+ wcstof_l
+ wcstol_l
+ wcstold_l
+ wcstoll_l
+ wcstoul_l
+ wcstoull_l
</screen>
</sect1>