diff --git a/clog.h b/clog.h index 525de1e..48266bc 100644 --- a/clog.h +++ b/clog.h @@ -62,19 +62,29 @@ #ifndef __CLOG_H__ #define __CLOG_H__ -#include -#include -#include -#include #include -#include +#include // malloc, realloc, free #include -#include +#include // strcpy, ... #include -#include +#include // errno + +/* check whether C/C++ standard supports variadic macros + * (they are supported as of C99 and C++11). */ +#ifndef USE_VARIADIC +# ifdef __cplusplus +# define USE_VARIADIC (__cplusplus >= 201103L) +# else +# ifdef __STDC_VERSION__ +# define USE_VARIADIC (__STDC_VERSION__ >= 199901L) +# else +# define USE_VARIADIC 0 +# endif +# endif +#endif /* Number of loggers that can be defined. */ -#define CLOG_MAX_LOGGERS 16 +#define CLOG_MAX_LOGGERS FOPEN_MAX /* (typically 16) */ /* Format strings cannot be longer than this. */ #define CLOG_FORMAT_LENGTH 256 @@ -128,7 +138,7 @@ int clog_init_path(int id, const char *const path); * @return * Zero on success, non-zero on failure. */ -int clog_init_fd(int id, int fd); +int clog_init_fd(int id, FILE* fd); /** * Destroy (clean up) a logger. You should do this at the end of execution, @@ -139,8 +149,6 @@ int clog_init_fd(int id, int fd); */ void clog_free(int id); -#define CLOG(id) __FILE__, __LINE__, id - /** * Log functions (one per level). Call these to write messages to the log * file. The first three arguments can be replaced with a call to the CLOG @@ -163,10 +171,56 @@ void clog_free(int id); * @param ... * Any additional format arguments. */ -void clog_debug(const char *sfile, int sline, int id, const char *fmt, ...); -void clog_info(const char *sfile, int sline, int id, const char *fmt, ...); -void clog_warn(const char *sfile, int sline, int id, const char *fmt, ...); -void clog_error(const char *sfile, int sline, int id, const char *fmt, ...); +void _clog_debug(const char *sfile, int sline, int id, const char *fmt, ...); +void _clog_info(const char *sfile, int sline, int id, const char *fmt, ...); +void _clog_warn(const char *sfile, int sline, int id, const char *fmt, ...); +void _clog_error(const char *sfile, int sline, int id, const char *fmt, ...); + +/** + * Variadic macro log functions (one per level). Insert at any point in the + * code to write messages to the log file. The first argument is the logger id, + * while the following arguments are the same as for the printf function: + * + * clog_debug(MY_LOGGER_ID, "%s is %d log message.", "This", 1); + * + * @param id + * The id of the logger to write to. + * + * @param fmt + * The format string for the message (printf formatting). + * + * @param ... + * Any additional format arguments. + * + * Note, that these are only available with the standard C99/C++11 or later. + * For earlier versions the behaviour is the same as the clog_xxx log functions. + */ +#if USE_VARIADIC +/* for backwards compatibility: */ +#define CLOG(id) id + +#define clog_debug(id, ...) _clog_debug(__FILE__, __LINE__, id, __VA_ARGS__) +#define clog_info(id, ...) _clog_info(__FILE__, __LINE__, id, __VA_ARGS__) +#define clog_warn(id, ...) _clog_warn(__FILE__, __LINE__, id, __VA_ARGS__) +#define clog_error(id, ...) _clog_error(__FILE__, __LINE__, id, __VA_ARGS__) + +#else +/* formerly, the macro supplying the linenumber and filename had to be + * included in the function call: + * + * clog_debug(CLOG(MY_LOGGER_ID), "This is a log message."); + * + * if the C-standard does not support variadic macros or USE_VARIADIC is + * defined as `false`, keep it this way: + */ +#define CLOG(id) __FILE__, __LINE__, id + +/* use dummy macros pointing to the function call */ +#define clog_debug _clog_debug +#define clog_info _clog_info +#define clog_warn _clog_warn +#define clog_error _clog_error +#endif /** * Set the minimum level of messages that should be written to the log. @@ -256,7 +310,7 @@ struct clog { enum clog_level level; /* The file being written. */ - int fd; + FILE* fd; /* The format specifier. */ char fmt[CLOG_FORMAT_LENGTH]; @@ -291,13 +345,13 @@ const char *const CLOG_LEVEL_NAMES[] = { int clog_init_path(int id, const char *const path) { - int fd = open(path, O_CREAT | O_WRONLY | O_APPEND, 0666); - if (fd == -1) { + FILE* fd = fopen(path, "a"); + if (! fd) { _clog_err("Unable to open %s: %s\n", path, strerror(errno)); return 1; } if (clog_init_fd(id, fd)) { - close(fd); + fclose(fd); return 1; } _clog_loggers[id]->opened = 1; @@ -305,7 +359,7 @@ clog_init_path(int id, const char *const path) } int -clog_init_fd(int id, int fd) +clog_init_fd(int id, FILE* fd) { struct clog *logger; @@ -336,7 +390,7 @@ clog_free(int id) { if (_clog_loggers[id]) { if (_clog_loggers[id]->opened) { - close(_clog_loggers[id]->fd); + fclose(_clog_loggers[id]->fd); } free(_clog_loggers[id]); } @@ -536,7 +590,7 @@ _clog_log(const char *sfile, int sline, enum clog_level level, char *dynbuf = buf; char *message; va_list ap_copy; - int result; + size_t result; struct clog *logger = _clog_loggers[id]; if (!logger) { @@ -555,7 +609,7 @@ _clog_log(const char *sfile, int sline, enum clog_level level, buf_size = result + 1; dynbuf = (char *) malloc(buf_size); result = vsnprintf(dynbuf, buf_size, fmt, ap_copy); - if ((size_t) result >= buf_size) { + if (result >= buf_size) { /* Formatting failed -- too large */ _clog_err("Formatting failed (1).\n"); va_end(ap_copy); @@ -577,8 +631,9 @@ _clog_log(const char *sfile, int sline, enum clog_level level, } return; } - result = write(logger->fd, message, strlen(message)); - if (result == -1) { + size_t count = strlen(message); + result = fwrite(message, sizeof(char), count, logger->fd); + if (result < count) { _clog_err("Unable to write to log file: %s\n", strerror(errno)); } if (message != message_buf) { @@ -591,7 +646,7 @@ _clog_log(const char *sfile, int sline, enum clog_level level, } void -clog_debug(const char *sfile, int sline, int id, const char *fmt, ...) +_clog_debug(const char *sfile, int sline, int id, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -600,7 +655,7 @@ clog_debug(const char *sfile, int sline, int id, const char *fmt, ...) } void -clog_info(const char *sfile, int sline, int id, const char *fmt, ...) +_clog_info(const char *sfile, int sline, int id, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -609,7 +664,7 @@ clog_info(const char *sfile, int sline, int id, const char *fmt, ...) } void -clog_warn(const char *sfile, int sline, int id, const char *fmt, ...) +_clog_warn(const char *sfile, int sline, int id, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -618,7 +673,7 @@ clog_warn(const char *sfile, int sline, int id, const char *fmt, ...) } void -clog_error(const char *sfile, int sline, int id, const char *fmt, ...) +_clog_error(const char *sfile, int sline, int id, const char *fmt, ...) { va_list ap; va_start(ap, fmt); diff --git a/test/Makefile b/test/Makefile index 115b997..a667478 100644 --- a/test/Makefile +++ b/test/Makefile @@ -20,6 +20,6 @@ check: clog_test @./clog_test clean: - rm -f clog_test clog_test.out *.o + rm -f clog_test *.out *.o .PHONY: clean check