Rework conditional feature usage

Currently, the infrastructure that we have to enable a flexible
compilation environment has a few issues:

 - the allocator configuration is performed at run-time, while the log
   configuration is performed at compile-time

 - for a standard compile (ie, standard userspace, using
   autoconf+automake to build), we need a few pre-defined configuration
   options.

This change adds a bit of runtime selection to the logging
infrastructure, to match the allocator setup. We also unify the
compile-time defines into config.h, using MCTP_-prefixed macro names,
allowing integration into other build systems.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/Makefile.am b/Makefile.am
index 1f3cd2a..b14f3d2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,11 +1,8 @@
 ACLOCAL_AMFLAGS = -I m4
 
-# standalone compilation uses stdio
-libmctp_la_CPPFLAGS = -DMCTP_LOG_STDERR -DMCTP_FILEIO
-
 lib_LTLIBRARIES = libmctp.la
-libmctp_la_SOURCES = core.c alloc.c \
-		     libmctp.h libmctp-alloc.h
+libmctp_la_SOURCES = core.c alloc.c log.c \
+		     libmctp.h libmctp-alloc.h libmctp-log.h
 
 if LIBMCTP_BINDING_serial
 libmctp_la_SOURCES += serial.c libmctp-serial.h
diff --git a/Makefile.inc b/Makefile.inc
index fd63032..1ee555d 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -1,5 +1,5 @@
 LIBMCTP_DIR ?= libmctp/
-LIBMCTP_OBJS = core.o alloc.o
+LIBMCTP_OBJS = core.o alloc.o log.o
 LIBMCTP_BINDINGS ?= serial astlpc
 
 LIBMCTP_OBJS += $(LIBMCTP_BINDINGS:%=%.o)
diff --git a/README.md b/README.md
index 80b0150..ab89bbf 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@
 The libmctp code is intended to be integrated into other codebases by two
 methods:
 
- 1. as a simple library (`libmctp.a`), which can be compiled separately
+ 1. as a simple library (`libmctp.{a,so}`) which can be compiled separately
     and linked into the containing project
 
  2. as a set of sources to be included into the containing project (either
@@ -64,23 +64,16 @@
 For the latter, we need to support customisation of the functions that libmctp
 uses (for example, POSIX file IO is not available).
 
-In order to support these, we have a couple of compile-time definitions:
+In order to support these, we have a few compile-time definitions:
 
- - `MCTP_FILEIO`: define if POSIX file io is available, allowing the
+ - `MCTP_HAVE_FILEIO`: define if POSIX file io is available, allowing the
    serial hardware binding to access char devices for IO.
 
- - `MCTP_LOG_`: allows selection of a logging backend. Currently available
-   are:
+ - `MCTP_HAVE_SYSLOG`: allow logging to syslog, through the `vsyslog`
+   call.
 
-    - `MCTP_LOG_STDERR`: use `fprintf(stderr, ...)` for log output
-
-    - `MCTP_LOG_SYSLOG`: use `syslog()` for log output
-
-    - `MCTP_LOG_CUSTOM`: provide your own macro for logging, of
-      the format: ```#define mctp_prlog(level, fmt, ...) (....)```
-
- - `MCTP_NO_DEFAULT_ALLOC`: do not set default allocator functions (malloc,
-   free, realloc), and require the use of `mctp_set_alloc_ops`.
+ - `MCTP_DEFAULT_ALLOC`: set default allocator functions (malloc, free,
+   realloc), so that applications do not have to provide their own.
 
 TODO
 ----
diff --git a/alloc.c b/alloc.c
index db16d84..1e7da5a 100644
--- a/alloc.c
+++ b/alloc.c
@@ -5,12 +5,16 @@
 #include "libmctp.h"
 #include "libmctp-alloc.h"
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 struct {
 	void	*(*m_alloc)(size_t);
 	void	(*m_free)(void *);
 	void	*(*m_realloc)(void *, size_t);
 } alloc_ops = {
-#ifndef MCTP_NO_DEFAULT_ALLOC
+#ifdef MCTP_DEFAULT_ALLOC
 	malloc,
 	free,
 	realloc,
diff --git a/configure.ac b/configure.ac
index 334b0a5..a33d1b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,6 +15,14 @@
 # libtool init
 LT_INIT
 
+# Set defaults for standard library compiles. We may want to
+# AC_ARG_WITH these in the future.
+AC_DEFINE([MCTP_HAVE_SYSLOG], [1], [Define to enable syslog])
+AC_DEFINE([MCTP_HAVE_FILEIO], [1], [Define to enable filesystem functions])
+AC_DEFINE([MCTP_DEFAULT_ALLOC], [1],
+    [Define to populate allocation functions to defaults (malloc/free)])
+
+# Enable all bindings. AC_ARG_ENABLE in future.
 AM_CONDITIONAL([LIBMCTP_BINDING_serial], [true])
 AM_CONDITIONAL([LIBMCTP_BINDING_astlpc], [true])
 
diff --git a/libmctp-log.h b/libmctp-log.h
index 1024913..001374b 100644
--- a/libmctp-log.h
+++ b/libmctp-log.h
@@ -4,44 +4,18 @@
 #define _LIBMCTP_LOG_H
 
 /* libmctp-internal logging */
-#ifndef pr_fmt
-#define pr_fmt
-#endif
 
-#if defined(MCTP_LOG_STDERR)
+/* these should match the syslog-standard LOG_* definitions, for
+ * easier use with syslog */
+#define MCTP_LOG_ERR		3
+#define MCTP_LOG_WARNING	4
+#define MCTP_LOG_NOTICE		5
+#define MCTP_LOG_INFO		6
+#define MCTP_LOG_DEBUG		7
 
-#include <stdio.h>
-
-#define MCTP_LOG_ERR		0
-#define MCTP_LOG_WARNING	0
-#define MCTP_LOG_NOTICE		0
-#define MCTP_LOG_INFO		0
-#define MCTP_LOG_DEBUG		0
-
-#define mctp_prlog(x, fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__)
-
-#elif defined(MCTP_LOG_SYSLOG)
-
-#include <syslog.h>
-
-#define MCTP_LOG_ERR		LOG_ERR
-#define MCTP_LOG_WARNING	LOG_WARNING
-#define MCTP_LOG_NOTICE		LOG_NOTICE
-#define MCTP_LOG_INFO		LOG_INFO
-#define MCTP_LOG_DEBUG		LOG_DEBUG
-
-#define mctp_prlog(x, fmt, ...) syslog(x, fmt, ##__VA_ARGS__)
-
-#elif defined(MCTP_LOG_CUSTOM)
-
-extern void mctp_prlog(int level, const char *fmt, ...)
+void mctp_prlog(int level, const char *fmt, ...)
 	__attribute__((format(printf, 2, 3)));
 
-
-#else
-#error No log implementation found
-#endif
-
 #define mctp_prerr(fmt, ...)  mctp_prlog(MCTP_LOG_ERR, fmt, ##__VA_ARGS__)
 #define mctp_prwarn(fmt, ...) mctp_prlog(MCTP_LOG_WARNING, fmt, ##__VA_ARGS__)
 #define mctp_prinfo(fmt, ...) mctp_prlog(MCTP_LOG_INFO, fmt, ##__VA_ARGS__)
diff --git a/libmctp.h b/libmctp.h
index 5c0c9f4..e3a125c 100644
--- a/libmctp.h
+++ b/libmctp.h
@@ -7,6 +7,7 @@
 extern "C" {
 #endif
 
+#include <stdarg.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stddef.h>
@@ -102,6 +103,11 @@
 		void (*free)(void *),
 		void *(realloc)(void *, size_t));
 
+/* environment-specific logging */
+void mctp_set_log_stdio(int level);
+void mctp_set_log_syslog(void);
+void mctp_set_log_custom(void (*fn)(int, const char *, va_list));
+
 
 #ifdef __cplusplus
 }
diff --git a/log.c b/log.c
new file mode 100644
index 0000000..12662a3
--- /dev/null
+++ b/log.c
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "libmctp.h"
+#include "libmctp-log.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef MCTP_HAVE_SYSLOG
+#include <syslog.h>
+#endif
+
+enum {
+	MCTP_LOG_NONE,
+	MCTP_LOG_STDIO,
+	MCTP_LOG_SYSLOG,
+	MCTP_LOG_CUSTOM,
+} log_type = MCTP_LOG_NONE;
+
+static int log_stdio_level;
+static void (*log_custom_fn)(int, const char *, va_list);
+
+void mctp_prlog(int level, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+
+	switch (log_type) {
+	case MCTP_LOG_NONE:
+		break;
+	case MCTP_LOG_STDIO:
+		if (level <= log_stdio_level) {
+			vfprintf(stderr, fmt, ap);
+			fputs("\n", stderr);
+		}
+		break;
+	case MCTP_LOG_SYSLOG:
+#ifdef MCTP_HAVE_SYSLOG
+		vsyslog(level, fmt, ap);
+#endif
+		break;
+	case MCTP_LOG_CUSTOM:
+		log_custom_fn(level, fmt, ap);
+		break;
+	}
+
+	va_end(ap);
+}
+
+void mctp_set_log_stdio(int level)
+{
+	log_type = MCTP_LOG_STDIO;
+	log_stdio_level = level;
+}
+
+void mctp_set_log_syslog(void)
+{
+	log_type = MCTP_LOG_SYSLOG;
+}
+
+void mctp_set_log_custom(void (*fn)(int, const char *, va_list))
+{
+	log_type = MCTP_LOG_CUSTOM;
+	log_custom_fn = fn;
+}
diff --git a/serial.c b/serial.c
index 22c1b4b..8c5303b 100644
--- a/serial.c
+++ b/serial.c
@@ -6,7 +6,11 @@
 #include <string.h>
 #include <unistd.h>
 
-#ifdef MCTP_FILEIO
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef MCTP_HAVE_FILEIO
 #include <fcntl.h>
 #endif
 
@@ -243,7 +247,7 @@
 		mctp_rx_consume_one(serial, *(uint8_t *)(buf + i));
 }
 
-#ifdef MCTP_FILEIO
+#ifdef MCTP_HAVE_FILEIO
 int mctp_serial_read(struct mctp_binding_serial *serial)
 {
 	ssize_t len;