/* Copyright (C) 2002 Manuel Novoa III
* From my (incomplete) stdlib library for linux and (soon) elks.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, see
* .
*/
/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
*
* This code is currently under development. Also, I plan to port
* it to elks which is a 16-bit environment with a fairly limited
* compiler. Therefore, please refrain from modifying this code
* and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel
*
* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
/* Oct 29, 2002
* Fix a couple of 'restrict' bugs in mbstowcs and wcstombs.
*
* Nov 21, 2002
* Add wscto{inttype} functions.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef __UCLIBC_HAS_WCHAR__
#include
#include
#include
/* TODO: clean up the following... */
#if WCHAR_MAX > 0xffffUL
#define UTF_8_MAX_LEN 6
#else
#define UTF_8_MAX_LEN 3
#endif
#ifdef __UCLIBC_HAS_LOCALE__
#define ENCODING (__UCLIBC_CURLOCALE->encoding)
#ifndef __CTYPE_HAS_UTF_8_LOCALES
#ifdef L_mblen
/* emit only once */
#warning __CTYPE_HAS_UTF_8_LOCALES not set!
#endif
#endif
#else /* __UCLIBC_HAS_LOCALE__ */
#ifdef __UCLIBC_MJN3_ONLY__
#ifdef L_mblen
/* emit only once */
#warning devel checks
#endif
#endif
#ifdef __CTYPE_HAS_8_BIT_LOCALES
#error __CTYPE_HAS_8_BIT_LOCALES is defined!
#endif
#ifdef __CTYPE_HAS_UTF_8_LOCALES
#error __CTYPE_HAS_UTF_8_LOCALES is defined!
#endif
#endif
#endif /* __UCLIBC_HAS_LOCALE__ */
/**********************************************************************/
#ifdef __UCLIBC_HAS_XLOCALE__
extern unsigned long
_stdlib_strto_l_l(register const char * __restrict str,
char ** __restrict endptr, int base, int sflag,
__locale_t locale_arg) attribute_hidden;
#if defined(ULLONG_MAX)
extern unsigned long long
_stdlib_strto_ll_l(register const char * __restrict str,
char ** __restrict endptr, int base, int sflag,
__locale_t locale_arg) attribute_hidden;
#endif
#ifdef __UCLIBC_HAS_WCHAR__
extern unsigned long
_stdlib_wcsto_l_l(register const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base, int sflag,
__locale_t locale_arg) attribute_hidden;
#if defined(ULLONG_MAX)
extern unsigned long long
_stdlib_wcsto_ll_l(register const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base, int sflag,
__locale_t locale_arg) attribute_hidden;
#endif
#endif /* __UCLIBC_HAS_WCHAR__ */
#endif /* __UCLIBC_HAS_XLOCALE__ */
extern unsigned long
_stdlib_strto_l(register const char * __restrict str,
char ** __restrict endptr, int base, int sflag) attribute_hidden;
#if defined(ULLONG_MAX)
extern unsigned long long
_stdlib_strto_ll(register const char * __restrict str,
char ** __restrict endptr, int base, int sflag) attribute_hidden;
#endif
#ifdef __UCLIBC_HAS_WCHAR__
extern unsigned long
_stdlib_wcsto_l(register const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base, int sflag) attribute_hidden;
#if defined(ULLONG_MAX)
extern unsigned long long
_stdlib_wcsto_ll(register const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base, int sflag) attribute_hidden;
#endif
#endif /* __UCLIBC_HAS_WCHAR__ */
/**********************************************************************/
#ifdef L_atof
double atof(const char *nptr)
{
return strtod(nptr, (char **) NULL);
}
#endif
/**********************************************************************/
#ifdef L_abs
#if INT_MAX < LONG_MAX
int abs(int j)
{
return (j >= 0) ? j : -j;
}
#endif /* INT_MAX < LONG_MAX */
#endif
/**********************************************************************/
#ifdef L_labs
long int labs(long int j)
{
return (j >= 0) ? j : -j;
}
#if UINT_MAX == ULONG_MAX
strong_alias_untyped(labs,abs)
#endif
#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
strong_alias_untyped(labs,llabs)
#endif
#if ULONG_MAX == UINTMAX_MAX
strong_alias_untyped(labs,imaxabs)
#endif
#endif
/**********************************************************************/
#ifdef L_llabs
#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
long long int llabs(long long int j)
{
return (j >= 0) ? j : -j;
}
#if (ULLONG_MAX == UINTMAX_MAX)
strong_alias_untyped(llabs,imaxabs)
#endif
#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
#endif
/**********************************************************************/
#ifdef L_atoi
#if INT_MAX < LONG_MAX
int atoi(const char *nptr)
{
return (int) strtol(nptr, (char **) NULL, 10);
}
libc_hidden_def(atoi)
#endif /* INT_MAX < LONG_MAX */
#endif
/**********************************************************************/
#ifdef L_atol
long atol(const char *nptr)
{
return strtol(nptr, (char **) NULL, 10);
}
#if UINT_MAX == ULONG_MAX
strong_alias_untyped(atol,atoi)
libc_hidden_def(atoi)
#endif
#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
strong_alias_untyped(atol,atoll)
#endif
#endif
/**********************************************************************/
#ifdef L_atoll
#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
long long atoll(const char *nptr)
{
return strtoll(nptr, (char **) NULL, 10);
}
#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
#endif
/**********************************************************************/
#ifdef L_rpmatch
int rpmatch (const char *__response)
{
return (__response[0] == 'y' || __response[0] == 'Y') ? 1 :
(__response[0] == 'n' || __response[0] == 'N') ? 0 : -1;
}
#endif
/**********************************************************************/
#if defined(L_strtol) || defined(L_strtol_l)
long __XL_NPP(strtol)(const char * __restrict str, char ** __restrict endptr,
int base __LOCALE_PARAM)
{
return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 1 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(strtol))
#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtol_l)
strong_alias(strtol,strtoimax)
#endif
#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
strong_alias_untyped(__XL_NPP(strtol),__XL_NPP(strtoll))
#ifdef L_strtol
libc_hidden_def(__XL_NPP(strtoll))
strong_alias(strtol,strtoq)
#endif
#endif
#endif
/**********************************************************************/
#if defined(L_strtoll) || defined(L_strtoll_l)
#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
long long __XL_NPP(strtoll)(const char * __restrict str,
char ** __restrict endptr, int base
__LOCALE_PARAM)
{
return (long long) __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 1 __LOCALE_ARG);
}
#ifdef L_strtoll
libc_hidden_def(__XL_NPP(strtoll))
#if (ULLONG_MAX == UINTMAX_MAX)
strong_alias(strtoll,strtoimax)
#endif
strong_alias(strtoll,strtoq)
#endif
#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
#endif
/**********************************************************************/
#if defined(L_strtoul) || defined(L_strtoul_l)
unsigned long __XL_NPP(strtoul)(const char * __restrict str,
char ** __restrict endptr, int base
__LOCALE_PARAM)
{
return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 0 __LOCALE_ARG);
}
libc_hidden_def(__XL_NPP(strtoul))
#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtoul_l)
strong_alias(strtoul,strtoumax)
#endif
#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
strong_alias_untyped(__XL_NPP(strtoul),__XL_NPP(strtoull))
#if !defined(L_strtoul_l)
strong_alias(strtoul,strtouq)
#endif
#endif
#endif
/**********************************************************************/
#if defined(L_strtoull) || defined(L_strtoull_l)
#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
unsigned long long __XL_NPP(strtoull)(const char * __restrict str,
char ** __restrict endptr, int base
__LOCALE_PARAM)
{
return __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 0 __LOCALE_ARG);
}
#if !defined(L_strtoull_l)
#if (ULLONG_MAX == UINTMAX_MAX)
strong_alias(strtoull,strtoumax)
#endif
strong_alias(strtoull,strtouq)
#endif
#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
#endif
/**********************************************************************/
/* Support routines follow */
/**********************************************************************/
/* Set if we want errno set appropriately. */
/* NOTE: Implies _STRTO_ENDPTR below */
#define _STRTO_ERRNO 1
/* Set if we want support for the endptr arg. */
/* Implied by _STRTO_ERRNO. */
#define _STRTO_ENDPTR 1
#if _STRTO_ERRNO
#undef _STRTO_ENDPTR
#define _STRTO_ENDPTR 1
#define SET_ERRNO(X) __set_errno(X)
#else
#define SET_ERRNO(X) ((void)(X)) /* keep side effects */
#endif
/**********************************************************************/
#if defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l)
#ifndef L__stdlib_strto_l
#define L__stdlib_strto_l
#endif
#endif
#if defined(L__stdlib_strto_l) || defined(L__stdlib_strto_l_l)
#if defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l)
#define _stdlib_strto_l _stdlib_wcsto_l
#define _stdlib_strto_l_l _stdlib_wcsto_l_l
#define Wchar wchar_t
#define Wuchar __uwchar_t
#ifdef __UCLIBC_DO_XLOCALE
#define ISSPACE(C) iswspace_l((C), locale_arg)
#else
#define ISSPACE(C) iswspace((C))
#endif
#else /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */
#define Wchar char
#define Wuchar unsigned char
#ifdef __UCLIBC_DO_XLOCALE
#define ISSPACE(C) isspace_l((C), locale_arg)
#else
#define ISSPACE(C) isspace((C))
#endif
#endif /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
unsigned long attribute_hidden _stdlib_strto_l(register const Wchar * __restrict str,
Wchar ** __restrict endptr, int base,
int sflag)
{
return _stdlib_strto_l_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE);
}
#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
/* This is the main work fuction which handles both strtol (sflag = 1) and
* strtoul (sflag = 0). */
unsigned long attribute_hidden __XL_NPP(_stdlib_strto_l)(register const Wchar * __restrict str,
Wchar ** __restrict endptr, int base,
int sflag __LOCALE_PARAM)
{
unsigned long number, cutoff;
#if _STRTO_ENDPTR
const Wchar *fail_char;
#define SET_FAIL(X) fail_char = (X)
#else
#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
#endif
unsigned char negative, digit, cutoff_digit;
assert(((unsigned int)sflag) <= 1);
SET_FAIL(str);
while (ISSPACE(*str)) { /* Skip leading whitespace. */
++str;
}
/* Handle optional sign. */
negative = 0;
switch (*str) {
case '-': negative = 1; /* Fall through to increment str. */
case '+': ++str;
}
if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */
base += 10; /* Default is 10 (26). */
if (*str == '0') {
SET_FAIL(++str);
base -= 2; /* Now base is 8 or 16 (24). */
if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */
++str;
base += base; /* Base is 16 (16 or 48). */
}
}
if (base > 16) { /* Adjust in case base wasn't dynamic. */
base = 16;
}
}
number = 0;
if (((unsigned)(base - 2)) < 35) { /* Legal base. */
cutoff_digit = ULONG_MAX % base;
cutoff = ULONG_MAX / base;
do {
digit = ((Wuchar)(*str - '0') <= 9)
? /* 0..9 */ (*str - '0')
: /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */
? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10))
: /* else */ 40 /* bad value */);
if (digit >= base) {
break;
}
SET_FAIL(++str);
if ((number > cutoff)
|| ((number == cutoff) && (digit > cutoff_digit))) {
number = ULONG_MAX;
negative &= sflag;
SET_ERRNO(ERANGE);
} else {
number = number * base + digit;
}
} while (1);
}
#if _STRTO_ENDPTR
if (endptr) {
*endptr = (Wchar *) fail_char;
}
#endif
{
unsigned long tmp = (negative
? ((unsigned long)(-(1+LONG_MIN)))+1
: LONG_MAX);
if (sflag && (number > tmp)) {
number = tmp;
SET_ERRNO(ERANGE);
}
}
return negative ? (unsigned long)(-((long)number)) : number;
}
#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
#endif
/**********************************************************************/
#if defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l)
#ifndef L__stdlib_strto_ll
#define L__stdlib_strto_ll
#endif
#endif
#if defined(L__stdlib_strto_ll) || defined(L__stdlib_strto_ll_l)
#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
#if defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l)
#define _stdlib_strto_ll _stdlib_wcsto_ll
#define _stdlib_strto_ll_l _stdlib_wcsto_ll_l
#define Wchar wchar_t
#define Wuchar __uwchar_t
#ifdef __UCLIBC_DO_XLOCALE
#define ISSPACE(C) iswspace_l((C), locale_arg)
#else
#define ISSPACE(C) iswspace((C))
#endif
#else /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */
#define Wchar char
#define Wuchar unsigned char
#ifdef __UCLIBC_DO_XLOCALE
#define ISSPACE(C) isspace_l((C), locale_arg)
#else
#define ISSPACE(C) isspace((C))
#endif
#endif /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
unsigned long long attribute_hidden _stdlib_strto_ll(register const Wchar * __restrict str,
Wchar ** __restrict endptr, int base,
int sflag)
{
return _stdlib_strto_ll_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE);
}
#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
/* This is the main work fuction which handles both strtoll (sflag = 1) and
* strtoull (sflag = 0). */
unsigned long long attribute_hidden __XL_NPP(_stdlib_strto_ll)(register const Wchar * __restrict str,
Wchar ** __restrict endptr, int base,
int sflag __LOCALE_PARAM)
{
unsigned long long number;
#if _STRTO_ENDPTR
const Wchar *fail_char;
#define SET_FAIL(X) fail_char = (X)
#else
#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
#endif
unsigned int n1;
unsigned char negative, digit;
assert(((unsigned int)sflag) <= 1);
SET_FAIL(str);
while (ISSPACE(*str)) { /* Skip leading whitespace. */
++str;
}
/* Handle optional sign. */
negative = 0;
switch (*str) {
case '-': negative = 1; /* Fall through to increment str. */
case '+': ++str;
}
if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */
base += 10; /* Default is 10 (26). */
if (*str == '0') {
SET_FAIL(++str);
base -= 2; /* Now base is 8 or 16 (24). */
if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */
++str;
base += base; /* Base is 16 (16 or 48). */
}
}
if (base > 16) { /* Adjust in case base wasn't dynamic. */
base = 16;
}
}
number = 0;
if (((unsigned)(base - 2)) < 35) { /* Legal base. */
do {
digit = ((Wuchar)(*str - '0') <= 9)
? /* 0..9 */ (*str - '0')
: /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */
? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10))
: /* else */ 40 /* bad value */);
if (digit >= base) {
break;
}
SET_FAIL(++str);
#if 1
/* Optional, but speeds things up in the usual case. */
if (number <= (ULLONG_MAX >> 6)) {
number = number * base + digit;
} else
#endif
{
n1 = ((unsigned char) number) * base + digit;
number = (number >> CHAR_BIT) * base;
if (number + (n1 >> CHAR_BIT) <= (ULLONG_MAX >> CHAR_BIT)) {
number = (number << CHAR_BIT) + n1;
} else { /* Overflow. */
number = ULLONG_MAX;
negative &= sflag;
SET_ERRNO(ERANGE);
}
}
} while (1);
}
#if _STRTO_ENDPTR
if (endptr) {
*endptr = (Wchar *) fail_char;
}
#endif
{
unsigned long long tmp = ((negative)
? ((unsigned long long)(-(1+LLONG_MIN)))+1
: LLONG_MAX);
if (sflag && (number > tmp)) {
number = tmp;
SET_ERRNO(ERANGE);
}
}
return negative ? (unsigned long long)(-((long long)number)) : number;
}
#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
#endif
#ifdef L_bsearch
void *bsearch(const void *key, const void *base, size_t /* nmemb */ high,
size_t size, int (*compar)(const void *, const void *))
{
register char *p;
size_t low;
size_t mid;
int r;
if (size > 0) { /* TODO: change this to an assert?? */
low = 0;
while (low < high) {
mid = low + ((high - low) >> 1); /* Avoid possible overflow here. */
p = ((char *)base) + mid * size; /* Could overflow here... */
r = (*compar)(key, p); /* but that's an application problem! */
if (r > 0) {
low = mid + 1;
} else if (r < 0) {
high = mid;
} else {
return p;
}
}
}
return NULL;
}
#endif
/**********************************************************************/
#ifdef L_qsort_r
/* This code is derived from a public domain shell sort routine by
* Ray Gardner and found in Bob Stout's snippets collection. The
* original code is included below in an #if 0/#endif block.
*
* I modified it to avoid the possibility of overflow in the wgap
* calculation, as well as to reduce the generated code size with
* bcc and gcc. */
void qsort_r(void *base,
size_t nel,
size_t width,
__compar_d_fn_t comp,
void *arg)
{
size_t wgap, i, j, k;
char tmp;
if ((nel > 1) && (width > 0)) {
assert(nel <= ((size_t)(-1)) / width); /* check for overflow */
wgap = 0;
do {
wgap = 3 * wgap + 1;
} while (wgap < (nel-1)/3);
/* From the above, we know that either wgap == 1 < nel or */
/* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap < nel. */
wgap *= width; /* So this can not overflow if wnel doesn't. */
nel *= width; /* Convert nel to 'wnel' */
do {
i = wgap;
do {
j = i;
do {
register char *a;
register char *b;
j -= wgap;
a = j + ((char *)base);
b = a + wgap;
if ((*comp)(a, b, arg) <= 0) {
break;
}
k = width;
do {
tmp = *a;
*a++ = *b;
*b++ = tmp;
} while (--k);
} while (j >= wgap);
i += width;
} while (i < nel);
wgap = (wgap - width)/3;
} while (wgap);
}
}
libc_hidden_def(qsort_r)
/* ---------- original snippets version below ---------- */
#if 0
/*
** ssort() -- Fast, small, qsort()-compatible Shell sort
**
** by Ray Gardner, public domain 5/90
*/
#include
void ssort(void *base,
size_t nel,
size_t width,
int (*comp)(const void *, const void *))
{
size_t wnel, gap, wgap, i, j, k;
char *a, *b, tmp;
wnel = width * nel;
for (gap = 0; ++gap < nel;)
gap *= 3;
while ((gap /= 3) != 0) {
wgap = width * gap;
for (i = wgap; i < wnel; i += width) {
for (j = i - wgap; ;j -= wgap) {
a = j + (char *)base;
b = a + wgap;
if ((*comp)(a, b) <= 0)
break;
k = width;
do {
tmp = *a;
*a++ = *b;
*b++ = tmp;
} while (--k);
if (j < wgap)
break;
}
}
}
}
#endif
#endif
#ifdef L_qsort
void qsort(void *base,
size_t nel,
size_t width,
__compar_fn_t comp)
{
return qsort_r (base, nel, width, (__compar_d_fn_t) comp, NULL);
}
libc_hidden_def(qsort)
#endif
/**********************************************************************/
#ifdef L__stdlib_mb_cur_max
size_t _stdlib_mb_cur_max(void)
{
#ifdef __CTYPE_HAS_UTF_8_LOCALES
return __UCLIBC_CURLOCALE->mb_cur_max;
#else
#ifdef __CTYPE_HAS_8_BIT_LOCALES
#ifdef __UCLIBC_MJN3_ONLY__
#warning need to change this when/if transliteration is implemented
#endif
#endif
return 1;
#endif
}
libc_hidden_def(_stdlib_mb_cur_max)
#endif
#ifdef __UCLIBC_HAS_LOCALE__
/*
* The following function return 1 if the encoding is stateful, 0 if stateless.
* To note, until now all the supported encoding are stateless.
*/
static __always_inline int is_stateful(unsigned char encoding)
{
switch (encoding)
{
case __ctype_encoding_7_bit:
case __ctype_encoding_utf8:
case __ctype_encoding_8_bit:
return 0;
default:
assert(0);
return -1;
}
}
#else
#define is_stateful(encoding) 0
#endif
/**********************************************************************/
#ifdef L_mblen
int mblen(register const char *s, size_t n)
{
static mbstate_t state;
size_t r;
if (!s) {
state.__mask = 0;
/*
In this case we have to return 0 because the only multibyte supported encoding
is utf-8, that is a stateless encoding. See mblen() documentation.
*/
return is_stateful(ENCODING);
}
if (*s == '\0')
/* According to the ISO C 89 standard this is the expected behaviour. */
return 0;
if ((r = mbrlen(s, n, &state)) == (size_t) -2) {
/* TODO: Should we set an error state? */
state.__wc = 0xffffU; /* Make sure we're in an error state. */
return -1; /* TODO: Change error code above? */
}
return r;
}
#endif
/**********************************************************************/
#ifdef L_mbtowc
int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n)
{
static mbstate_t state;
size_t r;
if (!s) {
state.__mask = 0;
/*
In this case we have to return 0 because the only multibyte supported encoding
is utf-8, that is a stateless encoding. See mbtowc() documentation.
*/
return is_stateful(ENCODING);
}
if (*s == '\0')
/* According to the ISO C 89 standard this is the expected behaviour. */
return 0;
if ((r = mbrtowc(pwc, s, n, &state)) == (size_t) -2) {
/* TODO: Should we set an error state? */
state.__wc = 0xffffU; /* Make sure we're in an error state. */
return -1; /* TODO: Change error code above? */
}
return r;
}
#endif
/**********************************************************************/
#ifdef L_wctomb
/* Note: We completely ignore state in all currently supported conversions. */
int wctomb(register char *__restrict s, wchar_t swc)
{
return (!s)
?
/*
In this case we have to return 0 because the only multibyte supported encoding
is utf-8, that is a stateless encoding. See wctomb() documentation.
*/
is_stateful(ENCODING)
: ((ssize_t) wcrtomb(s, swc, NULL));
}
#endif
/**********************************************************************/
#ifdef L_mbstowcs
size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
{
mbstate_t state;
const char *e = s; /* Needed because of restrict. */
state.__mask = 0; /* Always start in initial shift state. */
return mbsrtowcs(pwcs, &e, n, &state);
}
#endif
/**********************************************************************/
#ifdef L_wcstombs
/* Note: We completely ignore state in all currently supported conversions. */
size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
{
const wchar_t *e = pwcs; /* Needed because of restrict. */
return wcsrtombs(s, &e, n, NULL);
}
#endif
/**********************************************************************/
#if defined(L_wcstol) || defined(L_wcstol_l)
long __XL_NPP(wcstol)(const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base __LOCALE_PARAM)
{
return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 1 __LOCALE_ARG);
}
#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstol_l)
strong_alias(wcstol,wcstoimax)
#endif
#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
strong_alias_untyped(__XL_NPP(wcstol),__XL_NPP(wcstoll))
#endif
#endif
/**********************************************************************/
#if defined(L_wcstoll) || defined(L_wcstoll_l)
#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
long long __XL_NPP(wcstoll)(const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base
__LOCALE_PARAM)
{
return (long long) __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 1 __LOCALE_ARG);
}
#if !defined(L_wcstoll_l)
#if (ULLONG_MAX == UINTMAX_MAX)
strong_alias(wcstoll,wcstoimax)
#endif
strong_alias(wcstoll,wcstoq)
#endif
#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
#endif
/**********************************************************************/
#if defined(L_wcstoul) || defined(L_wcstoul_l)
unsigned long __XL_NPP(wcstoul)(const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base
__LOCALE_PARAM)
{
return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 0 __LOCALE_ARG);
}
#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstoul_l)
strong_alias(wcstoul,wcstoumax)
#endif
#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
strong_alias_untyped(__XL_NPP(wcstoul),__XL_NPP(wcstoull))
#endif
#endif
/**********************************************************************/
#if defined(L_wcstoull) || defined(L_wcstoull_l)
#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX)
unsigned long long __XL_NPP(wcstoull)(const wchar_t * __restrict str,
wchar_t ** __restrict endptr, int base
__LOCALE_PARAM)
{
return __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 0 __LOCALE_ARG);
}
#if !defined(L_wcstoull_l)
#if (ULLONG_MAX == UINTMAX_MAX)
strong_alias(wcstoull,wcstoumax)
#endif
strong_alias(wcstoull,wcstouq)
#endif
#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */
#endif
/**********************************************************************/