diff options
Diffstat (limited to 'libmisc')
-rw-r--r-- | libmisc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libmisc/assert.c | 4 | ||||
-rw-r--r-- | libmisc/include/libmisc/_intercept.h | 21 | ||||
-rw-r--r-- | libmisc/include/libmisc/log.h | 9 | ||||
-rw-r--r-- | libmisc/intercept.c | 25 | ||||
-rw-r--r-- | libmisc/log.c | 10 | ||||
-rw-r--r-- | libmisc/tests/test_assert.c | 18 | ||||
-rw-r--r-- | libmisc/tests/test_log.c | 47 | ||||
-rw-r--r-- | libmisc/tests/test_rand.c | 13 |
9 files changed, 94 insertions, 54 deletions
diff --git a/libmisc/CMakeLists.txt b/libmisc/CMakeLists.txt index 5052f29..8d842c3 100644 --- a/libmisc/CMakeLists.txt +++ b/libmisc/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(libmisc INTERFACE) target_include_directories(libmisc SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) target_sources(libmisc INTERFACE assert.c + intercept.c log.c ) target_compile_options(libmisc INTERFACE "$<$<COMPILE_LANGUAGE:C>:-fplan9-extensions>") diff --git a/libmisc/assert.c b/libmisc/assert.c index 8231c85..69c0530 100644 --- a/libmisc/assert.c +++ b/libmisc/assert.c @@ -5,7 +5,6 @@ */ #include <stdbool.h> /* for bool, true, false */ -#include <stdlib.h> /* for abort() */ #define LOG_NAME ASSERT #include <libmisc/log.h> /* for errorf() */ @@ -13,7 +12,6 @@ #include <libmisc/assert.h> #ifndef NDEBUG -[[noreturn, gnu::weak]] void __assert_msg_fail(const char *expr, const char *file, unsigned int line, const char *func, const char *msg) { @@ -26,6 +24,6 @@ void __assert_msg_fail(const char *expr, msg ? ": " : "", msg ?: ""); in_fail = false; } - abort(); + __lm_abort(); } #endif diff --git a/libmisc/include/libmisc/_intercept.h b/libmisc/include/libmisc/_intercept.h new file mode 100644 index 0000000..47e4620 --- /dev/null +++ b/libmisc/include/libmisc/_intercept.h @@ -0,0 +1,21 @@ +/* libmisc/_intercept.h - Interceptable ("weak") functions + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIBMISC__INTERCEPT_H_ +#define _LIBMISC__INTERCEPT_H_ + +/* pico-sdk/newlib define these to be [[gnu:weak]] already, but + * depending on optimization options glibc might not, and GCC might + * assume it knows what they do and optimize them out. So define our + * own `__lm_` wrappers that GCC/glibc won't interfere with. + */ + +[[format(printf, 1, 2)]] +int __lm_printf(const char *format, ...); + +[[noreturn]] void __lm_abort(void); + +#endif /* _LIBMISC__INTERCEPT_H_ */ diff --git a/libmisc/include/libmisc/log.h b/libmisc/include/libmisc/log.h index 8c6d6be..121b0e1 100644 --- a/libmisc/include/libmisc/log.h +++ b/libmisc/include/libmisc/log.h @@ -10,6 +10,7 @@ #include <stdint.h> /* for uint8_t */ #include <libmisc/macro.h> +#include <libmisc/_intercept.h> #ifndef LOG_NAME #error "each compilation unit that includes <libmisc/log.h> must define LOG_NAME" @@ -21,12 +22,10 @@ #define _LOG_NDEBUG 0 #endif -[[format(printf, 1, 2)]] int _log_printf(const char *format, ...); - -#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_errorf(nam, fmt, ...) do { __lm_printf("error: " LM_STR_(nam) ": " fmt "\n" __VA_OPT__(,) __VA_ARGS__); } while (0) +#define n_infof(nam, fmt, ...) do { __lm_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) + __lm_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/intercept.c b/libmisc/intercept.c new file mode 100644 index 0000000..dda8c09 --- /dev/null +++ b/libmisc/intercept.c @@ -0,0 +1,25 @@ +/* libmisc/intercept.c - Interceptable ("weak") functions + * + * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <stdarg.h> /* for va_list, va_start(), va_end() */ +#include <stdio.h> /* for vprintf() */ +#include <stdlib.h> /* for abort() */ + +#include <libmisc/_intercept.h> + +[[gnu::weak]] +int __lm_printf(const char *format, ...) { + va_list va; + va_start(va, format); + int ret = vprintf(format, va); + va_end(va); + return ret; +} + +[[gnu::weak]] +void __lm_abort(void) { + abort(); +} diff --git a/libmisc/log.c b/libmisc/log.c index 9bf5366..ff4dac6 100644 --- a/libmisc/log.c +++ b/libmisc/log.c @@ -7,19 +7,11 @@ #include <stdio.h> /* for vprintf() */ #include <stdarg.h> /* for va_list, va_start(), va_end() */ -#include <libmisc/assert.h> +#include <libmisc/assert.h> /* for static_assert() */ #define LOG_NAME #include <libmisc/log.h> -int _log_printf(const char *format, ...) { - va_list va; - va_start(va, format); - int ret = vprintf(format, va); - va_end(va); - return ret; -} - static const char *byte_strs[] = { "0x00", "0x01", diff --git a/libmisc/tests/test_assert.c b/libmisc/tests/test_assert.c index 189f6de..0c51bbd 100644 --- a/libmisc/tests/test_assert.c +++ b/libmisc/tests/test_assert.c @@ -5,12 +5,14 @@ */ #include <setjmp.h> +#include <stdarg.h> /* for va_list, va_start(), va_end() */ #include <stdbool.h> -#include <string.h> #include <stdlib.h> +#include <string.h> #include <libmisc/macro.h> #include <libmisc/assert.h> +#include <libmisc/_intercept.h> #include "test.h" @@ -28,17 +30,21 @@ jmp_buf global_env; setjmp(global_env) == 0; \ }) -[[noreturn]] void abort(void) { +void __lm_abort(void) { global_failed = true; longjmp(global_env, 1); } -#define __builtin_unreachable() test_assert(0) - -int vprintf(const char *format, va_list ap) { - return vasprintf(&global_log, format, ap); +int __lm_printf(const char *format, ...) { + va_list va; + va_start(va, format); + int ret = vasprintf(&global_log, format, va); + va_end(va); + return ret; } +#define __builtin_unreachable() test_assert(0) + /* Utilities ******************************************************************/ #define test_should_succeed(test) do { \ diff --git a/libmisc/tests/test_log.c b/libmisc/tests/test_log.c index 286738d..e819c09 100644 --- a/libmisc/tests/test_log.c +++ b/libmisc/tests/test_log.c @@ -13,36 +13,43 @@ #define LOG_NAME FROBNICATE #include <libmisc/log.h> +#include <libmisc/_intercept.h> + #include "test.h" /* Intercept output ***********************************************************/ static char *log_output = NULL; -int vprintf(const char *format, va_list ap) { - return vasprintf(&log_output, format, ap); +int __lm_printf(const char *format, ...) { + va_list va; + va_start(va, format); + int ret = vasprintf(&log_output, format, va); + va_end(va); + return ret; } /* Actual tests ***************************************************************/ -#define should_print(_exp, cmd) do { \ - char *exp = _exp; \ - test_assert(!log_output); \ - cmd; \ - if (!exp) \ - test_assert(!log_output); \ - else \ - if (!(log_output != NULL && \ - strcmp(log_output, exp) == 0)) { \ - printf("exp = \"%s\"\n" \ - "act = \"%s\"\n", \ - exp, log_output); \ - test_assert(0); \ - } \ - if (log_output) { \ - free(log_output); \ - log_output = NULL; \ - } \ +#define should_print(_exp, cmd) do { \ + char *exp = _exp; \ + test_assert(!log_output); \ + cmd; \ + if (!exp) \ + test_assert(!log_output); \ + else { \ + test_assert(log_output); \ + if (strcmp(log_output, exp)) { \ + printf("exp = \"%s\"\n" \ + "act = \"%s\"\n", \ + exp, log_output); \ + test_assert(0); \ + } \ + } \ + if (log_output) { \ + free(log_output); \ + log_output = NULL; \ + } \ } while (0) int main() { diff --git a/libmisc/tests/test_rand.c b/libmisc/tests/test_rand.c index fff1b27..295ea61 100644 --- a/libmisc/tests/test_rand.c +++ b/libmisc/tests/test_rand.c @@ -8,6 +8,7 @@ #include <setjmp.h> #include <libmisc/rand.h> +#include <libmisc/_intercept.h> #include "test.h" @@ -15,19 +16,9 @@ jmp_buf *__catch; -void __assert_msg_fail(const char *expr, - const char *file, unsigned int line, const char *func, - const char *msg) { - static bool in_fail = false; +void __lm_abort(void) { if (__catch) longjmp(*__catch, 1); - if (!in_fail) { - in_fail = true; - printf("error: %s:%u:%s(): assertion \"%s\" failed%s%s\n", - file, line, func, - expr, - msg ? ": " : "", msg); - } abort(); } |