stdlib.c (5621B)
1 //===-- stdlib.c - kit freestanding stdlib primitives -------------------===// 2 // 3 // SPDX-License-Identifier: 0BSD 4 //===----------------------------------------------------------------------===// 5 6 #include <stddef.h> 7 8 typedef struct { 9 int quot; 10 int rem; 11 } div_t; 12 13 typedef struct { 14 long quot; 15 long rem; 16 } ldiv_t; 17 18 typedef struct { 19 long long quot; 20 long long rem; 21 } lldiv_t; 22 23 static int kit_isspace(char c) { return c == ' ' || (c >= '\t' && c <= '\r'); } 24 25 static int kit_digit_value(char c) { 26 if (c >= '0' && c <= '9') return c - '0'; 27 if (c >= 'a' && c <= 'z') return c - 'a' + 10; 28 if (c >= 'A' && c <= 'Z') return c - 'A' + 10; 29 return -1; 30 } 31 32 static int kit_match_ci(const char* s, const char* word) { 33 while (*word != '\0') { 34 char a = *s++; 35 char b = *word++; 36 if (a >= 'A' && a <= 'Z') a = (char)(a - 'A' + 'a'); 37 if (a != b) return 0; 38 } 39 return 1; 40 } 41 42 __attribute__((weak)) unsigned long long strtoull(const char* nptr, 43 char** endptr, int base) { 44 const char* s = nptr; 45 int neg = 0; 46 unsigned long long value = 0; 47 int any = 0; 48 49 while (kit_isspace(*s)) s++; 50 if (*s == '+' || *s == '-') neg = *s++ == '-'; 51 52 if ((base == 0 || base == 16) && s[0] == '0' && 53 (s[1] == 'x' || s[1] == 'X')) { 54 int d = kit_digit_value(s[2]); 55 if (d >= 0 && d < 16) { 56 s += 2; 57 base = 16; 58 } 59 } 60 if (base == 0) base = (*s == '0') ? 8 : 10; 61 if (base < 2 || base > 36) { 62 if (endptr) *endptr = (char*)nptr; 63 return 0; 64 } 65 66 for (;;) { 67 int d = kit_digit_value(*s); 68 if (d < 0 || d >= base) break; 69 value = value * (unsigned)base + (unsigned)d; 70 s++; 71 any = 1; 72 } 73 74 if (endptr) *endptr = (char*)(any ? s : nptr); 75 return neg ? 0 - value : value; 76 } 77 78 __attribute__((weak)) unsigned long strtoul(const char* nptr, char** endptr, 79 int base) { 80 return (unsigned long)strtoull(nptr, endptr, base); 81 } 82 83 __attribute__((weak)) long long strtoll(const char* nptr, char** endptr, 84 int base) { 85 return (long long)strtoull(nptr, endptr, base); 86 } 87 88 __attribute__((weak)) long strtol(const char* nptr, char** endptr, int base) { 89 return (long)strtoull(nptr, endptr, base); 90 } 91 92 __attribute__((weak)) long long atoll(const char* nptr) { 93 return strtoll(nptr, NULL, 10); 94 } 95 __attribute__((weak)) long atol(const char* nptr) { 96 return strtol(nptr, NULL, 10); 97 } 98 __attribute__((weak)) int atoi(const char* nptr) { 99 return (int)strtol(nptr, NULL, 10); 100 } 101 102 static long double kit_strtold_impl(const char* nptr, char** endptr) { 103 const char* s = nptr; 104 int neg = 0; 105 int any = 0; 106 long double value = 0.0L; 107 108 while (kit_isspace(*s)) s++; 109 if (*s == '+' || *s == '-') neg = *s++ == '-'; 110 111 if (kit_match_ci(s, "infinity")) { 112 if (endptr) *endptr = (char*)(s + 8); 113 return neg ? -(1.0L / 0.0L) : (1.0L / 0.0L); 114 } 115 if (kit_match_ci(s, "inf")) { 116 if (endptr) *endptr = (char*)(s + 3); 117 return neg ? -(1.0L / 0.0L) : (1.0L / 0.0L); 118 } 119 if (kit_match_ci(s, "nan")) { 120 if (endptr) *endptr = (char*)(s + 3); 121 return 0.0L / 0.0L; 122 } 123 124 while (*s >= '0' && *s <= '9') { 125 value = value * 10.0L + (long double)(*s - '0'); 126 s++; 127 any = 1; 128 } 129 130 if (*s == '.') { 131 long double place = 0.1L; 132 s++; 133 while (*s >= '0' && *s <= '9') { 134 value += (long double)(*s - '0') * place; 135 place *= 0.1L; 136 s++; 137 any = 1; 138 } 139 } 140 141 if (!any) { 142 if (endptr) *endptr = (char*)nptr; 143 return 0.0L; 144 } 145 146 if (*s == 'e' || *s == 'E') { 147 const char* exp_start = s; 148 int exp_neg = 0; 149 int exp_any = 0; 150 int exp = 0; 151 s++; 152 if (*s == '+' || *s == '-') exp_neg = *s++ == '-'; 153 while (*s >= '0' && *s <= '9') { 154 exp = exp * 10 + (*s - '0'); 155 s++; 156 exp_any = 1; 157 } 158 if (exp_any) { 159 while (exp-- > 0) value = exp_neg ? value / 10.0L : value * 10.0L; 160 } else { 161 s = exp_start; 162 } 163 } 164 165 if (endptr) *endptr = (char*)s; 166 return neg ? -value : value; 167 } 168 169 __attribute__((weak)) long double strtold(const char* nptr, char** endptr) { 170 return kit_strtold_impl(nptr, endptr); 171 } 172 173 __attribute__((weak)) double strtod(const char* nptr, char** endptr) { 174 return (double)kit_strtold_impl(nptr, endptr); 175 } 176 177 __attribute__((weak)) float strtof(const char* nptr, char** endptr) { 178 return (float)kit_strtold_impl(nptr, endptr); 179 } 180 181 __attribute__((weak)) int abs(int j) { return j < 0 ? -j : j; } 182 __attribute__((weak)) long labs(long j) { return j < 0 ? -j : j; } 183 __attribute__((weak)) long long llabs(long long j) { return j < 0 ? -j : j; } 184 185 __attribute__((weak)) div_t div(int numer, int denom) { 186 div_t r; 187 r.quot = numer / denom; 188 r.rem = numer % denom; 189 return r; 190 } 191 192 __attribute__((weak)) ldiv_t ldiv(long numer, long denom) { 193 ldiv_t r; 194 r.quot = numer / denom; 195 r.rem = numer % denom; 196 return r; 197 } 198 199 __attribute__((weak)) lldiv_t lldiv(long long numer, long long denom) { 200 lldiv_t r; 201 r.quot = numer / denom; 202 r.rem = numer % denom; 203 return r; 204 } 205 206 __attribute__((weak)) void* bsearch(const void* key, const void* base, 207 size_t nmemb, size_t size, 208 int (*compar)(const void*, const void*)) { 209 const unsigned char* b = (const unsigned char*)base; 210 size_t low = 0; 211 size_t high = nmemb; 212 213 while (low < high) { 214 size_t mid = low + (high - low) / 2; 215 const void* elem = b + mid * size; 216 int cmp = compar(key, elem); 217 if (cmp < 0) { 218 high = mid; 219 } else if (cmp > 0) { 220 low = mid + 1; 221 } else { 222 return (void*)elem; 223 } 224 } 225 return NULL; 226 }