blob: d641e00d536fdafdd8cb5ec6ecd968afdaf67978 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2** Copyright 2001, Travis Geiselbrecht. All rights reserved.
3** Distributed under the terms of the NewOS License.
4*/
5/*
6 * Copyright (c) 2008 Travis Geiselbrecht
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files
10 * (the "Software"), to deal in the Software without restriction,
11 * including without limitation the rights to use, copy, modify, merge,
12 * publish, distribute, sublicense, and/or sell copies of the Software,
13 * and to permit persons to whom the Software is furnished to do so,
14 * subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <stdlib.h>
29#include <ctype.h>
30#include <errno.h>
31
32#define LONG_IS_INT 1
33
34static int hexval(char c)
35{
36 if (c >= '0' && c <= '9')
37 return c - '0';
38 else if (c >= 'a' && c <= 'f')
39 return c - 'a' + 10;
40 else if (c >= 'A' && c <= 'F')
41 return c - 'A' + 10;
42
43 return 0;
44}
45
46int atoi(const char *num)
47{
48#if !LONG_IS_INT
49 // XXX fail
50#else
51 return atol(num);
52#endif
53}
54
55unsigned int atoui(const char *num)
56{
57#if !LONG_IS_INT
58 // XXX fail
59#else
60 return atoul(num);
61#endif
62}
63
64long atol(const char *num)
65{
66 long value = 0;
67 int neg = 0;
68
69 if (num[0] == '0' && num[1] == 'x') {
70 // hex
71 num += 2;
72 while (*num && isxdigit(*num))
73 value = value * 16 + hexval(*num++);
74 } else {
75 // decimal
76 if (num[0] == '-') {
77 neg = 1;
78 num++;
79 }
80 while (*num && isdigit(*num))
81 value = value * 10 + *num++ - '0';
82 }
83
84 if (neg)
85 value = -value;
86
87 return value;
88}
89
90unsigned long atoul(const char *num)
91{
92 unsigned long value = 0;
93 if (num[0] == '0' && num[1] == 'x') {
94 // hex
95 num += 2;
96 while (*num && isxdigit(*num))
97 value = value * 16 + hexval(*num++);
98 } else {
99 // decimal
100 while (*num && isdigit(*num))
101 value = value * 10 + *num++ - '0';
102 }
103
104 return value;
105}
106
107unsigned long long atoull(const char *num)
108{
109 unsigned long long value = 0;
110 if (num[0] == '0' && num[1] == 'x') {
111 // hex
112 num += 2;
113 while (*num && isxdigit(*num))
114 value = value * 16 + hexval(*num++);
115 } else {
116 // decimal
117 while (*num && isdigit(*num))
118 value = value * 10 + *num++ - '0';
119 }
120
121 return value;
122}
123
124unsigned long strtoul(const char *nptr, char **endptr, int base)
125{
126 int neg = 0;
127 unsigned long ret = 0;
128
129 if (base < 0 || base == 1 || base > 36) {
130 errno = EINVAL;
131 return 0;
132 }
133
134 while (isspace(*nptr)) {
135 nptr++;
136 }
137
138 if (*nptr == '+') {
139 nptr++;
140 } else if (*nptr == '-') {
141 neg = 1;
142 nptr++;
143 }
144
145 if ((base == 0 || base == 16) && nptr[0] == '0' && nptr[1] == 'x') {
146 base = 16;
147 nptr += 2;
148 } else if (base == 0 && nptr[0] == '0') {
149 base = 8;
150 nptr++;
151 } else if (base == 0) {
152 base = 10;
153 }
154
155 for (;;) {
156 char c = *nptr;
157 int v = -1;
158 unsigned long new_ret;
159
160 if (c >= 'A' && c <= 'Z') {
161 v = c - 'A' + 10;
162 } else if (c >= 'a' && c <= 'z') {
163 v = c - 'a' + 10;
164 } else if (c >= '0' && c <= '9') {
165 v = c - '0';
166 }
167
168 if (v < 0 || v >= base) {
169 *endptr = (char *) nptr;
170 break;
171 }
172
173 new_ret = ret * base;
174 if (new_ret / base != ret ||
175 new_ret + v < new_ret ||
176 ret == ULONG_MAX) {
177 ret = ULONG_MAX;
178 errno = ERANGE;
179 } else {
180 ret = new_ret + v;
181 }
182
183 nptr++;
184 }
185
186 if (neg && ret != ULONG_MAX) {
187 ret = -ret;
188 }
189
190 return ret;
191}