[newlib-cygwin] Implement strto[dflu]_l/wcsto[dflu]_l

Corinna Vinschen corinna@sourceware.org
Mon Aug 15 15:50:00 GMT 2016


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=238455adfab4f8070ac65400aac22bb8a9e502fc

commit 238455adfab4f8070ac65400aac22bb8a9e502fc
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Wed Aug 10 16:30:46 2016 +0200

    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>

Diff:
---
 newlib/libc/include/stdlib.h           |  19 +++++
 newlib/libc/include/wchar.h            |  13 +++
 newlib/libc/locale/setlocale.h         |   3 +
 newlib/libc/stdlib/gdtoa-gethex.c      |  13 +--
 newlib/libc/stdlib/mprec.h             |  12 ++-
 newlib/libc/stdlib/strtod.c            | 110 +++++++++++++++++++------
 newlib/libc/stdlib/strtodg.c           |  89 ++++++---------------
 newlib/libc/stdlib/strtol.c            |  75 ++++++++++++------
 newlib/libc/stdlib/strtold.c           |  28 ++++++-
 newlib/libc/stdlib/strtoll.c           | 137 +++++++++++++++++++++++++++++---
 newlib/libc/stdlib/strtoll_r.c         | 141 +--------------------------------
 newlib/libc/stdlib/strtorx.c           |   7 +-
 newlib/libc/stdlib/strtoul.c           |  74 +++++++++++------
 newlib/libc/stdlib/strtoull.c          | 117 ++++++++++++++++++++++++---
 newlib/libc/stdlib/strtoull_r.c        | 121 +---------------------------
 newlib/libc/stdlib/wcsnrtombs.c        |  28 ++++---
 newlib/libc/stdlib/wcstod.c            | 110 +++++++++++++++++++------
 newlib/libc/stdlib/wcstol.c            |  73 ++++++++++++-----
 newlib/libc/stdlib/wcstold.c           |  28 +++++--
 newlib/libc/stdlib/wcstoll.c           | 137 +++++++++++++++++++++++++++++---
 newlib/libc/stdlib/wcstoll_r.c         | 141 +--------------------------------
 newlib/libc/stdlib/wcstoul.c           |  68 +++++++++++-----
 newlib/libc/stdlib/wcstoull.c          | 131 +++++++++++++++++++++++++++---
 newlib/libc/stdlib/wcstoull_r.c        | 131 +-----------------------------
 winsup/cygwin/common.din               |  14 ++++
 winsup/cygwin/include/cygwin/version.h |   5 +-
 winsup/doc/posix.xml                   |  22 ++++-
 27 files changed, 1035 insertions(+), 812 deletions(-)

diff --git a/newlib/libc/include/stdlib.h b/newlib/libc/include/stdlib.h
index 3d1b8a9..7b62e00 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 4df60b4..b7f8374 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 b528ab9..de2bd67 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 3449c98..fd3903c 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 afda63e..330c398 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 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;
diff --git a/newlib/libc/stdlib/strtodg.c b/newlib/libc/stdlib/strtodg.c
index a6b3290..d8546c3 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 7273c7d..276ad13 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 1128b74..6bd1c2c 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 3ad8199..e61a62a 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 515464d..2997587 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 961ecd2..aeeb250 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 12c6834..062606f 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 13a54db..ba6452e 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 d0868ad..2997587 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 b09f7e1..8ad8bcd 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 c91ecf2..43f7b4e 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 adda9c2..4c74805 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 e94aca9..c57def2 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 2c36d6d..2996b11 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 d6baaca..2997587 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 4b0a950..e87b2ec 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 206bb34..131a837 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 abad681..2997587 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 2cc8264..f945078 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 ee8011d..0e00ae1 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 48499fb..5a1e040 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>



More information about the Cygwin-cvs mailing list