ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
Common Definitions

⚙️ Code shared throughout the library More...

Files

file  common.c
 🔧 Core utilities: memory management, safe macros, and cross-platform helpers
 
file  fps.c
 ⏱️ FPS tracking utility implementation (nanosecond-precision)
 
file  common.h
 ⚙️ Common definitions, error codes, macros, and types shared throughout the application
 
file  embedded_resources.h
 Embedded resource management for production builds.
 
file  fps.h
 ⏱️ FPS tracking utility for monitoring frame throughput across all threads
 

Data Structures

struct  fps_t
 FPS tracking state. More...
 

Macros

#define ASCII_CHAT_APP_NAME   "ascii-chat"
 Application name for key comments ("ascii-chat")
 
#define PLATFORM_MAX_PATH_LENGTH   4096
 
#define NONSTRING   /* nothing */
 
#define FATAL(code, ...)   asciichat_fatal_with_context(code, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
 Exit with error code and custom message, with stack trace in debug builds.
 
#define RUN_BURST_AND_THROTTLE(burst_ns, throttle_ns, code_block)
 Return the minimum of two values.
 
#define ALLOC_MALLOC(size)   malloc(size)
 
#define ALLOC_CALLOC(count, size)   calloc((count), (size))
 
#define ALLOC_REALLOC(ptr, size)   realloc((ptr), (size))
 
#define ALLOC_FREE(ptr)   free(ptr)
 
#define ASCIICHAT_CHECK_AND_LOG(expr, ok_value, msg, ...)
 Check result and log error if operation failed.
 

Typedefs

typedef unsigned char uint8_t
 
typedef unsigned short uint16_t
 
typedef unsigned int uint32_t
 
typedef unsigned long long uint64_t
 

Functions

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)
 
asciichat_error_t asciichat_shared_init (const char *log_file, bool is_client, bool quiet_startup)
 Initialize common subsystems shared by client and server.
 
void asciichat_shared_destroy (void)
 Clean up shared library subsystems.
 
void fps_init (fps_t *tracker, int expected_fps, const char *name)
 Initialize FPS tracker.
 
void fps_init_with_interval (fps_t *tracker, int expected_fps, const char *name, uint64_t report_interval_ns)
 Initialize FPS tracker with custom report interval.
 
void fps_frame_ns (fps_t *tracker, uint64_t current_time_ns, const char *context)
 Track a frame and detect lag conditions (nanosecond version - PRIMARY)
 

Variables

int g_argc
 Global argc for early argument inspection (e.g., –color flag detection) Set by main() for access from lib/platform/terminal.c during early execution.
 
char ** g_argv
 Global argv for early argument inspection (e.g., –color flag detection) Set by main() for access from lib/platform/terminal.c during early execution.
 
bool g_color_flag_passed
 Was –color explicitly passed in command-line arguments? Set by options_init() before RCU is initialized, used by terminal_should_color_output()
 
bool g_color_flag_value
 Value of –color flag (true if –color was in argv) Set by options_init() before RCU is initialized, used by terminal_should_color_output()
 

Memory Debugging Macros

#define SAFE_MALLOC(size, cast)
 
#define SAFE_CALLOC(count, size, cast)
 
#define SAFE_REALLOC(ptr, size, cast)
 
#define TRACK_ALIGNED_ALLOC(ptr, size, file, line)   ((void)0)
 
#define SAFE_MALLOC_ALIGNED(size, alignment, cast)
 
#define SAFE_MALLOC_SIMD(size, cast)   SAFE_MALLOC_ALIGNED(size, 16, cast)
 
#define SAFE_CALLOC_SIMD(count, size, cast)
 
#define SAFE_FREE(ptr)
 
#define SAFE_FCLOSE(fp)
 
#define UNTRACKED_MALLOC(size, cast)
 
#define UNTRACKED_FREE(ptr)
 
#define SAFE_STRNCPY(dst, src, size)   platform_strlcpy((dst), (src), (size))
 
#define SAFE_STRDUP(dst, src)
 
#define SAFE_GETENV(name)   platform_getenv(name)
 
#define SAFE_SSCANF(str, format, ...)   sscanf(str, format, __VA_ARGS__)
 
#define SAFE_STRERROR(errnum)   platform_strerror(errnum)
 
#define SAFE_MEMCPY(dest, dest_size, src, count)   platform_memcpy((dest), (dest_size), (src), (count))
 
#define SAFE_MEMSET(dest, dest_size, ch, count)   platform_memset((dest), (dest_size), (ch), (count))
 
#define SAFE_MEMMOVE(dest, dest_size, src, count)   platform_memmove((dest), (dest_size), (src), (count))
 
#define SAFE_STRCPY(dest, dest_size, src)   platform_strcpy((dest), (dest_size), (src))
 
#define read_u16_unaligned   bytes_read_u16_unaligned
 
#define read_u32_unaligned   bytes_read_u32_unaligned
 
#define write_u16_unaligned   bytes_write_u16_unaligned
 
#define write_u32_unaligned   bytes_write_u32_unaligned
 
#define safe_size_mul   bytes_safe_size_mul
 
#define SAFE_SNPRINTF(buffer, buffer_size, ...)   (size_t)safe_snprintf((buffer), (buffer_size), __VA_ARGS__)
 
#define SAFE_BUFFER_SIZE(buffer_size, offset)    ((offset) < 0 || (size_t)(offset) >= (buffer_size) ? 0 : (buffer_size) - (size_t)(offset))
 Safe buffer size calculation for snprintf.
 
#define THREAD_CREATE_OR_RETURN(thread, func, arg)
 Create a thread or log error and return.
 
#define MUTEX_INIT_OR_RETURN(m)
 Initialize a mutex or log error and return.
 

Detailed Description

⚙️ Code shared throughout the library

This header provides core functionality used throughout ascii-chat:

Note
This header should be included early in other headers as it provides fundamental types and macros that many other modules depend on.

Provides a reusable FPS tracking mechanism for monitoring real-time frame delivery rates across all client threads (data reception, webcam capture, audio capture, keepalive). Tracks frame intervals, detects lag conditions, and generates periodic FPS reports every 7-15 seconds.

USAGE:

fps_t tracker;
fps_init(&tracker, 60, "WEBCAM"); // 60 FPS expected
// In your frame processing loop
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
fps_frame(&tracker, &now, "frame received");
void fps_init(fps_t *tracker, int expected_fps, const char *name)
Initialize FPS tracker.
Definition fps.c:32
FPS tracking state.
Definition fps.h:52

FEATURES:

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
December 2025
Version
2.0 (Refactored with unified thread tracking)

Macro Definition Documentation

◆ ALLOC_CALLOC

#define ALLOC_CALLOC (   count,
  size 
)    calloc((count), (size))

#include <common.h>

Definition at line 252 of file common.h.

◆ ALLOC_FREE

#define ALLOC_FREE (   ptr)    free(ptr)

#include <common.h>

Definition at line 254 of file common.h.

◆ ALLOC_MALLOC

#define ALLOC_MALLOC (   size)    malloc(size)

#include <common.h>

Definition at line 251 of file common.h.

◆ ALLOC_REALLOC

#define ALLOC_REALLOC (   ptr,
  size 
)    realloc((ptr), (size))

#include <common.h>

Definition at line 253 of file common.h.

◆ ASCII_CHAT_APP_NAME

#define ASCII_CHAT_APP_NAME   "ascii-chat"

#include <common.h>

Application name for key comments ("ascii-chat")

Definition at line 43 of file common.h.

◆ ASCIICHAT_CHECK_AND_LOG

#define ASCIICHAT_CHECK_AND_LOG (   expr,
  ok_value,
  msg,
  ... 
)

#include <common.h>

Value:
do { \
if ((expr) != (ok_value)) { \
log_error(msg, ##__VA_ARGS__); \
return (expr); \
} \
} while (0)

Check result and log error if operation failed.

Consolidates the pattern:

operation_result_t result = operation();
if (result != OK) {
log_error("Operation failed: %d", result);
return result;
}
#define log_error(...)
Log an ERROR message.
Definition log/log.h:587

Usage:

ASCIICHAT_CHECK_AND_LOG(crypto_result = crypto_operation(args),
ASCIICHAT_OK, "Crypto operation failed: %d",
crypto_result);
#define ASCIICHAT_CHECK_AND_LOG(expr, ok_value, msg,...)
Check result and log error if operation failed.
Definition common.h:629
@ ASCIICHAT_OK
Definition error_codes.h:51
action_args_t args

Definition at line 629 of file common.h.

630 { \
631 if ((expr) != (ok_value)) { \
632 log_error(msg, ##__VA_ARGS__); \
633 return (expr); \
634 } \
635 } while (0)

◆ FATAL

#define FATAL (   code,
  ... 
)    asciichat_fatal_with_context(code, __FILE__, __LINE__, __func__, ##__VA_ARGS__)

#include <common.h>

Exit with error code and custom message, with stack trace in debug builds.

Parameters
codeError code (asciichat_error_t)
...Custom message format string and arguments (printf-style)
Note
In debug builds, includes file, line, and function information. In release builds, file/line/function are omitted to reduce binary size.
Warning
This macro terminates the program. Use only for unrecoverable errors.
Example:
FATAL(ERROR_NETWORK_BIND, "Cannot bind to port %d", port_number);
#define FATAL(code,...)
Exit with error code and custom message, with stack trace in debug builds.
Definition common.h:158
@ ERROR_NETWORK_BIND
Definition error_codes.h:78

Definition at line 158 of file common.h.

◆ MUTEX_INIT_OR_RETURN

#define MUTEX_INIT_OR_RETURN (   m)

#include <common.h>

Value:
do { \
if (mutex_init(&(m)) != 0) { \
log_error("Failed to initialize mutex: %s", #m); \
return -1; \
} \
} while (0)
int mutex_init(mutex_t *mutex, const char *name)
Initialize a mutex with a name.
Definition threading.c:16

Initialize a mutex or log error and return.

Parameters
mPointer to mutex_t variable

Handles common pattern: init mutex, log error if failed, then return -1. Example usage:

MUTEX_INIT_OR_RETURN(mutex); // Mutex initialized successfully, continue

Definition at line 542 of file common.h.

543 { \
544 if (mutex_init(&(m)) != 0) { \
545 log_error("Failed to initialize mutex: %s", #m); \
546 return -1; \
547 } \
548 } while (0)

◆ NONSTRING

#define NONSTRING   /* nothing */

#include <common.h>

Definition at line 98 of file common.h.

◆ PLATFORM_MAX_PATH_LENGTH

#define PLATFORM_MAX_PATH_LENGTH   4096

#include <common.h>

Definition at line 91 of file common.h.

◆ read_u16_unaligned

#define read_u16_unaligned   bytes_read_u16_unaligned

#include <common.h>

Definition at line 484 of file common.h.

◆ read_u32_unaligned

#define read_u32_unaligned   bytes_read_u32_unaligned

#include <common.h>

Definition at line 485 of file common.h.

◆ RUN_BURST_AND_THROTTLE

#define RUN_BURST_AND_THROTTLE (   burst_ns,
  throttle_ns,
  code_block 
)

#include <common.h>

Value:
do { \
static uint64_t burst_start = 0; \
uint64_t now = time_get_ns(); \
\
/* First call or timer reset */ \
if (burst_start == 0) { \
burst_start = now; \
code_block; \
} else { \
uint64_t elapsed_ns = now - burst_start; \
\
if (elapsed_ns < (uint64_t)(burst_ns)) { \
/* Within burst window */ \
code_block; \
} else if (elapsed_ns >= (uint64_t)(throttle_ns)) { \
/* Throttle period complete, reset and execute */ \
burst_start = now; \
code_block; \
} \
/* else: in throttle period, do nothing */ \
} \
} while (0)
unsigned long long uint64_t
Definition common.h:59
uint64_t time_get_ns(void)
Get current monotonic time in nanoseconds.
Definition util/time.c:108

Return the minimum of two values.

Return the maximum of two values

Calculate the number of elements in an array

Definition at line 206 of file common.h.

207 { \
208 static uint64_t burst_start = 0; \
209 uint64_t now = time_get_ns(); \
210 \
211 /* First call or timer reset */ \
212 if (burst_start == 0) { \
213 burst_start = now; \
214 code_block; \
215 } else { \
216 uint64_t elapsed_ns = now - burst_start; \
217 \
218 if (elapsed_ns < (uint64_t)(burst_ns)) { \
219 /* Within burst window */ \
220 code_block; \
221 } else if (elapsed_ns >= (uint64_t)(throttle_ns)) { \
222 /* Throttle period complete, reset and execute */ \
223 burst_start = now; \
224 code_block; \
225 } \
226 /* else: in throttle period, do nothing */ \
227 } \
228 } while (0)

◆ SAFE_BUFFER_SIZE

#define SAFE_BUFFER_SIZE (   buffer_size,
  offset 
)     ((offset) < 0 || (size_t)(offset) >= (buffer_size) ? 0 : (buffer_size) - (size_t)(offset))

#include <common.h>

Safe buffer size calculation for snprintf.

Casts offset to size_t to avoid sign conversion warnings when subtracting from buffer_size. Returns 0 if offset is negative or >= buffer_size (prevents underflow).

Definition at line 501 of file common.h.

502 : (buffer_size) - (size_t)(offset))
int buffer_size
Size of circular buffer.
Definition grep.c:90

◆ SAFE_CALLOC

#define SAFE_CALLOC (   count,
  size,
  cast 
)

#include <common.h>

Value:
({ \
cast _ptr = (cast)ALLOC_CALLOC((count), (size)); \
if (!_ptr) { \
FATAL(ERROR_MEMORY, "Memory allocation failed: %zu elements x %zu bytes", (size_t)(count), (size_t)(size)); \
} \
_ptr; \
})
#define ALLOC_CALLOC(count, size)
Definition common.h:252
@ ERROR_MEMORY
Definition error_codes.h:56

Definition at line 274 of file common.h.

275 { \
276 cast _ptr = (cast)ALLOC_CALLOC((count), (size)); \
277 if (!_ptr) { \
278 FATAL(ERROR_MEMORY, "Memory allocation failed: %zu elements x %zu bytes", (size_t)(count), (size_t)(size)); \
279 } \
280 _ptr; \
281 })

◆ SAFE_CALLOC_SIMD

#define SAFE_CALLOC_SIMD (   count,
  size,
  cast 
)

#include <common.h>

Value:
({ \
size_t total_size = (count) * (size); \
cast _ptr = SAFE_MALLOC_SIMD(total_size, cast); \
memset(_ptr, 0, total_size); \
_ptr; \
})
#define SAFE_MALLOC_SIMD(size, cast)
Definition common.h:364

Definition at line 367 of file common.h.

368 { \
369 size_t total_size = (count) * (size); \
370 cast _ptr = SAFE_MALLOC_SIMD(total_size, cast); \
371 memset(_ptr, 0, total_size); \
372 _ptr; \
373 })

◆ SAFE_FCLOSE

#define SAFE_FCLOSE (   fp)

#include <common.h>

Value:
do { \
if ((fp) != NULL) { \
fclose(fp); \
(fp) = NULL; \
} \
} while (0)

Definition at line 386 of file common.h.

387 { \
388 if ((fp) != NULL) { \
389 fclose(fp); \
390 (fp) = NULL; \
391 } \
392 } while (0)

◆ SAFE_FREE

#define SAFE_FREE (   ptr)

#include <common.h>

Value:
do { \
if ((ptr) != NULL) { \
ALLOC_FREE((void *)(ptr)); \
(ptr) = NULL; \
} \
} while (0)

Definition at line 376 of file common.h.

377 { \
378 if ((ptr) != NULL) { \
379 ALLOC_FREE((void *)(ptr)); \
380 (ptr) = NULL; \
381 } \
382 } while (0)

◆ SAFE_GETENV

#define SAFE_GETENV (   name)    platform_getenv(name)

#include <common.h>

Definition at line 434 of file common.h.

◆ SAFE_MALLOC

#define SAFE_MALLOC (   size,
  cast 
)

#include <common.h>

Value:
({ \
cast _ptr = (cast)ALLOC_MALLOC(size); \
if (!_ptr) { \
FATAL(ERROR_MEMORY, "Memory allocation failed: %zu bytes", (size_t)(size)); \
} \
_ptr; \
})
#define ALLOC_MALLOC(size)
Definition common.h:251

Definition at line 264 of file common.h.

265 { \
266 cast _ptr = (cast)ALLOC_MALLOC(size); \
267 if (!_ptr) { \
268 FATAL(ERROR_MEMORY, "Memory allocation failed: %zu bytes", (size_t)(size)); \
269 } \
270 _ptr; \
271 })

◆ SAFE_MALLOC_ALIGNED

#define SAFE_MALLOC_ALIGNED (   size,
  alignment,
  cast 
)

#include <common.h>

Value:
({ \
size_t aligned_size = (((size) + (alignment) - 1) / (alignment)) * (alignment); \
cast _ptr = (cast)aligned_alloc((alignment), aligned_size); \
if (!_ptr) { \
FATAL(ERROR_MEMORY, "Aligned memory allocation failed: %zu bytes, %zu alignment", aligned_size, \
(size_t)(alignment)); \
} \
TRACK_ALIGNED_ALLOC(_ptr, aligned_size, __FILE__, __LINE__); \
_ptr; \
})

Definition at line 349 of file common.h.

350 { \
351 size_t aligned_size = (((size) + (alignment) - 1) / (alignment)) * (alignment); \
352 cast _ptr = (cast)aligned_alloc((alignment), aligned_size); \
353 if (!_ptr) { \
354 FATAL(ERROR_MEMORY, "Aligned memory allocation failed: %zu bytes, %zu alignment", aligned_size, \
355 (size_t)(alignment)); \
356 } \
357 TRACK_ALIGNED_ALLOC(_ptr, aligned_size, __FILE__, __LINE__); \
358 _ptr; \
359 })

◆ SAFE_MALLOC_SIMD

#define SAFE_MALLOC_SIMD (   size,
  cast 
)    SAFE_MALLOC_ALIGNED(size, 16, cast)

#include <common.h>

Definition at line 364 of file common.h.

◆ SAFE_MEMCPY

#define SAFE_MEMCPY (   dest,
  dest_size,
  src,
  count 
)    platform_memcpy((dest), (dest_size), (src), (count))

#include <common.h>

Definition at line 468 of file common.h.

◆ SAFE_MEMMOVE

#define SAFE_MEMMOVE (   dest,
  dest_size,
  src,
  count 
)    platform_memmove((dest), (dest_size), (src), (count))

#include <common.h>

Definition at line 470 of file common.h.

◆ SAFE_MEMSET

#define SAFE_MEMSET (   dest,
  dest_size,
  ch,
  count 
)    platform_memset((dest), (dest_size), (ch), (count))

#include <common.h>

Definition at line 469 of file common.h.

◆ SAFE_REALLOC

#define SAFE_REALLOC (   ptr,
  size,
  cast 
)

#include <common.h>

Value:
({ \
void *tmp_ptr = ALLOC_REALLOC((ptr), (size)); \
if (!tmp_ptr) { \
FATAL(ERROR_MEMORY, "Memory reallocation failed: %zu bytes", (size_t)(size)); \
} \
(cast)(tmp_ptr); \
})
#define ALLOC_REALLOC(ptr, size)
Definition common.h:253

Definition at line 284 of file common.h.

285 { \
286 void *tmp_ptr = ALLOC_REALLOC((ptr), (size)); \
287 if (!tmp_ptr) { \
288 FATAL(ERROR_MEMORY, "Memory reallocation failed: %zu bytes", (size_t)(size)); \
289 } \
290 (cast)(tmp_ptr); \
291 })

◆ safe_size_mul

#define safe_size_mul   bytes_safe_size_mul

#include <common.h>

Definition at line 488 of file common.h.

◆ SAFE_SNPRINTF

#define SAFE_SNPRINTF (   buffer,
  buffer_size,
  ... 
)    (size_t)safe_snprintf((buffer), (buffer_size), __VA_ARGS__)

#include <common.h>

Definition at line 492 of file common.h.

◆ SAFE_SSCANF

#define SAFE_SSCANF (   str,
  format,
  ... 
)    sscanf(str, format, __VA_ARGS__)

#include <common.h>

Definition at line 440 of file common.h.

◆ SAFE_STRCPY

#define SAFE_STRCPY (   dest,
  dest_size,
  src 
)    platform_strcpy((dest), (dest_size), (src))

#include <common.h>

Definition at line 471 of file common.h.

◆ SAFE_STRDUP

#define SAFE_STRDUP (   dst,
  src 
)

#include <common.h>

Value:
do { \
if (src) { \
size_t _len = strlen(src) + 1; \
(dst) = SAFE_MALLOC(_len, char *); \
if (dst) { \
SAFE_MEMCPY((dst), _len, (src), _len); \
} else { \
SET_ERRNO(ERROR_MEMORY, "String duplication failed for: %s", (src)); \
} \
} else { \
(dst) = NULL; \
} \
} while (0)
#define SAFE_MALLOC(size, cast)
Definition common.h:264

Definition at line 418 of file common.h.

419 { \
420 if (src) { \
421 size_t _len = strlen(src) + 1; \
422 (dst) = SAFE_MALLOC(_len, char *); \
423 if (dst) { \
424 SAFE_MEMCPY((dst), _len, (src), _len); \
425 } else { \
426 SET_ERRNO(ERROR_MEMORY, "String duplication failed for: %s", (src)); \
427 } \
428 } else { \
429 (dst) = NULL; \
430 } \
431 } while (0)

◆ SAFE_STRERROR

#define SAFE_STRERROR (   errnum)    platform_strerror(errnum)

#include <common.h>

Definition at line 465 of file common.h.

◆ SAFE_STRNCPY

#define SAFE_STRNCPY (   dst,
  src,
  size 
)    platform_strlcpy((dst), (src), (size))

#include <common.h>

Definition at line 414 of file common.h.

◆ THREAD_CREATE_OR_RETURN

#define THREAD_CREATE_OR_RETURN (   thread,
  func,
  arg 
)

#include <common.h>

Value:
do { \
if (asciichat_thread_create(&(thread), (func), (arg)) != 0) { \
log_error("Failed to create thread: %s", #func); \
return -1; \
} \
} while (0)
#define asciichat_thread_create(thread_ptr, attr, start_routine, arg)

Create a thread or log error and return.

Parameters
threadPointer to thread_t variable
funcThread function (should match void* (*)(void*) signature)
argThread argument

Handles common pattern: create thread, log error if failed, then return -1. Example usage:

THREAD_CREATE_OR_RETURN(thread, thread_func, arg); // Thread created successfully, continue

Definition at line 522 of file common.h.

523 { \
524 if (asciichat_thread_create(&(thread), (func), (arg)) != 0) { \
525 log_error("Failed to create thread: %s", #func); \
526 return -1; \
527 } \
528 } while (0)

◆ TRACK_ALIGNED_ALLOC

#define TRACK_ALIGNED_ALLOC (   ptr,
  size,
  file,
  line 
)    ((void)0)

#include <common.h>

Definition at line 303 of file common.h.

◆ UNTRACKED_FREE

#define UNTRACKED_FREE (   ptr)

#include <common.h>

Value:
do { \
if ((ptr) != NULL) { \
free((void *)(ptr)); \
(ptr) = NULL; \
} \
} while (0)

Definition at line 405 of file common.h.

406 { \
407 if ((ptr) != NULL) { \
408 free((void *)(ptr)); \
409 (ptr) = NULL; \
410 } \
411 } while (0)

◆ UNTRACKED_MALLOC

#define UNTRACKED_MALLOC (   size,
  cast 
)

#include <common.h>

Value:
({ \
cast _ptr = (cast)malloc(size); \
if (!_ptr) { \
FATAL(ERROR_MEMORY, "Memory allocation failed: %zu bytes", (size_t)(size)); \
} \
_ptr; \
})

Definition at line 396 of file common.h.

397 { \
398 cast _ptr = (cast)malloc(size); \
399 if (!_ptr) { \
400 FATAL(ERROR_MEMORY, "Memory allocation failed: %zu bytes", (size_t)(size)); \
401 } \
402 _ptr; \
403 })

◆ write_u16_unaligned

#define write_u16_unaligned   bytes_write_u16_unaligned

#include <common.h>

Definition at line 486 of file common.h.

◆ write_u32_unaligned

#define write_u32_unaligned   bytes_write_u32_unaligned

#include <common.h>

Definition at line 487 of file common.h.

Typedef Documentation

◆ uint16_t

typedef unsigned short uint16_t

#include <common.h>

Definition at line 57 of file common.h.

◆ uint32_t

typedef unsigned int uint32_t

#include <common.h>

Definition at line 58 of file common.h.

◆ uint64_t

typedef unsigned long long uint64_t

#include <common.h>

Definition at line 59 of file common.h.

◆ uint8_t

typedef unsigned char uint8_t

#include <common.h>

Definition at line 56 of file common.h.

Function Documentation

◆ asciichat_fatal_with_context()

void asciichat_fatal_with_context ( asciichat_error_t  code,
const char *  file,
int  line,
const char *  function,
const char *  format,
  ... 
)

#include <common.h>

Exit with error code and context (used by FATAL macro)

Parameters
codeError code (asciichat_error_t)
fileSource file name (can be NULL)
lineLine number (0 if not provided)
functionFunction name (can be NULL)
formatFormat string (printf-style)
...Format arguments

Low-level function used by FATAL() macro. Sets error context and exits the program with the specified error code. In debug builds, prints stack trace before exiting.

Note
This function never returns (terminates program).
In debug builds, prints full error context and stack trace.
Thread-safe: Uses thread-local storage.
Warning
This function terminates the program. Use FATAL() macro instead of calling this directly.

Definition at line 261 of file asciichat_errno.c.

262 {
263 (void)file;
264 (void)line;
265 (void)function;
266
267 // Print library error context if available
269 if (HAS_ERRNO(&err_ctx)) {
270 log_labeled("\nasciichat_errno: libary code error context", LOG_COLOR_ERROR, "");
272 } else {
273 log_plain("WARNING: No error context found (asciichat_errno_context.code=%d)", asciichat_errno_context.code);
274 }
275
276 safe_fprintf(stderr, "\n");
277 log_labeled("FATAL ERROR", LOG_COLOR_FATAL, "exit code %d (%s)", (int)code, asciichat_error_string(code));
278#ifndef NDEBUG
279 const char *relative_file = extract_project_relative_path(file);
280 log_plain(" Location: %s:%d in %s()", relative_file, line, function);
281#endif
282
283 if (format) {
284 va_list args;
285 va_start(args, format);
286 char *formatted_message = format_message(format, args);
287 log_plain(" Error message: %s", formatted_message);
288 SAFE_FREE(formatted_message);
289 va_end(args);
290 }
291
292#ifndef NDEBUG
293 // Always print platform backtrace in debug/dev builds
294 backtrace_t bt = {0};
296 if (bt.count > 0) {
297 backtrace_print("\nFATAL BACKTRACE", &bt, 0, 0, skip_backtrace_frame);
298 backtrace_t_free(&bt);
299 }
300#endif
301
302#ifdef EMSCRIPTEN_BUILD
303 // In WASM builds, do not call exit() — it permanently kills the module runtime.
304 // Instead, set the error and return so callers can handle it gracefully.
305 SET_ERRNO(code, "FATAL (non-exit in WASM): code=%d", (int)code);
306#else
307 exit(code);
308#endif
309}
void backtrace_t_free(backtrace_t *bt)
Free backtrace symbols.
void backtrace_capture_and_symbolize(backtrace_t *bt)
Capture and symbolize in one call.
void backtrace_print(const char *label, const backtrace_t *bt, int skip_frames, int max_frames, backtrace_frame_filter_t filter)
Print backtrace with dual output: colored stderr + plain log file.
#define SAFE_FREE(ptr)
Definition common.h:376
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
#define HAS_ERRNO(var)
Check if an error occurred and get full context.
__thread asciichat_error_context_t asciichat_errno_context
Thread-local error context storage.
void asciichat_print_error_context(const asciichat_error_context_t *context)
Print full error context to stderr.
char * format_message(const char *format, va_list args)
Format a message using va_list.
Definition log/log.c:248
void log_labeled(const char *label, log_color_t color, const char *message,...)
Print a labeled message with color.
#define log_plain(...)
Plain logging - writes to both log file and stderr without timestamps or log levels.
Definition log/log.h:618
@ LOG_COLOR_FATAL
Definition log/log.h:136
@ LOG_COLOR_ERROR
Definition log/log.h:135
int safe_fprintf(FILE *stream, const char *format,...)
Safe formatted output to file stream.
Definition system.c:172
const char * extract_project_relative_path(const char *file)
Extract relative path from an absolute path.
Definition path.c:456
Error context structure.
asciichat_error_t code
Error code (asciichat_error_t enum value)
int count
Number of frames captured.

References args, asciichat_errno_context, asciichat_print_error_context(), backtrace_capture_and_symbolize(), backtrace_print(), backtrace_t_free(), asciichat_error_context_t::code, backtrace_t::count, extract_project_relative_path(), format_message(), HAS_ERRNO, LOG_COLOR_ERROR, LOG_COLOR_FATAL, log_labeled(), log_plain, safe_fprintf(), SAFE_FREE, and SET_ERRNO.

◆ asciichat_shared_destroy()

void asciichat_shared_destroy ( void  )

#include <common.h>

Clean up shared library subsystems.

Performs cleanup of all subsystems initialized by asciichat_shared_init(). All cleanup functions are idempotent and safe to call multiple times.

Applications should typically register this with atexit(): asciichat_shared_init(log_file, is_client); atexit(asciichat_shared_destroy);

Note
This function is safe to call even if init failed or wasn't called.
Cleanup order is the reverse of initialization order.
Library code never calls atexit() - only application code should.

Clean up shared library subsystems.

Performs comprehensive cleanup of all subsystems initialized by asciichat_shared_init(). All cleanup functions are idempotent (safe to call multiple times), so this can be called explicitly and also via atexit() without issues.

Cleanup order is carefully chosen to be the reverse of initialization, ensuring dependencies are respected (e.g., timer cleanup before memory reporting, memory reporting before errno cleanup).

Note
This function is safe to call even if init failed or wasn't called.
All subsystem cleanup functions must remain idempotent.

Definition at line 195 of file common.c.

195 {
196 // Guard against double cleanup (can be called explicitly + via atexit)
197 static bool shutdown_done = false;
198 if (shutdown_done) {
199 return;
200 }
201 shutdown_done = true;
202
204
205 // Cleanup in reverse order of initialization (LIFO)
206 // This ensures dependencies are properly handled
207
208 // 0. Stop background threads first (before any cleanup that might use them)
209 // Terminal resize detection thread (Windows only, checks if active)
211
212#ifndef NDEBUG
213 // Lock debug thread - must join before any lock cleanup
215
216 // Clean up all remaining mutex stacks before memory report
218
219 // Clean up current thread's allocations
221
222 // Memory debug thread - prints memory report (must be last)
223#if defined(DEBUG_MEMORY)
225#endif
226
227 // Lock debug system - set initialized=false so mutex_lock uses mutex_lock_impl directly
228 // This must happen after thread cleanup but before any subsystem that uses mutex_lock
230
231 // Atomic debug cleanup
233#endif
234
235 // 1. Terminal screen - cleanup frame buffer
237
238 // 2. SIMD caches - cleanup CPU-specific caches
240
241 // 3. Discovery service strings cache - cleanup session string cache
243
244 // 4. Logging - in correct order (end first, then begin)
247
248 // 5. Known hosts - cleanup authentication state
250
251 // 6. Options state - cleanup RCU-based options
253
254 // 7. Buffer pool - cleanup global buffer pool
256
257 // 8. Platform cleanup - restores terminal, cleans up platform resources
258 // (includes symbol cache cleanup on Windows)
260
261 // 9. Keyboard - restore terminal settings (redundant with platform_destroy but safe)
263
264 // 10. Timer system - cleanup timers (may still log!)
266
267 // 11. Error context cleanup
269
270 // 12. Logging cleanup - free log format buffers and system state
271 log_destroy();
273
274 // 13. Mutex stack cleanup - must be before memory report so stacks are freed
275#ifndef NDEBUG
277 // Final cleanup: free the main thread's debug allocations
279#endif
280
281 // 14. Memory stats (debug builds only) - runs with colors still available
282 // Note: PCRE2 singletons are cleaned up later via atexit handler (runs after this function)
283 // This ensures code can still use PCRE2 during normal program shutdown
284 // Note: debug_memory_report() is also called manually during shutdown in server_main()
285 // The function is safe to call multiple times with polling-based locking
286#if defined(USE_MIMALLOC_DEBUG) && !defined(NDEBUG)
287 print_mimalloc_stats();
288#endif
289
290#if defined(DEBUG_MEMORY) && !defined(NDEBUG)
292#endif
293
294 // 15. Color cleanup - free compiled ANSI strings (AFTER memory report)
297
298 // 16. Clean up binary path cache explicitly
299 // Note: This is also called by platform_destroy() via atexit(), but it's idempotent
301
302 // 17. Clean up RCU-based options state
304
305 // 18. Clean up errno context (allocated strings, backtrace symbols)
307
308#ifndef NDEBUG
309 // 19. Named registry - cleanup all registered thread names and debug entries
310 // Must come BEFORE PCRE2 cleanup since named_destroy() uses path normalization which needs PCRE2
312#endif
313
314 // 20. PCRE2 - cleanup all regex singletons together (after named_destroy)
316
317 // 21. timer resolution restore
318 platform_restore_timer_resolution(); // Restore timer resolution (no-op on POSIX)
319
320 // 22. Clean up SIMD caches
322
323 // 23. Clean up symbol cache
324 // This must be called BEFORE log_destroy() as symbol_cache_destroy() uses log_debug()
325 // Safe to call even if atexit() runs - it's idempotent (checks g_symbol_cache_initialized)
326 // Also called via platform_destroy() atexit handler, but explicit call ensures proper ordering
328
329 // 24. Clean up global buffer pool (explicitly, as atexit may not run on Ctrl-C)
330 // Note: This is also registered with atexit(), but calling it explicitly is safe (idempotent)
331 // Safe to call even if atexit() runs - it checks g_global_buffer_pool and sets it to NULL
333
334#ifndef NDEBUG
335 // 25. Symbol cache cleanup
337#endif
338}
void colorscheme_destroy(void)
Shutdown the color system.
void debug_atomic_shutdown(void)
Lifecycle shutdown for debug atomic tracking.
void debug_memory_thread_cleanup(void)
void debug_memory_report(void)
void mutex_stack_cleanup(void)
Cleanup mutex stack system.
void acds_strings_destroy(void)
Cleanup function for session string cache Called by asciichat_shared_destroy() during library cleanup...
void buffer_pool_cleanup_global(void)
void known_hosts_destroy(void)
Cleanup function to free cached known_hosts path.
void named_destroy(void)
Destroy the named object registry.
void debug_sync_destroy(void)
Destroy debug synchronization system.
Definition sync.c:670
void debug_sync_final_cleanup(void)
Final cleanup of all debug allocations at shutdown.
Definition sync.c:595
void debug_sync_cleanup_thread(void)
Stop and clean up background debug thread.
Definition sync.c:674
void asciichat_errno_destroy(void)
Cleanup error system resources.
void log_shutdown_end(void)
End shutdown phase - restore previous logging settings.
Definition log/log.c:1806
void log_destroy(void)
Destroy the logging system and close log file.
Definition log/log.c:624
void log_cleanup_colors(void)
Clean up compiled color scheme.
Definition log/log.c:1822
void log_shutdown_begin(void)
Begin shutdown phase - disable console logging but keep file logging.
Definition log/log.c:1795
void log_system_destroy(void)
Shutdown the logging system internal state (system-level cleanup)
Definition log/log.c:686
void timer_system_destroy(void)
Cleanup the timing system.
Definition util/time.c:213
void platform_destroy(void)
Cleanup platform-specific subsystems.
void keyboard_destroy(void)
Cleanup keyboard input system and restore terminal.
void symbol_cache_destroy(void)
Clean up the symbol cache and free all resources.
Definition symbols.c:316
asciichat_error_t platform_restore_timer_resolution(void)
Restore default timer precision.
Definition misc.c:99
void platform_cleanup_binary_path_cache(void)
Cleanup the binary PATH cache.
Definition filesystem.c:113
void simd_caches_destroy_all(void)
Destroy all SIMD caches (palette and other caches)
void terminal_stop_resize_detection(void)
No-op stub on POSIX platforms (no resize detection thread)
Definition misc.c:91
void asciichat_pcre2_cleanup_all(void)
Free all PCRE2 singletons in the global registry.
Definition pcre2.c:214
void options_state_destroy(void)
Shutdown RCU options system.
Definition rcu.c:461
void terminal_screen_cleanup(void)
Clean up terminal screen resources.

References acds_strings_destroy(), asciichat_errno_destroy(), asciichat_pcre2_cleanup_all(), buffer_pool_cleanup_global(), colorscheme_destroy(), debug_atomic_shutdown(), debug_memory_report(), debug_memory_thread_cleanup(), debug_sync_cleanup_thread(), debug_sync_destroy(), debug_sync_final_cleanup(), keyboard_destroy(), known_hosts_destroy(), log_cleanup_colors(), log_destroy(), log_shutdown_begin(), log_shutdown_end(), log_system_destroy(), mutex_stack_cleanup(), named_destroy(), options_state_destroy(), platform_cleanup_binary_path_cache(), platform_destroy(), platform_restore_timer_resolution(), simd_caches_destroy_all(), symbol_cache_destroy(), terminal_screen_cleanup(), terminal_stop_resize_detection(), and timer_system_destroy().

Referenced by client_main(), and main().

◆ asciichat_shared_init()

asciichat_error_t asciichat_shared_init ( const char *  log_file,
bool  is_client,
bool  quiet_startup 
)

#include <common.h>

Initialize common subsystems shared by client and server.

This function performs initialization that is common to both client and server modes:

  • Platform initialization (Winsock, etc.)
  • Logging setup with default filename
  • Palette configuration
  • Buffer pool initialization
  • Cleanup registration (errno, known_hosts, platform, buffer pool)
  • Mimalloc debug registration (if enabled)

Note: Memory debugging setup is handled separately by each mode due to different requirements (client has snapshot mode, server doesn't).

Call this BEFORE options_init() so that options parsing can use properly configured logging with colors. This initializes timer system, logging, and platform subsystems.

Parameters
log_fileLog filename to use (e.g., "client.log" or "ascii-chat.log")
is_clienttrue for client mode (routes all logs to stderr), false for server mode
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 115 of file common.c.

115 {
116 // Initialize shared subsystems BEFORE options_init()
117 // This allows options_init() to use properly configured logging with colors
118 //
119 // NOTE: This function is called BEFORE options_init(), so we can't use GET_OPTION()
120 // Palette config and quiet mode will be applied after options_init() is called
121
122 // Only register initialization tracking once
123 if (!g_shared_initialized) {
124 // 1. TIMER SYSTEM - Initialize first so timing is available for everything else
125 if (!timer_system_init()) {
126 FATAL(ERROR_PLATFORM_INIT, "Failed to initialize timer system");
127 }
128
129 // KEYBOARD SYSTEM must be initialized BEFORE logging since keyboard_init() calls log_info()
130 // But we need to initialize logging AFTER timer_system_init() and BEFORE keyboard_init()
131 // So we move keyboard_init() to AFTER log_init()
132
133#ifndef NDEBUG
134 if (named_init() != ASCIICHAT_OK) {
135 return SET_ERRNO(ERROR_PLATFORM_INIT, "Failed to initialize named.");
136 }
139#endif
140
141 // 2. LOGGING - Initialize system state first, then user-level logging
142 // Initialize logging system internal state (terminal caps, colors)
144
145 // Initialize with provided log file
146 // Force stderr for client-like modes when stdout is piped to keep stdout clean
147 bool force_stderr = is_client && terminal_is_piped_output();
148
149 if (quiet_startup) {
151 }
152
153 // Use LOG_DEBUG by default; will be reconfigured after options_init()
154 log_init(log_file, LOG_DEBUG, force_stderr, false /* don't use_mmap */);
155
156 // 2. KEYBOARD SYSTEM - Initialize keyboard input AFTER logging (may fail if stdin/tty not available)
157 // Failure is not fatal - keyboard_read_nonblocking() safely handles uninitialized state
159
160 // 3. PLATFORM - Initialize platform-specific functionality (Winsock, etc)
161 if (platform_init() != ASCIICHAT_OK) {
162 FATAL(ERROR_PLATFORM_INIT, "Failed to initialize platform");
163 }
164
165 // 4. BUFFER POOL - Initialize global shared buffer pool
167
168 // Mark that we've initialized (prevents re-registration of subsystems)
169 g_shared_initialized = true;
170 }
171
172 // NOTE: This library function does NOT register atexit() handlers.
173 // Library code should not own the process lifecycle. The application
174 // is responsible for calling atexit(asciichat_shared_destroy) if it
175 // wants automatic cleanup on normal exit.
176
177 return ASCIICHAT_OK;
178}
void buffer_pool_init_global(void)
asciichat_error_t named_init(void)
Initialize the named object registry.
Definition debug/named.c:89
void debug_memory_ensure_init(void)
Init the lifecycle of the debug memory module.
@ ERROR_PLATFORM_INIT
Definition error_codes.h:60
void log_system_init(void)
Initialize the logging system internal state (system-level init)
Definition log/log.c:669
void log_init(const char *filename, log_level_t level, bool force_stderr, bool use_mmap)
Initialize the logging system.
Definition log/log.c:533
#define log_file(...)
File-only logging - writes to log file only, no stderr output.
Definition log/log.h:646
void log_set_terminal_output(bool enabled)
Control stderr output to terminal.
Definition log/log.c:700
bool timer_system_init(void)
Initialize the timing system.
Definition util/time.c:191
asciichat_error_t keyboard_init(void)
Initialize keyboard input system.
asciichat_error_t symbol_cache_init(void)
Initialize the symbol cache.
Definition symbols.c:291
asciichat_error_t platform_init(void)
Initialize platform-specific subsystems.
bool terminal_is_piped_output(void)
Check if stdout is piped or redirected.
#define LOG_DEBUG
Definition types.h:39

References ASCIICHAT_OK, buffer_pool_init_global(), debug_memory_ensure_init(), ERROR_PLATFORM_INIT, FATAL, keyboard_init(), LOG_DEBUG, log_file, log_init(), log_set_terminal_output(), log_system_init(), named_init(), platform_init(), SET_ERRNO, symbol_cache_init(), terminal_is_piped_output(), and timer_system_init().

Referenced by main().

◆ fps_frame_ns()

void fps_frame_ns ( fps_t *  tracker,
uint64_t  current_time_ns,
const char *  context 
)

#include <fps.h>

Track a frame and detect lag conditions (nanosecond version - PRIMARY)

Call this function when a frame is processed. Automatically detects when frames arrive late and generates periodic FPS reports every report_interval_ns. This is the primary API that all code should use going forward.

Parameters
trackerFPS tracker state
current_time_nsTimestamp of this frame in nanoseconds (from time_get_ns())
contextOptional context string for lag logging (e.g., "ASCII frame received")

Example usage:

fps_t tracker;
fps_init(&tracker, 60, "RENDER");
// In your frame loop
fps_frame_ns(&tracker, now, "frame rendered");
void fps_frame_ns(fps_t *tracker, uint64_t current_time_ns, const char *context)
Track a frame and detect lag conditions (nanosecond version - PRIMARY)
Definition fps.c:52

Definition at line 52 of file fps.c.

52 {
53 if (!tracker) {
54 return;
55 }
56
57 // Initialize on first frame
58 if (tracker->last_fps_report_ns == 0) {
59 tracker->last_fps_report_ns = current_time_ns;
60 tracker->last_frame_time_ns = current_time_ns;
61 }
62
63 tracker->frame_count++;
64
65 // Calculate time since last frame in nanoseconds
66 uint64_t frame_interval_ns = time_elapsed_ns(tracker->last_frame_time_ns, current_time_ns);
67 tracker->last_frame_time_ns = current_time_ns;
68
69 // Expected frame interval in nanoseconds
70 // For 60 FPS: 1 second / 60 = 16,666,666 ns per frame
71 uint64_t expected_interval_ns = NS_PER_SEC_INT / (uint64_t)tracker->expected_fps;
72 uint64_t lag_threshold_ns = expected_interval_ns + (expected_interval_ns / 2); // 50% over expected
73
74 // Log error if frame arrived too late (only after first frame)
75 if (tracker->frame_count > 1 && frame_interval_ns > lag_threshold_ns) {
76 const char *context_str = context ? context : "Frame";
77
78 // Convert to milliseconds for display (but calculations stay in nanoseconds)
79 double late_ms = time_ns_to_us(frame_interval_ns - expected_interval_ns) / 1000.0;
80 double expected_ms = time_ns_to_us(expected_interval_ns) / 1000.0;
81 double actual_ms = time_ns_to_us(frame_interval_ns) / 1000.0;
82 double actual_fps = 1e9 / (double)frame_interval_ns;
83
84 log_lag_event(tracker->tracker_name, context_str, late_ms, expected_ms, actual_ms, actual_fps);
85 }
86
87 // Report FPS every report_interval_ns
88 uint64_t elapsed_ns = time_elapsed_ns(tracker->last_fps_report_ns, current_time_ns);
89
90 if (elapsed_ns >= tracker->report_interval_ns) {
91 double elapsed_seconds = time_ns_to_s(elapsed_ns);
92 double actual_fps = (double)tracker->frame_count / elapsed_seconds;
93 log_fps_report(tracker->tracker_name, actual_fps, tracker->frame_count, elapsed_seconds);
94
95 // Reset counters for next interval
96 tracker->frame_count = 0;
97 tracker->last_fps_report_ns = current_time_ns;
98 }
99}
#define NS_PER_SEC_INT
Definition time.h:157
uint64_t time_elapsed_ns(uint64_t start_ns, uint64_t end_ns)
Calculate elapsed time with wraparound safety.
Definition util/time.c:150
const char * tracker_name
Definition fps.h:58
uint64_t frame_count
Definition fps.h:53
uint64_t report_interval_ns
Definition fps.h:57
uint64_t last_frame_time_ns
Definition fps.h:55
int expected_fps
Definition fps.h:56
uint64_t last_fps_report_ns
Definition fps.h:54

References fps_t::expected_fps, fps_t::frame_count, fps_t::last_fps_report_ns, fps_t::last_frame_time_ns, NS_PER_SEC_INT, fps_t::report_interval_ns, time_elapsed_ns(), and fps_t::tracker_name.

Referenced by client_audio_render_thread(), client_video_render_thread(), and session_capture_read_frame().

◆ fps_init()

void fps_init ( fps_t *  tracker,
int  expected_fps,
const char *  name 
)

#include <fps.h>

Initialize FPS tracker.

Sets up the tracker with expected FPS and default reporting interval (10 seconds). Should be called once before using the tracker.

Parameters
trackerPointer to uninitialized fps_t (should be zero-initialized)
expected_fpsExpected frame rate in FPS (e.g., 60, 30, 20)
nameDisplay name for logging (e.g., "CLIENT", "WEBCAM", "AUDIO", "KEEPALIVE")

Definition at line 32 of file fps.c.

32 {
33 // Default report interval: 1 second
34 fps_init_with_interval(tracker, expected_fps, name, 1 * NS_PER_SEC_INT);
35}
void fps_init_with_interval(fps_t *tracker, int expected_fps, const char *name, uint64_t report_interval_ns)
Initialize FPS tracker with custom report interval.
Definition fps.c:37

References fps_init_with_interval(), and NS_PER_SEC_INT.

Referenced by client_audio_render_thread(), client_video_render_thread(), session_capture_create(), and session_network_capture_create().

◆ fps_init_with_interval()

void fps_init_with_interval ( fps_t *  tracker,
int  expected_fps,
const char *  name,
uint64_t  report_interval_ns 
)

#include <fps.h>

Initialize FPS tracker with custom report interval.

Sets up the tracker with expected FPS and custom reporting interval in nanoseconds. Useful for different threads that may need different reporting frequencies.

Parameters
trackerPointer to uninitialized fps_t (should be zero-initialized)
expected_fpsExpected frame rate in FPS
nameDisplay name for logging
report_interval_nsCustom report interval in nanoseconds (e.g., 10000000000 = 10 seconds)

Definition at line 37 of file fps.c.

37 {
38 if (!tracker) {
39 return;
40 }
41
42 tracker->frame_count = 0;
43 tracker->expected_fps = expected_fps > 0 ? expected_fps : 60;
44 tracker->tracker_name = name ? name : "FPS";
45 tracker->report_interval_ns = report_interval_ns;
46
47 // Initialize timestamps to zero (will be set on first frame)
48 tracker->last_fps_report_ns = 0;
49 tracker->last_frame_time_ns = 0;
50}

References fps_t::expected_fps, fps_t::frame_count, fps_t::last_fps_report_ns, fps_t::last_frame_time_ns, fps_t::report_interval_ns, and fps_t::tracker_name.

Referenced by fps_init().

Variable Documentation

◆ g_argc

int g_argc
extern

#include <common.h>

Global argc for early argument inspection (e.g., –color flag detection) Set by main() for access from lib/platform/terminal.c during early execution.

Definition at line 53 of file common.c.

Referenced by main(), and terminal_should_color_output().

◆ g_argv

char** g_argv
extern

#include <common.h>

Global argv for early argument inspection (e.g., –color flag detection) Set by main() for access from lib/platform/terminal.c during early execution.

Definition at line 54 of file common.c.

Referenced by main(), and terminal_should_color_output().

◆ g_color_flag_passed

bool g_color_flag_passed
extern

#include <common.h>

Was –color explicitly passed in command-line arguments? Set by options_init() before RCU is initialized, used by terminal_should_color_output()

Definition at line 57 of file common.c.

Referenced by colored_string(), log_msg(), and main().

◆ g_color_flag_value

bool g_color_flag_value
extern

#include <common.h>

Value of –color flag (true if –color was in argv) Set by options_init() before RCU is initialized, used by terminal_should_color_output()

Definition at line 58 of file common.c.

Referenced by colored_string(), log_msg(), and main().