Code:
/*** WOULD BE in header file **/
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#ifndef MAYBE_UNUSED
#if defined(__clang_analyzer__ ) || defined(__GNUC__)
#define MAYBE_UNUSED __attribute__((unused))
#else
#define MAYBE_UNUSED /*@unused@*/
#endif
#endif /*** MAYBE_UNUSED ***/
#define TEST_LOG( xx_lvl, xx_fmt, xx_args...) \
test_loggers[((unsigned int)(xx_lvl))%MAX_LOG_LEVELS] \
(xx_lvl, __FILE__, __func__, __LINE__, xx_fmt, ## xx_args)
#define MAX_LOG_LEVELS 14
typedef void (*TEST_LOG_FUNC)(uint8_t level, const char *file, const char *func, int line, const char *fmt, ...)
__attribute__((format(printf,5, 6)));
extern TEST_LOG_FUNC test_loggers[MAX_LOG_LEVELS] ;
extern int set_log_level(uint8_t lvl,FILE *fp);
/**** SOURCE FILE *****/
static void nop_log(uint8_t level, const char *file, const char *func, int line, const char *fmt, ...)
__attribute__((format(printf,5, 6)));
static void do_log(uint8_t level, const char *file, const char *func, int line, const char *fmt, ...)
__attribute__((format(printf,5, 6)));
static FILE *logfp = NULL;
static void nop_log(MAYBE_UNUSED uint8_t level, MAYBE_UNUSED const char *file, MAYBE_UNUSED const char *func, MAYBE_UNUSED int line, MAYBE_UNUSED MAYBE_UNUSED const char *fmt, ...)
{
}
static void do_log(uint8_t level, const char *file, const char *func, int line, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(logfp,"%s:%d %s [%d]:",file,line,func, level);
vfprintf(logfp, fmt, ap);
va_end(ap);
}
/*** would_be_in src file ***/
TEST_LOG_FUNC
test_loggers[MAX_LOG_LEVELS] =
{
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
nop_log,
};
int
set_log_level(uint8_t lvl, FILE *fp)
{
int x = lvl;
if(fp == NULL)
{
fp = stdout;
}
logfp = fp;
if(lvl >= MAX_LOG_LEVELS)
{
lvl = MAX_LOG_LEVELS-1;
}
for(x = lvl; x-->0;)
{
test_loggers[x] = do_log;
}
for(x = lvl; ++x < MAX_LOG_LEVELS;)
{
test_loggers[x] = nop_log;
}
return(lvl);
}
#if 1
int
main(MAYBE_UNUSED int argc, MAYBE_UNUSED const char **argv, MAYBE_UNUSED const char **envr)
{
TEST_LOG_FUNC log_me = nop_log;
set_log_level(10,NULL);
nop_log(10,__FILE__,__func__,__LINE__,"bad %d\n");
do_log(10,__FILE__,__func__,__LINE__,"bad %d\n");
log_me(10,__FILE__,__func__,__LINE__,"bad %d\n");
TEST_LOG(10,"bad %d\n");
TEST_LOG(11,"bad %d\n");
return(0);
}
#endif