|  | /** | 
|  | * This file has no copyright assigned and is placed in the Public Domain. | 
|  | * This file is part of the w64 mingw-runtime package. | 
|  | * No warranty is given; refer to the file DISCLAIMER within this package. | 
|  | */ | 
|  | /* | 
|  | 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); |