1*56bb7041Schristos# memmem.m4 serial 27 2*56bb7041Schristosdnl Copyright (C) 2002-2004, 2007-2020 Free Software Foundation, Inc. 3*56bb7041Schristosdnl This file is free software; the Free Software Foundation 4*56bb7041Schristosdnl gives unlimited permission to copy and/or distribute it, 5*56bb7041Schristosdnl with or without modifications, as long as this notice is preserved. 6*56bb7041Schristos 7*56bb7041Schristosdnl Check that memmem is present and functional. 8*56bb7041SchristosAC_DEFUN([gl_FUNC_MEMMEM_SIMPLE], 9*56bb7041Schristos[ 10*56bb7041Schristos dnl Persuade glibc <string.h> to declare memmem(). 11*56bb7041Schristos AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) 12*56bb7041Schristos 13*56bb7041Schristos AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) 14*56bb7041Schristos AC_CHECK_FUNCS([memmem]) 15*56bb7041Schristos if test $ac_cv_func_memmem = yes; then 16*56bb7041Schristos HAVE_MEMMEM=1 17*56bb7041Schristos else 18*56bb7041Schristos HAVE_MEMMEM=0 19*56bb7041Schristos fi 20*56bb7041Schristos AC_CHECK_DECLS_ONCE([memmem]) 21*56bb7041Schristos if test $ac_cv_have_decl_memmem = no; then 22*56bb7041Schristos HAVE_DECL_MEMMEM=0 23*56bb7041Schristos else 24*56bb7041Schristos dnl Detect https://sourceware.org/bugzilla/show_bug.cgi?id=12092. 25*56bb7041Schristos dnl Also check that we handle empty needles correctly. 26*56bb7041Schristos AC_CACHE_CHECK([whether memmem works], 27*56bb7041Schristos [gl_cv_func_memmem_works_always], 28*56bb7041Schristos [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ 29*56bb7041Schristos#include <string.h> /* for memmem */ 30*56bb7041Schristos#define P "_EF_BF_BD" 31*56bb7041Schristos#define HAYSTACK "F_BD_CE_BD" P P P P "_C3_88_20" P P P "_C3_A7_20" P 32*56bb7041Schristos#define NEEDLE P P P P P 33*56bb7041Schristos]], [[ 34*56bb7041Schristos int result = 0; 35*56bb7041Schristos if (memmem (HAYSTACK, strlen (HAYSTACK), NEEDLE, strlen (NEEDLE))) 36*56bb7041Schristos result |= 1; 37*56bb7041Schristos /* Check for empty needle behavior. */ 38*56bb7041Schristos { 39*56bb7041Schristos const char *haystack = "AAA"; 40*56bb7041Schristos if (memmem (haystack, 3, (const char *) 1, 0) != haystack) 41*56bb7041Schristos result |= 2; 42*56bb7041Schristos } 43*56bb7041Schristos return result; 44*56bb7041Schristos ]])], 45*56bb7041Schristos [gl_cv_func_memmem_works_always=yes], 46*56bb7041Schristos [gl_cv_func_memmem_works_always=no], 47*56bb7041Schristos [dnl glibc 2.9..2.12 and cygwin 1.7.7 have issue #12092 above. 48*56bb7041Schristos dnl Also empty needles work on glibc >= 2.1 and cygwin >= 1.7.0. 49*56bb7041Schristos dnl uClibc is not affected, since it uses different source code. 50*56bb7041Schristos dnl Assume that it works on all other platforms (even if not linear). 51*56bb7041Schristos AC_EGREP_CPP([Lucky user], 52*56bb7041Schristos [ 53*56bb7041Schristos#ifdef __GNU_LIBRARY__ 54*56bb7041Schristos #include <features.h> 55*56bb7041Schristos #if ((__GLIBC__ == 2 && ((__GLIBC_MINOR > 0 && __GLIBC_MINOR__ < 9) \ 56*56bb7041Schristos || __GLIBC_MINOR__ > 12)) \ 57*56bb7041Schristos || (__GLIBC__ > 2)) \ 58*56bb7041Schristos || defined __UCLIBC__ 59*56bb7041Schristos Lucky user 60*56bb7041Schristos #endif 61*56bb7041Schristos#elif defined __CYGWIN__ 62*56bb7041Schristos #include <cygwin/version.h> 63*56bb7041Schristos #if CYGWIN_VERSION_DLL_COMBINED > CYGWIN_VERSION_DLL_MAKE_COMBINED (1007, 7) 64*56bb7041Schristos Lucky user 65*56bb7041Schristos #endif 66*56bb7041Schristos#else 67*56bb7041Schristos Lucky user 68*56bb7041Schristos#endif 69*56bb7041Schristos ], 70*56bb7041Schristos [gl_cv_func_memmem_works_always="guessing yes"], 71*56bb7041Schristos [gl_cv_func_memmem_works_always="$gl_cross_guess_normal"]) 72*56bb7041Schristos ]) 73*56bb7041Schristos ]) 74*56bb7041Schristos case "$gl_cv_func_memmem_works_always" in 75*56bb7041Schristos *yes) ;; 76*56bb7041Schristos *) 77*56bb7041Schristos REPLACE_MEMMEM=1 78*56bb7041Schristos ;; 79*56bb7041Schristos esac 80*56bb7041Schristos fi 81*56bb7041Schristos gl_PREREQ_MEMMEM 82*56bb7041Schristos]) # gl_FUNC_MEMMEM_SIMPLE 83*56bb7041Schristos 84*56bb7041Schristosdnl Additionally, check that memmem has linear performance characteristics 85*56bb7041SchristosAC_DEFUN([gl_FUNC_MEMMEM], 86*56bb7041Schristos[ 87*56bb7041Schristos AC_REQUIRE([gl_FUNC_MEMMEM_SIMPLE]) 88*56bb7041Schristos if test $HAVE_DECL_MEMMEM = 1 && test $REPLACE_MEMMEM = 0; then 89*56bb7041Schristos AC_CACHE_CHECK([whether memmem works in linear time], 90*56bb7041Schristos [gl_cv_func_memmem_works_fast], 91*56bb7041Schristos [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ 92*56bb7041Schristos#include <signal.h> /* for signal */ 93*56bb7041Schristos#include <string.h> /* for memmem */ 94*56bb7041Schristos#include <stdlib.h> /* for malloc */ 95*56bb7041Schristos#include <unistd.h> /* for alarm */ 96*56bb7041Schristosstatic void quit (int sig) { _exit (sig + 128); } 97*56bb7041Schristos]], [[ 98*56bb7041Schristos int result = 0; 99*56bb7041Schristos size_t m = 1000000; 100*56bb7041Schristos char *haystack = (char *) malloc (2 * m + 1); 101*56bb7041Schristos char *needle = (char *) malloc (m + 1); 102*56bb7041Schristos /* Failure to compile this test due to missing alarm is okay, 103*56bb7041Schristos since all such platforms (mingw) also lack memmem. */ 104*56bb7041Schristos signal (SIGALRM, quit); 105*56bb7041Schristos alarm (5); 106*56bb7041Schristos /* Check for quadratic performance. */ 107*56bb7041Schristos if (haystack && needle) 108*56bb7041Schristos { 109*56bb7041Schristos memset (haystack, 'A', 2 * m); 110*56bb7041Schristos haystack[2 * m] = 'B'; 111*56bb7041Schristos memset (needle, 'A', m); 112*56bb7041Schristos needle[m] = 'B'; 113*56bb7041Schristos if (!memmem (haystack, 2 * m + 1, needle, m + 1)) 114*56bb7041Schristos result |= 1; 115*56bb7041Schristos } 116*56bb7041Schristos /* Free allocated memory, in case some sanitizer is watching. */ 117*56bb7041Schristos free (haystack); 118*56bb7041Schristos free (needle); 119*56bb7041Schristos return result; 120*56bb7041Schristos ]])], 121*56bb7041Schristos [gl_cv_func_memmem_works_fast=yes], [gl_cv_func_memmem_works_fast=no], 122*56bb7041Schristos [dnl Only glibc >= 2.9 and cygwin > 1.7.0 are known to have a 123*56bb7041Schristos dnl memmem that works in linear time. 124*56bb7041Schristos AC_EGREP_CPP([Lucky user], 125*56bb7041Schristos [ 126*56bb7041Schristos#include <features.h> 127*56bb7041Schristos#ifdef __GNU_LIBRARY__ 128*56bb7041Schristos #if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 9) || (__GLIBC__ > 2)) \ 129*56bb7041Schristos && !defined __UCLIBC__ 130*56bb7041Schristos Lucky user 131*56bb7041Schristos #endif 132*56bb7041Schristos#endif 133*56bb7041Schristos#ifdef __CYGWIN__ 134*56bb7041Schristos #include <cygwin/version.h> 135*56bb7041Schristos #if CYGWIN_VERSION_DLL_COMBINED > CYGWIN_VERSION_DLL_MAKE_COMBINED (1007, 0) 136*56bb7041Schristos Lucky user 137*56bb7041Schristos #endif 138*56bb7041Schristos#endif 139*56bb7041Schristos ], 140*56bb7041Schristos [gl_cv_func_memmem_works_fast="guessing yes"], 141*56bb7041Schristos [gl_cv_func_memmem_works_fast="$gl_cross_guess_normal"]) 142*56bb7041Schristos ]) 143*56bb7041Schristos ]) 144*56bb7041Schristos case "$gl_cv_func_memmem_works_fast" in 145*56bb7041Schristos *yes) ;; 146*56bb7041Schristos *) 147*56bb7041Schristos REPLACE_MEMMEM=1 148*56bb7041Schristos ;; 149*56bb7041Schristos esac 150*56bb7041Schristos fi 151*56bb7041Schristos]) # gl_FUNC_MEMMEM 152*56bb7041Schristos 153*56bb7041Schristos# Prerequisites of lib/memmem.c. 154*56bb7041SchristosAC_DEFUN([gl_PREREQ_MEMMEM], [:]) 155