| #ifndef LOG_H |
| #define LOG_H |
| |
| #include <stdint.h> |
| #include <stddef.h> |
| |
| #ifndef LOGMODULE |
| #error "LOGMODULE must be set before including log/log.h" |
| #endif |
| |
| #ifndef LOGDEFAULT |
| #define LOGDEFAULT LOGLEVEL_WARNING |
| #endif |
| |
| #if defined (__GNUC__) |
| #define COMPILER_ATTR(...) __attribute__((__VA_ARGS__)) |
| #else |
| #define COMPILER_ATTR(...) |
| #endif |
| |
| typedef enum { |
| LOGLEVEL_NONE = 0, |
| LOGLEVEL_ERROR = 1, |
| LOGLEVEL_WARNING = 2, |
| LOGLEVEL_INFO = 3, |
| LOGLEVEL_DEBUG = 4, |
| LOGLEVEL_TRACE = 5, |
| LOGLEVEL_UNDEFINED = 0xff |
| } log_level; |
| |
| static const char *log_strings[] COMPILER_ATTR(unused) = { |
| "none", |
| "ERROR", |
| "WARNING", |
| "info", |
| "debug", |
| "trace" |
| }; |
| |
| #define xstr(s) str(s) |
| #define str(s) #s |
| |
| static log_level LOGMODULE_status COMPILER_ATTR(unused) = LOGLEVEL_UNDEFINED; |
| |
| #ifndef MAXLOGLEVEL |
| #error "MAXLOGLEVEL undefined" |
| #endif |
| #if MAXLOGLEVEL != 'E' && \ |
| MAXLOGLEVEL != 'W' && \ |
| MAXLOGLEVEL != 'I' && \ |
| MAXLOGLEVEL != 'D' && \ |
| MAXLOGLEVEL != 'T' && \ |
| MAXLOGLEVEL != 'N' |
| #error "Unknown MAXLOGLEVEL" |
| #endif |
| |
| /* MAXLOGLEVEL is Error or "higher" */ |
| #if MAXLOGLEVEL == 'E' || \ |
| MAXLOGLEVEL == 'W' || \ |
| MAXLOGLEVEL == 'I' || \ |
| MAXLOGLEVEL == 'D' || \ |
| MAXLOGLEVEL == 'T' |
| #define LOG_ERROR(FORMAT, ...) doLog(LOGLEVEL_ERROR, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| FORMAT, ## __VA_ARGS__) |
| #define LOGBLOB_ERROR(BUFFER, SIZE, FORMAT, ...) doLogBlob(LOGLEVEL_ERROR, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| BUFFER, SIZE, \ |
| FORMAT, ## __VA_ARGS__) |
| #else /* MAXLOGLEVEL is not Error or "higher" */ |
| #define LOG_ERROR(FORMAT, ...) {} |
| #define LOGBLOB_ERROR(FORMAT, ...) {} |
| #endif |
| |
| /* MAXLOGLEVEL is Warning or "higher" */ |
| #if MAXLOGLEVEL == 'W' || \ |
| MAXLOGLEVEL == 'I' || \ |
| MAXLOGLEVEL == 'D' || \ |
| MAXLOGLEVEL == 'T' |
| #define LOG_WARNING(FORMAT, ...) doLog(LOGLEVEL_WARNING, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| FORMAT, ## __VA_ARGS__) |
| #define LOGBLOB_WARNING(BUFFER, SIZE, FORMAT, ...) doLogBlob(LOGLEVEL_WARNING, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| BUFFER, SIZE, \ |
| FORMAT, ## __VA_ARGS__) |
| #else /* MAXLOGLEVEL is not Warning or "higher" */ |
| #define LOG_WARNING(FORMAT, ...) {} |
| #define LOGBLOB_WARNING(FORMAT, ...) {} |
| #endif |
| |
| /* MAXLOGLEVEL is Info or "higher" */ |
| #if MAXLOGLEVEL == 'I' || \ |
| MAXLOGLEVEL == 'D' || \ |
| MAXLOGLEVEL == 'T' |
| #define LOG_INFO(FORMAT, ...) doLog(LOGLEVEL_INFO, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| FORMAT, ## __VA_ARGS__) |
| #define LOGBLOB_INFO(BUFFER, SIZE, FORMAT, ...) doLogBlob(LOGLEVEL_INFO, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| BUFFER, SIZE, \ |
| FORMAT, ## __VA_ARGS__) |
| #else /* MAXLOGLEVEL is not Info or "higher" */ |
| #define LOG_INFO(FORMAT, ...) {} |
| #define LOGBLOB_INFO(FORMAT, ...) {} |
| #endif |
| |
| /* MAXLOGLEVEL is Debug or "higher" */ |
| #if MAXLOGLEVEL == 'D' || \ |
| MAXLOGLEVEL == 'T' |
| #define LOG_DEBUG(FORMAT, ...) doLog(LOGLEVEL_DEBUG, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| FORMAT, ## __VA_ARGS__) |
| #define LOGBLOB_DEBUG(BUFFER, SIZE, FORMAT, ...) doLogBlob(LOGLEVEL_DEBUG, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| BUFFER, SIZE, \ |
| FORMAT, ## __VA_ARGS__) |
| #else /* MAXLOGLEVEL is not Debug or "higher" */ |
| #define LOG_DEBUG(FORMAT, ...) {} |
| #define LOGBLOB_DEBUG(FORMAT, ...) {} |
| #endif |
| |
| /* MAXLOGLEVEL is Trace */ |
| #if MAXLOGLEVEL == 'T' |
| #define LOG_TRACE(FORMAT, ...) doLog(LOGLEVEL_TRACE, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| FORMAT, ## __VA_ARGS__) |
| #define LOGBLOB_TRACE(BUFFER, SIZE, FORMAT, ...) doLogBlob(LOGLEVEL_TRACE, \ |
| xstr(LOGMODULE), LOGDEFAULT, \ |
| &LOGMODULE_status, \ |
| __FILE__, __func__, __LINE__, \ |
| BUFFER, SIZE, \ |
| FORMAT, ## __VA_ARGS__) |
| #else /* MAXLOGLEVEL is not Trace */ |
| #define LOG_TRACE(FORMAT, ...) {} |
| #define LOGBLOB_TRACE(FORMAT, ...) {} |
| #endif |
| |
| void |
| doLog(log_level loglevel, const char *module, log_level logdefault, |
| log_level *status, |
| const char *file, const char *func, int line, |
| const char *msg, ...) |
| COMPILER_ATTR(unused, format (printf, 8, 9)); |
| |
| void |
| doLogBlob(log_level loglevel, const char *module, log_level logdefault, |
| log_level *status, |
| const char *file, const char *func, int line, |
| const uint8_t *buffer, size_t size, const char *msg, ...) |
| COMPILER_ATTR(unused, format (printf, 10, 11)); |
| |
| #if defined(_MSC_VER) |
| inline char* |
| index (const char *s, |
| int c) |
| { |
| return strchr(s, c); |
| } |
| |
| #define _CRT_DECLARE_NONSTDC_NAMES 1 |
| #include <string.h> |
| inline int |
| strncasecmp (const char *s1, |
| const char *s2, |
| size_t len) |
| { |
| return _strnicmp(s1, s2, len); |
| } |
| #endif /* _MSC_VER */ |
| #endif /* LOG_H */ |