summaryrefslogtreecommitdiffstats
path: root/winsup/mingw/mingwex/wcstoumax.c
diff options
context:
space:
mode:
authorDanny Smith <dannysmith@users.sourceforge.net>2002-06-13 10:20:48 +0000
committerDanny Smith <dannysmith@users.sourceforge.net>2002-06-13 10:20:48 +0000
commitdc8971488e7c174ab4084cbdb0a8f12c39b738d7 (patch)
treed679387fa379b6d5feb9756bdd7237347614453b /winsup/mingw/mingwex/wcstoumax.c
parent5f74ae83e5fba1ceb73a8d822cbe2b48c619127f (diff)
downloadcygnal-dc8971488e7c174ab4084cbdb0a8f12c39b738d7.tar.gz
cygnal-dc8971488e7c174ab4084cbdb0a8f12c39b738d7.tar.bz2
cygnal-dc8971488e7c174ab4084cbdb0a8f12c39b738d7.zip
* include/_mingw.h: Increment version to 2.0.
* Makefile.in: Ditto. Merge in mingwex branch.
Diffstat (limited to 'winsup/mingw/mingwex/wcstoumax.c')
-rw-r--r--winsup/mingw/mingwex/wcstoumax.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/winsup/mingw/mingwex/wcstoumax.c b/winsup/mingw/mingwex/wcstoumax.c
new file mode 100644
index 000000000..9bd6cd704
--- /dev/null
+++ b/winsup/mingw/mingwex/wcstoumax.c
@@ -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);