I would like to implement a debug printing mechanism that allows both run-time and compile time filtering. Filtering is accomplished via a one-hot encoded mask.
Run-time filtering is done by checking the mask within a function. If the level is not currently set it returns. Compile-time actually removes the call to the debug print.
Compile time can be implemented easily enough.
#include <stdio.h>
#define PRINT_LEVEL_0 (0x0)
#define PRINT_LEVEL_1 (0x1)
#define PRINT_LEVEL_2 (0x2)
#define PRINT_LEVEL_3 (0x4)
#define PRINT_LEVEL_4 (0x8)
#define PRINT_COMPILE_LEVEL (PRINT_LEVEL_1 | PRINT_LEVEL_3 | PRINT_LEVEL_4)
#define PRINT( printLevel, ... ) \
printLevel ## _FILTER(__VA_ARGS__)
#define PRINT_LEVEL_0_FILTER( ... ) // Compile out
#if (PRINT_COMPILE_LEVEL & PRINT_LEVEL_1)
#define PRINT_LEVEL_1_FILTER(...) printf(__VA_ARGS__)
#else
#define PRINT_LEVEL_1_FILTER(...) // Compile out
#endif
#if (PRINT_COMPILE_LEVEL & PRINT_LEVEL_2)
#define PRINT_LEVEL_2_FILTER(...) printf(__VA_ARGS__)
#else
#define PRINT_LEVEL_2_FILTER(...) // Compile out
#endif
#if (PRINT_COMPILE_LEVEL & PRINT_LEVEL_3)
#define PRINT_LEVEL_3_FILTER(...) printf(__VA_ARGS__)
#else
#define PRINT_LEVEL_3_FILTER(...) // Compile out
#endif
#if (PRINT_COMPILE_LEVEL & PRINT_LEVEL_4)
#define PRINT_LEVEL_4_FILTER(...) printf(__VA_ARGS__)
#else
#define PRINT_LEVEL_4_FILTER(...) // Compile out
#endif
int main(void)
{
PRINT( PRINT_LEVEL_3,
"PRINT_TEST NO ARGS\n" );
PRINT( PRINT_LEVEL_3,
"PRINT_TEST ONE ARGS %u\n", 1 );
PRINT( PRINT_LEVEL_3,
"PRINT_TEST TWO ARGS %u %u\n", 1, 2 );
PRINT( PRINT_LEVEL_3,
"PRINT_TEST THREE ARGS %u %u %u\n", 1, 2, 3 );
PRINT( PRINT_LEVEL_3,
"PRINT_TEST FOUR ARGS %u %u %u %u\n", 1, 2, 3, 4 );
PRINT( PRINT_LEVEL_3,
"PRINT_TEST ONE ARGS %s\n", "Garfield" );
PRINT( PRINT_LEVEL_3,
"PRINT_TEST TWO ARGS %s %s\n", "Garfield", "likes" );
PRINT( PRINT_LEVEL_3,
"PRINT_TEST THREE ARGs %s %s %s\n", "Garfield", "likes", "eating" );
PRINT( PRINT_LEVEL_3,
"PRINT_TEST FOUR ARGS %s %s %s %s\n", "Garfield", "likes", "eating", "lasagna" );
return 0;
}
This only works if a valid PRINT_LEVEL_# pre-processor is provided as the first input argument to the PRINT macro.
I am interested in finding a way to call a different macro (valid for run-time filtering) if printLevel ## _FILTER doesn't exist. The exact case would be something like:
void foo()
{
uint32_t level = PRINT_LEVEL_3;
PRINT( level, "VARIABLE LEVEL TEST" );
}
Thanks for your help!