1 /* 2 * This software is licensed under the terms of the MIT License. 3 * See COPYING for further information. 4 * --- 5 * Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>. 6 * Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>. 7 */ 8 9 #ifndef IGUARD_log_h 10 #define IGUARD_log_h 11 12 #include "taisei.h" 13 14 #include <SDL.h> 15 16 enum { 17 _LOG_DEBUG_ID, 18 _LOG_INFO_ID, 19 _LOG_WARN_ID, 20 _LOG_ERROR_ID, 21 _LOG_FATAL_ID, 22 23 _LOG_NOABORT_BIT, 24 }; 25 26 typedef enum LogLevel { 27 LOG_NONE = 0, 28 LOG_DEBUG = (1 << _LOG_DEBUG_ID), 29 LOG_INFO = (1 << _LOG_INFO_ID), 30 LOG_WARN = (1 << _LOG_WARN_ID), 31 LOG_ERROR = (1 << _LOG_ERROR_ID), 32 LOG_FATAL = (1 << _LOG_FATAL_ID), 33 34 LOG_SPAM = LOG_DEBUG | LOG_INFO, 35 LOG_ALERT = LOG_WARN | LOG_ERROR | LOG_FATAL, 36 37 LOG_ALL = LOG_SPAM | LOG_ALERT, 38 39 LOG_NOABORT_BIT = (1 << _LOG_NOABORT_BIT), 40 41 LOG_FAKEFATAL = LOG_FATAL | LOG_NOABORT_BIT, 42 } LogLevel; 43 44 #ifndef LOG_DEFAULT_LEVELS 45 #define LOG_DEFAULT_LEVELS LOG_ALL 46 #endif 47 48 #ifndef LOG_DEFAULT_LEVELS_FILE 49 #ifdef __EMSCRIPTEN__ 50 #define LOG_DEFAULT_LEVELS_FILE LOG_NONE 51 #else 52 #define LOG_DEFAULT_LEVELS_FILE LOG_ALL 53 #endif 54 #endif 55 56 #ifndef LOG_DEFAULT_LEVELS_CONSOLE 57 #ifdef DEBUG 58 #define LOG_DEFAULT_LEVELS_CONSOLE LOG_ALL 59 #elif defined __EMSCRIPTEN__ 60 #define LOG_DEFAULT_LEVELS_CONSOLE LOG_ALERT | LOG_INFO 61 #else 62 #define LOG_DEFAULT_LEVELS_CONSOLE LOG_ALERT 63 #endif 64 #endif 65 66 #ifndef LOG_DEFAULT_LEVELS_STDOUT 67 #ifdef __EMSCRIPTEN__ 68 #define LOG_DEFAULT_LEVELS_STDOUT LOG_ALL 69 #else 70 #define LOG_DEFAULT_LEVELS_STDOUT LOG_SPAM 71 #endif 72 #endif 73 74 #ifndef LOG_DEFAULT_LEVELS_STDERR 75 #ifdef __EMSCRIPTEN__ 76 #define LOG_DEFAULT_LEVELS_STDERR LOG_NONE 77 #else 78 #define LOG_DEFAULT_LEVELS_STDERR LOG_ALERT 79 #endif 80 #endif 81 82 typedef struct LogEntry { 83 const char *message; 84 const char *file; 85 const char *func; 86 uint time; 87 uint line; 88 LogLevel level; 89 } LogEntry; 90 91 typedef struct FormatterObj FormatterObj; 92 93 struct FormatterObj { 94 int (*format)(FormatterObj *self, char *buf, size_t buf_size, LogEntry *entry); 95 void (*free)(FormatterObj *self); 96 void *data; 97 }; 98 99 // "constructor". initializer, actually. 100 typedef void Formatter(FormatterObj *obj, const SDL_RWops *output); 101 102 extern Formatter log_formatter_file; 103 extern Formatter log_formatter_console; 104 105 void log_init(LogLevel lvls); 106 void log_shutdown(void); 107 void log_add_output(LogLevel levels, SDL_RWops *output, Formatter *formatter) attr_nonnull(3); 108 void log_backtrace(LogLevel lvl); 109 LogLevel log_parse_levels(LogLevel lvls, const char *lvlmod) attr_nodiscard; 110 bool log_initialized(void) attr_nodiscard; 111 void log_set_gui_error_appendix(const char *message); 112 113 #if defined(DEBUG) && !defined(__EMSCRIPTEN__) 114 #define log_debug(...) log_custom(LOG_DEBUG, __VA_ARGS__) 115 #undef UNREACHABLE 116 #define UNREACHABLE log_fatal("This code should never be reached") 117 #else 118 #define log_debug(...) 119 #define LOG_NO_FILENAMES 120 #endif 121 122 #ifdef LOG_NO_FILENAMES 123 #define _do_log(func, lvl, ...) (func)(lvl, __func__, "<unknown>", 0, __VA_ARGS__) 124 #else 125 #define _do_log(func, lvl, ...) (func)(lvl, __func__, __FILE__, __LINE__, __VA_ARGS__) 126 #endif 127 128 #define log_custom(lvl, ...) _do_log(_taisei_log, lvl, __VA_ARGS__) 129 #define log_info(...) log_custom(LOG_INFO, __VA_ARGS__) 130 #define log_warn(...) log_custom(LOG_WARN, __VA_ARGS__) 131 #define log_error(...) log_custom(LOG_ERROR, __VA_ARGS__) 132 #define log_fatal(...) _do_log(_taisei_log_fatal, LOG_FATAL, __VA_ARGS__) 133 134 #define log_sdl_error(lvl, funcname) log_custom(lvl, "%s() failed: %s", funcname, SDL_GetError()) 135 136 // 137 // don't call these directly, use the macros 138 // 139 140 void _taisei_log(LogLevel lvl, const char *funcname, const char *filename, uint line, const char *fmt, ...) 141 attr_printf(5, 6); 142 143 noreturn void _taisei_log_fatal(LogLevel lvl, const char *funcname, const char *filename, uint line, const char *fmt, ...) 144 attr_printf(5, 6); 145 146 #endif // IGUARD_log_h 147