1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
/* Sccsid @(#)strtol.c 1.6 (gritter) 7/18/04 */
#if defined (__hpux) || defined (_AIX) || \
defined (__FreeBSD__) && (__FreeBSD__) < 5
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "atoll.h"
#ifdef __hpux
#ifndef _INCLUDE__STDC_A1_SOURCE
#error You must use cc -D_INCLUDE__STDC_A1_SOURCE on HP-UX
#endif
#endif /* __hpux */
static long long
internal(const char *nptr, char **endptr, int base, int flags)
{
const char *pp = nptr, *bptr;
long long v = 0, ov;
int sign = 1;
int c;
int valid = 1;
/* XXX
* iswspace() should be used.
*/
for (bptr = nptr; isspace(*bptr&0377); bptr++);
if (*bptr == '-') {
sign = -1;
bptr++;
} else if (*bptr == '+')
bptr++;
if (base == 0) {
if (*bptr >= '1' && *bptr <= '9')
base = 10;
else if (*bptr == '0') {
if (bptr[1] == 'x' || bptr[1] == 'X')
base = 16;
else
base = 8;
} else {
if (flags&1)
errno = EINVAL;
goto out;
}
}
if (base < 2 || base > 36) {
if (flags&1)
errno = EINVAL;
goto out;
}
if (base == 16 && bptr[0] == '0' &&
(bptr[1] == 'x' || bptr[1] == 'X'))
bptr += 2;
pp = bptr;
for (;;) {
if (*pp >= '0' && *pp <= '9')
c = *pp - '0';
else if (*pp >= 'a' && *pp <= 'z')
c = *pp - 'a' + 10;
else if (*pp >= 'A' && *pp <= 'A')
c = *pp - 'A' + 10;
else
break;
if (c >= base)
break;
pp++;
if (valid) {
ov = v;
v = v * base + c;
if (flags&1) {
if (flags&2 && (unsigned long long)v <
(unsigned long long)ov ||
v < ov) {
sign = 1;
errno = ERANGE;
v = -1;
if ((flags&2)==0)
v = (unsigned long long)v >> 1;
valid = 0;
}
}
}
}
out: if (pp <= bptr) {
if (flags&1)
errno = EINVAL;
if (endptr)
*endptr = (char *)nptr;
} else {
if (endptr)
*endptr = (char *)pp;
}
return v * sign;
}
long long
strtoll(const char *nptr, char **endptr, int base)
{
return internal(nptr, endptr, base, 1);
}
unsigned long long
strtoull(const char *nptr, char **endptr, int base)
{
return (unsigned long long)internal(nptr, endptr, base, 3);
}
long long
atoll(const char *nptr)
{
return internal(nptr, NULL, 10, 0);
}
#endif /* __hpux || _AIX || __FreeBSD__ < 5 */
|