1 /* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2003,2004,2005
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library 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 GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 /* Match STRING against the filename pattern PATTERN, returning zero if
21 it matches, nonzero if not. */
22 static int FCT (const CHAR
*pattern
, const CHAR
*string
,
23 const CHAR
*string_end
, int no_leading_period
, int flags
)
25 static int EXT (INT opt
, const CHAR
*pattern
, const CHAR
*string
,
26 const CHAR
*string_end
, int no_leading_period
, int flags
)
28 static const CHAR
*END (const CHAR
*patternp
) internal_function
;
32 FCT (pattern
, string
, string_end
, no_leading_period
, flags
)
35 const CHAR
*string_end
;
36 int no_leading_period
;
39 register const CHAR
*p
= pattern
, *n
= string
;
42 # if WIDE_CHAR_VERSION
43 const char *collseq
= (const char *)
44 _NL_CURRENT(LC_COLLATE
, _NL_COLLATE_COLLSEQWC
);
46 const UCHAR
*collseq
= (const UCHAR
*)
47 _NL_CURRENT(LC_COLLATE
, _NL_COLLATE_COLLSEQMB
);
51 while ((c
= *p
++) != L('\0'))
53 int new_no_leading_period
= 0;
59 if (__builtin_expect (flags
& FNM_EXTMATCH
, 0) && *p
== '(')
63 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
== '(')
95 res
= EXT (c
, p
, n
, string_end
, no_leading_period
,
101 if (n
!= string_end
&& *n
== L('.') && no_leading_period
)
104 for (c
= *p
++; c
== L('?') || c
== L('*'); c
= *p
++)
106 if (*p
== L('(') && (flags
& FNM_EXTMATCH
) != 0)
108 const CHAR
*endp
= END (p
);
111 /* This is a pattern. Skip over it. */
119 /* A ? needs to match one character. */
121 /* There isn't another character; no match. */
123 else if (*n
== L('/')
124 && __builtin_expect (flags
& FNM_FILE_NAME
, 0))
125 /* A slash does not match a wildcard under
129 /* One character of the string is consumed in matching
130 this ? wildcard, so *??? won't match if there are
131 less than three characters. */
137 /* The wildcard(s) is/are the last element of the pattern.
138 If the name is a file name and contains another slash
139 this means it cannot match, unless the FNM_LEADING_DIR
142 int result
= (flags
& FNM_FILE_NAME
) == 0 ? 0 : FNM_NOMATCH
;
144 if (flags
& FNM_FILE_NAME
)
146 if (flags
& FNM_LEADING_DIR
)
150 if (MEMCHR (n
, L('/'), string_end
- n
) == NULL
)
161 endp
= MEMCHR (n
, (flags
& FNM_FILE_NAME
) ? L('/') : L('\0'),
167 || (__builtin_expect (flags
& FNM_EXTMATCH
, 0) != 0
168 && (c
== L('@') || c
== L('+') || c
== L('!'))
171 int flags2
= ((flags
& FNM_FILE_NAME
)
172 ? flags
: (flags
& ~FNM_PERIOD
));
173 int no_leading_period2
= no_leading_period
;
175 for (--p
; n
< endp
; ++n
, no_leading_period2
= 0)
176 if (FCT (p
, n
, string_end
, no_leading_period2
, flags2
)
180 else if (c
== L('/') && (flags
& FNM_FILE_NAME
))
182 while (n
< string_end
&& *n
!= L('/'))
184 if (n
< string_end
&& *n
== L('/')
185 && (FCT (p
, n
+ 1, string_end
, flags
& FNM_PERIOD
, flags
)
191 int flags2
= ((flags
& FNM_FILE_NAME
)
192 ? flags
: (flags
& ~FNM_PERIOD
));
193 int no_leading_period2
= no_leading_period
;
195 if (c
== L('\\') && !(flags
& FNM_NOESCAPE
))
198 for (--p
; n
< endp
; ++n
, no_leading_period2
= 0)
199 if (FOLD ((UCHAR
) *n
) == c
200 && (FCT (p
, n
, string_end
, no_leading_period2
, flags2
)
206 /* If we come here no match is possible with the wildcard. */
211 /* Nonzero if the sense of the character class is inverted. */
216 if (posixly_correct
== 0)
217 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
222 if (*n
== L('.') && no_leading_period
)
225 if (*n
== L('/') && (flags
& FNM_FILE_NAME
))
226 /* `/' cannot be matched. */
229 not = (*p
== L('!') || (posixly_correct
< 0 && *p
== L('^')));
233 fn
= FOLD ((UCHAR
) *n
);
238 if (!(flags
& FNM_NOESCAPE
) && c
== L('\\'))
242 c
= FOLD ((UCHAR
) *p
);
247 else if (c
== L('[') && *p
== L(':'))
249 /* Leave room for the null. */
250 CHAR str
[CHAR_CLASS_MAX_LENGTH
+ 1];
252 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
255 const CHAR
*startp
= p
;
259 if (c1
== CHAR_CLASS_MAX_LENGTH
)
260 /* The name is too long and therefore the pattern
265 if (c
== L(':') && p
[1] == L(']'))
270 if (c
< L('a') || c
>= L('z'))
272 /* This cannot possibly be a character class name.
273 Match it as a normal range. */
282 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
283 wt
= IS_CHAR_CLASS (str
);
285 /* Invalid character class name. */
288 # if defined _LIBC && ! WIDE_CHAR_VERSION
289 /* The following code is glibc specific but does
290 there a good job in speeding up the code since
291 we can avoid the btowc() call. */
292 if (_ISCTYPE ((UCHAR
) *n
, wt
))
295 if (ISWCTYPE (BTOWC ((UCHAR
) *n
), wt
))
299 if ((STREQ (str
, L("alnum")) && ISALNUM ((UCHAR
) *n
))
300 || (STREQ (str
, L("alpha")) && ISALPHA ((UCHAR
) *n
))
301 || (STREQ (str
, L("blank")) && ISBLANK ((UCHAR
) *n
))
302 || (STREQ (str
, L("cntrl")) && ISCNTRL ((UCHAR
) *n
))
303 || (STREQ (str
, L("digit")) && ISDIGIT ((UCHAR
) *n
))
304 || (STREQ (str
, L("graph")) && ISGRAPH ((UCHAR
) *n
))
305 || (STREQ (str
, L("lower")) && ISLOWER ((UCHAR
) *n
))
306 || (STREQ (str
, L("print")) && ISPRINT ((UCHAR
) *n
))
307 || (STREQ (str
, L("punct")) && ISPUNCT ((UCHAR
) *n
))
308 || (STREQ (str
, L("space")) && ISSPACE ((UCHAR
) *n
))
309 || (STREQ (str
, L("upper")) && ISUPPER ((UCHAR
) *n
))
310 || (STREQ (str
, L("xdigit")) && ISXDIGIT ((UCHAR
) *n
)))
316 else if (c
== L('[') && *p
== L('='))
320 _NL_CURRENT_WORD (LC_COLLATE
, _NL_COLLATE_NRULES
);
321 const CHAR
*startp
= p
;
333 if (c
!= L('=') || p
[1] != L(']'))
343 if ((UCHAR
) *n
== str
[0])
348 const int32_t *table
;
349 # if WIDE_CHAR_VERSION
350 const int32_t *weights
;
351 const int32_t *extra
;
353 const unsigned char *weights
;
354 const unsigned char *extra
;
356 const int32_t *indirect
;
358 const UCHAR
*cp
= (const UCHAR
*) str
;
360 /* This #include defines a local function! */
361 # if WIDE_CHAR_VERSION
362 # include <locale/weightwc.h>
364 # include <locale/weight.h>
367 # if WIDE_CHAR_VERSION
368 table
= (const int32_t *)
369 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEWC
);
370 weights
= (const int32_t *)
371 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTWC
);
372 extra
= (const int32_t *)
373 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAWC
);
374 indirect
= (const int32_t *)
375 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTWC
);
377 table
= (const int32_t *)
378 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_TABLEMB
);
379 weights
= (const unsigned char *)
380 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_WEIGHTMB
);
381 extra
= (const unsigned char *)
382 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_EXTRAMB
);
383 indirect
= (const int32_t *)
384 _NL_CURRENT (LC_COLLATE
, _NL_COLLATE_INDIRECTMB
);
390 /* We found a table entry. Now see whether the
391 character we are currently at has the same
392 equivalance class value. */
393 int len
= weights
[idx
];
395 const UCHAR
*np
= (const UCHAR
*) n
;
397 idx2
= findidx (&np
);
398 if (idx2
!= 0 && len
== weights
[idx2
])
403 && (weights
[idx
+ 1 + cnt
]
404 == weights
[idx2
+ 1 + cnt
]))
416 else if (c
== L('\0'))
417 /* [ (unterminated) loses. */
426 if (c
== L('[') && *p
== L('.'))
429 _NL_CURRENT_WORD (LC_COLLATE
, _NL_COLLATE_NRULES
);
430 const CHAR
*startp
= p
;
436 if (c
== L('.') && p
[1] == L(']'))
446 /* We have to handling the symbols differently in
447 ranges since then the collation sequence is
449 is_range
= *p
== L('-') && p
[1] != L('\0');
453 /* There are no names defined in the collation
454 data. Therefore we only accept the trivial
455 names consisting of the character itself. */
459 if (!is_range
&& *n
== startp
[1])
468 const int32_t *symb_table
;
469 # ifdef WIDE_CHAR_VERSION
473 # define str (startp + 1)
475 const unsigned char *extra
;
481 # ifdef WIDE_CHAR_VERSION
482 /* We have to convert the name to a single-byte
483 string. This is possible since the names
484 consist of ASCII characters and the internal
485 representation is UCS4. */
486 for (strcnt
= 0; strcnt
< c1
; ++strcnt
)
487 str
[strcnt
] = startp
[1 + strcnt
];
491 _NL_CURRENT_WORD (LC_COLLATE
,
492 _NL_COLLATE_SYMB_HASH_SIZEMB
);
493 symb_table
= (const int32_t *)
494 _NL_CURRENT (LC_COLLATE
,
495 _NL_COLLATE_SYMB_TABLEMB
);
496 extra
= (const unsigned char *)
497 _NL_CURRENT (LC_COLLATE
,
498 _NL_COLLATE_SYMB_EXTRAMB
);
500 /* Locate the character in the hashing table. */
501 hash
= elem_hash (str
, c1
);
504 elem
= hash
% table_size
;
505 if (symb_table
[2 * elem
] != 0)
507 second
= hash
% (table_size
- 2) + 1;
511 /* First compare the hashing value. */
512 if (symb_table
[2 * elem
] == hash
514 == extra
[symb_table
[2 * elem
+ 1]])
516 &extra
[symb_table
[2 * elem
520 /* Yep, this is the entry. */
521 idx
= symb_table
[2 * elem
+ 1];
522 idx
+= 1 + extra
[idx
];
529 while (symb_table
[2 * elem
] != 0);
532 if (symb_table
[2 * elem
] != 0)
534 /* Compare the byte sequence but only if
535 this is not part of a range. */
536 # ifdef WIDE_CHAR_VERSION
539 idx
+= 1 + extra
[idx
];
540 /* Adjust for the alignment. */
541 idx
= (idx
+ 3) & ~3;
543 wextra
= (int32_t *) &extra
[idx
+ 4];
548 # ifdef WIDE_CHAR_VERSION
550 (int32_t) c1
< wextra
[idx
];
552 if (n
[c1
] != wextra
[1 + c1
])
555 if ((int32_t) c1
== wextra
[idx
])
558 for (c1
= 0; c1
< extra
[idx
]; ++c1
)
559 if (n
[c1
] != extra
[1 + c1
])
562 if (c1
== extra
[idx
])
567 /* Get the collation sequence value. */
569 # ifdef WIDE_CHAR_VERSION
570 cold
= wextra
[1 + wextra
[idx
]];
572 /* Adjust for the alignment. */
573 idx
+= 1 + extra
[idx
];
574 idx
= (idx
+ 3) & ~4;
575 cold
= *((int32_t *) &extra
[idx
]);
582 /* No valid character. Match it as a
584 if (!is_range
&& *n
== str
[0])
601 /* We have to handling the symbols differently in
602 ranges since then the collation sequence is
604 is_range
= (*p
== L('-') && p
[1] != L('\0')
607 if (!is_range
&& c
== fn
)
610 /* This is needed if we goto normal_bracket; from
611 outside of is_seqval's scope. */
617 if (c
== L('-') && *p
!= L(']'))
620 /* We have to find the collation sequence
621 value for C. Collation sequence is nothing
622 we can regularly access. The sequence
623 value is defined by the order in which the
624 definitions of the collation values for the
625 various characters appear in the source
626 file. A strange concept, nowhere
632 # ifdef WIDE_CHAR_VERSION
633 /* Search in the `names' array for the characters. */
634 fcollseq
= __collseq_table_lookup (collseq
, fn
);
635 if (fcollseq
== ~((uint32_t) 0))
636 /* XXX We don't know anything about the character
637 we are supposed to match. This means we are
639 goto range_not_matched
;
644 lcollseq
= __collseq_table_lookup (collseq
, cold
);
646 fcollseq
= collseq
[fn
];
647 lcollseq
= is_seqval
? cold
: collseq
[(UCHAR
) cold
];
651 if (cend
== L('[') && *p
== L('.'))
654 _NL_CURRENT_WORD (LC_COLLATE
,
656 const CHAR
*startp
= p
;
662 if (c
== L('.') && p
[1] == L(']'))
674 /* There are no names defined in the
675 collation data. Therefore we only
676 accept the trivial names consisting
677 of the character itself. */
686 const int32_t *symb_table
;
687 # ifdef WIDE_CHAR_VERSION
691 # define str (startp + 1)
693 const unsigned char *extra
;
699 # ifdef WIDE_CHAR_VERSION
700 /* We have to convert the name to a single-byte
701 string. This is possible since the names
702 consist of ASCII characters and the internal
703 representation is UCS4. */
704 for (strcnt
= 0; strcnt
< c1
; ++strcnt
)
705 str
[strcnt
] = startp
[1 + strcnt
];
709 _NL_CURRENT_WORD (LC_COLLATE
,
710 _NL_COLLATE_SYMB_HASH_SIZEMB
);
711 symb_table
= (const int32_t *)
712 _NL_CURRENT (LC_COLLATE
,
713 _NL_COLLATE_SYMB_TABLEMB
);
714 extra
= (const unsigned char *)
715 _NL_CURRENT (LC_COLLATE
,
716 _NL_COLLATE_SYMB_EXTRAMB
);
718 /* Locate the character in the hashing
720 hash
= elem_hash (str
, c1
);
723 elem
= hash
% table_size
;
724 if (symb_table
[2 * elem
] != 0)
726 second
= hash
% (table_size
- 2) + 1;
730 /* First compare the hashing value. */
731 if (symb_table
[2 * elem
] == hash
733 == extra
[symb_table
[2 * elem
+ 1]])
735 &extra
[symb_table
[2 * elem
+ 1]
738 /* Yep, this is the entry. */
739 idx
= symb_table
[2 * elem
+ 1];
740 idx
+= 1 + extra
[idx
];
747 while (symb_table
[2 * elem
] != 0);
750 if (symb_table
[2 * elem
] != 0)
752 /* Compare the byte sequence but only if
753 this is not part of a range. */
754 # ifdef WIDE_CHAR_VERSION
757 idx
+= 1 + extra
[idx
];
758 /* Adjust for the alignment. */
759 idx
= (idx
+ 3) & ~4;
761 wextra
= (int32_t *) &extra
[idx
+ 4];
763 /* Get the collation sequence value. */
765 # ifdef WIDE_CHAR_VERSION
766 cend
= wextra
[1 + wextra
[idx
]];
768 /* Adjust for the alignment. */
769 idx
+= 1 + extra
[idx
];
770 idx
= (idx
+ 3) & ~4;
771 cend
= *((int32_t *) &extra
[idx
]);
774 else if (symb_table
[2 * elem
] != 0 && c1
== 1)
786 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
793 /* XXX It is not entirely clear to me how to handle
794 characters which are not mentioned in the
795 collation specification. */
797 # ifdef WIDE_CHAR_VERSION
798 lcollseq
== 0xffffffff ||
800 lcollseq
<= fcollseq
)
802 /* We have to look at the upper bound. */
809 # ifdef WIDE_CHAR_VERSION
811 __collseq_table_lookup (collseq
, cend
);
812 if (hcollseq
== ~((uint32_t) 0))
814 /* Hum, no information about the upper
815 bound. The matching succeeds if the
816 lower bound is matched exactly. */
817 if (lcollseq
!= fcollseq
)
818 goto range_not_matched
;
823 hcollseq
= collseq
[cend
];
827 if (lcollseq
<= hcollseq
&& fcollseq
<= hcollseq
)
830 # ifdef WIDE_CHAR_VERSION
834 /* We use a boring value comparison of the character
835 values. This is better than comparing using
836 `strcoll' since the latter would have surprising
837 and sometimes fatal consequences. */
840 if (!(flags
& FNM_NOESCAPE
) && cend
== L('\\'))
846 if (cold
<= fn
&& fn
<= cend
)
863 /* Skip the rest of the [...] that already matched. */
870 /* [... (unterminated) loses. */
873 if (!(flags
& FNM_NOESCAPE
) && c
== L('\\'))
877 /* XXX 1003.2d11 is unclear if this is right. */
880 else if (c
== L('[') && *p
== L(':'))
883 const CHAR
*startp
= p
;
888 if (++c1
== CHAR_CLASS_MAX_LENGTH
)
891 if (*p
== L(':') && p
[1] == L(']'))
894 if (c
< L('a') || c
>= L('z'))
903 else if (c
== L('[') && *p
== L('='))
909 if (c
!= L('=') || p
[1] != L(']'))
914 else if (c
== L('[') && *p
== L('.'))
923 if (*p
== L('.') && p
[1] == L(']'))
939 if (__builtin_expect (flags
& FNM_EXTMATCH
, 0) && *p
== '(')
943 res
= EXT (c
, p
, n
, string_end
, no_leading_period
, flags
);
950 if (NO_LEADING_PERIOD (flags
))
952 if (n
== string_end
|| c
!= (UCHAR
) *n
)
955 new_no_leading_period
= 1;
961 if (n
== string_end
|| c
!= FOLD ((UCHAR
) *n
))
965 no_leading_period
= new_no_leading_period
;
972 if ((flags
& FNM_LEADING_DIR
) && n
!= string_end
&& *n
== L('/'))
973 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
982 END (const CHAR
*pattern
)
984 const CHAR
*p
= pattern
;
988 /* This is an invalid pattern. */
990 else if (*p
== L('['))
992 /* Handle brackets special. */
993 if (posixly_correct
== 0)
994 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
996 /* Skip the not sign. We have to recognize it because of a possibly
998 if (*++p
== L('!') || (posixly_correct
< 0 && *p
== L('^')))
1000 /* A leading ']' is recognized as such. */
1003 /* Skip over all characters of the list. */
1004 while (*p
!= L(']'))
1005 if (*p
++ == L('\0'))
1006 /* This is no valid pattern. */
1009 else if ((*p
== L('?') || *p
== L('*') || *p
== L('+') || *p
== L('@')
1010 || *p
== L('!')) && p
[1] == L('('))
1012 else if (*p
== L(')'))
1021 EXT (INT opt
, const CHAR
*pattern
, const CHAR
*string
, const CHAR
*string_end
,
1022 int no_leading_period
, int flags
)
1028 struct patternlist
*next
;
1031 struct patternlist
**lastp
= &list
;
1032 size_t pattern_len
= STRLEN (pattern
);
1036 /* Parse the pattern. Store the individual parts in the list. */
1038 for (startp
= p
= pattern
+ 1; level
>= 0; ++p
)
1040 /* This is an invalid pattern. */
1042 else if (*p
== L('['))
1044 /* Handle brackets special. */
1045 if (posixly_correct
== 0)
1046 posixly_correct
= getenv ("POSIXLY_CORRECT") != NULL
? 1 : -1;
1048 /* Skip the not sign. We have to recognize it because of a possibly
1050 if (*++p
== L('!') || (posixly_correct
< 0 && *p
== L('^')))
1052 /* A leading ']' is recognized as such. */
1055 /* Skip over all characters of the list. */
1056 while (*p
!= L(']'))
1057 if (*p
++ == L('\0'))
1058 /* This is no valid pattern. */
1061 else if ((*p
== L('?') || *p
== L('*') || *p
== L('+') || *p
== L('@')
1062 || *p
== L('!')) && p
[1] == L('('))
1063 /* Remember the nesting level. */
1065 else if (*p
== L(')'))
1069 /* This means we found the end of the pattern. */
1070 #define NEW_PATTERN \
1071 struct patternlist *newp; \
1073 if (opt == L('?') || opt == L('@')) \
1074 newp = alloca (sizeof (struct patternlist) \
1075 + (pattern_len * sizeof (CHAR))); \
1077 newp = alloca (sizeof (struct patternlist) \
1078 + ((p - startp + 1) * sizeof (CHAR))); \
1079 *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
1080 newp->next = NULL; \
1086 else if (*p
== L('|'))
1094 assert (list
!= NULL
);
1095 assert (p
[-1] == L(')'));
1101 if (FCT (p
, string
, string_end
, no_leading_period
, flags
) == 0)
1108 for (rs
= string
; rs
<= string_end
; ++rs
)
1109 /* First match the prefix with the current pattern with the
1111 if (FCT (list
->str
, string
, rs
, no_leading_period
,
1112 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
) == 0
1113 /* This was successful. Now match the rest with the rest
1115 && (FCT (p
, rs
, string_end
,
1118 : rs
[-1] == '/' && NO_LEADING_PERIOD (flags
) ? 1 : 0,
1119 flags
& FNM_FILE_NAME
1120 ? flags
: flags
& ~FNM_PERIOD
) == 0
1121 /* This didn't work. Try the whole pattern. */
1123 && FCT (pattern
- 1, rs
, string_end
,
1126 : (rs
[-1] == '/' && NO_LEADING_PERIOD (flags
)
1128 flags
& FNM_FILE_NAME
1129 ? flags
: flags
& ~FNM_PERIOD
) == 0)))
1130 /* It worked. Signal success. */
1133 while ((list
= list
->next
) != NULL
);
1135 /* None of the patterns lead to a match. */
1139 if (FCT (p
, string
, string_end
, no_leading_period
, flags
) == 0)
1145 /* I cannot believe it but `strcat' is actually acceptable
1146 here. Match the entire string with the prefix from the
1147 pattern list and the rest of the pattern following the
1149 if (FCT (STRCAT (list
->str
, p
), string
, string_end
,
1151 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
) == 0)
1152 /* It worked. Signal success. */
1154 while ((list
= list
->next
) != NULL
);
1156 /* None of the patterns lead to a match. */
1160 for (rs
= string
; rs
<= string_end
; ++rs
)
1162 struct patternlist
*runp
;
1164 for (runp
= list
; runp
!= NULL
; runp
= runp
->next
)
1165 if (FCT (runp
->str
, string
, rs
, no_leading_period
,
1166 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
) == 0)
1169 /* If none of the patterns matched see whether the rest does. */
1171 && (FCT (p
, rs
, string_end
,
1174 : rs
[-1] == '/' && NO_LEADING_PERIOD (flags
) ? 1 : 0,
1175 flags
& FNM_FILE_NAME
? flags
: flags
& ~FNM_PERIOD
)
1177 /* This is successful. */
1181 /* None of the patterns together with the rest of the pattern
1186 assert (! "Invalid extended matching operator");