From 262d4a1522c38be0588746e874159da5c7bb457d Mon Sep 17 00:00:00 2001
From: David Robillard <d@drobilla.net>
Date: Thu, 9 Feb 2023 23:41:35 -0500
Subject: Improve system feature detection

---
 src/ring.c       |  16 +++----
 src/zix_config.h | 124 +++++++++++++++++++++++++------------------------------
 2 files changed, 65 insertions(+), 75 deletions(-)

(limited to 'src')

diff --git a/src/ring.c b/src/ring.c
index 23199a0..ad00f75 100644
--- a/src/ring.c
+++ b/src/ring.c
@@ -9,10 +9,10 @@
 #include "zix/allocator.h"
 #include "zix/status.h"
 
-#if USE_MLOCK
-#  include <sys/mman.h>
-#elif defined(_WIN32)
+#if defined(_WIN32)
 #  include <windows.h>
+#elif USE_MLOCK
+#  include <sys/mman.h>
 #endif
 
 /*
@@ -108,16 +108,16 @@ zix_ring_free(ZixRing* const ring)
 ZixStatus
 zix_ring_mlock(ZixRing* const ring)
 {
-#if USE_MLOCK
-  return zix_errno_status_if(mlock(ring, sizeof(ZixRing)) +
-                             mlock(ring->buf, ring->size));
-
-#elif defined(_WIN32)
+#if defined(_WIN32)
   return (VirtualLock(ring, sizeof(ZixRing)) &&
           VirtualLock(ring->buf, ring->size))
            ? ZIX_STATUS_SUCCESS
            : ZIX_STATUS_ERROR;
 
+#elif USE_MLOCK
+  return zix_errno_status_if(mlock(ring, sizeof(ZixRing)) +
+                             mlock(ring->buf, ring->size));
+
 #else
   return ZIX_STATUS_NOT_SUPPORTED;
 #endif
diff --git a/src/zix_config.h b/src/zix_config.h
index 7b87826..0aab586 100644
--- a/src/zix_config.h
+++ b/src/zix_config.h
@@ -1,26 +1,35 @@
-// Copyright 2021-2022 David Robillard <d@drobilla.net>
+// Copyright 2021-2023 David Robillard <d@drobilla.net>
 // SPDX-License-Identifier: ISC
 
 /*
-  Configuration header that defines reasonable defaults at compile time.
-
-  This allows compile-time configuration from the command line, while still
-  allowing the source to be built "as-is" without any configuration.  The idea
-  is to support an advanced build system with configuration checks, while still
-  allowing the code to be simply "thrown at a compiler" with features
-  determined from the compiler or system headers.  Everything can be
-  overridden, so it should never be necessary to edit this file to build
-  successfully.
-
-  To ensure that all configure checks are performed, the build system can
-  define ZIX_NO_DEFAULT_CONFIG to disable defaults.  In this case, it must
-  define all HAVE_FEATURE symbols below to 1 or 0 to enable or disable
-  features.  Any missing definitions will generate a compiler warning.
-
-  To ensure that this header is always included properly, all code that uses
-  configuration variables includes this header and checks their value with #if
-  (not #ifdef).  Variables like USE_FEATURE are internal and should never be
-  defined on the command line.
+  Configuration header that defines reasonable defaults at compile-time.
+
+  This allows configuration from the command-line (usually by the build system)
+  while still allowing the code to compile "as-is" with reasonable default
+  features on supported platforms.
+
+  This system is designed so that, ideally, no command-line or build-system
+  configuration is needed, but automatic feature detection can be disabled or
+  overridden for maximum control.  It should never be necessary to edit the
+  source code to achieve a given configuration.
+
+  Usage:
+
+  - By default, features are enabled if they can be detected or assumed to be
+    available from the build environment, unless `ZIX_NO_DEFAULT_CONFIG` is
+    defined, which disables everything by default.
+
+  - If a symbol like `HAVE_SOMETHING` is defined to non-zero, then the
+    "something" feature is assumed to be available.
+
+  Code rules:
+
+  - To check for a feature, this header must be included, and the symbol
+    `USE_SOMETHING` used as a boolean in an `#if` expression.
+
+  - None of the other configuration symbols described here may be used
+    directly.  In particular, this header should be the only place in the
+    source code that touches `HAVE` symbols.
 */
 
 #ifndef ZIX_CONFIG_H
@@ -39,12 +48,17 @@
 #    endif
 #  endif
 
+// Define ZIX_POSIX_VERSION unconditionally for convenience
+#  if defined(_POSIX_VERSION)
+#    define ZIX_POSIX_VERSION _POSIX_VERSION
+#  else
+#    define ZIX_POSIX_VERSION 0
+#  endif
+
 // POSIX.1-2001: clock_gettime()
 #  ifndef HAVE_CLOCK_GETTIME
-#    if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
+#    if ZIX_POSIX_VERSION >= 200112L
 #      define HAVE_CLOCK_GETTIME 1
-#    else
-#      define HAVE_CLOCK_GETTIME 0
 #    endif
 #  endif
 
@@ -52,8 +66,6 @@
 #  ifndef HAVE_CLONEFILE
 #    if defined(__APPLE__) && __has_include(<sys/clonefile.h>)
 #      define HAVE_CLONEFILE 1
-#    else
-#      define HAVE_CLONEFILE 0
 #    endif
 #  endif
 
@@ -63,8 +75,6 @@
       (defined(__GLIBC__) &&                                                 \
        (__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 27))
 #      define HAVE_COPY_FILE_RANGE 1
-#    else
-#      define HAVE_COPY_FILE_RANGE 0
 #    endif
 #  endif
 
@@ -72,8 +82,6 @@
 #  ifndef HAVE_CREATESYMBOLICLINK
 #    if defined(_MSC_VER) && _MSC_VER >= 1910
 #      define HAVE_CREATESYMBOLICLINK 1
-#    else
-#      define HAVE_CREATESYMBOLICLINK 0
 #    endif
 #  endif
 
@@ -81,8 +89,6 @@
 #  ifndef HAVE_FILENO
 #    if defined(_WIN32) || defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
 #      define HAVE_FILENO 1
-#    else
-#      define HAVE_FILENO 0
 #    endif
 #  endif
 
@@ -90,71 +96,55 @@
 #  ifndef HAVE_FLOCK
 #    if defined(__APPLE__) || defined(__unix__)
 #      define HAVE_FLOCK 1
-#    else
-#      define HAVE_FLOCK 0
 #    endif
 #  endif
 
 // POSIX.1-2001: mlock()
 #  ifndef HAVE_MLOCK
-#    if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
+#    if ZIX_POSIX_VERSION >= 200112L
 #      define HAVE_MLOCK 1
-#    else
-#      define HAVE_MLOCK 0
 #    endif
 #  endif
 
 // POSIX.1-2001: pathconf()
 #  ifndef HAVE_PATHCONF
-#    if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
+#    if ZIX_POSIX_VERSION >= 200112L
 #      define HAVE_PATHCONF 1
-#    else
-#      define HAVE_PATHCONF 0
 #    endif
 #  endif
 
 // POSIX.1-2001: posix_fadvise()
 #  ifndef HAVE_POSIX_FADVISE
-#    if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
+#    if ZIX_POSIX_VERSION >= 200112L
 #      define HAVE_POSIX_FADVISE 1
-#    else
-#      define HAVE_POSIX_FADVISE 0
 #    endif
 #  endif
 
 // POSIX.1-2001: posix_memalign()
 #  ifndef HAVE_POSIX_MEMALIGN
-#    if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
+#    if ZIX_POSIX_VERSION >= 200112L
 #      define HAVE_POSIX_MEMALIGN 1
-#    else
-#      define HAVE_POSIX_MEMALIGN 0
 #    endif
 #  endif
 
 // POSIX.1-2001: realpath()
 #  ifndef HAVE_REALPATH
-#    if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
+#    if ZIX_POSIX_VERSION >= 200112L
 #      define HAVE_REALPATH 1
-#    else
-#      define HAVE_REALPATH 0
 #    endif
 #  endif
 
 // POSIX.1-2001: sem_timedwait()
 #  ifndef HAVE_SEM_TIMEDWAIT
-#    if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
+#    if ZIX_POSIX_VERSION >= 200112L
 #      define HAVE_SEM_TIMEDWAIT 1
-#    else
-#      define HAVE_SEM_TIMEDWAIT 0
 #    endif
 #  endif
 
 // POSIX.1-2001: sysconf()
 #  ifndef HAVE_SYSCONF
-#    if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
+#    if ZIX_POSIX_VERSION >= 200112L
 #      define HAVE_SYSCONF 1
-#    else
-#      define HAVE_SYSCONF 0
 #    endif
 #  endif
 
@@ -168,79 +158,79 @@
   if the build system defines them all.
 */
 
-#if HAVE_CLOCK_GETTIME
+#if defined(HAVE_CLOCK_GETTIME) && HAVE_CLOCK_GETTIME
 #  define USE_CLOCK_GETTIME 1
 #else
 #  define USE_CLOCK_GETTIME 0
 #endif
 
-#if HAVE_CLONEFILE
+#if defined(HAVE_CLONEFILE) && HAVE_CLONEFILE
 #  define USE_CLONEFILE 1
 #else
 #  define USE_CLONEFILE 0
 #endif
 
-#if HAVE_COPY_FILE_RANGE
+#if defined(HAVE_COPY_FILE_RANGE) && HAVE_COPY_FILE_RANGE
 #  define USE_COPY_FILE_RANGE 1
 #else
 #  define USE_COPY_FILE_RANGE 0
 #endif
 
-#if HAVE_CREATESYMBOLICLINK
+#if defined(HAVE_CREATESYMBOLICLINK) && HAVE_CREATESYMBOLICLINK
 #  define USE_CREATESYMBOLICLINK 1
 #else
 #  define USE_CREATESYMBOLICLINK 0
 #endif
 
-#if HAVE_FILENO
+#if defined(HAVE_FILENO) && HAVE_FILENO
 #  define USE_FILENO 1
 #else
 #  define USE_FILENO 0
 #endif
 
-#if HAVE_FLOCK
+#if defined(HAVE_FLOCK) && HAVE_FLOCK
 #  define USE_FLOCK 1
 #else
 #  define USE_FLOCK 0
 #endif
 
-#if HAVE_MLOCK
+#if defined(HAVE_MLOCK) && HAVE_MLOCK
 #  define USE_MLOCK 1
 #else
 #  define USE_MLOCK 0
 #endif
 
-#if HAVE_PATHCONF
+#if defined(HAVE_PATHCONF) && HAVE_PATHCONF
 #  define USE_PATHCONF 1
 #else
 #  define USE_PATHCONF 0
 #endif
 
-#if HAVE_POSIX_FADVISE
+#if defined(HAVE_POSIX_FADVISE) && HAVE_POSIX_FADVISE
 #  define USE_POSIX_FADVISE 1
 #else
 #  define USE_POSIX_FADVISE 0
 #endif
 
-#if HAVE_POSIX_MEMALIGN
+#if defined(HAVE_POSIX_MEMALIGN) && HAVE_POSIX_MEMALIGN
 #  define USE_POSIX_MEMALIGN 1
 #else
 #  define USE_POSIX_MEMALIGN 0
 #endif
 
-#if HAVE_REALPATH
+#if defined(HAVE_REALPATH) && HAVE_REALPATH
 #  define USE_REALPATH 1
 #else
 #  define USE_REALPATH 0
 #endif
 
-#if HAVE_SEM_TIMEDWAIT
+#if defined(HAVE_SEM_TIMEDWAIT) && HAVE_SEM_TIMEDWAIT
 #  define USE_SEM_TIMEDWAIT 1
 #else
 #  define USE_SEM_TIMEDWAIT 0
 #endif
 
-#if HAVE_SYSCONF
+#if defined(HAVE_SYSCONF) && HAVE_SYSCONF
 #  define USE_SYSCONF 1
 #else
 #  define USE_SYSCONF 0
-- 
cgit v1.2.1