• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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