diff --git a/common/log.c b/common/log.c index 2cc7289c5..bf1246bba 100644 --- a/common/log.c +++ b/common/log.c @@ -1,14 +1,20 @@ +#define _POSIX_C_SOURCE 199506L #include #include +#include #include +#include +#include #include "log.h" void sway_terminate(int code); + + void _sway_abort(const char *format, ...) { va_list args; va_start(args, format); - _wlr_vlog(L_ERROR, format, args); + _sway_vlog(L_ERROR, format, args); va_end(args); sway_terminate(EXIT_FAILURE); } @@ -20,7 +26,7 @@ bool _sway_assert(bool condition, const char *format, ...) { va_list args; va_start(args, format); - _wlr_vlog(L_ERROR, format, args); + _sway_vlog(L_ERROR, format, args); va_end(args); #ifndef NDEBUG @@ -29,3 +35,81 @@ bool _sway_assert(bool condition, const char *format, ...) { return false; } + +static bool colored = true; +static log_importance_t log_importance = L_ERROR; + +static const char *verbosity_colors[] = { + [L_SILENT] = "", + [L_ERROR ] = "\x1B[1;31m", + [L_INFO ] = "\x1B[1;34m", + [L_DEBUG ] = "\x1B[1;30m", +}; + +static void log_stderr(log_importance_t verbosity, const char *fmt, + va_list args) { + if (verbosity > log_importance) { + return; + } + // prefix the time to the log message + struct tm result; + time_t t = time(NULL); + struct tm *tm_info = localtime_r(&t, &result); + char buffer[26]; + + // generate time prefix + strftime(buffer, sizeof(buffer), "%F %T - ", tm_info); + fprintf(stderr, "%s", buffer); + + unsigned c = (verbosity < L_LAST) ? verbosity : L_LAST - 1; + + if (colored && isatty(STDERR_FILENO)) { + fprintf(stderr, "%s", verbosity_colors[c]); + } + + vfprintf(stderr, fmt, args); + + if (colored && isatty(STDERR_FILENO)) { + fprintf(stderr, "\x1B[0m"); + } + fprintf(stderr, "\n"); +} + +static log_callback_t log_callback = log_stderr; + +void sway_log_init(log_importance_t verbosity, log_callback_t callback) { + if (verbosity < L_LAST) { + log_importance = verbosity; + } + if (callback) { + log_callback = callback; + } +} + +void _sway_vlog(log_importance_t verbosity, const char *fmt, va_list args) { + log_callback(verbosity, fmt, args); +} + +void _sway_log(log_importance_t verbosity, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + log_callback(verbosity, fmt, args); + va_end(args); +} + +// strips the path prefix from filepath +// will try to strip SWAY_SRC_DIR as well as a relative src dir +// e.g. '/src/build/sway/util/log.c' and +// '../util/log.c' will both be stripped to +// 'util/log.c' +const char *sway_strip_path(const char *filepath) { + static int srclen = sizeof(SWAY_SRC_DIR); + if (strstr(filepath, SWAY_SRC_DIR) == filepath) { + filepath += srclen; + } else if (*filepath == '.') { + while (*filepath == '.' || *filepath == '/') { + ++filepath; + } + } + return filepath; +} diff --git a/include/log.h b/include/log.h index a97481274..2599c9aa2 100644 --- a/include/log.h +++ b/include/log.h @@ -1,16 +1,39 @@ #ifndef _SWAY_LOG_H #define _SWAY_LOG_H -#include + #include +#include +#include +#include +#include void _sway_abort(const char *filename, ...) ATTRIB_PRINTF(1, 2); #define sway_abort(FMT, ...) \ - _sway_abort("[%s:%d] " FMT, wlr_strip_path(__FILE__), __LINE__, ##__VA_ARGS__) + _sway_abort("[%s:%d] " FMT, sway_strip_path(__FILE__), __LINE__, ##__VA_ARGS__) bool _sway_assert(bool condition, const char* format, ...) ATTRIB_PRINTF(2, 3); #define sway_assert(COND, FMT, ...) \ - _sway_assert(COND, "[%s:%d] %s:" FMT, wlr_strip_path(__FILE__), __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) + _sway_assert(COND, "[%s:%d] %s:" FMT, sway_strip_path(__FILE__), __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) void error_handler(int sig); +typedef void (*log_callback_t)(log_importance_t importance, const char *fmt, va_list args); + +// Will log all messages less than or equal to `verbosity` +// If `callback` is NULL, sway will use its default logger. +void sway_log_init(log_importance_t verbosity, log_callback_t callback); + +void _sway_log(log_importance_t verbosity, const char *format, ...) ATTRIB_PRINTF(2, 3); +void _sway_vlog(log_importance_t verbosity, const char *format, va_list args) ATTRIB_PRINTF(2, 0); +const char *sway_strip_path(const char *filepath); + +#define sway_log(verb, fmt, ...) \ + _sway_log(verb, "[%s:%d] " fmt, sway_strip_path(__FILE__), __LINE__, ##__VA_ARGS__) + +#define sway_vlog(verb, fmt, args) \ + _sway_vlog(verb, "[%s:%d] " fmt, sway_strip_path(__FILE__), __LINE__, args) + +#define sway_log_errno(verb, fmt, ...) \ + sway_log(verb, fmt ": %s", ##__VA_ARGS__, strerror(errno)) + #endif diff --git a/meson.build b/meson.build index d4ee1a118..890c1787f 100644 --- a/meson.build +++ b/meson.build @@ -12,6 +12,7 @@ project( add_project_arguments('-Wno-unused-parameter', language: 'c') add_project_arguments('-Wno-unused-function', language: 'c') add_project_arguments('-Wno-unused-result', language: 'c') +add_project_arguments('-DSWAY_SRC_DIR="@0@"'.format(meson.source_root()), language: 'c') cc = meson.get_compiler('c')