From fbfc078e9f44c1c1e95c9c484f1d5650bcf631b7 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sat, 27 Jul 2024 16:57:39 -0400 Subject: lots and lots of userspace stuff --- euler/source/std/cctype.cpp | 7 ++++ euler/source/std/cstdio.cpp | 59 ++++++++++++++++++++++++++++++ euler/source/std/cstdlib.cpp | 19 ++++++++++ euler/source/std/cstring.cpp | 36 +++++++++++++++++++ euler/source/std/string.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 207 insertions(+) create mode 100644 euler/source/std/cctype.cpp create mode 100644 euler/source/std/cstdio.cpp create mode 100644 euler/source/std/cstdlib.cpp create mode 100644 euler/source/std/cstring.cpp create mode 100644 euler/source/std/string.cpp (limited to 'euler/source/std') diff --git a/euler/source/std/cctype.cpp b/euler/source/std/cctype.cpp new file mode 100644 index 0000000..a35d1a5 --- /dev/null +++ b/euler/source/std/cctype.cpp @@ -0,0 +1,7 @@ +#include + +extern "C" int isspace(int ch) { + return + ch == ' ' || ch == '\f' || ch == '\n' || + ch == '\r' || ch == '\t' || ch == '\v'; +} diff --git a/euler/source/std/cstdio.cpp b/euler/source/std/cstdio.cpp new file mode 100644 index 0000000..8c12a7c --- /dev/null +++ b/euler/source/std/cstdio.cpp @@ -0,0 +1,59 @@ +#include + +extern "C" FILE *fopen(const char *filename, const char *mode) { + + bool r = false, w = false, a = false, p = false, x = false; + for (size_t i = 0; mode[i] != '\0'; ++i) + if (mode[i] == 'r') r = true; + else if (mode[i] == 'w') w = true; + else if (mode[i] == 'a') a = true; + else if (mode[i] == 'p') p = true; + else if (mode[i] == 'x') x = true; + + euler::syscall::stream_handle handle; + if (euler::syscall::open_file(filename, !r, x, handle) != + euler::syscall::stream_result::success) + return 0; + + if (w && euler::syscall::set_stream_length(handle, 0) != + euler::syscall::stream_result::success) + return 0; + + if (a && euler::syscall::seek_stream( + handle, euler::syscall::seek_from::end, 0) != + euler::syscall::stream_result::success) { + euler::syscall::close_stream(handle); + return 0; + } + + uint64_t length; + if (euler::syscall::get_stream_length(handle, length) != + euler::syscall::stream_result::success) { + euler::syscall::close_stream(handle); + return 0; + } + + return new euler::file_stream(handle, r || p, length, a ? length : 0); + +} + +extern "C" void fclose(FILE *stream) { + stream->close(); + delete stream; +} + +extern "C" int fseek(FILE *stream, long offset, int origin) { + + if (origin < 0 || origin > 2) + return -1; + + return (int)stream->seek((euler::syscall::seek_from)origin, offset); + +} + +extern "C" size_t fread( + void *buffer, size_t size, size_t count, FILE *stream) { + + return (stream->read(size * count, buffer).first - 1) / size + 1; + +} diff --git a/euler/source/std/cstdlib.cpp b/euler/source/std/cstdlib.cpp new file mode 100644 index 0000000..cfb4b48 --- /dev/null +++ b/euler/source/std/cstdlib.cpp @@ -0,0 +1,19 @@ +#include +#include + +extern "C" [[noreturn]] void abort() noexcept { + //TODO + while (1) + ; +} + +extern "C" void *malloc(size_t size) { + size_t *block = (size_t *)euler::heap::get_block(size + 8); + *block = size; + return block + 1; +} + +extern "C" void free(void *ptr) { + size_t *block = (size_t *)ptr - 1; + euler::heap::return_block(block, *block + 8); +} diff --git a/euler/source/std/cstring.cpp b/euler/source/std/cstring.cpp new file mode 100644 index 0000000..3e5a56c --- /dev/null +++ b/euler/source/std/cstring.cpp @@ -0,0 +1,36 @@ +#include + +extern "C" void *memset(void *dest, int ch, size_t count) { + unsigned char c = static_cast(ch); + unsigned char *d = (unsigned char *)dest; + for (size_t i = 0; i < count; ++i) + d[i] = c; + return dest; +} + +extern "C" void *memcpy(void *dest, const void *src, size_t count) { + unsigned char *d = (unsigned char *)dest; + const unsigned char *s = (const unsigned char *)src; + for (size_t i = 0; i < count; ++i) + d[i] = s[i]; + return dest; +} + +extern "C" int strcmp(const char *lhs, const char *rhs) { + const unsigned char *l = (const unsigned char *)lhs; + const unsigned char *r = (const unsigned char *)rhs; + while (*l == *r) { + if (*l == 0) + return 0; + ++l; + ++r; + } + return *l < *r ? -1 : 1; +} + +extern "C" size_t strlen(const char *str) { + size_t len = 0; + while (str[len] != '\0') + ++len; + return len; +} diff --git a/euler/source/std/string.cpp b/euler/source/std/string.cpp new file mode 100644 index 0000000..31c47a5 --- /dev/null +++ b/euler/source/std/string.cpp @@ -0,0 +1,86 @@ +#include +#include + +namespace std { + + int stoi(const std::string &str, size_t *pos, int base) { + //TODO: exceptions + + size_t i = 0; + while (isspace(str[i])) + ++i; + + bool is_negative = false; + if (str[i] == '-') { + is_negative = true; + ++i; + } + else if (str[i] == '+') + ++i; + + if ((base == 16 || base == 0) && str[i] == '0' && + (str[i + 1] == 'x' || str[i + 1] == 'X')) { + base = 16; + i += 2; + } + + else if ((base == 8 || base == 0) && str[i] == '0') { + base = 8; + ++i; + } + + else if (base == 0) + base = 10; + + int value = 0; + + while (true) { + char c = str[i]; + if (c >= '0' && c < '0' + base) + value = value * base + c - '0'; + else if (c >= 'a' && c < 'a' + base - 10) + value = value * base + c - 'a' + 10; + else if (c >= 'A' && c < 'A' + base - 10) + value = value * base + c - 'A' + 10; + else + break; + } + + if (pos != 0) + *pos = i; + + return is_negative ? -value : value; + + } + + std::string to_string(int value) { + + int max_place = 1; + int places = 1; + while (max_place <= value / 10) { + max_place *= 10; + ++places; + } + + std::string s; + s.resize(places); + + for (int i = 0; i < places; ++i) { + s[i] = (value / max_place) % 10 + '0'; + max_place /= 10; + } + + return s; + + } + + std::string operator +(std::string &&lhs, std::string &&rhs) { + std::string s = std::move(lhs); + s.resize(lhs.size() + rhs.size()); + for (size_t i = 0; i < rhs.size(); ++i) + s[lhs.size() + i] = rhs[i]; + rhs.clear(); + return s; + } + +} -- cgit v1.2.3