Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b
Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/dbg/dbg.c b/src/dbg/dbg.c
new file mode 100644
index 0000000..52e7e67
--- /dev/null
+++ b/src/dbg/dbg.c
@@ -0,0 +1,328 @@
+/**
+ * @file dbg.c Debug printing
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PTHREAD
+#include <stdlib.h>
+#include <pthread.h>
+#endif
+#include <time.h>
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_list.h>
+#include <re_tmr.h>
+
+
+#define DEBUG_MODULE "dbg"
+#define DEBUG_LEVEL 0
+#include <re_dbg.h>
+
+
+/** Debug configuration */
+static struct {
+ uint64_t tick; /**< Init ticks */
+ int level; /**< Current debug level */
+ enum dbg_flags flags; /**< Debug flags */
+ dbg_print_h *ph; /**< Optional print handler */
+ void *arg; /**< Handler argument */
+ FILE *f; /**< Logfile */
+#ifdef HAVE_PTHREAD
+ pthread_mutex_t mutex; /**< Thread locking */
+#endif
+} dbg = {
+ 0,
+ DBG_INFO,
+ DBG_ANSI,
+ NULL,
+ NULL,
+ NULL,
+#ifdef HAVE_PTHREAD
+ PTHREAD_MUTEX_INITIALIZER,
+#endif
+};
+
+
+#ifdef HAVE_PTHREAD
+static inline void dbg_lock(void)
+{
+ pthread_mutex_lock(&dbg.mutex);
+}
+
+
+static inline void dbg_unlock(void)
+{
+ pthread_mutex_unlock(&dbg.mutex);
+}
+#else
+#define dbg_lock() /**< Stub */
+#define dbg_unlock() /**< Stub */
+#endif
+
+
+/**
+ * Initialise debug printing
+ *
+ * @param level Debug level
+ * @param flags Debug flags
+ */
+void dbg_init(int level, enum dbg_flags flags)
+{
+ dbg.tick = tmr_jiffies();
+ dbg.level = level;
+ dbg.flags = flags;
+}
+
+
+/**
+ * Close debugging
+ */
+void dbg_close(void)
+{
+ if (dbg.f) {
+ (void)fclose(dbg.f);
+ dbg.f = NULL;
+ }
+}
+
+
+/**
+ * Set debug logfile
+ *
+ * @param name Name of the logfile, NULL to close
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int dbg_logfile_set(const char *name)
+{
+ time_t t;
+
+ dbg_close();
+
+ if (!name)
+ return 0;
+
+ dbg.f = fopen(name, "a+");
+ if (!dbg.f)
+ return errno;
+
+ (void)time(&t);
+ (void)re_fprintf(dbg.f, "\n===== Log Started: %s", ctime(&t));
+ (void)fflush(dbg.f);
+
+ return 0;
+}
+
+
+/**
+ * Set optional debug print handler
+ *
+ * @param ph Print handler
+ * @param arg Handler argument
+ */
+void dbg_handler_set(dbg_print_h *ph, void *arg)
+{
+ dbg.ph = ph;
+ dbg.arg = arg;
+}
+
+
+/* NOTE: This function should not allocate memory */
+static void dbg_vprintf(int level, const char *fmt, va_list ap)
+{
+ if (level > dbg.level)
+ return;
+
+ /* Print handler? */
+ if (dbg.ph)
+ return;
+
+ dbg_lock();
+
+ if (dbg.flags & DBG_ANSI) {
+
+ switch (level) {
+
+ case DBG_WARNING:
+ (void)re_fprintf(stderr, "\x1b[31m"); /* Red */
+ break;
+
+ case DBG_NOTICE:
+ (void)re_fprintf(stderr, "\x1b[33m"); /* Yellow */
+ break;
+
+ case DBG_INFO:
+ (void)re_fprintf(stderr, "\x1b[32m"); /* Green */
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (dbg.flags & DBG_TIME) {
+ const uint64_t ticks = tmr_jiffies();
+
+ if (0 == dbg.tick)
+ dbg.tick = tmr_jiffies();
+
+ (void)re_fprintf(stderr, "[%09llu] ", ticks - dbg.tick);
+ }
+
+ (void)re_vfprintf(stderr, fmt, ap);
+
+ if (dbg.flags & DBG_ANSI && level < DBG_DEBUG)
+ (void)re_fprintf(stderr, "\x1b[;m");
+
+ dbg_unlock();
+}
+
+
+/* Formatted output to print handler and/or logfile */
+static void dbg_fmt_vprintf(int level, const char *fmt, va_list ap)
+{
+ char buf[256];
+ int len;
+
+ if (level > dbg.level)
+ return;
+
+ if (!dbg.ph && !dbg.f)
+ return;
+
+ dbg_lock();
+
+ len = re_vsnprintf(buf, sizeof(buf), fmt, ap);
+ if (len <= 0)
+ goto out;
+
+ /* Print handler? */
+ if (dbg.ph) {
+ dbg.ph(level, buf, len, dbg.arg);
+ }
+
+ /* Output to file */
+ if (dbg.f) {
+ if (fwrite(buf, 1, len, dbg.f) > 0)
+ (void)fflush(dbg.f);
+ }
+
+ out:
+ dbg_unlock();
+}
+
+
+/**
+ * Print a formatted debug message
+ *
+ * @param level Debug level
+ * @param fmt Formatted string
+ */
+void dbg_printf(int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ dbg_vprintf(level, fmt, ap);
+ va_end(ap);
+
+ va_start(ap, fmt);
+ dbg_fmt_vprintf(level, fmt, ap);
+ va_end(ap);
+}
+
+
+/**
+ * Print a formatted debug message to /dev/null
+ *
+ * @param fmt Formatted string
+ */
+void dbg_noprintf(const char *fmt, ...)
+{
+ (void)fmt;
+}
+
+
+/**
+ * Print a formatted warning message
+ *
+ * @param fmt Formatted string
+ */
+void dbg_warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ dbg_vprintf(DBG_WARNING, fmt, ap);
+ va_end(ap);
+
+ va_start(ap, fmt);
+ dbg_fmt_vprintf(DBG_WARNING, fmt, ap);
+ va_end(ap);
+}
+
+
+/**
+ * Print a formatted notice message
+ *
+ * @param fmt Formatted string
+ */
+void dbg_notice(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ dbg_vprintf(DBG_NOTICE, fmt, ap);
+ va_end(ap);
+
+ va_start(ap, fmt);
+ dbg_fmt_vprintf(DBG_NOTICE, fmt, ap);
+ va_end(ap);
+}
+
+
+/**
+ * Print a formatted info message
+ *
+ * @param fmt Formatted string
+ */
+void dbg_info(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ dbg_vprintf(DBG_INFO, fmt, ap);
+ va_end(ap);
+
+ va_start(ap, fmt);
+ dbg_fmt_vprintf(DBG_INFO, fmt, ap);
+ va_end(ap);
+}
+
+
+/**
+ * Get the name of the debug level
+ *
+ * @param level Debug level
+ *
+ * @return String with debug level name
+ */
+const char *dbg_level_str(int level)
+{
+ switch (level) {
+
+ case DBG_EMERG: return "EMERGENCY";
+ case DBG_ALERT: return "ALERT";
+ case DBG_CRIT: return "CRITICAL";
+ case DBG_ERR: return "ERROR";
+ case DBG_WARNING: return "WARNING";
+ case DBG_NOTICE: return "NOTICE";
+ case DBG_INFO: return "INFO";
+ case DBG_DEBUG: return "DEBUG";
+ default: return "???";
+ }
+}