1 /* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001,
2 2002 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program 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
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Match STRING against the filename pattern PATTERN, returning zero if
19 it matches, nonzero if not. */
20 static int FCT (const CHAR
*pattern
, const CHAR
*string
,
21 const CHAR
*string_end
, int no_leading_period
, int flags
)
23 static int EXT (INT opt
, const CHAR
*pattern
, const CHAR
*string
,
24 const CHAR
*string_end
, int no_leading_period
, int flags
)
26 static const CHAR
*END (const CHAR
*patternp
) internal_function
;
30 FCT (pattern
, string
, string_end
, no_leading_period
, flags
)
33 const CHAR
*string_end
;
34 int no_leading_period
;
37 register const CHAR
*p
= pattern
, *n
= string
;
40 # if WIDE_CHAR_VERSION
41 const char *collseq
= (const char *)
42 _NL_CURRENT(LC_COLLATE
, _NL_COLLATE_COLLSEQWC
);
44 const UCHAR
*collseq
= (const UCHAR
*)
45 _NL_CURRENT(LC_COLLATE
, _NL_COLLATE_COLLSEQMB
);
49 while ((c
= *p
++) != L('\0'))
51 int new_no_leading_period
= 0;
57 if (__builtin_expect (flags
& FNM_EXTMATCH
, 0) && *p
== '(')
61 res
= EXT (c
, p
, n
, string_end
, no_leading_period
,
69 else if (*n
== L('/') && (flags
& FNM_FILE_NAME
))
71 else if (*n
== L('.') && no_leading_period
)
76 if (!(flags
& FNM_NOESCAPE
))
80 /* Trailing \ loses. */
84 if (n
== string_end
|| FOLD ((UCHAR
) *n
) != c
)
89 if (__builtin_expect (flags
& FNM_EXTMATCH
, 0) && *p
== '(')
93 res
= EXT (c
, p
, n
, string_end
, no_leading_period
,
99 if (n
!= string_end
&& *n
== L('.') && no_leading_period
)
102 for (c
= *p
++; c
== L('?') || c
== L('*'); c
= *p
++)
104 if (*p
== L('(') && (flags
& FNM_EXTMATCH
) != 0)
106 const CHAR
*endp
= END (p
);
109 /* This is a pattern. Skip over it. */
117 /* A ? needs to match one character. */
119 /* There isn't another character; no match. */
121 else if (*n
== L('/')
122 && __builtin_expect (flags
& FNM_FILE_NAME
, 0))
123 /* A slash does not match a wildcard under
127 /* One character of the string is consumed in matching
128 this ? wildcard, so *??? won't match if there are
129 less than three characters. */
135 /* The wildcard(s) is/are the last element of the pattern.
136 If the name is a file name and contains another slash
137 this means it cannot match, unless the FNM_LEADING_DIR
140 int result
= (flags
& FNM_FILE_NAME
) == 0 ? 0 : FNM_NOMATCH
;
142 if (flags
& FNM_FILE_NAME
)
144 if (flags
& FNM_LEADING_DIR
)
148 if (MEMCHR (n
, L('/'), string_end
- n
) == NULL
)
159 endp
= MEMCHR (n
, (flags
& FNM_FILE_NAME
) ? L('/') : L('\0'),
165 || (__builtin_expect (flags
& FNM_EXTMATCH
, 0) != 0
166 && (c
== L('@') || c
== L('+') || c
== L('!'))
169 int flags2
= ((flags
& FNM_FILE_NAME
)
170 ? flags
: (flags
& ~FNM_PERIOD
));
171 int no_leading_period2
= no_leading_period
;
173 for (--p
; n
< endp
; ++n
, no_leading_period2
= 0)
174 if (FCT (p
, n
, string_end
, no_leading_period2
, flags2
)
178 else if (c
== L('/') && (flags
& FNM_FILE_NAME
))
180 while (n
< string_end
&& *n
!= L('/'))
182 if (n
< string_end
&& *n
== L('/')
183 && (FCT (p
, n
+ 1, string_end
, flags
& FNM_PERIOD
, flags
)
189 int flags2
= ((flags
& FNM_FILE_NAME
)
190 ? flags
: (flags
& ~FNM_PERIOD
));
191 int no_leading_period2
= no_leading_period
;
193 if (c
== L('\\') && !(flags
& FNM_NOESCAPE
))
196 for (--p
; n
< endp
; ++n
, no_leading_period2
= 0)
197 if (FOLD ((UCHAR
) *n
) == c
198 && (FCT (p
, n
, string_end
, no_leading_period2
, flags2
)
204 /* If we come here no match is possible with the wildcard. */
209 /* Nonzero if the sense of the character class is inverted. */
214 if (posixly_correct
== 0)
215 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
220 if (*n
== L('.') && no_leading_period
)
223 if (*n
== L('/') && (flags
& FNM_FILE_NAME
))
224 /* `/' cannot be matched. */
227 not = (*p
== L('!') || (posixly_correct
< 0 && *p
== L('^')));
231 fn
= FOLD ((UCHAR
) *n
);
236 if (!(flags
& FNM_NOESCAPE
) && c
== L('\\'))
240 c
= FOLD ((UCHAR
) *p
);
246 else if (c
== L('[') && *p
== L(':'))
248 /* Leave room for the null. */
249 CHAR str
[CHAR_CLASS_MAX_LENGTH
+ 1];
251 #if defined _LIBC || WIDE_CHAR_SUPPORT
254 const CHAR
*startp
= p
;
258 if (c1
== CHAR_CLASS_MAX_LENGTH
)
259 /* The name is too long and therefore the pattern
264 if (c
== L(':') && p
[1] == L(']'))
269 if (c
< L('a') || c
>= L('z'))
271 /* This cannot possibly be a character class name.
272 Match it as a normal range. */
281 #if defined _LIBC || WIDE_CHAR_SUPPORT
282 wt
= IS_CHAR_CLASS (str
);
284 /* Invalid character class name. */
287 # if defined _LIBC && ! WIDE_CHAR_VERSION
288 /* The following code is glibc specific but does
289 there a good job in speeding up the code since
290 we can avoid the btowc() call. */
291 if (_ISCTYPE ((UCHAR
) *n
, wt
))
294 if (ISWCTYPE (BTOWC ((UCHAR
) *n
), wt
))
298 if ((STREQ (str
, L("alnum")) && ISALNUM ((UCHAR
) *n
))
299 || (STREQ (str
, L("alpha")) && ISALPHA ((UCHAR
) *n
))
300 || (STREQ (str
, L("blank")) && ISBLANK ((UCHAR
) *n
))
301 || (STREQ (str
, L("cntrl")) && ISCNTRL ((UCHAR
) *n
))
302 || (STREQ (str
, L("digit")) && ISDIGIT ((UCHAR
) *n
))
303 || (STREQ (str
, L("graph")) && ISGRAPH ((UCHAR
) *n
))
304 || (STREQ (str
, L("lower")) && ISLOWER ((UCHAR
) *n
))
305 || (STREQ (str
, L("print")) && ISPRINT ((UCHAR
) *n
))
306 || (STREQ (str
, L("punct")) && ISPUNCT ((UCHAR
) *n
))
307 || (STREQ (str
, L("space")) && ISSPACE ((UCHAR
) *n
))
308 || (STREQ (str
, L("upper")) && ISUPPER ((UCHAR
) *n
))
309 || (STREQ (str
, L("xdigit")) && ISXDIGIT ((UCHAR
) *n
)))
315 else if (c
== L('[') && *p
== L('='))
319 _NL_CURRENT_WORD (LC_COLLATE
, _NL_COLLATE_NRULES
);
320 const CHAR
*startp
= p
;
332 if (c
!= L('=') || p
[1] != L(']'))
342 if ((UCHAR
) *n
== str
[0])
347 const int32_t *table
;
348 # if WIDE_CHAR_VERSION
349 const int32_t *weights
;
350 const int32_t *extra
;
352 const unsigned char *weights
;
353 const unsigned char *extra
;
355 const int32_t *indirect
;
357 const UCHAR
*cp
= (const UCHAR
*) str
;
359 /* This #include defines a local function! */
360 # if WIDE_CHAR_VERSION
361 # include <locale/weightwc.h>
363 # include <locale/weight.h>
366 # if WIDE_CHAR_VERSION
367 table
= (const int32_t *)
368 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEWC
);
369 weights
= (const int32_t *)
370 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTWC
);
371 extra
= (const int32_t *)
372 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAWC
);
373 indirect
= (const int32_t *)
374 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTWC
);
376 table
= (const int32_t *)
377 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEMB
);
378 weights
= (const unsigned char *)
379 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTMB
);
380 extra
= (const unsigned char *)
381 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAMB
);
382 indirect
= (const int32_t *)
383 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTMB
);
389 /* We found a table entry. Now see whether the
390 character we are currently at has the same
391 equivalance class value. */
392 int len
= weights
[idx
];
394 const UCHAR
*np
= (const UCHAR
*) n
;
396 idx2
= findidx (&np
);
397 if (idx2
!= 0 && len
== weights
[idx2
])
402 && (weights
[idx
+ 1 + cnt
]
403 == weights
[idx2
+ 1 + cnt
]))
415 else if (c
== L('\0'))
416 /* [ (unterminated) loses. */
425 if (c
== L('[') && *p
== L('.'))
428 _NL_CURRENT_WORD (LC_COLLATE
, _NL_COLLATE_NRULES
);
429 const CHAR
*startp
= p
;
435 if (c
== L('.') && p
[1] == L(']'))
445 /* We have to handling the symbols differently in
446 ranges since then the collation sequence is
448 is_range
= *p
== L('-') && p
[1] != L('\0');
452 /* There are no names defined in the collation
453 data. Therefore we only accept the trivial
454 names consisting of the character itself. */
458 if (!is_range
&& *n
== startp
[1])
467 const int32_t *symb_table
;
468 # ifdef WIDE_CHAR_VERSION
472 # define str (startp + 1)
474 const unsigned char *extra
;
480 # ifdef WIDE_CHAR_VERSION
481 /* We have to convert the name to a single-byte
482 string. This is possible since the names
483 consist of ASCII characters and the internal
484 representation is UCS4. */
485 for (strcnt
= 0; strcnt
< c1
; ++strcnt
)
486 str
[strcnt
] = startp
[1 + strcnt
];
490 _NL_CURRENT_WORD (LC_COLLATE
,
491 _NL_COLLATE_SYMB_HASH_SIZEMB
);
492 symb_table
= (const int32_t *)
493 _NL_CURRENT (LC_COLLATE
,
494 _NL_COLLATE_SYMB_TABLEMB
);
495 extra
= (const unsigned char *)
496 _NL_CURRENT (LC_COLLATE
,
497 _NL_COLLATE_SYMB_EXTRAMB
);
499 /* Locate the character in the hashing table. */
500 hash
= elem_hash (str
, c1
);
503 elem
= hash
% table_size
;
504 second
= hash
% (table_size
- 2);
505 while (symb_table
[2 * elem
] != 0)
507 /* First compare the hashing value. */
508 if (symb_table
[2 * elem
] == hash
509 && c1
== extra
[symb_table
[2 * elem
+ 1]]
511 &extra
[symb_table
[2 * elem
+ 1]
514 /* Yep, this is the entry. */
515 idx
= symb_table
[2 * elem
+ 1];
516 idx
+= 1 + extra
[idx
];
524 if (symb_table
[2 * elem
] != 0)
526 /* Compare the byte sequence but only if
527 this is not part of a range. */
528 # ifdef WIDE_CHAR_VERSION
531 idx
+= 1 + extra
[idx
];
532 /* Adjust for the alignment. */
533 idx
= (idx
+ 3) & ~3;
535 wextra
= (int32_t *) &extra
[idx
+ 4];
540 # ifdef WIDE_CHAR_VERSION
541 for (c1
= 0; c1
< wextra
[idx
]; ++c1
)
542 if (n
[c1
] != wextra
[1 + c1
])
545 if (c1
== wextra
[idx
])
548 for (c1
= 0; c1
< extra
[idx
]; ++c1
)
549 if (n
[c1
] != extra
[1 + c1
])
552 if (c1
== extra
[idx
])
557 /* Get the collation sequence value. */
559 # ifdef WIDE_CHAR_VERSION
560 cold
= wextra
[1 + wextra
[idx
]];
562 /* Adjust for the alignment. */
563 idx
+= 1 + extra
[idx
];
564 idx
= (idx
+ 3) & ~4;
565 cold
= *((int32_t *) &extra
[idx
]);
572 /* No valid character. Match it as a
574 if (!is_range
&& *n
== str
[0])
591 /* We have to handling the symbols differently in
592 ranges since then the collation sequence is
594 is_range
= (*p
== L('-') && p
[1] != L('\0')
597 if (!is_range
&& c
== fn
)
604 if (c
== L('-') && *p
!= L(']'))
607 /* We have to find the collation sequence
608 value for C. Collation sequence is nothing
609 we can regularly access. The sequence
610 value is defined by the order in which the
611 definitions of the collation values for the
612 various characters appear in the source
613 file. A strange concept, nowhere
619 # ifdef WIDE_CHAR_VERSION
620 /* Search in the `names' array for the characters. */
621 fcollseq
= collseq_table_lookup (collseq
, fn
);
622 if (fcollseq
== ~((uint32_t) 0))
623 /* XXX We don't know anything about the character
624 we are supposed to match. This means we are
626 goto range_not_matched
;
631 lcollseq
= collseq_table_lookup (collseq
, cold
);
633 fcollseq
= collseq
[fn
];
634 lcollseq
= is_seqval
? cold
: collseq
[(UCHAR
) cold
];
638 if (cend
== L('[') && *p
== L('.'))
641 _NL_CURRENT_WORD (LC_COLLATE
,
643 const CHAR
*startp
= p
;
649 if (c
== L('.') && p
[1] == L(']'))
661 /* There are no names defined in the
662 collation data. Therefore we only
663 accept the trivial names consisting
664 of the character itself. */
673 const int32_t *symb_table
;
674 # ifdef WIDE_CHAR_VERSION
678 # define str (startp + 1)
680 const unsigned char *extra
;
686 # ifdef WIDE_CHAR_VERSION
687 /* We have to convert the name to a single-byte
688 string. This is possible since the names
689 consist of ASCII characters and the internal
690 representation is UCS4. */
691 for (strcnt
= 0; strcnt
< c1
; ++strcnt
)
692 str
[strcnt
] = startp
[1 + strcnt
];
696 _NL_CURRENT_WORD (LC_COLLATE
,
697 _NL_COLLATE_SYMB_HASH_SIZEMB
);
698 symb_table
= (const int32_t *)
699 _NL_CURRENT (LC_COLLATE
,
700 _NL_COLLATE_SYMB_TABLEMB
);
701 extra
= (const unsigned char *)
702 _NL_CURRENT (LC_COLLATE
,
703 _NL_COLLATE_SYMB_EXTRAMB
);
705 /* Locate the character in the hashing
707 hash
= elem_hash (str
, c1
);
710 elem
= hash
% table_size
;
711 second
= hash
% (table_size
- 2);
712 while (symb_table
[2 * elem
] != 0)
714 /* First compare the hashing value. */
715 if (symb_table
[2 * elem
] == hash
717 == extra
[symb_table
[2 * elem
+ 1]])
719 &extra
[symb_table
[2 * elem
+ 1]
722 /* Yep, this is the entry. */
723 idx
= symb_table
[2 * elem
+ 1];
724 idx
+= 1 + extra
[idx
];
732 if (symb_table
[2 * elem
] != 0)
734 /* Compare the byte sequence but only if
735 this is not part of a range. */
736 # ifdef WIDE_CHAR_VERSION
739 idx
+= 1 + extra
[idx
];
740 /* Adjust for the alignment. */
741 idx
= (idx
+ 3) & ~4;
743 wextra
= (int32_t *) &extra
[idx
+ 4];
745 /* Get the collation sequence value. */
747 # ifdef WIDE_CHAR_VERSION
748 cend
= wextra
[1 + wextra
[idx
]];
750 /* Adjust for the alignment. */
751 idx
+= 1 + extra
[idx
];
752 idx
= (idx
+ 3) & ~4;
753 cend
= *((int32_t *) &extra
[idx
]);
756 else if (symb_table
[2 * elem
] != 0 && c1
== 1)
768 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
775 /* XXX It is not entirely clear to me how to handle
776 characters which are not mentioned in the
777 collation specification. */
779 # ifdef WIDE_CHAR_VERSION
780 lcollseq
== 0xffffffff ||
782 lcollseq
<= fcollseq
)
784 /* We have to look at the upper bound. */
791 # ifdef WIDE_CHAR_VERSION
793 collseq_table_lookup (collseq
, cend
);
794 if (hcollseq
== ~((uint32_t) 0))
796 /* Hum, no information about the upper
797 bound. The matching succeeds if the
798 lower bound is matched exactly. */
799 if (lcollseq
!= fcollseq
)
800 goto range_not_matched
;
805 hcollseq
= collseq
[cend
];
809 if (lcollseq
<= hcollseq
&& fcollseq
<= hcollseq
)
812 # ifdef WIDE_CHAR_VERSION
816 /* We use a boring value comparison of the character
817 values. This is better than comparing using
818 `strcoll' since the latter would have surprising
819 and sometimes fatal consequences. */
822 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
828 if (cold
<= fn
&& fn
<= cend
)
845 /* Skip the rest of the [...] that already matched. */
852 /* [... (unterminated) loses. */
855 if (!(flags
& FNM_NOESCAPE
) && c
== L('\\'))
859 /* XXX 1003.2d11 is unclear if this is right. */
862 else if (c
== L('[') && *p
== L(':'))
865 const CHAR
*startp
= p
;
870 if (++c1
== CHAR_CLASS_MAX_LENGTH
)
873 if (*p
== L(':') && p
[1] == L(']'))
876 if (c
< L('a') || c
>= L('z'))
885 else if (c
== L('[') && *p
== L('='))
891 if (c
!= L('=') || p
[1] != L(']'))
896 else if (c
== L('[') && *p
== L('.'))
905 if (*p
== L('.') && p
[1] == L(']'))
921 if (__builtin_expect (flags
& FNM_EXTMATCH
, 0) && *p
== '(')
925 res
= EXT (c
, p
, n
, string_end
, no_leading_period
, flags
);
932 if (NO_LEADING_PERIOD (flags
))
934 if (n
== string_end
|| c
!= *n
)
937 new_no_leading_period
= 1;
943 if (n
== string_end
|| c
!= FOLD ((UCHAR
) *n
))
947 no_leading_period
= new_no_leading_period
;
954 if ((flags
& FNM_LEADING_DIR
) && n
!= string_end
&& *n
== L('/'))
955 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
964 END (const CHAR
*pattern
)
966 const CHAR
*p
= pattern
;
970 /* This is an invalid pattern. */
972 else if (*p
== L('['))
974 /* Handle brackets special. */
975 if (posixly_correct
== 0)
976 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
978 /* Skip the not sign. We have to recognize it because of a possibly
980 if (*++p
== L('!') || (posixly_correct
< 0 && *p
== L('^')))
982 /* A leading ']' is recognized as such. */
985 /* Skip over all characters of the list. */
988 /* This is no valid pattern. */
991 else if ((*p
== L('?') || *p
== L('*') || *p
== L('+') || *p
== L('@')
992 || *p
== L('!')) && p
[1] == L('('))
994 else if (*p
== L(')'))
1003 EXT (INT opt
, const CHAR
*pattern
, const CHAR
*string
, const CHAR
*string_end
,
1004 int no_leading_period
, int flags
)
1010 struct patternlist
*next
;
1013 struct patternlist
**lastp
= &list
;
1014 size_t pattern_len
= STRLEN (pattern
);
1018 /* Parse the pattern. Store the individual parts in the list. */
1020 for (startp
= p
= pattern
+ 1; level
>= 0; ++p
)
1022 /* This is an invalid pattern. */
1024 else if (*p
== L('['))
1026 /* Handle brackets special. */
1027 if (posixly_correct
== 0)
1028 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
1030 /* Skip the not sign. We have to recognize it because of a possibly
1032 if (*++p
== L('!') || (posixly_correct
< 0 && *p
== L('^')))
1034 /* A leading ']' is recognized as such. */
1037 /* Skip over all characters of the list. */
1038 while (*p
!= L(']'))
1039 if (*p
++ == L('\0'))
1040 /* This is no valid pattern. */
1043 else if ((*p
== L('?') || *p
== L('*') || *p
== L('+') || *p
== L('@')
1044 || *p
== L('!')) && p
[1] == L('('))
1045 /* Remember the nesting level. */
1047 else if (*p
== L(')'))
1051 /* This means we found the end of the pattern. */
1052 #define NEW_PATTERN \
1053 struct patternlist *newp; \
1055 if (opt == L('?') || opt == L('@')) \
1056 newp = alloca (offsetof (struct patternlist, str) \
1057 + (pattern_len * sizeof (CHAR))); \
1059 newp = alloca (offsetof (struct patternlist, str) \
1060 + ((p - startp + 1) * sizeof (CHAR))); \
1061 *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
1062 newp->next = NULL; \
1068 else if (*p
== L('|'))
1076 assert (list
!= NULL
);
1077 assert (p
[-1] == L(')'));
1083 if (FCT (p
, string
, string_end
, no_leading_period
, flags
) == 0)
1090 for (rs
= string
; rs
<= string_end
; ++rs
)
1091 /* First match the prefix with the current pattern with the
1093 if (FCT (list
->str
, string
, rs
, no_leading_period
,
1094 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
) == 0
1095 /* This was successful. Now match the rest with the rest
1097 && (FCT (p
, rs
, string_end
,
1100 : rs
[-1] == '/' && NO_LEADING_PERIOD (flags
) ? 1 : 0,
1101 flags
& FNM_FILE_NAME
1102 ? flags
: flags
& ~FNM_PERIOD
) == 0
1103 /* This didn't work. Try the whole pattern. */
1105 && FCT (pattern
- 1, rs
, string_end
,
1108 : (rs
[-1] == '/' && NO_LEADING_PERIOD (flags
)
1110 flags
& FNM_FILE_NAME
1111 ? flags
: flags
& ~FNM_PERIOD
) == 0)))
1112 /* It worked. Signal success. */
1115 while ((list
= list
->next
) != NULL
);
1117 /* None of the patterns lead to a match. */
1121 if (FCT (p
, string
, string_end
, no_leading_period
, flags
) == 0)
1127 /* I cannot believe it but `strcat' is actually acceptable
1128 here. Match the entire string with the prefix from the
1129 pattern list and the rest of the pattern following the
1131 if (FCT (STRCAT (list
->str
, p
), string
, string_end
,
1133 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
) == 0)
1134 /* It worked. Signal success. */
1136 while ((list
= list
->next
) != NULL
);
1138 /* None of the patterns lead to a match. */
1142 for (rs
= string
; rs
<= string_end
; ++rs
)
1144 struct patternlist
*runp
;
1146 for (runp
= list
; runp
!= NULL
; runp
= runp
->next
)
1147 if (FCT (runp
->str
, string
, rs
, no_leading_period
,
1148 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
) == 0)
1151 /* If none of the patterns matched see whether the rest does. */
1153 && (FCT (p
, rs
, string_end
,
1156 : rs
[-1] == '/' && NO_LEADING_PERIOD (flags
) ? 1 : 0,
1157 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
)
1159 /* This is successful. */
1163 /* None of the patterns together with the rest of the pattern
1168 assert (! "Invalid extended matching operator");