From e10cc2d9543ef88a33a32c0ea0c8c27a5ee72eee Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 3 Jun 2023 20:20:01 +0200 Subject: [PATCH] libc: Add the internal TRY_OR_SET_ERRNO macro Similar mechanism to TRY(), but propagating C-like errors instead of Results on failure. --- libc/include/bits/errno-return.h | 15 +++++++++++++++ libc/src/env.cpp | 16 ++++------------ libc/src/grp.cpp | 9 ++------- libc/src/stdlib.cpp | 25 ++++--------------------- libc/src/unistd.cpp | 8 +------- 5 files changed, 26 insertions(+), 47 deletions(-) diff --git a/libc/include/bits/errno-return.h b/libc/include/bits/errno-return.h index aa8d9492..9eb6931a 100644 --- a/libc/include/bits/errno-return.h +++ b/libc/include/bits/errno-return.h @@ -5,6 +5,7 @@ #include +// Set errno after a failed system call, otherwise extract the successful value. #define __errno_return(value, type) \ do { \ if (value < 0) \ @@ -15,4 +16,18 @@ return (type)value; \ } while (0) +// If expr has a value, evaluates to that value. Otherwise, short-circuits, sets errno to expr's error, and returns +// failval (casted to rtype) from the calling function. Similar to TRY() in luna/Result.h, but used for transforming +// errors from luna functions to libc functions. +#define TRY_OR_SET_ERRNO(expr, rtype, failval) \ + ({ \ + auto _expr_rc = (expr); \ + if (!_expr_rc.has_value()) \ + { \ + errno = _expr_rc.error(); \ + return (rtype)failval; \ + } \ + _expr_rc.release_value(); \ + }) + #endif diff --git a/libc/src/env.cpp b/libc/src/env.cpp index 60ab6971..57b8fb34 100644 --- a/libc/src/env.cpp +++ b/libc/src/env.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -83,12 +84,8 @@ static Result _try_move_env() static int _move_env() { - auto rc = _try_move_env(); - if (rc.has_error()) - { - errno = rc.error(); - return -1; - } + TRY_OR_SET_ERRNO(_try_move_env(), int, -1); + return 0; } @@ -178,12 +175,7 @@ extern "C" // Add a new NULL at the end of the array and replace the previous one with our string. index = g_dynamic_env.size() - 1; - auto rc = g_dynamic_env.try_append(nullptr); - if (rc.has_error()) - { - errno = rc.error(); - return -1; - } + TRY_OR_SET_ERRNO(g_dynamic_env.try_append(nullptr), int, -1); guard.deactivate(); _update_env(); diff --git a/libc/src/grp.cpp b/libc/src/grp.cpp index d266d435..d6a46905 100644 --- a/libc/src/grp.cpp +++ b/libc/src/grp.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -67,13 +68,7 @@ extern "C" struct group* getgrent() { - auto rc = try_getgrent(); - if (rc.has_error()) - { - errno = rc.error(); - return nullptr; - } - return rc.value(); + return TRY_OR_SET_ERRNO(try_getgrent(), group*, nullptr); } struct group* getgrnam(const char* name) diff --git a/libc/src/stdlib.cpp b/libc/src/stdlib.cpp index 19eac27b..5a31db25 100644 --- a/libc/src/stdlib.cpp +++ b/libc/src/stdlib.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -144,35 +145,17 @@ extern "C" void* malloc(size_t size) { - auto rc = malloc_impl(size); - if (rc.has_error()) - { - errno = rc.error(); - return nullptr; - } - return rc.value(); + return TRY_OR_SET_ERRNO(malloc_impl(size), void*, nullptr); } void* calloc(size_t nmemb, size_t size) { - auto rc = calloc_impl(nmemb, size); - if (rc.has_error()) - { - errno = rc.error(); - return nullptr; - } - return rc.value(); + return TRY_OR_SET_ERRNO(calloc_impl(nmemb, size), void*, nullptr); } void* realloc(void* ptr, size_t size) { - auto rc = realloc_impl(ptr, size); - if (rc.has_error()) - { - errno = rc.error(); - return nullptr; - } - return rc.value(); + return TRY_OR_SET_ERRNO(realloc_impl(ptr, size), void*, nullptr); } void free(void* ptr) diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp index 66115a62..27f334b5 100644 --- a/libc/src/unistd.cpp +++ b/libc/src/unistd.cpp @@ -169,13 +169,7 @@ extern "C" int execvpe(const char* name, char* const* argv, char* const* envp) { - auto rc = try_execvpe(name, argv, envp); - if (rc.has_error()) - { - errno = rc.error(); - return -1; - } - return rc.value(); + return TRY_OR_SET_ERRNO(try_execvpe(name, argv, envp), int, -1); } int execvp(const char* name, char* const* argv)