1*4d5abbe8Smrg /*-
2*4d5abbe8Smrg * Copyright (c) 2014 The Regents of the University of California.
3*4d5abbe8Smrg * All rights reserved.
4*4d5abbe8Smrg *
5*4d5abbe8Smrg * Redistribution and use in source and binary forms, with or without
6*4d5abbe8Smrg * modification, are permitted provided that the following conditions
7*4d5abbe8Smrg * are met:
8*4d5abbe8Smrg * 1. Redistributions of source code must retain the above copyright
9*4d5abbe8Smrg * notice, this list of conditions and the following disclaimer.
10*4d5abbe8Smrg * 2. Redistributions in binary form must reproduce the above copyright
11*4d5abbe8Smrg * notice, this list of conditions and the following disclaimer in the
12*4d5abbe8Smrg * documentation and/or other materials provided with the distribution.
13*4d5abbe8Smrg * 3. [rescinded 22 July 1999]
14*4d5abbe8Smrg * 4. Neither the name of the University nor the names of its contributors
15*4d5abbe8Smrg * may be used to endorse or promote products derived from this software
16*4d5abbe8Smrg * without specific prior written permission.
17*4d5abbe8Smrg *
18*4d5abbe8Smrg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19*4d5abbe8Smrg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*4d5abbe8Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*4d5abbe8Smrg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22*4d5abbe8Smrg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*4d5abbe8Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*4d5abbe8Smrg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*4d5abbe8Smrg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*4d5abbe8Smrg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*4d5abbe8Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*4d5abbe8Smrg * SUCH DAMAGE.
29*4d5abbe8Smrg */
30*4d5abbe8Smrg
31*4d5abbe8Smrg /*
32*4d5abbe8Smrg
33*4d5abbe8Smrg @deftypefn Supplemental {long long int} strtoll (const char *@var{string}, @
34*4d5abbe8Smrg char **@var{endptr}, int @var{base})
35*4d5abbe8Smrg @deftypefnx Supplemental {unsigned long long int} strtoul (@
36*4d5abbe8Smrg const char *@var{string}, char **@var{endptr}, int @var{base})
37*4d5abbe8Smrg
38*4d5abbe8Smrg The @code{strtoll} function converts the string in @var{string} to a
39*4d5abbe8Smrg long long integer value according to the given @var{base}, which must be
40*4d5abbe8Smrg between 2 and 36 inclusive, or be the special value 0. If @var{base}
41*4d5abbe8Smrg is 0, @code{strtoll} will look for the prefixes @code{0} and @code{0x}
42*4d5abbe8Smrg to indicate bases 8 and 16, respectively, else default to base 10.
43*4d5abbe8Smrg When the base is 16 (either explicitly or implicitly), a prefix of
44*4d5abbe8Smrg @code{0x} is allowed. The handling of @var{endptr} is as that of
45*4d5abbe8Smrg @code{strtod} above. The @code{strtoull} function is the same, except
46*4d5abbe8Smrg that the converted value is unsigned.
47*4d5abbe8Smrg
48*4d5abbe8Smrg @end deftypefn
49*4d5abbe8Smrg
50*4d5abbe8Smrg */
51*4d5abbe8Smrg
52*4d5abbe8Smrg #ifdef HAVE_CONFIG_H
53*4d5abbe8Smrg #include "config.h"
54*4d5abbe8Smrg #endif
55*4d5abbe8Smrg #ifdef HAVE_LIMITS_H
56*4d5abbe8Smrg #include <limits.h>
57*4d5abbe8Smrg #endif
58*4d5abbe8Smrg #ifdef HAVE_SYS_PARAM_H
59*4d5abbe8Smrg #include <sys/param.h>
60*4d5abbe8Smrg #endif
61*4d5abbe8Smrg #include <errno.h>
62*4d5abbe8Smrg #ifdef NEED_DECLARATION_ERRNO
63*4d5abbe8Smrg extern int errno;
64*4d5abbe8Smrg #endif
65*4d5abbe8Smrg #include "safe-ctype.h"
66*4d5abbe8Smrg
67*4d5abbe8Smrg #ifdef HAVE_LONG_LONG
68*4d5abbe8Smrg
69*4d5abbe8Smrg __extension__
70*4d5abbe8Smrg typedef unsigned long long ullong_type;
71*4d5abbe8Smrg
72*4d5abbe8Smrg __extension__
73*4d5abbe8Smrg typedef long long llong_type;
74*4d5abbe8Smrg
75*4d5abbe8Smrg /* FIXME: It'd be nice to configure around these, but the include files are too
76*4d5abbe8Smrg painful. These macros should at least be more portable than hardwired hex
77*4d5abbe8Smrg constants. */
78*4d5abbe8Smrg
79*4d5abbe8Smrg #ifndef ULLONG_MAX
80*4d5abbe8Smrg #define ULLONG_MAX (~(ullong_type)0) /* 0xFFFFFFFFFFFFFFFF */
81*4d5abbe8Smrg #endif
82*4d5abbe8Smrg
83*4d5abbe8Smrg #ifndef LLONG_MAX
84*4d5abbe8Smrg #define LLONG_MAX ((llong_type)(ULLONG_MAX >> 1)) /* 0x7FFFFFFFFFFFFFFF */
85*4d5abbe8Smrg #endif
86*4d5abbe8Smrg
87*4d5abbe8Smrg #ifndef LLONG_MIN
88*4d5abbe8Smrg #define LLONG_MIN (~LLONG_MAX) /* 0x8000000000000000 */
89*4d5abbe8Smrg #endif
90*4d5abbe8Smrg
91*4d5abbe8Smrg /*
92*4d5abbe8Smrg * Convert a string to a long long integer.
93*4d5abbe8Smrg *
94*4d5abbe8Smrg * Ignores `locale' stuff. Assumes that the upper and lower case
95*4d5abbe8Smrg * alphabets and digits are each contiguous.
96*4d5abbe8Smrg */
97*4d5abbe8Smrg llong_type
strtoll(const char * nptr,char ** endptr,register int base)98*4d5abbe8Smrg strtoll(const char *nptr, char **endptr, register int base)
99*4d5abbe8Smrg {
100*4d5abbe8Smrg register const char *s = nptr;
101*4d5abbe8Smrg register ullong_type acc;
102*4d5abbe8Smrg register int c;
103*4d5abbe8Smrg register ullong_type cutoff;
104*4d5abbe8Smrg register int neg = 0, any, cutlim;
105*4d5abbe8Smrg
106*4d5abbe8Smrg /*
107*4d5abbe8Smrg * Skip white space and pick up leading +/- sign if any.
108*4d5abbe8Smrg * If base is 0, allow 0x for hex and 0 for octal, else
109*4d5abbe8Smrg * assume decimal; if base is already 16, allow 0x.
110*4d5abbe8Smrg */
111*4d5abbe8Smrg do {
112*4d5abbe8Smrg c = *s++;
113*4d5abbe8Smrg } while (ISSPACE(c));
114*4d5abbe8Smrg if (c == '-') {
115*4d5abbe8Smrg neg = 1;
116*4d5abbe8Smrg c = *s++;
117*4d5abbe8Smrg } else if (c == '+')
118*4d5abbe8Smrg c = *s++;
119*4d5abbe8Smrg if ((base == 0 || base == 16) &&
120*4d5abbe8Smrg c == '0' && (*s == 'x' || *s == 'X')) {
121*4d5abbe8Smrg c = s[1];
122*4d5abbe8Smrg s += 2;
123*4d5abbe8Smrg base = 16;
124*4d5abbe8Smrg }
125*4d5abbe8Smrg if (base == 0)
126*4d5abbe8Smrg base = c == '0' ? 8 : 10;
127*4d5abbe8Smrg
128*4d5abbe8Smrg /*
129*4d5abbe8Smrg * Compute the cutoff value between legal numbers and illegal
130*4d5abbe8Smrg * numbers. That is the largest legal value, divided by the
131*4d5abbe8Smrg * base. An input number that is greater than this value, if
132*4d5abbe8Smrg * followed by a legal input character, is too big. One that
133*4d5abbe8Smrg * is equal to this value may be valid or not; the limit
134*4d5abbe8Smrg * between valid and invalid numbers is then based on the last
135*4d5abbe8Smrg * digit. For instance, if the range for longs is
136*4d5abbe8Smrg * [-2147483648..2147483647] and the input base is 10,
137*4d5abbe8Smrg * cutoff will be set to 214748364 and cutlim to either
138*4d5abbe8Smrg * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
139*4d5abbe8Smrg * a value > 214748364, or equal but the next digit is > 7 (or 8),
140*4d5abbe8Smrg * the number is too big, and we will return a range error.
141*4d5abbe8Smrg *
142*4d5abbe8Smrg * Set any if any `digits' consumed; make it negative to indicate
143*4d5abbe8Smrg * overflow.
144*4d5abbe8Smrg */
145*4d5abbe8Smrg cutoff = neg ? -(ullong_type)LLONG_MIN : LLONG_MAX;
146*4d5abbe8Smrg cutlim = cutoff % (ullong_type)base;
147*4d5abbe8Smrg cutoff /= (ullong_type)base;
148*4d5abbe8Smrg for (acc = 0, any = 0;; c = *s++) {
149*4d5abbe8Smrg if (ISDIGIT(c))
150*4d5abbe8Smrg c -= '0';
151*4d5abbe8Smrg else if (ISALPHA(c))
152*4d5abbe8Smrg c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10;
153*4d5abbe8Smrg else
154*4d5abbe8Smrg break;
155*4d5abbe8Smrg if (c >= base)
156*4d5abbe8Smrg break;
157*4d5abbe8Smrg if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
158*4d5abbe8Smrg any = -1;
159*4d5abbe8Smrg else {
160*4d5abbe8Smrg any = 1;
161*4d5abbe8Smrg acc *= base;
162*4d5abbe8Smrg acc += c;
163*4d5abbe8Smrg }
164*4d5abbe8Smrg }
165*4d5abbe8Smrg if (any < 0) {
166*4d5abbe8Smrg acc = neg ? LLONG_MIN : LLONG_MAX;
167*4d5abbe8Smrg errno = ERANGE;
168*4d5abbe8Smrg } else if (neg)
169*4d5abbe8Smrg acc = -acc;
170*4d5abbe8Smrg if (endptr != 0)
171*4d5abbe8Smrg *endptr = (char *) (any ? s - 1 : nptr);
172*4d5abbe8Smrg return (acc);
173*4d5abbe8Smrg }
174*4d5abbe8Smrg
175*4d5abbe8Smrg #endif /* ifdef HAVE_LONG_LONG */
176