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