src/lib/log.c
branchnew-lib-errors
changeset 217 7728d6ec3abf
parent 216 a10ba529ae39
child 218 5229a5d098b2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/log.c	Wed May 27 23:57:48 2009 +0300
@@ -0,0 +1,165 @@
+
+#include "log.h"
+#include "str.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+/**
+ * The default log output func
+ */
+void log_default_func (const char *line, void *arg)
+{
+    (void) arg;
+
+    // display
+    printf("%s\n", line);
+}
+
+/**
+ * The global log level
+ */
+static enum log_level _log_level = LOG_LEVEL_DEFAULT;
+
+/**
+ * The global log output func
+ */
+static struct log_output_ctx {
+    /** The function itself */
+    log_output_func func;
+
+    /** The arg */
+    void *arg;
+} _log_output_ctx = { log_default_func, NULL };
+
+/**
+ * List of log level names
+ */
+const char *log_level_names[] = {
+    "DEBUG",
+    "INFO",
+    "WARN",
+    "ERROR",
+    "FATAL",
+    NULL
+};
+
+#define _LOG_LEVEL_NAME(ll) case LOG_ ## ll: return #ll;
+const char *log_level_name (enum log_level level)
+{
+    switch (level) {
+        _LOG_LEVEL_NAME(DEBUG)
+        _LOG_LEVEL_NAME(INFO)
+        _LOG_LEVEL_NAME(WARN)
+        _LOG_LEVEL_NAME(ERROR)
+        _LOG_LEVEL_NAME(FATAL)
+        default: return "???";
+    }
+}
+#undef _LOG_LEVEL_NAME
+
+void set_log_level (enum log_level level)
+{
+    // meep meep
+    _log_level = level;
+}
+
+void log_set_func (log_output_func func, void *arg)
+{
+    // replace the current one
+    _log_output_ctx.func = func ? func : log_default_func;
+    _log_output_ctx.arg = arg;
+}
+
+void log_output_tag_va (enum log_level level, const char *tag, const char *func, const char *user_fmt, va_list user_fmtargs, const char *log_fmt, va_list log_fmtargs)
+{
+    char buf[LOG_MSG_MAX], *buf_ptr = buf;
+    size_t buf_size = sizeof(buf);
+
+    // filter out?
+    if (level < _log_level)
+        return;
+
+    // output the header
+    buf_ptr += str_advance(NULL, &buf_size, str_append_fmt(buf_ptr, buf_size, "[%5s] %20s : ", tag, func));
+    
+    // output the user data
+    if (user_fmt)
+        buf_ptr += str_advance(NULL, &buf_size, str_append_fmt_va(buf_ptr, buf_size, user_fmt, user_fmtargs));
+    
+    // output the suffix
+    if (log_fmt)
+        buf_ptr += str_advance(NULL, &buf_size, str_append_fmt_va(buf_ptr, buf_size, log_fmt, log_fmtargs));
+
+    // send it to the output func
+    _log_output_ctx.func(buf, _log_output_ctx.arg);
+
+}
+
+void log_output_tag (enum log_level level, const char *tag, const char *func, const char *user_fmt, va_list user_fmtargs, const char *log_fmt, ...)
+{
+    va_list vargs;
+
+    va_start(vargs, log_fmt);
+    log_output_tag_va(level, tag, func, user_fmt, user_fmtargs, log_fmt, vargs);
+    va_end(vargs);
+}
+
+void _log_msg (enum log_level level, const char *func, const char *format, ...)
+{
+    va_list vargs;
+    
+    // formatted output: no suffix
+    va_start(vargs, format);
+    log_output_tag(level, log_level_name(level), func, format, vargs, NULL);
+    va_end(vargs);
+}
+
+void _log_msg_va2 (enum log_level level, const char *func, const char *fmt1, va_list fmtargs1, const char *fmt2, va_list fmtargs2)
+{
+    log_output_tag_va(level, log_level_name(level), func, fmt1, fmtargs1, fmt2, fmtargs2);
+}
+
+void _log_err (enum log_level level, const struct error_list *list, err_t code, const char *func, const char *format, ...)
+{
+    va_list vargs;
+
+    // formatted output: suffix error_name()
+    va_start(vargs, format);
+    log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", error_name(list, code));
+    va_end(vargs);
+}
+
+void _log_error (enum log_level level, const error_t *err, const char *func, const char *format, ...)
+{
+    va_list vargs;
+
+    // formatted output: suffix error_msg()
+    va_start(vargs, format);
+    log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", error_msg(err));
+    va_end(vargs);
+}
+
+void _log_perr (enum log_level level, const char *func, const char *format, ...)
+{
+    va_list vargs;
+
+    // formatted output: suffix strerror()
+    va_start(vargs, format);
+    log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", strerror(errno));
+    va_end(vargs);
+}
+
+void _log_exit (enum log_level level, int exit_code, const char *func, const char *format, ...)
+{
+    va_list vargs;
+
+    // formatted output without any suffix
+    va_start(vargs, format);
+    log_output_tag(level, "EXIT", func, format, vargs, NULL);
+    va_end(vargs);
+
+    // exit
+    exit(exit_code);
+}