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 "???";
+	}
+}