#ifndef LOG_H #define LOG_H #include "string.h" #define LOG_LEVEL(l) (l <= LOG_LEVEL_COMPTIME) /* Log level configuration */ #ifndef LOG_LEVEL_COMPTIME # if RTC || PROFILING # define LOG_LEVEL_COMPTIME LOG_LEVEL_DEBUG # else # define LOG_LEVEL_COMPTIME LOG_LEVEL_INFO # endif #endif /* Source location configuration */ #ifndef LOG_INCLUDE_SOURCE_LOCATION # define LOG_INCLUDE_SOURCE_LOCATION (DEBINFO) #endif #define LOG_LEVEL_NONE -1 #define LOG_LEVEL_CRITICAL 0 #define LOG_LEVEL_ERROR 1 #define LOG_LEVEL_WARNING 2 #define LOG_LEVEL_INFO 3 #define LOG_LEVEL_DEBUG 4 #define LOG_LEVEL_COUNT 5 /* ========================== * * Callback interface * ========================== */ struct log_level_settings { struct string shorthand; u32 color; }; struct log_event { i32 level; struct string msg; /* Lifetime is only as long as the callback function call */ struct log_level_settings settings; /* These will be nulled if LOG_INCLUDE_SOURCE_LOCATION is disabled */ struct string file; i32 line; }; typedef void (log_event_callback_func)(struct log_event); void log_register_callback(log_event_callback_func *func); /* ========================== * * Logging macros * ========================== */ #if LOG_LEVEL(LOG_LEVEL_CRITICAL) # if LOG_INCLUDE_SOURCE_LOCATION # define log_critical(msg) _log(LOG_LEVEL_CRITICAL, STR(__FILE__), __LINE__, msg) # define logf_critical(fmt, ...) _logf(LOG_LEVEL_CRITICAL, STR(__FILE__), __LINE__, STR(fmt), __VA_ARGS__, FMT_END) # else # define log_critical(msg) _log(LOG_LEVEL_CRITICAL, msg) # define logf_critical(fmt, ...) _logf(LOG_LEVEL_CRITICAL, STR(fmt), __VA_ARGS__, FMT_END) # endif #else # define log_critical(msg) # define logf_critical(fmt, ...) #endif #if LOG_LEVEL(LOG_LEVEL_ERROR) # if LOG_INCLUDE_SOURCE_LOCATION # define log_error(msg) _log(LOG_LEVEL_ERROR, STR(__FILE__), __LINE__, msg) # define logf_error(fmt, ...) _logf(LOG_LEVEL_ERROR, STR(__FILE__), __LINE__, STR(fmt), __VA_ARGS__, FMT_END) # else # define log_error(msg) _log(LOG_LEVEL_ERROR, msg) # define logf_error(fmt, ...) _logf(LOG_LEVEL_ERROR, STR(fmt), __VA_ARGS__, FMT_END) # endif #else # define log_error(msg) # define logf_error(fmt, ...) #endif #if LOG_LEVEL(LOG_LEVEL_WARNING) # if LOG_INCLUDE_SOURCE_LOCATION # define log_warning(msg) _log(LOG_LEVEL_WARNING, STR(__FILE__), __LINE__, msg) # define logf_warning(fmt, ...) _logf(LOG_LEVEL_WARNING, STR(__FILE__), __LINE__, STR(fmt), __VA_ARGS__, FMT_END) # else # define log_warning(msg) _log(LOG_LEVEL_WARNING, msg) # define logf_warning(fmt, ...) _logf(LOG_LEVEL_WARNING, STR(fmt), __VA_ARGS__, FMT_END) # endif #else # define log_warning(msg) # define logf_warning(fmt, ...) #endif #if LOG_LEVEL(LOG_LEVEL_DEBUG) # if LOG_INCLUDE_SOURCE_LOCATION # define log_debug(msg) _log(LOG_LEVEL_DEBUG, STR(__FILE__), __LINE__, msg) # define logf_debug(fmt, ...) _logf(LOG_LEVEL_DEBUG, STR(__FILE__), __LINE__, STR(fmt), __VA_ARGS__, FMT_END) # else # define log_debug(msg) _log(LOG_LEVEL_DEBUG, msg) # define logf_debug(fmt, ...) _logf(LOG_LEVEL_DEBUG, STR(fmt), __VA_ARGS__, FMT_END) # endif #else # define log_debug(msg) # define logf_debug(fmt, ...) #endif #if LOG_LEVEL(LOG_LEVEL_INFO) # if LOG_INCLUDE_SOURCE_LOCATION # define log_info(msg) _log(LOG_LEVEL_INFO, STR(__FILE__), __LINE__, msg) # define logf_info(fmt, ...) _logf(LOG_LEVEL_INFO, STR(__FILE__), __LINE__, STR(fmt), __VA_ARGS__, FMT_END) # else # define log_info(msg) _log(LOG_LEVEL_INFO, msg) # define logf_info(fmt, ...) _logf(LOG_LEVEL_INFO, STR(fmt), __VA_ARGS__, FMT_END) # endif #else # define log_info(msg) # define logf_info(fmt, ...) #endif /* ========================== * * Function declarations * ========================== */ struct log_startup_receipt { i32 _; }; struct log_startup_receipt log_startup(struct string logfile_path); #if LOG_INCLUDE_SOURCE_LOCATION void _log(i32 level, struct string file, u32 line, struct string msg); #else void _log(i32 level, struct string msg); #endif #if LOG_INCLUDE_SOURCE_LOCATION void _logfv(i32 level, struct string file, u32 line, struct string fmt, va_list args); #else void _logfv(i32 level, struct string fmt, va_list args); #endif #if LOG_INCLUDE_SOURCE_LOCATION void _logf(i32 level, struct string file, u32 line, struct string fmt, ...); #else void _logf(i32 level, struct string fmt, ...); #endif #endif