1 /* Copyright (C) 1991-2020 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/>. */
24 int no_leading_period
;
27 /* Match STRING against the filename pattern PATTERN, returning zero if
28 it matches, nonzero if not. */
29 static int FCT (const CHAR
*pattern
, const CHAR
*string
,
30 const CHAR
*string_end
, int no_leading_period
, int flags
,
31 struct STRUCT
*ends
, size_t alloca_used
);
32 static int EXT (INT opt
, const CHAR
*pattern
, const CHAR
*string
,
33 const CHAR
*string_end
, int no_leading_period
, int flags
,
35 static const CHAR
*END (const CHAR
*patternp
);
38 FCT (const CHAR
*pattern
, const CHAR
*string
, const CHAR
*string_end
,
39 int no_leading_period
, int flags
, struct STRUCT
*ends
, size_t alloca_used
)
41 const CHAR
*p
= pattern
, *n
= string
;
44 # if WIDE_CHAR_VERSION
45 const char *collseq
= (const char *)
46 _NL_CURRENT(LC_COLLATE
, _NL_COLLATE_COLLSEQWC
);
48 const UCHAR
*collseq
= (const UCHAR
*)
49 _NL_CURRENT(LC_COLLATE
, _NL_COLLATE_COLLSEQMB
);
53 while ((c
= *p
++) != L('\0'))
55 int new_no_leading_period
= 0;
61 if (__builtin_expect (flags
& FNM_EXTMATCH
, 0) && *p
== '(')
63 int res
= EXT (c
, p
, n
, string_end
, no_leading_period
,
71 else if (*n
== L('/') && (flags
& FNM_FILE_NAME
))
73 else if (*n
== L('.') && no_leading_period
)
78 if (!(flags
& FNM_NOESCAPE
))
82 /* Trailing \ loses. */
86 if (n
== string_end
|| FOLD ((UCHAR
) *n
) != c
)
91 if (__builtin_expect (flags
& FNM_EXTMATCH
, 0) && *p
== '(')
93 int res
= EXT (c
, p
, n
, string_end
, no_leading_period
,
98 else if (ends
!= NULL
)
100 ends
->pattern
= p
- 1;
102 ends
->no_leading_period
= no_leading_period
;
106 if (n
!= string_end
&& *n
== L('.') && no_leading_period
)
109 for (c
= *p
++; c
== L('?') || c
== L('*'); c
= *p
++)
111 if (*p
== L('(') && (flags
& FNM_EXTMATCH
) != 0)
113 const CHAR
*endp
= END (p
);
116 /* This is a pattern. Skip over it. */
124 /* A ? needs to match one character. */
126 /* There isn't another character; no match. */
128 else if (*n
== L('/')
129 && __builtin_expect (flags
& FNM_FILE_NAME
, 0))
130 /* A slash does not match a wildcard under
134 /* One character of the string is consumed in matching
135 this ? wildcard, so *??? won't match if there are
136 less than three characters. */
142 /* The wildcard(s) is/are the last element of the pattern.
143 If the name is a file name and contains another slash
144 this means it cannot match, unless the FNM_LEADING_DIR
147 int result
= (flags
& FNM_FILE_NAME
) == 0 ? 0 : FNM_NOMATCH
;
149 if (flags
& FNM_FILE_NAME
)
151 if (flags
& FNM_LEADING_DIR
)
155 if (MEMCHR (n
, L('/'), string_end
- n
) == NULL
)
168 endp
= MEMCHR (n
, (flags
& FNM_FILE_NAME
) ? L('/') : L('\0'),
174 || (__builtin_expect (flags
& FNM_EXTMATCH
, 0) != 0
175 && (c
== L('@') || c
== L('+') || c
== L('!'))
178 int flags2
= ((flags
& FNM_FILE_NAME
)
179 ? flags
: (flags
& ~FNM_PERIOD
));
181 for (--p
; n
< endp
; ++n
, no_leading_period
= 0)
182 if (FCT (p
, n
, string_end
, no_leading_period
, flags2
,
183 &end
, alloca_used
) == 0)
186 else if (c
== L('/') && (flags
& FNM_FILE_NAME
))
188 while (n
< string_end
&& *n
!= L('/'))
190 if (n
< string_end
&& *n
== L('/')
191 && (FCT (p
, n
+ 1, string_end
, flags
& FNM_PERIOD
, flags
,
192 NULL
, alloca_used
) == 0))
197 int flags2
= ((flags
& FNM_FILE_NAME
)
198 ? flags
: (flags
& ~FNM_PERIOD
));
200 if (c
== L('\\') && !(flags
& FNM_NOESCAPE
))
203 for (--p
; n
< endp
; ++n
, no_leading_period
= 0)
204 if (FOLD ((UCHAR
) *n
) == c
205 && (FCT (p
, n
, string_end
, no_leading_period
, flags2
,
206 &end
, alloca_used
) == 0))
209 if (end
.pattern
== NULL
)
213 if (end
.pattern
!= NULL
)
217 no_leading_period
= end
.no_leading_period
;
223 /* If we come here no match is possible with the wildcard. */
228 /* Nonzero if the sense of the character class is inverted. */
229 const CHAR
*p_init
= p
;
230 const CHAR
*n_init
= n
;
235 if (posixly_correct
== 0)
236 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
241 if (*n
== L('.') && no_leading_period
)
244 if (*n
== L('/') && (flags
& FNM_FILE_NAME
))
245 /* `/' cannot be matched. */
248 not = (*p
== L('!') || (posixly_correct
< 0 && *p
== L('^')));
252 fn
= FOLD ((UCHAR
) *n
);
257 if (!(flags
& FNM_NOESCAPE
) && c
== L('\\'))
261 c
= FOLD ((UCHAR
) *p
);
266 else if (c
== L('[') && *p
== L(':'))
268 /* Leave room for the null. */
269 CHAR str
[CHAR_CLASS_MAX_LENGTH
+ 1];
271 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
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 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
302 wt
= IS_CHAR_CLASS (str
);
304 /* Invalid character class name. */
307 # if defined _LIBC && ! WIDE_CHAR_VERSION
308 /* The following code is glibc specific but does
309 there a good job in speeding up the code since
310 we can avoid the btowc() call. */
311 if (_ISCTYPE ((UCHAR
) *n
, wt
))
314 if (ISWCTYPE (BTOWC ((UCHAR
) *n
), wt
))
318 if ((STREQ (str
, L("alnum")) && ISALNUM ((UCHAR
) *n
))
319 || (STREQ (str
, L("alpha")) && ISALPHA ((UCHAR
) *n
))
320 || (STREQ (str
, L("blank")) && ISBLANK ((UCHAR
) *n
))
321 || (STREQ (str
, L("cntrl")) && ISCNTRL ((UCHAR
) *n
))
322 || (STREQ (str
, L("digit")) && ISDIGIT ((UCHAR
) *n
))
323 || (STREQ (str
, L("graph")) && ISGRAPH ((UCHAR
) *n
))
324 || (STREQ (str
, L("lower")) && ISLOWER ((UCHAR
) *n
))
325 || (STREQ (str
, L("print")) && ISPRINT ((UCHAR
) *n
))
326 || (STREQ (str
, L("punct")) && ISPUNCT ((UCHAR
) *n
))
327 || (STREQ (str
, L("space")) && ISSPACE ((UCHAR
) *n
))
328 || (STREQ (str
, L("upper")) && ISUPPER ((UCHAR
) *n
))
329 || (STREQ (str
, L("xdigit")) && ISXDIGIT ((UCHAR
) *n
)))
335 else if (c
== L('[') && *p
== L('='))
337 /* It's important that STR be a scalar variable rather
338 than a one-element array, because GCC (at least 4.9.2
339 -O2 on x86-64) can be confused by the array and
340 diagnose a "used initialized" in a dead branch in the
344 _NL_CURRENT_WORD (LC_COLLATE
, _NL_COLLATE_NRULES
);
345 const CHAR
*startp
= p
;
357 if (c
!= L('=') || p
[1] != L(']'))
367 if ((UCHAR
) *n
== str
)
372 const int32_t *table
;
373 # if WIDE_CHAR_VERSION
374 const int32_t *weights
;
377 const unsigned char *weights
;
378 const unsigned char *extra
;
380 const int32_t *indirect
;
382 const UCHAR
*cp
= (const UCHAR
*) &str
;
384 # if WIDE_CHAR_VERSION
385 table
= (const int32_t *)
386 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEWC
);
387 weights
= (const int32_t *)
388 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTWC
);
389 extra
= (const wint_t *)
390 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAWC
);
391 indirect
= (const int32_t *)
392 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTWC
);
394 table
= (const int32_t *)
395 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEMB
);
396 weights
= (const unsigned char *)
397 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTMB
);
398 extra
= (const unsigned char *)
399 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAMB
);
400 indirect
= (const int32_t *)
401 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTMB
);
404 idx
= FINDIDX (table
, indirect
, extra
, &cp
, 1);
407 /* We found a table entry. Now see whether the
408 character we are currently at has the same
409 equivalance class value. */
410 int len
= weights
[idx
& 0xffffff];
412 const UCHAR
*np
= (const UCHAR
*) n
;
414 idx2
= FINDIDX (table
, indirect
, extra
,
415 &np
, string_end
- n
);
417 && (idx
>> 24) == (idx2
>> 24)
418 && len
== weights
[idx2
& 0xffffff])
426 && (weights
[idx
+ 1 + cnt
]
427 == weights
[idx2
+ 1 + cnt
]))
439 else if (c
== L('\0'))
441 /* [ unterminated, treat as normal character. */
454 if (c
== L('[') && *p
== L('.'))
457 _NL_CURRENT_WORD (LC_COLLATE
, _NL_COLLATE_NRULES
);
458 const CHAR
*startp
= p
;
464 if (c
== L('.') && p
[1] == L(']'))
474 /* We have to handling the symbols differently in
475 ranges since then the collation sequence is
477 is_range
= *p
== L('-') && p
[1] != L('\0');
481 /* There are no names defined in the collation
482 data. Therefore we only accept the trivial
483 names consisting of the character itself. */
487 if (!is_range
&& *n
== startp
[1])
496 const int32_t *symb_table
;
497 const unsigned char *extra
;
500 # if WIDE_CHAR_VERSION
505 _NL_CURRENT_WORD (LC_COLLATE
,
506 _NL_COLLATE_SYMB_HASH_SIZEMB
);
507 symb_table
= (const int32_t *)
508 _NL_CURRENT (LC_COLLATE
,
509 _NL_COLLATE_SYMB_TABLEMB
);
510 extra
= (const unsigned char *)
511 _NL_CURRENT (LC_COLLATE
,
512 _NL_COLLATE_SYMB_EXTRAMB
);
514 for (elem
= 0; elem
< table_size
; elem
++)
515 if (symb_table
[2 * elem
] != 0)
517 idx
= symb_table
[2 * elem
+ 1];
518 /* Skip the name of collating element. */
519 idx
+= 1 + extra
[idx
];
520 # if WIDE_CHAR_VERSION
521 /* Skip the byte sequence of the
522 collating element. */
523 idx
+= 1 + extra
[idx
];
524 /* Adjust for the alignment. */
525 idx
= (idx
+ 3) & ~3;
527 wextra
= (CHAR
*) &extra
[idx
+ 4];
529 if (/* Compare the length of the sequence. */
531 /* Compare the wide char sequence. */
532 && WMEMCMP (startp
+ 1, &wextra
[1],
534 /* Yep, this is the entry. */
537 if (/* Compare the length of the sequence. */
539 /* Compare the byte sequence. */
540 && memcmp (startp
+ 1,
541 &extra
[idx
+ 1], c1
) == 0)
542 /* Yep, this is the entry. */
547 if (elem
< table_size
)
549 /* Compare the byte sequence but only if
550 this is not part of a range. */
553 # if WIDE_CHAR_VERSION
554 && WMEMCMP (n
, &wextra
[1], c1
) == 0
556 && memcmp (n
, &extra
[idx
+ 1], c1
) == 0
564 /* Get the collation sequence value. */
566 # if WIDE_CHAR_VERSION
567 cold
= wextra
[1 + wextra
[idx
]];
569 idx
+= 1 + extra
[idx
];
570 /* Adjust for the alignment. */
571 idx
= (idx
+ 3) & ~3;
572 cold
= *((int32_t *) &extra
[idx
]);
579 /* No valid character. Match it as a
581 if (!is_range
&& *n
== startp
[1])
597 /* We have to handling the symbols differently in
598 ranges since then the collation sequence is
600 is_range
= (*p
== L('-') && p
[1] != L('\0')
603 if (!is_range
&& c
== fn
)
606 /* This is needed if we goto normal_bracket; from
607 outside of is_seqval's scope. */
613 if (c
== L('-') && *p
!= L(']'))
616 /* We have to find the collation sequence
617 value for C. Collation sequence is nothing
618 we can regularly access. The sequence
619 value is defined by the order in which the
620 definitions of the collation values for the
621 various characters appear in the source
622 file. A strange concept, nowhere
628 # if WIDE_CHAR_VERSION
629 /* Search in the `names' array for the characters. */
630 fcollseq
= __collseq_table_lookup (collseq
, fn
);
631 if (fcollseq
== ~((uint32_t) 0))
632 /* XXX We don't know anything about the character
633 we are supposed to match. This means we are
635 goto range_not_matched
;
640 lcollseq
= __collseq_table_lookup (collseq
, cold
);
642 fcollseq
= collseq
[fn
];
643 lcollseq
= is_seqval
? cold
: collseq
[(UCHAR
) cold
];
647 if (cend
== L('[') && *p
== L('.'))
650 _NL_CURRENT_WORD (LC_COLLATE
,
652 const CHAR
*startp
= p
;
658 if (c
== L('.') && p
[1] == L(']'))
670 /* There are no names defined in the
671 collation data. Therefore we only
672 accept the trivial names consisting
673 of the character itself. */
682 const int32_t *symb_table
;
683 const unsigned char *extra
;
686 # if WIDE_CHAR_VERSION
691 _NL_CURRENT_WORD (LC_COLLATE
,
692 _NL_COLLATE_SYMB_HASH_SIZEMB
);
693 symb_table
= (const int32_t *)
694 _NL_CURRENT (LC_COLLATE
,
695 _NL_COLLATE_SYMB_TABLEMB
);
696 extra
= (const unsigned char *)
697 _NL_CURRENT (LC_COLLATE
,
698 _NL_COLLATE_SYMB_EXTRAMB
);
700 for (elem
= 0; elem
< table_size
; elem
++)
701 if (symb_table
[2 * elem
] != 0)
703 idx
= symb_table
[2 * elem
+ 1];
704 /* Skip the name of collating
706 idx
+= 1 + extra
[idx
];
707 # if WIDE_CHAR_VERSION
708 /* Skip the byte sequence of the
709 collating element. */
710 idx
+= 1 + extra
[idx
];
711 /* Adjust for the alignment. */
712 idx
= (idx
+ 3) & ~3;
714 wextra
= (CHAR
*) &extra
[idx
+ 4];
716 if (/* Compare the length of the
719 /* Compare the wide char sequence. */
720 && WMEMCMP (startp
+ 1, &wextra
[1],
722 /* Yep, this is the entry. */
725 if (/* Compare the length of the
728 /* Compare the byte sequence. */
729 && memcmp (startp
+ 1,
730 &extra
[idx
+ 1], c1
) == 0)
731 /* Yep, this is the entry. */
736 if (elem
< table_size
)
738 /* Get the collation sequence value. */
740 # if WIDE_CHAR_VERSION
741 cend
= wextra
[1 + wextra
[idx
]];
743 idx
+= 1 + extra
[idx
];
744 /* Adjust for the alignment. */
745 idx
= (idx
+ 3) & ~3;
746 cend
= *((int32_t *) &extra
[idx
]);
760 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
767 /* XXX It is not entirely clear to me how to handle
768 characters which are not mentioned in the
769 collation specification. */
771 # if WIDE_CHAR_VERSION
772 lcollseq
== 0xffffffff ||
774 lcollseq
<= fcollseq
)
776 /* We have to look at the upper bound. */
783 # if WIDE_CHAR_VERSION
785 __collseq_table_lookup (collseq
, cend
);
786 if (hcollseq
== ~((uint32_t) 0))
788 /* Hum, no information about the upper
789 bound. The matching succeeds if the
790 lower bound is matched exactly. */
791 if (lcollseq
!= fcollseq
)
792 goto range_not_matched
;
797 hcollseq
= collseq
[cend
];
801 if (lcollseq
<= hcollseq
&& fcollseq
<= hcollseq
)
804 # if WIDE_CHAR_VERSION
808 /* We use a boring value comparison of the character
809 values. This is better than comparing using
810 `strcoll' since the latter would have surprising
811 and sometimes fatal consequences. */
814 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
820 if (cold
<= fn
&& fn
<= cend
)
837 /* Skip the rest of the [...] that already matched. */
838 while ((c
= *p
++) != L (']'))
841 /* [... (unterminated) loses. */
844 if (!(flags
& FNM_NOESCAPE
) && c
== L('\\'))
848 /* XXX 1003.2d11 is unclear if this is right. */
851 else if (c
== L('[') && *p
== L(':'))
854 const CHAR
*startp
= p
;
859 if (++c1
== CHAR_CLASS_MAX_LENGTH
)
862 if (*p
== L(':') && p
[1] == L(']'))
865 if (c
< L('a') || c
>= L('z'))
873 else if (c
== L('[') && *p
== L('='))
879 if (c
!= L('=') || p
[1] != L(']'))
883 else if (c
== L('[') && *p
== L('.'))
891 if (c
== L('.') && p
[1] == L(']'))
905 if (__builtin_expect (flags
& FNM_EXTMATCH
, 0) && *p
== '(')
907 int res
= EXT (c
, p
, n
, string_end
, no_leading_period
, flags
,
915 if (NO_LEADING_PERIOD (flags
))
917 if (n
== string_end
|| c
!= (UCHAR
) *n
)
920 new_no_leading_period
= 1;
926 if (n
== string_end
|| c
!= FOLD ((UCHAR
) *n
))
930 no_leading_period
= new_no_leading_period
;
937 if ((flags
& FNM_LEADING_DIR
) && n
!= string_end
&& *n
== L('/'))
938 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
946 END (const CHAR
*pattern
)
948 const CHAR
*p
= pattern
;
952 /* This is an invalid pattern. */
954 else if (*p
== L('['))
956 /* Handle brackets special. */
957 if (posixly_correct
== 0)
958 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
960 /* Skip the not sign. We have to recognize it because of a possibly
962 if (*++p
== L('!') || (posixly_correct
< 0 && *p
== L('^')))
964 /* A leading ']' is recognized as such. */
967 /* Skip over all characters of the list. */
970 /* This is no valid pattern. */
973 else if ((*p
== L('?') || *p
== L('*') || *p
== L('+') || *p
== L('@')
974 || *p
== L('!')) && p
[1] == L('('))
978 /* This is an invalid pattern. */
981 else if (*p
== L(')'))
989 EXT (INT opt
, const CHAR
*pattern
, const CHAR
*string
, const CHAR
*string_end
,
990 int no_leading_period
, int flags
, size_t alloca_used
)
996 struct patternlist
*next
;
1000 struct patternlist
**lastp
= &list
;
1001 size_t pattern_len
= STRLEN (pattern
);
1002 int any_malloced
= 0;
1007 /* Parse the pattern. Store the individual parts in the list. */
1009 for (startp
= p
= pattern
+ 1; level
>= 0; ++p
)
1012 /* This is an invalid pattern. */
1016 else if (*p
== L('['))
1018 /* Handle brackets special. */
1019 if (posixly_correct
== 0)
1020 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
1022 /* Skip the not sign. We have to recognize it because of a possibly
1024 if (*++p
== L('!') || (posixly_correct
< 0 && *p
== L('^')))
1026 /* A leading ']' is recognized as such. */
1029 /* Skip over all characters of the list. */
1030 while (*p
!= L(']'))
1031 if (*p
++ == L('\0'))
1033 /* This is no valid pattern. */
1038 else if ((*p
== L('?') || *p
== L('*') || *p
== L('+') || *p
== L('@')
1039 || *p
== L('!')) && p
[1] == L('('))
1040 /* Remember the nesting level. */
1042 else if (*p
== L(')'))
1046 /* This means we found the end of the pattern. */
1047 #define NEW_PATTERN \
1048 struct patternlist *newp; \
1049 size_t slen = (opt == L('?') || opt == L('@') \
1050 ? pattern_len : (p - startp + 1)); \
1051 slen = sizeof (struct patternlist) + (slen * sizeof (CHAR)); \
1052 int malloced = ! __libc_use_alloca (alloca_used + slen); \
1053 if (__builtin_expect (malloced, 0)) \
1055 newp = malloc (slen); \
1064 newp = alloca_account (slen, alloca_used); \
1065 newp->next = NULL; \
1066 newp->malloced = malloced; \
1067 *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
1073 else if (*p
== L('|'))
1081 assert (list
!= NULL
);
1082 assert (p
[-1] == L(')'));
1088 if (FCT (p
, string
, string_end
, no_leading_period
, flags
, NULL
,
1096 for (rs
= string
; rs
<= string_end
; ++rs
)
1097 /* First match the prefix with the current pattern with the
1099 if (FCT (list
->str
, string
, rs
, no_leading_period
,
1100 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
,
1101 NULL
, alloca_used
) == 0
1102 /* This was successful. Now match the rest with the rest
1104 && (FCT (p
, rs
, string_end
,
1107 : rs
[-1] == '/' && NO_LEADING_PERIOD (flags
) ? 1 : 0,
1108 flags
& FNM_FILE_NAME
1109 ? flags
: flags
& ~FNM_PERIOD
, NULL
, alloca_used
) == 0
1110 /* This didn't work. Try the whole pattern. */
1112 && FCT (pattern
- 1, rs
, string_end
,
1115 : (rs
[-1] == '/' && NO_LEADING_PERIOD (flags
)
1117 flags
& FNM_FILE_NAME
1118 ? flags
: flags
& ~FNM_PERIOD
, NULL
,
1119 alloca_used
) == 0)))
1120 /* It worked. Signal success. */
1123 while ((list
= list
->next
) != NULL
);
1125 /* None of the patterns lead to a match. */
1126 retval
= FNM_NOMATCH
;
1130 if (FCT (p
, string
, string_end
, no_leading_period
, flags
, NULL
,
1137 /* I cannot believe it but `strcat' is actually acceptable
1138 here. Match the entire string with the prefix from the
1139 pattern list and the rest of the pattern following the
1141 if (FCT (STRCAT (list
->str
, p
), string
, string_end
,
1143 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
,
1144 NULL
, alloca_used
) == 0)
1145 /* It worked. Signal success. */
1147 while ((list
= list
->next
) != NULL
);
1149 /* None of the patterns lead to a match. */
1150 retval
= FNM_NOMATCH
;
1154 for (rs
= string
; rs
<= string_end
; ++rs
)
1156 struct patternlist
*runp
;
1158 for (runp
= list
; runp
!= NULL
; runp
= runp
->next
)
1159 if (FCT (runp
->str
, string
, rs
, no_leading_period
,
1160 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
,
1161 NULL
, alloca_used
) == 0)
1164 /* If none of the patterns matched see whether the rest does. */
1166 && (FCT (p
, rs
, string_end
,
1169 : rs
[-1] == '/' && NO_LEADING_PERIOD (flags
) ? 1 : 0,
1170 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
,
1171 NULL
, alloca_used
) == 0))
1172 /* This is successful. */
1176 /* None of the patterns together with the rest of the pattern
1178 retval
= FNM_NOMATCH
;
1182 assert (! "Invalid extended matching operator");
1190 while (list
!= NULL
)
1192 struct patternlist
*old
= list
;
1217 #undef WIDE_CHAR_VERSION