summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--Makefile.files10
-rw-r--r--debug.c (renamed from debug.cc)198
-rw-r--r--debug.h99
-rw-r--r--main.c68
5 files changed, 376 insertions, 4 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..fc5b439
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,5 @@
+include Makefile.files
+
+all:
+ gcc ${DEBUG_SOURCES} main.c -o debug
+# -DWITH_DBG_MUTEX \ No newline at end of file
diff --git a/Makefile.files b/Makefile.files
new file mode 100644
index 0000000..e707d13
--- /dev/null
+++ b/Makefile.files
@@ -0,0 +1,10 @@
+#
+# Include this file from your project Makefile and add the
+# variable DEBUG_SOURCES to the files that need compilation.
+#
+
+DEBUG_SOURCES = \
+ debug.c
+
+DEBUG_EXTRA_DIST = \
+ debug.h \ No newline at end of file
diff --git a/debug.cc b/debug.c
index ed0ac84..22c0000 100644
--- a/debug.cc
+++ b/debug.c
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set et sw=2 ts=2: */
/***************************************************************************
- * debug.cc
+ * debug.c
*
* Thu Nov 1 13:38:47 CET 2012
* Copyright 2012 Bent Bisballe Nyeng
@@ -27,6 +27,199 @@
*/
#include "debug.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef WITH_DBG_MUTEX
+#include <pthread.h>
+#endif
+
+struct {
+ unsigned int flags;
+#ifdef WITH_DBG_MUTEX
+ pthread_mutex_t mutex;
+#endif
+ int fd;
+ int file_fd;
+} dbg_config = { .flags = DBG_FLAG_DEFAULT, .fd = -1, .file_fd = -1 };
+
+static void dbg_mutex_init()
+{
+#ifdef WITH_DBG_MUTEX
+ if(dbg_config.flags & DBG_FLAG_USE_MUTEX) {
+ pthread_mutex_init(&dbg_config.mutex, NULL);
+ }
+#endif
+}
+
+static void dbg_mutex_lock()
+{
+#ifdef WITH_DBG_MUTEX
+ if(dbg_config.flags & DBG_FLAG_USE_MUTEX) {
+ pthread_mutex_lock(&dbg_config.mutex);
+ }
+#endif
+}
+
+static void dbg_mutex_unlock()
+{
+#ifdef WITH_DBG_MUTEX
+ if(dbg_config.flags & DBG_FLAG_USE_MUTEX) {
+ pthread_mutex_unlock(&dbg_config.mutex);
+ }
+#endif
+}
+
+static void dbg_mutex_close()
+{
+#ifdef WITH_DBG_MUTEX
+ if(dbg_config.flags & DBG_FLAG_USE_MUTEX) {
+ // Make sure we don't destroy the mutex while another thread is using it.
+ dbg_mutex_lock();
+ dbg_mutex_unlock();
+ pthread_mutex_destroy(&dbg_config.mutex);
+ }
+#endif
+}
+
+dbg_status_t dbg_init(unsigned int flags, ...)
+{
+ dbg_status_t status = DBG_STATUS_OK;
+
+ dbg_config.flags = flags;
+
+ int end = 0;
+
+ va_list vl;
+ va_start(vl, flags);
+ while(!end) {
+ int option = va_arg(vl, int);
+ switch(option) {
+ case DBG_OPTION_END:
+ end = 1;
+ break;
+ case DBG_OPTION_FD:
+ dbg_config.fd = va_arg(vl, int);
+ break;
+ case DBG_OPTION_FILENAME:
+ if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_FILE) {
+ const char *filename = (const char*)va_arg(vl, char*);
+ dbg_config.file_fd = open(filename, O_CREAT | O_RDWR, 0777);
+ }
+ break;
+ default:
+ status = DBG_STATUS_UNKNOWN_OPTION;
+ printf("option: %x\n", option);
+ goto err;
+ }
+ }
+
+ dbg_mutex_init();
+
+ err:
+ va_end(vl);
+
+ return status;
+}
+
+void dbg_close()
+{
+ if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_FILE) {
+ if(dbg_config.file_fd != -1) close(dbg_config.file_fd);
+ }
+
+ dbg_mutex_close();
+}
+
+static const char * const debug_class_str[] =
+ { "fixme", "err", "warn", "info", "debug" };
+
+static int dbg_create_header(char *hdr, size_t size)
+{
+ time_t rawtime = time(NULL);
+ struct tm t;
+ localtime_r(&rawtime, &t);
+
+ return snprintf(hdr, size,
+ "%d-%02d-%02d %02d:%02d:%02d",
+ t.tm_year + 1900,
+ t.tm_mon + 1,
+ t.tm_mday,
+ t.tm_hour,
+ t.tm_min,
+ t.tm_sec);
+}
+
+static int dbg_output_fd(int fd, const char *msg)
+{
+ if(fd == -1) return 1;
+
+ char hdr[32];
+ dbg_create_header(hdr, sizeof(hdr));
+ write(fd, hdr, strlen(hdr));
+ write(fd, " ", 1);
+ write(fd, msg, strlen(msg));
+ if(msg[strlen(msg) - 1] != '\n') write(fd, "\n", 1);
+ return 0;
+}
+
+int __debug(const char *func, const int line,
+ const enum __debug_class cl,
+ const char *ch, const char *fmt, ...)
+{
+ int result = 0;
+
+ dbg_mutex_lock();
+
+ //
+ // Generate message
+ //
+
+ char buf[1024];
+
+ int sz = snprintf(buf, sizeof(buf),
+ "%s:%s:%s:%d ",
+ debug_class_str[(unsigned)cl], ch, func, line);
+ va_list va;
+ va_start(va, fmt);
+ sz += vsnprintf(buf + sz, sizeof(buf) - sz, fmt, va);
+ va_end(va);
+
+ //
+ // Send message to output
+ //
+
+ if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_STDOUT) {
+ dbg_output_fd(STDOUT_FILENO, buf);
+ }
+
+ if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_STDERR) {
+ dbg_output_fd(STDERR_FILENO, buf);
+ }
+
+ if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_FD) {
+ dbg_output_fd(dbg_config.fd, buf);
+ }
+
+ if(dbg_config.flags & DBG_FLAG_OUTPUT_TO_FILE) {
+ dbg_output_fd(dbg_config.file_fd, buf);
+ }
+
+ done:
+ dbg_mutex_unlock();
+
+ return result;
+}
+
+#if 0
+
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
@@ -176,3 +369,6 @@ void debug_parse(const char *fmt)
}
free(s);
}
+
+
+#endif
diff --git a/debug.h b/debug.h
index 0c5e3a5..1241f67 100644
--- a/debug.h
+++ b/debug.h
@@ -28,10 +28,103 @@
#ifndef __DEBUG_MODULE_DEBUG_H__
#define __DEBUG_MODULE_DEBUG_H__
-#include <stdio.h>
+enum DBG_FLAG {
+ // Features
+#ifdef WITH_DBG_THREAD
+ DBG_FLAG_USE_THREAD = 0x00000001,
+#endif
+#ifdef WITH_DBG_MUTEX
+ DBG_FLAG_USE_MUTEX = 0x00000002,
+#endif
+#ifdef WITH_DBG_FILTER
+ DBG_FLAG_USE_FILTER = 0x00000004,
+#endif
-void debug_init(FILE *fp);
-void debug_parse(const char *fmt);
+ // Outputs
+ DBG_FLAG_OUTPUT_TO_STDOUT = 0x00010000,
+ DBG_FLAG_OUTPUT_TO_STDERR = 0x00020000,
+ DBG_FLAG_OUTPUT_TO_FD = 0x00040000,
+ DBG_FLAG_OUTPUT_TO_FILE = 0x00080000,
+#ifdef WITH_DBG_SYSLOG
+ DBG_FLAG_OUTPUT_TO_SYSLOG = 0x000f0000,
+#endif
+
+ // Default value of flags
+ DBG_FLAG_DEFAULT = DBG_FLAG_OUTPUT_TO_STDOUT, // Output to stdout
+};
+
+enum DBG_OPTION {
+ /**
+ * No more options / last option. This is used
+ * to terminate the VARARGs list.
+ */
+ DBG_OPTION_END,
+
+ /**
+ * const char* argument containing a filename which will be used for log
+ * output. To be used with the DBG_FLAG_OUTPUT_TO_FILE flag.
+ */
+ DBG_OPTION_FILENAME,
+
+ /**
+ * Integer argument describing a file descriptor which will be used for log
+ * output. To be used with the DBG_FLAG_OUTPUT_TO_FD flag.
+ */
+ DBG_OPTION_FD,
+
+ /**
+ * Host and port to use when logging on an external server.
+ * Host is a const char* argument, port is an integer.
+ * To be used with the DBG_FLAG_USE_SYSLOG flag.
+ * Linux: If DBG_OPTION_SYSLOG_HOST is not supplied, the local syslog will be
+ * used.
+ * Windows: If DBG_OPTION_SYSLOG_HOST is not supplied an error will be
+ * returned by debug_init.
+ * If DBG_OPTION_SYSLOG_PORT is not supplied, the default syslogd port will
+ * be used (port 514).
+ */
+#ifdef WITH_DBG_SYSLOG
+ DBG_OPTION_SYSLOG_HOST,
+ DBG_OPTION_SYSLOG_PORT,
+#endif
+
+ /**
+ *
+ */
+};
+
+typedef enum {
+ DBG_STATUS_OK = 0,
+ DBG_STATUS_UNKNOWN_OPTION,
+ DBG_STATUS_ERROR,
+} dbg_status_t;
+
+/**
+ * @param flags combination of DBG_FLAG values
+ * @param ... list of options (type-value pairs,
+ * terminated with DBG_OPTION_END).
+ * @return 0 on success, 1 on error.
+ */
+dbg_status_t dbg_init(unsigned int flags, ...);
+void dbg_close();
+
+/**
+ * Example of usage (use mutex protected calls, send output to file):
+ *
+ * dbg_status_t status;
+ * status = debug_init(DBG_FLAG_OUTPUT_TO_FILE | DBG_FLAG_USE_MUTEX,
+ * DBG_OPTION_FILENAME, "/tmp/my.log",
+ DBG_OPTION_END);
+ * if(status != DBG_STATUS_OK) exit(1);
+ * INFO(example, "We are up and running\n");
+ * dbg_close();
+ */
+
+/**
+ * Example of usage (simply outputs to stdout):
+ *
+ * INFO(example, "We are up and running\n");
+ */
enum __debug_class
{
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..8e0efca
--- /dev/null
+++ b/main.c
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * main.cc
+ *
+ * Fri Dec 7 09:35:45 CET 2012
+ * Copyright 2012 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Debug Module.
+ *
+ * Debug Module is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Debug Module is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Debug Module; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "debug.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ /*
+ int fd = open("/tmp/my.log", O_CREAT | O_RDWR, 0777);
+ if(fd == -1) {
+ return 1;
+ }
+ */
+ dbg_status_t status = dbg_init(//DBG_FLAG_USE_MUTEX |
+ DBG_FLAG_OUTPUT_TO_FILE |
+ //DBG_FLAG_OUTPUT_TO_FD |
+ //DBG_FLAG_OUTPUT_TO_STDOUT |
+ //DBG_FLAG_OUTPUT_TO_STDERR |
+ 0,
+ //DBG_OPTION_FD, fd,
+ DBG_OPTION_FILENAME, "/tmp/my2.log",
+ DBG_OPTION_END);
+
+ if(status != DBG_STATUS_OK) {
+ printf("Error: %d\n", status);
+ return 1;
+ }
+
+ INFO(example, "We are up and running");
+
+ DEBUG(example, "Or are we %d?", 42);
+
+ dbg_close();
+
+ //close(fd);
+
+ return 0;
+}