/** * @file log.hxx * @author Piotr Krygier (everyonencancode@gmail.com) * @brief Logging interfaces * @version 0.1 * @date 2022-02-11 * * @copyright Copyright (c) 2022 * */ #ifndef LOG_H #define LOG_H #include /* Controls level of logging. TODO: Move this to cmake or some config */ #define LOG_LEVEL 6 #define LOG(level, ...) _LOG_##level(__VA_ARGS__) #if LOG_LEVEL >= 1 #define _LOG_FATAL(...) __LOG(FATAL, __VA_ARGS__) #else #define _LOG_FATAL(...) #endif #if LOG_LEVEL >= 2 #define _LOG_ERROR(...) __LOG(ERROR, __VA_ARGS__) #else #define _LOG_ERROR(...) #endif #if LOG_LEVEL >= 3 #define _LOG_WARNING(...) __LOG(WARNING, __VA_ARGS__) #else #define _LOG_WARNING(...) #endif #if LOG_LEVEL >= 4 #define _LOG_INFO(...) __LOG(INFO, __VA_ARGS__) #else #define _LOG_INFO(...) #endif #if LOG_LEVEL >= 5 #define _LOG_DEBUG(...) __LOG(DEBUG, __VA_ARGS__) #else #define _LOG_DEBUG(...) #endif #if LOG_LEVEL >= 6 #define _LOG_TRACE(...) __LOG(TRACE, __VA_ARGS__) #else #define _LOG_TRACE(...) #endif /* Macro magic, that makes logging work. It's better than C++ solution anyway... */ #define _LOG_SIZEOF(...) __LOG_SIZEOF(__VA_ARGS__, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0) #define __LOG_SIZEOF(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, N, \ ...) \ N #define _LOG_EVAL(x) x #define __LOG(level, ...) ___LOG(_LOG_SIZEOF(__VA_ARGS__), level, __VA_ARGS__) #define ___LOG(n, ...) ____LOG(n, __VA_ARGS__) #define ____LOG(n, ...) ____LOG##n(__VA_ARGS__) #define ____LOG1(level, format) \ fprintf(stdout, \ "[" #level \ "]" \ "\t%s:%d\t" format "\n", \ __builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__, __LINE__) #define ____LOG2(level, format, ...) \ fprintf(stdout, \ "[" #level \ "]" \ "\t%s:%d\t" format "\n", \ __builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__, __LINE__, __VA_ARGS__) typedef enum { TRACE = 1, DEBUG = 2, INFO = 3, WARNING = 4, ERROR = 5, FATAL = 6 } LogLevel; #endif /* LOG_H */