#include #include #include #include #include #include #include #include #include template static T string_to_integer_type(const char* str) { bool neg = false; T val = 0; switch (*str) { case '-': neg = true; str++; break; case '+': str++; break; default: break; } while (isdigit(*str)) { val = (10 * val) + (*str++ - '0'); } return (neg ? -val : val); } template static T string_to_float_type(const char* str) { bool neg = false; T val = 0; T small = 0; switch (*str) { case '-': neg = true; str++; break; case '+': str++; break; default: break; } while (isdigit(*str)) { val = (10 * val) + (T)(*str++ - '0'); } if (*str == '.') { str++; T div = 10; while (isdigit(*str)) { small = small + (T)(*str++ - '0') / div; div *= 10; } val += small; } return (neg ? -val : val); } template static inline Struct common_div(Arg a, Arg b) { Struct result; result.quot = a / b; result.rem = a % b; if (a >= 0 && result.rem < 0) { result.quot++; result.rem -= b; } return result; } static void qswap(void* ptr1, void* ptr2, size_t size) { char* x = (char*)ptr1; char* y = (char*)ptr2; while (size--) { char t = *x; *x = *y; *y = t; x += 1; y += 1; } } static size_t partition(void* base, size_t start, size_t end, size_t size, int (*compar)(const void*, const void*)) { auto atindex = [&base, &size](size_t index) { return (void*)((char*)base + (index * size)); }; void* pivot = atindex(end); size_t i = (start - 1); for (size_t j = start; j <= end - 1; j++) { if (compar(atindex(j), pivot) < 0) { i++; qswap(atindex(i), atindex(j), size); } } qswap(atindex(i + 1), pivot, size); return i + 1; } static void quicksort(void* base, size_t start, size_t end, size_t size, int (*compar)(const void*, const void*)) { if (start < end) { size_t pivot = partition(base, start, end, size, compar); quicksort(base, start, pivot - 1, size, compar); quicksort(base, pivot + 1, end, size, compar); } } void* binary_search(const void* key, const void* base, size_t start, size_t end, size_t size, int (*compar)(const void*, const void*)) { auto atindex = [&base, &size](size_t index) { return (const void*)((const char*)base + (index * size)); }; if (end >= start) { size_t middle = start + (end - start) / 2; int rc = compar(atindex(middle), key); if (rc == 0) return const_cast(atindex(middle)); // we found it!! if (rc < 0) return binary_search(key, base, middle + 1, end, size, compar); return binary_search(key, base, start, middle - 1, size, compar); } return NULL; } extern "C" { __lc_noreturn void abort() { _Exit(-1); } float atof(const char* str) { return string_to_float_type(str); } int atoi(const char* str) { return string_to_integer_type(str); } long atol(const char* str) { return string_to_integer_type(str); } long long atoll(const char* str) { return string_to_integer_type(str); } unsigned long strtoul(const char* str, char** endptr, int base) { if (base != 0 && base != 10) NOT_IMPLEMENTED("strtoul with base not in (0,10)"); if (endptr) NOT_IMPLEMENTED("strtoul with non-null endptr"); return string_to_integer_type(str); } long strtol(const char* str, char** endptr, int base) { if (base != 0 && base != 10) NOT_IMPLEMENTED("strtol with base not in (0,10)"); if (endptr) NOT_IMPLEMENTED("strtol with non-null endptr"); return string_to_integer_type(str); } char* getenv(const char*) { return NULL; // FIXME: Not implemented :) } __lc_noreturn void _Exit(int status) { __lc_fast_syscall1(SYS_exit, status); __lc_unreachable(); } int abs(int val) { return __builtin_abs(val); } long labs(long val) { return __builtin_labs(val); } long long llabs(long long val) { return __builtin_llabs(val); } div_t div(int a, int b) { return common_div(a, b); } ldiv_t ldiv(long a, long b) { return common_div(a, b); } lldiv_t lldiv(long long a, long long b) { return common_div(a, b); } int system(const char* command) { pid_t child = fork(); if (child < 0) return -1; if (child == 0) { char* argv[] = {const_cast("/bin/sh"), const_cast("-c"), const_cast(command), nullptr}; // FIXME: This is very verbose. execv(argv[0], argv); exit(127); } int status; waitpid(child, &status, 0); return status; } void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)) { quicksort(base, 0, nmemb - 1, size, compar); } void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)) { return binary_search(key, base, 0, nmemb - 1, size, compar); } size_t mbstowcs(wchar_t*, const char*, size_t) { NOT_IMPLEMENTED("mbstowcs"); } static void gentemp(char* startptr) { for (int i = 0; i < 6; i++) { startptr[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"[rand() % 63]; } } char* mktemp(char* str) { size_t len = strlen(str); if (len < 6) { errno = EINVAL; return NULL; } char* startptr = str + (len - 6); if (strncmp(startptr, "XXXXXX", 6)) { errno = EINVAL; return NULL; } do { gentemp(startptr); } while (access(str, F_OK) == 0); return str; } char* mkdtemp(char* str) { size_t len = strlen(str); if (len < 6) { errno = EINVAL; return NULL; } char* startptr = str + (len - 6); if (strncmp(startptr, "XXXXXX", 6)) { errno = EINVAL; return NULL; } do { gentemp(startptr); } while (mkdir(str, 0700) < 0 && errno == EEXIST); if (errno) return NULL; return str; } }