improve feature test for memrchr() making it also available on BSD

Thu, 02 Oct 2025 21:21:45 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 02 Oct 2025 21:21:45 +0200
changeset 1413
c5a225d7228c
parent 1412
a6f357c18ac6
child 1414
597cf869e8bc

improve feature test for memrchr() making it also available on BSD

configure file | annotate | diff | comparison | revisions
make/configure.vm file | annotate | diff | comparison | revisions
make/project.xml file | annotate | diff | comparison | revisions
make/test_memrchr.c file | annotate | diff | comparison | revisions
src/string.c file | annotate | diff | comparison | revisions
--- a/configure	Thu Oct 02 17:58:43 2025 +0200
+++ b/configure	Thu Oct 02 21:21:45 2025 +0200
@@ -115,6 +115,7 @@
   --enable-api-docs       run Doxygen during build
   --enable-coverage       test coverage with gcov
   --enable-asan           address sanitizer
+  --disable-memrchr
   --disable-cxx-tests     the check-cxx makefile target
   --disable-szmul-builtin use custom implementation, instead
 
@@ -161,6 +162,7 @@
 fi
 
 # features
+FEATURE_MEMRCHR=auto
 FEATURE_CXX_TESTS=auto
 FEATURE_SZMUL_BUILTIN=auto
 
@@ -195,6 +197,8 @@
         "--disable-coverage") unset FEATURE_COVERAGE ;;
         "--enable-asan") FEATURE_ASAN=on ;;
         "--disable-asan") unset FEATURE_ASAN ;;
+        "--enable-memrchr") FEATURE_MEMRCHR=on ;;
+        "--disable-memrchr") unset FEATURE_MEMRCHR ;;
         "--enable-cxx-tests") FEATURE_CXX_TESTS=on ;;
         "--disable-cxx-tests") unset FEATURE_CXX_TESTS ;;
         "--enable-szmul-builtin") FEATURE_SZMUL_BUILTIN=on ;;
@@ -349,7 +353,7 @@
         if notistoolchain "gcc"; then
             break
         fi
-        if command -v gcovr > /dev/null ; then
+        if command -v gcovr > /dev/null 2>&1 ; then
             :
         else
             break
@@ -497,13 +501,48 @@
     dep_checked_file_tools=1
     return 0
 }
+dependency_error_memrchr()
+{
+    print_check_msg "$dep_checked_memrchr" "checking for memrchr... "
+    # dependency memrchr
+    while true
+    do
+        if $TOOLCHAIN_CC -o /dev/null make/test_memrchr.c > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        TEMP_CFLAGS="$TEMP_CFLAGS -DWITH_MEMRCHR"
+        print_check_msg "$dep_checked_memrchr" "yes\n"
+        dep_checked_memrchr=1
+        return 1
+    done
+
+    # dependency memrchr
+    while true
+    do
+        if $TOOLCHAIN_CC -o /dev/null -D_GNU_SOURCE make/test_memrchr.c > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        TEMP_CFLAGS="$TEMP_CFLAGS -DWITH_MEMRCHR -DMEMRCHR_NEED_GNU"
+        print_check_msg "$dep_checked_memrchr" "yes\n"
+        dep_checked_memrchr=1
+        return 1
+    done
+
+    print_check_msg "$dep_checked_memrchr" "no\n"
+    dep_checked_memrchr=1
+    return 0
+}
 dependency_error_doxygen()
 {
     print_check_msg "$dep_checked_doxygen" "checking for doxygen... "
     # dependency doxygen
     while true
     do
-        if test -n "$DOXYGEN" > /dev/null ; then
+        if test -n "$DOXYGEN" > /dev/null 2>&1 ; then
             :
         else
             break
@@ -527,7 +566,7 @@
     # dependency no_coverage
     while true
     do
-        if test -z "$FEATURE_COVERAGE" > /dev/null ; then
+        if test -z "$FEATURE_COVERAGE" > /dev/null 2>&1 ; then
             :
         else
             break
@@ -697,6 +736,26 @@
 else
     :
 fi
+if [ -n "$FEATURE_MEMRCHR" ]; then
+    # check dependency
+    if dependency_error_memrchr ; then
+        # "auto" features can fail and are just disabled in this case
+        if [ "$FEATURE_MEMRCHR" = "auto" ]; then
+            DISABLE_FEATURE_MEMRCHR=1
+        else
+            DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED memrchr "
+            ERROR=1
+        fi
+    fi
+    if [ -n "$DISABLE_FEATURE_MEMRCHR" ]; then
+        unset FEATURE_MEMRCHR
+    fi
+fi
+if [ -n "$FEATURE_MEMRCHR" ]; then
+    :
+else
+    :
+fi
 if [ -n "$FEATURE_CXX_TESTS" ]; then
     # check dependency
     if dependency_error_cxx ; then
@@ -843,6 +902,11 @@
 else
 echo "  asan: off"
 fi
+if [ -n "$FEATURE_MEMRCHR" ]; then
+echo "  memrchr: on"
+else
+echo "  memrchr: off"
+fi
 if [ -n "$FEATURE_CXX_TESTS" ]; then
 echo "  cxx-tests: on"
 else
--- a/make/configure.vm	Thu Oct 02 17:58:43 2025 +0200
+++ b/make/configure.vm	Thu Oct 02 21:21:45 2025 +0200
@@ -400,7 +400,7 @@
         fi
         #end
         #foreach( $test in $sub.tests )
-        if $test > /dev/null ; then
+        if $test > /dev/null 2>&1 ; then
             :
         else
             break
@@ -502,7 +502,6 @@
 
         #foreach( $flags in $dependency.flags )
         #if( $flags.exec )
-        $flags.value > /dev/null
         if tmp_flags=`$flags.value` ; then
             TEMP_$flags.varName="$TEMP_$flags.varName $tmp_flags"
         else
--- a/make/project.xml	Thu Oct 02 17:58:43 2025 +0200
+++ b/make/project.xml	Thu Oct 02 21:21:45 2025 +0200
@@ -89,6 +89,16 @@
         <test>test -z "$FEATURE_COVERAGE"</test>
     </dependency>
 
+    <dependency name="memrchr">
+        <test>$TOOLCHAIN_CC -o /dev/null make/test_memrchr.c</test>
+        <cflags>-DWITH_MEMRCHR</cflags>
+    </dependency>
+
+    <dependency name="memrchr">
+        <test>$TOOLCHAIN_CC -o /dev/null -D_GNU_SOURCE make/test_memrchr.c</test>
+        <cflags>-DWITH_MEMRCHR -DMEMRCHR_NEED_GNU</cflags>
+    </dependency>
+
     <target>
         <feature name="api-docs">
             <dependencies>doxygen</dependencies>
@@ -106,6 +116,9 @@
             <desc>address sanitizer</desc>
             <dependencies>asan</dependencies>
         </feature>
+        <feature name="memrchr" default="true">
+            <dependencies>memrchr</dependencies>
+        </feature>
         <feature name="cxx-tests" default="true">
             <dependencies>cxx</dependencies>
             <desc>the check-cxx makefile target</desc>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/test_memrchr.c	Thu Oct 02 21:21:45 2025 +0200
@@ -0,0 +1,6 @@
+#include <string.h>
+
+int main() {
+    const char *r = memrchr("tester", 'e', 6);
+    return !(r != NULL);
+}
--- a/src/string.c	Thu Oct 02 17:58:43 2025 +0200
+++ b/src/string.c	Thu Oct 02 21:21:45 2025 +0200
@@ -25,14 +25,13 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+#ifdef MEMRCHR_NEED_GNU
 #define _GNU_SOURCE
-#include <string.h>
-#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >=2
-#define FEATURE_MEMRCHR_AVAILABLE
 #endif
 
 #include "cx/string.h"
 
+#include <string.h>
 #include <stdarg.h>
 #include <assert.h>
 #include <errno.h>
@@ -239,7 +238,7 @@
     cxstring string,
     int chr
 ) {
-#ifdef FEATURE_MEMRCHR_AVAILABLE
+#ifdef WITH_MEMRCHR
     char *ret = memrchr(string.ptr, 0xFF & chr, string.length);
     if (ret == NULL) return (cxstring) {NULL, 0};
     return (cxstring) {ret, string.length - (ret - string.ptr)};
@@ -248,7 +247,6 @@
     size_t i = string.length;
     while (i > 0) {
         i--;
-        // TODO: improve by comparing multiple bytes at once
         if (string.ptr[i] == chr) {
             return cx_strsubs(string, i);
         }

mercurial