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>
This commit is contained in:
Corinna Vinschen 2016-08-10 16:30:46 +02:00
parent 5ef60b7e6a
commit 238455adfa
27 changed files with 1038 additions and 815 deletions

View File

@ -26,6 +26,10 @@
#include <cygwin/stdlib.h> #include <cygwin/stdlib.h>
#endif #endif
#if __GNU_VISIBLE
#include <sys/_locale.h>
#endif
_BEGIN_STD_C _BEGIN_STD_C
typedef struct 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,(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)); 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)); int _EXFUN(system,(const char *__string));
#if __SVID_VISIBLE || __XSI_VISIBLE >= 4 #if __SVID_VISIBLE || __XSI_VISIBLE >= 4

View File

@ -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 **)); long double _EXFUN(wcstold, (const wchar_t *, wchar_t **));
#endif #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 *)); wint_t _EXFUN(fgetwc, (__FILE *));
wchar_t *_EXFUN(fgetws, (wchar_t *__restrict, int, __FILE *__restrict)); wchar_t *_EXFUN(fgetws, (wchar_t *__restrict, int, __FILE *__restrict));
wint_t _EXFUN(fputwc, (wchar_t, __FILE *)); wint_t _EXFUN(fputwc, (wchar_t, __FILE *));

View File

@ -202,6 +202,9 @@ extern const char *__get_locale_env(struct _reent *, int);
extern struct lconv *__localeconv_l (struct __locale_t *locale); 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 /* In POSIX terms the global locale is the process-wide locale. Use this
function to always refer to the global locale. */ function to always refer to the global locale. */
_ELIDABLE_INLINE struct __locale_t * _ELIDABLE_INLINE struct __locale_t *

View File

@ -32,10 +32,10 @@ THIS SOFTWARE.
#include <_ansi.h> #include <_ansi.h>
#include <reent.h> #include <reent.h>
#include <string.h> #include <string.h>
#include <locale.h>
#include "mprec.h" #include "mprec.h"
#include "gdtoa.h" #include "gdtoa.h"
#include "gd_qnan.h" #include "gd_qnan.h"
#include "locale.h"
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && !defined(_SMALL_HEXDIG) #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && !defined(_SMALL_HEXDIG)
_CONST unsigned char __hexdig[256]= _CONST unsigned char __hexdig[256]=
@ -145,13 +145,8 @@ _DEFUN (increment, (ptr, b),
int int
_DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign), gethex (struct _reent *ptr, const char **sp, const FPI *fpi,
struct _reent *ptr _AND Long *exp, _Bigint **bp, int sign, locale_t loc)
_CONST char **sp _AND
_CONST FPI *fpi _AND
Long *exp _AND
_Bigint **bp _AND
int sign)
{ {
_Bigint *b; _Bigint *b;
_CONST unsigned char *decpt, *s0, *s, *s1; _CONST unsigned char *decpt, *s0, *s, *s1;
@ -159,7 +154,7 @@ _DEFUN(gethex, (ptr, sp, fpi, exp, bp, sign),
__ULong L, lostbits, *x; __ULong L, lostbits, *x;
Long e, e1; Long e, e1;
unsigned char *decimalpoint = (unsigned char *) unsigned char *decimalpoint = (unsigned char *)
_localeconv_r (ptr)->decimal_point; __localeconv_l (loc)->decimal_point;
size_t decp_len = strlen ((const char *) decimalpoint); size_t decp_len = strlen ((const char *) decimalpoint);
unsigned char decp_end = decimalpoint[decp_len - 1]; unsigned char decp_end = decimalpoint[decp_len - 1];

View File

@ -32,6 +32,7 @@
#include <errno.h> #include <errno.h>
#include <sys/config.h> #include <sys/config.h>
#include <sys/types.h> #include <sys/types.h>
#include "../locale/setlocale.h"
#ifdef __IEEE_LITTLE_ENDIAN #ifdef __IEEE_LITTLE_ENDIAN
#define IEEE_8087 #define IEEE_8087
@ -400,13 +401,18 @@ _Bigint * _EXFUN(lshift,(struct _reent *p, _Bigint *b, int k));
int _EXFUN(match,(const char**, char*)); int _EXFUN(match,(const char**, char*));
_Bigint * _EXFUN(diff,(struct _reent *p, _Bigint *a, _Bigint *b)); _Bigint * _EXFUN(diff,(struct _reent *p, _Bigint *a, _Bigint *b));
int _EXFUN(cmp,(_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)); double _EXFUN(ratio,(_Bigint *a, _Bigint *b));
__ULong _EXFUN(any_on,(_Bigint *b, int k)); __ULong _EXFUN(any_on,(_Bigint *b, int k));
void _EXFUN(copybits,(__ULong *c, int n, _Bigint *b)); 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) #if defined (_HAVE_LONG_DOUBLE) && !defined (_LDBL_EQ_DBL)
int _EXFUN(_strtorx_r,(struct _reent *, _CONST char *, char **, int, void *)); int _strtorx_l (struct _reent *, const char *, char **, int,
int _EXFUN(_strtodg_r,(struct _reent *p, _CONST char *s00, char **se, struct FPI *fpi, Long *exp, __ULong *bits)); 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 */ #endif /* _HAVE_LONG_DOUBLE && !_LDBL_EQ_DBL */
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) || defined(_SMALL_HEXDIG) #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) || defined(_SMALL_HEXDIG)

View File

@ -1,18 +1,43 @@
/* /*
FUNCTION FUNCTION
<<strtod>>, <<strtof>>---string to double or float <<strtod>>, <<strtof>>, <<strtold>>, <<strtod_l>>, <<strtof_l>>, <<strtold_l>>---string to double or float
INDEX INDEX
strtod strtod
INDEX
_strtod_r
INDEX INDEX
strtof strtof
INDEX
strtold
INDEX
strtod_l
INDEX
strtof_l
INDEX
strtold_l
INDEX
_strtod_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <stdlib.h> #include <stdlib.h>
double strtod(const char *restrict <[str]>, char **restrict <[tail]>); double strtod(const char *restrict <[str]>, char **restrict <[tail]>);
float strtof(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]>, double _strtod_r(void *<[reent]>,
const char *restrict <[str]>, char **restrict <[tail]>); const char *restrict <[str]>, char **restrict <[tail]>);
@ -33,11 +58,11 @@ TRAD_SYNOPSIS
char **<[tail]>; char **<[tail]>;
DESCRIPTION DESCRIPTION
The function <<strtod>> parses the character string <[str]>, <<strtod>>, <<strtof>>, <<strtold>> parse the character string
producing a substring which can be converted to a double <[str]>, producing a substring which can be converted to a double,
value. The substring converted is the longest initial float, or long double value, respectively. The substring converted
subsequence of <[str]>, beginning with the first is the longest initial subsequence of <[str]>, beginning with the
non-whitespace character, that has one of these formats: first non-whitespace character, that has one of these formats:
.[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>] .[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[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)] .[+|-](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 (which will contain at least the terminating null character of
<[str]>) is stored in <<*<[tail]>>>. If you want no <[str]>) is stored in <<*<[tail]>>>. If you want no
assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>. 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 This implementation returns the nearest machine number to the
input decimal string. Ties are broken by using the IEEE input decimal string. Ties are broken by using the IEEE
round-even rule. However, <<strtof>> is currently subject to round-even rule. However, <<strtof>> is currently subject to
double rounding errors. 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 alternate function <<_strtod_r>> is a reentrant version.
The extra argument <[reent]> is a pointer to a reentrancy structure. The extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS RETURNS
<<strtod>> returns the converted substring value, if any. If These functions return the converted substring value, if any. If
no conversion could be performed, 0 is returned. If the no conversion could be performed, 0 is returned. If the correct
correct value is out of the range of representable values, value is out of the range of representable values, plus or minus
plus or minus <<HUGE_VAL>> is returned, and <<ERANGE>> is <<HUGE_VAL>> (<<HUGE_VALF>>, <<HUGE_VALL>>) is returned, and
stored in errno. If the correct value would cause underflow, 0 <<ERANGE>> is stored in errno. If the correct value would cause
is returned and <<ERANGE>> is stored in errno. 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>>, Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>. <<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. */ /* Original file gdtoa-strtod.c Modified 06-21-2006 by Jeff Johnston to work within newlib. */
#define _GNU_SOURCE
#include <_ansi.h> #include <_ansi.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
@ -117,6 +153,7 @@ THIS SOFTWARE.
#include "mprec.h" #include "mprec.h"
#include "gdtoa.h" #include "gdtoa.h"
#include "gd_qnan.h" #include "gd_qnan.h"
#include "../locale/setlocale.h"
/* #ifndef NO_FENV_H */ /* #ifndef NO_FENV_H */
/* #include <fenv.h> */ /* #include <fenv.h> */
@ -213,10 +250,8 @@ _DEFUN (ULtod, (L, bits, exp, k),
#endif /* !NO_HEX_FP */ #endif /* !NO_HEX_FP */
double double
_DEFUN (_strtod_r, (ptr, s00, se), _strtod_l (struct _reent *ptr, const char *__restrict s00, char **__restrict se,
struct _reent *ptr _AND locale_t loc)
_CONST char *__restrict s00 _AND
char **__restrict se)
{ {
#ifdef Avoid_Underflow #ifdef Avoid_Underflow
int scale; int scale;
@ -238,6 +273,8 @@ _DEFUN (_strtod_r, (ptr, s00, se),
#ifdef Honor_FLT_ROUNDS #ifdef Honor_FLT_ROUNDS
int rounding; int rounding;
#endif #endif
struct lconv *lconv = __localeconv_l (loc);
int dec_len = strlen (lconv->decimal_point);
delta = bs = bd = NULL; delta = bs = bd = NULL;
sign = nz0 = nz = decpt = 0; sign = nz0 = nz = decpt = 0;
@ -286,7 +323,7 @@ _DEFUN (_strtod_r, (ptr, s00, se),
#else #else
#define fpi1 fpi #define fpi1 fpi
#endif #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: case STRTOG_NoNumber:
s = s00; s = s00;
sign = 0; sign = 0;
@ -317,11 +354,10 @@ _DEFUN (_strtod_r, (ptr, s00, se),
else else
z = 10*z + c - '0'; z = 10*z + c - '0';
nd0 = nd; nd0 = nd;
if (strncmp (s, _localeconv_r (ptr)->decimal_point, if (strncmp (s, lconv->decimal_point, dec_len) == 0)
strlen (_localeconv_r (ptr)->decimal_point)) == 0)
{ {
decpt = 1; decpt = 1;
c = *(s += strlen (_localeconv_r (ptr)->decimal_point)); c = *(s += dec_len);
if (!nd) { if (!nd) {
for(; c == '0'; c = *++s) for(; c == '0'; c = *++s)
nz++; nz++;
@ -1230,13 +1266,37 @@ _DEFUN (_strtod_r, (ptr, s00, se),
return sign ? -dval(rv) : dval(rv); 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 #ifndef _REENT_ONLY
double
strtod_l (const char *__restrict s00, char **__restrict se, locale_t loc)
{
return _strtod_l (_REENT, s00, se, loc);
}
double double
_DEFUN (strtod, (s00, se), _DEFUN (strtod, (s00, se),
_CONST char *__restrict s00 _AND char **__restrict 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 float
@ -1244,7 +1304,7 @@ _DEFUN (strtof, (s00, se),
_CONST char *__restrict s00 _AND _CONST char *__restrict s00 _AND
char **__restrict se) char **__restrict se)
{ {
double retval = _strtod_r (_REENT, s00, se); double retval = _strtod_l (_REENT, s00, se, __get_current_locale ());
if (isnan (retval)) if (isnan (retval))
return nanf (NULL); return nanf (NULL);
return (float)retval; return (float)retval;

View File

@ -53,11 +53,7 @@ fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21,
}; };
static _Bigint * static _Bigint *
#ifdef KR_headers sum (struct _reent *p, _Bigint *a, _Bigint *b)
sum(p, a, b) struct _reent *p; _Bigint *a; _Bigint *b;
#else
sum(struct _reent *p, _Bigint *a, _Bigint *b)
#endif
{ {
_Bigint *c; _Bigint *c;
__ULong carry, *xc, *xa, *xb, *xe, y; __ULong carry, *xc, *xa, *xb, *xe, y;
@ -119,11 +115,7 @@ sum(struct _reent *p, _Bigint *a, _Bigint *b)
} }
static void static void
#ifdef KR_headers rshift (_Bigint *b, int k)
rshift(b, k) _Bigint *b; int k;
#else
rshift(_Bigint *b, int k)
#endif
{ {
__ULong *x, *x1, *xe, y; __ULong *x, *x1, *xe, y;
int n; int n;
@ -152,11 +144,7 @@ rshift(_Bigint *b, int k)
} }
static int static int
#ifdef KR_headers trailz (_Bigint *b)
trailz(b) _Bigint *b;
#else
trailz(_Bigint *b)
#endif
{ {
__ULong L, *x, *xe; __ULong L, *x, *xe;
int n = 0; int n = 0;
@ -172,12 +160,8 @@ trailz(_Bigint *b)
return n; return n;
} }
_Bigint * _Bigint *
#ifdef KR_headers increment (struct _reent *p, _Bigint *b)
increment(p, b) struct _reent *p; _Bigint *b;
#else
increment(struct _reent *p, _Bigint *b)
#endif
{ {
__ULong *x, *xe; __ULong *x, *xe;
_Bigint *b1; _Bigint *b1;
@ -217,12 +201,8 @@ increment(struct _reent *p, _Bigint *b)
return b; return b;
} }
int int
#ifdef KR_headers decrement (_Bigint *b)
decrement(b) _Bigint *b;
#else
decrement(_Bigint *b)
#endif
{ {
__ULong *x, *xe; __ULong *x, *xe;
#ifdef Pack_16 #ifdef Pack_16
@ -250,12 +230,8 @@ decrement(_Bigint *b)
return STRTOG_Inexlo; return STRTOG_Inexlo;
} }
static int static int
#ifdef KR_headers all_on (_Bigint *b, int n)
all_on(b, n) _Bigint *b; int n;
#else
all_on(_Bigint *b, int n)
#endif
{ {
__ULong *x, *xe; __ULong *x, *xe;
@ -269,12 +245,8 @@ all_on(_Bigint *b, int n)
return 1; return 1;
} }
_Bigint * _Bigint *
#ifdef KR_headers set_ones (struct _reent *p, _Bigint *b, int n)
set_ones(p, b, n) struct _reent *p; _Bigint *b; int n;
#else
set_ones(struct _reent *p, _Bigint *b, int n)
#endif
{ {
int k; int k;
__ULong *x, *xe; __ULong *x, *xe;
@ -297,14 +269,9 @@ set_ones(struct _reent *p, _Bigint *b, int n)
return b; return b;
} }
static int static int
rvOK rvOK (struct _reent *p, double d, FPI *fpi, Long *exp, __ULong *bits, int exact,
#ifdef KR_headers int rd, int *irv)
(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
{ {
_Bigint *b; _Bigint *b;
__ULong carry, inex, lostbits; __ULong carry, inex, lostbits;
@ -418,12 +385,8 @@ rvOK
return rv; return rv;
} }
static int static int
#ifdef KR_headers mantbits (U d)
mantbits(d) double d;
#else
mantbits(U d)
#endif
{ {
__ULong L; __ULong L;
#ifdef VAX #ifdef VAX
@ -441,14 +404,9 @@ mantbits(U d)
return P - 32 - lo0bits(&L); return P - 32 - lo0bits(&L);
} }
int int
_strtodg_r _strtodg_l (struct _reent *p, const char *s00, char **se, FPI *fpi, Long *exp,
#ifdef KR_headers __ULong *bits, locale_t loc)
(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 abe, abits, asub; int abe, abits, asub;
int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm; int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm;
@ -462,6 +420,8 @@ _strtodg_r
Long L; Long L;
__ULong y, z; __ULong y, z;
_Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; _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; irv = STRTOG_Zero;
denorm = sign = nz0 = nz = 0; denorm = sign = nz0 = nz = 0;
@ -497,7 +457,7 @@ _strtodg_r
switch(s[1]) { switch(s[1]) {
case 'x': case 'x':
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) { if (irv == STRTOG_NoNumber) {
s = s00; s = s00;
sign = 0; sign = 0;
@ -520,15 +480,14 @@ _strtodg_r
z = 10*z + c - '0'; z = 10*z + c - '0';
nd0 = nd; nd0 = nd;
#ifdef USE_LOCALE #ifdef USE_LOCALE
if (strncmp (s, _localeconv_r (p)->decimal_point, if (strncmp (s, lconv->decimal_point, dec_len) == 0)
strlen (_localeconv_r (p)->decimal_point)) == 0)
#else #else
if (c == '.') if (c == '.')
#endif #endif
{ {
decpt = 1; decpt = 1;
#ifdef USE_LOCALE #ifdef USE_LOCALE
c = *(s += strlen (_localeconv_r (p)->decimal_point)); c = *(s += dec_len);
#else #else
c = *++s; c = *++s;
#endif #endif

View File

@ -1,18 +1,27 @@
/* /*
FUNCTION FUNCTION
<<strtol>>---string to long <<strtol>>, <<strtol_l>>---string to long
INDEX INDEX
strtol strtol
INDEX
strtol_l
INDEX INDEX
_strtol_r _strtol_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <stdlib.h> #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]>, #include <stdlib.h>
const char *restrict <[s]>, char **restrict <[ptr]>,int <[base]>); 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 TRAD_SYNOPSIS
#include <stdlib.h> #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 is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>). 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 The alternate function <<_strtol_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure. extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS RETURNS
<<strtol>> returns the converted value, if any. If no conversion was <<strtol>>, <<strtol_l>> return the converted value, if any. If no
made, 0 is returned. conversion was made, 0 is returned.
<<strtol>> returns <<LONG_MAX>> or <<LONG_MIN>> if the magnitude of <<strtol>>, <<strtol_l>> return <<LONG_MAX>> or <<LONG_MIN>> if the
the converted value is too large, and sets <<errno>> to <<ERANGE>>. magnitude of the converted value is too large, and sets <<errno>>
to <<ERANGE>>.
PORTABILITY PORTABILITY
<<strtol>> is ANSI. <<strtol>> is ANSI.
<<strtol_l>> is a GNU extension.
No supporting OS subroutines are required. No supporting OS subroutines are required.
*/ */
@ -116,26 +131,21 @@ No supporting OS subroutines are required.
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#define _GNU_SOURCE
#include <_ansi.h> #include <_ansi.h>
#include <limits.h> #include <limits.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <reent.h> #include <reent.h>
#include "../locale/setlocale.h"
/* /*
* Convert a string to a long integer. * Convert a string to a long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/ */
long static long
_DEFUN (_strtol_r, (rptr, nptr, endptr, base), _strtol_l (struct _reent *rptr, const char *__restrict nptr,
struct _reent *rptr _AND char **__restrict endptr, int base, locale_t loc)
_CONST char *__restrict nptr _AND
char **__restrict endptr _AND
int base)
{ {
register const unsigned char *s = (const unsigned char *)nptr; register const unsigned char *s = (const unsigned char *)nptr;
register unsigned long acc; register unsigned long acc;
@ -150,7 +160,7 @@ _DEFUN (_strtol_r, (rptr, nptr, endptr, base),
*/ */
do { do {
c = *s++; c = *s++;
} while (isspace(c)); } while (isspace_l(c, loc));
if (c == '-') { if (c == '-') {
neg = 1; neg = 1;
c = *s++; c = *s++;
@ -186,10 +196,12 @@ _DEFUN (_strtol_r, (rptr, nptr, endptr, base),
cutlim = cutoff % (unsigned long)base; cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base; cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) { for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c)) if (c >= '0' && c <= '9')
c -= '0'; c -= '0';
else if (isalpha(c)) else if (c >= 'A' && c <= 'Z')
c -= isupper(c) ? 'A' - 10 : 'a' - 10; c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else else
break; break;
if (c >= base) if (c >= base)
@ -212,15 +224,32 @@ _DEFUN (_strtol_r, (rptr, nptr, endptr, base),
return (acc); 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 #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 long
_DEFUN (strtol, (s, ptr, base), _DEFUN (strtol, (s, ptr, base),
_CONST char *__restrict s _AND _CONST char *__restrict s _AND
char **__restrict ptr _AND char **__restrict ptr _AND
int base) int base)
{ {
return _strtol_r (_REENT, s, ptr, base); return _strtol_l (_REENT, s, ptr, base, __get_current_locale ());
} }
#endif #endif

View File

@ -64,11 +64,25 @@ _strtold_r (struct _reent *ptr, const char *__restrict s00,
{ {
#ifdef _LDBL_EQ_DBL #ifdef _LDBL_EQ_DBL
/* On platforms where long double is as wide as double. */ /* 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 #else
long double result; 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; return result;
#endif #endif
} }
@ -76,7 +90,15 @@ _strtold_r (struct _reent *ptr, const char *__restrict s00,
long double long double
strtold (const char *__restrict s00, char **__restrict se) 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 */ #endif /* _HAVE_LONG_DOUBLE */

View File

@ -1,18 +1,29 @@
/* /*
FUNCTION FUNCTION
<<strtoll>>---string to long long <<strtoll>>, <<strtoll_l>>---string to long long
INDEX INDEX
strtoll strtoll
INDEX
strtoll_l
INDEX INDEX
_strtoll_r _strtoll_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <stdlib.h> #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]>, 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 TRAD_SYNOPSIS
#include <stdlib.h> #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 is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>). 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 The alternate function <<_strtoll_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure. extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS RETURNS
<<strtoll>> returns the converted value, if any. If no conversion was <<strtoll>>, <<strtoll_l>> return the converted value, if any. If no
made, 0 is returned. conversion was made, 0 is returned.
<<strtoll>> returns <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>> if the magnitude of <<strtoll>>, <<strtoll_l>> return <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>>
the converted value is too large, and sets <<errno>> to <<ERANGE>>. if the magnitude of the converted value is too large, and sets <<errno>>
to <<ERANGE>>.
PORTABILITY PORTABILITY
<<strtoll>> is ANSI. <<strtoll>> is ANSI.
<<strtoll_l>> is a GNU extension.
No supporting OS subroutines are required. No supporting OS subroutines are required.
*/ */
@ -116,23 +133,125 @@ No supporting OS subroutines are required.
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#define _GNU_SOURCE
#include <_ansi.h> #include <_ansi.h>
#include <limits.h> #include <limits.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <reent.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 #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 long long
_DEFUN (strtoll, (s, ptr, base), _DEFUN (strtoll, (s, ptr, base),
_CONST char *__restrict s _AND _CONST char *__restrict s _AND
char **__restrict ptr _AND char **__restrict ptr _AND
int base) int base)
{ {
return _strtoll_r (_REENT, s, ptr, base); return _strtoll_l (_REENT, s, ptr, base, __get_current_locale ());
} }
#endif #endif

View File

@ -1,140 +1 @@
/* /* dummy */
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__ */

View File

@ -105,9 +105,10 @@ ULtox(__UShort *L, __ULong *bits, Long exp, int k)
int int
#ifdef KR_headers #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 #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 #endif
{ {
static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI }; 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; fpi1.rounding = rounding;
fpi = &fpi1; 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); ULtox((__UShort*)L, bits, exp, k);
return k; return k;
} }

View File

@ -1,19 +1,28 @@
/* /*
FUNCTION FUNCTION
<<strtoul>>---string to unsigned long <<strtoul>>, <<strtoul_l>>---string to unsigned long
INDEX INDEX
strtoul strtoul
INDEX
strtoul_l
INDEX INDEX
_strtoul_r _strtoul_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <stdlib.h> #include <stdlib.h>
unsigned long strtoul(const char *restrict <[s]>, char **restrict <[ptr]>, unsigned long strtoul(const char *restrict <[s]>,
int <[base]>); 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]>, unsigned long _strtoul_r(void *<[reent]>, const char *restrict <[s]>,
char **restrict <[ptr]>, int <[base]>); char **restrict <[ptr]>, int <[base]>);
TRAD_SYNOPSIS TRAD_SYNOPSIS
#include <stdlib.h> #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 is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>). 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 The alternate function <<_strtoul_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure. extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS RETURNS
<<strtoul>> returns the converted value, if any. If no conversion was <<strtoul>>, <strtoul_l>> return the converted value, if any. If no
made, <<0>> is returned. conversion was made, <<0>> is returned.
<<strtoul>> returns <<ULONG_MAX>> if the magnitude of the converted <<strtoul>>, <strtoul_l>> return <<ULONG_MAX>> if the magnitude of the
value is too large, and sets <<errno>> to <<ERANGE>>. converted value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY PORTABILITY
<<strtoul>> is ANSI. <<strtoul>> is ANSI.
<<strtoul_l>> is a GNU extension.
<<strtoul>> requires no supporting OS subroutines. <<strtoul>> requires no supporting OS subroutines.
*/ */
@ -118,25 +131,21 @@ PORTABILITY
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#define _GNU_SOURCE
#include <_ansi.h> #include <_ansi.h>
#include <limits.h> #include <limits.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <reent.h> #include <reent.h>
#include "../locale/setlocale.h"
/* /*
* Convert a string to an unsigned long integer. * 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 static unsigned long
_DEFUN (_strtoul_r, (rptr, nptr, endptr, base), _strtoul_l (struct _reent *rptr, const char *__restrict nptr,
struct _reent *rptr _AND char **__restrict endptr, int base, locale_t loc)
_CONST char *__restrict nptr _AND
char **__restrict endptr _AND
int base)
{ {
register const unsigned char *s = (const unsigned char *)nptr; register const unsigned char *s = (const unsigned char *)nptr;
register unsigned long acc; register unsigned long acc;
@ -149,7 +158,7 @@ _DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
*/ */
do { do {
c = *s++; c = *s++;
} while (isspace(c)); } while (isspace_l(c, loc));
if (c == '-') { if (c == '-') {
neg = 1; neg = 1;
c = *s++; c = *s++;
@ -166,10 +175,12 @@ _DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) { for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c)) if (c >= '0' && c <= '9')
c -= '0'; c -= '0';
else if (isalpha(c)) else if (c >= 'A' && c <= 'Z')
c -= isupper(c) ? 'A' - 10 : 'a' - 10; c -= 'A' - 10;
else if (c >= 'a' && c <= 'z')
c -= 'a' - 10;
else else
break; break;
if (c >= base) if (c >= base)
@ -192,15 +203,32 @@ _DEFUN (_strtoul_r, (rptr, nptr, endptr, base),
return (acc); 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 #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 unsigned long
_DEFUN (strtoul, (s, ptr, base), _DEFUN (strtoul, (s, ptr, base),
_CONST char *__restrict s _AND _CONST char *__restrict s _AND
char **__restrict ptr _AND char **__restrict ptr _AND
int base) int base)
{ {
return _strtoul_r (_REENT, s, ptr, base); return _strtoul_l (_REENT, s, ptr, base, __get_current_locale ());
} }
#endif #endif

View File

@ -1,19 +1,26 @@
/* /*
FUNCTION FUNCTION
<<strtoull>>---string to unsigned long long <<strtoull>>, <<strtoull_l>>---string to unsigned long long
INDEX INDEX
strtoull strtoull
INDEX INDEX
_strtoull_r strtoull_l
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <stdlib.h> #include <stdlib.h>
unsigned long long strtoull(const char *restrict <[s]>, char **restrict <[ptr]>, unsigned long long strtoull(const char *restrict <[s]>,
int <[base]>); char **restrict <[ptr]>, int <[base]>);
unsigned long long _strtoull_r(void *<[reent]>, const char *restrict <[s]>, #include <stdlib.h>
char **restrict <[ptr]>, int <[base]>); 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]>);
TRAD_SYNOPSIS TRAD_SYNOPSIS
#include <stdlib.h> #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 is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is
not <<NULL>>). 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 The alternate function <<_strtoull_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure. extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS RETURNS
<<strtoull>> returns the converted value, if any. If no conversion was <<strtoull>>, <<strtoull_l>> return the converted value, if any. If no
made, <<0>> is returned. conversion was made, <<0>> is returned.
<<strtoull>> returns <<ULONG_LONG_MAX>> if the magnitude of the converted <<strtoull>>, <<strtoull_l>> return <<ULONG_LONG_MAX>> if the magnitude
value is too large, and sets <<errno>> to <<ERANGE>>. of the converted value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY PORTABILITY
<<strtoull>> is ANSI. <<strtoull>> is ANSI.
<<strtoull_l>> is a GNU extension.
<<strtoull>> requires no supporting OS subroutines. <<strtoull>> requires no supporting OS subroutines.
*/ */
@ -118,22 +129,104 @@ PORTABILITY
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#define _GNU_SOURCE
#include <_ansi.h> #include <_ansi.h>
#include <limits.h> #include <limits.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <reent.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 #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 unsigned long long
_DEFUN (strtoull, (s, ptr, base), _DEFUN (strtoull, (s, ptr, base),
_CONST char *__restrict s _AND _CONST char *__restrict s _AND
char **__restrict ptr _AND char **__restrict ptr _AND
int base) int base)
{ {
return _strtoull_r (_REENT, s, ptr, base); return _strtoull_l (_REENT, s, ptr, base, __get_current_locale ());
} }
#endif #endif

View File

@ -1,120 +1 @@
/* /* dummy */
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__ */

View File

@ -103,15 +103,11 @@ PORTABILITY
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include "local.h" #include "local.h"
#include "../locale/setlocale.h"
size_t size_t
_DEFUN (_wcsnrtombs_r, (r, dst, src, nwc, len, ps), _wcsnrtombs_l (struct _reent *r, char *dst, const wchar_t **src, size_t nwc,
struct _reent *r _AND size_t len, mbstate_t *ps, locale_t loc)
char *dst _AND
const wchar_t **src _AND
size_t nwc _AND
size_t len _AND
mbstate_t *ps)
{ {
char *ptr = dst; char *ptr = dst;
char buff[10]; char buff[10];
@ -138,7 +134,7 @@ _DEFUN (_wcsnrtombs_r, (r, dst, src, nwc, len, ps),
{ {
int count = ps->__count; int count = ps->__count;
wint_t wch = ps->__value.__wch; wint_t wch = ps->__value.__wch;
int bytes = __WCTOMB (r, buff, *pwcs, ps); int bytes = loc->wctomb (r, buff, *pwcs, ps);
if (bytes == -1) if (bytes == -1)
{ {
r->_errno = EILSEQ; r->_errno = EILSEQ;
@ -174,6 +170,19 @@ _DEFUN (_wcsnrtombs_r, (r, dst, src, nwc, len, ps),
return n; 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 #ifndef _REENT_ONLY
size_t size_t
_DEFUN (wcsnrtombs, (dst, src, nwc, len, ps), _DEFUN (wcsnrtombs, (dst, src, nwc, len, ps),
@ -183,6 +192,7 @@ _DEFUN (wcsnrtombs, (dst, src, nwc, len, ps),
size_t len _AND size_t len _AND
mbstate_t *__restrict ps) 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 */ #endif /* !_REENT_ONLY */

View File

@ -1,22 +1,48 @@
/* /*
FUNCTION 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 INDEX
wcstod wcstod
INDEX
_wcstod_r
INDEX INDEX
wcstof wcstof
INDEX
wcstold
INDEX
wcstod_l
INDEX
wcstof_l
INDEX
wcstold_l
INDEX
_wcstod_r
INDEX INDEX
_wcstof_r _wcstof_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <stdlib.h> #include <stdlib.h>
double wcstod(const wchar_t *__restrict <[str]>, double wcstod(const wchar_t *__restrict <[str]>,
wchar_t **__restrict <[tail]>); wchar_t **__restrict <[tail]>);
float wcstof(const wchar_t *__restrict <[str]>, 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]>, double _wcstod_r(void *<[reent]>,
const wchar_t *<[str]>, wchar_t **<[tail]>); const wchar_t *<[str]>, wchar_t **<[tail]>);
@ -44,11 +70,11 @@ TRAD_SYNOPSIS
wchar_t **<[tail]>; wchar_t **<[tail]>;
DESCRIPTION DESCRIPTION
The function <<wcstod>> parses the wide character string <[str]>, <<wcstod>>, <<wcstof>>, <<wcstold>> parse the wide-character string
producing a substring which can be converted to a double <[str]>, producing a substring which can be converted to a double,
value. The substring converted is the longest initial float, or long double value. The substring converted is the longest
subsequence of <[str]>, beginning with the first initial subsequence of <[str]>, beginning with the first non-whitespace
non-whitespace character, that has one of these formats: character, that has one of these formats:
.[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>] .[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[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)] .[+|-](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 (which will contain at least the terminating null character of
<[str]>) is stored in <<*<[tail]>>>. If you want no <[str]>) is stored in <<*<[tail]>>>. If you want no
assignment to <<*<[tail]>>>, pass a null pointer as <[tail]>. 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 This implementation returns the nearest machine number to the
input decimal string. Ties are broken by using the IEEE input decimal string. Ties are broken by using the IEEE
round-even rule. However, <<wcstof>> is currently subject to round-even rule. However, <<wcstof>> is currently subject to
double rounding errors. 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 The alternate functions <<_wcstod_r>> and <<_wcstof_r>> are
reentrant versions of <<wcstod>> and <<wcstof>>, respectively. reentrant versions of <<wcstod>> and <<wcstof>>, respectively.
The extra argument <[reent]> is a pointer to a reentrancy structure. 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 stored in errno. If the correct value would cause underflow, 0
is returned and <<ERANGE>> is stored in errno. 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>>, Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>. <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
*/ */
@ -123,12 +159,11 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
#include <wctype.h> #include <wctype.h>
#include <locale.h> #include <locale.h>
#include <math.h> #include <math.h>
#include "mprec.h"
double double
_DEFUN (_wcstod_r, (ptr, nptr, endptr), _wcstod_l (struct _reent *ptr, const wchar_t *nptr, wchar_t **endptr,
struct _reent *ptr _AND locale_t loc)
_CONST wchar_t *nptr _AND
wchar_t **endptr)
{ {
static const mbstate_t initial; static const mbstate_t initial;
mbstate_t mbs; mbstate_t mbs;
@ -137,7 +172,7 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
const wchar_t *wcp; const wchar_t *wcp;
size_t len; size_t len;
while (iswspace(*nptr)) while (iswspace_l(*nptr, loc))
nptr++; nptr++;
/* /*
@ -152,7 +187,8 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
*/ */
wcp = nptr; wcp = nptr;
mbs = initial; 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) if (endptr != NULL)
*endptr = (wchar_t *)nptr; *endptr = (wchar_t *)nptr;
return (0.0); return (0.0);
@ -160,10 +196,10 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
if ((buf = _malloc_r(ptr, len + 1)) == NULL) if ((buf = _malloc_r(ptr, len + 1)) == NULL)
return (0.0); return (0.0);
mbs = initial; 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. */ /* 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_ * 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) just one byte long. The resulting difference (end - buf)
is then equivalent to the number of valid wide characters is then equivalent to the number of valid wide characters
in the input string. */ in the input string. */
len = strlen (_localeconv_r (ptr)->decimal_point); len = strlen (__localeconv_l (loc)->decimal_point);
if (len > 1) { if (len > 1) {
char *d = strstr (buf, char *d = strstr (buf,
_localeconv_r (ptr)->decimal_point); __localeconv_l (loc)->decimal_point);
if (d && d < end) if (d && d < end)
end -= len - 1; end -= len - 1;
} }
@ -197,13 +233,22 @@ _DEFUN (_wcstod_r, (ptr, nptr, endptr),
return (val); 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 float
_DEFUN (_wcstof_r, (ptr, nptr, endptr), _DEFUN (_wcstof_r, (ptr, nptr, endptr),
struct _reent *ptr _AND struct _reent *ptr _AND
_CONST wchar_t *nptr _AND _CONST wchar_t *nptr _AND
wchar_t **endptr) wchar_t **endptr)
{ {
double retval = _wcstod_r (ptr, nptr, endptr); double retval = _wcstod_l (ptr, nptr, endptr, __get_current_locale ());
if (isnan (retval)) if (isnan (retval))
return nanf (NULL); return nanf (NULL);
return (float)retval; return (float)retval;
@ -211,11 +256,28 @@ _DEFUN (_wcstof_r, (ptr, nptr, endptr),
#ifndef _REENT_ONLY #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 double
_DEFUN (wcstod, (nptr, endptr), _DEFUN (wcstod, (nptr, endptr),
_CONST wchar_t *__restrict nptr _AND wchar_t **__restrict 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 float
@ -223,7 +285,7 @@ _DEFUN (wcstof, (nptr, endptr),
_CONST wchar_t *__restrict nptr _AND _CONST wchar_t *__restrict nptr _AND
wchar_t **__restrict endptr) wchar_t **__restrict endptr)
{ {
double retval = _wcstod_r (_REENT, nptr, endptr); double retval = _wcstod_l (_REENT, nptr, endptr, __get_current_locale ());
if (isnan (retval)) if (isnan (retval))
return nanf (NULL); return nanf (NULL);
return (float)retval; return (float)retval;

View File

@ -1,19 +1,28 @@
/* /*
FUNCTION FUNCTION
<<wcstol>>---wide string to long <<wcstol>>, <<wcstol_l>>---wide string to long
INDEX INDEX
wcstol wcstol
INDEX
wcstol_l
INDEX INDEX
_wcstol_r _wcstol_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <wchar.h> #include <wchar.h>
long wcstol(const wchar_t *__restrict <[s]>, long wcstol(const wchar_t *__restrict <[s]>,
wchar_t **__restrict <[ptr]>,int <[base]>); wchar_t **__restrict <[ptr]>, int <[base]>);
long _wcstol_r(void *<[reent]>, #include <wchar.h>
const wchar_t *<[s]>, wchar_t **<[ptr]>,int <[base]>); 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 TRAD_SYNOPSIS
#include <stdlib.h> #include <stdlib.h>
@ -71,15 +80,21 @@ not <<NULL>>).
The alternate function <<_wcstol_r>> is a reentrant version. The The alternate function <<_wcstol_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure. extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS <<wcstol_l>> is like <<wcstol>> but performs the conversion based on the
<<wcstol>> returns the converted value, if any. If no conversion was locale specified by the locale object locale. If <[locale]> is
made, 0 is returned. LC_GLOBAL_LOCALE or not a valid locale object, the behaviour is undefined.
<<wcstol>> returns <<LONG_MAX>> or <<LONG_MIN>> if the magnitude of RETURNS
the converted value is too large, and sets <<errno>> to <<ERANGE>>. <<wcstol>>, <<wcstol_l>> return the converted value, if any. If no
conversion was made, 0 is returned.
<<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 PORTABILITY
<<wcstol>> is ANSI. <<wcstol>> is ANSI.
<<wcstol_l>> is a GNU extension.
No supporting OS subroutines are required. No supporting OS subroutines are required.
*/ */
@ -124,19 +139,14 @@ No supporting OS subroutines are required.
#include <errno.h> #include <errno.h>
#include <wchar.h> #include <wchar.h>
#include <reent.h> #include <reent.h>
#include "../locale/setlocale.h"
/* /*
* Convert a wide string to a long integer. * 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 static long
_DEFUN (_wcstol_r, (rptr, nptr, endptr, base), _wcstol_l (struct _reent *rptr, const wchar_t *nptr, wchar_t **endptr,
struct _reent *rptr _AND int base, locale_t loc)
_CONST wchar_t *nptr _AND
wchar_t **endptr _AND
int base)
{ {
register const wchar_t *s = nptr; register const wchar_t *s = nptr;
register unsigned long acc; register unsigned long acc;
@ -151,7 +161,7 @@ _DEFUN (_wcstol_r, (rptr, nptr, endptr, base),
*/ */
do { do {
c = *s++; c = *s++;
} while (iswspace(c)); } while (iswspace_l(c, loc));
if (c == L'-') { if (c == L'-') {
neg = 1; neg = 1;
c = *s++; c = *s++;
@ -187,10 +197,12 @@ _DEFUN (_wcstol_r, (rptr, nptr, endptr, base),
cutlim = cutoff % (unsigned long)base; cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base; cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) { for (acc = 0, any = 0;; c = *s++) {
if (iswdigit(c)) if (c >= L'0' && c <= L'9')
c -= L'0'; c -= L'0';
else if (iswalpha(c)) else if (c >= L'A' && c <= L'Z')
c -= iswupper(c) ? L'A' - 10 : L'a' - 10; c -= L'A' - 10;
else if (c >= L'a' && c <= L'z')
c -= L'a' - 10;
else else
break; break;
if (c >= base) if (c >= base)
@ -213,15 +225,32 @@ _DEFUN (_wcstol_r, (rptr, nptr, endptr, base),
return (acc); 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 #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 long
_DEFUN (wcstol, (s, ptr, base), _DEFUN (wcstol, (s, ptr, base),
_CONST wchar_t *__restrict s _AND _CONST wchar_t *__restrict s _AND
wchar_t **__restrict ptr _AND wchar_t **__restrict ptr _AND
int base) int base)
{ {
return _wcstol_r (_REENT, s, ptr, base); return _wcstol_l (_REENT, s, ptr, base, __get_current_locale ());
} }
#endif #endif

View File

@ -34,13 +34,15 @@ POSSIBILITY OF SUCH DAMAGE.
#include <wctype.h> #include <wctype.h>
#include <locale.h> #include <locale.h>
#include "local.h" #include "local.h"
#include "../locale/setlocale.h"
long double 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 #ifdef _LDBL_EQ_DBL
/* On platforms where long double is as wide as double. */ /* 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. */ #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. */ /* Convert the supplied numeric wide char string to multibyte. */
wcp = nptr; wcp = nptr;
mbs = initial; 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) if (endptr != NULL)
*endptr = (wchar_t *) nptr; *endptr = (wchar_t *) nptr;
@ -68,9 +71,9 @@ wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr)
return 0.0L; return 0.0L;
mbs = initial; 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_ /* We only know where the number ended in the _multibyte_
representation of the string. If the caller wants to know 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) just one byte long. The resulting difference (end - buf)
is then equivalent to the number of valid wide characters is then equivalent to the number of valid wide characters
in the input string. */ in the input string. */
len = strlen (localeconv ()->decimal_point); len = strlen (__localeconv_l (loc)->decimal_point);
if (len > 1) if (len > 1)
{ {
char *d = strstr (buf, localeconv ()->decimal_point); char *d = strstr (buf, __localeconv_l (loc)->decimal_point);
if (d && d < end) if (d && d < end)
end -= len - 1; end -= len - 1;
@ -106,3 +109,14 @@ wcstold (const wchar_t *__restrict nptr, wchar_t **__restrict endptr)
return val; return val;
#endif /* _LDBL_EQ_DBL */ #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
}

View File

@ -1,19 +1,28 @@
/* /*
FUNCTION FUNCTION
<<wcstoll>>---wide string to long long <<wcstoll>>, <<wcstoll_l>>---wide string to long long
INDEX INDEX
wcstoll wcstoll
INDEX
wcstoll_l
INDEX INDEX
_wcstoll_r _wcstoll_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <wchar.h> #include <wchar.h>
long long wcstoll(const wchar_t *__restrict <[s]>, 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]>, #include <wchar.h>
const wchar_t *<[s]>, wchar_t **<[ptr]>,int <[base]>); 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 TRAD_SYNOPSIS
#include <stdlib.h> #include <stdlib.h>
@ -71,15 +80,21 @@ not <<NULL>>).
The alternate function <<_wcstoll_r>> is a reentrant version. The The alternate function <<_wcstoll_r>> is a reentrant version. The
extra argument <[reent]> is a pointer to a reentrancy structure. extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS <<wcstoll_l>> is like <<wcstoll>> but performs the conversion based on the
<<wcstoll>> returns the converted value, if any. If no conversion was locale specified by the locale object locale. If <[locale]> is
made, 0 is returned. LC_GLOBAL_LOCALE or not a valid locale object, the behaviour is undefined.
<<wcstoll>> returns <<LONG_LONG_MAX>> or <<LONG_LONG_MIN>> if the magnitude of RETURNS
the converted value is too large, and sets <<errno>> to <<ERANGE>>. <<wcstoll>>, <<wcstoll_l>> return the converted value, if any. If no
conversion was made, 0 is returned.
<<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 PORTABILITY
<<wcstoll>> is ANSI. <<wcstoll>> is ANSI.
<<wcstoll_l>> is a GNU extension.
No supporting OS subroutines are required. No supporting OS subroutines are required.
*/ */
@ -117,23 +132,125 @@ No supporting OS subroutines are required.
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#define _GNU_SOURCE
#include <_ansi.h> #include <_ansi.h>
#include <limits.h> #include <limits.h>
#include <wctype.h> #include <wctype.h>
#include <errno.h> #include <errno.h>
#include <wchar.h> #include <wchar.h>
#include <reent.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 #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 long long
_DEFUN (wcstoll, (s, ptr, base), _DEFUN (wcstoll, (s, ptr, base),
_CONST wchar_t *__restrict s _AND _CONST wchar_t *__restrict s _AND
wchar_t **__restrict ptr _AND wchar_t **__restrict ptr _AND
int base) int base)
{ {
return _wcstoll_r (_REENT, s, ptr, base); return _wcstoll_l (_REENT, s, ptr, base, __get_current_locale ());
} }
#endif #endif

View File

@ -1,140 +1 @@
/* /* dummy */
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__ */

View File

@ -1,19 +1,28 @@
/* /*
FUNCTION FUNCTION
<<wcstoul>>---wide string to unsigned long <<wcstoul>>, <<wcstoul_l>>---wide string to unsigned long
INDEX INDEX
wcstoul wcstoul
INDEX
wcstoul_l
INDEX INDEX
_wcstoul_r _wcstoul_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <wchar.h> #include <wchar.h>
unsigned long wcstoul(const wchar_t *__restrict <[s]>, 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]>, unsigned long _wcstoul_r(void *<[reent]>, const wchar_t *<[s]>,
wchar_t **<[ptr]>, int <[base]>); wchar_t **<[ptr]>, int <[base]>);
TRAD_SYNOPSIS TRAD_SYNOPSIS
#include <wchar.h> #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. extra argument <[reent]> is a pointer to a reentrancy structure.
RETURNS <<wcstoul_l>> is like <<wcstoul>> but performs the conversion based on the
<<wcstoul>> returns the converted value, if any. If no conversion was locale specified by the locale object locale. If <[locale]> is
made, <<0>> is returned. LC_GLOBAL_LOCALE or not a valid locale object, the behaviour is undefined.
<<wcstoul>> returns <<ULONG_MAX>> if the magnitude of the converted RETURNS
value is too large, and sets <<errno>> to <<ERANGE>>. <<wcstoul>>, <<wcstoul_l>> return the converted value, if any. If no
conversion was made, <<0>> is returned.
<<wcstoul>>, <<wcstoul_l>> return <<ULONG_MAX>> if the magnitude of the
converted value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY PORTABILITY
<<wcstoul>> is ANSI. <<wcstoul>> is ANSI.
<<wcstoul_l>> is a GNU extension.
<<wcstoul>> requires no supporting OS subroutines. <<wcstoul>> requires no supporting OS subroutines.
*/ */
@ -125,19 +139,14 @@ PORTABILITY
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <reent.h> #include <reent.h>
#include "../locale/setlocale.h"
/* /*
* Convert a wide string to an unsigned long integer. * 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 unsigned long
_DEFUN (_wcstoul_r, (rptr, nptr, endptr, base), _wcstoul_l (struct _reent *rptr, const wchar_t *nptr, wchar_t **endptr,
struct _reent *rptr _AND int base, locale_t loc)
_CONST wchar_t *nptr _AND
wchar_t **endptr _AND
int base)
{ {
register const wchar_t *s = nptr; register const wchar_t *s = nptr;
register unsigned long acc; register unsigned long acc;
@ -150,7 +159,7 @@ _DEFUN (_wcstoul_r, (rptr, nptr, endptr, base),
*/ */
do { do {
c = *s++; c = *s++;
} while (iswspace(c)); } while (iswspace_l(c, loc));
if (c == L'-') { if (c == L'-') {
neg = 1; neg = 1;
c = *s++; c = *s++;
@ -167,10 +176,12 @@ _DEFUN (_wcstoul_r, (rptr, nptr, endptr, base),
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) { for (acc = 0, any = 0;; c = *s++) {
if (iswdigit(c)) if (c >= L'0' && c <= L'9')
c -= L'0'; c -= L'0';
else if (iswalpha(c)) else if (c >= L'A' && c <= L'Z')
c -= iswupper(c) ? L'A' - 10 : L'a' - 10; c -= L'A' - 10;
else if (c >= L'a' && c <= L'z')
c -= L'a' - 10;
else else
break; break;
if (c >= base) if (c >= base)
@ -193,15 +204,32 @@ _DEFUN (_wcstoul_r, (rptr, nptr, endptr, base),
return (acc); 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 #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 unsigned long
_DEFUN (wcstoul, (s, ptr, base), _DEFUN (wcstoul, (s, ptr, base),
_CONST wchar_t *__restrict s _AND _CONST wchar_t *__restrict s _AND
wchar_t **__restrict ptr _AND wchar_t **__restrict ptr _AND
int base) int base)
{ {
return _wcstoul_r (_REENT, s, ptr, base); return _wcstoul_l (_REENT, s, ptr, base, __get_current_locale ());
} }
#endif #endif

View File

@ -1,19 +1,30 @@
/* /*
FUNCTION FUNCTION
<<wcstoull>>---wide string to unsigned long long <<wcstoull>>, <<wcstoull_l>>---wide string to unsigned long long
INDEX INDEX
wcstoull wcstoull
INDEX
wcstoull_l
INDEX INDEX
_wcstoull_r _wcstoull_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <wchar.h> #include <wchar.h>
unsigned long long wcstoull(const wchar_t *__restrict <[s]>, 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]>, unsigned long long _wcstoull_r(void *<[reent]>, const wchar_t *<[s]>,
wchar_t **<[ptr]>, int <[base]>); wchar_t **<[ptr]>, int <[base]>);
TRAD_SYNOPSIS TRAD_SYNOPSIS
#include <wchar.h> #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. 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 RETURNS
<<wcstoull>> returns <<0>> and sets <<errno>> to <<EINVAL>> if the value of <<wcstoull>>, <<wcstoull_l>> return <<0>> and sets <<errno>> to <<EINVAL>>
<[base]> is not supported. if the value of <[base]> is not supported.
<<wcstoull>> returns the converted value, if any. If no conversion was <<wcstoull>>, <<wcstoull_l>> return the converted value, if any. If no
made, <<0>> is returned. conversion was made, <<0>> is returned.
<<wcstoull>> returns <<ULLONG_MAX>> if the magnitude of the converted <<wcstoull>>, <<wcstoull_l>> return <<ULLONG_MAX>> if the magnitude of
value is too large, and sets <<errno>> to <<ERANGE>>. the converted value is too large, and sets <<errno>> to <<ERANGE>>.
PORTABILITY PORTABILITY
<<wcstoull>> is ANSI. <<wcstoull>> is ANSI.
<<wcstoull_l>> is a GNU extension.
<<wcstoull>> requires no supporting OS subroutines. <<wcstoull>> requires no supporting OS subroutines.
*/ */
@ -122,19 +138,114 @@ PORTABILITY
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#define _GNU_SOURCE
#include <_ansi.h> #include <_ansi.h>
#include <limits.h>
#include <wchar.h> #include <wchar.h>
#include <wctype.h>
#include <errno.h>
#include <reent.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 #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 unsigned long long
_DEFUN (wcstoull, (s, ptr, base), _DEFUN (wcstoull, (s, ptr, base),
_CONST wchar_t *__restrict s _AND _CONST wchar_t *__restrict s _AND
wchar_t **__restrict ptr _AND wchar_t **__restrict ptr _AND
int base) int base)
{ {
return _wcstoull_r (_REENT, s, ptr, base); return _wcstoull_l (_REENT, s, ptr, base, __get_current_locale ());
} }
#endif #endif

View File

@ -1,130 +1 @@
/* /* dummy */
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__ */

View File

@ -1366,16 +1366,23 @@ strsignal SIGFE
strspn NOSIGFE strspn NOSIGFE
strstr NOSIGFE strstr NOSIGFE
strtod SIGFE strtod SIGFE
strtod_l SIGFE
strtof SIGFE strtof SIGFE
strtof_l SIGFE
strtoimax = strtoll NOSIGFE strtoimax = strtoll NOSIGFE
strtok NOSIGFE strtok NOSIGFE
strtok_r NOSIGFE strtok_r NOSIGFE
strtol NOSIGFE strtol NOSIGFE
strtol_l NOSIGFE
strtold SIGFE strtold SIGFE
strtold_l SIGFE
strtoll NOSIGFE strtoll NOSIGFE
strtoll_l NOSIGFE
strtosigno NOSIGFE strtosigno NOSIGFE
strtoul NOSIGFE strtoul NOSIGFE
strtoul_l NOSIGFE
strtoull NOSIGFE strtoull NOSIGFE
strtoull_l NOSIGFE
strtoumax = strtoull NOSIGFE strtoumax = strtoull NOSIGFE
strupr NOSIGFE strupr NOSIGFE
strxfrm NOSIGFE strxfrm NOSIGFE
@ -1527,15 +1534,22 @@ wcsrtombs NOSIGFE
wcsspn NOSIGFE wcsspn NOSIGFE
wcsstr NOSIGFE wcsstr NOSIGFE
wcstod NOSIGFE wcstod NOSIGFE
wcstod_l NOSIGFE
wcstof NOSIGFE wcstof NOSIGFE
wcstof_l NOSIGFE
wcstoimax = wcstoll NOSIGFE wcstoimax = wcstoll NOSIGFE
wcstok NOSIGFE wcstok NOSIGFE
wcstol NOSIGFE wcstol NOSIGFE
wcstol_l NOSIGFE
wcstold NOSIGFE wcstold NOSIGFE
wcstold_l NOSIGFE
wcstoll NOSIGFE wcstoll NOSIGFE
wcstoll_l NOSIGFE
wcstombs NOSIGFE wcstombs NOSIGFE
wcstoul NOSIGFE wcstoul NOSIGFE
wcstoul_l NOSIGFE
wcstoull NOSIGFE wcstoull NOSIGFE
wcstoull_l NOSIGFE
wcstoumax = wcstoull NOSIGFE wcstoumax = wcstoull NOSIGFE
wcswidth NOSIGFE wcswidth NOSIGFE
wcsxfrm NOSIGFE wcsxfrm NOSIGFE

View File

@ -463,12 +463,15 @@ details. */
toupper_l, towctrans_l, towlower_l, towupper_l, wctrans_l, wctype_l. toupper_l, towctrans_l, towlower_l, towupper_l, wctrans_l, wctype_l.
300: Export strcasecmp_l, strcoll_l, strfmon_l, strftime_l, strncasecmp_l, 300: Export strcasecmp_l, strcoll_l, strfmon_l, strftime_l, strncasecmp_l,
strxfrm_l, wcscasecmp_l, wcscoll_l, wcstrncasecmp_l, wcstrxfrm_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, Note that we forgot to bump the api for ualarm, strtoll, strtoull,
sigaltstack, sethostname. */ sigaltstack, sethostname. */
#define CYGWIN_VERSION_API_MAJOR 0 #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 /* There is also a compatibity version number associated with the shared memory
regions. It is incremented when incompatible changes are made to the shared regions. It is incremented when incompatible changes are made to the shared

View File

@ -1290,11 +1290,11 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
exp10l exp10l
fcloseall fcloseall
fcloseall_r fcloseall_r
fedisableexcept
feenableexcept
fegetexcept
fegetprec fegetprec
fesetprec fesetprec
feenableexcept
fedisableexcept
fegetexcept
ffsl ffsl
ffsll ffsll
fgets_unlocked fgets_unlocked
@ -1310,9 +1310,9 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
fsetxattr fsetxattr
get_avphys_pages get_avphys_pages
get_current_dir_name get_current_dir_name
get_phys_pages
get_nprocs get_nprocs
get_nprocs_conf get_nprocs_conf
get_phys_pages
getmntent_r getmntent_r
getopt_long getopt_long
getopt_long_only getopt_long_only
@ -1350,6 +1350,13 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
sincosf sincosf
sincosl sincosl
strchrnul strchrnul
strtod_l
strtof_l
strtol_l
strtold_l
strtoll_l
strtoul_l
strtoull_l
sysinfo sysinfo
tdestroy tdestroy
timegm timegm
@ -1360,6 +1367,13 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
vasnprintf vasnprintf
vasprintf vasprintf
vasprintf_r vasprintf_r
wcstod_l
wcstof_l
wcstol_l
wcstold_l
wcstoll_l
wcstoul_l
wcstoull_l
</screen> </screen>
</sect1> </sect1>