diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-12-13 18:49:15 -0500 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-12-13 18:49:15 -0500 |
commit | c578a300c7d0d46662fcd0bdce69af95a821bc18 (patch) | |
tree | a99de333f2812d7c018820f39d78b8c4e744f705 /libmisc | |
parent | 6a719c63ecb83a850c317ea94b8932aa0c857770 (diff) | |
parent | 57cc0523f600575feda09bd9fae13f685ce85b0f (diff) |
Merge commit '57cc0523f600575feda09bd9fae13f685ce85b0f'
Diffstat (limited to 'libmisc')
-rw-r--r-- | libmisc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libmisc/include/libmisc/log.h | 14 | ||||
-rw-r--r-- | libmisc/include/libmisc/macro.h | 55 | ||||
-rw-r--r-- | libmisc/include/libmisc/private.h | 29 | ||||
-rw-r--r-- | libmisc/tests/test_assert.c | 14 | ||||
-rw-r--r-- | libmisc/tests/test_macro.c | 32 |
6 files changed, 103 insertions, 42 deletions
diff --git a/libmisc/CMakeLists.txt b/libmisc/CMakeLists.txt index 02b19d5..83e91fe 100644 --- a/libmisc/CMakeLists.txt +++ b/libmisc/CMakeLists.txt @@ -15,6 +15,7 @@ add_lib_test(libmisc test_assert) add_lib_test(libmisc test_endian) add_lib_test(libmisc test_hash) add_lib_test(libmisc test_log) +add_lib_test(libmisc test_macro) add_lib_test(libmisc test_private) add_lib_test(libmisc test_rand) add_lib_test(libmisc test_vcall) diff --git a/libmisc/include/libmisc/log.h b/libmisc/include/libmisc/log.h index b4f5461..8c6d6be 100644 --- a/libmisc/include/libmisc/log.h +++ b/libmisc/include/libmisc/log.h @@ -9,6 +9,8 @@ #include <stdint.h> /* for uint8_t */ +#include <libmisc/macro.h> + #ifndef LOG_NAME #error "each compilation unit that includes <libmisc/log.h> must define LOG_NAME" #endif @@ -18,17 +20,13 @@ #else #define _LOG_NDEBUG 0 #endif -#define __LOG_STR(x) #x -#define _LOG_STR(x) __LOG_STR(x) -#define __LOG_CAT3(a, b, c) a ## b ## c -#define _LOG_CAT3(a, b, c) __LOG_CAT3(a, b, c) [[format(printf, 1, 2)]] int _log_printf(const char *format, ...); -#define n_errorf(nam, fmt, ...) do { _log_printf("error: " _LOG_STR(nam) ": " fmt "\n" __VA_OPT__(,) __VA_ARGS__); } while (0) -#define n_infof(nam, fmt, ...) do { _log_printf("info : " _LOG_STR(nam) ": " fmt "\n" __VA_OPT__(,) __VA_ARGS__); } while (0) -#define n_debugf(nam, fmt, ...) do { if (_LOG_CAT3(CONFIG_, nam, _DEBUG) && !_LOG_NDEBUG) \ - _log_printf("debug: " _LOG_STR(nam) ": " fmt "\n" __VA_OPT__(,) __VA_ARGS__); } while (0) +#define n_errorf(nam, fmt, ...) do { _log_printf("error: " LM_STR_(nam) ": " fmt "\n" __VA_OPT__(,) __VA_ARGS__); } while (0) +#define n_infof(nam, fmt, ...) do { _log_printf("info : " LM_STR_(nam) ": " fmt "\n" __VA_OPT__(,) __VA_ARGS__); } while (0) +#define n_debugf(nam, fmt, ...) do { if (LM_CAT3_(CONFIG_, nam, _DEBUG) && !_LOG_NDEBUG) \ + _log_printf("debug: " LM_STR_(nam) ": " fmt "\n" __VA_OPT__(,) __VA_ARGS__); } while (0) #define errorf(fmt, ...) n_errorf(LOG_NAME, fmt, __VA_ARGS__) #define infof(fmt, ...) n_infof(LOG_NAME, fmt, __VA_ARGS__) diff --git a/libmisc/include/libmisc/macro.h b/libmisc/include/libmisc/macro.h new file mode 100644 index 0000000..9bb068f --- /dev/null +++ b/libmisc/include/libmisc/macro.h @@ -0,0 +1,55 @@ +/* libmisc/macro.h - Useful C preprocessor macros + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIBMISC_MACRO_H_ +#define _LIBMISC_MACRO_H_ + +/* for function definitions */ + +#define LM_UNUSED(argname) +#define LM_ALWAYS_INLINE [[gnu::always_inline]] inline +#define LM_NEVER_INLINE [[gnu::noinline]] +#define LM_FLATTEN [[gnu::flatten]] + +/* numeric */ + +#define LM_ARRAY_LEN(ary) (sizeof(ary)/sizeof((ary)[0])) +#define LM_CEILDIV(n, d) ( ((n)+(d)-1) / (d) ) +#define LM_ROUND_UP(n, d) ( LM_CEILDIV(n, d) * (d) ) /** Return `n` rounded up to the nearest multiple of `d` */ +#define LM_NEXT_POWER_OF_2(x) ((1ULL)<<((sizeof(unsigned long long)*8)-__builtin_clzll(x))) + +/* strings */ + +#define LM_STR(x) #x +#define LM_STR_(x) LM_STR(x) + +/* token pasting */ + +#define LM_CAT2(a, b) a ## b +#define LM_CAT3(a, b, c) a ## b ## c + +#define LM_CAT2_(a, b) LM_CAT2(a, b) +#define LM_CAT3_(a, b, c) LM_CAT3(a, b, c) + +/* macro arguments */ + +#define LM_SECOND(a, b, ...) b +#define LM_EAT(...) +#define LM_EXPAND(...) __VA_ARGS__ + +/* conditionals */ + +#define LM_T xxTxx +#define LM_F xxFxx + +#define LM_SENTINEL() bogus, LM_T /* a magic sentinel value */ +#define LM_IS_SENTINEL(...) LM_SECOND(__VA_ARGS__, LM_F) + +#define LM_IF(cond) LM_CAT2(_LM_IF__, cond) /* LM_IF(cond)(then)(else) */ +#define _LM_IF__xxTxx(...) __VA_ARGS__ LM_EAT +#define _LM_IF__xxFxx(...) LM_EXPAND + +#endif /* _LIBMISC_MACRO_H_ */ diff --git a/libmisc/include/libmisc/private.h b/libmisc/include/libmisc/private.h index bc5e7ad..1db7915 100644 --- a/libmisc/include/libmisc/private.h +++ b/libmisc/include/libmisc/private.h @@ -7,31 +7,10 @@ #ifndef _LIBMISC_PRIVATE_H_ #define _LIBMISC_PRIVATE_H_ -/* primitive utilities */ +#include <libmisc/macro.h> -#define _SECOND(a, b, ...) b - -#define _CAT(a, b) a ## b -#define _CAT2(a, b) _CAT(a, b) -#define _EAT(...) -#define _EXPAND(...) __VA_ARGS__ - -/* conditionals */ - -#define _T xxTxx -#define _F xxFxx - -#define _SENTINEL() bogus, _T /* a magic sentinel value */ -#define _IS_SENTINEL(...) _SECOND(__VA_ARGS__, _F) - -#define _IF(cond) _CAT(_IF__, cond) /* _IF(cond)(then)(else) */ -#define _IF__xxTxx(...) __VA_ARGS__ _EAT -#define _IF__xxFxx(...) _EXPAND - -/* high-level functionality */ - -#define YES _SENTINEL() -#define BEGIN_PRIVATE(name) _IF(_IS_SENTINEL(IMPLEMENTATION_FOR_##name))()(struct {) -#define END_PRIVATE(name) _IF(_IS_SENTINEL(IMPLEMENTATION_FOR_##name))()(} _CAT2(_HIDDEN_, __COUNTER__);) +#define YES LM_SENTINEL() +#define BEGIN_PRIVATE(name) LM_IF(LM_IS_SENTINEL(IMPLEMENTATION_FOR_##name))()(struct {) +#define END_PRIVATE(name) LM_IF(LM_IS_SENTINEL(IMPLEMENTATION_FOR_##name))()(} LM_CAT2_(_HIDDEN_, __COUNTER__);) #endif /* _LIBMISC_PRIVATE_H_ */ diff --git a/libmisc/tests/test_assert.c b/libmisc/tests/test_assert.c index 5b28561..189f6de 100644 --- a/libmisc/tests/test_assert.c +++ b/libmisc/tests/test_assert.c @@ -9,12 +9,11 @@ #include <string.h> #include <stdlib.h> +#include <libmisc/macro.h> #include <libmisc/assert.h> #include "test.h" -#define UNUSED(name) - /* Intercept failures and logging *********************************************/ bool global_failed; @@ -64,23 +63,20 @@ int vprintf(const char *format, va_list ap) { } \ } while (0) -#define _STR(x) #x -#define STR(x) _STR(x) - /* Actual tests ***************************************************************/ static_assert(sizeof(char) == 1); int main() { test_should_succeed(assert(true)); - test_should_fail(assert(false), "error: ASSERT: "__FILE__":"STR(__LINE__)":main(): assertion \"false\" failed\n"); + test_should_fail(assert(false), "error: ASSERT: "__FILE__":"LM_STR_(__LINE__)":main(): assertion \"false\" failed\n"); test_should_succeed(assert_msg(true, "foo")); - test_should_fail(assert_msg(false, "foo"), "error: ASSERT: "__FILE__":"STR(__LINE__)":main(): assertion \"false\" failed: foo\n"); + test_should_fail(assert_msg(false, "foo"), "error: ASSERT: "__FILE__":"LM_STR_(__LINE__)":main(): assertion \"false\" failed: foo\n"); test_should_succeed(assert_msg(true, NULL)); - test_should_fail(assert_msg(false, NULL), "error: ASSERT: "__FILE__":"STR(__LINE__)":main(): assertion \"false\" failed\n"); + test_should_fail(assert_msg(false, NULL), "error: ASSERT: "__FILE__":"LM_STR_(__LINE__)":main(): assertion \"false\" failed\n"); - test_should_fail(assert_notreached("xxx"), "error: ASSERT: "__FILE__":"STR(__LINE__)":main(): assertion \"notreached\" failed: xxx\n"); + test_should_fail(assert_notreached("xxx"), "error: ASSERT: "__FILE__":"LM_STR_(__LINE__)":main(): assertion \"notreached\" failed: xxx\n"); if (global_log) { free(global_log); diff --git a/libmisc/tests/test_macro.c b/libmisc/tests/test_macro.c new file mode 100644 index 0000000..7cbf9d3 --- /dev/null +++ b/libmisc/tests/test_macro.c @@ -0,0 +1,32 @@ +/* libmisc/tests/test_macro.c - Tests for <libmisc/macro.h> + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libmisc/macro.h> + +#include "test.h" + +int main() { + /* valid down to 0. */ + test_assert(LM_NEXT_POWER_OF_2(0) == 1); + test_assert(LM_NEXT_POWER_OF_2(1) == 2); + test_assert(LM_NEXT_POWER_OF_2(2) == 4); + test_assert(LM_NEXT_POWER_OF_2(3) == 4); + test_assert(LM_NEXT_POWER_OF_2(4) == 8); + test_assert(LM_NEXT_POWER_OF_2(5) == 8); + test_assert(LM_NEXT_POWER_OF_2(6) == 8); + test_assert(LM_NEXT_POWER_OF_2(7) == 8); + test_assert(LM_NEXT_POWER_OF_2(8) == 16); + /* ... */ + test_assert(LM_NEXT_POWER_OF_2(16) == 32); + /* ... */ + test_assert(LM_NEXT_POWER_OF_2(0x7000000000000000) == 0x8000000000000000); + /* ... */ + test_assert(LM_NEXT_POWER_OF_2(0x8000000000000000-1) == 0x8000000000000000); + /* Valid up to 0x8000000000000000-1 = (1<<63)-1 */ + test_assert(LM_NEXT_POWER_OF_2(0x8000000000000000) == 0); /* :( */ + + return 0; +} |