+/* ========================================================================= */
+
+/* ------------------------------------------------------------------------- */
+/* logging functions */
+/* ------------------------------------------------------------------------- */
+
+#define DUPLICATE_LOG_OUT_TO_STDOUT TRUE
+#define DUPLICATE_LOG_ERR_TO_STDERR TRUE
+
+
+#if defined(PLATFORM_ANDROID)
+static int android_log_prio = ANDROID_LOG_INFO;
+static char *android_log_buffer = NULL;
+
+static void append_to_android_log_buffer(char *format, va_list ap)
+{
+ char text_new[MAX_OUTPUT_LINESIZE];
+
+ // print text to temporary string
+ vsnprintf(text_new, MAX_OUTPUT_LINESIZE, format, ap);
+
+ if (android_log_buffer == NULL)
+ {
+ android_log_buffer = getStringCopy(text_new);
+ }
+ else
+ {
+ char *android_log_buffer_old = android_log_buffer;
+
+ // append new text to existing text
+ android_log_buffer = getStringCat2(android_log_buffer, text_new);
+
+ checked_free(android_log_buffer_old);
+ }
+}
+
+static void vprintf_log_nonewline(char *format, va_list ap)
+{
+ // add log output to buffer until text with newline is printed
+ append_to_android_log_buffer(format, ap);
+}
+
+static void vprintf_log(char *format, va_list ap)
+{
+ // add log output to buffer
+ append_to_android_log_buffer(format, ap);
+
+ // __android_log_vprint(android_log_prio, program.program_title, format, ap);
+ __android_log_write(android_log_prio, program.program_title,
+ android_log_buffer);
+
+ checked_free(android_log_buffer);
+ android_log_buffer = NULL;
+}
+
+#else
+
+static void vprintf_log_nonewline(char *format, va_list ap)
+{
+ FILE *file = program.log_file[LOG_ERR_ID];
+
+#if DUPLICATE_LOG_ERR_TO_STDERR
+ if (file != program.log_file_default[LOG_ERR_ID])
+ {
+ va_list ap2;
+ va_copy(ap2, ap);
+
+ vfprintf(program.log_file_default[LOG_ERR_ID], format, ap2);
+
+ va_end(ap2);
+ }
+#endif
+
+ vfprintf(file, format, ap);
+}
+
+static void vprintf_log(char *format, va_list ap)
+{
+ FILE *file = program.log_file[LOG_ERR_ID];
+ char *newline = STRING_NEWLINE;
+
+#if DUPLICATE_LOG_ERR_TO_STDERR
+ if (file != program.log_file_default[LOG_ERR_ID])
+ {
+ va_list ap2;
+ va_copy(ap2, ap);
+
+ vfprintf(program.log_file_default[LOG_ERR_ID], format, ap2);
+ fprintf(program.log_file_default[LOG_ERR_ID], "%s", newline);
+
+ va_end(ap2);
+ }
+#endif
+
+ vfprintf(file, format, ap);
+ fprintf(file, "%s", newline);
+}
+#endif
+
+static void printf_log_nonewline(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vprintf_log_nonewline(format, ap);
+ va_end(ap);
+}
+
+static void printf_log(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vprintf_log(format, ap);
+ va_end(ap);
+}
+
+static void printf_log_line(char *line_chars, int line_length)
+{
+ int i;
+
+ for (i = 0; i < line_length; i++)
+ printf_log_nonewline("%s", line_chars);
+
+ printf_log("");
+}
+
+