bootstrap: Avoid failure when gnulib-tool removed gettext.m4.
[gnulib.git] / m4 / fnmatch.m4
blob6e45b8aa004ad5689a4eebbf8a9bfb78a5f56ed4
1 # fnmatch.m4
2 # serial 21  -*- coding: utf-8 -*-
3 dnl Copyright (C) 2000-2007, 2009-2024 Free Software Foundation, Inc.
4 dnl This file is free software; the Free Software Foundation
5 dnl gives unlimited permission to copy and/or distribute it,
6 dnl with or without modifications, as long as this notice is preserved.
8 # Check for fnmatch
10 # Autoconf defines AC_FUNC_FNMATCH, but that is obsolescent.
11 # New applications should use the macros below instead.
13 # Request a POSIX compliant fnmatch function.
14 AC_DEFUN([gl_FUNC_FNMATCH_POSIX],
16   m4_divert_text([DEFAULTS], [gl_fnmatch_required=POSIX])
18   AC_REQUIRE([gl_FNMATCH_H])
19   AC_REQUIRE([AC_CANONICAL_HOST])
20   gl_fnmatch_required_lowercase=`
21     echo $gl_fnmatch_required | LC_ALL=C tr '[[A-Z]]' '[[a-z]]'
22   `
23   AC_CHECK_FUNCS_ONCE([fnmatch])
24   if test $ac_cv_func_fnmatch = no; then
25     HAVE_FNMATCH=0
26   else
27     gl_fnmatch_cache_var="gl_cv_func_fnmatch_${gl_fnmatch_required_lowercase}"
28     AC_CACHE_CHECK([for working $gl_fnmatch_required fnmatch],
29       [$gl_fnmatch_cache_var],
30       [dnl Some versions of Solaris, SCO, and the GNU C Library
31        dnl have a broken or incompatible fnmatch.
32        dnl So we run a test program.  If we are cross-compiling, take no chance.
33        dnl Thanks to John Oleynick, François Pinard, and Paul Eggert for this
34        dnl test.
35        if test $gl_fnmatch_required = GNU; then
36          gl_fnmatch_gnu_start=
37          gl_fnmatch_gnu_end=
38        else
39          gl_fnmatch_gnu_start='#if 0'
40          gl_fnmatch_gnu_end='#endif'
41        fi
42        AC_RUN_IFELSE(
43          [AC_LANG_PROGRAM(
44             [[#include <fnmatch.h>
45               #include <locale.h>
46               #include <stddef.h>
47               static int
48               y (char const *pattern, char const *string, int flags)
49               {
50                 return fnmatch (pattern, string, flags) == 0;
51               }
52               static int
53               n (char const *pattern, char const *string, int flags)
54               {
55                 return fnmatch (pattern, string, flags) == FNM_NOMATCH;
56               }
57             ]],
58             [[char const *Apat = 'A' < '\\\\' ? "[A-\\\\\\\\]" : "[\\\\\\\\-A]";
59               char const *apat = 'a' < '\\\\' ? "[a-\\\\\\\\]" : "[\\\\\\\\-a]";
60               static char const A_1[] = { 'A' - 1, 0 };
61               static char const A01[] = { 'A' + 1, 0 };
62               static char const a_1[] = { 'a' - 1, 0 };
63               static char const a01[] = { 'a' + 1, 0 };
64               static char const bs_1[] = { '\\\\' - 1, 0 };
65               static char const bs01[] = { '\\\\' + 1, 0 };
66               int result = 0;
67               /* ==== Start of tests in the "C" locale ==== */
68               /* These are sanity checks. They all succeed on current platforms.  */
69               if (!n ("a*", "", 0))
70                 return 1;
71               if (!y ("a*", "abc", 0))
72                 return 1;
73               if (!n ("d*/*1", "d/s/1", FNM_PATHNAME))
74                 return 1;
75               if (!y ("a\\\\bc", "abc", 0))
76                 return 1;
77               if (!n ("a\\\\bc", "abc", FNM_NOESCAPE))
78                 return 1;
79               if (!y ("*x", ".x", 0))
80                 return 1;
81               if (!n ("*x", ".x", FNM_PERIOD))
82                 return 1;
83               /* glibc bug <https://sourceware.org/bugzilla/show_bug.cgi?id=361>
84                  exists in glibc 2.3.3, fixed in glibc 2.5.  */
85               if (!y (Apat, "\\\\", 0))
86                 result |= 2;
87               if (!y (Apat, "A", 0))
88                 result |= 2;
89               if (!y (apat, "\\\\", 0))
90                 result |= 2;
91               if (!y (apat, "a", 0))
92                 result |= 2;
93               if (!(n (Apat, A_1, 0) == ('A' < '\\\\')))
94                 result |= 2;
95               if (!(n (apat, a_1, 0) == ('a' < '\\\\')))
96                 result |= 2;
97               if (!(y (Apat, A01, 0) == ('A' < '\\\\')))
98                 result |= 2;
99               if (!(y (apat, a01, 0) == ('a' < '\\\\')))
100                 result |= 2;
101               if (!(y (Apat, bs_1, 0) == ('A' < '\\\\')))
102                 result |= 2;
103               if (!(y (apat, bs_1, 0) == ('a' < '\\\\')))
104                 result |= 2;
105               if (!(n (Apat, bs01, 0) == ('A' < '\\\\')))
106                 result |= 2;
107               if (!(n (apat, bs01, 0) == ('a' < '\\\\')))
108                 result |= 2;
109               /* glibc bug <https://sourceware.org/bugzilla/show_bug.cgi?id=12378>
110                  exists in glibc 2.12, fixed in glibc 2.13.  */
111               if (!y ("[/b", "[/b", 0)) /*"]]"*/
112                 result |= 4;
113               /* glibc bug <https://sourceware.org/bugzilla/show_bug.cgi?id=17062>
114                  is fixed in glibc 2.20.
115                  glibc bugs <https://sourceware.org/bugzilla/show_bug.cgi?id=18032>
116                             <https://sourceware.org/bugzilla/show_bug.cgi?id=18036>
117                  are fixed in glibc 2.22.
118                  These bugs are not easy to test for reliably (without mmap),
119                  therefore test the glibc version.  */
120               #if defined __GLIBC__
121               if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 22)
122                 result |= 4;
123               #endif
124               /* This test fails on FreeBSD 13.2, NetBSD 10.0, Cygwin 3.4.6.  */
125               if (!y ("[[:alnum:]]", "a", 0))
126                 result |= 8;
127               $gl_fnmatch_gnu_start /* ==== Start of GNU extensions tests ==== */
128               /* Sanity checks, mainly to check the presence of the FNM_* macros.  */
129               if (!y ("xxXX", "xXxX", FNM_CASEFOLD))
130                 result |= 64;
131               if (!y ("a++(x|yy)b", "a+xyyyyxb", FNM_EXTMATCH))
132                 result |= 64;
133               if (!n ("d*/*1", "d/s/1", FNM_FILE_NAME))
134                 result |= 64;
135               if (!y ("*", "x", FNM_FILE_NAME | FNM_LEADING_DIR))
136                 result |= 64;
137               if (!y ("x*", "x/y/z", FNM_FILE_NAME | FNM_LEADING_DIR))
138                 result |= 64;
139               if (!y ("*c*", "c/x", FNM_FILE_NAME | FNM_LEADING_DIR))
140                 result |= 64;
141               $gl_fnmatch_gnu_end /* ==== End of GNU extensions tests ==== */
142               /* ==== End of tests in the "C" locale ==== */
143               /* ==== Start of tests that require a specific locale ==== */
144               /* This test fails on Solaris 11.4.  */
145               if (setlocale (LC_ALL, "en_US.UTF-8") != NULL)
146                 {
147                   if (!n ("[!a-z]", "", 0))
148                     result |= 16;
149                 }
150               /* This test fails on NetBSD 10.0, Android 13.  */
151               if (setlocale (LC_ALL, "C.UTF-8") != NULL)
152                 {
153                   if (!y ("x?y", "x\\303\\274y", 0))
154                     result |= 32;
155                 }
156               /* ==== End of tests that require a specific locale ==== */
157               return result;
158             ]])],
159          [eval "$gl_fnmatch_cache_var=yes"],
160          [eval "$gl_fnmatch_cache_var=no"],
161          [case "$host_os" in
162                                 # Guess yes on musl systems.
163             *-musl* | midipix*) eval "$gl_fnmatch_cache_var=\"guessing yes\"" ;;
164                                 # Guess no otherwise, even on glibc systems.
165             *)                  eval "$gl_fnmatch_cache_var=\"guessing no\"" ;;
166           esac
167          ])
168       ])
169     eval "gl_fnmatch_result=\"\$$gl_fnmatch_cache_var\""
170     case "$gl_fnmatch_result" in
171       *yes) ;;
172       *) REPLACE_FNMATCH=1 ;;
173     esac
174     dnl On AIX 7.2 in 32-bit mode, fnmatch()'s only POSIX compliance problem is
175     dnl that is does not support characters outside the Unicode BMP correctly.
176     dnl Test case: fnmatch ("x?y", "x\360\237\230\213y", 0) == 0
177     dnl This is due to wchar_t being only 16 bits wide.
178     AC_REQUIRE([gl_UCHAR_H])
179     if test $SMALL_WCHAR_T = 1; then
180       case "$host_os" in
181         cygwin*)
182           dnl On Cygwin < 3.5.0, the above $gl_fnmatch_result came out as 'no',
183           dnl On Cygwin >= 3.5.0, fnmatch supports all Unicode characters,
184           dnl despite wchar_t being only 16 bits wide (because internally it
185           dnl works on wint_t values).
186           ;;
187         *)
188           REPLACE_FNMATCH=1
189           ;;
190       esac
191     fi
192   fi
193   if test $HAVE_FNMATCH = 0 || test $REPLACE_FNMATCH = 1; then
194     gl_REPLACE_FNMATCH_H
195   fi
198 # Request a POSIX compliant fnmatch function with GNU extensions.
199 AC_DEFUN([gl_FUNC_FNMATCH_GNU],
201   m4_divert_text([INIT_PREPARE], [gl_fnmatch_required=GNU])
203   AC_REQUIRE([gl_FUNC_FNMATCH_POSIX])
206 AC_DEFUN([gl_PREREQ_FNMATCH],
208   dnl Prerequisites of lib/fnmatch.c.
209   AC_REQUIRE([AC_TYPE_MBSTATE_T])
210   AC_CHECK_FUNCS_ONCE([mbsrtowcs])