basic_includes = include_directories(
'src/basic',
+ 'src/fundamental',
'src/systemd',
'.')
subdir('po')
subdir('catalog')
+subdir('src/fundamental')
subdir('src/basic')
subdir('src/libsystemd')
subdir('src/shared')
libsystemd_sources,
basic_sources,
basic_gcrypt_sources,
+ fundamental_sources,
disable_mempool_c,
include_directories : libsystemd_includes,
build_by_default : static_libsystemd != 'false',
install_libudev_static = static_library(
'udev',
basic_sources,
+ fundamental_sources,
shared_sources,
libsystemd_sources,
libudev_sources,
(void*)memset(_new_, 0, _xsize_); \
})
-/* Takes inspiration from Rust's Option::take() method: reads and returns a pointer, but at the same time
- * resets it to NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
-#define TAKE_PTR(ptr) \
- ({ \
- typeof(ptr) _ptr_ = (ptr); \
- (ptr) = NULL; \
- _ptr_; \
- })
-
#if HAS_FEATURE_MEMORY_SANITIZER
# define msan_unpoison(r, s) __msan_unpoison(r, s)
#else
#include <sys/sysmacros.h>
#include <sys/types.h>
+#include "macro-fundamental.h"
+
#define _printf_(a, b) __attribute__((__format__(printf, a, b)))
#ifdef __clang__
# define _alloc_(...)
#define _sentinel_ __attribute__((__sentinel__))
#define _section_(x) __attribute__((__section__(x)))
#define _used_ __attribute__((__used__))
-#define _unused_ __attribute__((__unused__))
#define _destructor_ __attribute__((__destructor__))
-#define _pure_ __attribute__((__pure__))
-#define _const_ __attribute__((__const__))
#define _deprecated_ __attribute__((__deprecated__))
#define _packed_ __attribute__((__packed__))
#define _malloc_ __attribute__((__malloc__))
#define _align_(x) __attribute__((__aligned__(x)))
#define _alignas_(x) __attribute__((__aligned__(__alignof(x))))
#define _alignptr_ __attribute__((__aligned__(sizeof(void*))))
-#define _cleanup_(x) __attribute__((__cleanup__(x)))
#if __GNUC__ >= 7
#define _fallthrough_ __attribute__((__fallthrough__))
#else
#define XSTRINGIFY(x) #x
#define STRINGIFY(x) XSTRINGIFY(x)
-#define XCONCATENATE(x, y) x ## y
-#define CONCATENATE(x, y) XCONCATENATE(x, y)
-
-#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
-#define UNIQ __COUNTER__
-
/* builtins */
#if __SIZEOF_INT__ == 4
#define BUILTIN_FFS_U32(x) __builtin_ffs(x);
return m;
}
-#ifndef __COVERITY__
-# define VOID_0 ((void)0)
-#else
-# define VOID_0 ((void*)0)
-#endif
-
-#define ELEMENTSOF(x) \
- (__builtin_choose_expr( \
- !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
- sizeof(x)/sizeof((x)[0]), \
- VOID_0))
-
/*
* STRLEN - return the length of a string literal, minus the trailing NUL byte.
* Contrary to strlen(), this is a constant expression.
(type*)( (char *)UNIQ_T(A, uniq) - offsetof(type, member) ); \
})
-#undef MAX
-#define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b))
-#define __MAX(aq, a, bq, b) \
- ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
- })
-
-/* evaluates to (void) if _A or _B are not constant or of different types */
-#define CONST_MAX(_A, _B) \
- (__builtin_choose_expr( \
- __builtin_constant_p(_A) && \
- __builtin_constant_p(_B) && \
- __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
- ((_A) > (_B)) ? (_A) : (_B), \
- VOID_0))
-
-/* takes two types and returns the size of the larger one */
-#define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; }))
-
-#define MAX3(x, y, z) \
- ({ \
- const typeof(x) _c = MAX(x, y); \
- MAX(_c, z); \
- })
-
-#define MAX4(x, y, z, a) \
- ({ \
- const typeof(x) _d = MAX3(x, y, z); \
- MAX(_d, a); \
- })
-
-#undef MIN
-#define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b))
-#define __MIN(aq, a, bq, b) \
- ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A, aq) < UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
- })
-
-/* evaluates to (void) if _A or _B are not constant or of different types */
-#define CONST_MIN(_A, _B) \
- (__builtin_choose_expr( \
- __builtin_constant_p(_A) && \
- __builtin_constant_p(_B) && \
- __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
- ((_A) < (_B)) ? (_A) : (_B), \
- VOID_0))
-
-#define MIN3(x, y, z) \
- ({ \
- const typeof(x) _c = MIN(x, y); \
- MIN(_c, z); \
- })
-
-#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
-#define __LESS_BY(aq, a, bq, b) \
- ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) - UNIQ_T(B, bq) : 0; \
- })
-
-#define CMP(a, b) __CMP(UNIQ, (a), UNIQ, (b))
-#define __CMP(aq, a, bq, b) \
- ({ \
- const typeof(a) UNIQ_T(A, aq) = (a); \
- const typeof(b) UNIQ_T(B, bq) = (b); \
- UNIQ_T(A, aq) < UNIQ_T(B, bq) ? -1 : \
- UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \
- })
-
-#undef CLAMP
-#define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high))
-#define __CLAMP(xq, x, lowq, low, highq, high) \
- ({ \
- const typeof(x) UNIQ_T(X, xq) = (x); \
- const typeof(low) UNIQ_T(LOW, lowq) = (low); \
- const typeof(high) UNIQ_T(HIGH, highq) = (high); \
- UNIQ_T(X, xq) > UNIQ_T(HIGH, highq) ? \
- UNIQ_T(HIGH, highq) : \
- UNIQ_T(X, xq) < UNIQ_T(LOW, lowq) ? \
- UNIQ_T(LOW, lowq) : \
- UNIQ_T(X, xq); \
- })
-
-/* [(x + y - 1) / y] suffers from an integer overflow, even though the
- * computation should be possible in the given type. Therefore, we use
- * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the
- * quotient and the remainder, so both should be equally fast. */
-#define DIV_ROUND_UP(x, y) __DIV_ROUND_UP(UNIQ, (x), UNIQ, (y))
-#define __DIV_ROUND_UP(xq, x, yq, y) \
- ({ \
- const typeof(x) UNIQ_T(X, xq) = (x); \
- const typeof(y) UNIQ_T(Y, yq) = (y); \
- (UNIQ_T(X, xq) / UNIQ_T(Y, yq) + !!(UNIQ_T(X, xq) % UNIQ_T(Y, yq))); \
- })
-
#ifdef __COVERITY__
/* Use special definitions of assertion macros in order to prevent
#define assert_not_reached(t) \
log_assert_failed_unreachable(t, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__)
-#if defined(static_assert)
-#define assert_cc(expr) \
- static_assert(expr, #expr)
-#else
-#define assert_cc(expr) \
- struct CONCATENATE(_assert_struct_, __COUNTER__) { \
- char x[(expr) ? 0 : -1]; \
- }
-#endif
-
#define assert_return(expr, r) \
do { \
if (!assert_log(expr, #expr)) \
#define FLAGS_SET(v, flags) \
((~(v) & (flags)) == 0)
-#define CASE_F(X) case X:
-#define CASE_F_1(CASE, X) CASE_F(X)
-#define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__)
-#define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__)
-#define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__)
-#define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__)
-#define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__)
-#define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__)
-#define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__)
-#define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__)
-#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
-#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
-#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
-#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
-#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
-#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
-#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
-#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
-#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
-#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
-#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
-
-#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
-#define FOR_EACH_MAKE_CASE(...) \
- GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
- CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
- (CASE_F,__VA_ARGS__)
-
-#define IN_SET(x, ...) \
- ({ \
- bool _found = false; \
- /* If the build breaks in the line below, you need to extend the case macros. (We use "long double" as \
- * type for the array, in the hope that checkers such as ubsan don't complain that the initializers for \
- * the array are not representable by the base type. Ideally we'd use typeof(x) as base type, but that \
- * doesn't work, as we want to use this on bitfields and gcc refuses typeof() on bitfields.) */ \
- static const long double __assert_in_set[] _unused_ = { __VA_ARGS__ }; \
- assert_cc(ELEMENTSOF(__assert_in_set) <= 20); \
- switch(x) { \
- FOR_EACH_MAKE_CASE(__VA_ARGS__) \
- _found = true; \
- break; \
- default: \
- break; \
- } \
- _found; \
- })
-
#define SWAP_TWO(x, y) do { \
typeof(x) _t = (x); \
(x) = (y); \
libbasic = static_library(
'basic',
basic_sources,
+ fundamental_sources,
include_directories : basic_includes,
dependencies : [versiondep,
threads,
#include "utf8.h"
#include "util.h"
-int strcmp_ptr(const char *a, const char *b) {
- /* Like strcmp(), but tries to make sense of NULL pointers */
-
- if (a && b)
- return strcmp(a, b);
- return CMP(a, b); /* Direct comparison of pointers, one of which is NULL */
-}
-
-int strcasecmp_ptr(const char *a, const char *b) {
- /* Like strcasecmp(), but tries to make sense of NULL pointers */
-
- if (a && b)
- return strcasecmp(a, b);
- return CMP(a, b); /* Direct comparison of pointers, one of which is NULL */
-}
-
-char* endswith(const char *s, const char *postfix) {
- size_t sl, pl;
-
- assert(s);
- assert(postfix);
-
- sl = strlen(s);
- pl = strlen(postfix);
-
- if (pl == 0)
- return (char*) s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (memcmp(s + sl - pl, postfix, pl) != 0)
- return NULL;
-
- return (char*) s + sl - pl;
-}
-
-char* endswith_no_case(const char *s, const char *postfix) {
- size_t sl, pl;
-
- assert(s);
- assert(postfix);
-
- sl = strlen(s);
- pl = strlen(postfix);
-
- if (pl == 0)
- return (char*) s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (strcasecmp(s + sl - pl, postfix) != 0)
- return NULL;
-
- return (char*) s + sl - pl;
-}
-
char* first_word(const char *s, const char *word) {
size_t sl, wl;
const char *p;
#include "alloc-util.h"
#include "macro.h"
+#include "string-util-fundamental.h"
/* What is interpreted as whitespace? */
#define WHITESPACE " \t\n\r"
#define ALPHANUMERICAL LETTERS DIGITS
#define HEXDIGITS DIGITS "abcdefABCDEF"
-#define streq(a,b) (strcmp((a),(b)) == 0)
-#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
-#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)
-#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
-
-int strcmp_ptr(const char *a, const char *b) _pure_;
-int strcasecmp_ptr(const char *a, const char *b) _pure_;
-
-static inline bool streq_ptr(const char *a, const char *b) {
- return strcmp_ptr(a, b) == 0;
-}
-
-static inline bool strcaseeq_ptr(const char *a, const char *b) {
- return strcasecmp_ptr(a, b) == 0;
-}
-
static inline char* strstr_ptr(const char *haystack, const char *needle) {
if (!haystack || !needle)
return NULL;
return s ?: "n/a";
}
-static inline const char* yes_no(bool b) {
- return b ? "yes" : "no";
-}
-
static inline const char* true_false(bool b) {
return b ? "true" : "false";
}
return b ? "enable" : "disable";
}
-static inline bool isempty(const char *p) {
- return !p || !p[0];
-}
-
static inline const char *empty_to_null(const char *p) {
return isempty(p) ? NULL : p;
}
return empty_or_dash(p) ? NULL : p;
}
-static inline char *startswith(const char *s, const char *prefix) {
- size_t l;
-
- l = strlen(prefix);
- if (strncmp(s, prefix, l) == 0)
- return (char*) s + l;
-
- return NULL;
-}
-
-static inline char *startswith_no_case(const char *s, const char *prefix) {
- size_t l;
-
- l = strlen(prefix);
- if (strncasecmp(s, prefix, l) == 0)
- return (char*) s + l;
-
- return NULL;
-}
-
-char *endswith(const char *s, const char *postfix) _pure_;
-char *endswith_no_case(const char *s, const char *postfix) _pure_;
-
char *first_word(const char *s, const char *word) _pure_;
char *strnappend(const char *s, const char *suffix, size_t length);
#include "console.h"
#include "crc32.h"
#include "disk.h"
+#include "efi-loader-features.h"
#include "graphics.h"
#include "linux.h"
-#include "loader-features.h"
#include "measure.h"
#include "pe.h"
#include "random-seed.h"
'-Wno-missing-field-initializers',
'-isystem', efi_incdir,
'-isystem', join_paths(efi_incdir, gnu_efi_path_arch),
+ '-I', fundamental_path,
+ '-DSD_BOOT',
'-include', efi_config_h,
'-include', version_h]
if efi_arch == 'x86_64'
systemd_boot_objects = []
stub_objects = []
- foreach file : common_sources + systemd_boot_sources + stub_sources
- o_file = custom_target(file + '.o',
+ foreach file : fundamental_source_paths + common_sources + systemd_boot_sources + stub_sources
+ o_file = custom_target(file.split('/')[-1] + '.o',
input : file,
- output : file + '.o',
+ output : file.split('/')[-1] + '.o',
command : efi_cc + ['-c', '@INPUT@', '-o', '@OUTPUT@']
+ compile_args,
- depend_files : efi_headers)
- if (common_sources + systemd_boot_sources).contains(file)
+ depend_files : efi_headers + fundamental_headers)
+ if (fundamental_source_paths + common_sources + systemd_boot_sources).contains(file)
systemd_boot_objects += o_file
endif
- if (common_sources + stub_sources).contains(file)
+ if (fundamental_source_paths + common_sources + stub_sources).contains(file)
stub_objects += o_file
endif
endforeach
return NULL;
}
-const CHAR16 *startswith(const CHAR16 *s, const CHAR16 *prefix) {
- UINTN l;
-
- l = StrLen(prefix);
- if (StrnCmp(s, prefix, l) == 0)
- return s + l;
-
- return NULL;
-}
-
-const CHAR16 *endswith(const CHAR16 *s, const CHAR16 *postfix) {
- UINTN sl, pl;
-
- sl = StrLen(s);
- pl = StrLen(postfix);
-
- if (pl == 0)
- return s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (StrnCmp(s + sl - pl, postfix, pl) != 0)
- return NULL;
-
- return s + sl - pl;
-}
-
-const CHAR16 *startswith_no_case(const CHAR16 *s, const CHAR16 *prefix) {
- UINTN l;
-
- l = StrLen(prefix);
- if (StriCmp(s, prefix) == 0)
- return s + l;
-
- return NULL;
-}
-
-const CHAR16 *endswith_no_case(const CHAR16 *s, const CHAR16 *postfix) {
- UINTN sl, pl;
-
- sl = StrLen(s);
- pl = StrLen(postfix);
-
- if (pl == 0)
- return s + sl;
-
- if (sl < pl)
- return NULL;
-
- if (StriCmp(s + sl - pl, postfix) != 0)
- return NULL;
-
- return s + sl - pl;
-}
-
EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **ret, UINTN *ret_size) {
_cleanup_(FileHandleClosep) EFI_FILE_HANDLE handle = NULL;
_cleanup_freepool_ CHAR8 *buf = NULL;
#include <efi.h>
#include <efilib.h>
-#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
+#include "string-util-fundamental.h"
+
#define OFFSETOF(x,y) __builtin_offsetof(x,y)
static inline UINTN ALIGN_TO(UINTN l, UINTN ali) {
return ((l + ali - 1) & ~(ali - 1));
}
-static inline const CHAR16 *yes_no(BOOLEAN b) {
- return b ? L"yes" : L"no";
-}
-
EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b);
UINT64 ticks_read(void);
CHAR16 *stra_to_path(CHAR8 *stra);
CHAR16 *stra_to_str(CHAR8 *stra);
-const CHAR16 *startswith(const CHAR16 *s, const CHAR16 *prefix);
-const CHAR16 *endswith(const CHAR16 *s, const CHAR16 *postfix);
-
-const CHAR16 *startswith_no_case(const CHAR16 *s, const CHAR16 *prefix);
-const CHAR16 *endswith_no_case(const CHAR16 *s, const CHAR16 *postfix);
-
EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size);
static inline void FreePoolp(void *p) {
FreePool(q);
}
-#define _cleanup_(x) __attribute__((__cleanup__(x)))
#define _cleanup_freepool_ _cleanup_(FreePoolp)
static inline void FileHandleClosep(EFI_FILE_HANDLE *handle) {
#define UINTN_MAX (~(UINTN)0)
#define INTN_MAX ((INTN)(UINTN_MAX>>1))
-#define TAKE_PTR(ptr) \
- ({ \
- typeof(ptr) _ptr_ = (ptr); \
- (ptr) = NULL; \
- _ptr_; \
- })
-
EFI_STATUS log_oom(void);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#ifndef SD_BOOT
+#include <assert.h>
+#endif
+
+#include "type.h"
+
+#define _const_ __attribute__((__const__))
+#define _pure_ __attribute__((__pure__))
+#define _unused_ __attribute__((__unused__))
+#define _cleanup_(x) __attribute__((__cleanup__(x)))
+
+#ifndef __COVERITY__
+# define VOID_0 ((void)0)
+#else
+# define VOID_0 ((void*)0)
+#endif
+
+#define ELEMENTSOF(x) \
+ (__builtin_choose_expr( \
+ !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \
+ sizeof(x)/sizeof((x)[0]), \
+ VOID_0))
+
+#define XCONCATENATE(x, y) x ## y
+#define CONCATENATE(x, y) XCONCATENATE(x, y)
+
+#ifdef SD_BOOT
+#define assert(expr) do {} while (false)
+#endif
+
+#if defined(static_assert)
+#define assert_cc(expr) \
+ static_assert(expr, #expr)
+#else
+#define assert_cc(expr) \
+ struct CONCATENATE(_assert_struct_, __COUNTER__) { \
+ char x[(expr) ? 0 : -1]; \
+ }
+#endif
+
+#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
+#define UNIQ __COUNTER__
+
+#undef MAX
+#define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b))
+#define __MAX(aq, a, bq, b) \
+ ({ \
+ const typeof(a) UNIQ_T(A, aq) = (a); \
+ const typeof(b) UNIQ_T(B, bq) = (b); \
+ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
+ })
+
+/* evaluates to (void) if _A or _B are not constant or of different types */
+#define CONST_MAX(_A, _B) \
+ (__builtin_choose_expr( \
+ __builtin_constant_p(_A) && \
+ __builtin_constant_p(_B) && \
+ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
+ ((_A) > (_B)) ? (_A) : (_B), \
+ VOID_0))
+
+/* takes two types and returns the size of the larger one */
+#define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; }))
+
+#define MAX3(x, y, z) \
+ ({ \
+ const typeof(x) _c = MAX(x, y); \
+ MAX(_c, z); \
+ })
+
+#define MAX4(x, y, z, a) \
+ ({ \
+ const typeof(x) _d = MAX3(x, y, z); \
+ MAX(_d, a); \
+ })
+
+#undef MIN
+#define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b))
+#define __MIN(aq, a, bq, b) \
+ ({ \
+ const typeof(a) UNIQ_T(A, aq) = (a); \
+ const typeof(b) UNIQ_T(B, bq) = (b); \
+ UNIQ_T(A, aq) < UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
+ })
+
+/* evaluates to (void) if _A or _B are not constant or of different types */
+#define CONST_MIN(_A, _B) \
+ (__builtin_choose_expr( \
+ __builtin_constant_p(_A) && \
+ __builtin_constant_p(_B) && \
+ __builtin_types_compatible_p(typeof(_A), typeof(_B)), \
+ ((_A) < (_B)) ? (_A) : (_B), \
+ VOID_0))
+
+#define MIN3(x, y, z) \
+ ({ \
+ const typeof(x) _c = MIN(x, y); \
+ MIN(_c, z); \
+ })
+
+#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
+#define __LESS_BY(aq, a, bq, b) \
+ ({ \
+ const typeof(a) UNIQ_T(A, aq) = (a); \
+ const typeof(b) UNIQ_T(B, bq) = (b); \
+ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) - UNIQ_T(B, bq) : 0; \
+ })
+
+#define CMP(a, b) __CMP(UNIQ, (a), UNIQ, (b))
+#define __CMP(aq, a, bq, b) \
+ ({ \
+ const typeof(a) UNIQ_T(A, aq) = (a); \
+ const typeof(b) UNIQ_T(B, bq) = (b); \
+ UNIQ_T(A, aq) < UNIQ_T(B, bq) ? -1 : \
+ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \
+ })
+
+#undef CLAMP
+#define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high))
+#define __CLAMP(xq, x, lowq, low, highq, high) \
+ ({ \
+ const typeof(x) UNIQ_T(X, xq) = (x); \
+ const typeof(low) UNIQ_T(LOW, lowq) = (low); \
+ const typeof(high) UNIQ_T(HIGH, highq) = (high); \
+ UNIQ_T(X, xq) > UNIQ_T(HIGH, highq) ? \
+ UNIQ_T(HIGH, highq) : \
+ UNIQ_T(X, xq) < UNIQ_T(LOW, lowq) ? \
+ UNIQ_T(LOW, lowq) : \
+ UNIQ_T(X, xq); \
+ })
+
+/* [(x + y - 1) / y] suffers from an integer overflow, even though the
+ * computation should be possible in the given type. Therefore, we use
+ * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the
+ * quotient and the remainder, so both should be equally fast. */
+#define DIV_ROUND_UP(x, y) __DIV_ROUND_UP(UNIQ, (x), UNIQ, (y))
+#define __DIV_ROUND_UP(xq, x, yq, y) \
+ ({ \
+ const typeof(x) UNIQ_T(X, xq) = (x); \
+ const typeof(y) UNIQ_T(Y, yq) = (y); \
+ (UNIQ_T(X, xq) / UNIQ_T(Y, yq) + !!(UNIQ_T(X, xq) % UNIQ_T(Y, yq))); \
+ })
+
+#define CASE_F(X) case X:
+#define CASE_F_1(CASE, X) CASE_F(X)
+#define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__)
+#define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__)
+#define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__)
+#define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__)
+#define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__)
+#define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__)
+#define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__)
+#define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__)
+#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
+#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
+#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
+#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
+#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
+#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
+#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
+#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
+#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
+#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
+#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
+
+#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
+#define FOR_EACH_MAKE_CASE(...) \
+ GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
+ CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
+ (CASE_F,__VA_ARGS__)
+
+#define IN_SET(x, ...) \
+ ({ \
+ sd_bool _found = false; \
+ /* If the build breaks in the line below, you need to extend the case macros. (We use "long double" as \
+ * type for the array, in the hope that checkers such as ubsan don't complain that the initializers for \
+ * the array are not representable by the base type. Ideally we'd use typeof(x) as base type, but that \
+ * doesn't work, as we want to use this on bitfields and gcc refuses typeof() on bitfields.) */ \
+ static const long double __assert_in_set[] _unused_ = { __VA_ARGS__ }; \
+ assert_cc(ELEMENTSOF(__assert_in_set) <= 20); \
+ switch(x) { \
+ FOR_EACH_MAKE_CASE(__VA_ARGS__) \
+ _found = true; \
+ break; \
+ default: \
+ break; \
+ } \
+ _found; \
+ })
+
+/* Takes inspiration from Rust's Option::take() method: reads and returns a pointer, but at the same time
+ * resets it to NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
+#define TAKE_PTR(ptr) \
+ ({ \
+ typeof(ptr) _ptr_ = (ptr); \
+ (ptr) = NULL; \
+ _ptr_; \
+ })
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+fundamental_path = meson.current_source_dir()
+
+fundamental_headers = files(
+ 'efi-loader-features.h',
+ 'macro-fundamental.h',
+ 'string-util-fundamental.h',
+ 'type.h')
+
+sources = '''
+ string-util-fundamental.c
+'''.split()
+
+# for sd-boot
+fundamental_source_paths = []
+foreach s : sources
+ fundamental_source_paths += join_paths(meson.current_source_dir(), s)
+endforeach
+
+# for libbasic
+fundamental_sources = files(sources) + fundamental_headers
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#ifndef SD_BOOT
+#include "macro.h"
+#endif
+#include "string-util-fundamental.h"
+
+sd_char *startswith(const sd_char *s, const sd_char *prefix) {
+ sd_size_t l;
+
+ assert(s);
+ assert(prefix);
+
+ l = strlen(prefix);
+ if (!strneq(s, prefix, l))
+ return NULL;
+
+ return (sd_char*) s + l;
+}
+
+#ifndef SD_BOOT
+sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) {
+ sd_size_t l;
+
+ assert(s);
+ assert(prefix);
+
+ l = strlen(prefix);
+ if (!strncaseeq(s, prefix, l))
+ return NULL;
+
+ return (sd_char*) s + l;
+}
+#endif
+
+sd_char* endswith(const sd_char *s, const sd_char *postfix) {
+ sd_size_t sl, pl;
+
+ assert(s);
+ assert(postfix);
+
+ sl = strlen(s);
+ pl = strlen(postfix);
+
+ if (pl == 0)
+ return (sd_char*) s + sl;
+
+ if (sl < pl)
+ return NULL;
+
+ if (strcmp(s + sl - pl, postfix) != 0)
+ return NULL;
+
+ return (sd_char*) s + sl - pl;
+}
+
+sd_char* endswith_no_case(const sd_char *s, const sd_char *postfix) {
+ sd_size_t sl, pl;
+
+ assert(s);
+ assert(postfix);
+
+ sl = strlen(s);
+ pl = strlen(postfix);
+
+ if (pl == 0)
+ return (sd_char*) s + sl;
+
+ if (sl < pl)
+ return NULL;
+
+ if (strcasecmp(s + sl - pl, postfix) != 0)
+ return NULL;
+
+ return (sd_char*) s + sl - pl;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#ifdef SD_BOOT
+#include <efi.h>
+#include <efilib.h>
+#else
+#include <string.h>
+#endif
+
+#include "macro-fundamental.h"
+
+#ifdef SD_BOOT
+#define strlen(a) StrLen((a))
+#define strcmp(a, b) StrCmp((a), (b))
+#define strncmp(a, b, n) StrnCmp((a), (b), (n))
+#define strcasecmp(a, b) StriCmp((a), (b))
+#define STR_C(str) (L ## str)
+#else
+#define STR_C(str) (str)
+#endif
+
+#define streq(a,b) (strcmp((a),(b)) == 0)
+#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
+#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)
+#ifndef SD_BOOT
+#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
+#endif
+
+static inline sd_int strcmp_ptr(const sd_char *a, const sd_char *b) {
+ if (a && b)
+ return strcmp(a, b);
+
+ return CMP(a, b);
+}
+
+static inline sd_int strcasecmp_ptr(const sd_char *a, const sd_char *b) {
+ if (a && b)
+ return strcasecmp(a, b);
+
+ return CMP(a, b);
+}
+
+static inline sd_bool streq_ptr(const sd_char *a, const sd_char *b) {
+ return strcmp_ptr(a, b) == 0;
+}
+
+static inline sd_bool strcaseeq_ptr(const sd_char *a, const sd_char *b) {
+ return strcasecmp_ptr(a, b) == 0;
+}
+
+sd_char *startswith(const sd_char *s, const sd_char *prefix) _pure_;
+#ifndef SD_BOOT
+sd_char *startswith_no_case(const sd_char *s, const sd_char *prefix) _pure_;
+#endif
+sd_char *endswith(const sd_char *s, const sd_char *postfix) _pure_;
+sd_char *endswith_no_case(const sd_char *s, const sd_char *postfix) _pure_;
+
+static inline sd_bool isempty(const sd_char *a) {
+ return !a || a[0] == '\0';
+}
+
+static inline const sd_char *yes_no(sd_bool b) {
+ return b ? STR_C("yes") : STR_C("no");
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#ifdef SD_BOOT
+#include <efi.h>
+
+typedef BOOLEAN sd_bool;
+typedef CHAR16 sd_char;
+typedef INTN sd_int;
+typedef UINTN sd_size_t;
+
+#define true TRUE
+#define false FALSE
+#else
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef bool sd_bool;
+typedef char sd_char;
+typedef int sd_int;
+typedef size_t sd_size_t;
+#endif
+++ /dev/null
-../boot/efi/loader-features.h
\ No newline at end of file
dns-domain.h
dropin.c
dropin.h
- efi-loader-features.h
efi-loader.c
efi-loader.h
enable-mempool.c