More implementation of the C standard library.
This commit is contained in:
parent
2a612d2d83
commit
b965486de3
@ -5,6 +5,6 @@ bastl_sources = Split('''
|
||||
src/new.cpp
|
||||
''')
|
||||
|
||||
env.Append(KERNEL_SOURCES = [env.File(f) for f in bastl_sources])
|
||||
# env.Append(KERNEL_SOURCES = [env.File(f) for f in bastl_sources])
|
||||
|
||||
Return('env')
|
27
targets/_any/bastl/include/cctype
Normal file
27
targets/_any/bastl/include/cctype
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_CCTYPE_INCLUDED)
|
||||
#define BAD_APPLE_OS_CCTYPE_INCLUDED
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
using ::isalnum;
|
||||
using ::isalpha;
|
||||
using ::islower;
|
||||
using ::isupper;
|
||||
using ::isdigit;
|
||||
using ::isxdigit;
|
||||
using ::iscntrl;
|
||||
using ::isgraph;
|
||||
using ::isspace;
|
||||
using ::isblank;
|
||||
using ::isprint;
|
||||
using ::ispunct;
|
||||
using ::tolower;
|
||||
using ::toupper;
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_CCTYPE_INCLUDED)
|
9
targets/_any/bastl/include/cerrno
Normal file
9
targets/_any/bastl/include/cerrno
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_CERRNO_INCLUDED)
|
||||
#define BAD_APPLE_OS_CERRNO_INCLUDED
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_CERRNO_INCLUDED)
|
@ -16,6 +16,21 @@ using ::uint8_t;
|
||||
using ::uint16_t;
|
||||
using ::uint32_t;
|
||||
using ::uint64_t;
|
||||
|
||||
using ::intptr_t;
|
||||
using ::uintptr_t;
|
||||
|
||||
using ::int_fast8_t;
|
||||
using ::int_fast16_t;
|
||||
using ::int_fast32_t;
|
||||
using ::int_fast64_t;
|
||||
using ::uint_fast8_t;
|
||||
using ::uint_fast16_t;
|
||||
using ::uint_fast32_t;
|
||||
using ::uint_fast64_t;
|
||||
|
||||
using ::intmax_t;
|
||||
using ::uintmax_t;
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_CSTDINT_INCLUDED)
|
||||
|
@ -8,12 +8,16 @@
|
||||
|
||||
namespace std
|
||||
{
|
||||
using ::strlen;
|
||||
|
||||
using ::memcmp;
|
||||
using ::memcpy;
|
||||
using ::memmove;
|
||||
using ::memset;
|
||||
|
||||
|
||||
using ::strcat;
|
||||
using ::strchr;
|
||||
using ::strcpy;
|
||||
using ::strlen;
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_CSTRING_INCLUDED)
|
||||
|
82
targets/_any/bastl/include/string_view
Normal file
82
targets/_any/bastl/include/string_view
Normal file
@ -0,0 +1,82 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_STRING_VIEW_INCLUDED)
|
||||
#define BAD_APPLE_OS_STRING_VIEW_INCLUDED
|
||||
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<typename CharT, typename Traits = char_traits<CharT>>
|
||||
class basic_string_view
|
||||
{
|
||||
public:
|
||||
using traits_type = Traits;
|
||||
using value_type = CharT;
|
||||
using pointer = CharT*;
|
||||
using const_pointer = const CharT*;
|
||||
using reference = CharT&;
|
||||
using const_reference = const CharT&;
|
||||
using iterator = const CharT*;
|
||||
using const_iterator = const CharT*;
|
||||
// TODO: reverse iterators
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
private:
|
||||
const_pointer _begin = nullptr;
|
||||
const_pointer _end = nullptr;
|
||||
public:
|
||||
constexpr basic_string_view() noexcept = default;
|
||||
constexpr basic_string_view(const basic_string_view&) noexcept = default;
|
||||
constexpr basic_string_view(const_pointer s, size_type count) noexcept : _begin(s), _end(s + count) {}
|
||||
constexpr basic_string_view(const_pointer s) noexcept : _begin(s), _end(s)
|
||||
{
|
||||
while (*_end) { ++_end; }
|
||||
}
|
||||
template<typename It, typename End>
|
||||
constexpr basic_string_view(It first, End last) noexcept : _begin(first), _end(last) {}
|
||||
constexpr basic_string_view(nullptr_t) = delete;
|
||||
|
||||
constexpr basic_string_view& operator=(const basic_string_view&) noexcept = default;
|
||||
|
||||
[[nodiscard]] constexpr iterator begin() const noexcept { return _begin; }
|
||||
[[nodiscard]] constexpr const_iterator cbegin() const noexcept { return _begin; }
|
||||
[[nodiscard]] constexpr iterator end() const noexcept { return _end; }
|
||||
[[nodiscard]] constexpr const_iterator cend() const noexcept { return _end; }
|
||||
// TODO: reverse iterators
|
||||
|
||||
[[nodiscard]] constexpr const_reference operator[](size_type pos) const noexcept { return _begin[pos]; }
|
||||
[[nodiscard]] constexpr const_reference at(size_type pos) const
|
||||
{
|
||||
if (pos >= size()) {
|
||||
__ba_throw out_of_range();
|
||||
}
|
||||
return _begin[pos];
|
||||
}
|
||||
[[nodiscard]] constexpr const_reference front() const noexcept { return *_begin; }
|
||||
[[nodiscard]] constexpr const_reference back() const noexcept { return _end[-1]; }
|
||||
[[nodiscard]] constexpr const_pointer data() const noexcept { return _begin; }
|
||||
|
||||
[[nodiscard]] constexpr size_type size() const noexcept { return _end - _begin; }
|
||||
[[nodiscard]] constexpr size_type length() const noexcept { return _end - _begin; }
|
||||
[[nodiscard]] constexpr size_type max_size() const noexcept { return numeric_limits<size_type>::max(); }
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
|
||||
|
||||
constexpr void remove_prefix(size_type n) noexcept { _begin += n; }
|
||||
constexpr void remove_suffix(size_type n) noexcept { _end -= n; }
|
||||
|
||||
constexpr void swap(basic_string_view& v) noexcept
|
||||
{
|
||||
swap(_begin, v._begin);
|
||||
swap(_end, v._end);
|
||||
}
|
||||
};
|
||||
|
||||
using string_view = basic_string_view<char>;
|
||||
using wstring_view = basic_string_view<wchar_t>;
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_STRING_VIEW_INCLUDED)
|
@ -4,7 +4,7 @@
|
||||
#if !defined(BAD_APPLE_OS_UTILITY_INCLUDED)
|
||||
#define BAD_APPLE_OS_UTILITY_INCLUDED
|
||||
|
||||
#include "type_traits"
|
||||
#include <type_traits>
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
Import('env')
|
||||
|
||||
init_sources = Split('''
|
||||
src/main.c
|
||||
src/main.cpp
|
||||
''')
|
||||
|
||||
init_env = env.Clone()
|
||||
@ -11,6 +11,7 @@ init_env['CC'] = 'x86_64-elf-baos-gcc'
|
||||
init_env['CXX'] = 'x86_64-elf-baos-g++'
|
||||
init_env['LD'] = 'x86_64-elf-baos-g++'
|
||||
init_env.Append(CXXFLAGS = ['-fno-exceptions', '-fno-rtti', '-std=c++20'])
|
||||
init_env.Append(LINKFLAGS = ['-nostdlib++']) # TODO: this should be changed in GCC, but I can't find a way to do it
|
||||
init_env.Append(CPPPATH = ['#targets/_any/bastl/include', '#targets/_any/stdlib/include', '#targets/_any/kernel/include'])
|
||||
|
||||
prog_init = init_env.Program(
|
||||
|
@ -55,4 +55,15 @@ inline void serialWriteString(std::uint16_t port, const char* str) noexcept
|
||||
}
|
||||
}
|
||||
|
||||
inline void serialWriteString(std::uint16_t port, const char* str, size_t count) noexcept
|
||||
{
|
||||
for (size_t pos = 0; pos < count; ++pos)
|
||||
{
|
||||
if (str[pos] == '\n') {
|
||||
serialWrite(port, '\r');
|
||||
}
|
||||
serialWrite(port, str[pos]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_SERIAL_HPP_INCLUDED)
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <span>
|
||||
|
||||
namespace baos
|
||||
{
|
||||
@ -47,6 +48,33 @@ public:
|
||||
--mBufferedElements;
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isDataContinuous() const noexcept
|
||||
{
|
||||
return mBufferedElements <= mPosition;
|
||||
}
|
||||
|
||||
void normalize() noexcept
|
||||
{
|
||||
std::array<T, SIZE> tempElements;
|
||||
auto it = tempElements.begin();
|
||||
while (next(*it)) { ++it; }
|
||||
mBufferedElements = it - tempElements.begin();
|
||||
mElements = std::move(tempElements);
|
||||
mPosition = mBufferedElements;
|
||||
}
|
||||
|
||||
std::span<T> getAll(bool reset = true) noexcept
|
||||
{
|
||||
if (!isDataContinuous()) {
|
||||
normalize();
|
||||
}
|
||||
std::span<T> result = {mElements.data() + mPosition - mBufferedElements, mBufferedElements};
|
||||
if (reset) {
|
||||
mBufferedElements = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ void sysFileRead(unsigned fileDescriptor, char* buffer, std::size_t count) noexc
|
||||
|
||||
void sysFileWrite(unsigned fileDescriptor, const char* buffer, std::size_t count) noexcept
|
||||
{
|
||||
serialWriteString(PORT_COM1, buffer, count);
|
||||
for (std::size_t index = 0; index < count; ++index) {
|
||||
serialWrite(PORT_COM1, buffer[index]);
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ env['CRT0_PATH'] = env.File(f'src/crt0.{env["TARGET_ARCH"]}.s').abspath
|
||||
|
||||
stdlib_sources = Split(f'''
|
||||
src/assert.cpp
|
||||
src/ctype.cpp
|
||||
src/errno.cpp
|
||||
src/stdio.cpp
|
||||
src/stdlib.cpp
|
||||
src/string.cpp
|
||||
|
28
targets/_any/stdlib/include/ctype.h
Normal file
28
targets/_any/stdlib/include/ctype.h
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_CTYPE_H_INCLUDED)
|
||||
#define BAD_APPLE_OS_CTYPE_H_INCLUDED
|
||||
|
||||
#include "./detail/common.h"
|
||||
|
||||
BA_EXTERN_C_BEGIN
|
||||
|
||||
BA_CXX_NODISCARD int isalnum(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int isalpha(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int islower(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int isupper(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int isdigit(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int isxdigit(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int iscntrl(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int isgraph(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int isspace(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int isblank(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int isprint(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int ispunct(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int tolower(int ch) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int toupper(int ch) BA_CXX_NOEXCEPT;
|
||||
|
||||
BA_EXTERN_C_END
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_CTYPE_H_INCLUDED)
|
@ -1,7 +1,170 @@
|
||||
|
||||
// shamelessly stolen from my Linux distro (which means this is GPL code!)
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_ERRNO_H_INCLUDED)
|
||||
#define BAD_APPLE_OS_ERRNO_H_INCLUDED
|
||||
|
||||
#include "./detail/common.h"
|
||||
|
||||
#define errno (*__errno())
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
|
||||
/*
|
||||
* This error code is special: arch syscall entry code will return
|
||||
* -ENOSYS if users try to call a syscall that doesn't exist. To keep
|
||||
* failures of syscalls that really do exist distinguishable from
|
||||
* failures due to attempts to use a nonexistent syscall, syscall
|
||||
* implementations should refrain from returning -ENOSYS.
|
||||
*/
|
||||
#define ENOSYS 38 /* Invalid system call number */
|
||||
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
#define ECANCELED 125 /* Operation Canceled */
|
||||
#define ENOKEY 126 /* Required key not available */
|
||||
#define EKEYEXPIRED 127 /* Key has expired */
|
||||
#define EKEYREVOKED 128 /* Key has been revoked */
|
||||
#define EKEYREJECTED 129 /* Key was rejected by service */
|
||||
|
||||
/* for robust mutexes */
|
||||
#define EOWNERDEAD 130 /* Owner died */
|
||||
#define ENOTRECOVERABLE 131 /* State not recoverable */
|
||||
|
||||
#define ERFKILL 132 /* Operation not possible due to RF-kill */
|
||||
|
||||
#define EHWPOISON 133 /* Memory page has hardware error */
|
||||
|
||||
BA_EXTERN_C_BEGIN
|
||||
|
||||
BA_CXX_NODISCARD int* __errno() BA_CXX_NOEXCEPT;
|
||||
|
||||
|
||||
|
||||
BA_EXTERN_C_END
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_ERRNO_H_INCLUDED)
|
||||
|
@ -33,6 +33,7 @@ int vprintf(const char* BA_C_RESTRICT format, va_list vlist) BA_CXX_NOEXCEPT;
|
||||
int sprintf(char* BA_C_RESTRICT buffer, const char* BA_C_RESTRICT format, ...) BA_CXX_NOEXCEPT;
|
||||
int snprintf(char* BA_C_RESTRICT buffer, size_t bufferSize, const char* BA_C_RESTRICT format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 3, 4)));
|
||||
int vsnprintf(char* BA_C_RESTRICT buffer, size_t bufferSize, const char* BA_C_RESTRICT format, va_list vlist) BA_CXX_NOEXCEPT;
|
||||
int vsprintf(char* BA_C_RESTRICT buffer, const char* BA_C_RESTRICT format, va_list vlist) BA_CXX_NOEXCEPT;
|
||||
|
||||
int fclose(FILE* stream) BA_CXX_NOEXCEPT;
|
||||
int fflush(FILE* stream) BA_CXX_NOEXCEPT;
|
||||
@ -40,6 +41,8 @@ int fgetc(FILE* stream) BA_CXX_NOEXCEPT;
|
||||
FILE* fopen(const char* BA_C_RESTRICT filename, const char* BA_C_RESTRICT mode) BA_CXX_NOEXCEPT;
|
||||
char* fgets(char* buffer, int count, FILE* stream) BA_CXX_NOEXCEPT;
|
||||
int fprintf(FILE* BA_C_RESTRICT stream, const char* BA_C_RESTRICT format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 2, 3)));
|
||||
int fputc(int ch, FILE* stream) BA_CXX_NOEXCEPT;
|
||||
int fputs(const char* BA_C_RESTRICT str, FILE* BA_C_RESTRICT stream) BA_CXX_NOEXCEPT;
|
||||
size_t fread(void* BA_C_RESTRICT buffer, size_t size, size_t count, FILE* BA_C_RESTRICT stream) BA_CXX_NOEXCEPT;
|
||||
int fseek(FILE* stream, long offset, int origin) BA_CXX_NOEXCEPT;
|
||||
long ftell(FILE* stream) BA_CXX_NOEXCEPT;
|
||||
@ -49,6 +52,7 @@ int vfprintf(FILE* BA_C_RESTRICT stream, const char* BA_C_RESTRICT format, va_li
|
||||
|
||||
inline int getc(FILE* stream) BA_CXX_NOEXCEPT { return fgetc(stream); }
|
||||
inline int getchar() BA_CXX_NOEXCEPT { return fgetc(stdin); }
|
||||
inline int putc(int ch, FILE* stream) BA_CXX_NOEXCEPT { return fputc(ch, stream); }
|
||||
|
||||
BA_EXTERN_C_END
|
||||
|
||||
|
@ -15,6 +15,7 @@ BA_CXX_NORETURN void exit(int exitCode) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD char* getenv(const char* name) BA_CXX_NOEXCEPT;
|
||||
|
||||
BA_CXX_NODISCARD int abs(int n) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD double atof(const char* str) BA_CXX_NOEXCEPT;
|
||||
BA_CXX_NODISCARD int atoi(const char* str) BA_CXX_NOEXCEPT;
|
||||
|
||||
BA_CXX_NODISCARD void* calloc(size_t num, size_t size) BA_CXX_NOEXCEPT;
|
||||
|
79
targets/_any/stdlib/src/ctype.cpp
Normal file
79
targets/_any/stdlib/src/ctype.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int isalnum(int ch) noexcept
|
||||
{
|
||||
return isdigit(ch) || isalpha(ch);
|
||||
}
|
||||
|
||||
int isalpha(int ch) noexcept
|
||||
{
|
||||
return islower(ch) || isupper(ch);
|
||||
}
|
||||
|
||||
int islower(int ch) noexcept
|
||||
{
|
||||
return ch >= 'a' && ch <= 'z';
|
||||
}
|
||||
|
||||
int isupper(int ch) noexcept
|
||||
{
|
||||
return ch >= 'A' && ch <= 'Z';
|
||||
}
|
||||
|
||||
int isdigit(int ch) noexcept
|
||||
{
|
||||
return ch >= '0' && ch <= '9';
|
||||
}
|
||||
|
||||
int isxdigit(int ch) noexcept
|
||||
{
|
||||
return isdigit(ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F');
|
||||
}
|
||||
|
||||
int iscntrl(int ch) noexcept
|
||||
{
|
||||
return (ch >= 0x00 && ch <= 0x1F) || ch == 0x7F;
|
||||
}
|
||||
|
||||
int isgraph(int ch) noexcept
|
||||
{
|
||||
return isalnum(ch) || ispunct(ch);
|
||||
}
|
||||
|
||||
int isspace(int ch) noexcept
|
||||
{
|
||||
static const char SPACE_CHARS[] = " \f\n\r\t\v";
|
||||
return strchr(SPACE_CHARS, ch) != nullptr;
|
||||
}
|
||||
|
||||
int isblank(int ch) noexcept
|
||||
{
|
||||
return ch == ' ' || ch == '\t';
|
||||
}
|
||||
|
||||
int isprint(int ch) noexcept
|
||||
{
|
||||
return isgraph(ch) || isspace(ch);
|
||||
}
|
||||
|
||||
int ispunct(int ch) noexcept
|
||||
{
|
||||
static const char PUNCTUATION_CHARS[] = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||
return strchr(PUNCTUATION_CHARS, ch) != nullptr;
|
||||
}
|
||||
|
||||
int tolower(int ch) noexcept
|
||||
{
|
||||
return isupper(ch) ? (ch - 'A' + 'a') : ch;
|
||||
}
|
||||
|
||||
int toupper(int ch) noexcept
|
||||
{
|
||||
return islower(ch) ? (ch - 'a' + 'A') : ch;
|
||||
}
|
||||
}
|
15
targets/_any/stdlib/src/errno.cpp
Normal file
15
targets/_any/stdlib/src/errno.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
constinit int gErrno = 0; // TODO: make this thread-local once there are threads
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int* __errno() noexcept
|
||||
{
|
||||
return &gErrno;
|
||||
}
|
||||
}
|
@ -2,7 +2,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <stdarg.h>
|
||||
#include "os/tools/printf_helper.hpp"
|
||||
#include "os/tools/ringbuffer.hpp"
|
||||
@ -17,34 +20,64 @@
|
||||
struct __file
|
||||
{
|
||||
protected:
|
||||
static constexpr unsigned BUFFER_SIZE = 4096;
|
||||
|
||||
baos::RingBuffer<char, BUFFER_SIZE> mBuffer;
|
||||
bool mEof = false;
|
||||
bool mError = false;
|
||||
protected:
|
||||
virtual bool underflow() noexcept = 0;
|
||||
public:
|
||||
[[nodiscard]] bool isEof() const noexcept { return mEof; }
|
||||
[[nodiscard]] bool isError() const noexcept { return mError; }
|
||||
|
||||
bool readChar(char& outChar) noexcept
|
||||
virtual bool readChar(char& outChar) noexcept { return false; }
|
||||
virtual bool readLine(std::string& outLine) noexcept { return false; }
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
struct BufferPrinter
|
||||
{
|
||||
char* pos = nullptr;
|
||||
char* end = nullptr;
|
||||
|
||||
void putchar(int chr) noexcept // NOLINT
|
||||
{
|
||||
while (!mBuffer.next(outChar)) {
|
||||
if (!underflow()) {
|
||||
if (pos != end)
|
||||
{
|
||||
*pos = static_cast<char>(chr);
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class InFile : public __file
|
||||
{
|
||||
protected:
|
||||
static constexpr unsigned BUFFER_SIZE = 4096;
|
||||
|
||||
baos::RingBuffer<char, BUFFER_SIZE> mBuffer;
|
||||
protected:
|
||||
virtual bool underflow() noexcept = 0;
|
||||
|
||||
public:
|
||||
bool readChar(char& outChar) noexcept override
|
||||
{
|
||||
while (!mBuffer.next(outChar))
|
||||
{
|
||||
if (!underflow())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readLine(std::string& outLine) noexcept
|
||||
bool readLine(std::string& outLine) noexcept override
|
||||
{
|
||||
outLine.clear();
|
||||
while(true)
|
||||
while (true)
|
||||
{
|
||||
while (mBuffer.empty()) {
|
||||
if (!underflow()) {
|
||||
while (mBuffer.empty())
|
||||
{
|
||||
if (!underflow())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -71,35 +104,46 @@ public:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
class OutFile : public __file
|
||||
{
|
||||
struct RegularPrinter
|
||||
{
|
||||
void putchar(int chr) noexcept // NOLINT
|
||||
{
|
||||
::putchar(chr);
|
||||
}
|
||||
};
|
||||
protected:
|
||||
static constexpr unsigned BUFFER_SIZE = 4096;
|
||||
|
||||
struct BufferPrinter
|
||||
{
|
||||
char* pos = nullptr;
|
||||
char* end = nullptr;
|
||||
|
||||
void putchar(int chr) noexcept // NOLINT
|
||||
baos::RingBuffer<char, BUFFER_SIZE> mWriteBuffer;
|
||||
protected:
|
||||
virtual void overflow() noexcept = 0;
|
||||
public:
|
||||
void putChar(char chr) noexcept
|
||||
{
|
||||
if (pos != end)
|
||||
while (mWriteBuffer.full()) {
|
||||
overflow();
|
||||
}
|
||||
mWriteBuffer.append(chr);
|
||||
if (chr == '\n')
|
||||
{
|
||||
*pos = static_cast<char>(chr);
|
||||
++pos;
|
||||
overflow();
|
||||
}
|
||||
}
|
||||
|
||||
void putString(std::string_view str) noexcept
|
||||
{
|
||||
for (char chr : str)
|
||||
{
|
||||
putChar(chr);
|
||||
}
|
||||
}
|
||||
|
||||
void flush() noexcept
|
||||
{
|
||||
overflow();
|
||||
}
|
||||
};
|
||||
|
||||
class StdinFile : public __file
|
||||
class StdinFile : public InFile
|
||||
{
|
||||
public:
|
||||
bool underflow() noexcept override
|
||||
@ -114,49 +158,52 @@ public:
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
class StdoutFile : public OutFile
|
||||
{
|
||||
public:
|
||||
void overflow() noexcept override
|
||||
{
|
||||
std::span<char> chars = mWriteBuffer.getAll();
|
||||
if (!chars.empty())
|
||||
{
|
||||
#if defined(__baos_kernel_source__)
|
||||
serialWriteString(PORT_COM1, chars.data(), chars.size());
|
||||
tty::write(chars.data(), chars.size());
|
||||
#else
|
||||
baos::doSyscall(baos::Syscall::FILE_WRITE, 0, chars.data(), chars.size());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FilePrinter
|
||||
{
|
||||
OutFile& file;
|
||||
|
||||
void putchar(int chr) noexcept
|
||||
{
|
||||
file.putChar(static_cast<char>(chr));
|
||||
}
|
||||
};
|
||||
|
||||
StdinFile gStdin;
|
||||
StdoutFile gStdout;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
FILE* __stdin = &gStdin;
|
||||
FILE* __stdout = &gStdout;
|
||||
|
||||
// TODO: line-buffering
|
||||
int putchar(int chr) noexcept
|
||||
{
|
||||
#if defined(__baos_kernel_source__)
|
||||
tty::putChar(static_cast<char>(chr));
|
||||
if (chr == '\n')
|
||||
{
|
||||
serialWrite(PORT_COM1, '\r');
|
||||
serialWrite(PORT_COM1, '\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
serialWrite(PORT_COM1, static_cast<std::uint8_t>(chr));
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
char asChar = static_cast<char>(chr);
|
||||
baos::doSyscall(baos::Syscall::FILE_WRITE, 0, &asChar, 1);
|
||||
return 0;
|
||||
#endif
|
||||
return fputc(chr, stdout);
|
||||
}
|
||||
|
||||
int puts(const char* str) noexcept
|
||||
{
|
||||
#if defined(__baos_kernel_source__)
|
||||
while (*str)
|
||||
{
|
||||
putchar(*str);
|
||||
++str;
|
||||
}
|
||||
putchar('\n');
|
||||
return 0;
|
||||
#else
|
||||
baos::doSyscall(baos::Syscall::FILE_WRITE, 0, str, std::strlen(str));
|
||||
return 0;
|
||||
#endif
|
||||
return fputs(str, stdout);
|
||||
}
|
||||
|
||||
int printf(const char* format, ...) noexcept
|
||||
@ -168,9 +215,18 @@ int printf(const char* format, ...) noexcept
|
||||
return result;
|
||||
}
|
||||
|
||||
int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT
|
||||
int vprintf(const char* format, va_list vlist) noexcept
|
||||
{
|
||||
return baos::PrintFHelper<RegularPrinter>().vprintf(format, vlist);
|
||||
return vfprintf(stdout, format, vlist);
|
||||
}
|
||||
|
||||
int sprintf(char* buffer, const char* format, ...) noexcept
|
||||
{
|
||||
va_list parameters;
|
||||
va_start(parameters, format);
|
||||
const int result = vsprintf(buffer, format, parameters);
|
||||
va_end(parameters);
|
||||
return result;
|
||||
}
|
||||
|
||||
int snprintf(char* buffer, size_t bufferSize, const char* format, ...) noexcept
|
||||
@ -196,6 +252,30 @@ int vsnprintf(char* buffer, size_t bufferSize, const char* format, va_list vlist
|
||||
return length;
|
||||
}
|
||||
|
||||
int vsprintf(char* buffer, const char* format, va_list vlist) noexcept
|
||||
{
|
||||
BufferPrinter printer{
|
||||
.pos = buffer,
|
||||
.end = std::bit_cast<char*>(std::numeric_limits<std::uintptr_t>::max())
|
||||
};
|
||||
const int length = baos::PrintFHelper(printer).vprintf(format, vlist);
|
||||
buffer[length] = '\0';
|
||||
return length;
|
||||
}
|
||||
|
||||
int fclose(FILE* stream) noexcept
|
||||
{
|
||||
(void) stream;
|
||||
// TODO: implement
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int fflush(FILE* stream) noexcept
|
||||
{
|
||||
static_cast<OutFile*>(stream)->flush();
|
||||
return stream->isError() ? EOF : 0;
|
||||
}
|
||||
|
||||
int fgetc(FILE* stream) noexcept
|
||||
{
|
||||
char chr;
|
||||
@ -232,6 +312,32 @@ char* fgets(char* buffer, int count, FILE* stream) noexcept
|
||||
buffer[pos] = '\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int fprintf(FILE* stream, const char* format, ...) noexcept
|
||||
{
|
||||
va_list parameters;
|
||||
va_start(parameters, format);
|
||||
const int result = vfprintf(stream, format, parameters);
|
||||
va_end(parameters);
|
||||
return result;
|
||||
}
|
||||
|
||||
int fputc(int ch, FILE* stream) noexcept
|
||||
{
|
||||
static_cast<OutFile*>(stream)->putChar(static_cast<char>(ch));
|
||||
return stream->isError() ? EOF : 0;
|
||||
}
|
||||
|
||||
int fputs(const char* str, FILE* stream) noexcept
|
||||
{
|
||||
static_cast<OutFile*>(stream)->putString(str);
|
||||
return stream->isError() ? EOF : 0;
|
||||
}
|
||||
|
||||
int vfprintf(FILE* stream, const char* format, va_list vlist) noexcept
|
||||
{
|
||||
return baos::PrintFHelper(FilePrinter(*static_cast<OutFile*>(stream))).vprintf(format, vlist);
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
namespace std
|
||||
|
@ -58,6 +58,20 @@ void* memset(void* dest, int value, size_t count) noexcept
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* strchr(const char* str, int ch) noexcept
|
||||
{
|
||||
for (const char* chr = str;; ++chr)
|
||||
{
|
||||
if (*chr == ch) {
|
||||
return const_cast<char*>(chr);
|
||||
}
|
||||
++chr;
|
||||
if (!*chr) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t strlen(const char* str) noexcept
|
||||
{
|
||||
size_t len = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user