Compare commits

..

No commits in common. "0f678f845c39d849c710991f713fcd1b65ddd483" and "e6c4ceb18fbd6ae1d3181b90d384882683b16da4" have entirely different histories.

33 changed files with 297 additions and 482 deletions

View File

@ -28,20 +28,6 @@ set(CMAKE_FIND_ROOT_PATH ${LUNA_ROOT}/toolchain/${LUNA_ARCH}-luna)
message(STATUS "Configuring Luna for ${LUNA_ARCH}")
set(COMMON_FLAGS -Wall -Wextra -Werror -Wvla
-Wdisabled-optimization -Wformat=2 -Winit-self
-Wmissing-include-dirs -Wswitch-default -Wcast-qual
-Wundef -Wcast-align -Wwrite-strings -Wlogical-op
-Wredundant-decls -Wshadow -Wconversion
-fno-asynchronous-unwind-tables -fno-omit-frame-pointer
-std=c++20 -fno-rtti -fno-exceptions)
if(LUNA_NO_OPTIMIZATIONS)
set(COMMON_FLAGS ${COMMON_FLAGS} -ggdb)
else()
set(COMMON_FLAGS ${COMMON_FLAGS} -Os)
endif()
add_subdirectory(libluna)
add_subdirectory(libos)
add_subdirectory(libc)

View File

@ -1,6 +1,6 @@
function(luna_app SOURCE_FILE APP_NAME)
add_executable(${APP_NAME} ${SOURCE_FILE})
target_compile_options(${APP_NAME} PRIVATE -Os ${COMMON_FLAGS} -Wno-write-strings)
target_compile_options(${APP_NAME} PRIVATE -Os -Wall -Wextra -pedantic -Werror -Wno-write-strings)
add_dependencies(${APP_NAME} libc)
target_include_directories(${APP_NAME} PRIVATE ${LUNA_BASE}/usr/include)
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin)

View File

@ -35,7 +35,7 @@ int main(int argc, char** argv)
{
StringView filename;
os::ArgumentParser parser;
ArgumentParser parser;
parser.add_positional_argument(filename, "file"_sv, "-"_sv);
Vector<StringView> extra_files = parser.parse(argc, argv).value();

View File

@ -9,7 +9,7 @@ int main(int argc, char** argv)
{
StringView date;
os::ArgumentParser parser;
ArgumentParser parser;
parser.add_value_argument(date, 'd', "date"_sv, true);
parser.parse(argc, argv);

View File

@ -9,7 +9,7 @@ int main(int argc, char** argv)
FILE* f;
StringView pathname;
os::ArgumentParser parser;
ArgumentParser parser;
parser.add_positional_argument(pathname, "file"_sv, true);
parser.parse(argc, argv);

View File

@ -11,7 +11,7 @@ int main(int argc, char** argv)
bool show_all { false };
bool show_almost_all { false };
os::ArgumentParser parser;
ArgumentParser parser;
parser.add_positional_argument(pathname, "directory"_sv, "/"_sv);
parser.add_switch_argument(show_all, 'a', "all"_sv);
parser.add_switch_argument(show_almost_all, 'A', "almost-all"_sv);

View File

@ -1,4 +1,3 @@
#include <luna/StringBuilder.h>
#include <luna/Vector.h>
#include <errno.h>
@ -22,7 +21,7 @@ static Result<Vector<char*>> split_command_into_argv(const char* cmd)
for (;;)
{
segment = strtok(NULL, " \n");
char* segment = strtok(NULL, " \n");
TRY(result.try_append(segment));
if (segment == NULL) return result;
@ -31,23 +30,21 @@ static Result<Vector<char*>> split_command_into_argv(const char* cmd)
return result;
}
static Result<String> join_path(const char* str1, const char* str2)
static char* join_path(const char* str1, const char* str2)
{
StringBuilder sb;
TRY(sb.add(StringView { str1 }));
TRY(sb.add(StringView { str2 }));
return sb.string();
char* buf = (char*)malloc(strlen(str1) + strlen(str2) + 1);
strlcpy(buf, str1, strlen(str1) + 1);
strncat(buf, str2, strlen(str2));
return buf;
}
static int execute_in_path(const char* dir, char** argv)
{
String path;
bool ok = join_path(dir, argv[0]).try_move_value_or_error(path, errno);
if (!ok) return -1;
char* path = join_path(dir, argv[0]);
int err = errno;
int status = execv(path.chars(), argv);
int status = execv(path, argv);
free(path);
if (errno == ENOENT)
{
@ -96,14 +93,16 @@ int main()
if (child == 0)
{
Vector<char*> argv;
bool ok = split_command_into_argv(command).try_move_value_or_error(argv, errno);
if (!ok)
auto maybe_argv = split_command_into_argv(command);
if (maybe_argv.has_error())
{
errno = maybe_argv.error();
perror("failed to parse command");
return 1;
}
auto argv = maybe_argv.release_value();
if (argv[0] == NULL) return 0;
sh_execvp(argv.data());
perror(argv[0]);

View File

@ -76,8 +76,13 @@ target_link_libraries(moon luna-freestanding)
target_compile_definitions(moon PRIVATE IN_MOON)
target_compile_options(moon PRIVATE ${COMMON_FLAGS})
target_compile_options(moon PRIVATE -nostdlib -mcmodel=kernel -ffreestanding)
target_compile_options(moon PRIVATE -Wall -Wextra -Werror -Wvla -Wsign-conversion)
target_compile_options(moon PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self)
target_compile_options(moon PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef)
target_compile_options(moon PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion)
target_compile_options(moon PRIVATE -fno-rtti -ffreestanding -fno-exceptions)
target_compile_options(moon PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer)
target_compile_options(moon PRIVATE -nostdlib -mcmodel=kernel)
if("${LUNA_ARCH}" MATCHES "x86_64")
target_compile_options(moon PRIVATE -mno-red-zone)
@ -85,8 +90,12 @@ if("${LUNA_ARCH}" MATCHES "x86_64")
target_link_options(moon PRIVATE -mno-red-zone)
endif()
if(MOON_DEBUG)
if(MOON_DEBUG_SYMBOLS)
message(STATUS "Building Moon with debug symbols")
target_compile_options(moon PRIVATE -ggdb)
include(debug.cmake)
else()
target_compile_options(moon PRIVATE -Os)
endif()
target_link_options(moon PRIVATE -lgcc -Wl,--build-id=none -z max-page-size=0x1000 -mcmodel=kernel)

View File

@ -30,9 +30,10 @@ namespace KernelVM
{
auto kernelvm_bitmap = g_kernelvm_bitmap.lock();
usize index;
bool ok = kernelvm_bitmap->find_and_toggle(false).try_set_value(index);
if (!ok) return err(ENOMEM);
const auto maybe_index = kernelvm_bitmap->find_and_toggle(false);
if (!maybe_index.has_value()) return err(ENOMEM);
const usize index = maybe_index.value();
g_used_vm += ARCH_PAGE_SIZE;

View File

@ -139,9 +139,10 @@ namespace MemoryManager
{
auto frame_bitmap = g_frame_bitmap.lock();
usize index;
bool ok = frame_bitmap->find_and_toggle(false, start_index).try_set_value(index);
if (!ok) return err(ENOMEM);
const auto maybe_index = frame_bitmap->find_and_toggle(false, start_index);
if (!maybe_index.has_value()) return err(ENOMEM);
const usize index = maybe_index.value();
start_index = index + 1;

View File

@ -65,13 +65,15 @@ Result<bool> UserVM::try_expand(usize size)
Result<u64> UserVM::alloc_one_page()
{
u64 index;
bool ok = m_bitmap.find_and_toggle(false).try_set_value(index);
if (!ok)
const auto maybe_index = m_bitmap.find_and_toggle(false);
if (!maybe_index.has_value())
{
bool success = TRY(try_expand());
if (!success) return err(ENOMEM);
index = TRY(Result<u64>::from_option(m_bitmap.find_and_toggle(false), ENOMEM));
}
else
index = maybe_index.value();
return VM_BASE + index * ARCH_PAGE_SIZE;
}
@ -79,13 +81,15 @@ Result<u64> UserVM::alloc_one_page()
Result<u64> UserVM::alloc_several_pages(usize count)
{
u64 index;
bool ok = m_bitmap.find_and_toggle_region(false, count).try_set_value(index);
if (!ok)
const auto maybe_index = m_bitmap.find_and_toggle_region(false, count);
if (!maybe_index.has_value())
{
bool success = TRY(try_expand((count / 8) + INITIAL_VM_SIZE));
if (!success) return err(ENOMEM);
index = TRY(Result<u64>::from_option(m_bitmap.find_and_toggle_region(false, count), ENOMEM));
}
else
index = maybe_index.value();
return VM_BASE + index * ARCH_PAGE_SIZE;
}

View File

@ -19,12 +19,13 @@ Result<u64> sys_getdents(Registers*, SyscallArgs args)
usize nwrite = 0;
while (nwrite < count)
{
VFS::DirectoryEntry entry;
bool ok = descriptor.inode->get(descriptor.offset).try_set_value(entry);
if (!ok) break;
auto maybe_entry = descriptor.inode->get(descriptor.offset);
if (!maybe_entry.has_value()) break;
descriptor.offset++;
auto entry = maybe_entry.release_value();
luna_dirent kent;
kent.inode = entry.inode->inode_number();
strlcpy(kent.name, entry.name.chars(), entry.name.length() + 1);

View File

@ -24,27 +24,27 @@ Result<u64> sys_open(Registers*, SyscallArgs args)
// Caller did not pass either O_RDONLY, O_WRONLY or O_RDWR
if ((flags & O_RDWR) == 0) { return err(EINVAL); }
int error;
bool ok = VFS::resolve_path(path.chars()).try_set_value_or_error(inode, error);
if (!ok)
auto maybe_inode = VFS::resolve_path(path.chars());
if (maybe_inode.has_error())
{
if (error == ENOENT && (flags & O_CREAT))
if (maybe_inode.error() == ENOENT && (flags & O_CREAT))
{
inode = TRY(VFS::create_file(path.chars()));
inode->chmod(mode);
}
else
return err(error);
return maybe_inode.release_error();
}
else if (flags & O_EXCL)
return err(EEXIST);
else
{
inode = maybe_inode.release_value();
if ((flags & O_RDONLY) && (inode->mode() & S_IRUSR) == 0) return err(EACCES);
if ((flags & O_WRONLY) && (inode->mode() & S_IWUSR) == 0) return err(EACCES);
}
if (inode->type() != VFS::InodeType::Directory && (flags & O_DIRECTORY)) return err(ENOTDIR);
if(inode->type() != VFS::InodeType::Directory && (flags & O_DIRECTORY)) return err(ENOTDIR);
if ((flags & O_WRONLY) && (flags & O_TRUNC)) inode->truncate(0);

View File

@ -40,7 +40,8 @@ target_link_libraries(bare_libc PUBLIC luna)
target_include_directories(bare_libc PUBLIC include/)
target_compile_options(bare_libc PRIVATE ${COMMON_FLAGS})
target_compile_options(bare_libc PRIVATE -Os -Wall -Wextra -Werror -nostdlib)
target_compile_options(bare_libc PRIVATE -fno-exceptions -fno-rtti)
target_link_options(bare_libc PRIVATE -nostdlib)

View File

@ -33,7 +33,7 @@ extern "C"
long rc = syscall(SYS_getdents, stream->_fd, &ent, 1);
if (rc < 0)
{
errno = (int)-rc;
errno = -rc;
return nullptr;
}

View File

@ -278,19 +278,19 @@ extern "C"
int vfprintf(FILE* stream, const char* format, va_list ap)
{
usize count = cstyle_format(
format,
[](char c, void* f) -> Result<void> {
int rc = fputc(c, (FILE*)f);
if (rc == EOF) return err(errno);
return {};
},
stream, ap)
.value_or(-1);
usize rc = cstyle_format(
format,
[](char c, void* f) -> Result<void> {
int rc = fputc(c, (FILE*)f);
if (rc == EOF) return err(errno);
return {};
},
stream, ap)
.value_or(-1);
if (count == (usize)-1) return -1;
if (rc == (usize)-1) return -1;
return (int)count;
return (int)rc;
}
int fprintf(FILE* stream, const char* format, ...)

View File

@ -107,35 +107,23 @@ extern "C"
size_t mbstowcs(wchar_t* buf, const char* src, size_t max)
{
if (max == 0) return 0;
size_t result = (size_t)-1;
Utf8StringDecoder decoder(src);
if (!buf)
{
decoder.code_points().try_set_value_or_error(result, errno);
return result;
}
if (!buf) { return decoder.code_points().value_or((size_t)-1); }
decoder.decode(buf, max).try_set_value_or_error(result, errno);
return result;
return decoder.decode(buf, max).value_or((size_t)-1);
}
size_t wcstombs(char* buf, const wchar_t* src, size_t max)
{
if (max == 0) return 0;
size_t result = (size_t)-1;
Utf8StringEncoder encoder(src);
if (!buf)
{
encoder.byte_length().try_set_value_or_error(result, errno);
return result;
}
if (!buf) { return encoder.byte_length().value_or((size_t)-1); }
encoder.encode(buf, max).try_set_value_or_error(result, errno);
return result;
return encoder.encode(buf, max).value_or((size_t)-1);
}
void* malloc(size_t size)

View File

@ -14,7 +14,6 @@ set(FREESTANDING_SOURCES
src/Buffer.cpp
src/Stack.cpp
src/String.cpp
src/StringBuilder.cpp
src/StringView.cpp
src/Utf8.cpp
src/TarStream.cpp
@ -33,15 +32,24 @@ set(SOURCES
add_library(luna-freestanding ${FREESTANDING_SOURCES})
target_compile_definitions(luna-freestanding PRIVATE USE_FREESTANDING)
target_compile_options(luna-freestanding PRIVATE ${COMMON_FLAGS})
target_compile_options(luna-freestanding PRIVATE -nostdlib -mcmodel=kernel -ffreestanding)
target_compile_options(luna-freestanding PRIVATE -Os -Wall -Wextra -Werror -Wvla)
target_compile_options(luna-freestanding PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self -Wsign-conversion)
target_compile_options(luna-freestanding PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef)
target_compile_options(luna-freestanding PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion)
target_compile_options(luna-freestanding PRIVATE -fno-rtti -ffreestanding -fno-exceptions)
target_compile_options(luna-freestanding PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer)
target_compile_options(luna-freestanding PRIVATE -nostdlib -mcmodel=kernel)
target_include_directories(luna-freestanding PUBLIC include/)
target_include_directories(luna-freestanding PRIVATE ${LUNA_ROOT}/kernel/src)
set_target_properties(luna-freestanding PROPERTIES CXX_STANDARD 20)
add_library(luna ${SOURCES})
target_compile_options(luna PRIVATE ${COMMON_FLAGS})
target_compile_options(luna PRIVATE -Os -Wall -Wextra -Werror -Wvla)
target_compile_options(luna PRIVATE -Wdisabled-optimization -Wformat=2 -Winit-self)
target_compile_options(luna PRIVATE -Wmissing-include-dirs -Wswitch-default -Wcast-qual -Wundef)
target_compile_options(luna PRIVATE -Wcast-align -Wwrite-strings -Wlogical-op -Wredundant-decls -Wshadow -Wconversion)
target_compile_options(luna PRIVATE -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -std=c++20 -fno-rtti -fno-exceptions)
target_include_directories(luna PUBLIC include/)
target_include_directories(luna PUBLIC ${LUNA_BASE}/usr/include)
@ -51,3 +59,9 @@ target_compile_options(luna-freestanding PRIVATE -mno-80387 -mno-mmx -mno-sse -m
target_compile_definitions(luna-freestanding PUBLIC ARCH_X86_64)
target_compile_definitions(luna PUBLIC ARCH_X86_64)
endif()
if(LUNA_DEBUG_SYMBOLS)
message(STATUS "Building Luna with debug symbols")
target_compile_options(luna PRIVATE -ggdb)
target_compile_options(luna-freestanding PRIVATE -ggdb)
endif()

View File

@ -19,7 +19,7 @@ class Buffer
Result<u8*> slice(usize offset, usize size);
Result<void> append_data(const u8* data, usize size);
Result<void> append_data(u8* data, usize size);
u8* data()
{

View File

@ -110,25 +110,11 @@ template <typename T> class Result
return m_value.try_set_value(ref);
}
bool try_set_value_or_error(T& ref, int& err) const
{
bool ok = m_value.try_set_value(ref);
if (!ok) err = m_error;
return ok;
}
bool try_move_value(T& ref)
{
return m_value.try_move_value(ref);
}
bool try_move_value_or_error(T& ref, int& err)
{
bool ok = m_value.try_move_value(ref);
if (!ok) err = m_error;
return ok;
}
T release_value(SourceLocation caller = SourceLocation::current())
{
expect_at(has_value(), caller, "Result::release_value() called on a Result that holds an error");
@ -148,13 +134,6 @@ template <typename T> class Result
return Error { error };
}
static Result<T> from_syscall(long rc)
{
if (rc < 0) return Error { (int)-rc };
else
return (T)rc;
}
private:
Option<T> m_value;
int m_error;

View File

@ -1,7 +1,6 @@
#pragma once
#include <luna/Result.h>
#include <luna/StringView.h>
#include <stdarg.h>
class String
{
@ -17,18 +16,12 @@ class String
String(String&&);
String(const String&) = delete;
String& operator=(String&&);
String& operator=(const String&) = delete;
~String();
Result<String> clone() const;
Result<String> substring(usize begin, usize size) const;
static Result<String> format(const String& fmt, ...);
static Result<String> format(StringView fmt, ...);
static Result<String> from_cstring(const char* str);
const char* chars() const
@ -82,6 +75,4 @@ class String
bool m_inline { true };
usize m_length { 0 };
static Result<String> vformat(StringView fmt, va_list ap);
};

View File

@ -1,22 +0,0 @@
#pragma once
#include <luna/Buffer.h>
#include <luna/String.h>
class StringBuilder
{
public:
Result<void> add(const String& value);
Result<void> add(StringView value);
Result<void> add(void* value);
Result<void> add(long value);
Result<void> add(unsigned long value);
Result<void> add(char value);
Result<void> format(StringView fmt, ...);
Result<void> vformat(StringView fmt, va_list ap);
Result<String> string();
private:
Buffer m_data;
};

View File

@ -70,11 +70,5 @@ namespace UBSAN
{
SourceLocation location;
};
struct NonnullArgInfo
{
SourceLocation location;
SourceLocation attr_location;
};
}
}

View File

@ -2,4 +2,5 @@
#include <luna/Result.h>
#include <luna/String.h>
usize to_dynamic_unit_cstr(usize value, char* buffer, usize max);
Result<String> to_dynamic_unit(usize value);

View File

@ -46,7 +46,7 @@ Result<u8*> Buffer::slice(usize offset, usize size)
return m_data + offset;
}
Result<void> Buffer::append_data(const u8* data, usize size)
Result<void> Buffer::append_data(u8* data, usize size)
{
memcpy(TRY(slice_at_end(size)), data, size);

View File

@ -1,8 +1,6 @@
#include <luna/Alloc.h>
#include <luna/CString.h>
#include <luna/Format.h>
#include <luna/String.h>
#include <luna/Vector.h>
String::String()
{
@ -23,24 +21,6 @@ String::String(String&& other)
other.m_string = nullptr;
}
String& String::operator=(String&& other)
{
if (&other == this) return *this;
if (!m_inline) free_impl(m_string);
m_inline = other.m_inline;
m_string = other.m_string;
m_length = other.m_length;
if (m_inline) memcpy(m_inline_storage, other.m_inline_storage, sizeof(m_inline_storage));
other.m_string = nullptr;
return *this;
}
String::String(char* c_str)
{
check(c_str);
@ -81,43 +61,6 @@ const char& String::operator[](usize index) const
return chars()[index];
}
Result<String> String::format(const String& fmt, ...)
{
va_list ap;
va_start(ap, fmt);
auto rc = vformat(fmt.view(), ap);
va_end(ap);
return rc;
}
Result<String> String::format(StringView fmt, ...)
{
va_list ap;
va_start(ap, fmt);
auto rc = vformat(fmt, ap);
va_end(ap);
return rc;
}
Result<String> String::vformat(StringView fmt, va_list ap)
{
Vector<char> buf;
TRY(cstyle_format(
fmt.chars(), [](char c, void* data) -> Result<void> { return ((Vector<char>*)data)->try_append(c); }, &buf,
ap));
TRY(buf.try_append(0));
return from_cstring(buf.data());
}
Result<String> String::from_cstring(const char* str)
{
usize len = strlen(str);

View File

@ -1,65 +0,0 @@
#include <luna/Format.h>
#include <luna/StringBuilder.h>
#include <luna/Vector.h>
Result<void> StringBuilder::add(StringView value)
{
return m_data.append_data((const u8*)value.chars(), value.length());
}
Result<void> StringBuilder::add(const String& value)
{
return add(value.view());
}
Result<void> StringBuilder::add(void* value)
{
return format("%p"_sv, value);
}
Result<void> StringBuilder::add(long value)
{
return format("%li"_sv, value);
}
Result<void> StringBuilder::add(unsigned long value)
{
return format("%lu"_sv, value);
}
Result<void> StringBuilder::add(char value)
{
return format("%c"_sv, value);
}
Result<void> StringBuilder::format(StringView fmt, ...)
{
va_list ap;
va_start(ap, fmt);
auto rc = vformat(fmt, ap);
va_end(ap);
return rc;
}
Result<void> StringBuilder::vformat(StringView fmt, va_list ap)
{
Vector<char> temp;
TRY(cstyle_format(
fmt.chars(), [](char c, void* buf) -> Result<void> { return ((Vector<char>*)buf)->try_append(c); }, &temp, ap));
TRY(m_data.append_data((u8*)temp.data(), temp.size()));
return {};
}
Result<String> StringBuilder::string()
{
char nul = '\0';
TRY(m_data.append_data((u8*)&nul, 1));
return String::from_cstring((const char*)m_data.data());
}

View File

@ -118,10 +118,4 @@ extern "C"
};
__ubsan_handle_type_mismatch(&info, pointer);
}
void __ubsan_handle_nonnull_arg(NonnullArgInfo* info, intptr_t)
{
dbgln("ubsan: null argument at %s:%d:%d", DISPLAY(info->location));
ub_panic();
}
}

View File

@ -1,11 +1,12 @@
#include <luna/Alloc.h>
#include <luna/Format.h>
#include <luna/Result.h>
#include <luna/ScopeGuard.h>
#include <luna/Units.h>
Result<String> to_dynamic_unit(usize value)
usize to_dynamic_unit_cstr(usize value, char* buffer, usize max)
{
if (value < 1024) { return String::format("%zu bytes"_sv, value); }
if (value < 1024) { return string_format(buffer, max, "%zu bytes", value); }
const char* unit_prefixes = "KMGTPE";
while (value > (1024 * 1024))
@ -14,5 +15,14 @@ Result<String> to_dynamic_unit(usize value)
unit_prefixes++;
}
return String::format("%zu.%zu %ciB"_sv, value / 1024, (value % 1024) / 103, *unit_prefixes);
return string_format(buffer, max, "%zu.%zu %ciB", value / 1024, (value % 1024) / 103, *unit_prefixes);
}
Result<String> to_dynamic_unit(usize value)
{
char* const buf = TRY(make_array<char>(64));
to_dynamic_unit_cstr(value, buf, 64);
return String { buf };
}

View File

@ -8,10 +8,20 @@ set(SOURCES
)
add_library(os ${SOURCES})
target_compile_options(os PRIVATE ${COMMON_FLAGS})
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()

View File

@ -2,50 +2,47 @@
#include <luna/StringView.h>
#include <luna/Vector.h>
namespace os
class ArgumentParser
{
class ArgumentParser
public:
ArgumentParser() = default;
Result<void> add_positional_argument(StringView& out, StringView name, bool required);
Result<void> add_positional_argument(StringView& out, StringView name, StringView fallback);
Result<void> add_switch_argument(bool& out, char short_flag, StringView long_flag);
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, bool value_required);
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, StringView fallback);
Result<Vector<StringView>> parse(int argc, char* const* argv);
private:
struct PositionalArgument
{
public:
ArgumentParser() = default;
Result<void> add_positional_argument(StringView& out, StringView name, bool required);
Result<void> add_positional_argument(StringView& out, StringView name, StringView fallback);
Result<void> add_switch_argument(bool& out, char short_flag, StringView long_flag);
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, bool value_required);
Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, StringView fallback);
Result<Vector<StringView>> parse(int argc, char* const* argv);
private:
struct PositionalArgument
{
StringView* out;
StringView name;
bool required;
StringView fallback;
};
struct SwitchArgument
{
bool* out;
char short_flag;
StringView long_flag;
};
struct ValueArgument
{
StringView* out;
char short_flag;
StringView long_flag;
bool required;
StringView fallback;
};
Vector<PositionalArgument> m_positional_args;
Vector<SwitchArgument> m_switch_args;
Vector<ValueArgument> m_value_args;
StringView* out;
StringView name;
bool required;
StringView fallback;
};
}
struct SwitchArgument
{
bool* out;
char short_flag;
StringView long_flag;
};
struct ValueArgument
{
StringView* out;
char short_flag;
StringView long_flag;
bool required;
StringView fallback;
};
Vector<PositionalArgument> m_positional_args;
Vector<SwitchArgument> m_switch_args;
Vector<ValueArgument> m_value_args;
};

View File

@ -2,94 +2,130 @@
#include <stdio.h>
#include <stdlib.h>
namespace os
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, bool required)
{
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, bool required)
PositionalArgument arg { &out, name, required, {} };
return m_positional_args.try_append(move(arg));
}
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, StringView fallback)
{
PositionalArgument arg { &out, name, false, fallback };
return m_positional_args.try_append(move(arg));
}
Result<void> ArgumentParser::add_switch_argument(bool& out, char short_flag, StringView long_flag)
{
SwitchArgument arg { &out, short_flag, long_flag };
return m_switch_args.try_append(move(arg));
}
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
bool value_required)
{
ValueArgument arg { &out, short_flag, long_flag, value_required, {} };
return m_value_args.try_append(move(arg));
}
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
StringView fallback)
{
ValueArgument arg { &out, short_flag, long_flag, false, fallback };
return m_value_args.try_append(move(arg));
}
static bool looks_like_short_flag(StringView arg)
{
return arg.length() > 1 && arg[0] == '-';
}
static bool looks_like_long_flag(StringView arg)
{
return arg.length() > 2 && arg[0] == '-' && arg[1] == '-';
}
Result<Vector<StringView>> ArgumentParser::parse(int argc, char* const* argv)
{
StringView program_name = argv[0];
Vector<StringView> leftovers;
Option<ValueArgument> current_value_argument = {};
bool is_parsing_value_argument = false;
bool is_still_parsing_flags = true;
for (int i = 1; i < argc; i++)
{
PositionalArgument arg { &out, name, required, {} };
StringView arg = argv[i];
return m_positional_args.try_append(move(arg));
}
Result<void> ArgumentParser::add_positional_argument(StringView& out, StringView name, StringView fallback)
{
PositionalArgument arg { &out, name, false, fallback };
return m_positional_args.try_append(move(arg));
}
Result<void> ArgumentParser::add_switch_argument(bool& out, char short_flag, StringView long_flag)
{
SwitchArgument arg { &out, short_flag, long_flag };
return m_switch_args.try_append(move(arg));
}
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
bool value_required)
{
ValueArgument arg { &out, short_flag, long_flag, value_required, {} };
return m_value_args.try_append(move(arg));
}
Result<void> ArgumentParser::add_value_argument(StringView& out, char short_flag, StringView long_flag,
StringView fallback)
{
ValueArgument arg { &out, short_flag, long_flag, false, fallback };
return m_value_args.try_append(move(arg));
}
static bool looks_like_short_flag(StringView arg)
{
return arg.length() > 1 && arg[0] == '-';
}
static bool looks_like_long_flag(StringView arg)
{
return arg.length() > 2 && arg[0] == '-' && arg[1] == '-';
}
Result<Vector<StringView>> ArgumentParser::parse(int argc, char* const* argv)
{
StringView program_name = argv[0];
Vector<StringView> leftovers;
Option<ValueArgument> current_value_argument = {};
bool is_parsing_value_argument = false;
bool is_still_parsing_flags = true;
for (int i = 1; i < argc; i++)
if (is_parsing_value_argument)
{
StringView arg = argv[i];
*current_value_argument->out = arg;
is_parsing_value_argument = false;
continue;
}
if (is_parsing_value_argument)
if (is_still_parsing_flags)
{
if (arg == "--")
{
*current_value_argument->out = arg;
is_parsing_value_argument = false;
is_still_parsing_flags = false;
continue;
}
if (is_still_parsing_flags)
if (looks_like_long_flag(arg))
{
if (arg == "--")
StringView flag = &arg[2];
bool found = false;
for (const auto& current : m_switch_args)
{
is_still_parsing_flags = false;
continue;
if (current.long_flag == flag)
{
*current.out = true;
found = true;
break;
}
}
if (looks_like_long_flag(arg))
for (const auto& current : m_value_args)
{
StringView flag = &arg[2];
if (current.long_flag == flag)
{
current_value_argument = current;
is_parsing_value_argument = true;
found = true;
break;
}
}
if (found) continue;
fprintf(stderr, "%s: unrecognized option '%s'\n", program_name.chars(), arg.chars());
exit(1);
}
else if (looks_like_short_flag(arg))
{
StringView flags = &arg[1];
for (char c : flags)
{
bool found = false;
// FIXME: Implement value arguments for short flags.
for (const auto& current : m_switch_args)
{
if (current.long_flag == flag)
if (current.short_flag == ' ') continue;
if (current.short_flag == c)
{
*current.out = true;
found = true;
@ -97,104 +133,47 @@ namespace os
}
}
for (const auto& current : m_value_args)
{
if (current.long_flag == flag)
{
current_value_argument = current;
is_parsing_value_argument = true;
found = true;
break;
}
}
if (found) continue;
fprintf(stderr, "%s: unrecognized option '%s'\n", program_name.chars(), arg.chars());
fprintf(stderr, "%s: invalid option -- '%c'\n", program_name.chars(), c);
exit(1);
}
else if (looks_like_short_flag(arg))
{
StringView flags = &arg[1];
for (usize j = 0; j < flags.length(); j++)
{
char c = flags[j];
bool found = false;
// Last flag, this could be a value flag
if (j + 1 == flags.length())
{
for (const auto& current : m_value_args)
{
if (current.short_flag == ' ') continue;
if (current.short_flag == c)
{
current_value_argument = current;
is_parsing_value_argument = true;
found = true;
break;
}
}
if (found) continue;
}
for (const auto& current : m_switch_args)
{
if (current.short_flag == ' ') continue;
if (current.short_flag == c)
{
*current.out = true;
found = true;
break;
}
}
if (found) continue;
fprintf(stderr, "%s: invalid option -- '%c'\n", program_name.chars(), c);
exit(1);
}
continue;
}
}
Option<PositionalArgument> current = m_positional_args.try_dequeue();
if (!current.has_value())
{
TRY(leftovers.try_append(arg));
continue;
}
*current->out = arg;
}
if (is_parsing_value_argument)
Option<PositionalArgument> current = m_positional_args.try_dequeue();
if (!current.has_value())
{
if (current_value_argument->required)
{
fprintf(stderr, "%s: option '--%s' requires an argument\n", program_name.chars(),
current_value_argument->long_flag.chars());
exit(1);
}
else { *current_value_argument->out = current_value_argument->fallback; }
TRY(leftovers.try_append(arg));
continue;
}
// 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; }
}
return leftovers;
*current->out = arg;
}
if (is_parsing_value_argument)
{
if (current_value_argument->required)
{
fprintf(stderr, "%s: option '--%s' requires an argument\n", program_name.chars(),
current_value_argument->long_flag.chars());
exit(1);
}
else { *current_value_argument->out = current_value_argument->fallback; }
}
// 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; }
}
return leftovers;
}

View File

@ -11,7 +11,7 @@ tools/full-clean.sh
tools/install-headers.sh
cmake -S . -B $LUNA_BUILD_DIR -DLUNA_NO_OPTIMIZATIONS=ON -DMOON_DEBUG=ON -G "$LUNA_CMAKE_GENERATOR_NAME"
cmake -S . -B $LUNA_BUILD_DIR -DMOON_DEBUG_SYMBOLS=ON -DLUNA_DEBUG_SYMBOLS=ON -G "$LUNA_CMAKE_GENERATOR_NAME"
cmake --build $LUNA_BUILD_DIR
cmake --install $LUNA_BUILD_DIR