refactor logging utility

This commit is contained in:
Lephenixnoir 2022-03-27 12:57:36 +01:00
parent b37a056c2e
commit 50963d7c20
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
7 changed files with 141 additions and 111 deletions

View File

@ -2,7 +2,9 @@ cmake_minimum_required(VERSION 3.16)
project(fxos LANGUAGES C CXX)
find_package(FLEX 2.6)
add_compile_options(-Wall -Wextra -D_GNU_SOURCE -std=c++17 -O0 -g)
add_compile_options(
-Wall -Wextra -D_GNU_SOURCE -std=c++17 -O0 -g
-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/=)
#---
# fxos core
@ -15,7 +17,6 @@ set(fxos_core_SOURCES
lib/disassembly.cpp
lib/domains/relconst.cpp
lib/lang.cpp
lib/log.cpp
lib/memory.cpp
lib/os.cpp
lib/passes/cfg.cpp
@ -27,6 +28,7 @@ set(fxos_core_SOURCES
lib/vspace.cpp
lib/util/Buffer.cpp
lib/util/log.cpp
lib/util/Timer.cpp)
add_library(fxos-core ${fxos_core_SOURCES} ${FLEX_LoadAsm_OUTPUTS})

View File

@ -1,41 +0,0 @@
//---
// fxos.log: Logging functions
//---
#ifndef FXOS_LOG_H
#define FXOS_LOG_H
#include <fxos/util/format.h>
namespace FxOS::Log {
/* Message levels, used for masking and statistics */
#define LEVEL_LOG 0
#define LEVEL_WRN 1
#define LEVEL_ERR 4
/* Prefixes to set in the call to log() for brevity. The comma is included.
Typical usage would be log(ERR "logic is inconsistent"). */
#define LOG LEVEL_LOG,
#define WRN LEVEL_WRN,
#define ERR LEVEL_ERR,
/* Select the log level */
void log_setminlevel(int level);
/* Get the minimum log level */
int log_getminlevel();
/* General message logger */
void logmsg(int level, char const *function, std::string message);
/* Automatically apply format strings. Also force the first argument to be
expanded first, since this causes a comma to appear. */
#define log(level, ...) \
loghelper(level, __VA_ARGS__)
#define loghelper(level, fmtstr, ...) \
FxOS::Log::logmsg(level, __func__, format(fmtstr __VA_OPT__(,)__VA_ARGS__))
} /* namespace FxOS::Log */
#endif /* FXOS_LOG_H */

50
include/fxos/util/log.h Normal file
View File

@ -0,0 +1,50 @@
//---------------------------------------------------------------------------//
// 1100101 |_ mov #0, r4 __ //
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
// |_ base# + offset |_| /_\_\___/__/ //
//---------------------------------------------------------------------------//
// fxos/util/log: Basic logging utilities
//
// This header exposes a single macro
// FxOS_log(LEVEL, FORMAT, ...)
// where LEVEL should be "LOG", "WRN" or "ERR", FORMAT is a printf()-style
// format and variable arguments are provided as needed.
//
// The log level can be set with log_getminlevel() and log_setminlevel(). The
// point of this header is to report runtime warnings and errors caused by
// invalid input or flawed internal logic, and print performance metrics in
// debug mode.
//
// The log level can also be set with the FXOS_LOG environment variable.
//---
#ifndef FXOS_UTIL_LOG_H
#define FXOS_UTIL_LOG_H
#include <fxos/util/format.h>
namespace FxOS {
/* Message levels, for masking */
constexpr int LOG_LEVEL_LOG = 0;
constexpr int LOG_LEVEL_WRN = 1;
constexpr int LOG_LEVEL_ERR = 2;
/* Select the log level */
void log_setminlevel(int level);
/* Get the minimum log level */
int log_getminlevel();
/* General message logger */
void logmsg(int level, char const *file, int line, char const *func,
std::string message);
} /* namespace FxOS */
#define FxOS_log(level, fmt, ...) \
FxOS::logmsg(LOG_LEVEL_ ## level, __FILE__, __LINE__, __func__, \
format(fmt, ##__VA_ARGS__))
#endif /* FXOS_UTIL_LOG_H */

View File

@ -1,62 +0,0 @@
#include <fxos/log.h>
#include <iostream>
#include <map>
namespace FxOS::Log {
/* Currently configured log level */
static int loglevel = LEVEL_WRN;
/* Level of the last message */
static int lastlevel = -1;
/* Prefixes for each level */
static std::map<int,std::string> prefixes = {
{ LEVEL_WRN, "warning: " },
{ LEVEL_ERR, "error: " },
};
/* Select the log level */
void log_setminlevel(int level)
{
loglevel = level;
}
/* Get the minimum log level */
int log_getminlevel()
{
return loglevel;
}
/* General message logger */
void logmsg(int level, char const *function, std::string message)
{
if(level < loglevel) return;
bool endline = true;
bool prefix = true;
/* Add a newline if last line was unfinished, but level changed */
if(lastlevel >= 0 && lastlevel != level) std::cerr << '\n';
else if(lastlevel >= 0) prefix = false;
if(message.size() && message.back() == '\\')
{
endline = false;
message.pop_back();
}
if(prefix)
{
if(level == LEVEL_LOG) std::cerr << "[" << function << "] ";
std::cerr << prefixes[level];
}
else std::cerr << " ";
std::cerr << message;
lastlevel = -1;
if(endline) std::cerr << '\n';
else lastlevel = level;
}
} /* namespace FxOS::Log */

View File

@ -5,11 +5,8 @@
#include <fxos/disasm-passes/cfg.h>
#include <fxos/disassembly.h>
#include <fxos/errors.h>
#include <fxos/log.h>
#include <cassert>
using namespace FxOS::Log;
namespace FxOS {
CfgPass::CfgPass(Disassembly &disasm):

85
lib/util/log.cpp Normal file
View File

@ -0,0 +1,85 @@
//---------------------------------------------------------------------------//
// 1100101 |_ mov #0, r4 __ //
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
// |_ base# + offset |_| /_\_\___/__/ //
//---------------------------------------------------------------------------//
#include <fxos/util/log.h>
#include <cstdlib>
#include <cstring>
#include <iostream>
namespace FxOS {
/* Currently configured log level */
static int loglevel = LOG_LEVEL_WRN;
/* Level of the last message */
static int lastlevel = -1;
/* Initialize log level depending on environment variable at startup */
__attribute__((constructor))
static void init_log_level(void)
{
char const *FXOS_LOG = std::getenv("FXOS_LOG");
if(!FXOS_LOG)
return;
if(!strcmp(FXOS_LOG, "LOG"))
loglevel = LOG_LEVEL_LOG;
else if(!strcmp(FXOS_LOG, "WRN"))
loglevel = LOG_LEVEL_WRN;
else if(!strcmp(FXOS_LOG, "ERR"))
loglevel = LOG_LEVEL_ERR;
else FxOS_log(WRN, "invalid FXOS_LOG value: %s", FXOS_LOG);
}
void log_setminlevel(int level)
{
loglevel = level;
}
int log_getminlevel()
{
return loglevel;
}
void logmsg(int level, char const *file, int line, char const *func,
std::string message)
{
if(level < loglevel) return;
bool endline = true;
bool prefix = true;
/* Add a newline if last line was unfinished, but level changed */
if(lastlevel >= 0 && lastlevel != level) std::cerr << '\n';
else if(lastlevel >= 0) prefix = false;
if(message.size() > 0 && message.back() == '\\') {
endline = false;
message.pop_back();
}
if(prefix) {
if(level == LOG_LEVEL_LOG)
std::cerr << "[" << file << ":" << line << "@" << func << "] ";
if(level == LOG_LEVEL_WRN)
std::cerr << "warning: ";
if(level == LOG_LEVEL_ERR)
std::cerr << "err: ";
}
else std::cerr << " ";
std::cerr << message;
if(endline) {
std::cerr << '\n';
lastlevel = -1;
}
else {
lastlevel = level;
}
}
} /* namespace FxOS */

View File

@ -7,7 +7,7 @@
#include <fxos/disassembly.h>
#include <fxos/util/Timer.h>
#include <fxos/log.h>
#include <fxos/util/log.h>
#include <fxos/disasm-passes/cfg.h>
#include <fxos/disasm-passes/pcrel.h>
#include <fxos/disasm-passes/syscall.h>
@ -20,7 +20,6 @@ static void disassemble(Session &session, Disassembly &disasm,
{
Timer timer;
timer.start();
log(LOG "Running pass %s...\\", pass);
if(pass == "cfg")
{
@ -55,7 +54,7 @@ static void disassemble(Session &session, Disassembly &disasm,
p.run();
}
timer.stop();
log(LOG "%s", timer.format_time());
FxOS_log(LOG, "Finished pass <%s> in %s", pass, timer.format_time());
}
}