1 /* Copyright (C) 1991-2022 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 Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
26 bool no_leading_period
;
29 /* Match STRING against the file name pattern PATTERN, returning zero if
30 it matches, nonzero if not. */
31 static int FCT (const CHAR
*pattern
, const CHAR
*string
,
32 const CHAR
*string_end
, bool no_leading_period
, int flags
,
33 struct STRUCT
*ends
, size_t alloca_used
);
34 static int EXT (INT opt
, const CHAR
*pattern
, const CHAR
*string
,
35 const CHAR
*string_end
, bool no_leading_period
, int flags
,
37 static const CHAR
*END (const CHAR
*patternp
);
40 FCT (const CHAR
*pattern
, const CHAR
*string
, const CHAR
*string_end
,
41 bool no_leading_period
, int flags
, struct STRUCT
*ends
, size_t alloca_used
)
43 const CHAR
*p
= pattern
, *n
= string
;
46 # if WIDE_CHAR_VERSION
47 const char *collseq
= (const char *)
48 _NL_CURRENT(LC_COLLATE
, _NL_COLLATE_COLLSEQWC
);
50 const UCHAR
*collseq
= (const UCHAR
*)
51 _NL_CURRENT(LC_COLLATE
, _NL_COLLATE_COLLSEQMB
);
55 while ((c
= *p
++) != L_('\0'))
57 bool new_no_leading_period
= false;
63 if (__glibc_unlikely (flags
& FNM_EXTMATCH
) && *p
== '(')
65 int res
= EXT (c
, p
, n
, string_end
, no_leading_period
,
73 else if (*n
== L_('/') && (flags
& FNM_FILE_NAME
))
75 else if (*n
== L_('.') && no_leading_period
)
80 if (!(flags
& FNM_NOESCAPE
))
84 /* Trailing \ loses. */
88 if (n
== string_end
|| FOLD ((UCHAR
) *n
) != c
)
93 if (__glibc_unlikely (flags
& FNM_EXTMATCH
) && *p
== '(')
95 int res
= EXT (c
, p
, n
, string_end
, no_leading_period
,
100 else if (ends
!= NULL
)
102 ends
->pattern
= p
- 1;
104 ends
->no_leading_period
= no_leading_period
;
108 if (n
!= string_end
&& *n
== L_('.') && no_leading_period
)
111 for (c
= *p
++; c
== L_('?') || c
== L_('*'); c
= *p
++)
113 if (*p
== L_('(') && (flags
& FNM_EXTMATCH
) != 0)
115 const CHAR
*endp
= END (p
);
118 /* This is a pattern. Skip over it. */
126 /* A ? needs to match one character. */
128 /* There isn't another character; no match. */
130 else if (*n
== L_('/')
131 && __glibc_unlikely (flags
& FNM_FILE_NAME
))
132 /* A slash does not match a wildcard under
136 /* One character of the string is consumed in matching
137 this ? wildcard, so *??? won't match if there are
138 less than three characters. */
144 /* The wildcard(s) is/are the last element of the pattern.
145 If the name is a file name and contains another slash
146 this means it cannot match, unless the FNM_LEADING_DIR
149 int result
= (flags
& FNM_FILE_NAME
) == 0 ? 0 : FNM_NOMATCH
;
151 if (flags
& FNM_FILE_NAME
)
153 if (flags
& FNM_LEADING_DIR
)
157 if (MEMCHR (n
, L_('/'), string_end
- n
) == NULL
)
170 endp
= MEMCHR (n
, (flags
& FNM_FILE_NAME
) ? L_('/') : L_('\0'),
176 || (__glibc_unlikely (flags
& FNM_EXTMATCH
)
177 && (c
== L_('@') || c
== L_('+') || c
== L_('!'))
180 int flags2
= ((flags
& FNM_FILE_NAME
)
181 ? flags
: (flags
& ~FNM_PERIOD
));
183 for (--p
; n
< endp
; ++n
, no_leading_period
= false)
184 if (FCT (p
, n
, string_end
, no_leading_period
, flags2
,
185 &end
, alloca_used
) == 0)
188 else if (c
== L_('/') && (flags
& FNM_FILE_NAME
))
190 while (n
< string_end
&& *n
!= L_('/'))
192 if (n
< string_end
&& *n
== L_('/')
193 && (FCT (p
, n
+ 1, string_end
, flags
& FNM_PERIOD
, flags
,
194 NULL
, alloca_used
) == 0))
199 int flags2
= ((flags
& FNM_FILE_NAME
)
200 ? flags
: (flags
& ~FNM_PERIOD
));
202 if (c
== L_('\\') && !(flags
& FNM_NOESCAPE
))
205 for (--p
; n
< endp
; ++n
, no_leading_period
= false)
206 if (FOLD ((UCHAR
) *n
) == c
207 && (FCT (p
, n
, string_end
, no_leading_period
, flags2
,
208 &end
, alloca_used
) == 0))
211 if (end
.pattern
== NULL
)
215 if (end
.pattern
!= NULL
)
219 no_leading_period
= end
.no_leading_period
;
225 /* If we come here no match is possible with the wildcard. */
230 /* Nonzero if the sense of the character class is inverted. */
231 const CHAR
*p_init
= p
;
232 const CHAR
*n_init
= n
;
237 if (posixly_correct
== 0)
238 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
243 if (*n
== L_('.') && no_leading_period
)
246 if (*n
== L_('/') && (flags
& FNM_FILE_NAME
))
247 /* '/' cannot be matched. */
250 not = (*p
== L_('!') || (posixly_correct
< 0 && *p
== L_('^')));
254 fn
= FOLD ((UCHAR
) *n
);
259 if (!(flags
& FNM_NOESCAPE
) && c
== L_('\\'))
263 c
= FOLD ((UCHAR
) *p
);
268 else if (c
== L_('[') && *p
== L_(':'))
270 /* Leave room for the null. */
271 CHAR str
[CHAR_CLASS_MAX_LENGTH
+ 1];
274 const CHAR
*startp
= p
;
278 if (c1
== CHAR_CLASS_MAX_LENGTH
)
279 /* The name is too long and therefore the pattern
284 if (c
== L_(':') && p
[1] == L_(']'))
289 if (c
< L_('a') || c
>= L_('z'))
291 /* This cannot possibly be a character class name.
292 Match it as a normal range. */
301 wt
= IS_CHAR_CLASS (str
);
303 /* Invalid character class name. */
306 #if defined _LIBC && ! WIDE_CHAR_VERSION
307 /* The following code is glibc specific but does
308 there a good job in speeding up the code since
309 we can avoid the btowc() call. */
310 if (_ISCTYPE ((UCHAR
) *n
, wt
))
313 if (iswctype (BTOWC ((UCHAR
) *n
), wt
))
319 else if (c
== L_('[') && *p
== L_('='))
321 /* It's important that STR be a scalar variable rather
322 than a one-element array, because GCC (at least 4.9.2
323 -O2 on x86-64) can be confused by the array and
324 diagnose a "used initialized" in a dead branch in the
328 _NL_CURRENT_WORD (LC_COLLATE
, _NL_COLLATE_NRULES
);
329 const CHAR
*startp
= p
;
341 if (c
!= L_('=') || p
[1] != L_(']'))
351 if ((UCHAR
) *n
== str
)
356 const int32_t *table
;
357 # if WIDE_CHAR_VERSION
358 const int32_t *weights
;
361 const unsigned char *weights
;
362 const unsigned char *extra
;
364 const int32_t *indirect
;
366 const UCHAR
*cp
= (const UCHAR
*) &str
;
368 # if WIDE_CHAR_VERSION
369 table
= (const int32_t *)
370 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEWC
);
371 weights
= (const int32_t *)
372 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTWC
);
373 extra
= (const wint_t *)
374 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAWC
);
375 indirect
= (const int32_t *)
376 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTWC
);
378 table
= (const int32_t *)
379 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEMB
);
380 weights
= (const unsigned char *)
381 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTMB
);
382 extra
= (const unsigned char *)
383 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAMB
);
384 indirect
= (const int32_t *)
385 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTMB
);
388 idx
= FINDIDX (table
, indirect
, extra
, &cp
, 1);
391 /* We found a table entry. Now see whether the
392 character we are currently at has the same
393 equivalence class value. */
394 int len
= weights
[idx
& 0xffffff];
396 const UCHAR
*np
= (const UCHAR
*) n
;
398 idx2
= FINDIDX (table
, indirect
, extra
,
399 &np
, string_end
- n
);
401 && (idx
>> 24) == (idx2
>> 24)
402 && len
== weights
[idx2
& 0xffffff])
410 && (weights
[idx
+ 1 + cnt
]
411 == weights
[idx2
+ 1 + cnt
]))
423 else if (c
== L_('\0'))
425 /* [ unterminated, treat as normal character. */
433 bool is_range
= false;
436 bool is_seqval
= false;
438 if (c
== L_('[') && *p
== L_('.'))
441 _NL_CURRENT_WORD (LC_COLLATE
, _NL_COLLATE_NRULES
);
442 const CHAR
*startp
= p
;
448 if (c
== L_('.') && p
[1] == L_(']'))
458 /* We have to handling the symbols differently in
459 ranges since then the collation sequence is
461 is_range
= *p
== L_('-') && p
[1] != L_('\0');
465 /* There are no names defined in the collation
466 data. Therefore we only accept the trivial
467 names consisting of the character itself. */
471 if (!is_range
&& *n
== startp
[1])
480 const int32_t *symb_table
;
481 const unsigned char *extra
;
484 # if WIDE_CHAR_VERSION
489 _NL_CURRENT_WORD (LC_COLLATE
,
490 _NL_COLLATE_SYMB_HASH_SIZEMB
);
491 symb_table
= (const int32_t *)
492 _NL_CURRENT (LC_COLLATE
,
493 _NL_COLLATE_SYMB_TABLEMB
);
494 extra
= (const unsigned char *)
495 _NL_CURRENT (LC_COLLATE
,
496 _NL_COLLATE_SYMB_EXTRAMB
);
498 for (elem
= 0; elem
< table_size
; elem
++)
499 if (symb_table
[2 * elem
] != 0)
501 idx
= symb_table
[2 * elem
+ 1];
502 /* Skip the name of collating element. */
503 idx
+= 1 + extra
[idx
];
504 # if WIDE_CHAR_VERSION
505 /* Skip the byte sequence of the
506 collating element. */
507 idx
+= 1 + extra
[idx
];
508 /* Adjust for the alignment. */
509 idx
= (idx
+ 3) & ~3;
511 wextra
= (CHAR
*) &extra
[idx
+ 4];
513 if (/* Compare the length of the sequence. */
515 /* Compare the wide char sequence. */
516 && (__wmemcmp (startp
+ 1, &wextra
[1],
519 /* Yep, this is the entry. */
522 if (/* Compare the length of the sequence. */
524 /* Compare the byte sequence. */
525 && memcmp (startp
+ 1,
526 &extra
[idx
+ 1], c1
) == 0)
527 /* Yep, this is the entry. */
532 if (elem
< table_size
)
534 /* Compare the byte sequence but only if
535 this is not part of a range. */
538 # if WIDE_CHAR_VERSION
539 && __wmemcmp (n
, &wextra
[1], c1
) == 0
541 && memcmp (n
, &extra
[idx
+ 1], c1
) == 0
549 /* Get the collation sequence value. */
551 # if WIDE_CHAR_VERSION
552 cold
= wextra
[1 + wextra
[0]];
554 idx
+= 1 + extra
[idx
];
555 /* Adjust for the alignment. */
556 idx
= (idx
+ 3) & ~3;
557 cold
= *((int32_t *) &extra
[idx
]);
564 /* No valid character. Match it as a
566 if (!is_range
&& *n
== startp
[1])
582 /* We have to handling the symbols differently in
583 ranges since then the collation sequence is
585 is_range
= (*p
== L_('-') && p
[1] != L_('\0')
588 if (!is_range
&& c
== fn
)
592 /* This is needed if we goto normal_bracket; from
593 outside of is_seqval's scope. */
600 if (c
== L_('-') && *p
!= L_(']'))
603 /* We have to find the collation sequence
604 value for C. Collation sequence is nothing
605 we can regularly access. The sequence
606 value is defined by the order in which the
607 definitions of the collation values for the
608 various characters appear in the source
609 file. A strange concept, nowhere
615 # if WIDE_CHAR_VERSION
616 /* Search in the 'names' array for the characters. */
617 fcollseq
= __collseq_table_lookup (collseq
, fn
);
618 if (fcollseq
== ~((uint32_t) 0))
619 /* XXX We don't know anything about the character
620 we are supposed to match. This means we are
622 goto range_not_matched
;
627 lcollseq
= __collseq_table_lookup (collseq
, cold
);
629 fcollseq
= collseq
[fn
];
630 lcollseq
= is_seqval
? cold
: collseq
[(UCHAR
) cold
];
634 if (cend
== L_('[') && *p
== L_('.'))
637 _NL_CURRENT_WORD (LC_COLLATE
,
639 const CHAR
*startp
= p
;
645 if (c
== L_('.') && p
[1] == L_(']'))
657 /* There are no names defined in the
658 collation data. Therefore we only
659 accept the trivial names consisting
660 of the character itself. */
669 const int32_t *symb_table
;
670 const unsigned char *extra
;
673 # if WIDE_CHAR_VERSION
678 _NL_CURRENT_WORD (LC_COLLATE
,
679 _NL_COLLATE_SYMB_HASH_SIZEMB
);
680 symb_table
= (const int32_t *)
681 _NL_CURRENT (LC_COLLATE
,
682 _NL_COLLATE_SYMB_TABLEMB
);
683 extra
= (const unsigned char *)
684 _NL_CURRENT (LC_COLLATE
,
685 _NL_COLLATE_SYMB_EXTRAMB
);
687 for (elem
= 0; elem
< table_size
; elem
++)
688 if (symb_table
[2 * elem
] != 0)
690 idx
= symb_table
[2 * elem
+ 1];
691 /* Skip the name of collating
693 idx
+= 1 + extra
[idx
];
694 # if WIDE_CHAR_VERSION
695 /* Skip the byte sequence of the
696 collating element. */
697 idx
+= 1 + extra
[idx
];
698 /* Adjust for the alignment. */
699 idx
= (idx
+ 3) & ~3;
701 wextra
= (CHAR
*) &extra
[idx
+ 4];
703 if (/* Compare the length of the
706 /* Compare the wide char sequence. */
707 && (__wmemcmp (startp
+ 1,
710 /* Yep, this is the entry. */
713 if (/* Compare the length of the
716 /* Compare the byte sequence. */
717 && memcmp (startp
+ 1,
718 &extra
[idx
+ 1], c1
) == 0)
719 /* Yep, this is the entry. */
724 if (elem
< table_size
)
726 /* Get the collation sequence value. */
728 # if WIDE_CHAR_VERSION
729 cend
= wextra
[1 + wextra
[0]];
731 idx
+= 1 + extra
[idx
];
732 /* Adjust for the alignment. */
733 idx
= (idx
+ 3) & ~3;
734 cend
= *((int32_t *) &extra
[idx
]);
748 if (!(flags
& FNM_NOESCAPE
) && cend
== L_('\\'))
750 if (cend
== L_('\0'))
755 /* XXX It is not entirely clear to me how to handle
756 characters which are not mentioned in the
757 collation specification. */
759 # if WIDE_CHAR_VERSION
760 lcollseq
== 0xffffffff ||
762 lcollseq
<= fcollseq
)
764 /* We have to look at the upper bound. */
771 # if WIDE_CHAR_VERSION
773 __collseq_table_lookup (collseq
, cend
);
774 if (hcollseq
== ~((uint32_t) 0))
776 /* Hum, no information about the upper
777 bound. The matching succeeds if the
778 lower bound is matched exactly. */
779 if (lcollseq
!= fcollseq
)
780 goto range_not_matched
;
785 hcollseq
= collseq
[cend
];
789 if (lcollseq
<= hcollseq
&& fcollseq
<= hcollseq
)
792 # if WIDE_CHAR_VERSION
796 /* We use a boring value comparison of the character
797 values. This is better than comparing using
798 'strcoll' since the latter would have surprising
799 and sometimes fatal consequences. */
802 if (!(flags
& FNM_NOESCAPE
) && cend
== L_('\\'))
804 if (cend
== L_('\0'))
808 if ((UCHAR
) cold
<= fn
&& fn
<= cend
)
825 /* Skip the rest of the [...] that already matched. */
826 while ((c
= *p
++) != L_(']'))
829 /* [... (unterminated) loses. */
832 if (!(flags
& FNM_NOESCAPE
) && c
== L_('\\'))
836 /* XXX 1003.2d11 is unclear if this is right. */
839 else if (c
== L_('[') && *p
== L_(':'))
842 const CHAR
*startp
= p
;
847 if (++c1
== CHAR_CLASS_MAX_LENGTH
)
850 if (*p
== L_(':') && p
[1] == L_(']'))
853 if (c
< L_('a') || c
>= L_('z'))
861 else if (c
== L_('[') && *p
== L_('='))
867 if (c
!= L_('=') || p
[1] != L_(']'))
871 else if (c
== L_('[') && *p
== L_('.'))
879 if (c
== L_('.') && p
[1] == L_(']'))
893 if (__glibc_unlikely (flags
& FNM_EXTMATCH
) && *p
== '(')
895 int res
= EXT (c
, p
, n
, string_end
, no_leading_period
, flags
,
903 if (NO_LEADING_PERIOD (flags
))
905 if (n
== string_end
|| c
!= (UCHAR
) *n
)
908 new_no_leading_period
= true;
914 if (n
== string_end
|| c
!= FOLD ((UCHAR
) *n
))
918 no_leading_period
= new_no_leading_period
;
925 if ((flags
& FNM_LEADING_DIR
) && n
!= string_end
&& *n
== L_('/'))
926 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
934 END (const CHAR
*pattern
)
936 const CHAR
*p
= pattern
;
939 if (*++p
== L_('\0'))
940 /* This is an invalid pattern. */
942 else if (*p
== L_('['))
944 /* Handle brackets special. */
945 if (posixly_correct
== 0)
946 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
948 /* Skip the not sign. We have to recognize it because of a possibly
950 if (*++p
== L_('!') || (posixly_correct
< 0 && *p
== L_('^')))
952 /* A leading ']' is recognized as such. */
955 /* Skip over all characters of the list. */
956 while (*p
!= L_(']'))
957 if (*p
++ == L_('\0'))
958 /* This is no valid pattern. */
961 else if ((*p
== L_('?') || *p
== L_('*') || *p
== L_('+') || *p
== L_('@')
962 || *p
== L_('!')) && p
[1] == L_('('))
966 /* This is an invalid pattern. */
969 else if (*p
== L_(')'))
977 EXT (INT opt
, const CHAR
*pattern
, const CHAR
*string
, const CHAR
*string_end
,
978 bool no_leading_period
, int flags
, size_t alloca_used
)
984 struct patternlist
*next
;
988 struct patternlist
**lastp
= &list
;
989 size_t pattern_len
= STRLEN (pattern
);
990 bool any_malloced
= false;
995 /* Parse the pattern. Store the individual parts in the list. */
997 for (startp
= p
= pattern
+ 1; level
>= 0; ++p
)
1000 /* This is an invalid pattern. */
1004 else if (*p
== L_('['))
1006 /* Handle brackets special. */
1007 if (posixly_correct
== 0)
1008 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
1010 /* Skip the not sign. We have to recognize it because of a possibly
1012 if (*++p
== L_('!') || (posixly_correct
< 0 && *p
== L_('^')))
1014 /* A leading ']' is recognized as such. */
1017 /* Skip over all characters of the list. */
1018 while (*p
!= L_(']'))
1019 if (*p
++ == L_('\0'))
1021 /* This is no valid pattern. */
1026 else if ((*p
== L_('?') || *p
== L_('*') || *p
== L_('+') || *p
== L_('@')
1027 || *p
== L_('!')) && p
[1] == L_('('))
1028 /* Remember the nesting level. */
1030 else if (*p
== L_(')'))
1034 /* This means we found the end of the pattern. */
1035 #define NEW_PATTERN \
1036 struct patternlist *newp; \
1037 size_t plen = (opt == L_('?') || opt == L_('@') \
1038 ? pattern_len : (p - startp + 1UL)); \
1039 idx_t slen = FLEXSIZEOF (struct patternlist, str, 0); \
1040 idx_t new_used = alloca_used + slen; \
1042 if (INT_MULTIPLY_WRAPV (plen, sizeof (CHAR), &plensize) \
1043 || INT_ADD_WRAPV (new_used, plensize, &new_used)) \
1049 bool malloced = ! __libc_use_alloca (new_used); \
1050 if (__glibc_unlikely (malloced)) \
1052 newp = malloc (slen); \
1058 any_malloced = true; \
1061 newp = alloca_account (slen, alloca_used); \
1062 newp->next = NULL; \
1063 newp->malloced = malloced; \
1064 *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \
1070 else if (*p
== L_('|'))
1078 assert (list
!= NULL
);
1079 assert (p
[-1] == L_(')'));
1085 if (FCT (p
, string
, string_end
, no_leading_period
, flags
, NULL
,
1092 for (rs
= string
; rs
<= string_end
; ++rs
)
1093 /* First match the prefix with the current pattern with the
1095 if (FCT (list
->str
, string
, rs
, no_leading_period
,
1096 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
,
1097 NULL
, alloca_used
) == 0
1098 /* This was successful. Now match the rest with the rest
1100 && (FCT (p
, rs
, string_end
,
1103 : rs
[-1] == '/' && NO_LEADING_PERIOD (flags
),
1104 flags
& FNM_FILE_NAME
1105 ? flags
: flags
& ~FNM_PERIOD
, NULL
, alloca_used
) == 0
1106 /* This didn't work. Try the whole pattern. */
1108 && FCT (pattern
- 1, rs
, string_end
,
1111 : rs
[-1] == '/' && NO_LEADING_PERIOD (flags
),
1112 flags
& FNM_FILE_NAME
1113 ? flags
: flags
& ~FNM_PERIOD
, NULL
,
1114 alloca_used
) == 0)))
1115 /* It worked. Signal success. */
1118 while ((list
= list
->next
) != NULL
);
1120 /* None of the patterns lead to a match. */
1121 retval
= FNM_NOMATCH
;
1125 if (FCT (p
, string
, string_end
, no_leading_period
, flags
, NULL
,
1131 /* I cannot believe it but 'strcat' is actually acceptable
1132 here. Match the entire string with the prefix from the
1133 pattern list and the rest of the pattern following the
1135 if (FCT (STRCAT (list
->str
, p
), string
, string_end
,
1137 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
,
1138 NULL
, alloca_used
) == 0)
1139 /* It worked. Signal success. */
1141 while ((list
= list
->next
) != NULL
);
1143 /* None of the patterns lead to a match. */
1144 retval
= FNM_NOMATCH
;
1148 for (rs
= string
; rs
<= string_end
; ++rs
)
1150 struct patternlist
*runp
;
1152 for (runp
= list
; runp
!= NULL
; runp
= runp
->next
)
1153 if (FCT (runp
->str
, string
, rs
, no_leading_period
,
1154 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
,
1155 NULL
, alloca_used
) == 0)
1158 /* If none of the patterns matched see whether the rest does. */
1160 && (FCT (p
, rs
, string_end
,
1163 : rs
[-1] == '/' && NO_LEADING_PERIOD (flags
),
1164 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
,
1165 NULL
, alloca_used
) == 0))
1166 /* This is successful. */
1170 /* None of the patterns together with the rest of the pattern
1172 retval
= FNM_NOMATCH
;
1176 assert (! "Invalid extended matching operator");
1184 while (list
!= NULL
)
1186 struct patternlist
*old
= list
;
1210 #undef WIDE_CHAR_VERSION