OSDN Git Service

More rationalization of CRT_INLINE function implementations.
[mingw/mingw-org-wsl.git] / mingwrt / mingwex / strtoumax.c
1 /*
2     This source code was extracted from the Q8 package created and
3     placed in the PUBLIC DOMAIN by Doug Gwyn <gwyn@arl.mil>
4     last edit:  1999/11/05      gwyn@arl.mil
5
6         Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E).
7
8         This particular implementation requires the matching <inttypes.h>.
9         It also assumes that character codes for A..Z and a..z are in
10         contiguous ascending order; this is true for ASCII but not EBCDIC.
11 */
12 #include <stdlib.h>
13 #include <errno.h>
14 #include <ctype.h>
15 #include <inttypes.h>
16
17 /* Helper macros */
18
19 /* convert digit character to number, in any base */
20 #define ToNumber(c)     (isdigit(c) ? (c) - '0' : \
21                          isupper(c) ? (c) - 'A' + 10 : \
22                          islower(c) ? (c) - 'a' + 10 : \
23                          -1             /* "invalid" flag */ \
24                         )
25 /* validate converted digit character for specific base */
26 #define valid(n, b)     ((n) >= 0 && (n) < (b))
27
28 uintmax_t
29 strtoumax(nptr, endptr, base)
30         register const char * __restrict__      nptr;
31         char ** __restrict__                    endptr;
32         register int                            base;
33         {
34         register uintmax_t      accum;  /* accumulates converted value */
35         register uintmax_t      next;   /* for computing next value of accum */
36         register int            n;      /* numeral from digit character */
37         int                     minus;  /* set iff minus sign seen (yes!) */
38         int                     toobig; /* set iff value overflows */
39
40         if ( endptr != NULL )
41                 *endptr = (char *)nptr; /* in case no conversion's performed */
42
43         if ( base < 0 || base == 1 || base > 36 )
44                 {
45                 errno = EDOM;
46                 return 0;               /* unspecified behavior */
47                 }
48
49         /* skip initial, possibly empty sequence of white-space characters */
50
51         while ( isspace(*nptr) )
52                 ++nptr;
53
54         /* process subject sequence: */
55
56         /* optional sign (yes!) */
57
58         if ( (minus = *nptr == '-') || *nptr == '+' )
59                 ++nptr;
60
61         if ( base == 0 )
62         {
63                 if ( *nptr == '0' )
64             {
65                         if ( nptr[1] == 'X' || nptr[1] == 'x' )
66                                 base = 16;
67                         else
68                                 base = 8;
69                     }
70                 else
71                                 base = 10;
72                 }
73
74     /* optional "0x" or "0X" for base 16 */
75
76         if ( base == 16 && *nptr == '0' && (nptr[1] == 'X' || nptr[1] == 'x') )
77                 nptr += 2;              /* skip past this prefix */
78
79         /* check whether there is at least one valid digit */
80
81         n = ToNumber(*nptr);
82         ++nptr;
83
84         if ( !valid(n, base) )
85                 return 0;               /* subject seq. not of expected form */
86
87         accum = n;
88
89         for ( toobig = 0; n = ToNumber(*nptr), valid(n, base); ++nptr )
90                 if ( accum > UINTMAX_MAX / base + 1     /* major wrap-around */
91                   || (next = base * accum + n) < accum  /* minor wrap-around */
92                    )
93                         toobig = 1;     /* but keep scanning */
94                 else
95                         accum = next;
96
97         if ( endptr != NULL )
98                 *endptr = (char *)nptr; /* points to first not-valid-digit */
99
100         if ( toobig )
101                 {
102                 errno = ERANGE;
103                 return UINTMAX_MAX;
104                 }
105         else
106                 return minus ? -accum : accum;  /* (yes!) */
107         }
108
109 unsigned long long __attribute__ ((alias ("strtoumax")))
110 strtoull (const char* __restrict__ nptr, char ** __restrict__ endptr, int base);