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 last edit: 1999/11/05 gwyn@arl.mil
10
11 Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E).
12
13 This particular implementation requires the matching <inttypes.h>.
14 It also assumes that character codes for A..Z and a..z are in
15 contiguous ascending order; this is true for ASCII but not EBCDIC.
16 */
17 #include <stdlib.h>
18 #include <errno.h>
19 #include <ctype.h>
20 #include <inttypes.h>
21
22 /* Helper macros */
23
24 /* convert digit character to number, in any base */
25 #define ToNumber(c) (isdigit(c) ? (c) - '0' : \
26 isupper(c) ? (c) - 'A' + 10 : \
27 islower(c) ? (c) - 'a' + 10 : \
28 -1 /* "invalid" flag */ \
29 )
30 /* validate converted digit character for specific base */
31 #define valid(n, b) ((n) >= 0 && (n) < (b))
32
33 intmax_t
strtoimax(nptr,endptr,base)34 strtoimax(nptr, endptr, base)
35 register const char * __restrict__ nptr;
36 char ** __restrict__ endptr;
37 register 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 = (char *)nptr; /* in case no conversion's 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 characters */
54
55 while ( isspace(*nptr) )
56 ++nptr;
57
58 /* process subject sequence: */
59
60 /* optional sign */
61 if ( (minus = *nptr == '-') || *nptr == '+' )
62 ++nptr;
63
64 if ( base == 0 ) {
65 if ( *nptr == '0' ) {
66 if ( nptr[1] == 'X' || nptr[1] == 'x' )
67 base = 16;
68 else
69 base = 8;
70 }
71 else
72 base = 10;
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_t)(INTMAX_MAX / base + 2) ) /* major wrap-around */
91 toobig = 1; /* but keep scanning */
92 else
93 accum = base * accum + n;
94
95 if ( endptr != NULL )
96 *endptr = (char *)nptr; /* points to first not-valid-digit */
97
98 if ( minus )
99 {
100 if ( accum > (uintmax_t)INTMAX_MAX + 1 )
101 toobig = 1;
102 }
103 else
104 if ( accum > (uintmax_t)INTMAX_MAX )
105 toobig = 1;
106
107 if ( toobig )
108 {
109 errno = ERANGE;
110 return minus ? INTMAX_MIN : INTMAX_MAX;
111 }
112 else
113 return (intmax_t)(minus ? -accum : accum);
114 }
115
116 long long __attribute__ ((alias ("strtoimax")))
117 strtoll (const char* __restrict__ nptr, char ** __restrict__ endptr, int base);
118