]>
git.ipfire.org Git - thirdparty/bash.git/blob - lib/glob/fnmatch.c
1 /* Copyright (C) 1991 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
22 #if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS)
28 /* Match STRING against the filename pattern PATTERN, returning zero if
29 it matches, FNM_NOMATCH if not. */
31 fnmatch (pattern
, string
, flags
)
36 register char *p
= pattern
, *n
= string
;
39 if ((flags
& ~__FNM_FLAGS
) != 0)
45 while ((c
= *p
++) != '\0')
52 else if ((flags
& FNM_PATHNAME
) && *n
== '/')
53 /* If we are matching a pathname, `?' can never match a `/'. */
55 else if ((flags
& FNM_PERIOD
) && *n
== '.' &&
56 (n
== string
|| ((flags
& FNM_PATHNAME
) && n
[-1] == '/')))
57 /* `?' cannot match a `.' if it is the first character of the
58 string or if it is the first character following a slash and
59 we are matching a pathname. */
64 if (!(flags
& FNM_NOESCAPE
))
75 if ((flags
& FNM_PERIOD
) && *n
== '.' &&
76 (n
== string
|| ((flags
& FNM_PATHNAME
) && n
[-1] == '/')))
77 /* `*' cannot match a `.' if it is the first character of the
78 string or if it is the first character following a slash and
79 we are matching a pathname. */
82 /* Collapse multiple consecutive, `*' and `?', but make sure that
83 one character of the string is consumed for each `?'. */
84 for (c
= *p
++; c
== '?' || c
== '*'; c
= *p
++)
86 if ((flags
& FNM_PATHNAME
) && *n
== '/')
87 /* A slash does not match a wildcard under FNM_PATHNAME. */
93 /* One character of the string is consumed in matching
94 this ? wildcard, so *??? won't match if there are
95 fewer than three characters. */
103 /* General case, use recursion. */
105 char c1
= (!(flags
& FNM_NOESCAPE
) && c
== '\\') ? *p
: c
;
106 for (--p
; *n
!= '\0'; ++n
)
107 /* Only call fnmatch if the first character indicates a
109 if ((c
== '[' || *n
== c1
) &&
110 fnmatch (p
, n
, flags
& ~FNM_PERIOD
) == 0)
112 return (FNM_NOMATCH
);
117 /* Nonzero if the sense of the character class is inverted. */
121 return (FNM_NOMATCH
);
123 /* A character class cannot match a `.' if it is the first
124 character of the string or if it is the first character
125 following a slash and we are matching a pathname. */
126 if ((flags
& FNM_PERIOD
) && *n
== '.' &&
127 (n
== string
|| ((flags
& FNM_PATHNAME
) && n
[-1] == '/')))
128 return (FNM_NOMATCH
);
130 /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
131 is not preceded by a backslash and is not part of a bracket
132 expression produces undefined results.' This implementation
133 treats the `[' as just a character to be matched if there is
134 not a closing `]'. This code will have to be changed when
135 POSIX.2 character classes are implemented. */
139 for (np
= p
; np
&& *np
&& *np
!= ']'; np
++)
145 return (FNM_NOMATCH
);
150 not = (*p
== '!' || *p
== '^');
157 register char cstart
, cend
;
159 /* Initialize cstart and cend in case `-' is the last
160 character of the pattern. */
163 if (!(flags
& FNM_NOESCAPE
) && c
== '\\')
167 cstart
= cend
= *p
++;
171 /* [ (unterminated) loses. */
172 return (FNM_NOMATCH
);
176 if ((flags
& FNM_PATHNAME
) && c
== '/')
177 /* [/] can never match. */
178 return (FNM_NOMATCH
);
180 /* This introduces a range, unless the `-' is the last
181 character of the class. Find the end of the range
183 if (c
== '-' && *p
!= ']')
186 if (!(flags
& FNM_NOESCAPE
) && cend
== '\\')
189 return (FNM_NOMATCH
);
194 if (*n
>= cstart
&& *n
<= cend
)
201 return (FNM_NOMATCH
);
205 /* Skip the rest of the [...] that already matched. */
209 /* [... (unterminated) loses. */
210 return (FNM_NOMATCH
);
213 if (!(flags
& FNM_NOESCAPE
) && c
== '\\')
217 /* XXX 1003.2d11 is unclear if this is right. */
222 return (FNM_NOMATCH
);
228 return (FNM_NOMATCH
);
237 return (FNM_NOMATCH
);