C89 compatible version

This commit is contained in:
Rostislav Stříbrný 2022-11-07 17:09:20 +01:00
parent b3ace3b239
commit 774d7dad28
4 changed files with 41 additions and 114 deletions

View File

@ -7,7 +7,7 @@ SRC := $(wildcard $(SRC_DIR)/*.c)
OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
CPPFLAGS := -Iinclude -MMD -MP CPPFLAGS := -Iinclude -MMD -MP
CFLAGS := -Wall CFLAGS := -Wall -std=c89
LDFLAGS := -Llib LDFLAGS := -Llib
LDLIBS := -lm LDLIBS := -lm

View File

@ -24,15 +24,17 @@ int main(int argc, char** argv) {
log_add_fp(f5, LOG_ERROR); log_add_fp(f5, LOG_ERROR);
log_add_fp(f6, LOG_FATAL); log_add_fp(f6, LOG_FATAL);
log_trace("TRACE - Hello %s", "world"); log_trace2("TRACE - Hello %s", "world");
log_debug("DEBUG - Hello %s", "world"); log_debug2("DEBUG - Hello %s", "world");
log_info("INFO - Hello %s", "world"); log_info2("INFO - Hello %s", "world");
log_warn("WARNING - Hello %s", "world"); log_warn2("WARNING - Hello %s", "world");
log_error("ERROR - Hello %s", "world"); log_error2("ERROR - Hello %s", "world");
log_fatal("FATAL - Hello %s", "world"); log_fatal2("FATAL - Hello %s", "world");
// Pre-C99 usage example /* Pre-C99 usage example
log_trace3("test 3 args: %s %s", "arg1", "arg2"); log_trace3("test 3 args: %s %s", "arg1", "arg2");
*/
log_log(LOG_ERROR, __FILE__, __LINE__, "test 3 args: %s %s", "arg1", "arg2");
fclose(f1); fclose(f1);
fclose(f2); fclose(f2);
@ -40,5 +42,7 @@ int main(int argc, char** argv) {
fclose(f4); fclose(f4);
fclose(f5); fclose(f5);
fclose(f6); fclose(f6);
return 0;
} }

View File

@ -1,25 +1,3 @@
/*
* 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 <sys/time.h> #include <sys/time.h>
#include "log.h" #include "log.h"
@ -38,7 +16,7 @@ static struct {
bool quiet; bool quiet;
Callback callbacks[MAX_CALLBACKS]; Callback callbacks[MAX_CALLBACKS];
} L = { } L = {
NULL, NULL, RXI_LOGC_DEFAULT_LEVEL, false, {{0}}, NULL, NULL, LOG_TRACE, false, {{0}},
}; };
static void time_to_str(char *); static void time_to_str(char *);
@ -58,7 +36,7 @@ static struct tm *tm;
static const char *level_strings[] = {"[[TRACE]]", "[[DEBUG]]", "[[ INFO]]", static const char *level_strings[] = {"[[TRACE]]", "[[DEBUG]]", "[[ INFO]]",
"[[ WARN]]", "[[ERROR]]", "[[FATAL]]"}; "[[ WARN]]", "[[ERROR]]", "[[FATAL]]"};
static inline const char *get_level_string(int level) { static const char *get_level_string(int level) {
return level_strings[(level + 32) / 32]; return level_strings[(level + 32) / 32];
} }
@ -66,14 +44,16 @@ static inline const char *get_level_string(int level) {
static const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", static const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m",
"\x1b[33m", "\x1b[31m", "\x1b[35m"}; "\x1b[33m", "\x1b[31m", "\x1b[35m"};
static inline const char *get_level_color(int level) { static const char *get_level_color(int level) {
return level_colors[(level + 32) / 32]; return level_colors[(level + 32) / 32];
} }
#endif #endif
static void stdout_callback(log_Event *ev) { static void stdout_callback(log_Event *ev) {
//char buf[16]; /*
//buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0'; char buf[16];
buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0';
*/
char *buf = ev->time_str; char *buf = ev->time_str;
#ifdef LOG_USE_COLOR #ifdef LOG_USE_COLOR
@ -90,8 +70,10 @@ static void stdout_callback(log_Event *ev) {
} }
static void file_callback(log_Event *ev) { static void file_callback(log_Event *ev) {
//char buf[64]; /*
//buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0'; char buf[64];
buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0';
*/
char *buf = ev->time_str; char *buf = ev->time_str;
fprintf(ev->udata, "%s %-7s %s:%d: ", buf, get_level_string(ev->level), ev->file, ev->line); fprintf(ev->udata, "%s %-7s %s:%d: ", buf, get_level_string(ev->level), ev->file, ev->line);
@ -123,7 +105,8 @@ void log_set_level(int level) { L.level = level; }
void log_set_quiet(bool enable) { L.quiet = enable; } void log_set_quiet(bool enable) { L.quiet = enable; }
int log_add_callback(log_LogFn fn, void *udata, int level) { int log_add_callback(log_LogFn fn, void *udata, int level) {
for (int i = 0; i < MAX_CALLBACKS; i++) { int i = 0;
for (i = 0; i < MAX_CALLBACKS; i++) {
if (!L.callbacks[i].fn) { if (!L.callbacks[i].fn) {
L.callbacks[i] = (Callback){fn, udata, level}; L.callbacks[i] = (Callback){fn, udata, level};
return 0; return 0;
@ -138,13 +121,16 @@ int log_add_fp(FILE *fp, int level) {
static void init_event(log_Event *ev, void *udata) { static void init_event(log_Event *ev, void *udata) {
if (!ev->time) { if (!ev->time) {
/*
time_t t = time(NULL); time_t t = time(NULL);
ev->time = localtime_r(&t, &ev->time_buf); ev->time = localtime_r(&t, &ev->time_buf);
*/
} }
ev->udata = udata; ev->udata = udata;
} }
void log_log(int level, const char *file, int line, const char *fmt, ...) { void log_log(int level, const char *file, int line, const char *fmt, ...) {
int i = 0;
log_Event ev = { log_Event ev = {
.fmt = fmt, .fmt = fmt,
.file = file, .file = file,
@ -163,7 +149,7 @@ void log_log(int level, const char *file, int line, const char *fmt, ...) {
va_end(ev.ap); va_end(ev.ap);
} }
for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) { for (i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) {
Callback *cb = &L.callbacks[i]; Callback *cb = &L.callbacks[i];
if (level >= cb->level) { if (level >= cb->level) {
init_event(&ev, cb->udata); init_event(&ev, cb->udata);
@ -190,8 +176,10 @@ static void time_to_str(char *buf)
minutes = tm->tm_min; minutes = tm->tm_min;
seconds = tm->tm_sec; seconds = tm->tm_sec;
usec = tv.tv_usec; usec = tv.tv_usec;
// msec /* msec */
// buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", lt)] = '\0'; /*
buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", lt)] = '\0';
*/
int len = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%06d ", int len = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
year, year,
month, month,

View File

@ -1,10 +1,3 @@
/**
* 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 #ifndef LOG_H
#define LOG_H #define LOG_H
@ -23,16 +16,6 @@
#define LOG_VERSION "0.1.0" #define LOG_VERSION "0.1.0"
#ifndef RXI_LOGC_DEFAULT_LEVEL
#define RXI_LOGC_DEFAULT_LEVEL LOG_TRACE
#endif
#if defined __GNUC__
#define RXI_LOGC_PRINTF_ATTRIB(n, m) __attribute__((format(printf, n, m)))
#else
#define RXI_LOGC_PRINTF_ATTRIB(n, m)
#endif
enum { enum {
LOG_TRACE = -32, LOG_TRACE = -32,
LOG_DEBUG = 0, LOG_DEBUG = 0,
@ -57,36 +40,21 @@ typedef struct {
typedef void (*log_LogFn)(log_Event *ev); typedef void (*log_LogFn)(log_Event *ev);
typedef void (*log_LockFn)(bool lock, void *udata); typedef void (*log_LockFn)(bool lock, void *udata);
// Pre-C99 compatible definitions - BEGIN /* Pre-C99 compatible definitions - BEGIN */
#define log_internal1(level, file, line, arg1) \ #define log_internal1(level, file, line, arg1) \
do { \ log_log(level, file, line, arg1);
if (level >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(level, file, line, arg1); \
} while (0)
#define log_internal2(level, file, line, arg1, arg2) \ #define log_internal2(level, file, line, arg1, arg2) \
do { \ log_log(level, file, line, arg1, arg2);
if (level >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(level, file, line, arg1, arg2); \
} while (0)
#define log_internal3(level, file, line, arg1, arg2, arg3) \ #define log_internal3(level, file, line, arg1, arg2, arg3) \
do { \ log_log(level, file, line, arg1, arg2, arg3);
if (level >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(level, file, line, arg1, arg2, arg3); \
} while (0)
#define log_internal4(level, file, line, arg1, arg2, arg3, arg4) \ #define log_internal4(level, file, line, arg1, arg2, arg3, arg4) \
do { \ log_log(level, file, line, arg1, arg2, arg3, arg4);
if (level >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(level, file, line, arg1, arg2, arg3, arg4); \
} while (0)
#define log_internal5(level, file, line, arg1, arg2, arg3, arg4, arg5) \ #define log_internal5(level, file, line, arg1, arg2, arg3, arg4, arg5) \
do { \ log_log(level, file, line, arg1, arg2, arg3, arg4, arg5);
if (level >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(level, file, line, arg1, arg2, arg3, arg4, arg5); \
} while (0)
#define log_trace1(arg1) log_internal1(LOG_TRACE, __FILE__, __LINE__, arg1); #define log_trace1(arg1) log_internal1(LOG_TRACE, __FILE__, __LINE__, arg1);
#define log_trace2(arg1, arg2) log_internal2(LOG_TRACE, __FILE__, __LINE__, arg1, arg2); #define log_trace2(arg1, arg2) log_internal2(LOG_TRACE, __FILE__, __LINE__, arg1, arg2);
@ -123,39 +91,7 @@ typedef void (*log_LockFn)(bool lock, void *udata);
#define log_fatal3(arg1, arg2, arg3) log_internal3(LOG_FATAL, __FILE__, __LINE__, arg1, arg2, arg3); #define log_fatal3(arg1, arg2, arg3) log_internal3(LOG_FATAL, __FILE__, __LINE__, arg1, arg2, arg3);
#define log_fatal4(arg1, arg2, arg3, arg4) log_internal4(LOG_FATAL, __FILE__, __LINE__, arg1, arg2, arg3, arg4); #define log_fatal4(arg1, arg2, arg3, arg4) log_internal4(LOG_FATAL, __FILE__, __LINE__, arg1, arg2, arg3, arg4);
#define log_fatal5(arg1, arg2, arg3, arg4, arg5) log_internal5(LOG_FATAL, __FILE__, __LINE__, arg1, arg2, arg3, arg4, arg5); #define log_fatal5(arg1, arg2, arg3, arg4, arg5) log_internal5(LOG_FATAL, __FILE__, __LINE__, arg1, arg2, arg3, arg4, arg5);
// Pre-C99 compatible definitions - END /* Pre-C99 compatible definitions - END */
#define log_trace(...) \
do { \
if (LOG_TRACE >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__); \
} while (0)
#define log_debug(...) \
do { \
if (LOG_DEBUG >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__); \
} while (0)
#define log_info(...) \
do { \
if (LOG_INFO >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__); \
} while (0)
#define log_warn(...) \
do { \
if (LOG_WARN >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__); \
} while (0)
#define log_error(...) \
do { \
if (LOG_ERROR >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__); \
} while (0)
#define log_fatal(...) \
do { \
if (LOG_FATAL >= RXI_LOGC_DEFAULT_LEVEL) \
log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__); \
} while (0)
const char *log_level_string(int level); const char *log_level_string(int level);
void log_set_lock(log_LockFn fn, void *udata); void log_set_lock(log_LockFn fn, void *udata);
@ -164,7 +100,6 @@ void log_set_quiet(bool enable);
int log_add_callback(log_LogFn fn, void *udata, int level); int log_add_callback(log_LogFn fn, void *udata, int level);
int log_add_fp(FILE *fp, int level); int log_add_fp(FILE *fp, int level);
void log_log(int level, const char *file, int line, const char *fmt, ...) void log_log(int level, const char *file, int line, const char *fmt, ...);
RXI_LOGC_PRINTF_ATTRIB(4, 5);
#endif #endif