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