From 690cfd32e3d8c88121cd39d20a5715a4c4814b35 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Wed, 15 Dec 2021 01:37:11 +0500 Subject: [PATCH] Add runtime assertions feature --- .github/workflows/test.yml | 4 ++-- .gitignore | 2 ++ Makefile.am | 9 +++++++ README.md | 1 + configure.ac | 5 ++++ examples/assert.c | 49 ++++++++++++++++++++++++++++++++++++++ include/Makefile.am | 1 + include/kernaux.h | 1 + include/kernaux/assert.h | 19 +++++++++++++++ src/assert.c | 19 +++++++++++++++ 10 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 examples/assert.c create mode 100644 include/kernaux/assert.h create mode 100644 src/assert.c diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b0037be..42ef4ed 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: - name: autogen run: ./autogen.sh - name: configure - run: ./configure --disable-multiboot2 CFLAGS='-Werror' + run: ./configure --enable-assert --disable-multiboot2 CFLAGS='-Werror' - name: make run: make - name: check @@ -27,7 +27,7 @@ jobs: - name: autogen run: ./autogen.sh - name: configure - run: ./configure + run: ./configure --enable-assert - name: make run: make - name: check diff --git a/.gitignore b/.gitignore index 0cc67fb..a49f5c5 100644 --- a/.gitignore +++ b/.gitignore @@ -34,11 +34,13 @@ /tests/test*.log /tests/test*.trs +/examples/assert /examples/cmdline /examples/pfa /examples/printf /examples/printf_va /examples/units_human + /tests/multiboot2_print1 /tests/multiboot2_print2 /tests/test_cmdline diff --git a/Makefile.am b/Makefile.am index c8e030f..bd4e188 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,6 +18,7 @@ TESTS = \ noinst_PROGRAMS = $(TESTS) libkernaux_a_SOURCES = \ + src/assert.c \ src/printf.c \ src/stdlib.c @@ -29,6 +30,10 @@ if ARCH_X86_64 libkernaux_a_SOURCES += src/arch/x86_64.S endif +if ENABLE_ASSERT +TESTS += examples/assert +endif + if ENABLE_CMDLINE libkernaux_a_SOURCES += src/cmdline.c TESTS += \ @@ -73,6 +78,10 @@ TESTS += \ tests/test_units_human endif +examples_assert_SOURCES = \ + $(libkernaux_a_SOURCES) \ + examples/assert.c + examples_cmdline_SOURCES = \ $(libkernaux_a_SOURCES) \ examples/cmdline.c diff --git a/README.md b/README.md index a438872..11df280 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Table of contents API --- +* [Runtime assertions](/include/kernaux/assert.h) * [Measurement units utils](/include/kernaux/units.h) *(work in progress)* * [Simple command line parser](/include/kernaux/cmdline.h) * [Multiboot 2 (GRUB 2) information parser](/include/kernaux/multiboot2.h) diff --git a/configure.ac b/configure.ac index 7bb59b0..95dbd7c 100644 --- a/configure.ac +++ b/configure.ac @@ -10,6 +10,7 @@ AC_CONFIG_SRCDIR([src/pfa.c]) AC_CANONICAL_HOST +AC_ARG_ENABLE([assert], AS_HELP_STRING([--enable-assert], [enable runtime assertions])) AC_ARG_ENABLE([cmdline], AS_HELP_STRING([--disable-cmdline], [disable command line parser])) AC_ARG_ENABLE([console], AS_HELP_STRING([--disable-console], [disable serial console])) AC_ARG_ENABLE([elf], AS_HELP_STRING([--disable-elf], [disable ELF utils])) @@ -19,6 +20,8 @@ AC_ARG_ENABLE([units], AS_HELP_STRING([--disable-units], [disable meas AM_CONDITIONAL([ARCH_I386], [test "$host_cpu" = i386]) AM_CONDITIONAL([ARCH_X86_64], [test "$host_cpu" = x86_64]) + +AM_CONDITIONAL([ENABLE_ASSERT], [test "$enable_assert" != no]) AM_CONDITIONAL([ENABLE_CMDLINE], [test "$enable_cmdline" != no]) AM_CONDITIONAL([ENABLE_CONSOLE], [test "$enable_console" != no]) AM_CONDITIONAL([ENABLE_ELF], [test "$enable_elf" != no]) @@ -28,6 +31,8 @@ AM_CONDITIONAL([ENABLE_UNITS], [test "$enable_units" != no]) AS_IF([test "$host_cpu" = i386], [AC_DEFINE([ARCH_I386], [1], [architecture is i386])]) AS_IF([test "$host_cpu" = x86_64], [AC_DEFINE([ARCH_X86_64], [1], [architecture is x86_64])]) + +AS_IF([test "$enable_assert" != no], [AC_DEFINE([ENABLE_ASSERT], [1], [enabled runtime assertions])]) AS_IF([test "$enable_cmdline" != no], [AC_DEFINE([ENABLE_CMDLINE], [1], [enabled command line parser])]) AS_IF([test "$enable_console" != no], [AC_DEFINE([ENABLE_CONSOLE], [1], [enabled serial console])]) AS_IF([test "$enable_elf" != no], [AC_DEFINE([ENABLE_ELF], [1], [enabled ELF utils])]) diff --git a/examples/assert.c b/examples/assert.c new file mode 100644 index 0000000..6813969 --- /dev/null +++ b/examples/assert.c @@ -0,0 +1,49 @@ +#include + +#include +#include +#include + +static unsigned int count = 0; +static const char *last_file = NULL; +static int last_line = 0; +static const char *last_str = NULL; + +static void assert_cb( + const char *const file, + const int line, + const char *const str +) { + ++count; + last_file = file; + last_line = line; + last_str = str; +} + +int main() +{ + kernaux_assert_cb = assert_cb; + + kernaux_assert(1 == 1); + + assert(count == 0); + assert(last_file == NULL); + assert(last_line == 0); + assert(last_str == NULL); + + kernaux_assert(1 != 1); + + assert(count == 1); + assert(strcmp(last_file, __FILE__) == 0); + assert(last_line == __LINE__ - 4); + assert(strcmp(last_str, "1 != 1") == 0); + + kernaux_assert(strcmp("qwe", "rty") == 0); + + assert(count == 2); + assert(strcmp(last_file, __FILE__) == 0); + assert(last_line == __LINE__ - 4); + assert(strcmp(last_str, "strcmp(\"qwe\", \"rty\") == 0") == 0); + + return 0; +} diff --git a/include/Makefile.am b/include/Makefile.am index aee8bb0..6d53ce0 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -2,6 +2,7 @@ nobase_include_HEADERS = \ kernaux.h \ kernaux/arch/i386.h \ kernaux/arch/x86_64.h \ + kernaux/assert.h \ kernaux/cmdline.h \ kernaux/console.h \ kernaux/multiboot2.h \ diff --git a/include/kernaux.h b/include/kernaux.h index 7255ccb..d025a26 100644 --- a/include/kernaux.h +++ b/include/kernaux.h @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/include/kernaux/assert.h b/include/kernaux/assert.h new file mode 100644 index 0000000..136a706 --- /dev/null +++ b/include/kernaux/assert.h @@ -0,0 +1,19 @@ +#ifndef KERNAUX_INCLUDED_ASSERT +#define KERNAUX_INCLUDED_ASSERT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define kernaux_assert(cond) \ + { if (!(cond)) kernaux_assert_do(__FILE__, __LINE__, #cond); } + +void kernaux_assert_do(const char *file, int line, const char *str); + +extern void (*kernaux_assert_cb)(const char *file, int line, const char *str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/assert.c b/src/assert.c new file mode 100644 index 0000000..00509ed --- /dev/null +++ b/src/assert.c @@ -0,0 +1,19 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +void (*kernaux_assert_cb)(const char *file, int line, const char *str) = NULL; + +void kernaux_assert_do( + const char *const file, + const int line, + const char *const str +) { +#ifdef ENABLE_ASSERT + if (kernaux_assert_cb) kernaux_assert_cb(file, line, str); +#endif +}