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.
121 lines
2.5 KiB
121 lines
2.5 KiB
// Trace messages
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <trace.h>
|
|
|
|
#include <tracem/macros.h>
|
|
#include <tracem/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;
|
|
}
|