├── package.json ├── CHANGELOG.md ├── README.md ├── clog.h └── clog.c /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clog", 3 | "version": "0.1.0", 4 | "repo": "aperezdc/clog", 5 | "description": "Non-allocating runtime configurable logger", 6 | "license": "MIT", 7 | "keywords": ["log", "logging", "debug"], 8 | "src": ["clog.h", "clog.c"] 9 | } 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.1.0] - 2020-08-19 11 | 12 | Initial release. 13 | 14 | [Unreleased]: https://github.com/aperezdc/clog/compare/0.1.0...HEAD 15 | [0.1.0]: https://github.com/aperezdc/clog/releases/tag/0.1.0 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | clog 2 | ==== 3 | 4 | Installation 5 | ------------ 6 | 7 | With [clib](https://github.com/clibs/clib): 8 | 9 | ```sh 10 | clib install aperezdc/clog 11 | ``` 12 | 13 | Exmple 14 | ------ 15 | 16 | ```c 17 | #define CLOG_SHORT_MACROS 1 18 | 19 | #include "clog.h" 20 | 21 | int 22 | main(int argc, char **argv) 23 | { 24 | clog_init(NULL); 25 | 26 | cmessage("Message :]"); 27 | cinfo("Some info"); 28 | cwarning("Some warning"); 29 | puts("Normal output"); 30 | cdebug("Some debugging"); 31 | cerror("Some error"); 32 | 33 | return EXIT_SUCCESS; 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /clog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * clog.h 3 | * Copyright (C) 2020 Adrian Perez de Castro 4 | * 5 | * Distributed under terms of the MIT license. 6 | */ 7 | 8 | #ifndef CLOG_H 9 | #define CLOG_H 10 | 11 | #include 12 | #include 13 | 14 | enum clog_level { 15 | CLOG_LEVEL_INFO, 16 | CLOG_LEVEL_WARNING, 17 | CLOG_LEVEL_ERROR, 18 | CLOG_LEVEL_DEBUG, 19 | }; 20 | 21 | extern bool clog_debug_enabled; 22 | extern bool clog_fatal_errors; 23 | extern bool clog_fatal_warnings; 24 | 25 | extern void clog_init(const char *env_prefix); 26 | extern void clog_format(enum clog_level, 27 | const char *file, 28 | unsigned line, 29 | const char *func, 30 | const char *fmt, 31 | ...); 32 | 33 | #define clog_message(fmt, ...) \ 34 | fprintf(stderr, " ** " fmt "\n", ##__VA_ARGS__) 35 | 36 | #define clog_info(fmt, ...) \ 37 | clog_format(CLOG_LEVEL_INFO, \ 38 | __FILE__, __LINE__, __func__, \ 39 | (fmt), ##__VA_ARGS__) 40 | 41 | #define clog_warning(fmt, ...) \ 42 | clog_format(CLOG_LEVEL_WARNING, \ 43 | __FILE__, __LINE__, __func__, \ 44 | (fmt), ##__VA_ARGS__) 45 | 46 | #define clog_error(fmt, ...) \ 47 | clog_format(CLOG_LEVEL_ERROR, \ 48 | __FILE__, __LINE__, __func__, \ 49 | (fmt), ##__VA_ARGS__) 50 | 51 | #define clog_debug(fmt, ...) \ 52 | do { \ 53 | if (clog_debug_enabled) \ 54 | clog_format(CLOG_LEVEL_DEBUG, \ 55 | __FILE__, __LINE__, __func__, \ 56 | (fmt), ##__VA_ARGS__); \ 57 | } while (false) 58 | 59 | #if defined(CLOG_SHORT_MACROS) && CLOG_SHORT_MACROS 60 | #define cmessage clog_message 61 | #define cinfo clog_info 62 | #define cwarning clog_warning 63 | #define cerror clog_error 64 | #define cdebug clog_debug 65 | #endif /* CLOG_SHORT_MACROS */ 66 | 67 | #endif /* !CLOG_H */ 68 | -------------------------------------------------------------------------------- /clog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * clog.c 3 | * Copyright (C) 2020 Adrian Perez de Castro 4 | * 5 | * Distributed under terms of the MIT license. 6 | */ 7 | 8 | #ifndef _POSIX_C_SOURCE 9 | #define _POSIX_C_SOURCE 1 10 | #endif 11 | 12 | #include "clog.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | bool clog_fatal_errors = true; 19 | bool clog_fatal_warnings = false; 20 | bool clog_debug_enabled = false; 21 | static bool use_colors = false; 22 | 23 | static const struct { 24 | const char *name; 25 | bool *data; 26 | } env_opts[] = { 27 | { "DEBUG", &clog_debug_enabled }, 28 | { "FATAL_ERRORS", &clog_fatal_errors }, 29 | { "FATAL_WARNINGS", &clog_fatal_warnings }, 30 | { "COLOR_MESSAGES", &use_colors }, 31 | }; 32 | 33 | static const char *names_plain[] = { 34 | [CLOG_LEVEL_INFO] = "INFO ", 35 | [CLOG_LEVEL_WARNING] = "WARN ", 36 | [CLOG_LEVEL_ERROR] = "ERROR ", 37 | [CLOG_LEVEL_DEBUG] = "DEBUG ", 38 | }; 39 | static const char *names_colored[] = { 40 | [CLOG_LEVEL_INFO] = "\33[32m" "INFO " "\33[39m", 41 | [CLOG_LEVEL_WARNING] = "\33[91m" "WARN " "\33[39m", 42 | [CLOG_LEVEL_ERROR] = "\33[31m" "ERROR " "\33[39m", 43 | [CLOG_LEVEL_DEBUG] = "\33[35m" "DEBUG " "\33[39m", 44 | }; 45 | static const char **names = names_plain; 46 | 47 | static const char loc_format_plain[] = 48 | " [%s:%d, %s]" 49 | "\n"; 50 | static const char loc_format_colored[] = 51 | "\33[90m" 52 | " [%s:%d, %s]" 53 | "\33[39m" 54 | "\n"; 55 | static const char *loc_format = loc_format_plain; 56 | 57 | void 58 | clog_init(const char *env_prefix) 59 | { 60 | static bool initialized = false; 61 | 62 | if (initialized) 63 | return; 64 | 65 | initialized = true; 66 | use_colors = isatty(fileno(stderr)); 67 | 68 | if (!env_prefix) 69 | env_prefix = "LOG"; 70 | 71 | unsigned env_prefix_len = strlen(env_prefix); 72 | char varname[env_prefix_len + 16]; 73 | memcpy(varname, env_prefix, env_prefix_len); 74 | varname[env_prefix_len] = '_'; 75 | 76 | for (unsigned i = 0; i < sizeof (env_opts) / sizeof (env_opts[0]); i++) { 77 | strcpy(varname + env_prefix_len + 1, env_opts[i].name); 78 | const char *value = getenv(varname); 79 | if (value) 80 | *env_opts[i].data = (*value != '\0' && *value != '0'); 81 | } 82 | 83 | if (use_colors) { 84 | names = names_colored; 85 | loc_format = loc_format_colored; 86 | } 87 | } 88 | 89 | 90 | void 91 | clog_format(enum clog_level level, 92 | const char *file, 93 | unsigned line, 94 | const char *func, 95 | const char *fmt, 96 | ...) 97 | { 98 | fputs(names[level], stderr); 99 | 100 | va_list args; 101 | va_start(args, fmt); 102 | vfprintf(stderr, fmt, args); 103 | va_end(args); 104 | 105 | fprintf(stderr, loc_format, file, line, func); 106 | 107 | if ((level == CLOG_LEVEL_WARNING && clog_fatal_warnings) || 108 | (level == CLOG_LEVEL_ERROR && clog_fatal_errors)) 109 | { 110 | fflush(stderr); 111 | abort(); 112 | } 113 | } 114 | --------------------------------------------------------------------------------