You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
naka/src/trace.c

120 lines
2.5 KiB

// Trace messages
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <trace.h>
#include <macros.h>
#include <ints.h>
static _Atomic enum trace_level _t_level = _TRACE_LEVEL_DEFAULT;
const char* const _TRACE_CONTROL_ENV_NAME = "LOG_LEVEL";
const struct {const char* const name; const enum trace_level level; } _trace_level_names[] = {
#define X(name) { #name, TRACE_LEVEL_ ## name }
#define Y(name, val) { #name, TRACE_LEVEL_ ## val }
X(DEBUG), Y(TRACE, DEBUG),
X(INFO),
X(WARN),
X(ERROR),
X(FATAL),
#undef Y
#undef X
};
#define _trace_level_names_n (sizeof(_trace_level_names) / sizeof(_trace_level_names[0]))
const char* const _trace_level_descriptions[_TRACE_LEVEL_NUM] = {
"All trace messages regarding internals, only useful for debugging",
"Information messages regarding processes, recommended level",
"Only show warnings",
"Only show errors",
"Only show fatal (aborting) errors",
};
static bool _trace_lookup(const char*pIN name, enum trace_level *pOUT olevel)
{
debug_assert(name);
for(usize i=0;i<_trace_level_names_n;i++) {
let level = &_trace_level_names[i];
debug_assert(level && level->name);
if(strcmp(name, level->name) == 0) {
*olevel =level->level;
return true;
}
}
return false;
}
static bool _trace_reverse_lookup(enum trace_level level, const char* *pOUT name)
{
for(usize i=0;i<_trace_level_names_n;i++) {
let lv = &_trace_level_names[i];
debug_assert(lv && lv->name);
if(lv->level == level) {
*name = lv->name;
return true;
}
}
return false;
}
const char* trace_name_of(enum trace_level lv)
{
const char* ret;
if(!_trace_reverse_lookup(lv, &ret)) return NULL;
else return ret;
}
inline enum trace_level trace_max_level()
{
return _t_level;
}
inline static bool _trace_hidden(enum trace_level l)
{
return l < trace_max_level();
}
int _t_fprintf(enum trace_level l, FILE* output, const char* msg, ...)
{
if(_trace_hidden(l)) return 0;
va_list ap;
va_start(ap, msg);
register int r = vfprintf(output, msg, ap);
va_end(ap);
return r;
}
void trace_init_with(enum trace_level max_level)
{
_t_level = max_level;
}
static inline bool _try_get_env(const char* name, const char* *pOUT value)
{
return !!(*value = (const char*)getenv(name));
}
int trace_init()
{
const char* eval;
if(!_try_get_env(_TRACE_CONTROL_ENV_NAME, &eval)) return 1;
else {
assert(eval);
if(*eval == 0) return 1; // Count empty string as default.
enum trace_level level;
if(!_trace_lookup(eval, &level)) return 0;
else {
trace_init_with(level);
}
}
return 1;
}