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