+ if (last_line_was_separator && strEqual(mode, mode_last))
+ return;
+
+ printf_log_prefix(log_level, mode);
+ printf_log_line(line_char, line_length);
+
+ if (!strEqual(mode, mode_last))
+ setString(&mode_last, mode);
+
+ last_line_was_separator = TRUE;
+
+ return;
+ }
+
+ last_line_was_separator = FALSE;
+
+ printf_log_prefix(log_level, mode);
+
+ vprintf_log(format, ap);
+}
+
+static void Log(int log_level, char *mode, char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vLog(log_level, mode, format, ap);
+ va_end(ap);
+}
+
+void DebugContinued(char *mode, char *format, ...)
+{
+ static char message[MAX_LINE_LEN] = { 0 };
+
+ // initialize message (optional)
+ if (strEqual(format, ""))
+ {
+ message[0] = '\0';
+
+ return;
+ }
+
+ char *message_ptr = message + strlen(message);
+ int size_left = MAX_LINE_LEN - strlen(message);
+ va_list ap;
+
+ // append message
+ va_start(ap, format);
+ vsnprintf(message_ptr, size_left, format, ap);
+ va_end(ap);
+
+ // finalize message
+ if (strSuffix(format, "\n"))
+ {
+ message[strlen(message) - 1] = '\0';
+
+ Debug(mode, message);
+
+ message[0] = '\0';
+ }
+}
+
+void Debug(char *mode, char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vLog(LOG_DEBUG, mode, format, ap);
+ va_end(ap);
+}
+
+void Info(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vLog(LOG_INFO, NULL, format, ap);
+ va_end(ap);
+}
+
+void Warn(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vLog(LOG_WARN, NULL, format, ap);
+ va_end(ap);
+}
+
+void Error(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vLog(LOG_ERROR, NULL, format, ap);
+ va_end(ap);
+}
+
+void Fail(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vLog(LOG_FATAL, NULL, format, ap);
+ va_end(ap);
+
+ if (!network.is_server_thread)
+ {
+ va_start(ap, format);
+ program.exit_message_function(format, ap);
+ va_end(ap);
+ }
+
+ Log(LOG_FATAL, NULL, "aborting");
+
+ // network server thread: normal exit
+ if (network.is_server_thread)
+ exit(1);
+
+ // main process: clean up stuff
+ program.exit_function(1);
+}
+
+void FailWithHelp(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vLog(LOG_FATAL, NULL, format, ap);
+ va_end(ap);
+
+ Log(LOG_FATAL, NULL, "try option '--help' for more information");
+ Log(LOG_FATAL, NULL, "aborting");
+
+ // main process: clean up stuff
+ program.exit_function(1);
+}
+
+
+// ----------------------------------------------------------------------------
+// string functions
+// ----------------------------------------------------------------------------