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 * Use of this source code is governed by a MIT-style 9 * license that can be found in the LICENSE file or at 10 * https://opensource.org/licenses/MIT 11 */ 12 13 #include <stdlib.h> 14 #include <ctype.h> 15 #include <errno.h> 16 17 #define LONG_IS_INT 1 18 hexval(char c)19static int hexval(char c) { 20 if (c >= '0' && c <= '9') 21 return c - '0'; 22 else if (c >= 'a' && c <= 'f') 23 return c - 'a' + 10; 24 else if (c >= 'A' && c <= 'F') 25 return c - 'A' + 10; 26 27 return 0; 28 } 29 atoi(const char * num)30int atoi(const char *num) { 31 #if !LONG_IS_INT 32 // XXX fail 33 #else 34 return atol(num); 35 #endif 36 } 37 atoui(const char * num)38unsigned int atoui(const char *num) { 39 #if !LONG_IS_INT 40 // XXX fail 41 #else 42 return atoul(num); 43 #endif 44 } 45 atol(const char * num)46long atol(const char *num) { 47 long value = 0; 48 int neg = 0; 49 50 if (num[0] == '0' && num[1] == 'x') { 51 // hex 52 num += 2; 53 while (*num && isxdigit(*num)) 54 value = value * 16 + hexval(*num++); 55 } else { 56 // decimal 57 if (num[0] == '-') { 58 neg = 1; 59 num++; 60 } 61 while (*num && isdigit(*num)) 62 value = value * 10 + *num++ - '0'; 63 } 64 65 if (neg) 66 value = -value; 67 68 return value; 69 } 70 atoul(const char * num)71unsigned long atoul(const char *num) { 72 unsigned long value = 0; 73 if (num[0] == '0' && num[1] == 'x') { 74 // hex 75 num += 2; 76 while (*num && isxdigit(*num)) 77 value = value * 16 + hexval(*num++); 78 } else { 79 // decimal 80 while (*num && isdigit(*num)) 81 value = value * 10 + *num++ - '0'; 82 } 83 84 return value; 85 } 86 atoull(const char * num)87unsigned long long atoull(const char *num) { 88 unsigned long long value = 0; 89 if (num[0] == '0' && num[1] == 'x') { 90 // hex 91 num += 2; 92 while (*num && isxdigit(*num)) 93 value = value * 16 + hexval(*num++); 94 } else { 95 // decimal 96 while (*num && isdigit(*num)) 97 value = value * 10 + *num++ - '0'; 98 } 99 100 return value; 101 } 102 strtoul(const char * nptr,char ** endptr,int base)103unsigned long strtoul(const char *nptr, char **endptr, int base) { 104 int neg = 0; 105 unsigned long ret = 0; 106 107 if (base < 0 || base == 1 || base > 36) { 108 errno = EINVAL; 109 return 0; 110 } 111 112 while (isspace(*nptr)) { 113 nptr++; 114 } 115 116 if (*nptr == '+') { 117 nptr++; 118 } else if (*nptr == '-') { 119 neg = 1; 120 nptr++; 121 } 122 123 if ((base == 0 || base == 16) && nptr[0] == '0' && nptr[1] == 'x') { 124 base = 16; 125 nptr += 2; 126 } else if (base == 0 && nptr[0] == '0') { 127 base = 8; 128 nptr++; 129 } else if (base == 0) { 130 base = 10; 131 } 132 133 for (;;) { 134 char c = *nptr; 135 int v = -1; 136 unsigned long new_ret; 137 138 if (c >= 'A' && c <= 'Z') { 139 v = c - 'A' + 10; 140 } else if (c >= 'a' && c <= 'z') { 141 v = c - 'a' + 10; 142 } else if (c >= '0' && c <= '9') { 143 v = c - '0'; 144 } 145 146 if (v < 0 || v >= base) { 147 if (endptr) { 148 *endptr = (char *) nptr; 149 } 150 break; 151 } 152 153 new_ret = ret * base; 154 if (new_ret / base != ret || 155 new_ret + v < new_ret || 156 ret == ULONG_MAX) { 157 ret = ULONG_MAX; 158 errno = ERANGE; 159 } else { 160 ret = new_ret + v; 161 } 162 163 nptr++; 164 } 165 166 if (neg && ret != ULONG_MAX) { 167 ret = -ret; 168 } 169 170 return ret; 171 } 172