OpenFPGA/libs/libvtrutil/src/vtr_log.h

160 lines
6.4 KiB
C++

#ifndef VTR_LOG_H
#define VTR_LOG_H
#include <tuple>
#include <unordered_set>
#include <string>
/*
* This header defines useful logging macros for VTR projects.
*
* Message Type
* ============
*
* Three types of log message types are defined:
* VTR_LOG - The standard 'info' type log message
* VTR_LOG_WARN - A warning log message
* VTR_LOG_ERROR - An error log message
*
* For example:
*
* VTR_LOG("This produces a regular '%s' message\n", "info");
* VTR_LOG_WARN("This produces a '%s' message\n", "warning");
* VTR_LOG_ERROR("This produces an '%s' message\n", "error");
*
* Conditional Logging
* ===================
*
* Each of the three message types also have a VTR_LOGV_* variant,
* which will cause the message to be logged if a user-defined condition
* is satisifed.
*
* For example:
*
* VTR_LOGV(verbosity > 5, "This message will be logged only if verbosity is greater than %d\n", 5);
* VTR_LOGV_WARN(verbose, "This warning message will be logged if verbose is true\n");
* VTR_LOGV_ERROR(false, "This error message will never be logged\n");
*
* Custom Location Logging
* =======================
*
* Each of the three message types also have a VTR_LOGF_* variant,
* which will cause the message to be logged for a custom file and
* line loation.
*
* For example:
*
* VTR_LOGF("my_file.txt", 42 "This message will be logged from file 'my_file.txt' line %d\n", 42);
*
* Debug Logging
* =============
*
* For debug purposes it may be useful to have additional logging.
* This is supported by VTR_LOG_DEBUG() and VTR_LOGV_DEBUG().
*
* To avoid run-time overhead, these are only enabled if VTR_ENABLE_DEBUG_LOGGING
* is defined (disabled by default).
*/
//Unconditional logging macros
#define VTR_LOG(...) VTR_LOGV(true, __VA_ARGS__)
#define VTR_LOG_WARN(...) VTR_LOGV_WARN(true, __VA_ARGS__)
#define VTR_LOG_ERROR(...) VTR_LOGV_ERROR(true, __VA_ARGS__)
#define VTR_LOG_NOP(...) VTR_LOGV_NOP(true, __VA_ARGS__)
//Conditional logging macros
#define VTR_LOGV(expr, ...) VTR_LOGVF(expr, __FILE__, __LINE__, __VA_ARGS__)
#define VTR_LOGV_WARN(expr, ...) VTR_LOGVF_WARN(expr, __FILE__, __LINE__, __VA_ARGS__)
#define VTR_LOGV_ERROR(expr, ...) VTR_LOGVF_ERROR(expr, __FILE__, __LINE__, __VA_ARGS__)
#define VTR_LOGV_NOP(expr, ...) VTR_LOGVF_NOP(expr, __FILE__, __LINE__, __VA_ARGS__)
//Custom file-line location logging macros
#define VTR_LOGF(file, line, ...) VTR_LOGVF(true, file, line, __VA_ARGS__)
#define VTR_LOGF_WARN(file, line, ...) VTR_LOGVF_WARN(true, file, line, __VA_ARGS__)
#define VTR_LOGF_ERROR(file, line, ...) VTR_LOGVF_ERROR(true, file, line, __VA_ARGS__)
#define VTR_LOGF_NOP(file, line, ...) VTR_LOGVF_NOP(true, file, line, __VA_ARGS__)
//Custom file-line-func location logging macros
#define VTR_LOGFF_WARN(file, line, func, ...) VTR_LOGVFF_WARN(true, file, line, func, __VA_ARGS__)
//Conditional logging and custom file-line location macros
#define VTR_LOGVF(expr, file, line, ...) \
do { \
if (expr) vtr::printf(__VA_ARGS__); \
} while (false)
#define VTR_LOGVF_WARN(expr, file, line, ...) \
do { \
if (expr) print_or_suppress_warning(file, line, __func__, __VA_ARGS__); \
} while (false)
#define VTR_LOGVF_ERROR(expr, file, line, ...) \
do { \
if (expr) vtr::printf_error(file, line, __VA_ARGS__); \
} while (false)
// Conditional logging and custom file-line-func location macros
#define VTR_LOGVFF_WARN(expr, file, line, func, ...) \
do { \
if (expr) print_or_suppress_warning(file, line, func, __VA_ARGS__); \
} while (false)
//No-op version of logging macro which avoids unused parameter warnings.
//
//Note that to avoid unused parameter warnings we call sizeof() and cast
//the result to void. sizeof is evaluated at compile time so there is no
//run-time overhead.
//
//Also note the use of std::make_tuple to ensure all arguments in VA_ARGS
//are used.
#define VTR_LOGVF_NOP(expr, file, line, ...) \
do { \
static_cast<void>(sizeof(expr)); \
static_cast<void>(sizeof(file)); \
static_cast<void>(sizeof(line)); \
static_cast<void>(sizeof(std::make_tuple(__VA_ARGS__))); \
} while (false)
//Debug logging macros
#ifdef VTR_ENABLE_DEBUG_LOGGING //Enable
# define VTR_LOG_DEBUG(...) VTR_LOG(__VA_ARGS__)
# define VTR_LOGV_DEBUG(expr, ...) VTR_LOGV(expr, __VA_ARGS__)
#else //Disable
# define VTR_LOG_DEBUG(...) VTR_LOG_NOP(__VA_ARGS__)
# define VTR_LOGV_DEBUG(expr, ...) VTR_LOGV_NOP(expr, __VA_ARGS__)
#endif
namespace vtr {
typedef void (*PrintHandlerInfo)(const char* pszMessage, ...);
typedef void (*PrintHandlerWarning)(const char* pszFileName, unsigned int lineNum, const char* pszMessage, ...);
typedef void (*PrintHandlerError)(const char* pszFileName, unsigned int lineNum, const char* pszMessage, ...);
typedef void (*PrintHandlerDirect)(const char* pszMessage, ...);
extern PrintHandlerInfo printf; //Same as printf_info
extern PrintHandlerInfo printf_info;
extern PrintHandlerWarning printf_warning;
extern PrintHandlerError printf_error;
extern PrintHandlerDirect printf_direct;
void set_log_file(const char* filename);
} // namespace vtr
// The following data structure and functions allow to suppress noisy warnings
// and direct them into an external file, if specified.
static std::unordered_set<std::string> warnings_to_suppress;
static std::string noisy_warn_log_file;
void add_warnings_to_suppress(std::string function_name);
// This function creates a new log file to hold the suppressed warnings.
// If the file already exists, it is cleared out first.
void set_noisy_warn_log_file(std::string log_file_name);
// This function checks whether the function from which the warning has been called
// is in the set of warnings_to_suppress. If so, the warning is printed on the
// noisy_warn_log_file, otherwise it is printed on stdout (or the regular log file)
void print_or_suppress_warning(const char* pszFileName, unsigned int lineNum, const char* pszFuncName, const char* pszMessage, ...);
#endif