31 .context_message = NULL,
35 .backtrace_symbols = NULL,
37 .has_system_error =
false};
42static bool g_suppress_error_context =
false;
50static bool stats_initialized =
false;
57#define MAX_THREAD_ERRORS 64
69static uint64_t get_timestamp_microseconds(
void) {
71 if (clock_gettime(CLOCK_REALTIME, &ts) == 0) {
78static void capture_backtrace(
void **backtrace,
char ***backtrace_symbols,
int *stack_depth) {
84 (void)backtrace_symbols;
89static bool skip_backtrace_frame(
const char *frame) {
90 return (strstr(frame,
"BaseThreadInitThunk") != NULL || strstr(frame,
"RtlUserThreadStart") != NULL ||
91 strstr(frame,
"__scrt_common_main_seh") != NULL || strstr(frame,
"capture_backtrace") != NULL ||
92 strstr(frame,
"safe_backtrace") != NULL || strstr(frame,
"platform_backtrace") != NULL ||
93 strstr(frame,
"asciichat_set_errno") != NULL || strstr(frame,
"asciichat_set_errno_with_message") != NULL ||
94 strstr(frame,
"SET_ERRNO") != NULL || strstr(frame,
"asciichat_fatal_with_context") != NULL ||
95 strstr(frame,
"asciichat_print_error_context") != NULL);
100 va_start(args, message);
107 log_file(
"%s: %s", label, formatted_message);
118 const char *context_message) {
120 if (g_suppress_error_context) {
142 if (context_message == NULL) {
144 const char *fallback =
"No context message (this is invalid - set a context message)";
145 size_t len = strlen(fallback) + 1;
150 log_error(
"SAFE_MALLOC failed for fallback context_message");
153 size_t len = strlen(context_message) + 1;
158 log_error(
"SAFE_MALLOC failed for context_message");
175 const char *format, ...) {
177 va_start(args, format);
182 if (context_message) {
197 const char *function,
int sys_errno,
const char *format, ...) {
199 va_start(args, format);
206 if (context_message) {
276 const char *format, ...) {
294 log_plain(
" Location: %s:%d in %s()", relative_file, line, function);
299 va_start(args, format);
301 log_plain(
" Error message: %s", formatted_message);
336 log_plain(
" Location: unknown (set by system code)");
352 time_t sec = (time_t)(context->
timestamp / 1000000);
353 long usec = (long)(context->
timestamp % 1000000);
357 (void)strftime(time_str,
sizeof(time_str),
"%Y-%m-%d %H:%M:%S", &tm_info);
358 log_plain(
" Timestamp: %s.%06ld", time_str, usec);
365 0, 0, skip_backtrace_frame);
375 if (!stats_initialized) {
376 memset(&error_stats, 0,
sizeof(error_stats));
377 stats_initialized =
true;
382 if (!stats_initialized) {
386 if (code >= 0 && code < 256) {
395 if (!stats_initialized || error_stats.
total_errors == 0) {
400 log_plain(
"\n=== ascii-chat Error Statistics ===\n");
408 strftime(time_str,
sizeof(time_str),
"%Y-%m-%d %H:%M:%S", &tm_info);
414 for (
int i = 0; i < 256; i++) {
424 memset(&error_stats, 0,
sizeof(error_stats));
428 if (!stats_initialized) {
442 return thread_errors[i].error_code;
456 if (!thread_errors[i].
valid && slot == -1) {
462 thread_errors[slot].thread_id =
thread_id;
463 thread_errors[slot].error_code = code;
464 thread_errors[slot].valid =
true;
471 thread_errors[i].valid =
false;
483 g_suppress_error_context = suppress;
502 g_suppress_error_context =
true;
asciichat_error_t error_code
#define MAX_THREAD_ERRORS
⚠️‼️ Error and/or exit() when things go bad.
#define SAFE_STRNCPY(dst, src, size)
#define SAFE_MALLOC(size, cast)
#define SAFE_STRERROR(errnum)
unsigned long long uint64_t
void asciichat_set_errno(asciichat_error_t code, const char *file, int line, const char *function, const char *context_message)
Set error code with basic context.
bool asciichat_has_wsa_error(void)
Check if current error has WSA error code.
void asciichat_clear_thread_error(int thread_id)
Clear error code for a specific thread.
void asciichat_fatal_with_context(asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)
Exit with error code and context (used by FATAL macro)
void asciichat_errno_suppress(bool suppress)
Suppress error logging and reporting.
void asciichat_set_errno_with_system_error(asciichat_error_t code, const char *file, int line, const char *function, int sys_errno)
Set error code with system error (errno)
#define HAS_ERRNO(var)
Check if an error occurred and get full context.
__thread asciichat_error_t asciichat_errno
Thread-local current error code.
void asciichat_error_stats_print(void)
Print error statistics to stderr.
bool asciichat_has_errno(asciichat_error_context_t *context)
Check if error occurred and get full context.
void asciichat_clear_errno(void)
Clear the current error state.
asciichat_error_t asciichat_get_thread_error(int thread_id)
Get error code for a specific thread.
asciichat_error_t asciichat_get_errno(void)
Get current error code.
void asciichat_set_errno_with_wsa_error(asciichat_error_t code, const char *file, int line, const char *function, int wsa_error)
Set error code with Windows socket error (WSA error)
asciichat_error_stats_t asciichat_error_stats_get(void)
Get current error statistics.
void asciichat_error_stats_init(void)
Initialize error statistics system.
void asciichat_errno_cleanup(void)
Cleanup error system resources.
void asciichat_set_errno_with_message(asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)
Set error code with formatted message.
void asciichat_error_stats_reset(void)
Reset all error statistics to zero.
__thread asciichat_error_context_t asciichat_errno_context
Thread-local error context storage.
void asciichat_set_thread_error(int thread_id, asciichat_error_t code)
Set error code for a specific thread.
void asciichat_print_error_context(const asciichat_error_context_t *context)
Print full error context to stderr.
void asciichat_set_errno_with_system_error_and_message(asciichat_error_t code, const char *file, int line, const char *function, int sys_errno, const char *format,...)
Set error code with system error and formatted message.
void asciichat_error_stats_record(asciichat_error_t code)
Record an error in statistics.
asciichat_error_t
Error and exit codes - unified status values (0-255)
const char * log_level_color(log_color_t color)
Get color string for a given color enum.
char * format_message(const char *format, va_list args)
Format a message using va_list.
log_color_t
Color enum for logging - indexes into color arrays.
#define log_error(...)
Log an ERROR message.
void log_labeled(const char *label, log_color_t color, const char *message,...)
Print a labeled message with color.
#define log_file(...)
File-only logging - writes to log file only, no stderr output.
#define log_plain(...)
Plain logging - writes to both log file and stderr without timestamps or log levels.
const char * extract_project_relative_path(const char *file)
Extract relative path from an absolute path.
📝 Logging API with multiple log levels and terminal output control
📂 Path Manipulation Utilities
int wsa_error
Windows socket error code (if applicable, 0 otherwise)
int system_errno
System errno value (if applicable, 0 otherwise)
const char * function
Function name where error occurred (NULL in release builds)
char * context_message
Optional custom message (dynamically allocated, owned by system)
uint64_t timestamp
Timestamp when error occurred (microseconds since epoch)
char ** backtrace_symbols
Stack trace symbol strings (debug builds only)
bool has_system_error
True if system_errno is valid.
const char * file
Source file where error occurred (NULL in release builds)
int stack_depth
Number of stack frames captured (0 if not captured)
int line
Line number where error occurred (0 in release builds)
bool has_wsa_error
True if wsa_error is valid.
asciichat_error_t code
Error code (asciichat_error_t enum value)
void * backtrace[32]
Stack trace addresses (debug builds only)
Error statistics structure.
uint64_t last_error_time
Timestamp of last error (microseconds since epoch)
uint64_t error_counts[256]
Count for each error code (256 possible error codes)
asciichat_error_t last_error_code
Error code of last error recorded.
uint64_t total_errors
Total number of errors recorded (sum of all error_counts)
Cross-platform system functions interface for ascii-chat.
⏱️ High-precision timing utilities using sokol_time.h and uthash
Common SIMD utilities and structures.