From a164dcc16052d17652e55acea362c5453e0213de Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 29 Mar 2023 18:27:02 +0200 Subject: [PATCH] libos: Add libos + very basic ArgumentParser libluna but for stuff that interests only userspace, like an argument parser or files or stuff like that. --- CMakeLists.txt | 1 + apps/CMakeLists.txt | 6 +++- apps/edit.cpp | 15 +++++----- apps/ls.cpp | 13 +++++---- libluna/include/luna/Vector.h | 13 +++++++++ libos/CMakeLists.txt | 27 ++++++++++++++++++ libos/include/os/ArgumentParser.h | 25 ++++++++++++++++ libos/src/ArgumentParser.cpp | 47 +++++++++++++++++++++++++++++++ tools/check-formatting.sh | 2 ++ tools/check-stdint.sh | 2 ++ tools/install-headers.sh | 2 ++ tools/replace-stdint.sh | 2 ++ tools/run-clang-format.sh | 4 ++- 13 files changed, 145 insertions(+), 14 deletions(-) create mode 100644 libos/CMakeLists.txt create mode 100644 libos/include/os/ArgumentParser.h create mode 100644 libos/src/ArgumentParser.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 04dd5fef..873ee732 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/${LUNA_ARCH}-luna) message(STATUS "Configuring Luna for ${LUNA_ARCH}") add_subdirectory(libluna) +add_subdirectory(libos) add_subdirectory(libc) add_subdirectory(kernel) add_subdirectory(apps) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index cddffe67..f4a131c6 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -8,7 +8,11 @@ endfunction() luna_app(init.cpp init) luna_app(cat.cpp cat) -luna_app(edit.cpp edit) luna_app(sh.cpp sh) luna_app(date.cpp date) + +luna_app(edit.cpp edit) +target_link_libraries(edit PRIVATE os) + luna_app(ls.cpp ls) +target_link_libraries(ls PRIVATE os) diff --git a/apps/edit.cpp b/apps/edit.cpp index e5d70f27..08a49586 100644 --- a/apps/edit.cpp +++ b/apps/edit.cpp @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -5,17 +7,16 @@ int main(int argc, char** argv) { FILE* f; + StringView pathname; - if (argc < 2) - { - fprintf(stderr, "usage: %s [file]", argv[0]); - return 1; - } + ArgumentParser parser; + parser.add_positional_argument(pathname, "file", true); + parser.parse(argc, argv); - f = fopen(argv[1], "w"); + f = fopen(pathname.chars(), "w"); if (!f) { - perror(argv[1]); + perror(pathname.chars()); return 1; } diff --git a/apps/ls.cpp b/apps/ls.cpp index f8a0a9ba..c9050b7d 100644 --- a/apps/ls.cpp +++ b/apps/ls.cpp @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -5,12 +7,13 @@ int main(int argc, char** argv) { - const char* pathname; - if (argc == 1) pathname = "/"; - else - pathname = argv[1]; + StringView pathname; - DIR* dp = opendir(pathname); + ArgumentParser parser; + parser.add_positional_argument(pathname, "directory", false, "/"); + parser.parse(argc, argv); + + DIR* dp = opendir(pathname.chars()); if (!dp) { perror("opendir"); diff --git a/libluna/include/luna/Vector.h b/libluna/include/luna/Vector.h index 51d1070d..29b288bf 100644 --- a/libluna/include/luna/Vector.h +++ b/libluna/include/luna/Vector.h @@ -103,6 +103,19 @@ template class Vector return move(m_data[m_size]); } + Option try_dequeue() + { + if (m_size == 0) return {}; + + T item = move(m_data[0]); + + memmove(m_data, m_data + 1, m_size - 1); + + m_size--; + + return move(item); + } + const T& operator[](usize index) const { check(index < m_size); diff --git a/libos/CMakeLists.txt b/libos/CMakeLists.txt new file mode 100644 index 00000000..dda82cd8 --- /dev/null +++ b/libos/CMakeLists.txt @@ -0,0 +1,27 @@ +# The C++ standard library for OS operations (userspace only), so most things that have to do with calling the kernel, or functions that the kernel has no use for. + +file(GLOB HEADERS include/os/*.h) + +set(SOURCES + ${HEADERS} + src/ArgumentParser.cpp +) + +add_library(os ${SOURCES}) +target_compile_options(os PRIVATE -Os -Wall -Wextra -Werror -Wvla) +target_compile_options(os PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self) +target_compile_options(os PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef) +target_compile_options(os PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion) +target_compile_options(os PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -std=c++20 -fno-rtti -fno-exceptions) +target_include_directories(os PUBLIC include/) +target_include_directories(os PUBLIC ${LUNA_BASE}/usr/include) + +if("${LUNA_ARCH}" MATCHES "x86_64") +target_compile_definitions(os PUBLIC ARCH_X86_64) +endif() + +if(LUNA_DEBUG_SYMBOLS) + message(STATUS "Building libOS with debug symbols") + target_compile_options(os PRIVATE -ggdb) + target_compile_options(os-freestanding PRIVATE -ggdb) +endif() diff --git a/libos/include/os/ArgumentParser.h b/libos/include/os/ArgumentParser.h new file mode 100644 index 00000000..f1655e44 --- /dev/null +++ b/libos/include/os/ArgumentParser.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +class ArgumentParser +{ + public: + ArgumentParser() = default; + + Result add_positional_argument(StringView& out, StringView name, bool required); + Result add_positional_argument(StringView& out, StringView name, bool required, StringView fallback); + + void parse(int argc, char* const* argv); + + private: + struct PositionalArgument + { + StringView* out; + StringView name; + bool required; + StringView fallback; + }; + + Vector m_positional_args; +}; diff --git a/libos/src/ArgumentParser.cpp b/libos/src/ArgumentParser.cpp new file mode 100644 index 00000000..91b672c7 --- /dev/null +++ b/libos/src/ArgumentParser.cpp @@ -0,0 +1,47 @@ +#include +#include +#include + +Result ArgumentParser::add_positional_argument(StringView& out, StringView name, bool required) +{ + PositionalArgument arg { &out, name, required, {} }; + + return m_positional_args.try_append(move(arg)); +} + +Result ArgumentParser::add_positional_argument(StringView& out, StringView name, bool required, + StringView fallback) +{ + PositionalArgument arg { &out, name, required, fallback }; + + return m_positional_args.try_append(move(arg)); +} + +void ArgumentParser::parse(int argc, char* const* argv) +{ + StringView program_name = argv[0]; + + for (int i = 1; i < argc; i++) + { + StringView arg = argv[i]; + Option current = m_positional_args.try_dequeue(); + if (!current.has_value()) + { + fprintf(stderr, "%s: unused argument '%s'\n", program_name.chars(), arg.chars()); + continue; + } + + *current->out = arg; + } + + // Loop through all remaining positional arguments. + for (const auto& arg : m_positional_args) + { + if (arg.required) + { + fprintf(stderr, "%s: required argument '%s' not provided\n", program_name.chars(), arg.name.chars()); + exit(1); + } + else { *arg.out = arg.fallback; } + } +} diff --git a/tools/check-formatting.sh b/tools/check-formatting.sh index 77c959f5..31fe22b7 100755 --- a/tools/check-formatting.sh +++ b/tools/check-formatting.sh @@ -7,6 +7,8 @@ cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm")) SOURCES+=($(find libluna/src -type f)) SOURCES+=($(find libluna/include/luna -type f)) +SOURCES+=($(find libos/src -type f)) +SOURCES+=($(find libos/include/os -type f)) ALL_OK=1 diff --git a/tools/check-stdint.sh b/tools/check-stdint.sh index d732ecf9..855fece7 100755 --- a/tools/check-stdint.sh +++ b/tools/check-stdint.sh @@ -8,6 +8,8 @@ cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm" | grep -v "bootboot.h")) SOURCES+=($(find libluna/src -type f)) SOURCES+=($(find libluna/include/luna -type f | grep -v "Types.h")) +SOURCES+=($(find libos/src -type f)) +SOURCES+=($(find libos/include/os -type f)) SUCCESS=1 diff --git a/tools/install-headers.sh b/tools/install-headers.sh index 71b3b07f..9e1eca75 100755 --- a/tools/install-headers.sh +++ b/tools/install-headers.sh @@ -8,6 +8,8 @@ cd $LUNA_ROOT mkdir -p $LUNA_BASE mkdir -p $LUNA_BASE/usr/include mkdir -p $LUNA_BASE/usr/include/luna +mkdir -p $LUNA_BASE/usr/include/os cp --preserve=timestamps -RT libc/include/ $LUNA_BASE/usr/include cp --preserve=timestamps -RT libluna/include/luna/ $LUNA_BASE/usr/include/luna +cp --preserve=timestamps -RT libos/include/os/ $LUNA_BASE/usr/include/os diff --git a/tools/replace-stdint.sh b/tools/replace-stdint.sh index a39a3e00..00a9f954 100755 --- a/tools/replace-stdint.sh +++ b/tools/replace-stdint.sh @@ -8,6 +8,8 @@ cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm" | grep -v "bootboot.h")) SOURCES+=($(find libluna/src -type f)) SOURCES+=($(find libluna/include/luna -type f | grep -v "Types.h")) +SOURCES+=($(find libos/src -type f)) +SOURCES+=($(find libos/include/os -type f)) for f in ${SOURCES[@]} do diff --git a/tools/run-clang-format.sh b/tools/run-clang-format.sh index 57e7ee85..1c154302 100755 --- a/tools/run-clang-format.sh +++ b/tools/run-clang-format.sh @@ -8,8 +8,10 @@ cd $LUNA_ROOT SOURCES=($(find kernel/src -type f | grep -v "\.asm")) SOURCES+=($(find libluna/src -type f)) SOURCES+=($(find libluna/include/luna -type f)) +SOURCES+=($(find libos/src -type f)) +SOURCES+=($(find libos/include/os -type f)) for f in ${SOURCES[@]} do clang-format $f -i -done \ No newline at end of file +done