|
#include <stdarg.h> |
|
#include <string.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#ifdef _WIN32 |
|
#include <windows.h> |
|
#else |
|
#include <unistd.h> |
|
#endif |
|
#ifdef __ANDROID__ |
|
#include <android/log.h> |
|
#endif |
|
#ifdef __hexagon__ |
|
#include <qurt_printf.h> |
|
#endif |
|
|
|
#ifndef CLOG_LOG_TO_STDIO |
|
#ifdef __ANDROID__ |
|
#define CLOG_LOG_TO_STDIO 0 |
|
#else |
|
#define CLOG_LOG_TO_STDIO 1 |
|
#endif |
|
#endif |
|
|
|
#include <clog.h> |
|
|
|
|
|
|
|
#define CLOG_STACK_BUFFER_SIZE 1024 |
|
|
|
#define CLOG_FATAL_PREFIX "Fatal error: " |
|
#define CLOG_FATAL_PREFIX_LENGTH 13 |
|
#define CLOG_FATAL_PREFIX_FORMAT "Fatal error in %s: " |
|
#define CLOG_ERROR_PREFIX "Error: " |
|
#define CLOG_ERROR_PREFIX_LENGTH 7 |
|
#define CLOG_ERROR_PREFIX_FORMAT "Error in %s: " |
|
#define CLOG_WARNING_PREFIX "Warning: " |
|
#define CLOG_WARNING_PREFIX_LENGTH 9 |
|
#define CLOG_WARNING_PREFIX_FORMAT "Warning in %s: " |
|
#define CLOG_INFO_PREFIX "Note: " |
|
#define CLOG_INFO_PREFIX_LENGTH 6 |
|
#define CLOG_INFO_PREFIX_FORMAT "Note (%s): " |
|
#define CLOG_DEBUG_PREFIX "Debug: " |
|
#define CLOG_DEBUG_PREFIX_LENGTH 7 |
|
#define CLOG_DEBUG_PREFIX_FORMAT "Debug (%s): " |
|
#define CLOG_SUFFIX_LENGTH 1 |
|
|
|
void clog_vlog_fatal(const char* module, const char* format, va_list args) { |
|
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO |
|
__android_log_vprint(ANDROID_LOG_FATAL, module, format, args); |
|
#else |
|
char stack_buffer[CLOG_STACK_BUFFER_SIZE]; |
|
char* heap_buffer = NULL; |
|
char* out_buffer = &stack_buffer[0]; |
|
|
|
|
|
va_list args_copy; |
|
va_copy(args_copy, args); |
|
|
|
int prefix_chars = CLOG_FATAL_PREFIX_LENGTH; |
|
if (module == NULL) { |
|
memcpy(stack_buffer, CLOG_FATAL_PREFIX, CLOG_FATAL_PREFIX_LENGTH); |
|
} else { |
|
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_FATAL_PREFIX_FORMAT, module); |
|
if (prefix_chars < 0) { |
|
|
|
prefix_chars = 0; |
|
} |
|
} |
|
|
|
int format_chars; |
|
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) { |
|
|
|
|
|
|
|
|
|
format_chars = vsnprintf(NULL, 0, format, args); |
|
} else { |
|
format_chars = |
|
vsnprintf( |
|
&stack_buffer[prefix_chars], |
|
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH, |
|
format, |
|
args); |
|
} |
|
if (format_chars < 0) { |
|
|
|
goto cleanup; |
|
} |
|
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
if (heap_buffer == NULL) { |
|
goto cleanup; |
|
} |
|
|
|
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
snprintf(heap_buffer, prefix_chars + 1 , CLOG_FATAL_PREFIX_FORMAT, module); |
|
} else { |
|
|
|
memcpy(heap_buffer, stack_buffer, prefix_chars); |
|
} |
|
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy); |
|
out_buffer = heap_buffer; |
|
} |
|
out_buffer[prefix_chars + format_chars] = '\n'; |
|
#if defined(_WIN32) |
|
DWORD bytes_written; |
|
WriteFile( |
|
GetStdHandle(STD_ERROR_HANDLE), |
|
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH, |
|
&bytes_written, NULL); |
|
#elif defined(__hexagon__) |
|
qurt_printf("%s", out_buffer); |
|
#else |
|
write(STDERR_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
#endif |
|
|
|
cleanup: |
|
free(heap_buffer); |
|
va_end(args_copy); |
|
#endif |
|
} |
|
|
|
void clog_vlog_error(const char* module, const char* format, va_list args) { |
|
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO |
|
__android_log_vprint(ANDROID_LOG_ERROR, module, format, args); |
|
#else |
|
char stack_buffer[CLOG_STACK_BUFFER_SIZE]; |
|
char* heap_buffer = NULL; |
|
char* out_buffer = &stack_buffer[0]; |
|
|
|
|
|
va_list args_copy; |
|
va_copy(args_copy, args); |
|
|
|
int prefix_chars = CLOG_ERROR_PREFIX_LENGTH; |
|
if (module == NULL) { |
|
memcpy(stack_buffer, CLOG_ERROR_PREFIX, CLOG_ERROR_PREFIX_LENGTH); |
|
} else { |
|
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_ERROR_PREFIX_FORMAT, module); |
|
if (prefix_chars < 0) { |
|
|
|
prefix_chars = 0; |
|
} |
|
} |
|
|
|
int format_chars; |
|
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) { |
|
|
|
|
|
|
|
|
|
format_chars = vsnprintf(NULL, 0, format, args); |
|
} else { |
|
format_chars = |
|
vsnprintf( |
|
&stack_buffer[prefix_chars], |
|
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH, |
|
format, |
|
args); |
|
} |
|
if (format_chars < 0) { |
|
|
|
goto cleanup; |
|
} |
|
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
if (heap_buffer == NULL) { |
|
goto cleanup; |
|
} |
|
|
|
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
snprintf(heap_buffer, prefix_chars + 1 , CLOG_ERROR_PREFIX_FORMAT, module); |
|
} else { |
|
|
|
memcpy(heap_buffer, stack_buffer, prefix_chars); |
|
} |
|
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy); |
|
out_buffer = heap_buffer; |
|
} |
|
out_buffer[prefix_chars + format_chars] = '\n'; |
|
#if defined(_WIN32) |
|
DWORD bytes_written; |
|
WriteFile( |
|
GetStdHandle(STD_ERROR_HANDLE), |
|
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH, |
|
&bytes_written, NULL); |
|
#elif defined(__hexagon__) |
|
qurt_printf("%s", out_buffer); |
|
#else |
|
write(STDERR_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
#endif |
|
|
|
cleanup: |
|
free(heap_buffer); |
|
va_end(args_copy); |
|
#endif |
|
} |
|
|
|
void clog_vlog_warning(const char* module, const char* format, va_list args) { |
|
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO |
|
__android_log_vprint(ANDROID_LOG_WARN, module, format, args); |
|
#else |
|
char stack_buffer[CLOG_STACK_BUFFER_SIZE]; |
|
char* heap_buffer = NULL; |
|
char* out_buffer = &stack_buffer[0]; |
|
|
|
|
|
va_list args_copy; |
|
va_copy(args_copy, args); |
|
|
|
int prefix_chars = CLOG_WARNING_PREFIX_LENGTH; |
|
if (module == NULL) { |
|
memcpy(stack_buffer, CLOG_WARNING_PREFIX, CLOG_WARNING_PREFIX_LENGTH); |
|
} else { |
|
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_WARNING_PREFIX_FORMAT, module); |
|
if (prefix_chars < 0) { |
|
|
|
prefix_chars = 0; |
|
} |
|
} |
|
|
|
int format_chars; |
|
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) { |
|
|
|
|
|
|
|
|
|
format_chars = vsnprintf(NULL, 0, format, args); |
|
} else { |
|
format_chars = |
|
vsnprintf( |
|
&stack_buffer[prefix_chars], |
|
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH, |
|
format, |
|
args); |
|
} |
|
if (format_chars < 0) { |
|
|
|
goto cleanup; |
|
} |
|
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
if (heap_buffer == NULL) { |
|
goto cleanup; |
|
} |
|
|
|
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
snprintf(heap_buffer, prefix_chars + 1 , CLOG_WARNING_PREFIX_FORMAT, module); |
|
} else { |
|
|
|
memcpy(heap_buffer, stack_buffer, prefix_chars); |
|
} |
|
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy); |
|
out_buffer = heap_buffer; |
|
} |
|
out_buffer[prefix_chars + format_chars] = '\n'; |
|
#if defined(_WIN32) |
|
DWORD bytes_written; |
|
WriteFile( |
|
GetStdHandle(STD_ERROR_HANDLE), |
|
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH, |
|
&bytes_written, NULL); |
|
#elif defined(__hexagon__) |
|
qurt_printf("%s", out_buffer); |
|
#else |
|
write(STDERR_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
#endif |
|
|
|
cleanup: |
|
free(heap_buffer); |
|
va_end(args_copy); |
|
#endif |
|
} |
|
|
|
void clog_vlog_info(const char* module, const char* format, va_list args) { |
|
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO |
|
__android_log_vprint(ANDROID_LOG_INFO, module, format, args); |
|
#else |
|
char stack_buffer[CLOG_STACK_BUFFER_SIZE]; |
|
char* heap_buffer = NULL; |
|
char* out_buffer = &stack_buffer[0]; |
|
|
|
|
|
va_list args_copy; |
|
va_copy(args_copy, args); |
|
|
|
int prefix_chars = CLOG_INFO_PREFIX_LENGTH; |
|
if (module == NULL) { |
|
memcpy(stack_buffer, CLOG_INFO_PREFIX, CLOG_INFO_PREFIX_LENGTH); |
|
} else { |
|
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_INFO_PREFIX_FORMAT, module); |
|
if (prefix_chars < 0) { |
|
|
|
prefix_chars = 0; |
|
} |
|
} |
|
|
|
int format_chars; |
|
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) { |
|
|
|
|
|
|
|
|
|
format_chars = vsnprintf(NULL, 0, format, args); |
|
} else { |
|
format_chars = |
|
vsnprintf( |
|
&stack_buffer[prefix_chars], |
|
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH, |
|
format, |
|
args); |
|
} |
|
if (format_chars < 0) { |
|
|
|
goto cleanup; |
|
} |
|
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
if (heap_buffer == NULL) { |
|
goto cleanup; |
|
} |
|
|
|
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
snprintf(heap_buffer, prefix_chars + 1 , CLOG_INFO_PREFIX_FORMAT, module); |
|
} else { |
|
|
|
memcpy(heap_buffer, stack_buffer, prefix_chars); |
|
} |
|
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy); |
|
out_buffer = heap_buffer; |
|
} |
|
out_buffer[prefix_chars + format_chars] = '\n'; |
|
#if defined(_WIN32) |
|
DWORD bytes_written; |
|
WriteFile( |
|
GetStdHandle(STD_OUTPUT_HANDLE), |
|
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH, |
|
&bytes_written, NULL); |
|
#elif defined(__hexagon__) |
|
qurt_printf("%s", out_buffer); |
|
#else |
|
write(STDOUT_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
#endif |
|
|
|
cleanup: |
|
free(heap_buffer); |
|
va_end(args_copy); |
|
#endif |
|
} |
|
|
|
void clog_vlog_debug(const char* module, const char* format, va_list args) { |
|
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO |
|
__android_log_vprint(ANDROID_LOG_DEBUG, module, format, args); |
|
#else |
|
char stack_buffer[CLOG_STACK_BUFFER_SIZE]; |
|
char* heap_buffer = NULL; |
|
char* out_buffer = &stack_buffer[0]; |
|
|
|
|
|
va_list args_copy; |
|
va_copy(args_copy, args); |
|
|
|
int prefix_chars = CLOG_DEBUG_PREFIX_LENGTH; |
|
if (module == NULL) { |
|
memcpy(stack_buffer, CLOG_DEBUG_PREFIX, CLOG_DEBUG_PREFIX_LENGTH); |
|
} else { |
|
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_DEBUG_PREFIX_FORMAT, module); |
|
if (prefix_chars < 0) { |
|
|
|
prefix_chars = 0; |
|
} |
|
} |
|
|
|
int format_chars; |
|
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) { |
|
|
|
|
|
|
|
|
|
format_chars = vsnprintf(NULL, 0, format, args); |
|
} else { |
|
format_chars = |
|
vsnprintf( |
|
&stack_buffer[prefix_chars], |
|
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH, |
|
format, |
|
args); |
|
} |
|
if (format_chars < 0) { |
|
|
|
goto cleanup; |
|
} |
|
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
if (heap_buffer == NULL) { |
|
goto cleanup; |
|
} |
|
|
|
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) { |
|
|
|
snprintf(heap_buffer, prefix_chars + 1 , CLOG_DEBUG_PREFIX_FORMAT, module); |
|
} else { |
|
|
|
memcpy(heap_buffer, stack_buffer, prefix_chars); |
|
} |
|
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy); |
|
out_buffer = heap_buffer; |
|
} |
|
out_buffer[prefix_chars + format_chars] = '\n'; |
|
#if defined(_WIN32) |
|
DWORD bytes_written; |
|
WriteFile( |
|
GetStdHandle(STD_OUTPUT_HANDLE), |
|
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH, |
|
&bytes_written, NULL); |
|
#elif defined(__hexagon__) |
|
qurt_printf("%s", out_buffer); |
|
#else |
|
write(STDOUT_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH); |
|
#endif |
|
|
|
cleanup: |
|
free(heap_buffer); |
|
va_end(args_copy); |
|
#endif |
|
} |
|
|