From 3686a4ade48bb5c8913eae18c8aef909f8e776fe Mon Sep 17 00:00:00 2001
From: Andrew Bettison <andrewb@zip.com.au>
Date: Thu, 29 Nov 2012 16:44:06 +1030
Subject: [PATCH] Improve new config code to use "log.h"

With all the __whence/__WHENCE__ goodness, ready for integration into servald.
---
 conf_om.c     | 75 +++++++++++++++++++++++----------------------------
 conf_parse.c  |  1 +
 conf_schema.c | 15 +++--------
 config.h      | 46 +++++++++++++++++++------------
 config_test.c | 56 +++++++++++++++++++++++++++++++-------
 log.h         |  1 +
 6 files changed, 113 insertions(+), 81 deletions(-)

diff --git a/conf_om.c b/conf_om.c
index 35d1c02d..d17b9fb4 100644
--- a/conf_om.c
+++ b/conf_om.c
@@ -29,16 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 #include "str.h"
 #include "strbuf.h"
 #include "strbuf_helpers.h"
-
-#define _DEBUGF(F,...) fprintf(stderr, "DEBUG: " F "\n", ##__VA_ARGS__)
-#define _WARNF(F,...) fprintf(stderr, "WARN:  " F "\n", ##__VA_ARGS__)
-#define _WHYF(F,...) fprintf(stderr, "ERROR: " F "\n", ##__VA_ARGS__)
-#define _WHYF_perror(F,...) fprintf(stderr, "ERROR: " F ": %s [errno=%d]\n", ##__VA_ARGS__, strerror(errno), errno)
-#define DEBUGF(F,...) _DEBUGF("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-#define WARNF(F,...) _WARNF("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-#define WHYF(F,...) _WHYF("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-#define WHYF_perror(F,...) _WHYF_perror("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-
+#include "log.h"
 #include "config.h"
 
 void *emalloc(size_t len)
@@ -241,7 +232,7 @@ void cf_dump_node(const struct cf_om_node *node, int indent)
   }
 }
 
-void cf_warn_nodev(const char *file, unsigned line, const struct cf_om_node *node, const char *key, const char *fmt, va_list ap)
+void _cf_warn_nodev(struct __sourceloc __whence, const struct cf_om_node *node, const char *key, const char *fmt, va_list ap)
 {
   strbuf b = strbuf_alloca(1024);
   if (node) {
@@ -256,61 +247,61 @@ void cf_warn_nodev(const char *file, unsigned line, const struct cf_om_node *nod
     strbuf_puts(b, "\" ");
   }
   strbuf_vsprintf(b, fmt, ap);
-  _WARNF("%s:%u  %s", file, line, strbuf_str(b));
+  WARN(strbuf_str(b));
 }
 
-void cf_warn_childrenv(const char *file, unsigned line, const struct cf_om_node *parent, const char *fmt, va_list ap)
+void _cf_warn_childrenv(struct __sourceloc __whence, const struct cf_om_node *parent, const char *fmt, va_list ap)
 {
   int i;
   for (i = 0; i < parent->nodc; ++i) {
-    cf_warn_nodev(file, line, parent->nodv[i], NULL, fmt, ap);
-    cf_warn_childrenv(file, line, parent->nodv[i], fmt, ap);
+    _cf_warn_nodev(__whence, parent->nodv[i], NULL, fmt, ap);
+    _cf_warn_childrenv(__whence, parent->nodv[i], fmt, ap);
   }
 }
 
-void cf_warn_node(const char *file, unsigned line, const struct cf_om_node *node, const char *key, const char *fmt, ...)
+void _cf_warn_node(struct __sourceloc __whence, const struct cf_om_node *node, const char *key, const char *fmt, ...)
 {
   va_list ap;
   va_start(ap, fmt);
-  cf_warn_nodev(file, line, node, key, fmt, ap);
+  _cf_warn_nodev(__whence, node, key, fmt, ap);
   va_end(ap);
 }
 
-void cf_warn_children(const char *file, unsigned line, const struct cf_om_node *node, const char *fmt, ...)
+void _cf_warn_children(struct __sourceloc __whence, const struct cf_om_node *node, const char *fmt, ...)
 {
   va_list ap;
   va_start(ap, fmt);
-  cf_warn_childrenv(file, line, node, fmt, ap);
+  _cf_warn_childrenv(__whence, node, fmt, ap);
   va_end(ap);
 }
 
-void cf_warn_duplicate_node(const struct cf_om_node *parent, const char *key)
+void _cf_warn_duplicate_node(struct __sourceloc __whence, const struct cf_om_node *parent, const char *key)
 {
-  cf_warn_node(__FILE__, __LINE__, parent, key, "is duplicate");
+  _cf_warn_node(__whence, parent, key, "is duplicate");
 }
 
-void cf_warn_missing_node(const struct cf_om_node *parent, const char *key)
+void _cf_warn_missing_node(struct __sourceloc __whence, const struct cf_om_node *parent, const char *key)
 {
-  cf_warn_node(__FILE__, __LINE__, parent, key, "is missing");
+  _cf_warn_node(__whence, parent, key, "is missing");
 }
 
-void cf_warn_spurious_children(const struct cf_om_node *parent)
+void _cf_warn_spurious_children(struct __sourceloc __whence, const struct cf_om_node *parent)
 {
-  cf_warn_children(__FILE__, __LINE__, parent, "spurious");
+  _cf_warn_children(__whence, parent, "spurious");
 }
 
-void cf_warn_unsupported_node(const struct cf_om_node *node)
+void _cf_warn_unsupported_node(struct __sourceloc __whence, const struct cf_om_node *node)
 {
-  cf_warn_node(__FILE__, __LINE__, node, NULL, "not supported");
+  _cf_warn_node(__whence, node, NULL, "not supported");
 }
 
-void cf_warn_unsupported_children(const struct cf_om_node *parent)
+void _cf_warn_unsupported_children(struct __sourceloc __whence, const struct cf_om_node *parent)
 {
   int i;
   for (i = 0; i < parent->nodc; ++i) {
     if (parent->nodv[i]->text)
-      cf_warn_unsupported_node(parent->nodv[i]);
-    cf_warn_unsupported_children(parent->nodv[i]);
+      _cf_warn_unsupported_node(__whence, parent->nodv[i]);
+    _cf_warn_unsupported_children(__whence, parent->nodv[i]);
   }
 }
 
@@ -389,39 +380,39 @@ strbuf strbuf_cf_flag_reason(strbuf sb, int flags)
   return sb;
 }
 
-void cf_warn_node_value(const struct cf_om_node *node, int reason)
+void _cf_warn_node_value(struct __sourceloc __whence, const struct cf_om_node *node, int reason)
 {
   strbuf b = strbuf_alloca(180);
   strbuf_cf_flag_reason(b, reason);
-  cf_warn_node(__FILE__, __LINE__, node, NULL, "value %s %s", alloca_str_toprint(node->text), strbuf_str(b));
+  _cf_warn_node(__whence, node, NULL, "value %s %s", alloca_str_toprint(node->text), strbuf_str(b));
 }
 
-void cf_warn_no_array(const struct cf_om_node *node, int reason)
+void _cf_warn_no_array(struct __sourceloc __whence, const struct cf_om_node *node, int reason)
 {
   strbuf b = strbuf_alloca(180);
   strbuf_cf_flag_reason(b, reason);
-  cf_warn_node(__FILE__, __LINE__, node, NULL, "array discarded -- %s", strbuf_str(b));
+  _cf_warn_node(__whence, node, NULL, "array discarded -- %s", strbuf_str(b));
 }
 
-void cf_warn_array_key(const struct cf_om_node *node, int reason)
+void _cf_warn_array_key(struct __sourceloc __whence, const struct cf_om_node *node, int reason)
 {
   strbuf b = strbuf_alloca(180);
   strbuf_cf_flag_reason(b, reason);
-  cf_warn_node(__FILE__, __LINE__, node, NULL, "array label %s -- %s", alloca_str_toprint(node->key), strbuf_str(b));
+  _cf_warn_node(__whence, node, NULL, "array label %s -- %s", alloca_str_toprint(node->key), strbuf_str(b));
 }
 
-void cf_warn_array_value(const struct cf_om_node *node, int reason)
+void _cf_warn_array_value(struct __sourceloc __whence, const struct cf_om_node *node, int reason)
 {
   strbuf b = strbuf_alloca(180);
   strbuf_cf_flag_reason(b, reason);
   if (node->text)
-    cf_warn_node(__FILE__, __LINE__, node, NULL, "array value %s -- %s", alloca_str_toprint(node->text), strbuf_str(b));
+    _cf_warn_node(__whence, node, NULL, "array value %s -- %s", alloca_str_toprint(node->text), strbuf_str(b));
   else
-    cf_warn_node(__FILE__, __LINE__, node, NULL, "array element -- %s", strbuf_str(b));
+    _cf_warn_node(__whence, node, NULL, "array element -- %s", strbuf_str(b));
 }
 
-void cf_warn_list_overflow(const struct cf_om_node *node)
+void _cf_warn_list_overflow(struct __sourceloc __whence, const struct cf_om_node *node)
 {
-  cf_warn_node(__FILE__, __LINE__, node, NULL, "list overflow");
-  cf_warn_children(__FILE__, __LINE__, node, "list overflow");
+  _cf_warn_node(__whence, node, NULL, "list overflow");
+  _cf_warn_children(__whence, node, "list overflow");
 }
diff --git a/conf_parse.c b/conf_parse.c
index 4f71cce1..e3c8aa88 100644
--- a/conf_parse.c
+++ b/conf_parse.c
@@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 
 #include <assert.h>
+#include "log.h"
 #include "config.h"
 
 // Generate config set-default function definitions, cf_dfl_config_NAME().
diff --git a/conf_schema.c b/conf_schema.c
index 0599fbe7..311794fe 100644
--- a/conf_schema.c
+++ b/conf_schema.c
@@ -25,19 +25,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 #include <assert.h>
 #include <arpa/inet.h>
 
+#include "log.h"
 #include "str.h"
 #include "strbuf.h"
 #include "strbuf_helpers.h"
-
-#define _DEBUGF(F,...) fprintf(stderr, "DEBUG: " F "\n", ##__VA_ARGS__)
-#define _WARNF(F,...) fprintf(stderr, "WARN:  " F "\n", ##__VA_ARGS__)
-#define _WHYF(F,...) fprintf(stderr, "ERROR: " F "\n", ##__VA_ARGS__)
-#define _WHYF_perror(F,...) fprintf(stderr, "ERROR: " F ": %s [errno=%d]\n", ##__VA_ARGS__, strerror(errno), errno)
-#define DEBUGF(F,...) _DEBUGF("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-#define WARNF(F,...) _WARNF("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-#define WHYF(F,...) _WHYF("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-#define WHYF_perror(F,...) _WHYF_perror("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-
 #include "config.h"
 
 int cf_opt_boolean(int *booleanp, const char *text)
@@ -241,7 +232,7 @@ int vld_argv(const struct cf_om_node *parent, struct config_argv *array, int res
     for (i = 1; i < array->ac; ++i) {
       unsigned short key = array->av[i].key;
       if (last_key > key) {
-	cf_warn_node(__FILE__, __LINE__, parent, NULL, "array is not sorted");
+	cf_warn_node(parent, NULL, "array is not sorted");
 	return CFERROR;
       }
       last_key = key;
@@ -503,7 +494,7 @@ int cf_opt_interface_list(struct config_interface_list *listp, const struct cf_o
 	    ++n;
 	    break;
 	  default:
-	    cf_warn_node(__FILE__, __LINE__, node, NULL, "invalid interface rule %s", alloca_str_toprint(buf)); \
+	    cf_warn_node(node, NULL, "invalid interface rule %s", alloca_str_toprint(buf)); \
 	    result |= CFSUB(ret);
 	    break;
 	  }
diff --git a/config.h b/config.h
index c4269f3f..6b0a166b 100644
--- a/config.h
+++ b/config.h
@@ -187,9 +187,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
 #define NELS(a) (sizeof (a) / sizeof *(a))
 
-typedef unsigned long debugflags_t;
-debugflags_t debugFlagMask(const char *flagname);
-
 #define RHIZOME_BUNDLE_KEY_BYTES        32
 
 #define PORT_DNA 4110
@@ -248,20 +245,35 @@ strbuf strbuf_cf_flag_reason(strbuf sb, int flags);
 
 /* Diagnostic functions for use in config schema parsing functions, cf_opt_xxx(). */
 
-void cf_warn_nodev(const char *file, unsigned line, const struct cf_om_node *node, const char *key, const char *fmt, va_list ap);
-void cf_warn_childrenv(const char *file, unsigned line, const struct cf_om_node *parent, const char *fmt, va_list ap);
-void cf_warn_node(const char *file, unsigned line, const struct cf_om_node *node, const char *key, const char *fmt, ...);
-void cf_warn_children(const char *file, unsigned line, const struct cf_om_node *node, const char *fmt, ...);
-void cf_warn_duplicate_node(const struct cf_om_node *parent, const char *key);
-void cf_warn_missing_node(const struct cf_om_node *parent, const char *key);
-void cf_warn_node_value(const struct cf_om_node *node, int reason);
-void cf_warn_no_array(const struct cf_om_node *node, int reason);
-void cf_warn_unsupported_node(const struct cf_om_node *node);
-void cf_warn_unsupported_children(const struct cf_om_node *parent);
-void cf_warn_list_overflow(const struct cf_om_node *node);
-void cf_warn_spurious_children(const struct cf_om_node *parent);
-void cf_warn_array_key(const struct cf_om_node *node, int reason);
-void cf_warn_array_value(const struct cf_om_node *node, int reason);
+void _cf_warn_nodev(struct __sourceloc __whence, const struct cf_om_node *node, const char *key, const char *fmt, va_list ap);
+void _cf_warn_childrenv(struct __sourceloc __whence, const struct cf_om_node *parent, const char *fmt, va_list ap);
+void _cf_warn_node(struct __sourceloc __whence, const struct cf_om_node *node, const char *key, const char *fmt, ...);
+void _cf_warn_children(struct __sourceloc __whence, const struct cf_om_node *node, const char *fmt, ...);
+void _cf_warn_duplicate_node(struct __sourceloc __whence, const struct cf_om_node *parent, const char *key);
+void _cf_warn_missing_node(struct __sourceloc __whence, const struct cf_om_node *parent, const char *key);
+void _cf_warn_node_value(struct __sourceloc __whence, const struct cf_om_node *node, int reason);
+void _cf_warn_no_array(struct __sourceloc __whence, const struct cf_om_node *node, int reason);
+void _cf_warn_unsupported_node(struct __sourceloc __whence, const struct cf_om_node *node);
+void _cf_warn_unsupported_children(struct __sourceloc __whence, const struct cf_om_node *parent);
+void _cf_warn_list_overflow(struct __sourceloc __whence, const struct cf_om_node *node);
+void _cf_warn_spurious_children(struct __sourceloc __whence, const struct cf_om_node *parent);
+void _cf_warn_array_key(struct __sourceloc __whence, const struct cf_om_node *node, int reason);
+void _cf_warn_array_value(struct __sourceloc __whence, const struct cf_om_node *node, int reason);
+
+#define cf_warn_nodev(node, key, fmt, ap)    _cf_warn_nodev(__WHENCE__, node, key, fmt, ap)
+#define cf_warn_childrenv(parent, fmt, ap)   _cf_warn_childrenv(__WHENCE__, parent, fmt, ap)
+#define cf_warn_node(node, key, fmt, ...)    _cf_warn_node(__WHENCE__, node, key, fmt, ##__VA_ARGS__)
+#define cf_warn_children(node, fmt, ...)     _cf_warn_children(__WHENCE__, node, fmt, ##__VA_ARGS__)
+#define cf_warn_duplicate_node(parent, key)  _cf_warn_duplicate_node(__WHENCE__, parent, key)
+#define cf_warn_missing_node(parent, key)    _cf_warn_missing_node(__WHENCE__, parent, key)
+#define cf_warn_node_value(node, reason)     _cf_warn_node_value(__WHENCE__, node, reason)
+#define cf_warn_no_array(node, reason)	     _cf_warn_no_array(__WHENCE__, node, reason)
+#define cf_warn_unsupported_node(node)	     _cf_warn_unsupported_node(__WHENCE__, node)
+#define cf_warn_unsupported_children(parent) _cf_warn_unsupported_children(__WHENCE__, parent)
+#define cf_warn_list_overflow(node)	     _cf_warn_list_overflow(__WHENCE__, node)
+#define cf_warn_spurious_children(parent)    _cf_warn_spurious_children(__WHENCE__, parent)
+#define cf_warn_array_key(node, reason)	     _cf_warn_array_key(__WHENCE__, node, reason)
+#define cf_warn_array_value(node, reason)    _cf_warn_array_value(__WHENCE__, node, reason)
 
 // Generate config struct definitions, struct config_NAME.
 #define STRUCT(__name, __validator...) \
diff --git a/config_test.c b/config_test.c
index 446c5022..7d5aca42 100644
--- a/config_test.c
+++ b/config_test.c
@@ -1,20 +1,12 @@
 #include <stdlib.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 
 #include "str.h"
-
-#define _DEBUGF(F,...) fprintf(stderr, "DEBUG: " F "\n", ##__VA_ARGS__)
-#define _WARNF(F,...) fprintf(stderr, "WARN:  " F "\n", ##__VA_ARGS__)
-#define _WHYF(F,...) fprintf(stderr, "ERROR: " F "\n", ##__VA_ARGS__)
-#define _WHYF_perror(F,...) fprintf(stderr, "ERROR: " F ": %s [errno=%d]\n", ##__VA_ARGS__, strerror(errno), errno)
-#define DEBUGF(F,...) _DEBUGF("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-#define WARNF(F,...) _WARNF("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-#define WHYF(F,...) _WHYF("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-#define WHYF_perror(F,...) _WHYF_perror("%s:%u  " F, __FILE__, __LINE__, ##__VA_ARGS__)
-
+#include "log.h"
 #include "config.h"
 
 int main(int argc, char **argv)
@@ -92,6 +84,50 @@ int main(int argc, char **argv)
   exit(0);
 }
 
+const struct __sourceloc __whence = __NOWHERE__;
+
+static const char *_trimbuildpath(const char *path)
+{
+  /* Remove common path prefix */
+  int lastsep = 0;
+  int i;
+  for (i = 0; __FILE__[i] && path[i]; ++i) {
+    if (i && path[i - 1] == '/')
+      lastsep = i;
+    if (__FILE__[i] != path[i])
+      break;
+  }
+  return &path[lastsep];
+}
+
+void logMessage(int level, struct __sourceloc whence, const char *fmt, ...)
+{
+  const char *levelstr = "UNKWN:";
+  switch (level) {
+    case LOG_LEVEL_FATAL: levelstr = "FATAL:"; break;
+    case LOG_LEVEL_ERROR: levelstr = "ERROR:"; break;
+    case LOG_LEVEL_INFO:  levelstr = "INFO:"; break;
+    case LOG_LEVEL_WARN:  levelstr = "WARN:"; break;
+    case LOG_LEVEL_DEBUG: levelstr = "DEBUG:"; break;
+  }
+  fprintf(stderr, "%s ", levelstr);
+  if (whence.file) {
+    fprintf(stderr, "%s", _trimbuildpath(whence.file));
+    if (whence.line)
+      fprintf(stderr, ":%u", whence.line);
+    if (whence.function)
+      fprintf(stderr, ":%s()", whence.function);
+    fputc(' ', stderr);
+  } else if (whence.function) {
+    fprintf(stderr, "%s() ", whence.function);
+  }
+  va_list ap;
+  va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+  fputc('\n', stderr);
+}
+
 debugflags_t debugFlagMask(const char *flagname)
 {
   if	  (!strcasecmp(flagname,"all"))			return ~0;
diff --git a/log.h b/log.h
index 86a54d5a..aa976f09 100644
--- a/log.h
+++ b/log.h
@@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 #define __SERVALD_LOG_H
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <stdarg.h>
 
 typedef unsigned int debugflags_t;