master
  1/**
  2 * This file has no copyright assigned and is placed in the Public Domain.
  3 * This file is part of the mingw-w64 runtime package.
  4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  5 */
  6/*
  7    This source code was extracted from the Q8 package created and
  8    placed in the PUBLIC DOMAIN by Doug Gwyn <gwyn@arl.mil>
  9
 10    last edit:	1999/11/05	gwyn@arl.mil
 11
 12	Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E).
 13
 14	This particular implementation requires the matching <inttypes.h>.
 15	It also assumes that character codes for A..Z and a..z are in
 16	contiguous ascending order; this is true for ASCII but not EBCDIC.
 17*/
 18
 19#include <wchar.h>
 20#include <errno.h>
 21#include <ctype.h>
 22#include <inttypes.h>
 23
 24/* convert digit wide character to number, in any base */
 25
 26#define ToWNumber(c)	(iswdigit(c) ? (c) - L'0' : \
 27			 iswupper(c) ? (c) - L'A' + 10 : \
 28			 iswlower(c) ? (c) - L'a' + 10 : \
 29			 -1		/* "invalid" flag */ \
 30			)
 31
 32/* validate converted digit character for specific base */
 33#define valid(n, b)	((n) >= 0 && (n) < (b))
 34
 35intmax_t
 36__cdecl
 37wcstoimax(const wchar_t * __restrict__ nptr, wchar_t ** __restrict__ endptr, int base)
 38	{
 39	register uintmax_t	accum;	/* accumulates converted value */
 40	register int		n;	/* numeral from digit character */
 41	int			minus;	/* set iff minus sign seen */
 42	int			toobig;	/* set iff value overflows */
 43
 44	if ( endptr != NULL )
 45		*endptr = (wchar_t *)nptr;	/* in case no conv performed */
 46
 47	if ( base < 0 || base == 1 || base > 36 )
 48		{
 49		errno = EDOM;
 50		return 0;		/* unspecified behavior */
 51		}
 52
 53	/* skip initial, possibly empty sequence of white-space w.characters */
 54
 55	while ( iswspace(*nptr) )
 56		++nptr;
 57
 58	/* process subject sequence: */
 59
 60	/* optional sign */
 61
 62	if ( (minus = *nptr == L'-') || *nptr == L'+' )
 63		++nptr;
 64
 65	if ( base == 0 )
 66        {
 67		if ( *nptr == L'0' )
 68            {
 69			if ( nptr[1] == L'X' || nptr[1] == L'x' )
 70				base = 16;
 71			else
 72				base = 8;
 73            }
 74		else
 75				base = 10;
 76        }
 77	/* optional "0x" or "0X" for base 16 */
 78
 79	if ( base == 16 && *nptr == L'0'
 80	  && (nptr[1] == L'X' || nptr[1] == L'x')
 81	   )
 82		nptr += 2;		/* skip past this prefix */
 83
 84	/* check whether there is at least one valid digit */
 85
 86	n = ToWNumber(*nptr);
 87	++nptr;
 88
 89	if ( !valid(n, base) )
 90		return 0;		/* subject seq. not of expected form */
 91
 92	accum = n;
 93
 94	for ( toobig = 0; n = ToWNumber(*nptr), valid(n, base); ++nptr )
 95		if ( accum > (uintmax_t)(INTMAX_MAX / base + 2) ) /* major wrap-around */
 96			toobig = 1;	/* but keep scanning */
 97		else
 98			accum = base * accum + n;
 99
100	if ( endptr != NULL )
101		*endptr = (wchar_t *)nptr;	/* -> first not-valid-digit */
102
103	if ( minus )
104		{
105		if ( accum > (uintmax_t)INTMAX_MAX + 1 )
106			toobig = 1;
107		}
108	else
109	if ( accum > (uintmax_t)INTMAX_MAX )
110		toobig = 1;
111
112	if ( toobig )
113		{
114		errno = ERANGE;
115		return minus ? INTMAX_MIN : INTMAX_MAX;
116		}
117	else
118		return (intmax_t)(minus ? -accum : accum);
119	}
120intmax_t (__cdecl *__MINGW_IMP_SYMBOL(wcstoimax))(const wchar_t * __restrict__, wchar_t ** __restrict__, int) = wcstoimax;
121
122long long __attribute__ ((alias ("wcstoimax")))
123__cdecl
124wcstoll (const wchar_t* __restrict__ nptr, wchar_t ** __restrict__ endptr, int base);
125extern long long __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(wcstoimax)))))
126(__cdecl *__MINGW_IMP_SYMBOL(wcstoll))(const wchar_t * __restrict__, wchar_t ** __restrict__, int);
127
128long long __attribute__ ((alias ("wcstoimax")))
129__cdecl
130_wcstoi64 (const wchar_t* __restrict__ nptr, wchar_t ** __restrict__ endptr, int base);
131extern long long __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(wcstoimax)))))
132(__cdecl *__MINGW_IMP_SYMBOL(_wcstoi64))(const wchar_t * __restrict__, wchar_t ** __restrict__, int);