diff options
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibC/stdlib.cpp | 188 | ||||
-rw-r--r-- | Libraries/LibC/stdlib.h | 1 | ||||
-rw-r--r-- | Libraries/LibC/unistd.cpp | 14 | ||||
-rw-r--r-- | Libraries/LibC/unistd.h | 1 |
4 files changed, 102 insertions, 102 deletions
diff --git a/Libraries/LibC/stdlib.cpp b/Libraries/LibC/stdlib.cpp index b4d2a97fa4..d0dc63e9fb 100644 --- a/Libraries/LibC/stdlib.cpp +++ b/Libraries/LibC/stdlib.cpp @@ -18,6 +18,92 @@ #include <sys/wait.h> #include <unistd.h> +template<typename T, T min_value, T max_value> +static inline T strtol_impl(const char* nptr, char** endptr, int base) +{ + errno = 0; + + if (base < 0 || base == 1 || base > 36) { + errno = EINVAL; + if (endptr) + *endptr = const_cast<char*>(nptr); + return 0; + } + + const char* p = nptr; + while (isspace(*p)) + ++p; + + bool is_negative = false; + if (*p == '-') { + is_negative = true; + ++p; + } else { + if (*p == '+') + ++p; + } + + if (base == 0 || base == 16) { + if (base == 0) + base = 10; + if (*p == '0') { + if (*(p + 1) == 'X' || *(p + 1) == 'x') { + p += 2; + base = 16; + } else if (base != 16) { + base = 8; + } + } + } + + long cutoff_point = is_negative ? (min_value / base) : (max_value / base); + int max_valid_digit_at_cutoff_point = is_negative ? (min_value % base) : (max_value % base); + + long num = 0; + + bool has_overflowed = false; + unsigned digits_consumed = 0; + + for (;;) { + char ch = *(p++); + int digit; + if (isdigit(ch)) + digit = ch - '0'; + else if (islower(ch)) + digit = ch - ('a' - 10); + else if (isupper(ch)) + digit = ch - ('A' - 10); + else + break; + + if (digit >= base) + break; + + if (has_overflowed) + continue; + + bool is_past_cutoff = is_negative ? num < cutoff_point : num > cutoff_point; + + if (is_past_cutoff || (num == cutoff_point && digit > max_valid_digit_at_cutoff_point)) { + has_overflowed = true; + num = is_negative ? min_value : max_value; + errno = ERANGE; + } else { + num *= base; + num += is_negative ? -digit : digit; + ++digits_consumed; + } + } + + if (endptr) { + if (has_overflowed || digits_consumed > 0) + *endptr = const_cast<char*>(p - 1); + else + *endptr = const_cast<char*>(nptr); + } + return num; +} + extern "C" { typedef void (*__atexit_handler)(); @@ -167,7 +253,6 @@ int putenv(char* new_var) environ = new_environ; return 0; } -} double strtod(const char* str, char** endptr) { @@ -503,92 +588,6 @@ size_t wcstombs(char* dest, const wchar_t* src, size_t max) return max; } -template<typename T, T min_value, T max_value> -static T strtol_impl(const char* nptr, char** endptr, int base) -{ - errno = 0; - - if (base < 0 || base == 1 || base > 36) { - errno = EINVAL; - if (endptr) - *endptr = const_cast<char*>(nptr); - return 0; - } - - const char* p = nptr; - while (isspace(*p)) - ++p; - - bool is_negative = false; - if (*p == '-') { - is_negative = true; - ++p; - } else { - if (*p == '+') - ++p; - } - - if (base == 0 || base == 16) { - if (base == 0) - base = 10; - if (*p == '0') { - if (*(p + 1) == 'X' || *(p + 1) == 'x') { - p += 2; - base = 16; - } else if (base != 16) { - base = 8; - } - } - } - - long cutoff_point = is_negative ? (min_value / base) : (max_value / base); - int max_valid_digit_at_cutoff_point = is_negative ? (min_value % base) : (max_value % base); - - long num = 0; - - bool has_overflowed = false; - unsigned digits_consumed = 0; - - for (;;) { - char ch = *(p++); - int digit; - if (isdigit(ch)) - digit = ch - '0'; - else if (islower(ch)) - digit = ch - ('a' - 10); - else if (isupper(ch)) - digit = ch - ('A' - 10); - else - break; - - if (digit >= base) - break; - - if (has_overflowed) - continue; - - bool is_past_cutoff = is_negative ? num < cutoff_point : num > cutoff_point; - - if (is_past_cutoff || (num == cutoff_point && digit > max_valid_digit_at_cutoff_point)) { - has_overflowed = true; - num = is_negative ? min_value : max_value; - errno = ERANGE; - } else { - num *= base; - num += is_negative ? -digit : digit; - ++digits_consumed; - } - } - - if (endptr) { - if (has_overflowed || digits_consumed > 0) - *endptr = const_cast<char*>(p - 1); - else - *endptr = const_cast<char*>(nptr); - } - return num; -} - long strtol(const char* str, char** endptr, int base) { return strtol_impl<long, LONG_MIN, LONG_MAX>(str, endptr, base); @@ -636,3 +635,18 @@ uint32_t arc4random_uniform(uint32_t max_bounds) // called "modulo bias". return arc4random() % max_bounds; } + +char* realpath(const char* pathname, char* buffer) +{ + size_t size = PATH_MAX; + if (buffer == nullptr) + buffer = (char*)malloc(size); + int rc = syscall(SC_realpath, pathname, buffer, size); + if (rc < 0) { + errno = -rc; + return nullptr; + } + errno = 0; + return buffer; +} +} diff --git a/Libraries/LibC/stdlib.h b/Libraries/LibC/stdlib.h index 529d4a99b7..7523636232 100644 --- a/Libraries/LibC/stdlib.h +++ b/Libraries/LibC/stdlib.h @@ -48,6 +48,7 @@ size_t mbstowcs(wchar_t*, const char*, size_t); size_t mbtowc(wchar_t*, const char*, size_t); int wctomb(char*, wchar_t); size_t wcstombs(char*, const wchar_t*, size_t); +char* realpath(const char* pathname, char* buffer); #define RAND_MAX 32767 int rand(); diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index 8715ecb4c8..d0f6af955a 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -578,20 +578,6 @@ int umount(const char* mountpoint) __RETURN_WITH_ERRNO(rc, rc, -1); } -char* realpath(const char* pathname, char* buffer) -{ - size_t size = PATH_MAX; - if (buffer == nullptr) - buffer = (char*)malloc(size); - int rc = syscall(SC_realpath, pathname, buffer, size); - if (rc < 0) { - errno = -rc; - return nullptr; - } - errno = 0; - return buffer; -} - void dump_backtrace() { syscall(SC_dump_backtrace); diff --git a/Libraries/LibC/unistd.h b/Libraries/LibC/unistd.h index f87a09b26b..8f57122693 100644 --- a/Libraries/LibC/unistd.h +++ b/Libraries/LibC/unistd.h @@ -115,7 +115,6 @@ int halt(); int reboot(); int mount(const char* device, const char* mountpoint, const char* fstype); int umount(const char* mountpoint); -char* realpath(const char* pathname, char* buffer); enum { _PC_NAME_MAX, |