OSDN Git Service

Adjust repository version following WSL-5.2.2 release.
[mingw/mingw-org-wsl.git] / mingwrt / mingwex / strtoimax.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 intmax_t
29 strtoimax(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 int            n;      /* numeral from digit character */
36         int                     minus;  /* set iff minus sign seen */
37         int                     toobig; /* set iff value overflows */
38
39         if ( endptr != NULL )
40                 *endptr = (char *)nptr; /* in case no conversion's performed */
41
42         if ( base < 0 || base == 1 || base > 36 )
43                 {
44                 errno = EDOM;
45                 return 0;               /* unspecified behavior */
46                 }
47
48         /* skip initial, possibly empty sequence of white-space characters */
49
50         while ( isspace(*nptr) )
51                 ++nptr;
52
53         /* process subject sequence: */
54
55         /* optional sign */
56         if ( (minus = *nptr == '-') || *nptr == '+' )
57                 ++nptr;
58
59         if ( base == 0 ) {
60                 if ( *nptr == '0' ) {
61                         if ( nptr[1] == 'X' || nptr[1] == 'x' )
62                                 base = 16;
63                         else
64                                 base = 8;
65                 }
66                 else
67                                 base = 10;
68         }
69         /* optional "0x" or "0X" for base 16 */
70
71         if ( base == 16 && *nptr == '0' && (nptr[1] == 'X' || nptr[1] == 'x') )
72                 nptr += 2;              /* skip past this prefix */
73
74         /* check whether there is at least one valid digit */
75
76         n = ToNumber(*nptr);
77         ++nptr;
78
79         if ( !valid(n, base) )
80                 return 0;               /* subject seq. not of expected form */
81
82         accum = n;
83
84         for ( toobig = 0; n = ToNumber(*nptr), valid(n, base); ++nptr )
85                 if ( accum > (uintmax_t)(INTMAX_MAX / base + 2) ) /* major wrap-around */
86                         toobig = 1;     /* but keep scanning */
87                 else
88                         accum = base * accum + n;
89
90         if ( endptr != NULL )
91                 *endptr = (char *)nptr; /* points to first not-valid-digit */
92
93         if ( minus )
94                 {
95                 if ( accum > (uintmax_t)INTMAX_MAX + 1 )
96                         toobig = 1;
97                 }
98         else
99         if ( accum > (uintmax_t)INTMAX_MAX )
100                 toobig = 1;
101
102         if ( toobig )
103                 {
104                 errno = ERANGE;
105                 return minus ? INTMAX_MIN : INTMAX_MAX;
106                 }
107         else
108                 return (intmax_t)(minus ? -accum : accum);
109         }
110
111 long long __attribute__ ((alias ("strtoimax")))
112 strtoll (const char* __restrict__ nptr, char ** __restrict__ endptr, int base);