* include/_mingw.h: Increment version to 2.0.
* Makefile.in: Ditto. Merge in mingwex branch.
This commit is contained in:
113
winsup/mingw/mingwex/wcstoumax.c
Normal file
113
winsup/mingw/mingwex/wcstoumax.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
This source code was extracted from the Q8 package created and
|
||||
placed in the PUBLIC DOMAIN by Doug Gwyn <gwyn@arl.mil>
|
||||
|
||||
last edit: 1999/11/05 gwyn@arl.mil
|
||||
|
||||
Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E).
|
||||
|
||||
This particular implementation requires the matching <inttypes.h>.
|
||||
It also assumes that character codes for A..Z and a..z are in
|
||||
contiguous ascending order; this is true for ASCII but not EBCDIC.
|
||||
*/
|
||||
|
||||
#include <wchar.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
/* convert digit wide character to number, in any base */
|
||||
|
||||
#define ToWNumber(c) (iswdigit(c) ? (c) - L'0' : \
|
||||
iswupper(c) ? (c) - L'A' + 10 : \
|
||||
iswlower(c) ? (c) - L'a' + 10 : \
|
||||
-1 /* "invalid" flag */ \
|
||||
)
|
||||
|
||||
/* validate converted digit character for specific base */
|
||||
#define valid(n, b) ((n) >= 0 && (n) < (b))
|
||||
|
||||
uintmax_t
|
||||
wcstoumax(nptr, endptr, base)
|
||||
register const wchar_t * __restrict__ nptr;
|
||||
wchar_t ** __restrict__ endptr;
|
||||
register int base;
|
||||
{
|
||||
register uintmax_t accum; /* accumulates converted value */
|
||||
register uintmax_t next; /* for computing next value of accum */
|
||||
register int n; /* numeral from digit character */
|
||||
int minus; /* set iff minus sign seen (yes!) */
|
||||
int toobig; /* set iff value overflows */
|
||||
|
||||
if ( endptr != NULL )
|
||||
*endptr = (wchar_t *)nptr; /* in case no conv performed */
|
||||
|
||||
if ( base < 0 || base == 1 || base > 36 )
|
||||
{
|
||||
errno = EDOM;
|
||||
return 0; /* unspecified behavior */
|
||||
}
|
||||
|
||||
/* skip initial, possibly empty sequence of white-space w.characters */
|
||||
|
||||
while ( iswspace(*nptr) )
|
||||
++nptr;
|
||||
|
||||
/* process subject sequence: */
|
||||
|
||||
/* optional sign */
|
||||
|
||||
if ( (minus = *nptr == L'-') || *nptr == L'+' )
|
||||
++nptr;
|
||||
|
||||
if ( base == 0 )
|
||||
{
|
||||
if ( *nptr == L'0' )
|
||||
{
|
||||
if ( nptr[1] == L'X' || nptr[1] == L'x' )
|
||||
base = 16;
|
||||
else
|
||||
base = 8;
|
||||
}
|
||||
else
|
||||
base = 10;
|
||||
}
|
||||
/* optional "0x" or "0X" for base 16 */
|
||||
|
||||
if ( base == 16 && *nptr == L'0'
|
||||
&& (nptr[1] == L'X' || nptr[1] == L'x')
|
||||
)
|
||||
nptr += 2; /* skip past this prefix */
|
||||
|
||||
/* check whether there is at least one valid digit */
|
||||
|
||||
n = ToWNumber(*nptr);
|
||||
++nptr;
|
||||
|
||||
if ( !valid(n, base) )
|
||||
return 0; /* subject seq. not of expected form */
|
||||
|
||||
accum = n;
|
||||
|
||||
for ( toobig = 0; n = ToWNumber(*nptr), valid(n, base); ++nptr )
|
||||
if ( accum > UINTMAX_MAX / base + 1 /* major wrap-around */
|
||||
|| (next = base * accum + n) < accum /* minor wrap-around */
|
||||
)
|
||||
toobig = 1; /* but keep scanning */
|
||||
else
|
||||
accum = next;
|
||||
|
||||
if ( endptr != NULL )
|
||||
*endptr = (wchar_t *)nptr; /* -> first not-valid-digit */
|
||||
|
||||
if ( toobig )
|
||||
{
|
||||
errno = ERANGE;
|
||||
return UINTMAX_MAX;
|
||||
}
|
||||
else
|
||||
return minus ? -accum : accum; /* (yes!) */
|
||||
}
|
||||
|
||||
unsigned long long __attribute__ ((alias ("wcstoumax")))
|
||||
wcstoull (const wchar_t* __restrict__ nptr, wchar_t ** __restrict__ endptr, int base);
|
Reference in New Issue
Block a user