taisei/src/log.h

141 lines
3.6 KiB
C
Raw Normal View History

2017-09-12 03:28:15 +02:00
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@alienslab.net>.
2017-09-12 03:28:15 +02:00
*/
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
#ifndef IGUARD_log_h
#define IGUARD_log_h
#include "taisei.h"
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
#include <SDL.h>
enum {
_LOG_DEBUG_ID,
_LOG_INFO_ID,
_LOG_WARN_ID,
_LOG_ERROR_ID,
_LOG_FATAL_ID,
};
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
typedef enum LogLevel {
LOG_NONE = 0,
LOG_DEBUG = (1 << _LOG_DEBUG_ID),
LOG_INFO = (1 << _LOG_INFO_ID),
LOG_WARN = (1 << _LOG_WARN_ID),
LOG_ERROR = (1 << _LOG_ERROR_ID),
LOG_FATAL = (1 << _LOG_FATAL_ID),
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
LOG_SPAM = LOG_DEBUG | LOG_INFO,
LOG_ALERT = LOG_WARN | LOG_ERROR | LOG_FATAL,
LOG_ALL = LOG_SPAM | LOG_ALERT,
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
} LogLevel;
#ifndef LOG_DEFAULT_LEVELS
#define LOG_DEFAULT_LEVELS LOG_ALL
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
#endif
#ifndef LOG_DEFAULT_LEVELS_FILE
#ifdef __EMSCRIPTEN__
#define LOG_DEFAULT_LEVELS_FILE LOG_NONE
2019-02-28 20:56:16 +01:00
#else
#define LOG_DEFAULT_LEVELS_FILE LOG_ALL
#endif
#endif
#ifndef LOG_DEFAULT_LEVELS_CONSOLE
#ifdef DEBUG
#define LOG_DEFAULT_LEVELS_CONSOLE LOG_ALL
Emscripten compatibility (#161) * Major refactoring of the main loop(s) and control flow (WIP) run_at_fps() is gone 🦀 Instead of nested blocking event loops, there is now an eventloop API that manages an explicit stack of scenes. This makes Taisei a lot more portable to async environments where spinning a loop forever without yielding control simply is not an option, and that is the entire point of this change. A prime example of such an environment is the Web (via emscripten). Taisei was able to run there through a terrible hack: inserting emscripten_sleep calls into the loop, which would yield to the browser. This has several major drawbacks: first of all, every function that could possibly call emscripten_sleep must be compiled into a special kind of bytecode, which then has to be interpreted at runtime, *much* slower than JITed WebAssembly. And that includes *everything* down the call stack, too! For more information, see https://emscripten.org/docs/porting/emterpreter.html Even though that method worked well enough for experimenting, despite suboptimal performance, there is another obvious drawback: emscripten_sleep is implemented via setTimeout(), which can be very imprecise and is generally not reliable for fluid animation. Browsers actually have an API specifically for that use case: window.requestAnimationFrame(), but Taisei's original blocking control flow style is simply not compatible with it. Emscripten exposes this API with its emscripten_set_main_loop(), which the eventloop backend now uses on that platform. Unfortunately, C is still C, with no fancy closures or coroutines. With blocking calls into menu/scene loops gone, the control flow is reimplemented via so-called (pun intended) "call chains". That is basically an euphemism for callback hell. With manual memory management and zero type-safety. Not that the menu system wasn't shitty enough already. I'll just keep telling myself that this is all temporary and will be replaced with scripts in v1.4. * improve build system for emscripten + various fixes * squish menu bugs * improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS Note that stock freetype does not work without EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the "emscripten" branch here: https://github.com/taisei-project/freetype2/tree/emscripten * Enable -Wcast-function-type Calling functions through incompatible pointers is nasal demons and doesn't work in WASM. * webgl: workaround a crash on some browsers * emscripten improvements: * Persist state (config, progress, replays, ...) in local IndexDB * Simpler HTML shell (temporary) * Enable more optimizations * fix build if validate_glsl=false * emscripten: improve asset packaging, with local cache Note that even though there are rules to build audio bundles, audio does *not* work yet. It looks like SDL2_mixer can not work without threads, which is a problem. Yet another reason to write an OpenAL backend - emscripten supports that natively. * emscripten: customize the html shell * emscripten: force "show log" checkbox unchecked initially * emscripten: remove quit shortcut from main menu (since there's no quit) * emscripten: log area fixes * emscripten/webgl: workaround for fullscreen viewport issue * emscripten: implement frameskip * emscripter: improve framerate limiter * align List to at least 8 bytes (shut up warnings) * fix non-emscripten builds * improve fullscreen handling, mainly for emscripten * Workaround to make audio work in chromium emscripten-core/emscripten#6511 * emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
#elif defined __EMSCRIPTEN__
#define LOG_DEFAULT_LEVELS_CONSOLE LOG_ALERT | LOG_INFO
#else
#define LOG_DEFAULT_LEVELS_CONSOLE LOG_ALERT
#endif
#endif
#ifndef LOG_DEFAULT_LEVELS_STDOUT
#ifdef __EMSCRIPTEN__
#define LOG_DEFAULT_LEVELS_STDOUT LOG_ALL
#else
#define LOG_DEFAULT_LEVELS_STDOUT LOG_SPAM
#endif
#endif
#ifndef LOG_DEFAULT_LEVELS_STDERR
#ifdef __EMSCRIPTEN__
#define LOG_DEFAULT_LEVELS_STDERR LOG_NONE
#else
#define LOG_DEFAULT_LEVELS_STDERR LOG_ALERT
#endif
#endif
typedef struct LogEntry {
const char *message;
const char *file;
const char *func;
uint time;
uint line;
LogLevel level;
} LogEntry;
typedef struct FormatterObj FormatterObj;
struct FormatterObj {
int (*format)(FormatterObj *self, char *buf, size_t buf_size, LogEntry *entry);
void (*free)(FormatterObj *self);
void *data;
};
// "constructor". initializer, actually.
typedef void Formatter(FormatterObj *obj, const SDL_RWops *output);
extern Formatter log_formatter_file;
extern Formatter log_formatter_console;
void log_init(LogLevel lvls);
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
void log_shutdown(void);
void log_add_output(LogLevel levels, SDL_RWops *output, Formatter *formatter) attr_nonnull(3);
void log_backtrace(LogLevel lvl);
LogLevel log_parse_levels(LogLevel lvls, const char *lvlmod) attr_nodiscard;
bool log_initialized(void) attr_nodiscard;
void log_set_gui_error_appendix(const char *message);
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
#if defined(DEBUG) && !defined(__EMSCRIPTEN__)
#define log_debug(...) log_custom(LOG_DEBUG, __VA_ARGS__)
#undef UNREACHABLE
#define UNREACHABLE log_fatal("This code should never be reached")
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
#else
#define log_debug(...)
#define LOG_NO_FILENAMES
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
#endif
#ifdef LOG_NO_FILENAMES
#define _do_log(func, lvl, ...) (func)(lvl, __func__, "<unknown>", 0, __VA_ARGS__)
#else
#define _do_log(func, lvl, ...) (func)(lvl, __func__, __FILE__, __LINE__, __VA_ARGS__)
#endif
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
#define log_custom(lvl, ...) _do_log(_taisei_log, lvl, __VA_ARGS__)
#define log_info(...) log_custom(LOG_INFO, __VA_ARGS__)
#define log_warn(...) log_custom(LOG_WARN, __VA_ARGS__)
#define log_error(...) log_custom(LOG_ERROR, __VA_ARGS__)
#define log_fatal(...) _do_log(_taisei_log_fatal, LOG_FATAL, __VA_ARGS__)
#define log_sdl_error(lvl, funcname) log_custom(lvl, "%s() failed: %s", funcname, SDL_GetError())
Implemented a simple and consistent logging subsystem The goal of this change is mainly to clean up Taisei's codebase and improve its console output. I've been frustrated by files littered with inconsistent printf/fprintf/warnx/errx calls for a long time, and now I actually did something about it. All the above functions are now considered deprecated and result in a compile-time warning when used. Instead, the following macros should be used: log_debug(format, ...) log_info(format, ...) log_warn(format, ...) log_err(format, ...) As you can see, all of them have the same printf-like interface. But they have different functionality and purpose: log_debug is intended for very verbose and specific information. It does nothing in release builds, much like assert(), so don't use expressions with side-effects in its arguments. log_info is for various status updates that are expected during normal operation of the program. log_warn is for non-critical failures or other things that may be worth investigating, but don't inherently render the program non-functional. log_err is for when the only choice is to give up. Like errx, it also terminates the program. Unlike errx, it actually calls abort(), which means the cleanup functions are not ran -- but on the other hand, you get a debuggable backtrace. However, if you're trying to catch programming errors, consider using assert() instead. All of them produce output that contains a timestamp, the log level identifier, the calling function's name, and the formatted message. The newline at the end of the format string is not required -- no, it is actually *prohibited*. The logging system will take care of the line breaks by itself, don't litter the code with that shit. Internally, the logging system is based on the SDL_RWops abstraction, and may have multiple, configurable destinations. This makes it easily extensible. Currently, log_debug and log_info are set to write to stdout, log_warn and log_err to stderr, and all of them also to the file log.txt in the Taisei config directory. Consequently, the nasty freopen hacks we used to make Taisei write to log files on Windows are no longer needed -- which is a very good thing, considering they probably would break if the configdir path contains UTF-8 characters. SDL_RWFromFile does not suffer this limitation. As an added bonus, it's also thread-safe. Note about printf and fprintf: in very few cases, the logging system is not a good substitute for these functions. That is, when you care about writing exactly to stdout/stderr and about exactly how the output looks. However, I insist on keeping the deprecation warnings on them to not tempt anyone to use them for logging/debugging out of habit and/or laziness. For this reason, I've added a tsfprintf function to util.c. It is functionally identical to fprintf, except it returns void. Yes, the name is deliberately ugly. Avoid using it if possible, but if you must, only use it to write to stdout or stderr. Do not write to actual files with it, use SDL_RWops.
2017-03-13 03:51:58 +01:00
//
// don't call these directly, use the macros
//
void _taisei_log(LogLevel lvl, const char *funcname, const char *filename, uint line, const char *fmt, ...)
attr_printf(5, 6);
noreturn void _taisei_log_fatal(LogLevel lvl, const char *funcname, const char *filename, uint line, const char *fmt, ...)
attr_printf(5, 6);
#endif // IGUARD_log_h