1*ef5ccd6cSJohn Marino /* Copyright (C) 1991-1993, 1996-2006, 2009-2012 Free Software Foundation, Inc.
2*ef5ccd6cSJohn Marino This file is part of the GNU C Library.
3*ef5ccd6cSJohn Marino
4*ef5ccd6cSJohn Marino This program is free software; you can redistribute it and/or modify
5*ef5ccd6cSJohn Marino it under the terms of the GNU General Public License as published by
6*ef5ccd6cSJohn Marino the Free Software Foundation; either version 3, or (at your option)
7*ef5ccd6cSJohn Marino any later version.
8*ef5ccd6cSJohn Marino
9*ef5ccd6cSJohn Marino This program is distributed in the hope that it will be useful,
10*ef5ccd6cSJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
11*ef5ccd6cSJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*ef5ccd6cSJohn Marino GNU General Public License for more details.
13*ef5ccd6cSJohn Marino
14*ef5ccd6cSJohn Marino You should have received a copy of the GNU General Public License
15*ef5ccd6cSJohn Marino along with this program; if not, see <http://www.gnu.org/licenses/>. */
16*ef5ccd6cSJohn Marino
17*ef5ccd6cSJohn Marino /* Match STRING against the file name pattern PATTERN, returning zero if
18*ef5ccd6cSJohn Marino it matches, nonzero if not. */
19*ef5ccd6cSJohn Marino static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
20*ef5ccd6cSJohn Marino const CHAR *string_end, bool no_leading_period, int flags)
21*ef5ccd6cSJohn Marino internal_function;
22*ef5ccd6cSJohn Marino static const CHAR *END (const CHAR *patternp) internal_function;
23*ef5ccd6cSJohn Marino
24*ef5ccd6cSJohn Marino static int
25*ef5ccd6cSJohn Marino internal_function
FCT(const CHAR * pattern,const CHAR * string,const CHAR * string_end,bool no_leading_period,int flags)26*ef5ccd6cSJohn Marino FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
27*ef5ccd6cSJohn Marino bool no_leading_period, int flags)
28*ef5ccd6cSJohn Marino {
29*ef5ccd6cSJohn Marino register const CHAR *p = pattern, *n = string;
30*ef5ccd6cSJohn Marino register UCHAR c;
31*ef5ccd6cSJohn Marino #ifdef _LIBC
32*ef5ccd6cSJohn Marino # if WIDE_CHAR_VERSION
33*ef5ccd6cSJohn Marino const char *collseq = (const char *)
34*ef5ccd6cSJohn Marino _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC);
35*ef5ccd6cSJohn Marino # else
36*ef5ccd6cSJohn Marino const UCHAR *collseq = (const UCHAR *)
37*ef5ccd6cSJohn Marino _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB);
38*ef5ccd6cSJohn Marino # endif
39*ef5ccd6cSJohn Marino #endif
40*ef5ccd6cSJohn Marino
41*ef5ccd6cSJohn Marino while ((c = *p++) != L_('\0'))
42*ef5ccd6cSJohn Marino {
43*ef5ccd6cSJohn Marino bool new_no_leading_period = false;
44*ef5ccd6cSJohn Marino c = FOLD (c);
45*ef5ccd6cSJohn Marino
46*ef5ccd6cSJohn Marino switch (c)
47*ef5ccd6cSJohn Marino {
48*ef5ccd6cSJohn Marino case L_('?'):
49*ef5ccd6cSJohn Marino if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
50*ef5ccd6cSJohn Marino {
51*ef5ccd6cSJohn Marino int res;
52*ef5ccd6cSJohn Marino
53*ef5ccd6cSJohn Marino res = EXT (c, p, n, string_end, no_leading_period,
54*ef5ccd6cSJohn Marino flags);
55*ef5ccd6cSJohn Marino if (res != -1)
56*ef5ccd6cSJohn Marino return res;
57*ef5ccd6cSJohn Marino }
58*ef5ccd6cSJohn Marino
59*ef5ccd6cSJohn Marino if (n == string_end)
60*ef5ccd6cSJohn Marino return FNM_NOMATCH;
61*ef5ccd6cSJohn Marino else if (*n == L_('/') && (flags & FNM_FILE_NAME))
62*ef5ccd6cSJohn Marino return FNM_NOMATCH;
63*ef5ccd6cSJohn Marino else if (*n == L_('.') && no_leading_period)
64*ef5ccd6cSJohn Marino return FNM_NOMATCH;
65*ef5ccd6cSJohn Marino break;
66*ef5ccd6cSJohn Marino
67*ef5ccd6cSJohn Marino case L_('\\'):
68*ef5ccd6cSJohn Marino if (!(flags & FNM_NOESCAPE))
69*ef5ccd6cSJohn Marino {
70*ef5ccd6cSJohn Marino c = *p++;
71*ef5ccd6cSJohn Marino if (c == L_('\0'))
72*ef5ccd6cSJohn Marino /* Trailing \ loses. */
73*ef5ccd6cSJohn Marino return FNM_NOMATCH;
74*ef5ccd6cSJohn Marino c = FOLD (c);
75*ef5ccd6cSJohn Marino }
76*ef5ccd6cSJohn Marino if (n == string_end || FOLD ((UCHAR) *n) != c)
77*ef5ccd6cSJohn Marino return FNM_NOMATCH;
78*ef5ccd6cSJohn Marino break;
79*ef5ccd6cSJohn Marino
80*ef5ccd6cSJohn Marino case L_('*'):
81*ef5ccd6cSJohn Marino if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
82*ef5ccd6cSJohn Marino {
83*ef5ccd6cSJohn Marino int res;
84*ef5ccd6cSJohn Marino
85*ef5ccd6cSJohn Marino res = EXT (c, p, n, string_end, no_leading_period,
86*ef5ccd6cSJohn Marino flags);
87*ef5ccd6cSJohn Marino if (res != -1)
88*ef5ccd6cSJohn Marino return res;
89*ef5ccd6cSJohn Marino }
90*ef5ccd6cSJohn Marino
91*ef5ccd6cSJohn Marino if (n != string_end && *n == L_('.') && no_leading_period)
92*ef5ccd6cSJohn Marino return FNM_NOMATCH;
93*ef5ccd6cSJohn Marino
94*ef5ccd6cSJohn Marino for (c = *p++; c == L_('?') || c == L_('*'); c = *p++)
95*ef5ccd6cSJohn Marino {
96*ef5ccd6cSJohn Marino if (*p == L_('(') && (flags & FNM_EXTMATCH) != 0)
97*ef5ccd6cSJohn Marino {
98*ef5ccd6cSJohn Marino const CHAR *endp = END (p);
99*ef5ccd6cSJohn Marino if (endp != p)
100*ef5ccd6cSJohn Marino {
101*ef5ccd6cSJohn Marino /* This is a pattern. Skip over it. */
102*ef5ccd6cSJohn Marino p = endp;
103*ef5ccd6cSJohn Marino continue;
104*ef5ccd6cSJohn Marino }
105*ef5ccd6cSJohn Marino }
106*ef5ccd6cSJohn Marino
107*ef5ccd6cSJohn Marino if (c == L_('?'))
108*ef5ccd6cSJohn Marino {
109*ef5ccd6cSJohn Marino /* A ? needs to match one character. */
110*ef5ccd6cSJohn Marino if (n == string_end)
111*ef5ccd6cSJohn Marino /* There isn't another character; no match. */
112*ef5ccd6cSJohn Marino return FNM_NOMATCH;
113*ef5ccd6cSJohn Marino else if (*n == L_('/')
114*ef5ccd6cSJohn Marino && __builtin_expect (flags & FNM_FILE_NAME, 0))
115*ef5ccd6cSJohn Marino /* A slash does not match a wildcard under
116*ef5ccd6cSJohn Marino FNM_FILE_NAME. */
117*ef5ccd6cSJohn Marino return FNM_NOMATCH;
118*ef5ccd6cSJohn Marino else
119*ef5ccd6cSJohn Marino /* One character of the string is consumed in matching
120*ef5ccd6cSJohn Marino this ? wildcard, so *??? won't match if there are
121*ef5ccd6cSJohn Marino less than three characters. */
122*ef5ccd6cSJohn Marino ++n;
123*ef5ccd6cSJohn Marino }
124*ef5ccd6cSJohn Marino }
125*ef5ccd6cSJohn Marino
126*ef5ccd6cSJohn Marino if (c == L_('\0'))
127*ef5ccd6cSJohn Marino /* The wildcard(s) is/are the last element of the pattern.
128*ef5ccd6cSJohn Marino If the name is a file name and contains another slash
129*ef5ccd6cSJohn Marino this means it cannot match, unless the FNM_LEADING_DIR
130*ef5ccd6cSJohn Marino flag is set. */
131*ef5ccd6cSJohn Marino {
132*ef5ccd6cSJohn Marino int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH;
133*ef5ccd6cSJohn Marino
134*ef5ccd6cSJohn Marino if (flags & FNM_FILE_NAME)
135*ef5ccd6cSJohn Marino {
136*ef5ccd6cSJohn Marino if (flags & FNM_LEADING_DIR)
137*ef5ccd6cSJohn Marino result = 0;
138*ef5ccd6cSJohn Marino else
139*ef5ccd6cSJohn Marino {
140*ef5ccd6cSJohn Marino if (MEMCHR (n, L_('/'), string_end - n) == NULL)
141*ef5ccd6cSJohn Marino result = 0;
142*ef5ccd6cSJohn Marino }
143*ef5ccd6cSJohn Marino }
144*ef5ccd6cSJohn Marino
145*ef5ccd6cSJohn Marino return result;
146*ef5ccd6cSJohn Marino }
147*ef5ccd6cSJohn Marino else
148*ef5ccd6cSJohn Marino {
149*ef5ccd6cSJohn Marino const CHAR *endp;
150*ef5ccd6cSJohn Marino
151*ef5ccd6cSJohn Marino endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L_('/') : L_('\0'),
152*ef5ccd6cSJohn Marino string_end - n);
153*ef5ccd6cSJohn Marino if (endp == NULL)
154*ef5ccd6cSJohn Marino endp = string_end;
155*ef5ccd6cSJohn Marino
156*ef5ccd6cSJohn Marino if (c == L_('[')
157*ef5ccd6cSJohn Marino || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0
158*ef5ccd6cSJohn Marino && (c == L_('@') || c == L_('+') || c == L_('!'))
159*ef5ccd6cSJohn Marino && *p == L_('(')))
160*ef5ccd6cSJohn Marino {
161*ef5ccd6cSJohn Marino int flags2 = ((flags & FNM_FILE_NAME)
162*ef5ccd6cSJohn Marino ? flags : (flags & ~FNM_PERIOD));
163*ef5ccd6cSJohn Marino bool no_leading_period2 = no_leading_period;
164*ef5ccd6cSJohn Marino
165*ef5ccd6cSJohn Marino for (--p; n < endp; ++n, no_leading_period2 = false)
166*ef5ccd6cSJohn Marino if (FCT (p, n, string_end, no_leading_period2, flags2)
167*ef5ccd6cSJohn Marino == 0)
168*ef5ccd6cSJohn Marino return 0;
169*ef5ccd6cSJohn Marino }
170*ef5ccd6cSJohn Marino else if (c == L_('/') && (flags & FNM_FILE_NAME))
171*ef5ccd6cSJohn Marino {
172*ef5ccd6cSJohn Marino while (n < string_end && *n != L_('/'))
173*ef5ccd6cSJohn Marino ++n;
174*ef5ccd6cSJohn Marino if (n < string_end && *n == L_('/')
175*ef5ccd6cSJohn Marino && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags)
176*ef5ccd6cSJohn Marino == 0))
177*ef5ccd6cSJohn Marino return 0;
178*ef5ccd6cSJohn Marino }
179*ef5ccd6cSJohn Marino else
180*ef5ccd6cSJohn Marino {
181*ef5ccd6cSJohn Marino int flags2 = ((flags & FNM_FILE_NAME)
182*ef5ccd6cSJohn Marino ? flags : (flags & ~FNM_PERIOD));
183*ef5ccd6cSJohn Marino int no_leading_period2 = no_leading_period;
184*ef5ccd6cSJohn Marino
185*ef5ccd6cSJohn Marino if (c == L_('\\') && !(flags & FNM_NOESCAPE))
186*ef5ccd6cSJohn Marino c = *p;
187*ef5ccd6cSJohn Marino c = FOLD (c);
188*ef5ccd6cSJohn Marino for (--p; n < endp; ++n, no_leading_period2 = false)
189*ef5ccd6cSJohn Marino if (FOLD ((UCHAR) *n) == c
190*ef5ccd6cSJohn Marino && (FCT (p, n, string_end, no_leading_period2, flags2)
191*ef5ccd6cSJohn Marino == 0))
192*ef5ccd6cSJohn Marino return 0;
193*ef5ccd6cSJohn Marino }
194*ef5ccd6cSJohn Marino }
195*ef5ccd6cSJohn Marino
196*ef5ccd6cSJohn Marino /* If we come here no match is possible with the wildcard. */
197*ef5ccd6cSJohn Marino return FNM_NOMATCH;
198*ef5ccd6cSJohn Marino
199*ef5ccd6cSJohn Marino case L_('['):
200*ef5ccd6cSJohn Marino {
201*ef5ccd6cSJohn Marino /* Nonzero if the sense of the character class is inverted. */
202*ef5ccd6cSJohn Marino const CHAR *p_init = p;
203*ef5ccd6cSJohn Marino const CHAR *n_init = n;
204*ef5ccd6cSJohn Marino register bool not;
205*ef5ccd6cSJohn Marino CHAR cold;
206*ef5ccd6cSJohn Marino UCHAR fn;
207*ef5ccd6cSJohn Marino
208*ef5ccd6cSJohn Marino if (posixly_correct == 0)
209*ef5ccd6cSJohn Marino posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
210*ef5ccd6cSJohn Marino
211*ef5ccd6cSJohn Marino if (n == string_end)
212*ef5ccd6cSJohn Marino return FNM_NOMATCH;
213*ef5ccd6cSJohn Marino
214*ef5ccd6cSJohn Marino if (*n == L_('.') && no_leading_period)
215*ef5ccd6cSJohn Marino return FNM_NOMATCH;
216*ef5ccd6cSJohn Marino
217*ef5ccd6cSJohn Marino if (*n == L_('/') && (flags & FNM_FILE_NAME))
218*ef5ccd6cSJohn Marino /* '/' cannot be matched. */
219*ef5ccd6cSJohn Marino return FNM_NOMATCH;
220*ef5ccd6cSJohn Marino
221*ef5ccd6cSJohn Marino not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^')));
222*ef5ccd6cSJohn Marino if (not)
223*ef5ccd6cSJohn Marino ++p;
224*ef5ccd6cSJohn Marino
225*ef5ccd6cSJohn Marino fn = FOLD ((UCHAR) *n);
226*ef5ccd6cSJohn Marino
227*ef5ccd6cSJohn Marino c = *p++;
228*ef5ccd6cSJohn Marino for (;;)
229*ef5ccd6cSJohn Marino {
230*ef5ccd6cSJohn Marino if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
231*ef5ccd6cSJohn Marino {
232*ef5ccd6cSJohn Marino if (*p == L_('\0'))
233*ef5ccd6cSJohn Marino return FNM_NOMATCH;
234*ef5ccd6cSJohn Marino c = FOLD ((UCHAR) *p);
235*ef5ccd6cSJohn Marino ++p;
236*ef5ccd6cSJohn Marino
237*ef5ccd6cSJohn Marino goto normal_bracket;
238*ef5ccd6cSJohn Marino }
239*ef5ccd6cSJohn Marino else if (c == L_('[') && *p == L_(':'))
240*ef5ccd6cSJohn Marino {
241*ef5ccd6cSJohn Marino /* Leave room for the null. */
242*ef5ccd6cSJohn Marino CHAR str[CHAR_CLASS_MAX_LENGTH + 1];
243*ef5ccd6cSJohn Marino size_t c1 = 0;
244*ef5ccd6cSJohn Marino #if defined _LIBC || WIDE_CHAR_SUPPORT
245*ef5ccd6cSJohn Marino wctype_t wt;
246*ef5ccd6cSJohn Marino #endif
247*ef5ccd6cSJohn Marino const CHAR *startp = p;
248*ef5ccd6cSJohn Marino
249*ef5ccd6cSJohn Marino for (;;)
250*ef5ccd6cSJohn Marino {
251*ef5ccd6cSJohn Marino if (c1 == CHAR_CLASS_MAX_LENGTH)
252*ef5ccd6cSJohn Marino /* The name is too long and therefore the pattern
253*ef5ccd6cSJohn Marino is ill-formed. */
254*ef5ccd6cSJohn Marino return FNM_NOMATCH;
255*ef5ccd6cSJohn Marino
256*ef5ccd6cSJohn Marino c = *++p;
257*ef5ccd6cSJohn Marino if (c == L_(':') && p[1] == L_(']'))
258*ef5ccd6cSJohn Marino {
259*ef5ccd6cSJohn Marino p += 2;
260*ef5ccd6cSJohn Marino break;
261*ef5ccd6cSJohn Marino }
262*ef5ccd6cSJohn Marino if (c < L_('a') || c >= L_('z'))
263*ef5ccd6cSJohn Marino {
264*ef5ccd6cSJohn Marino /* This cannot possibly be a character class name.
265*ef5ccd6cSJohn Marino Match it as a normal range. */
266*ef5ccd6cSJohn Marino p = startp;
267*ef5ccd6cSJohn Marino c = L_('[');
268*ef5ccd6cSJohn Marino goto normal_bracket;
269*ef5ccd6cSJohn Marino }
270*ef5ccd6cSJohn Marino str[c1++] = c;
271*ef5ccd6cSJohn Marino }
272*ef5ccd6cSJohn Marino str[c1] = L_('\0');
273*ef5ccd6cSJohn Marino
274*ef5ccd6cSJohn Marino #if defined _LIBC || WIDE_CHAR_SUPPORT
275*ef5ccd6cSJohn Marino wt = IS_CHAR_CLASS (str);
276*ef5ccd6cSJohn Marino if (wt == 0)
277*ef5ccd6cSJohn Marino /* Invalid character class name. */
278*ef5ccd6cSJohn Marino return FNM_NOMATCH;
279*ef5ccd6cSJohn Marino
280*ef5ccd6cSJohn Marino # if defined _LIBC && ! WIDE_CHAR_VERSION
281*ef5ccd6cSJohn Marino /* The following code is glibc specific but does
282*ef5ccd6cSJohn Marino there a good job in speeding up the code since
283*ef5ccd6cSJohn Marino we can avoid the btowc() call. */
284*ef5ccd6cSJohn Marino if (_ISCTYPE ((UCHAR) *n, wt))
285*ef5ccd6cSJohn Marino goto matched;
286*ef5ccd6cSJohn Marino # else
287*ef5ccd6cSJohn Marino if (ISWCTYPE (BTOWC ((UCHAR) *n), wt))
288*ef5ccd6cSJohn Marino goto matched;
289*ef5ccd6cSJohn Marino # endif
290*ef5ccd6cSJohn Marino #else
291*ef5ccd6cSJohn Marino if ((STREQ (str, L_("alnum")) && isalnum ((UCHAR) *n))
292*ef5ccd6cSJohn Marino || (STREQ (str, L_("alpha")) && isalpha ((UCHAR) *n))
293*ef5ccd6cSJohn Marino || (STREQ (str, L_("blank")) && isblank ((UCHAR) *n))
294*ef5ccd6cSJohn Marino || (STREQ (str, L_("cntrl")) && iscntrl ((UCHAR) *n))
295*ef5ccd6cSJohn Marino || (STREQ (str, L_("digit")) && isdigit ((UCHAR) *n))
296*ef5ccd6cSJohn Marino || (STREQ (str, L_("graph")) && isgraph ((UCHAR) *n))
297*ef5ccd6cSJohn Marino || (STREQ (str, L_("lower")) && islower ((UCHAR) *n))
298*ef5ccd6cSJohn Marino || (STREQ (str, L_("print")) && isprint ((UCHAR) *n))
299*ef5ccd6cSJohn Marino || (STREQ (str, L_("punct")) && ispunct ((UCHAR) *n))
300*ef5ccd6cSJohn Marino || (STREQ (str, L_("space")) && isspace ((UCHAR) *n))
301*ef5ccd6cSJohn Marino || (STREQ (str, L_("upper")) && isupper ((UCHAR) *n))
302*ef5ccd6cSJohn Marino || (STREQ (str, L_("xdigit")) && isxdigit ((UCHAR) *n)))
303*ef5ccd6cSJohn Marino goto matched;
304*ef5ccd6cSJohn Marino #endif
305*ef5ccd6cSJohn Marino c = *p++;
306*ef5ccd6cSJohn Marino }
307*ef5ccd6cSJohn Marino #ifdef _LIBC
308*ef5ccd6cSJohn Marino else if (c == L_('[') && *p == L_('='))
309*ef5ccd6cSJohn Marino {
310*ef5ccd6cSJohn Marino UCHAR str[1];
311*ef5ccd6cSJohn Marino uint32_t nrules =
312*ef5ccd6cSJohn Marino _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
313*ef5ccd6cSJohn Marino const CHAR *startp = p;
314*ef5ccd6cSJohn Marino
315*ef5ccd6cSJohn Marino c = *++p;
316*ef5ccd6cSJohn Marino if (c == L_('\0'))
317*ef5ccd6cSJohn Marino {
318*ef5ccd6cSJohn Marino p = startp;
319*ef5ccd6cSJohn Marino c = L_('[');
320*ef5ccd6cSJohn Marino goto normal_bracket;
321*ef5ccd6cSJohn Marino }
322*ef5ccd6cSJohn Marino str[0] = c;
323*ef5ccd6cSJohn Marino
324*ef5ccd6cSJohn Marino c = *++p;
325*ef5ccd6cSJohn Marino if (c != L_('=') || p[1] != L_(']'))
326*ef5ccd6cSJohn Marino {
327*ef5ccd6cSJohn Marino p = startp;
328*ef5ccd6cSJohn Marino c = L_('[');
329*ef5ccd6cSJohn Marino goto normal_bracket;
330*ef5ccd6cSJohn Marino }
331*ef5ccd6cSJohn Marino p += 2;
332*ef5ccd6cSJohn Marino
333*ef5ccd6cSJohn Marino if (nrules == 0)
334*ef5ccd6cSJohn Marino {
335*ef5ccd6cSJohn Marino if ((UCHAR) *n == str[0])
336*ef5ccd6cSJohn Marino goto matched;
337*ef5ccd6cSJohn Marino }
338*ef5ccd6cSJohn Marino else
339*ef5ccd6cSJohn Marino {
340*ef5ccd6cSJohn Marino const int32_t *table;
341*ef5ccd6cSJohn Marino # if WIDE_CHAR_VERSION
342*ef5ccd6cSJohn Marino const int32_t *weights;
343*ef5ccd6cSJohn Marino const int32_t *extra;
344*ef5ccd6cSJohn Marino # else
345*ef5ccd6cSJohn Marino const unsigned char *weights;
346*ef5ccd6cSJohn Marino const unsigned char *extra;
347*ef5ccd6cSJohn Marino # endif
348*ef5ccd6cSJohn Marino const int32_t *indirect;
349*ef5ccd6cSJohn Marino int32_t idx;
350*ef5ccd6cSJohn Marino const UCHAR *cp = (const UCHAR *) str;
351*ef5ccd6cSJohn Marino
352*ef5ccd6cSJohn Marino /* This #include defines a local function! */
353*ef5ccd6cSJohn Marino # if WIDE_CHAR_VERSION
354*ef5ccd6cSJohn Marino # include <locale/weightwc.h>
355*ef5ccd6cSJohn Marino # else
356*ef5ccd6cSJohn Marino # include <locale/weight.h>
357*ef5ccd6cSJohn Marino # endif
358*ef5ccd6cSJohn Marino
359*ef5ccd6cSJohn Marino # if WIDE_CHAR_VERSION
360*ef5ccd6cSJohn Marino table = (const int32_t *)
361*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC);
362*ef5ccd6cSJohn Marino weights = (const int32_t *)
363*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC);
364*ef5ccd6cSJohn Marino extra = (const int32_t *)
365*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC);
366*ef5ccd6cSJohn Marino indirect = (const int32_t *)
367*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC);
368*ef5ccd6cSJohn Marino # else
369*ef5ccd6cSJohn Marino table = (const int32_t *)
370*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
371*ef5ccd6cSJohn Marino weights = (const unsigned char *)
372*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);
373*ef5ccd6cSJohn Marino extra = (const unsigned char *)
374*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
375*ef5ccd6cSJohn Marino indirect = (const int32_t *)
376*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
377*ef5ccd6cSJohn Marino # endif
378*ef5ccd6cSJohn Marino
379*ef5ccd6cSJohn Marino idx = findidx (&cp);
380*ef5ccd6cSJohn Marino if (idx != 0)
381*ef5ccd6cSJohn Marino {
382*ef5ccd6cSJohn Marino /* We found a table entry. Now see whether the
383*ef5ccd6cSJohn Marino character we are currently at has the same
384*ef5ccd6cSJohn Marino equivalence class value. */
385*ef5ccd6cSJohn Marino int len = weights[idx & 0xffffff];
386*ef5ccd6cSJohn Marino int32_t idx2;
387*ef5ccd6cSJohn Marino const UCHAR *np = (const UCHAR *) n;
388*ef5ccd6cSJohn Marino
389*ef5ccd6cSJohn Marino idx2 = findidx (&np);
390*ef5ccd6cSJohn Marino if (idx2 != 0
391*ef5ccd6cSJohn Marino && (idx >> 24) == (idx2 >> 24)
392*ef5ccd6cSJohn Marino && len == weights[idx2 & 0xffffff])
393*ef5ccd6cSJohn Marino {
394*ef5ccd6cSJohn Marino int cnt = 0;
395*ef5ccd6cSJohn Marino
396*ef5ccd6cSJohn Marino idx &= 0xffffff;
397*ef5ccd6cSJohn Marino idx2 &= 0xffffff;
398*ef5ccd6cSJohn Marino
399*ef5ccd6cSJohn Marino while (cnt < len
400*ef5ccd6cSJohn Marino && (weights[idx + 1 + cnt]
401*ef5ccd6cSJohn Marino == weights[idx2 + 1 + cnt]))
402*ef5ccd6cSJohn Marino ++cnt;
403*ef5ccd6cSJohn Marino
404*ef5ccd6cSJohn Marino if (cnt == len)
405*ef5ccd6cSJohn Marino goto matched;
406*ef5ccd6cSJohn Marino }
407*ef5ccd6cSJohn Marino }
408*ef5ccd6cSJohn Marino }
409*ef5ccd6cSJohn Marino
410*ef5ccd6cSJohn Marino c = *p++;
411*ef5ccd6cSJohn Marino }
412*ef5ccd6cSJohn Marino #endif
413*ef5ccd6cSJohn Marino else if (c == L_('\0'))
414*ef5ccd6cSJohn Marino {
415*ef5ccd6cSJohn Marino /* [ unterminated, treat as normal character. */
416*ef5ccd6cSJohn Marino p = p_init;
417*ef5ccd6cSJohn Marino n = n_init;
418*ef5ccd6cSJohn Marino c = L_('[');
419*ef5ccd6cSJohn Marino goto normal_match;
420*ef5ccd6cSJohn Marino }
421*ef5ccd6cSJohn Marino else
422*ef5ccd6cSJohn Marino {
423*ef5ccd6cSJohn Marino bool is_range = false;
424*ef5ccd6cSJohn Marino
425*ef5ccd6cSJohn Marino #ifdef _LIBC
426*ef5ccd6cSJohn Marino bool is_seqval = false;
427*ef5ccd6cSJohn Marino
428*ef5ccd6cSJohn Marino if (c == L_('[') && *p == L_('.'))
429*ef5ccd6cSJohn Marino {
430*ef5ccd6cSJohn Marino uint32_t nrules =
431*ef5ccd6cSJohn Marino _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
432*ef5ccd6cSJohn Marino const CHAR *startp = p;
433*ef5ccd6cSJohn Marino size_t c1 = 0;
434*ef5ccd6cSJohn Marino
435*ef5ccd6cSJohn Marino while (1)
436*ef5ccd6cSJohn Marino {
437*ef5ccd6cSJohn Marino c = *++p;
438*ef5ccd6cSJohn Marino if (c == L_('.') && p[1] == L_(']'))
439*ef5ccd6cSJohn Marino {
440*ef5ccd6cSJohn Marino p += 2;
441*ef5ccd6cSJohn Marino break;
442*ef5ccd6cSJohn Marino }
443*ef5ccd6cSJohn Marino if (c == '\0')
444*ef5ccd6cSJohn Marino return FNM_NOMATCH;
445*ef5ccd6cSJohn Marino ++c1;
446*ef5ccd6cSJohn Marino }
447*ef5ccd6cSJohn Marino
448*ef5ccd6cSJohn Marino /* We have to handling the symbols differently in
449*ef5ccd6cSJohn Marino ranges since then the collation sequence is
450*ef5ccd6cSJohn Marino important. */
451*ef5ccd6cSJohn Marino is_range = *p == L_('-') && p[1] != L_('\0');
452*ef5ccd6cSJohn Marino
453*ef5ccd6cSJohn Marino if (nrules == 0)
454*ef5ccd6cSJohn Marino {
455*ef5ccd6cSJohn Marino /* There are no names defined in the collation
456*ef5ccd6cSJohn Marino data. Therefore we only accept the trivial
457*ef5ccd6cSJohn Marino names consisting of the character itself. */
458*ef5ccd6cSJohn Marino if (c1 != 1)
459*ef5ccd6cSJohn Marino return FNM_NOMATCH;
460*ef5ccd6cSJohn Marino
461*ef5ccd6cSJohn Marino if (!is_range && *n == startp[1])
462*ef5ccd6cSJohn Marino goto matched;
463*ef5ccd6cSJohn Marino
464*ef5ccd6cSJohn Marino cold = startp[1];
465*ef5ccd6cSJohn Marino c = *p++;
466*ef5ccd6cSJohn Marino }
467*ef5ccd6cSJohn Marino else
468*ef5ccd6cSJohn Marino {
469*ef5ccd6cSJohn Marino int32_t table_size;
470*ef5ccd6cSJohn Marino const int32_t *symb_table;
471*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
472*ef5ccd6cSJohn Marino char str[c1];
473*ef5ccd6cSJohn Marino size_t strcnt;
474*ef5ccd6cSJohn Marino # else
475*ef5ccd6cSJohn Marino # define str (startp + 1)
476*ef5ccd6cSJohn Marino # endif
477*ef5ccd6cSJohn Marino const unsigned char *extra;
478*ef5ccd6cSJohn Marino int32_t idx;
479*ef5ccd6cSJohn Marino int32_t elem;
480*ef5ccd6cSJohn Marino int32_t second;
481*ef5ccd6cSJohn Marino int32_t hash;
482*ef5ccd6cSJohn Marino
483*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
484*ef5ccd6cSJohn Marino /* We have to convert the name to a single-byte
485*ef5ccd6cSJohn Marino string. This is possible since the names
486*ef5ccd6cSJohn Marino consist of ASCII characters and the internal
487*ef5ccd6cSJohn Marino representation is UCS4. */
488*ef5ccd6cSJohn Marino for (strcnt = 0; strcnt < c1; ++strcnt)
489*ef5ccd6cSJohn Marino str[strcnt] = startp[1 + strcnt];
490*ef5ccd6cSJohn Marino # endif
491*ef5ccd6cSJohn Marino
492*ef5ccd6cSJohn Marino table_size =
493*ef5ccd6cSJohn Marino _NL_CURRENT_WORD (LC_COLLATE,
494*ef5ccd6cSJohn Marino _NL_COLLATE_SYMB_HASH_SIZEMB);
495*ef5ccd6cSJohn Marino symb_table = (const int32_t *)
496*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE,
497*ef5ccd6cSJohn Marino _NL_COLLATE_SYMB_TABLEMB);
498*ef5ccd6cSJohn Marino extra = (const unsigned char *)
499*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE,
500*ef5ccd6cSJohn Marino _NL_COLLATE_SYMB_EXTRAMB);
501*ef5ccd6cSJohn Marino
502*ef5ccd6cSJohn Marino /* Locate the character in the hashing table. */
503*ef5ccd6cSJohn Marino hash = elem_hash (str, c1);
504*ef5ccd6cSJohn Marino
505*ef5ccd6cSJohn Marino idx = 0;
506*ef5ccd6cSJohn Marino elem = hash % table_size;
507*ef5ccd6cSJohn Marino if (symb_table[2 * elem] != 0)
508*ef5ccd6cSJohn Marino {
509*ef5ccd6cSJohn Marino second = hash % (table_size - 2) + 1;
510*ef5ccd6cSJohn Marino
511*ef5ccd6cSJohn Marino do
512*ef5ccd6cSJohn Marino {
513*ef5ccd6cSJohn Marino /* First compare the hashing value. */
514*ef5ccd6cSJohn Marino if (symb_table[2 * elem] == hash
515*ef5ccd6cSJohn Marino && (c1
516*ef5ccd6cSJohn Marino == extra[symb_table[2 * elem + 1]])
517*ef5ccd6cSJohn Marino && memcmp (str,
518*ef5ccd6cSJohn Marino &extra[symb_table[2 * elem
519*ef5ccd6cSJohn Marino + 1]
520*ef5ccd6cSJohn Marino + 1], c1) == 0)
521*ef5ccd6cSJohn Marino {
522*ef5ccd6cSJohn Marino /* Yep, this is the entry. */
523*ef5ccd6cSJohn Marino idx = symb_table[2 * elem + 1];
524*ef5ccd6cSJohn Marino idx += 1 + extra[idx];
525*ef5ccd6cSJohn Marino break;
526*ef5ccd6cSJohn Marino }
527*ef5ccd6cSJohn Marino
528*ef5ccd6cSJohn Marino /* Next entry. */
529*ef5ccd6cSJohn Marino elem += second;
530*ef5ccd6cSJohn Marino }
531*ef5ccd6cSJohn Marino while (symb_table[2 * elem] != 0);
532*ef5ccd6cSJohn Marino }
533*ef5ccd6cSJohn Marino
534*ef5ccd6cSJohn Marino if (symb_table[2 * elem] != 0)
535*ef5ccd6cSJohn Marino {
536*ef5ccd6cSJohn Marino /* Compare the byte sequence but only if
537*ef5ccd6cSJohn Marino this is not part of a range. */
538*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
539*ef5ccd6cSJohn Marino int32_t *wextra;
540*ef5ccd6cSJohn Marino
541*ef5ccd6cSJohn Marino idx += 1 + extra[idx];
542*ef5ccd6cSJohn Marino /* Adjust for the alignment. */
543*ef5ccd6cSJohn Marino idx = (idx + 3) & ~3;
544*ef5ccd6cSJohn Marino
545*ef5ccd6cSJohn Marino wextra = (int32_t *) &extra[idx + 4];
546*ef5ccd6cSJohn Marino # endif
547*ef5ccd6cSJohn Marino
548*ef5ccd6cSJohn Marino if (! is_range)
549*ef5ccd6cSJohn Marino {
550*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
551*ef5ccd6cSJohn Marino for (c1 = 0;
552*ef5ccd6cSJohn Marino (int32_t) c1 < wextra[idx];
553*ef5ccd6cSJohn Marino ++c1)
554*ef5ccd6cSJohn Marino if (n[c1] != wextra[1 + c1])
555*ef5ccd6cSJohn Marino break;
556*ef5ccd6cSJohn Marino
557*ef5ccd6cSJohn Marino if ((int32_t) c1 == wextra[idx])
558*ef5ccd6cSJohn Marino goto matched;
559*ef5ccd6cSJohn Marino # else
560*ef5ccd6cSJohn Marino for (c1 = 0; c1 < extra[idx]; ++c1)
561*ef5ccd6cSJohn Marino if (n[c1] != extra[1 + c1])
562*ef5ccd6cSJohn Marino break;
563*ef5ccd6cSJohn Marino
564*ef5ccd6cSJohn Marino if (c1 == extra[idx])
565*ef5ccd6cSJohn Marino goto matched;
566*ef5ccd6cSJohn Marino # endif
567*ef5ccd6cSJohn Marino }
568*ef5ccd6cSJohn Marino
569*ef5ccd6cSJohn Marino /* Get the collation sequence value. */
570*ef5ccd6cSJohn Marino is_seqval = true;
571*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
572*ef5ccd6cSJohn Marino cold = wextra[1 + wextra[idx]];
573*ef5ccd6cSJohn Marino # else
574*ef5ccd6cSJohn Marino /* Adjust for the alignment. */
575*ef5ccd6cSJohn Marino idx += 1 + extra[idx];
576*ef5ccd6cSJohn Marino idx = (idx + 3) & ~4;
577*ef5ccd6cSJohn Marino cold = *((int32_t *) &extra[idx]);
578*ef5ccd6cSJohn Marino # endif
579*ef5ccd6cSJohn Marino
580*ef5ccd6cSJohn Marino c = *p++;
581*ef5ccd6cSJohn Marino }
582*ef5ccd6cSJohn Marino else if (c1 == 1)
583*ef5ccd6cSJohn Marino {
584*ef5ccd6cSJohn Marino /* No valid character. Match it as a
585*ef5ccd6cSJohn Marino single byte. */
586*ef5ccd6cSJohn Marino if (!is_range && *n == str[0])
587*ef5ccd6cSJohn Marino goto matched;
588*ef5ccd6cSJohn Marino
589*ef5ccd6cSJohn Marino cold = str[0];
590*ef5ccd6cSJohn Marino c = *p++;
591*ef5ccd6cSJohn Marino }
592*ef5ccd6cSJohn Marino else
593*ef5ccd6cSJohn Marino return FNM_NOMATCH;
594*ef5ccd6cSJohn Marino }
595*ef5ccd6cSJohn Marino }
596*ef5ccd6cSJohn Marino else
597*ef5ccd6cSJohn Marino # undef str
598*ef5ccd6cSJohn Marino #endif
599*ef5ccd6cSJohn Marino {
600*ef5ccd6cSJohn Marino c = FOLD (c);
601*ef5ccd6cSJohn Marino normal_bracket:
602*ef5ccd6cSJohn Marino
603*ef5ccd6cSJohn Marino /* We have to handling the symbols differently in
604*ef5ccd6cSJohn Marino ranges since then the collation sequence is
605*ef5ccd6cSJohn Marino important. */
606*ef5ccd6cSJohn Marino is_range = (*p == L_('-') && p[1] != L_('\0')
607*ef5ccd6cSJohn Marino && p[1] != L_(']'));
608*ef5ccd6cSJohn Marino
609*ef5ccd6cSJohn Marino if (!is_range && c == fn)
610*ef5ccd6cSJohn Marino goto matched;
611*ef5ccd6cSJohn Marino
612*ef5ccd6cSJohn Marino #if _LIBC
613*ef5ccd6cSJohn Marino /* This is needed if we goto normal_bracket; from
614*ef5ccd6cSJohn Marino outside of is_seqval's scope. */
615*ef5ccd6cSJohn Marino is_seqval = false;
616*ef5ccd6cSJohn Marino #endif
617*ef5ccd6cSJohn Marino
618*ef5ccd6cSJohn Marino cold = c;
619*ef5ccd6cSJohn Marino c = *p++;
620*ef5ccd6cSJohn Marino }
621*ef5ccd6cSJohn Marino
622*ef5ccd6cSJohn Marino if (c == L_('-') && *p != L_(']'))
623*ef5ccd6cSJohn Marino {
624*ef5ccd6cSJohn Marino #if _LIBC
625*ef5ccd6cSJohn Marino /* We have to find the collation sequence
626*ef5ccd6cSJohn Marino value for C. Collation sequence is nothing
627*ef5ccd6cSJohn Marino we can regularly access. The sequence
628*ef5ccd6cSJohn Marino value is defined by the order in which the
629*ef5ccd6cSJohn Marino definitions of the collation values for the
630*ef5ccd6cSJohn Marino various characters appear in the source
631*ef5ccd6cSJohn Marino file. A strange concept, nowhere
632*ef5ccd6cSJohn Marino documented. */
633*ef5ccd6cSJohn Marino uint32_t fcollseq;
634*ef5ccd6cSJohn Marino uint32_t lcollseq;
635*ef5ccd6cSJohn Marino UCHAR cend = *p++;
636*ef5ccd6cSJohn Marino
637*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
638*ef5ccd6cSJohn Marino /* Search in the 'names' array for the characters. */
639*ef5ccd6cSJohn Marino fcollseq = __collseq_table_lookup (collseq, fn);
640*ef5ccd6cSJohn Marino if (fcollseq == ~((uint32_t) 0))
641*ef5ccd6cSJohn Marino /* XXX We don't know anything about the character
642*ef5ccd6cSJohn Marino we are supposed to match. This means we are
643*ef5ccd6cSJohn Marino failing. */
644*ef5ccd6cSJohn Marino goto range_not_matched;
645*ef5ccd6cSJohn Marino
646*ef5ccd6cSJohn Marino if (is_seqval)
647*ef5ccd6cSJohn Marino lcollseq = cold;
648*ef5ccd6cSJohn Marino else
649*ef5ccd6cSJohn Marino lcollseq = __collseq_table_lookup (collseq, cold);
650*ef5ccd6cSJohn Marino # else
651*ef5ccd6cSJohn Marino fcollseq = collseq[fn];
652*ef5ccd6cSJohn Marino lcollseq = is_seqval ? cold : collseq[(UCHAR) cold];
653*ef5ccd6cSJohn Marino # endif
654*ef5ccd6cSJohn Marino
655*ef5ccd6cSJohn Marino is_seqval = false;
656*ef5ccd6cSJohn Marino if (cend == L_('[') && *p == L_('.'))
657*ef5ccd6cSJohn Marino {
658*ef5ccd6cSJohn Marino uint32_t nrules =
659*ef5ccd6cSJohn Marino _NL_CURRENT_WORD (LC_COLLATE,
660*ef5ccd6cSJohn Marino _NL_COLLATE_NRULES);
661*ef5ccd6cSJohn Marino const CHAR *startp = p;
662*ef5ccd6cSJohn Marino size_t c1 = 0;
663*ef5ccd6cSJohn Marino
664*ef5ccd6cSJohn Marino while (1)
665*ef5ccd6cSJohn Marino {
666*ef5ccd6cSJohn Marino c = *++p;
667*ef5ccd6cSJohn Marino if (c == L_('.') && p[1] == L_(']'))
668*ef5ccd6cSJohn Marino {
669*ef5ccd6cSJohn Marino p += 2;
670*ef5ccd6cSJohn Marino break;
671*ef5ccd6cSJohn Marino }
672*ef5ccd6cSJohn Marino if (c == '\0')
673*ef5ccd6cSJohn Marino return FNM_NOMATCH;
674*ef5ccd6cSJohn Marino ++c1;
675*ef5ccd6cSJohn Marino }
676*ef5ccd6cSJohn Marino
677*ef5ccd6cSJohn Marino if (nrules == 0)
678*ef5ccd6cSJohn Marino {
679*ef5ccd6cSJohn Marino /* There are no names defined in the
680*ef5ccd6cSJohn Marino collation data. Therefore we only
681*ef5ccd6cSJohn Marino accept the trivial names consisting
682*ef5ccd6cSJohn Marino of the character itself. */
683*ef5ccd6cSJohn Marino if (c1 != 1)
684*ef5ccd6cSJohn Marino return FNM_NOMATCH;
685*ef5ccd6cSJohn Marino
686*ef5ccd6cSJohn Marino cend = startp[1];
687*ef5ccd6cSJohn Marino }
688*ef5ccd6cSJohn Marino else
689*ef5ccd6cSJohn Marino {
690*ef5ccd6cSJohn Marino int32_t table_size;
691*ef5ccd6cSJohn Marino const int32_t *symb_table;
692*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
693*ef5ccd6cSJohn Marino char str[c1];
694*ef5ccd6cSJohn Marino size_t strcnt;
695*ef5ccd6cSJohn Marino # else
696*ef5ccd6cSJohn Marino # define str (startp + 1)
697*ef5ccd6cSJohn Marino # endif
698*ef5ccd6cSJohn Marino const unsigned char *extra;
699*ef5ccd6cSJohn Marino int32_t idx;
700*ef5ccd6cSJohn Marino int32_t elem;
701*ef5ccd6cSJohn Marino int32_t second;
702*ef5ccd6cSJohn Marino int32_t hash;
703*ef5ccd6cSJohn Marino
704*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
705*ef5ccd6cSJohn Marino /* We have to convert the name to a single-byte
706*ef5ccd6cSJohn Marino string. This is possible since the names
707*ef5ccd6cSJohn Marino consist of ASCII characters and the internal
708*ef5ccd6cSJohn Marino representation is UCS4. */
709*ef5ccd6cSJohn Marino for (strcnt = 0; strcnt < c1; ++strcnt)
710*ef5ccd6cSJohn Marino str[strcnt] = startp[1 + strcnt];
711*ef5ccd6cSJohn Marino # endif
712*ef5ccd6cSJohn Marino
713*ef5ccd6cSJohn Marino table_size =
714*ef5ccd6cSJohn Marino _NL_CURRENT_WORD (LC_COLLATE,
715*ef5ccd6cSJohn Marino _NL_COLLATE_SYMB_HASH_SIZEMB);
716*ef5ccd6cSJohn Marino symb_table = (const int32_t *)
717*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE,
718*ef5ccd6cSJohn Marino _NL_COLLATE_SYMB_TABLEMB);
719*ef5ccd6cSJohn Marino extra = (const unsigned char *)
720*ef5ccd6cSJohn Marino _NL_CURRENT (LC_COLLATE,
721*ef5ccd6cSJohn Marino _NL_COLLATE_SYMB_EXTRAMB);
722*ef5ccd6cSJohn Marino
723*ef5ccd6cSJohn Marino /* Locate the character in the hashing
724*ef5ccd6cSJohn Marino table. */
725*ef5ccd6cSJohn Marino hash = elem_hash (str, c1);
726*ef5ccd6cSJohn Marino
727*ef5ccd6cSJohn Marino idx = 0;
728*ef5ccd6cSJohn Marino elem = hash % table_size;
729*ef5ccd6cSJohn Marino if (symb_table[2 * elem] != 0)
730*ef5ccd6cSJohn Marino {
731*ef5ccd6cSJohn Marino second = hash % (table_size - 2) + 1;
732*ef5ccd6cSJohn Marino
733*ef5ccd6cSJohn Marino do
734*ef5ccd6cSJohn Marino {
735*ef5ccd6cSJohn Marino /* First compare the hashing value. */
736*ef5ccd6cSJohn Marino if (symb_table[2 * elem] == hash
737*ef5ccd6cSJohn Marino && (c1
738*ef5ccd6cSJohn Marino == extra[symb_table[2 * elem + 1]])
739*ef5ccd6cSJohn Marino && memcmp (str,
740*ef5ccd6cSJohn Marino &extra[symb_table[2 * elem + 1]
741*ef5ccd6cSJohn Marino + 1], c1) == 0)
742*ef5ccd6cSJohn Marino {
743*ef5ccd6cSJohn Marino /* Yep, this is the entry. */
744*ef5ccd6cSJohn Marino idx = symb_table[2 * elem + 1];
745*ef5ccd6cSJohn Marino idx += 1 + extra[idx];
746*ef5ccd6cSJohn Marino break;
747*ef5ccd6cSJohn Marino }
748*ef5ccd6cSJohn Marino
749*ef5ccd6cSJohn Marino /* Next entry. */
750*ef5ccd6cSJohn Marino elem += second;
751*ef5ccd6cSJohn Marino }
752*ef5ccd6cSJohn Marino while (symb_table[2 * elem] != 0);
753*ef5ccd6cSJohn Marino }
754*ef5ccd6cSJohn Marino
755*ef5ccd6cSJohn Marino if (symb_table[2 * elem] != 0)
756*ef5ccd6cSJohn Marino {
757*ef5ccd6cSJohn Marino /* Compare the byte sequence but only if
758*ef5ccd6cSJohn Marino this is not part of a range. */
759*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
760*ef5ccd6cSJohn Marino int32_t *wextra;
761*ef5ccd6cSJohn Marino
762*ef5ccd6cSJohn Marino idx += 1 + extra[idx];
763*ef5ccd6cSJohn Marino /* Adjust for the alignment. */
764*ef5ccd6cSJohn Marino idx = (idx + 3) & ~4;
765*ef5ccd6cSJohn Marino
766*ef5ccd6cSJohn Marino wextra = (int32_t *) &extra[idx + 4];
767*ef5ccd6cSJohn Marino # endif
768*ef5ccd6cSJohn Marino /* Get the collation sequence value. */
769*ef5ccd6cSJohn Marino is_seqval = true;
770*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
771*ef5ccd6cSJohn Marino cend = wextra[1 + wextra[idx]];
772*ef5ccd6cSJohn Marino # else
773*ef5ccd6cSJohn Marino /* Adjust for the alignment. */
774*ef5ccd6cSJohn Marino idx += 1 + extra[idx];
775*ef5ccd6cSJohn Marino idx = (idx + 3) & ~4;
776*ef5ccd6cSJohn Marino cend = *((int32_t *) &extra[idx]);
777*ef5ccd6cSJohn Marino # endif
778*ef5ccd6cSJohn Marino }
779*ef5ccd6cSJohn Marino else if (symb_table[2 * elem] != 0 && c1 == 1)
780*ef5ccd6cSJohn Marino {
781*ef5ccd6cSJohn Marino cend = str[0];
782*ef5ccd6cSJohn Marino c = *p++;
783*ef5ccd6cSJohn Marino }
784*ef5ccd6cSJohn Marino else
785*ef5ccd6cSJohn Marino return FNM_NOMATCH;
786*ef5ccd6cSJohn Marino }
787*ef5ccd6cSJohn Marino # undef str
788*ef5ccd6cSJohn Marino }
789*ef5ccd6cSJohn Marino else
790*ef5ccd6cSJohn Marino {
791*ef5ccd6cSJohn Marino if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
792*ef5ccd6cSJohn Marino cend = *p++;
793*ef5ccd6cSJohn Marino if (cend == L_('\0'))
794*ef5ccd6cSJohn Marino return FNM_NOMATCH;
795*ef5ccd6cSJohn Marino cend = FOLD (cend);
796*ef5ccd6cSJohn Marino }
797*ef5ccd6cSJohn Marino
798*ef5ccd6cSJohn Marino /* XXX It is not entirely clear to me how to handle
799*ef5ccd6cSJohn Marino characters which are not mentioned in the
800*ef5ccd6cSJohn Marino collation specification. */
801*ef5ccd6cSJohn Marino if (
802*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
803*ef5ccd6cSJohn Marino lcollseq == 0xffffffff ||
804*ef5ccd6cSJohn Marino # endif
805*ef5ccd6cSJohn Marino lcollseq <= fcollseq)
806*ef5ccd6cSJohn Marino {
807*ef5ccd6cSJohn Marino /* We have to look at the upper bound. */
808*ef5ccd6cSJohn Marino uint32_t hcollseq;
809*ef5ccd6cSJohn Marino
810*ef5ccd6cSJohn Marino if (is_seqval)
811*ef5ccd6cSJohn Marino hcollseq = cend;
812*ef5ccd6cSJohn Marino else
813*ef5ccd6cSJohn Marino {
814*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
815*ef5ccd6cSJohn Marino hcollseq =
816*ef5ccd6cSJohn Marino __collseq_table_lookup (collseq, cend);
817*ef5ccd6cSJohn Marino if (hcollseq == ~((uint32_t) 0))
818*ef5ccd6cSJohn Marino {
819*ef5ccd6cSJohn Marino /* Hum, no information about the upper
820*ef5ccd6cSJohn Marino bound. The matching succeeds if the
821*ef5ccd6cSJohn Marino lower bound is matched exactly. */
822*ef5ccd6cSJohn Marino if (lcollseq != fcollseq)
823*ef5ccd6cSJohn Marino goto range_not_matched;
824*ef5ccd6cSJohn Marino
825*ef5ccd6cSJohn Marino goto matched;
826*ef5ccd6cSJohn Marino }
827*ef5ccd6cSJohn Marino # else
828*ef5ccd6cSJohn Marino hcollseq = collseq[cend];
829*ef5ccd6cSJohn Marino # endif
830*ef5ccd6cSJohn Marino }
831*ef5ccd6cSJohn Marino
832*ef5ccd6cSJohn Marino if (lcollseq <= hcollseq && fcollseq <= hcollseq)
833*ef5ccd6cSJohn Marino goto matched;
834*ef5ccd6cSJohn Marino }
835*ef5ccd6cSJohn Marino # ifdef WIDE_CHAR_VERSION
836*ef5ccd6cSJohn Marino range_not_matched:
837*ef5ccd6cSJohn Marino # endif
838*ef5ccd6cSJohn Marino #else
839*ef5ccd6cSJohn Marino /* We use a boring value comparison of the character
840*ef5ccd6cSJohn Marino values. This is better than comparing using
841*ef5ccd6cSJohn Marino 'strcoll' since the latter would have surprising
842*ef5ccd6cSJohn Marino and sometimes fatal consequences. */
843*ef5ccd6cSJohn Marino UCHAR cend = *p++;
844*ef5ccd6cSJohn Marino
845*ef5ccd6cSJohn Marino if (!(flags & FNM_NOESCAPE) && cend == L_('\\'))
846*ef5ccd6cSJohn Marino cend = *p++;
847*ef5ccd6cSJohn Marino if (cend == L_('\0'))
848*ef5ccd6cSJohn Marino return FNM_NOMATCH;
849*ef5ccd6cSJohn Marino
850*ef5ccd6cSJohn Marino /* It is a range. */
851*ef5ccd6cSJohn Marino if (cold <= fn && fn <= cend)
852*ef5ccd6cSJohn Marino goto matched;
853*ef5ccd6cSJohn Marino #endif
854*ef5ccd6cSJohn Marino
855*ef5ccd6cSJohn Marino c = *p++;
856*ef5ccd6cSJohn Marino }
857*ef5ccd6cSJohn Marino }
858*ef5ccd6cSJohn Marino
859*ef5ccd6cSJohn Marino if (c == L_(']'))
860*ef5ccd6cSJohn Marino break;
861*ef5ccd6cSJohn Marino }
862*ef5ccd6cSJohn Marino
863*ef5ccd6cSJohn Marino if (!not)
864*ef5ccd6cSJohn Marino return FNM_NOMATCH;
865*ef5ccd6cSJohn Marino break;
866*ef5ccd6cSJohn Marino
867*ef5ccd6cSJohn Marino matched:
868*ef5ccd6cSJohn Marino /* Skip the rest of the [...] that already matched. */
869*ef5ccd6cSJohn Marino do
870*ef5ccd6cSJohn Marino {
871*ef5ccd6cSJohn Marino ignore_next:
872*ef5ccd6cSJohn Marino c = *p++;
873*ef5ccd6cSJohn Marino
874*ef5ccd6cSJohn Marino if (c == L_('\0'))
875*ef5ccd6cSJohn Marino /* [... (unterminated) loses. */
876*ef5ccd6cSJohn Marino return FNM_NOMATCH;
877*ef5ccd6cSJohn Marino
878*ef5ccd6cSJohn Marino if (!(flags & FNM_NOESCAPE) && c == L_('\\'))
879*ef5ccd6cSJohn Marino {
880*ef5ccd6cSJohn Marino if (*p == L_('\0'))
881*ef5ccd6cSJohn Marino return FNM_NOMATCH;
882*ef5ccd6cSJohn Marino /* XXX 1003.2d11 is unclear if this is right. */
883*ef5ccd6cSJohn Marino ++p;
884*ef5ccd6cSJohn Marino }
885*ef5ccd6cSJohn Marino else if (c == L_('[') && *p == L_(':'))
886*ef5ccd6cSJohn Marino {
887*ef5ccd6cSJohn Marino int c1 = 0;
888*ef5ccd6cSJohn Marino const CHAR *startp = p;
889*ef5ccd6cSJohn Marino
890*ef5ccd6cSJohn Marino while (1)
891*ef5ccd6cSJohn Marino {
892*ef5ccd6cSJohn Marino c = *++p;
893*ef5ccd6cSJohn Marino if (++c1 == CHAR_CLASS_MAX_LENGTH)
894*ef5ccd6cSJohn Marino return FNM_NOMATCH;
895*ef5ccd6cSJohn Marino
896*ef5ccd6cSJohn Marino if (*p == L_(':') && p[1] == L_(']'))
897*ef5ccd6cSJohn Marino break;
898*ef5ccd6cSJohn Marino
899*ef5ccd6cSJohn Marino if (c < L_('a') || c >= L_('z'))
900*ef5ccd6cSJohn Marino {
901*ef5ccd6cSJohn Marino p = startp;
902*ef5ccd6cSJohn Marino goto ignore_next;
903*ef5ccd6cSJohn Marino }
904*ef5ccd6cSJohn Marino }
905*ef5ccd6cSJohn Marino p += 2;
906*ef5ccd6cSJohn Marino c = *p++;
907*ef5ccd6cSJohn Marino }
908*ef5ccd6cSJohn Marino else if (c == L_('[') && *p == L_('='))
909*ef5ccd6cSJohn Marino {
910*ef5ccd6cSJohn Marino c = *++p;
911*ef5ccd6cSJohn Marino if (c == L_('\0'))
912*ef5ccd6cSJohn Marino return FNM_NOMATCH;
913*ef5ccd6cSJohn Marino c = *++p;
914*ef5ccd6cSJohn Marino if (c != L_('=') || p[1] != L_(']'))
915*ef5ccd6cSJohn Marino return FNM_NOMATCH;
916*ef5ccd6cSJohn Marino p += 2;
917*ef5ccd6cSJohn Marino c = *p++;
918*ef5ccd6cSJohn Marino }
919*ef5ccd6cSJohn Marino else if (c == L_('[') && *p == L_('.'))
920*ef5ccd6cSJohn Marino {
921*ef5ccd6cSJohn Marino ++p;
922*ef5ccd6cSJohn Marino while (1)
923*ef5ccd6cSJohn Marino {
924*ef5ccd6cSJohn Marino c = *++p;
925*ef5ccd6cSJohn Marino if (c == '\0')
926*ef5ccd6cSJohn Marino return FNM_NOMATCH;
927*ef5ccd6cSJohn Marino
928*ef5ccd6cSJohn Marino if (*p == L_('.') && p[1] == L_(']'))
929*ef5ccd6cSJohn Marino break;
930*ef5ccd6cSJohn Marino }
931*ef5ccd6cSJohn Marino p += 2;
932*ef5ccd6cSJohn Marino c = *p++;
933*ef5ccd6cSJohn Marino }
934*ef5ccd6cSJohn Marino }
935*ef5ccd6cSJohn Marino while (c != L_(']'));
936*ef5ccd6cSJohn Marino if (not)
937*ef5ccd6cSJohn Marino return FNM_NOMATCH;
938*ef5ccd6cSJohn Marino }
939*ef5ccd6cSJohn Marino break;
940*ef5ccd6cSJohn Marino
941*ef5ccd6cSJohn Marino case L_('+'):
942*ef5ccd6cSJohn Marino case L_('@'):
943*ef5ccd6cSJohn Marino case L_('!'):
944*ef5ccd6cSJohn Marino if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
945*ef5ccd6cSJohn Marino {
946*ef5ccd6cSJohn Marino int res;
947*ef5ccd6cSJohn Marino
948*ef5ccd6cSJohn Marino res = EXT (c, p, n, string_end, no_leading_period, flags);
949*ef5ccd6cSJohn Marino if (res != -1)
950*ef5ccd6cSJohn Marino return res;
951*ef5ccd6cSJohn Marino }
952*ef5ccd6cSJohn Marino goto normal_match;
953*ef5ccd6cSJohn Marino
954*ef5ccd6cSJohn Marino case L_('/'):
955*ef5ccd6cSJohn Marino if (NO_LEADING_PERIOD (flags))
956*ef5ccd6cSJohn Marino {
957*ef5ccd6cSJohn Marino if (n == string_end || c != (UCHAR) *n)
958*ef5ccd6cSJohn Marino return FNM_NOMATCH;
959*ef5ccd6cSJohn Marino
960*ef5ccd6cSJohn Marino new_no_leading_period = true;
961*ef5ccd6cSJohn Marino break;
962*ef5ccd6cSJohn Marino }
963*ef5ccd6cSJohn Marino /* FALLTHROUGH */
964*ef5ccd6cSJohn Marino default:
965*ef5ccd6cSJohn Marino normal_match:
966*ef5ccd6cSJohn Marino if (n == string_end || c != FOLD ((UCHAR) *n))
967*ef5ccd6cSJohn Marino return FNM_NOMATCH;
968*ef5ccd6cSJohn Marino }
969*ef5ccd6cSJohn Marino
970*ef5ccd6cSJohn Marino no_leading_period = new_no_leading_period;
971*ef5ccd6cSJohn Marino ++n;
972*ef5ccd6cSJohn Marino }
973*ef5ccd6cSJohn Marino
974*ef5ccd6cSJohn Marino if (n == string_end)
975*ef5ccd6cSJohn Marino return 0;
976*ef5ccd6cSJohn Marino
977*ef5ccd6cSJohn Marino if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_('/'))
978*ef5ccd6cSJohn Marino /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
979*ef5ccd6cSJohn Marino return 0;
980*ef5ccd6cSJohn Marino
981*ef5ccd6cSJohn Marino return FNM_NOMATCH;
982*ef5ccd6cSJohn Marino }
983*ef5ccd6cSJohn Marino
984*ef5ccd6cSJohn Marino
985*ef5ccd6cSJohn Marino static const CHAR *
986*ef5ccd6cSJohn Marino internal_function
END(const CHAR * pattern)987*ef5ccd6cSJohn Marino END (const CHAR *pattern)
988*ef5ccd6cSJohn Marino {
989*ef5ccd6cSJohn Marino const CHAR *p = pattern;
990*ef5ccd6cSJohn Marino
991*ef5ccd6cSJohn Marino while (1)
992*ef5ccd6cSJohn Marino if (*++p == L_('\0'))
993*ef5ccd6cSJohn Marino /* This is an invalid pattern. */
994*ef5ccd6cSJohn Marino return pattern;
995*ef5ccd6cSJohn Marino else if (*p == L_('['))
996*ef5ccd6cSJohn Marino {
997*ef5ccd6cSJohn Marino /* Handle brackets special. */
998*ef5ccd6cSJohn Marino if (posixly_correct == 0)
999*ef5ccd6cSJohn Marino posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
1000*ef5ccd6cSJohn Marino
1001*ef5ccd6cSJohn Marino /* Skip the not sign. We have to recognize it because of a possibly
1002*ef5ccd6cSJohn Marino following ']'. */
1003*ef5ccd6cSJohn Marino if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
1004*ef5ccd6cSJohn Marino ++p;
1005*ef5ccd6cSJohn Marino /* A leading ']' is recognized as such. */
1006*ef5ccd6cSJohn Marino if (*p == L_(']'))
1007*ef5ccd6cSJohn Marino ++p;
1008*ef5ccd6cSJohn Marino /* Skip over all characters of the list. */
1009*ef5ccd6cSJohn Marino while (*p != L_(']'))
1010*ef5ccd6cSJohn Marino if (*p++ == L_('\0'))
1011*ef5ccd6cSJohn Marino /* This is no valid pattern. */
1012*ef5ccd6cSJohn Marino return pattern;
1013*ef5ccd6cSJohn Marino }
1014*ef5ccd6cSJohn Marino else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
1015*ef5ccd6cSJohn Marino || *p == L_('!')) && p[1] == L_('('))
1016*ef5ccd6cSJohn Marino p = END (p + 1);
1017*ef5ccd6cSJohn Marino else if (*p == L_(')'))
1018*ef5ccd6cSJohn Marino break;
1019*ef5ccd6cSJohn Marino
1020*ef5ccd6cSJohn Marino return p + 1;
1021*ef5ccd6cSJohn Marino }
1022*ef5ccd6cSJohn Marino
1023*ef5ccd6cSJohn Marino
1024*ef5ccd6cSJohn Marino static int
1025*ef5ccd6cSJohn Marino internal_function
EXT(INT opt,const CHAR * pattern,const CHAR * string,const CHAR * string_end,bool no_leading_period,int flags)1026*ef5ccd6cSJohn Marino EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
1027*ef5ccd6cSJohn Marino bool no_leading_period, int flags)
1028*ef5ccd6cSJohn Marino {
1029*ef5ccd6cSJohn Marino const CHAR *startp;
1030*ef5ccd6cSJohn Marino size_t level;
1031*ef5ccd6cSJohn Marino struct patternlist
1032*ef5ccd6cSJohn Marino {
1033*ef5ccd6cSJohn Marino struct patternlist *next;
1034*ef5ccd6cSJohn Marino CHAR str[1];
1035*ef5ccd6cSJohn Marino } *list = NULL;
1036*ef5ccd6cSJohn Marino struct patternlist **lastp = &list;
1037*ef5ccd6cSJohn Marino size_t pattern_len = STRLEN (pattern);
1038*ef5ccd6cSJohn Marino const CHAR *p;
1039*ef5ccd6cSJohn Marino const CHAR *rs;
1040*ef5ccd6cSJohn Marino enum { ALLOCA_LIMIT = 8000 };
1041*ef5ccd6cSJohn Marino
1042*ef5ccd6cSJohn Marino /* Parse the pattern. Store the individual parts in the list. */
1043*ef5ccd6cSJohn Marino level = 0;
1044*ef5ccd6cSJohn Marino for (startp = p = pattern + 1; ; ++p)
1045*ef5ccd6cSJohn Marino if (*p == L_('\0'))
1046*ef5ccd6cSJohn Marino /* This is an invalid pattern. */
1047*ef5ccd6cSJohn Marino return -1;
1048*ef5ccd6cSJohn Marino else if (*p == L_('['))
1049*ef5ccd6cSJohn Marino {
1050*ef5ccd6cSJohn Marino /* Handle brackets special. */
1051*ef5ccd6cSJohn Marino if (posixly_correct == 0)
1052*ef5ccd6cSJohn Marino posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
1053*ef5ccd6cSJohn Marino
1054*ef5ccd6cSJohn Marino /* Skip the not sign. We have to recognize it because of a possibly
1055*ef5ccd6cSJohn Marino following ']'. */
1056*ef5ccd6cSJohn Marino if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^')))
1057*ef5ccd6cSJohn Marino ++p;
1058*ef5ccd6cSJohn Marino /* A leading ']' is recognized as such. */
1059*ef5ccd6cSJohn Marino if (*p == L_(']'))
1060*ef5ccd6cSJohn Marino ++p;
1061*ef5ccd6cSJohn Marino /* Skip over all characters of the list. */
1062*ef5ccd6cSJohn Marino while (*p != L_(']'))
1063*ef5ccd6cSJohn Marino if (*p++ == L_('\0'))
1064*ef5ccd6cSJohn Marino /* This is no valid pattern. */
1065*ef5ccd6cSJohn Marino return -1;
1066*ef5ccd6cSJohn Marino }
1067*ef5ccd6cSJohn Marino else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
1068*ef5ccd6cSJohn Marino || *p == L_('!')) && p[1] == L_('('))
1069*ef5ccd6cSJohn Marino /* Remember the nesting level. */
1070*ef5ccd6cSJohn Marino ++level;
1071*ef5ccd6cSJohn Marino else if (*p == L_(')'))
1072*ef5ccd6cSJohn Marino {
1073*ef5ccd6cSJohn Marino if (level-- == 0)
1074*ef5ccd6cSJohn Marino {
1075*ef5ccd6cSJohn Marino /* This means we found the end of the pattern. */
1076*ef5ccd6cSJohn Marino #define NEW_PATTERN \
1077*ef5ccd6cSJohn Marino struct patternlist *newp; \
1078*ef5ccd6cSJohn Marino size_t plen; \
1079*ef5ccd6cSJohn Marino size_t plensize; \
1080*ef5ccd6cSJohn Marino size_t newpsize; \
1081*ef5ccd6cSJohn Marino \
1082*ef5ccd6cSJohn Marino plen = (opt == L_('?') || opt == L_('@') \
1083*ef5ccd6cSJohn Marino ? pattern_len \
1084*ef5ccd6cSJohn Marino : p - startp + 1UL); \
1085*ef5ccd6cSJohn Marino plensize = plen * sizeof (CHAR); \
1086*ef5ccd6cSJohn Marino newpsize = offsetof (struct patternlist, str) + plensize; \
1087*ef5ccd6cSJohn Marino if ((size_t) -1 / sizeof (CHAR) < plen \
1088*ef5ccd6cSJohn Marino || newpsize < offsetof (struct patternlist, str) \
1089*ef5ccd6cSJohn Marino || ALLOCA_LIMIT <= newpsize) \
1090*ef5ccd6cSJohn Marino return -1; \
1091*ef5ccd6cSJohn Marino newp = (struct patternlist *) alloca (newpsize); \
1092*ef5ccd6cSJohn Marino *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \
1093*ef5ccd6cSJohn Marino newp->next = NULL; \
1094*ef5ccd6cSJohn Marino *lastp = newp; \
1095*ef5ccd6cSJohn Marino lastp = &newp->next
1096*ef5ccd6cSJohn Marino NEW_PATTERN;
1097*ef5ccd6cSJohn Marino break;
1098*ef5ccd6cSJohn Marino }
1099*ef5ccd6cSJohn Marino }
1100*ef5ccd6cSJohn Marino else if (*p == L_('|'))
1101*ef5ccd6cSJohn Marino {
1102*ef5ccd6cSJohn Marino if (level == 0)
1103*ef5ccd6cSJohn Marino {
1104*ef5ccd6cSJohn Marino NEW_PATTERN;
1105*ef5ccd6cSJohn Marino startp = p + 1;
1106*ef5ccd6cSJohn Marino }
1107*ef5ccd6cSJohn Marino }
1108*ef5ccd6cSJohn Marino assert (list != NULL);
1109*ef5ccd6cSJohn Marino assert (p[-1] == L_(')'));
1110*ef5ccd6cSJohn Marino #undef NEW_PATTERN
1111*ef5ccd6cSJohn Marino
1112*ef5ccd6cSJohn Marino switch (opt)
1113*ef5ccd6cSJohn Marino {
1114*ef5ccd6cSJohn Marino case L_('*'):
1115*ef5ccd6cSJohn Marino if (FCT (p, string, string_end, no_leading_period, flags) == 0)
1116*ef5ccd6cSJohn Marino return 0;
1117*ef5ccd6cSJohn Marino /* FALLTHROUGH */
1118*ef5ccd6cSJohn Marino
1119*ef5ccd6cSJohn Marino case L_('+'):
1120*ef5ccd6cSJohn Marino do
1121*ef5ccd6cSJohn Marino {
1122*ef5ccd6cSJohn Marino for (rs = string; rs <= string_end; ++rs)
1123*ef5ccd6cSJohn Marino /* First match the prefix with the current pattern with the
1124*ef5ccd6cSJohn Marino current pattern. */
1125*ef5ccd6cSJohn Marino if (FCT (list->str, string, rs, no_leading_period,
1126*ef5ccd6cSJohn Marino flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0
1127*ef5ccd6cSJohn Marino /* This was successful. Now match the rest with the rest
1128*ef5ccd6cSJohn Marino of the pattern. */
1129*ef5ccd6cSJohn Marino && (FCT (p, rs, string_end,
1130*ef5ccd6cSJohn Marino rs == string
1131*ef5ccd6cSJohn Marino ? no_leading_period
1132*ef5ccd6cSJohn Marino : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
1133*ef5ccd6cSJohn Marino flags & FNM_FILE_NAME
1134*ef5ccd6cSJohn Marino ? flags : flags & ~FNM_PERIOD) == 0
1135*ef5ccd6cSJohn Marino /* This didn't work. Try the whole pattern. */
1136*ef5ccd6cSJohn Marino || (rs != string
1137*ef5ccd6cSJohn Marino && FCT (pattern - 1, rs, string_end,
1138*ef5ccd6cSJohn Marino rs == string
1139*ef5ccd6cSJohn Marino ? no_leading_period
1140*ef5ccd6cSJohn Marino : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
1141*ef5ccd6cSJohn Marino flags & FNM_FILE_NAME
1142*ef5ccd6cSJohn Marino ? flags : flags & ~FNM_PERIOD) == 0)))
1143*ef5ccd6cSJohn Marino /* It worked. Signal success. */
1144*ef5ccd6cSJohn Marino return 0;
1145*ef5ccd6cSJohn Marino }
1146*ef5ccd6cSJohn Marino while ((list = list->next) != NULL);
1147*ef5ccd6cSJohn Marino
1148*ef5ccd6cSJohn Marino /* None of the patterns lead to a match. */
1149*ef5ccd6cSJohn Marino return FNM_NOMATCH;
1150*ef5ccd6cSJohn Marino
1151*ef5ccd6cSJohn Marino case L_('?'):
1152*ef5ccd6cSJohn Marino if (FCT (p, string, string_end, no_leading_period, flags) == 0)
1153*ef5ccd6cSJohn Marino return 0;
1154*ef5ccd6cSJohn Marino /* FALLTHROUGH */
1155*ef5ccd6cSJohn Marino
1156*ef5ccd6cSJohn Marino case L_('@'):
1157*ef5ccd6cSJohn Marino do
1158*ef5ccd6cSJohn Marino /* I cannot believe it but 'strcat' is actually acceptable
1159*ef5ccd6cSJohn Marino here. Match the entire string with the prefix from the
1160*ef5ccd6cSJohn Marino pattern list and the rest of the pattern following the
1161*ef5ccd6cSJohn Marino pattern list. */
1162*ef5ccd6cSJohn Marino if (FCT (STRCAT (list->str, p), string, string_end,
1163*ef5ccd6cSJohn Marino no_leading_period,
1164*ef5ccd6cSJohn Marino flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
1165*ef5ccd6cSJohn Marino /* It worked. Signal success. */
1166*ef5ccd6cSJohn Marino return 0;
1167*ef5ccd6cSJohn Marino while ((list = list->next) != NULL);
1168*ef5ccd6cSJohn Marino
1169*ef5ccd6cSJohn Marino /* None of the patterns lead to a match. */
1170*ef5ccd6cSJohn Marino return FNM_NOMATCH;
1171*ef5ccd6cSJohn Marino
1172*ef5ccd6cSJohn Marino case L_('!'):
1173*ef5ccd6cSJohn Marino for (rs = string; rs <= string_end; ++rs)
1174*ef5ccd6cSJohn Marino {
1175*ef5ccd6cSJohn Marino struct patternlist *runp;
1176*ef5ccd6cSJohn Marino
1177*ef5ccd6cSJohn Marino for (runp = list; runp != NULL; runp = runp->next)
1178*ef5ccd6cSJohn Marino if (FCT (runp->str, string, rs, no_leading_period,
1179*ef5ccd6cSJohn Marino flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
1180*ef5ccd6cSJohn Marino break;
1181*ef5ccd6cSJohn Marino
1182*ef5ccd6cSJohn Marino /* If none of the patterns matched see whether the rest does. */
1183*ef5ccd6cSJohn Marino if (runp == NULL
1184*ef5ccd6cSJohn Marino && (FCT (p, rs, string_end,
1185*ef5ccd6cSJohn Marino rs == string
1186*ef5ccd6cSJohn Marino ? no_leading_period
1187*ef5ccd6cSJohn Marino : rs[-1] == '/' && NO_LEADING_PERIOD (flags),
1188*ef5ccd6cSJohn Marino flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD)
1189*ef5ccd6cSJohn Marino == 0))
1190*ef5ccd6cSJohn Marino /* This is successful. */
1191*ef5ccd6cSJohn Marino return 0;
1192*ef5ccd6cSJohn Marino }
1193*ef5ccd6cSJohn Marino
1194*ef5ccd6cSJohn Marino /* None of the patterns together with the rest of the pattern
1195*ef5ccd6cSJohn Marino lead to a match. */
1196*ef5ccd6cSJohn Marino return FNM_NOMATCH;
1197*ef5ccd6cSJohn Marino
1198*ef5ccd6cSJohn Marino default:
1199*ef5ccd6cSJohn Marino assert (! "Invalid extended matching operator");
1200*ef5ccd6cSJohn Marino break;
1201*ef5ccd6cSJohn Marino }
1202*ef5ccd6cSJohn Marino
1203*ef5ccd6cSJohn Marino return -1;
1204*ef5ccd6cSJohn Marino }
1205*ef5ccd6cSJohn Marino
1206*ef5ccd6cSJohn Marino
1207*ef5ccd6cSJohn Marino #undef FOLD
1208*ef5ccd6cSJohn Marino #undef CHAR
1209*ef5ccd6cSJohn Marino #undef UCHAR
1210*ef5ccd6cSJohn Marino #undef INT
1211*ef5ccd6cSJohn Marino #undef FCT
1212*ef5ccd6cSJohn Marino #undef EXT
1213*ef5ccd6cSJohn Marino #undef END
1214*ef5ccd6cSJohn Marino #undef MEMPCPY
1215*ef5ccd6cSJohn Marino #undef MEMCHR
1216*ef5ccd6cSJohn Marino #undef STRLEN
1217*ef5ccd6cSJohn Marino #undef STRCAT
1218*ef5ccd6cSJohn Marino #undef L_
1219*ef5ccd6cSJohn Marino #undef BTOWC
1220