#Logging and Assertions
#define FIO_LOG
#include "fio-stl.h"Heap-allocation-free logging macros and assertion utilities. FIO_LOG2STDERR and the FIO_LOG_* macros are functional when FIO_LOG or FIO_LEAK_COUNTER is defined; otherwise they are no-ops.
FIO_LOG uses libc functions (vsnprintf, fwrite) and the library helper fio_memcpy32. If you are building without libc, provide your own implementations or shadowing macros before including the module.
#Log Levels
#define FIO_LOG_LEVEL_NONE 0 /* no logging */
#define FIO_LOG_LEVEL_FATAL 1 /* fatal errors */
#define FIO_LOG_LEVEL_ERROR 2 /* errors and above */
#define FIO_LOG_LEVEL_WARNING 3 /* warnings and above */
#define FIO_LOG_LEVEL_INFO 4 /* info and above */
#define FIO_LOG_LEVEL_DEBUG 5 /* everything, including debug */#Log Level Control
#FIO_LOG_LEVEL_SET
#define FIO_LOG_LEVEL_SET(new_level) fio___log_level_set(new_level)Sets the application-wide logging level. Returns the new level.
#FIO_LOG_LEVEL_GET
#define FIO_LOG_LEVEL_GET() ((fio___log_level()))Returns the current logging level as an integer.
FIO_LOG_LEVEL_SET(FIO_LOG_LEVEL_WARNING);
int level = FIO_LOG_LEVEL_GET(); /* 3 */#Configuration
#FIO_LOG_LEVEL_DEFAULT
Initial level. Defaults to FIO_LOG_LEVEL_INFO unless DEBUG is defined and truthy (defined(DEBUG) && DEBUG), in which case it is FIO_LOG_LEVEL_DEBUG.
#FIO_STDERR_FILE
#define FIO_STDERR_FILE stderrOutput destination for all logging. Define it before including ./fio-stl.h to redirect logs to another FILE*.
#FIO_LOG_LENGTH_LIMIT
#define FIO_LOG_LENGTH_LIMIT 1024Log buffer size. Keep this above 128.
- When
FIO_LOG_LENGTH_LIMIT > 128, the formatted message is limited toFIO_LOG_LENGTH_LIMIT - 34bytes, followed by a 32-byte truncation warning. - When
FIO_LOG_LENGTH_LIMIT <= 128,vsnprintfis capped atFIO_LOG_LENGTH_LIMIT - 2bytes; the truncation warning is appended afterward. - Values
<= 2are dangerous: thevsnprintfsize argument underflows/overflows.
#Core Logging Function
#FIO_LOG2STDERR
void FIO_LOG2STDERR(const char *format, ...);printf-style output to FIO_STDERR_FILE using only stack-allocated memory. Truncation follows the two FIO_LOG_LENGTH_LIMIT paths described above. In ./fio-stl/001 logging.h the name is #undef-ed before the static function definition, so a pre-include macro is removed and a post-inclusion function definition would conflict. Override it after inclusion only by defining FIO_LOG2STDERR as a macro.
#Log Macros
Most macros check the current log level before printing. FIO_LOG_WRITE has no level check and always prefixes output with the file and line number.
| Macro | Level | Prefix |
|---|---|---|
FIO_LOG_FATAL(...) |
≥ FATAL |
FATAL: (bold inverse) |
FIO_LOG_ERROR(...) |
≥ ERROR |
ERROR: (bold) |
FIO_LOG_SECURITY(...) |
≥ ERROR |
SECURITY: (bold) |
FIO_LOG_WARNING(...) |
≥ WARNING |
WARNING: (dim) |
FIO_LOG_INFO(...) |
≥ INFO |
INFO: |
FIO_LOG_DEBUG(...) |
≥ DEBUG |
DEBUG: + file:line |
FIO_LOG_DEBUG2(...) |
≥ DEBUG |
DEBUG: |
FIO_LOG_WRITE(...) |
always | file:line |
#Debug-Only Log Macros
These expand to their non-D counterparts when DEBUG is defined, and to no-ops otherwise.
FIO_LOG_DDEBUG(...)FIO_LOG_DDEBUG2(...)FIO_LOG_DERROR(...)FIO_LOG_DSECURITY(...)FIO_LOG_DWARNING(...)FIO_LOG_DINFO(...)
#Assertions
#FIO_ASSERT
#define FIO_ASSERT(cond, ...)If cond is false, prints a fatal message, prints errno and its string, sends SIGINT in debug builds, and calls exit(-1).
#FIO_ASSERT_ALLOC
#define FIO_ASSERT_ALLOC(ptr) FIO_ASSERT((ptr), "memory allocation failed.")Convenience wrapper for allocation failures.
#FIO_ASSERT_DEBUG
#define FIO_ASSERT_DEBUG(cond, ...)Active only when DEBUG is defined. On failure it behaves like FIO_ASSERT, printing the file and line number before terminating.
#FIO_ASSERT_STATIC
#define FIO_ASSERT_STATIC(cond, msg)Compile-time assertion. cond must be a constant expression; msg is a string literal with no format specifiers. Falls back to a sized-array trick on pre-C11 compilers.
See also: [Compiler Attributes](./001 compiler attributes.md).
#Leak Counter Helpers
Enabled by FIO_LEAK_COUNTER (default 1). FIO_NO_LOG and FIO_LEAK_COUNTER are mutually exclusive because leak reports are printed through the log.
#FIO_LEAK_COUNTER_DEF
#define FIO_LEAK_COUNTER_DEF(name)Defines a named counter and a cleanup function that reports remaining allocations at process exit.
#FIO_LEAK_COUNTER_ON_ALLOC
#define FIO_LEAK_COUNTER_ON_ALLOC(name)Increment the named counter. Call after a successful allocation.
#FIO_LEAK_COUNTER_ON_FREE
#define FIO_LEAK_COUNTER_ON_FREE(name)Decrement the named counter. Call when memory is freed. Detects double-free.
#FIO_LEAK_COUNTER_COUNT
#define FIO_LEAK_COUNTER_COUNT(name)Returns the current value of the named counter.
#FIO_LEAK_COUNTER_SKIP_EXIT
#define FIO_LEAK_COUNTER_SKIP_EXIT 0Set to 1 to prevent automatic leak reporting at exit.
#Example
#define FIO_LOG
#include "fio-stl.h"
int main(void) {
FIO_LOG_LEVEL_SET(FIO_LOG_LEVEL_WARNING);
FIO_LOG_INFO("not printed");
FIO_LOG_WARNING("number invalid: %d", 42);
FIO_LOG2STDERR("direct message");
void *ptr = malloc(100);
FIO_ASSERT_ALLOC(ptr);
FIO_ASSERT(ptr != NULL, "expected a pointer");
free(ptr);
return 0;
}