1*cb63e24eSchristos /* Copyright (C) 1991-2024 Free Software Foundation, Inc.
22a6b7db3Sskrll
32a6b7db3Sskrll NOTE: This source is derived from an old version taken from the GNU C
42a6b7db3Sskrll Library (glibc).
52a6b7db3Sskrll
62a6b7db3Sskrll This program is free software; you can redistribute it and/or modify it
72a6b7db3Sskrll under the terms of the GNU General Public License as published by the
82a6b7db3Sskrll Free Software Foundation; either version 2, or (at your option) any
92a6b7db3Sskrll later version.
102a6b7db3Sskrll
112a6b7db3Sskrll This program is distributed in the hope that it will be useful,
122a6b7db3Sskrll but WITHOUT ANY WARRANTY; without even the implied warranty of
132a6b7db3Sskrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
142a6b7db3Sskrll GNU General Public License for more details.
152a6b7db3Sskrll
162a6b7db3Sskrll You should have received a copy of the GNU General Public License
172a6b7db3Sskrll along with this program; if not, write to the Free Software
182a6b7db3Sskrll Foundation, 51 Franklin Street - Fifth Floor,
192a6b7db3Sskrll Boston, MA 02110-1301, USA. */
202a6b7db3Sskrll
212a6b7db3Sskrll #ifdef HAVE_CONFIG_H
222a6b7db3Sskrll #if defined (CONFIG_BROKETS)
232a6b7db3Sskrll /* We use <config.h> instead of "config.h" so that a compilation
242a6b7db3Sskrll using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
252a6b7db3Sskrll (which it would do because it found this file in $srcdir). */
262a6b7db3Sskrll #include <config.h>
272a6b7db3Sskrll #else
282a6b7db3Sskrll #include "config.h"
292a6b7db3Sskrll #endif
302a6b7db3Sskrll #endif
312a6b7db3Sskrll
322a6b7db3Sskrll
332a6b7db3Sskrll #ifndef _GNU_SOURCE
342a6b7db3Sskrll #define _GNU_SOURCE
352a6b7db3Sskrll #endif
362a6b7db3Sskrll
372a6b7db3Sskrll /* This code to undef const added in libiberty. */
382a6b7db3Sskrll #ifndef __STDC__
392a6b7db3Sskrll /* This is a separate conditional since some stdc systems
402a6b7db3Sskrll reject `defined (const)'. */
412a6b7db3Sskrll #ifndef const
422a6b7db3Sskrll #define const
432a6b7db3Sskrll #endif
442a6b7db3Sskrll #endif
452a6b7db3Sskrll
462a6b7db3Sskrll #include <errno.h>
472a6b7db3Sskrll #include <fnmatch.h>
482a6b7db3Sskrll #include <safe-ctype.h>
492a6b7db3Sskrll
502a6b7db3Sskrll /* Comment out all this code if we are using the GNU C Library, and are not
512a6b7db3Sskrll actually compiling the library itself. This code is part of the GNU C
522a6b7db3Sskrll Library, but also included in many other GNU distributions. Compiling
532a6b7db3Sskrll and linking in this code is a waste when using the GNU C library
542a6b7db3Sskrll (especially if it is a shared library). Rather than having every GNU
552a6b7db3Sskrll program understand `configure --with-gnu-libc' and omit the object files,
562a6b7db3Sskrll it is simpler to just do this in the source for each such file. */
572a6b7db3Sskrll
582a6b7db3Sskrll #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
592a6b7db3Sskrll
602a6b7db3Sskrll
612a6b7db3Sskrll #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
622a6b7db3Sskrll extern int errno;
632a6b7db3Sskrll #endif
642a6b7db3Sskrll
652a6b7db3Sskrll /* Match STRING against the filename pattern PATTERN, returning zero if
662a6b7db3Sskrll it matches, nonzero if not. */
672a6b7db3Sskrll int
fnmatch(const char * pattern,const char * string,int flags)682a6b7db3Sskrll fnmatch (const char *pattern, const char *string, int flags)
692a6b7db3Sskrll {
702a6b7db3Sskrll register const char *p = pattern, *n = string;
712a6b7db3Sskrll register unsigned char c;
722a6b7db3Sskrll
732a6b7db3Sskrll #define FOLD(c) ((flags & FNM_CASEFOLD) ? TOLOWER (c) : (c))
742a6b7db3Sskrll
752a6b7db3Sskrll while ((c = *p++) != '\0')
762a6b7db3Sskrll {
772a6b7db3Sskrll c = FOLD (c);
782a6b7db3Sskrll
792a6b7db3Sskrll switch (c)
802a6b7db3Sskrll {
812a6b7db3Sskrll case '?':
822a6b7db3Sskrll if (*n == '\0')
832a6b7db3Sskrll return FNM_NOMATCH;
842a6b7db3Sskrll else if ((flags & FNM_FILE_NAME) && *n == '/')
852a6b7db3Sskrll return FNM_NOMATCH;
862a6b7db3Sskrll else if ((flags & FNM_PERIOD) && *n == '.' &&
872a6b7db3Sskrll (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
882a6b7db3Sskrll return FNM_NOMATCH;
892a6b7db3Sskrll break;
902a6b7db3Sskrll
912a6b7db3Sskrll case '\\':
922a6b7db3Sskrll if (!(flags & FNM_NOESCAPE))
932a6b7db3Sskrll {
942a6b7db3Sskrll c = *p++;
952a6b7db3Sskrll c = FOLD (c);
962a6b7db3Sskrll }
972a6b7db3Sskrll if (FOLD ((unsigned char)*n) != c)
982a6b7db3Sskrll return FNM_NOMATCH;
992a6b7db3Sskrll break;
1002a6b7db3Sskrll
1012a6b7db3Sskrll case '*':
1022a6b7db3Sskrll if ((flags & FNM_PERIOD) && *n == '.' &&
1032a6b7db3Sskrll (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1042a6b7db3Sskrll return FNM_NOMATCH;
1052a6b7db3Sskrll
1062a6b7db3Sskrll for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
1072a6b7db3Sskrll if (((flags & FNM_FILE_NAME) && *n == '/') ||
1082a6b7db3Sskrll (c == '?' && *n == '\0'))
1092a6b7db3Sskrll return FNM_NOMATCH;
1102a6b7db3Sskrll
1112a6b7db3Sskrll if (c == '\0')
1122a6b7db3Sskrll return 0;
1132a6b7db3Sskrll
1142a6b7db3Sskrll {
1152a6b7db3Sskrll unsigned char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
1162a6b7db3Sskrll c1 = FOLD (c1);
1172a6b7db3Sskrll for (--p; *n != '\0'; ++n)
1182a6b7db3Sskrll if ((c == '[' || FOLD ((unsigned char)*n) == c1) &&
1192a6b7db3Sskrll fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
1202a6b7db3Sskrll return 0;
1212a6b7db3Sskrll return FNM_NOMATCH;
1222a6b7db3Sskrll }
1232a6b7db3Sskrll
1242a6b7db3Sskrll case '[':
1252a6b7db3Sskrll {
1262a6b7db3Sskrll /* Nonzero if the sense of the character class is inverted. */
1272a6b7db3Sskrll register int negate;
1282a6b7db3Sskrll
1292a6b7db3Sskrll if (*n == '\0')
1302a6b7db3Sskrll return FNM_NOMATCH;
1312a6b7db3Sskrll
1322a6b7db3Sskrll if ((flags & FNM_PERIOD) && *n == '.' &&
1332a6b7db3Sskrll (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
1342a6b7db3Sskrll return FNM_NOMATCH;
1352a6b7db3Sskrll
1362a6b7db3Sskrll negate = (*p == '!' || *p == '^');
1372a6b7db3Sskrll if (negate)
1382a6b7db3Sskrll ++p;
1392a6b7db3Sskrll
1402a6b7db3Sskrll c = *p++;
1412a6b7db3Sskrll for (;;)
1422a6b7db3Sskrll {
1432a6b7db3Sskrll register unsigned char cstart = c, cend = c;
1442a6b7db3Sskrll
1452a6b7db3Sskrll if (!(flags & FNM_NOESCAPE) && c == '\\')
1462a6b7db3Sskrll cstart = cend = *p++;
1472a6b7db3Sskrll
1482a6b7db3Sskrll cstart = cend = FOLD (cstart);
1492a6b7db3Sskrll
1502a6b7db3Sskrll if (c == '\0')
1512a6b7db3Sskrll /* [ (unterminated) loses. */
1522a6b7db3Sskrll return FNM_NOMATCH;
1532a6b7db3Sskrll
1542a6b7db3Sskrll c = *p++;
1552a6b7db3Sskrll c = FOLD (c);
1562a6b7db3Sskrll
1572a6b7db3Sskrll if ((flags & FNM_FILE_NAME) && c == '/')
1582a6b7db3Sskrll /* [/] can never match. */
1592a6b7db3Sskrll return FNM_NOMATCH;
1602a6b7db3Sskrll
1612a6b7db3Sskrll if (c == '-' && *p != ']')
1622a6b7db3Sskrll {
1632a6b7db3Sskrll cend = *p++;
1642a6b7db3Sskrll if (!(flags & FNM_NOESCAPE) && cend == '\\')
1652a6b7db3Sskrll cend = *p++;
1662a6b7db3Sskrll if (cend == '\0')
1672a6b7db3Sskrll return FNM_NOMATCH;
1682a6b7db3Sskrll cend = FOLD (cend);
1692a6b7db3Sskrll
1702a6b7db3Sskrll c = *p++;
1712a6b7db3Sskrll }
1722a6b7db3Sskrll
1732a6b7db3Sskrll if (FOLD ((unsigned char)*n) >= cstart
1742a6b7db3Sskrll && FOLD ((unsigned char)*n) <= cend)
1752a6b7db3Sskrll goto matched;
1762a6b7db3Sskrll
1772a6b7db3Sskrll if (c == ']')
1782a6b7db3Sskrll break;
1792a6b7db3Sskrll }
1802a6b7db3Sskrll if (!negate)
1812a6b7db3Sskrll return FNM_NOMATCH;
1822a6b7db3Sskrll break;
1832a6b7db3Sskrll
1842a6b7db3Sskrll matched:;
1852a6b7db3Sskrll /* Skip the rest of the [...] that already matched. */
1862a6b7db3Sskrll while (c != ']')
1872a6b7db3Sskrll {
1882a6b7db3Sskrll if (c == '\0')
1892a6b7db3Sskrll /* [... (unterminated) loses. */
1902a6b7db3Sskrll return FNM_NOMATCH;
1912a6b7db3Sskrll
1922a6b7db3Sskrll c = *p++;
1932a6b7db3Sskrll if (!(flags & FNM_NOESCAPE) && c == '\\')
1942a6b7db3Sskrll /* XXX 1003.2d11 is unclear if this is right. */
1952a6b7db3Sskrll ++p;
1962a6b7db3Sskrll }
1972a6b7db3Sskrll if (negate)
1982a6b7db3Sskrll return FNM_NOMATCH;
1992a6b7db3Sskrll }
2002a6b7db3Sskrll break;
2012a6b7db3Sskrll
2022a6b7db3Sskrll default:
2032a6b7db3Sskrll if (c != FOLD ((unsigned char)*n))
2042a6b7db3Sskrll return FNM_NOMATCH;
2052a6b7db3Sskrll }
2062a6b7db3Sskrll
2072a6b7db3Sskrll ++n;
2082a6b7db3Sskrll }
2092a6b7db3Sskrll
2102a6b7db3Sskrll if (*n == '\0')
2112a6b7db3Sskrll return 0;
2122a6b7db3Sskrll
2132a6b7db3Sskrll if ((flags & FNM_LEADING_DIR) && *n == '/')
2142a6b7db3Sskrll /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
2152a6b7db3Sskrll return 0;
2162a6b7db3Sskrll
2172a6b7db3Sskrll return FNM_NOMATCH;
2182a6b7db3Sskrll }
2192a6b7db3Sskrll
2202a6b7db3Sskrll #endif /* _LIBC or not __GNU_LIBRARY__. */
221