1 /*
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 /*
33 * Include our own stdlib.h which contains the definitions
34 * for all functions in this file
35 */
36 #include "include/stdlib.h"
37
38 #define LONG_IS_INT 1
39
hexval(char c)40 static int hexval(char c)
41 {
42 if (c >= '0' && c <= '9')
43 return c - '0';
44 else if (c >= 'a' && c <= 'f')
45 return c - 'a' + 10;
46 else if (c >= 'A' && c <= 'F')
47 return c - 'A' + 10;
48
49 return 0;
50 }
51
atoi(const char * num)52 int atoi(const char *num)
53 {
54 #if !LONG_IS_INT
55 // XXX fail
56 #else
57 return atol(num);
58 #endif
59 }
60
atoui(const char * num)61 unsigned int atoui(const char *num)
62 {
63 #if !LONG_IS_INT
64 // XXX fail
65 #else
66 return atoul(num);
67 #endif
68 }
69
atol(const char * num)70 long atol(const char *num)
71 {
72 long value = 0;
73 int neg = 0;
74
75 if (num[0] == '0' && num[1] == 'x') {
76 // hex
77 num += 2;
78 while (*num && isxdigit(*num))
79 value = value * 16 + hexval(*num++);
80 } else {
81 // decimal
82 if (num[0] == '-') {
83 neg = 1;
84 num++;
85 }
86 while (*num && isdigit(*num))
87 value = value * 10 + *num++ - '0';
88 }
89
90 if (neg)
91 value = -value;
92
93 return value;
94 }
95
atoul(const char * num)96 unsigned long atoul(const char *num)
97 {
98 unsigned long value = 0;
99 if (num[0] == '0' && num[1] == 'x') {
100 // hex
101 num += 2;
102 while (*num && isxdigit(*num))
103 value = value * 16 + hexval(*num++);
104 } else {
105 // decimal
106 while (*num && isdigit(*num))
107 value = value * 10 + *num++ - '0';
108 }
109
110 return value;
111 }
112
atoull(const char * num)113 unsigned long long atoull(const char *num)
114 {
115 unsigned long long value = 0;
116 if (num[0] == '0' && num[1] == 'x') {
117 // hex
118 num += 2;
119 while (*num && isxdigit(*num))
120 value = value * 16 + hexval(*num++);
121 } else {
122 // decimal
123 while (*num && isdigit(*num))
124 value = value * 10 + *num++ - '0';
125 }
126
127 return value;
128 }
129
strtoul(const char * nptr,char ** endptr,int base)130 unsigned long strtoul(const char *nptr, char **endptr, int base)
131 {
132 int neg = 0;
133 unsigned long ret = 0;
134
135 if (base < 0 || base == 1 || base > 36) {
136 errno = EINVAL;
137 return 0;
138 }
139
140 while (isspace(*nptr)) {
141 nptr++;
142 }
143
144 if (*nptr == '+') {
145 nptr++;
146 } else if (*nptr == '-') {
147 neg = 1;
148 nptr++;
149 }
150
151 if ((base == 0 || base == 16) && nptr[0] == '0' && nptr[1] == 'x') {
152 base = 16;
153 nptr += 2;
154 } else if (base == 0 && nptr[0] == '0') {
155 base = 8;
156 nptr++;
157 } else if (base == 0) {
158 base = 10;
159 }
160
161 for (;;) {
162 char c = *nptr;
163 int v = -1;
164 unsigned long new_ret;
165
166 if (c >= 'A' && c <= 'Z') {
167 v = c - 'A' + 10;
168 } else if (c >= 'a' && c <= 'z') {
169 v = c - 'a' + 10;
170 } else if (c >= '0' && c <= '9') {
171 v = c - '0';
172 }
173
174 if (v < 0 || v >= base) {
175 if (endptr) {
176 *endptr = (char *) nptr;
177 }
178 break;
179 }
180
181 new_ret = ret * base;
182 if (new_ret / base != ret ||
183 new_ret + v < new_ret ||
184 ret == ULONG_MAX) {
185 ret = ULONG_MAX;
186 errno = ERANGE;
187 } else {
188 ret = new_ret + v;
189 }
190
191 nptr++;
192 }
193
194 if (neg && ret != ULONG_MAX) {
195 ret = -ret;
196 }
197
198 return ret;
199 }
200