From a97fa4e6d2a79b720dd906c8924d5370f155d4e9 Mon Sep 17 00:00:00 2001 From: Epochryphon Date: Sun, 28 Jun 2026 08:45:41 -0500 Subject: [PATCH] initial commit --- README.md | 2 +- source_code/new_log.c | 295 ++++++++++++++++++++++++++++++++++++++++++ source_code/new_log.h | 89 +++++++++++++ src/log.c | 168 ------------------------ src/log.h | 49 ------- 5 files changed, 385 insertions(+), 218 deletions(-) create mode 100644 source_code/new_log.c create mode 100644 source_code/new_log.h delete mode 100644 src/log.c delete mode 100644 src/log.h diff --git a/README.md b/README.md index a8756e9..6ae883d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ function-like macros for logging: log_trace(const char *fmt, ...); log_debug(const char *fmt, ...); log_info(const char *fmt, ...); -log_warn(const char *fmt, ...); +log_warning(const char *fmt, ...); log_error(const char *fmt, ...); log_fatal(const char *fmt, ...); ``` diff --git a/source_code/new_log.c b/source_code/new_log.c new file mode 100644 index 0000000..79ed130 --- /dev/null +++ b/source_code/new_log.c @@ -0,0 +1,295 @@ +/* + * Original work Copyright (c) 2020 rxi (MIT License) + * + * ORIGINAL: + * Copyright (c) 2020 rxi + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * + * Modified work Copyright (c) 2026 Emilia Marigold (AGPLv3) + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * See the LICENSE file for the full AGPLv3 terms and conditions. + ***/ + +#include "new_log.h" + +#define MAX_CALLBACKS 32 + +typedef +struct callback_struct +{ + log_function function; + void *user_data; + int severity_level; +} +callback_type; + +static struct global_log_data_struct +{ + void *user_data; + lock_function lock; + int severity_level; + bool quiet; + callback_type callbacks[MAX_CALLBACKS]; +} global_log_data_struct; + + +static const char * +level_strings[] = +{ + "TRACE", + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "FATAL" +}; + +#ifdef LOG_USE_COLOR +static const char *level_colors[] = +{ + "\x1b[94m", + "\x1b[36m", + "\x1b[32m", + "\x1b[33m", + "\x1b[31m", + "\x1b[35m" +}; +#endif + + +static void +stdout_callback(log_event_type *event) +{ + char buffer[16]; + buffer[strftime(buffer, + sizeof(buffer), + "%H:%M:%S", + event->local_time)] = '\0'; + + #ifdef LOG_USE_COLOR + fprintf(event->user_data, + "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", + buffer, + level_colors[event->severity_level], + level_strings[event->severity_level], + event->file, + event->line); + #else + fprintf(event->user_data, + "%s %-5s %s:%d: ", + buffer, + level_strings[event->severity_level], + event->file, + event->line); + #endif + + vfprintf(event->user_data, + event->format, + event->argument_pointer); + + fprintf(event->user_data, + "\n"); + + fflush(event->user_data); +} + + +static void +file_callback(log_event_type *event) +{ + char buffer[64]; + buffer[strftime(buffer, + sizeof(buffer), + "%Y-%m-%d %H:%M:%S", + event->local_time)] = '\0'; + + fprintf(event->user_data, + "%s %-5s %s:%d: ", + buffer, + level_strings[event->severity_level], + event->file, + event->line); + + vfprintf(event->user_data, + event->format, + event->argument_pointer); + + fprintf(event->user_data, + "\n"); + + fflush(event->user_data); +} + + +static void +lock(void) +{ + if (global_log_data_struct.lock) + { + global_log_data_struct.lock(true, + global_log_data_struct.user_data); + } +} + + +static void +unlock(void) +{ + if (global_log_data_struct.lock) + { + global_log_data_struct.lock(false, + global_log_data_struct.user_data); + } +} + + +const char* +log_level_string(int severity_level) +{ + return level_strings[severity_level]; +} + + +void +log_set_lock(lock_function function, + void *user_data) +{ + global_log_data_struct.lock = function; + global_log_data_struct.user_data = user_data; +} + + +void +log_set_level(int severity_level) +{ + global_log_data_struct.severity_level = severity_level; +} + + +void +log_set_quiet(bool should_be_quiet) +{ + global_log_data_struct.quiet = should_be_quiet; +} + + +int +log_add_callback(log_function function, + void *user_data, + int level) +{ + for (int i = 0; i < MAX_CALLBACKS; i++) + { + if (global_log_data_struct.callbacks[i].function) + { + continue; + } + + global_log_data_struct.callbacks[i] = (callback_type) + { + function, + user_data, + level + }; + return 0; + } + return -1; +} + + +int +log_add_file_pointer(FILE *file_pointer, + int level) +{ + return log_add_callback(file_callback, + file_pointer, + level); +} + + +static void +init_event(log_event_type *event, + void *user_data) +{ + if (!event->local_time) + { + time_t timer = time(NULL); + event->local_time = localtime(&timer); + } + event->user_data = user_data; +} + + +void +log_log(int severity_level, + const char *file, + int line, + const char *format, + ...) +{ + log_event_type event = + { + .format = format, + .file = file, + .line = line, + .severity_level = severity_level, + }; + + lock(); + + if (!global_log_data_struct.quiet + && severity_level >= global_log_data_struct.severity_level) + { + init_event(&event, + stderr); + + va_start(event.argument_pointer, + format); + + stdout_callback(&event); + va_end(event.argument_pointer); + } + + for (int i = 0; i < MAX_CALLBACKS + && global_log_data_struct.callbacks[i].function; + i++) + { + callback_type *callback_pointer = &global_log_data_struct.callbacks[i]; + if (severity_level >= callback_pointer->severity_level) + { + init_event(&event, + callback_pointer->user_data); + + va_start(event.argument_pointer, + format); + + callback_pointer->function(&event); + va_end(event.argument_pointer); + } + } + + unlock(); +} diff --git a/source_code/new_log.h b/source_code/new_log.h new file mode 100644 index 0000000..84c5413 --- /dev/null +++ b/source_code/new_log.h @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2020 rxi + * + * Original library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See `log.c` for details. + * + * Modified work Copyright (c) 2026 Emilia Marigold. + * New changes licensed under the AGPLv3 license. + */ + +#ifndef LOG_H +#define LOG_H + +#include +#include +#include +#include + +#define LOG_VERSION "r:180.26.1" + +typedef +struct log_event_struct +{ + va_list argument_pointer; + const char *format; + const char *file; + struct tm *local_time; + void *user_data; + int line; + int severity_level; +} +log_event_type; + +typedef +void +(*log_function)(log_event_type *event); + +typedef +void +(*lock_function)(bool lock, + void *user_data); + +enum +{ + LOG_TRACE_ENUM = 0, + LOG_DEBUG_ENUM, + LOG_INFO_ENUM, + LOG_WARNING_ENUM, + LOG_ERROR_ENUM, + LOG_FATAL_ENUM +}; + +#define log_trace(...) log_log(LOG_TRACE_ENUM, __FILE__, __LINE__, __VA_ARGS__) +#define log_debug(...) log_log(LOG_DEBUG_ENUM, __FILE__, __LINE__, __VA_ARGS__) +#define log_info(...) log_log(LOG_INFO_ENUM, __FILE__, __LINE__, __VA_ARGS__) +#define log_warning(...) log_log(LOG_WARNING_ENUM, __FILE__, __LINE__, __VA_ARGS__) +#define log_error(...) log_log(LOG_ERROR_ENUM, __FILE__, __LINE__, __VA_ARGS__) +#define log_fatal(...) log_log(LOG_FATAL_ENUM, __FILE__, __LINE__, __VA_ARGS__) + +const char* +log_level_string(int severity_level); + +void +log_set_lock(lock_function function, + void *user_data); + +void +log_set_level(int severity_level); + +void +log_set_quiet(bool should_be_quiet); + +int +log_add_callback(log_function function, + void *user_data, + int severity_level); + +int +log_add_file_pointer(FILE *file_pointer, + int severity_level); + +void +log_log(int severity_level, + const char *file, + int line, + const char *format, + ...); + +#endif diff --git a/src/log.c b/src/log.c deleted file mode 100644 index 1a7626e..0000000 --- a/src/log.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2020 rxi - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "log.h" - -#define MAX_CALLBACKS 32 - -typedef struct { - log_LogFn fn; - void *udata; - int level; -} Callback; - -static struct { - void *udata; - log_LockFn lock; - int level; - bool quiet; - Callback callbacks[MAX_CALLBACKS]; -} L; - - -static const char *level_strings[] = { - "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" -}; - -#ifdef LOG_USE_COLOR -static const char *level_colors[] = { - "\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m" -}; -#endif - - -static void stdout_callback(log_Event *ev) { - char buf[16]; - buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0'; -#ifdef LOG_USE_COLOR - fprintf( - ev->udata, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", - buf, level_colors[ev->level], level_strings[ev->level], - ev->file, ev->line); -#else - fprintf( - ev->udata, "%s %-5s %s:%d: ", - buf, level_strings[ev->level], ev->file, ev->line); -#endif - vfprintf(ev->udata, ev->fmt, ev->ap); - fprintf(ev->udata, "\n"); - fflush(ev->udata); -} - - -static void file_callback(log_Event *ev) { - char buf[64]; - buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0'; - fprintf( - ev->udata, "%s %-5s %s:%d: ", - buf, level_strings[ev->level], ev->file, ev->line); - vfprintf(ev->udata, ev->fmt, ev->ap); - fprintf(ev->udata, "\n"); - fflush(ev->udata); -} - - -static void lock(void) { - if (L.lock) { L.lock(true, L.udata); } -} - - -static void unlock(void) { - if (L.lock) { L.lock(false, L.udata); } -} - - -const char* log_level_string(int level) { - return level_strings[level]; -} - - -void log_set_lock(log_LockFn fn, void *udata) { - L.lock = fn; - L.udata = udata; -} - - -void log_set_level(int level) { - L.level = level; -} - - -void log_set_quiet(bool enable) { - L.quiet = enable; -} - - -int log_add_callback(log_LogFn fn, void *udata, int level) { - for (int i = 0; i < MAX_CALLBACKS; i++) { - if (!L.callbacks[i].fn) { - L.callbacks[i] = (Callback) { fn, udata, level }; - return 0; - } - } - return -1; -} - - -int log_add_fp(FILE *fp, int level) { - return log_add_callback(file_callback, fp, level); -} - - -static void init_event(log_Event *ev, void *udata) { - if (!ev->time) { - time_t t = time(NULL); - ev->time = localtime(&t); - } - ev->udata = udata; -} - - -void log_log(int level, const char *file, int line, const char *fmt, ...) { - log_Event ev = { - .fmt = fmt, - .file = file, - .line = line, - .level = level, - }; - - lock(); - - if (!L.quiet && level >= L.level) { - init_event(&ev, stderr); - va_start(ev.ap, fmt); - stdout_callback(&ev); - va_end(ev.ap); - } - - for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) { - Callback *cb = &L.callbacks[i]; - if (level >= cb->level) { - init_event(&ev, cb->udata); - va_start(ev.ap, fmt); - cb->fn(&ev); - va_end(ev.ap); - } - } - - unlock(); -} diff --git a/src/log.h b/src/log.h deleted file mode 100644 index b1fae24..0000000 --- a/src/log.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2020 rxi - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the MIT license. See `log.c` for details. - */ - -#ifndef LOG_H -#define LOG_H - -#include -#include -#include -#include - -#define LOG_VERSION "0.1.0" - -typedef struct { - va_list ap; - const char *fmt; - const char *file; - struct tm *time; - void *udata; - int line; - int level; -} log_Event; - -typedef void (*log_LogFn)(log_Event *ev); -typedef void (*log_LockFn)(bool lock, void *udata); - -enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL }; - -#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__) -#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) -#define log_info(...) log_log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__) -#define log_warn(...) log_log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__) -#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__) -#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__) - -const char* log_level_string(int level); -void log_set_lock(log_LockFn fn, void *udata); -void log_set_level(int level); -void log_set_quiet(bool enable); -int log_add_callback(log_LogFn fn, void *udata, int level); -int log_add_fp(FILE *fp, int level); - -void log_log(int level, const char *file, int line, const char *fmt, ...); - -#endif