diff options
| author | Vasco <[email protected]> | 2026-08-23 02:25:33 +0100 |
|---|---|---|
| committer | Vasco <[email protected]> | 2026-08-23 02:25:33 +0100 |
| commit | dc96fcd771bea09d726a760266739906e95c09a6 (patch) | |
| tree | 5af4d4d7660a90a04016fae4defec3c2a422477d /Podium/p_log.h | |
Peak 0.1.1
Diffstat (limited to 'Podium/p_log.h')
| -rw-r--r-- | Podium/p_log.h | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/Podium/p_log.h b/Podium/p_log.h new file mode 100644 index 0000000..0f6ce6c --- /dev/null +++ b/Podium/p_log.h @@ -0,0 +1,186 @@ +/* + * Logging! + */ + +#include <stdlib.h> + +#ifdef DEBUG +#define LOG_DEBUG(...) PRINTF(__VA_ARGS__) +#else +#define LOG_DEBUG(...) ((void)0) +#endif + +/* fatal and error always enabled */ +#define PFATAL(message, ...) p_log_printf(P_LOG_LEVEL_FATAL, message, ##__VA_ARGS__) +#define PERROR(message, ...) p_log_printf(P_LOG_LEVEL_ERROR, message, ##__VA_ARGS__) + +/* warn and info enabled by default but can be disabled */ +#define P_LOG_WARN_ENABLED 1 +#define P_LOG_INFO_ENABLED 1 + +#if P_LOG_WARN_ENABLED == 1 +#define PWARN(message, ...) p_log_printf(P_LOG_LEVEL_WARN, message, ##__VA_ARGS__) +#else +#define PWARN(message, ...) +#endif + +#if P_LOG_INFO_ENABLED == 1 +#define PINFO(message, ...) p_log_printf(P_LOG_LEVEL_INFO, message, ##__VA_ARGS__) +#else +#define PINFO(message, ...) +#endif + +#if P_LOG_DEBUG_ENABLED == 1 +#define PDEBUG(message, ...) p_log_printf(P_LOG_LEVEL_DEBUG, message, ##__VA_ARGS__) +#else +#define PDEBUG(message, ...) +#endif + +#if P_LOG_TRACE_ENABLED == 1 +#define PTRACE(message, ...) p_log_printf(P_LOG_LEVEL_TRACE, message, ##__VA_ARGS__) +#else +#define PTRACE(message, ...) +#endif + +typedef enum P_Log_Level { + P_LOG_LEVEL_FATAL = 0, + P_LOG_LEVEL_ERROR, + P_LOG_LEVEL_WARN, + P_LOG_LEVEL_INFO, + P_LOG_LEVEL_DEBUG, + P_LOG_LEVEL_TRACE, + P_COUNT_LOG_LEVEL +} P_Log_Level; + +#define P_PREFIX_LEN 7 +static const char *p_prefix[P_COUNT_LOG_LEVEL] = { + [P_LOG_LEVEL_FATAL] = "[FATAL]", + [P_LOG_LEVEL_ERROR] = "[ERROR]", + [P_LOG_LEVEL_WARN] = "[WARNI]", + [P_LOG_LEVEL_INFO] = "[INFOR]", + [P_LOG_LEVEL_DEBUG] = "[DEBUG]", + [P_LOG_LEVEL_TRACE] = "[TRACE]", +}; + +#define P_MAX_ALLOCS 512 + +typedef struct P_DebugMemoryInfo { + void *ptr; + size_t size; + const char *file; + const char *func; + int line; +} P_DebugMemoryInfo; + +static uint64_t p_alloc_count = 0; +static P_DebugMemoryInfo p_ptr_array[P_MAX_ALLOCS]; + +static inline void * +p_debug_malloc_impl(size_t size, const char *file, int line, const char *func) +{ + void *ptr = malloc(size); + printf("[ALLOC] %p (%zu bytes) -> %s:%d %s()\n", ptr, size, file, line, func); + + if (ptr) { + if (p_alloc_count < P_MAX_ALLOCS) { + p_ptr_array[p_alloc_count++] = (P_DebugMemoryInfo){ + .ptr = ptr, + .size = size, + .file = file, + .func = func, + .line = line + }; + } else { + fprintf(stderr, "[ERROR] Debug allocator tracking capacity (%d) exceeded!\n", P_MAX_ALLOCS); + } + } + return ptr; +} + +static inline void +p_debug_free_impl(void *ptr, const char *file, int line, const char *func) +{ + printf("[FREE] %p -> %s:%d %s()\n", ptr, file, line, func); + + if (!ptr) return; // Standard C allows free(NULL) + + bool found = false; + uint64_t index = 0; + + /* Find allocation metadata */ + for (index = 0; index < p_alloc_count; ++index) { + if (p_ptr_array[index].ptr == ptr) { + found = true; + break; + } + } + + if (found) { + /* Shift array left to remove tracked struct */ + for (uint64_t j = index; j < p_alloc_count - 1; ++j) { + p_ptr_array[j] = p_ptr_array[j + 1]; + } + p_alloc_count--; + } else { + fprintf(stderr, "[WARNING] Attempted to free untracked/double-freed pointer %p at %s:%d %s()\n", + ptr, file, line, func); + } + + free(ptr); +} + +static inline void * +p_debug_realloc_impl(void *ptr, size_t size, const char *file, int line, const char *func) +{ + if (!ptr) { + return p_debug_malloc_impl(size, file, line, func); + } + if (size == 0) { + p_debug_free_impl(ptr, file, line, func); + return NULL; + } + + void *new_ptr = realloc(ptr, size); + printf("[REALLOC] %p -> %p (%zu bytes) -> %s:%d %s()\n", ptr, new_ptr, size, file, line, func); + + if (new_ptr) { + bool found = false; + for (uint64_t i = 0; i < p_alloc_count; ++i) { + if (p_ptr_array[i].ptr == ptr) { + p_ptr_array[i].ptr = new_ptr; + p_ptr_array[i].size = size; + p_ptr_array[i].file = file; + p_ptr_array[i].line = line; + p_ptr_array[i].func = func; + found = true; + break; + } + } + if (!found) { + if (p_alloc_count < P_MAX_ALLOCS) { + p_ptr_array[p_alloc_count++] = (P_DebugMemoryInfo){ + .ptr = new_ptr, + .size = size, + .file = file, + .func = func, + .line = line + }; + } + } + } + return new_ptr; +} + +static void +p_debug_memory_report(void) +{ + printf("\n==================== MEMORY REPORT ====================\n"); + printf("Remaining unfreed allocations: %lu\n", (unsigned long)p_alloc_count); + + for (uint64_t i = 0; i < p_alloc_count; ++i) { + P_DebugMemoryInfo *info = &p_ptr_array[i]; + printf("[LEAK] %p (%zu bytes) allocated at %s:%d in %s()\n", + info->ptr, info->size, info->file, info->line, info->func); + } + printf("=======================================================\n"); +} |
