radare2/libr/util/log.c
pancake 4823451497 Fix build and tests
* Fix one x86-64-specific test to pass everywhere
2022-04-22 05:46:34 +02:00

200 lines
4.3 KiB
C

/* radare - LGPL - Copyright 2010-2022 - pancake, ret2libc */
#define R_LOG_ORIGIN "util.log"
#include <r_core.h>
#include <stdarg.h>
static const char *level_tags[] = { // Log level to tag string lookup array
[R_LOGLVL_FATAL] = "FATAL",
[R_LOGLVL_ERROR] = "ERROR",
[R_LOGLVL_INFO] = "INFO",
[R_LOGLVL_WARN] = "WARN",
[R_LOGLVL_DEBUG] = "DEBUG",
};
static const char *level_name(int i) {
if (i >= 0 && i < R_LOGLVL_LAST) {
return level_tags[i];
}
return "UNKN";
}
static R_TH_LOCAL RLog *rlog = NULL;
// shouldnt be necessary as global thread-local instance
R_API void r_log_init(void) {
if (!rlog) {
rlog = R_NEW0 (RLog);
}
}
R_API void r_log_fini(void) {
if (rlog) {
free (rlog->file);
free (rlog->filter);
free (rlog);
rlog = NULL;
}
}
R_API void r_log_show_ts(bool ts) {
r_log_init ();
rlog->show_ts = ts;
}
R_API void r_log_set_level(RLogLevel level) {
r_log_init ();
rlog->level = level;
}
R_API void r_log_set_traplevel(RLogLevel level) {
r_log_init ();
rlog->traplevel = level;
}
R_API void r_log_set_filter(const char *s) {
r_log_init ();
R_FREE (rlog->filter);
if (R_STR_ISNOTEMPTY (s)) {
rlog->filter = strdup (s);
}
}
R_API void r_log_set_file(const char *filename) {
r_log_init ();
free (rlog->file);
rlog->file = strdup (filename);
}
R_API void r_log_show_origin(bool show_origin) {
r_log_init ();
rlog->show_origin = show_origin;
}
R_API void r_log_set_colors(bool color) {
r_log_init ();
rlog->color = color;
}
R_API void r_log_set_quiet(bool bq) {
r_log_init ();
rlog->quiet = bq;
}
R_API bool r_log_match(int level, const char *origin) { // , const char *sub_origin, const char *fmt, ...) {
r_log_init ();
if (R_STR_ISNOTEMPTY (rlog->filter)) {
if (strstr (origin, rlog->filter)) {
return false;
}
}
if (rlog->cbs) {
RListIter *iter;
RLogCallback cb;
r_list_foreach (rlog->cbs, iter, cb) {
if (cb (rlog->user, level, origin, NULL)) {
return true;
}
}
}
return level < rlog->level;
}
R_API void r_log_vmessage(RLogLevel level, const char *origin, const char *fmt, va_list ap) {
char out[512];
r_log_init ();
int type = 3;
vsnprintf (out, sizeof (out), fmt, ap);
if (rlog->cbs) {
RListIter *iter;
RLogCallback cb;
r_list_foreach (rlog->cbs, iter, cb) {
cb (rlog->user, type, NULL, out);
}
}
RStrBuf *sb = r_strbuf_new ("");
if (rlog->color) {
const char *k = Color_YELLOW;
switch (level) {
case R_LOGLVL_FATAL:
case R_LOGLVL_ERROR:
k = Color_RED;
break;
case R_LOGLVL_INFO:
k = Color_YELLOW;
break;
case R_LOGLVL_WARN:
k = Color_MAGENTA;
break;
case R_LOGLVL_DEBUG:
k = Color_GREEN;
break;
default:
break;
}
r_strbuf_appendf (sb, "%s%s: ", k, level_name (level));
if (rlog->show_origin) {
r_strbuf_appendf (sb, Color_YELLOW "[%s] " Color_RESET, origin);
} else {
r_strbuf_appendf (sb, Color_RESET);
}
} else {
r_strbuf_appendf (sb, "%s: ", level_name (level));
if (rlog->show_origin) {
r_strbuf_appendf (sb, "[%s] ", origin);
}
}
char ts[32] = {0};
if (rlog->show_ts) {
ut64 now = r_time_now ();
if (rlog->color) {
r_strbuf_appendf (sb, ts, sizeof (ts), Color_CYAN "[ts:%" PFMT64u "] " Color_RESET, now);
} else {
r_strbuf_appendf (sb, ts, sizeof (ts), "[ts:%" PFMT64u "] ", now);
}
}
r_strbuf_appendf (sb, "%s%s\n", ts, out);
char * s = r_strbuf_drain (sb);
sb = NULL;
if (!rlog->quiet) {
eprintf ("%s", s);
}
if (R_STR_ISNOTEMPTY (rlog->file)) {
r_file_dump (rlog->file, (const ut8*)s, strlen (s), true);
}
if (rlog->traplevel && (level >= rlog->traplevel || level == R_LOGLVL_FATAL)) {
r_sys_backtrace ();
r_sys_breakpoint ();
}
}
R_API void r_log_message(RLogLevel level, const char *origin, const char *fmt, ...) {
va_list ap;
va_start (ap, fmt);
r_log_vmessage (level, origin, fmt, ap);
va_end (ap);
}
R_API void r_log_add_callback(RLogCallback cb) {
r_log_init ();
if (!rlog->cbs) {
rlog->cbs = r_list_new ();
}
if (!r_list_contains (rlog->cbs, cb)) {
r_list_append (rlog->cbs, cb);
}
}
R_API void r_log_del_callback(RLogCallback cb) {
r_log_init ();
r_list_delete_data (rlog->cbs, cb);
}
R_API void r_log(const char *funcname, const char *filename, ut32 lineno, RLogLevel level, const char *origin, const char *fmtstr, ...) {
va_list args;
va_start (args, fmtstr);
r_log_vmessage (level, origin, fmtstr, args);
va_end (args);
}