source: trunk/essentials/app-shells/bash/lib/glob/sm_loop.c

Last change on this file was 3250, checked in by bird, 19 years ago

Applied bash31-015

  • Property svn:eol-style set to native
File size: 20.9 KB
Line 
1/* Copyright (C) 1991-2005 Free Software Foundation, Inc.
2
3 This file is part of GNU Bash, the Bourne Again SHell.
4
5 Bash is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 2, or (at your option) any later
8 version.
9
10 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with Bash; see the file COPYING. If not, write to the Free Software
17 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
18
19int FCT __P((CHAR *, CHAR *, int));
20
21static int GMATCH __P((CHAR *, CHAR *, CHAR *, CHAR *, int));
22static CHAR *PARSE_COLLSYM __P((CHAR *, INT *));
23static CHAR *BRACKMATCH __P((CHAR *, U_CHAR, int));
24static int EXTMATCH __P((INT, CHAR *, CHAR *, CHAR *, CHAR *, int));
25static CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
26
27int
28FCT (pattern, string, flags)
29 CHAR *pattern;
30 CHAR *string;
31 int flags;
32{
33 CHAR *se, *pe;
34
35 if (string == 0 || pattern == 0)
36 return FNM_NOMATCH;
37
38 se = string + STRLEN ((XCHAR *)string);
39 pe = pattern + STRLEN ((XCHAR *)pattern);
40
41 return (GMATCH (string, se, pattern, pe, flags));
42}
43
44/* Match STRING against the filename pattern PATTERN, returning zero if
45 it matches, FNM_NOMATCH if not. */
46static int
47GMATCH (string, se, pattern, pe, flags)
48 CHAR *string, *se;
49 CHAR *pattern, *pe;
50 int flags;
51{
52 CHAR *p, *n; /* pattern, string */
53 INT c; /* current pattern character - XXX U_CHAR? */
54 INT sc; /* current string character - XXX U_CHAR? */
55
56 p = pattern;
57 n = string;
58
59 if (string == 0 || pattern == 0)
60 return FNM_NOMATCH;
61
62#if DEBUG_MATCHING
63fprintf(stderr, "gmatch: string = %s; se = %s\n", string, se);
64fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
65#endif
66
67 while (p < pe)
68 {
69 c = *p++;
70 c = FOLD (c);
71
72 sc = n < se ? *n : '\0';
73
74#ifdef EXTENDED_GLOB
75 /* EXTMATCH () will handle recursively calling GMATCH, so we can
76 just return what EXTMATCH() returns. */
77 if ((flags & FNM_EXTMATCH) && *p == L('(') &&
78 (c == L('+') || c == L('*') || c == L('?') || c == L('@') || c == L('!'))) /* ) */
79 {
80 int lflags;
81 /* If we're not matching the start of the string, we're not
82 concerned about the special cases for matching `.' */
83 lflags = (n == string) ? flags : (flags & ~FNM_PERIOD);
84 return (EXTMATCH (c, n, se, p, pe, lflags));
85 }
86#endif /* EXTENDED_GLOB */
87
88 switch (c)
89 {
90 case L('?'): /* Match single character */
91 if (sc == '\0')
92 return FNM_NOMATCH;
93 else if ((flags & FNM_PATHNAME) && sc == L('/'))
94 /* If we are matching a pathname, `?' can never match a `/'. */
95 return FNM_NOMATCH;
96 else if ((flags & FNM_PERIOD) && sc == L('.') &&
97 (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
98 /* `?' cannot match a `.' if it is the first character of the
99 string or if it is the first character following a slash and
100 we are matching a pathname. */
101 return FNM_NOMATCH;
102 break;
103
104 case L('\\'): /* backslash escape removes special meaning */
105 if (p == pe)
106 return FNM_NOMATCH;
107
108 if ((flags & FNM_NOESCAPE) == 0)
109 {
110 c = *p++;
111 /* A trailing `\' cannot match. */
112 if (p > pe)
113 return FNM_NOMATCH;
114 c = FOLD (c);
115 }
116 if (FOLD (sc) != (U_CHAR)c)
117 return FNM_NOMATCH;
118 break;
119
120 case '*': /* Match zero or more characters */
121 if (p == pe)
122 return 0;
123
124 if ((flags & FNM_PERIOD) && sc == L('.') &&
125 (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
126 /* `*' cannot match a `.' if it is the first character of the
127 string or if it is the first character following a slash and
128 we are matching a pathname. */
129 return FNM_NOMATCH;
130
131 /* Collapse multiple consecutive `*' and `?', but make sure that
132 one character of the string is consumed for each `?'. */
133 for (c = *p++; (c == L('?') || c == L('*')); c = *p++)
134 {
135 if ((flags & FNM_PATHNAME) && sc == L('/'))
136 /* A slash does not match a wildcard under FNM_PATHNAME. */
137 return FNM_NOMATCH;
138#ifdef EXTENDED_GLOB
139 else if ((flags & FNM_EXTMATCH) && c == L('?') && *p == L('(')) /* ) */
140 {
141 CHAR *newn;
142 for (newn = n; newn < se; ++newn)
143 {
144 if (EXTMATCH (c, newn, se, p, pe, flags) == 0)
145 return (0);
146 }
147 /* We didn't match. If we have a `?(...)', that's failure. */
148 return FNM_NOMATCH;
149 }
150#endif
151 else if (c == L('?'))
152 {
153 if (sc == L('\0'))
154 return FNM_NOMATCH;
155 /* One character of the string is consumed in matching
156 this ? wildcard, so *??? won't match if there are
157 fewer than three characters. */
158 n++;
159 sc = n < se ? *n : '\0';
160 }
161
162#ifdef EXTENDED_GLOB
163 /* Handle ******(patlist) */
164 if ((flags & FNM_EXTMATCH) && c == L('*') && *p == L('(')) /*)*/
165 {
166 CHAR *newn;
167 /* We need to check whether or not the extended glob
168 pattern matches the remainder of the string.
169 If it does, we match the entire pattern. */
170 for (newn = n; newn < se; ++newn)
171 {
172 if (EXTMATCH (c, newn, se, p, pe, flags) == 0)
173 return (0);
174 }
175 /* We didn't match the extended glob pattern, but
176 that's OK, since we can match 0 or more occurrences.
177 We need to skip the glob pattern and see if we
178 match the rest of the string. */
179 newn = PATSCAN (p + 1, pe, 0);
180 /* If NEWN is 0, we have an ill-formed pattern. */
181 p = newn ? newn : pe;
182 }
183#endif
184 if (p == pe)
185 break;
186 }
187
188 /* If we've hit the end of the pattern and the last character of
189 the pattern was handled by the loop above, we've succeeded.
190 Otherwise, we need to match that last character. */
191 if (p == pe && (c == L('?') || c == L('*')))
192 return (0);
193
194 /* General case, use recursion. */
195 {
196 U_CHAR c1;
197
198 c1 = ((flags & FNM_NOESCAPE) == 0 && c == L('\\')) ? *p : c;
199 c1 = FOLD (c1);
200 for (--p; n < se; ++n)
201 {
202 /* Only call strmatch if the first character indicates a
203 possible match. We can check the first character if
204 we're not doing an extended glob match. */
205 if ((flags & FNM_EXTMATCH) == 0 && c != L('[') && FOLD (*n) != c1) /*]*/
206 continue;
207
208 /* If we're doing an extended glob match and the pattern is not
209 one of the extended glob patterns, we can check the first
210 character. */
211 if ((flags & FNM_EXTMATCH) && p[1] != L('(') && /*)*/
212 STRCHR (L("?*+@!"), *p) == 0 && c != L('[') && FOLD (*n) != c1) /*]*/
213 continue;
214
215 /* Otherwise, we just recurse. */
216 if (GMATCH (n, se, p, pe, flags & ~FNM_PERIOD) == 0)
217 return (0);
218 }
219 return FNM_NOMATCH;
220 }
221
222 case L('['):
223 {
224 if (sc == L('\0') || n == se)
225 return FNM_NOMATCH;
226
227 /* A character class cannot match a `.' if it is the first
228 character of the string or if it is the first character
229 following a slash and we are matching a pathname. */
230 if ((flags & FNM_PERIOD) && sc == L('.') &&
231 (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
232 return (FNM_NOMATCH);
233
234 p = BRACKMATCH (p, sc, flags);
235 if (p == 0)
236 return FNM_NOMATCH;
237 }
238 break;
239
240 default:
241 if ((U_CHAR)c != FOLD (sc))
242 return (FNM_NOMATCH);
243 }
244
245 ++n;
246 }
247
248 if (n == se)
249 return (0);
250
251 if ((flags & FNM_LEADING_DIR) && *n == L('/'))
252 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
253 return 0;
254
255 return (FNM_NOMATCH);
256}
257
258/* Parse a bracket expression collating symbol ([.sym.]) starting at P, find
259 the value of the symbol, and move P past the collating symbol expression.
260 The value is returned in *VP, if VP is not null. */
261static CHAR *
262PARSE_COLLSYM (p, vp)
263 CHAR *p;
264 INT *vp;
265{
266 register int pc;
267 INT val;
268
269 p++; /* move past the `.' */
270
271 for (pc = 0; p[pc]; pc++)
272 if (p[pc] == L('.') && p[pc+1] == L(']'))
273 break;
274 val = COLLSYM (p, pc);
275 if (vp)
276 *vp = val;
277 return (p + pc + 2);
278}
279
280/* Use prototype definition here because of type promotion. */
281static CHAR *
282#if defined (PROTOTYPES)
283BRACKMATCH (CHAR *p, U_CHAR test, int flags)
284#else
285BRACKMATCH (p, test, flags)
286 CHAR *p;
287 U_CHAR test;
288 int flags;
289#endif
290{
291 register CHAR cstart, cend, c;
292 register int not; /* Nonzero if the sense of the character class is inverted. */
293 int brcnt;
294 INT pc;
295 CHAR *savep;
296
297 test = FOLD (test);
298
299 savep = p;
300
301 /* POSIX.2 3.13.1 says that an exclamation mark (`!') shall replace the
302 circumflex (`^') in its role in a `nonmatching list'. A bracket
303 expression starting with an unquoted circumflex character produces
304 unspecified results. This implementation treats the two identically. */
305 if (not = (*p == L('!') || *p == L('^')))
306 ++p;
307
308 c = *p++;
309 for (;;)
310 {
311 /* Initialize cstart and cend in case `-' is the last
312 character of the pattern. */
313 cstart = cend = c;
314
315 /* POSIX.2 equivalence class: [=c=]. See POSIX.2 2.8.3.2. Find
316 the end of the equivalence class, move the pattern pointer past
317 it, and check for equivalence. XXX - this handles only
318 single-character equivalence classes, which is wrong, or at
319 least incomplete. */
320 if (c == L('[') && *p == L('=') && p[2] == L('=') && p[3] == L(']'))
321 {
322 pc = FOLD (p[1]);
323 p += 4;
324 if (COLLEQUIV (test, pc))
325 {
326/*[*/ /* Move past the closing `]', since the first thing we do at
327 the `matched:' label is back p up one. */
328 p++;
329 goto matched;
330 }
331 else
332 {
333 c = *p++;
334 if (c == L('\0'))
335 return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
336 c = FOLD (c);
337 continue;
338 }
339 }
340
341 /* POSIX.2 character class expression. See POSIX.2 2.8.3.2. */
342 if (c == L('[') && *p == L(':'))
343 {
344 CHAR *close, *ccname;
345
346 pc = 0; /* make sure invalid char classes don't match. */
347 /* Find end of character class name */
348 for (close = p + 1; *close != '\0'; close++)
349 if (*close == L(':') && *(close+1) == L(']'))
350 break;
351
352 if (*close != L('\0'))
353 {
354 ccname = (CHAR *)malloc ((close - p) * sizeof (CHAR));
355 if (ccname == 0)
356 pc = 0;
357 else
358 {
359 bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR));
360 *(ccname + (close - p - 1)) = L('\0');
361 pc = IS_CCLASS (test, (XCHAR *)ccname);
362 }
363 if (pc == -1)
364 pc = 0;
365 else
366 p = close + 2;
367
368 free (ccname);
369 }
370
371 if (pc)
372 {
373/*[*/ /* Move past the closing `]', since the first thing we do at
374 the `matched:' label is back p up one. */
375 p++;
376 goto matched;
377 }
378 else
379 {
380 /* continue the loop here, since this expression can't be
381 the first part of a range expression. */
382 c = *p++;
383 if (c == L('\0'))
384 return ((test == L('[')) ? savep : (CHAR *)0);
385 else if (c == L(']'))
386 break;
387 c = FOLD (c);
388 continue;
389 }
390 }
391
392 /* POSIX.2 collating symbols. See POSIX.2 2.8.3.2. Find the end of
393 the symbol name, make sure it is terminated by `.]', translate
394 the name to a character using the external table, and do the
395 comparison. */
396 if (c == L('[') && *p == L('.'))
397 {
398 p = PARSE_COLLSYM (p, &pc);
399 /* An invalid collating symbol cannot be the first point of a
400 range. If it is, we set cstart to one greater than `test',
401 so any comparisons later will fail. */
402 cstart = (pc == INVALID) ? test + 1 : pc;
403 }
404
405 if (!(flags & FNM_NOESCAPE) && c == L('\\'))
406 {
407 if (*p == '\0')
408 return (CHAR *)0;
409 cstart = cend = *p++;
410 }
411
412 cstart = cend = FOLD (cstart);
413
414 /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
415 is not preceded by a backslash and is not part of a bracket
416 expression produces undefined results.' This implementation
417 treats the `[' as just a character to be matched if there is
418 not a closing `]'. */
419 if (c == L('\0'))
420 return ((test == L('[')) ? savep : (CHAR *)0);
421
422 c = *p++;
423 c = FOLD (c);
424
425 if ((flags & FNM_PATHNAME) && c == L('/'))
426 /* [/] can never match when matching a pathname. */
427 return (CHAR *)0;
428
429 /* This introduces a range, unless the `-' is the last
430 character of the class. Find the end of the range
431 and move past it. */
432 if (c == L('-') && *p != L(']'))
433 {
434 cend = *p++;
435 if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
436 cend = *p++;
437 if (cend == L('\0'))
438 return (CHAR *)0;
439 if (cend == L('[') && *p == L('.'))
440 {
441 p = PARSE_COLLSYM (p, &pc);
442 /* An invalid collating symbol cannot be the second part of a
443 range expression. If we get one, we set cend to one fewer
444 than the test character to make sure the range test fails. */
445 cend = (pc == INVALID) ? test - 1 : pc;
446 }
447 cend = FOLD (cend);
448
449 c = *p++;
450
451 /* POSIX.2 2.8.3.2: ``The ending range point shall collate
452 equal to or higher than the starting range point; otherwise
453 the expression shall be treated as invalid.'' Note that this
454 applies to only the range expression; the rest of the bracket
455 expression is still checked for matches. */
456 if (RANGECMP (cstart, cend) > 0)
457 {
458 if (c == L(']'))
459 break;
460 c = FOLD (c);
461 continue;
462 }
463 }
464
465 if (RANGECMP (test, cstart) >= 0 && RANGECMP (test, cend) <= 0)
466 goto matched;
467
468 if (c == L(']'))
469 break;
470 }
471 /* No match. */
472 return (!not ? (CHAR *)0 : p);
473
474matched:
475 /* Skip the rest of the [...] that already matched. */
476 c = *--p;
477 brcnt = 1;
478 while (brcnt > 0)
479 {
480 /* A `[' without a matching `]' is just another character to match. */
481 if (c == L('\0'))
482 return ((test == L('[')) ? savep : (CHAR *)0);
483
484 c = *p++;
485 if (c == L('[') && (*p == L('=') || *p == L(':') || *p == L('.')))
486 brcnt++;
487 else if (c == L(']'))
488 brcnt--;
489 else if (!(flags & FNM_NOESCAPE) && c == L('\\'))
490 {
491 if (*p == '\0')
492 return (CHAR *)0;
493 /* XXX 1003.2d11 is unclear if this is right. */
494 ++p;
495 }
496 }
497 return (not ? (CHAR *)0 : p);
498}
499
500#if defined (EXTENDED_GLOB)
501/* ksh-like extended pattern matching:
502
503 [?*+@!](pat-list)
504
505 where pat-list is a list of one or patterns separated by `|'. Operation
506 is as follows:
507
508 ?(patlist) match zero or one of the given patterns
509 *(patlist) match zero or more of the given patterns
510 +(patlist) match one or more of the given patterns
511 @(patlist) match exactly one of the given patterns
512 !(patlist) match anything except one of the given patterns
513*/
514
515/* Scan a pattern starting at STRING and ending at END, keeping track of
516 embedded () and []. If DELIM is 0, we scan until a matching `)'
517 because we're scanning a `patlist'. Otherwise, we scan until we see
518 DELIM. In all cases, we never scan past END. The return value is the
519 first character after the matching DELIM. */
520static CHAR *
521PATSCAN (string, end, delim)
522 CHAR *string, *end;
523 INT delim;
524{
525 int pnest, bnest, skip;
526 INT cchar;
527 CHAR *s, c, *bfirst;
528
529 pnest = bnest = skip = 0;
530 cchar = 0;
531 bfirst = NULL;
532
533 for (s = string; c = *s; s++)
534 {
535 if (s >= end)
536 return (s);
537 if (skip)
538 {
539 skip = 0;
540 continue;
541 }
542 switch (c)
543 {
544 case L('\\'):
545 skip = 1;
546 break;
547
548 case L('\0'):
549 return ((CHAR *)NULL);
550
551 /* `[' is not special inside a bracket expression, but it may
552 introduce one of the special POSIX bracket expressions
553 ([.SYM.], [=c=], [: ... :]) that needs special handling. */
554 case L('['):
555 if (bnest == 0)
556 {
557 bfirst = s + 1;
558 if (*bfirst == L('!') || *bfirst == L('^'))
559 bfirst++;
560 bnest++;
561 }
562 else if (s[1] == L(':') || s[1] == L('.') || s[1] == L('='))
563 cchar = s[1];
564 break;
565
566 /* `]' is not special if it's the first char (after a leading `!'
567 or `^') in a bracket expression or if it's part of one of the
568 special POSIX bracket expressions ([.SYM.], [=c=], [: ... :]) */
569 case L(']'):
570 if (bnest)
571 {
572 if (cchar && s[-1] == cchar)
573 cchar = 0;
574 else if (s != bfirst)
575 {
576 bnest--;
577 bfirst = 0;
578 }
579 }
580 break;
581
582 case L('('):
583 if (bnest == 0)
584 pnest++;
585 break;
586
587 case L(')'):
588 if (bnest == 0 && pnest-- <= 0)
589 return ++s;
590 break;
591
592 case L('|'):
593 if (bnest == 0 && pnest == 0 && delim == L('|'))
594 return ++s;
595 break;
596 }
597 }
598
599 return (NULL);
600}
601
602/* Return 0 if dequoted pattern matches S in the current locale. */
603static int
604STRCOMPARE (p, pe, s, se)
605 CHAR *p, *pe, *s, *se;
606{
607 int ret;
608 CHAR c1, c2;
609
610 c1 = *pe;
611 c2 = *se;
612
613 *pe = *se = '\0';
614#if HAVE_MULTIBYTE || defined (HAVE_STRCOLL)
615 ret = STRCOLL ((XCHAR *)p, (XCHAR *)s);
616#else
617 ret = STRCMP ((XCHAR *)p, (XCHAR *)s);
618#endif
619
620 *pe = c1;
621 *se = c2;
622
623 return (ret == 0 ? ret : FNM_NOMATCH);
624}
625
626/* Match a ksh extended pattern specifier. Return FNM_NOMATCH on failure or
627 0 on success. This is handed the entire rest of the pattern and string
628 the first time an extended pattern specifier is encountered, so it calls
629 gmatch recursively. */
630static int
631EXTMATCH (xc, s, se, p, pe, flags)
632 INT xc; /* select which operation */
633 CHAR *s, *se;
634 CHAR *p, *pe;
635 int flags;
636{
637 CHAR *prest; /* pointer to rest of pattern */
638 CHAR *psub; /* pointer to sub-pattern */
639 CHAR *pnext; /* pointer to next sub-pattern */
640 CHAR *srest; /* pointer to rest of string */
641 int m1, m2, xflags; /* xflags = flags passed to recursive matches */
642
643#if DEBUG_MATCHING
644fprintf(stderr, "extmatch: xc = %c\n", xc);
645fprintf(stderr, "extmatch: s = %s; se = %s\n", s, se);
646fprintf(stderr, "extmatch: p = %s; pe = %s\n", p, pe);
647fprintf(stderr, "extmatch: flags = %d\n", flags);
648#endif
649
650 prest = PATSCAN (p + (*p == L('(')), pe, 0); /* ) */
651 if (prest == 0)
652 /* If PREST is 0, we failed to scan a valid pattern. In this
653 case, we just want to compare the two as strings. */
654 return (STRCOMPARE (p - 1, pe, s, se));
655
656 switch (xc)
657 {
658 case L('+'): /* match one or more occurrences */
659 case L('*'): /* match zero or more occurrences */
660 /* If we can get away with no matches, don't even bother. Just
661 call GMATCH on the rest of the pattern and return success if
662 it succeeds. */
663 if (xc == L('*') && (GMATCH (s, se, prest, pe, flags) == 0))
664 return 0;
665
666 /* OK, we have to do this the hard way. First, we make sure one of
667 the subpatterns matches, then we try to match the rest of the
668 string. */
669 for (psub = p + 1; ; psub = pnext)
670 {
671 pnext = PATSCAN (psub, pe, L('|'));
672 for (srest = s; srest <= se; srest++)
673 {
674 /* Match this substring (S -> SREST) against this
675 subpattern (psub -> pnext - 1) */
676 m1 = GMATCH (s, srest, psub, pnext - 1, flags) == 0;
677 /* OK, we matched a subpattern, so make sure the rest of the
678 string matches the rest of the pattern. Also handle
679 multiple matches of the pattern. */
680 if (m1)
681 {
682 /* if srest > s, we are not at start of string */
683 xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags;
684 m2 = (GMATCH (srest, se, prest, pe, xflags) == 0) ||
685 (s != srest && GMATCH (srest, se, p - 1, pe, xflags) == 0);
686 }
687 if (m1 && m2)
688 return (0);
689 }
690 if (pnext == prest)
691 break;
692 }
693 return (FNM_NOMATCH);
694
695 case L('?'): /* match zero or one of the patterns */
696 case L('@'): /* match exactly one of the patterns */
697 /* If we can get away with no matches, don't even bother. Just
698 call gmatch on the rest of the pattern and return success if
699 it succeeds. */
700 if (xc == L('?') && (GMATCH (s, se, prest, pe, flags) == 0))
701 return 0;
702
703 /* OK, we have to do this the hard way. First, we see if one of
704 the subpatterns matches, then, if it does, we try to match the
705 rest of the string. */
706 for (psub = p + 1; ; psub = pnext)
707 {
708 pnext = PATSCAN (psub, pe, L('|'));
709 srest = (prest == pe) ? se : s;
710 for ( ; srest <= se; srest++)
711 {
712 /* if srest > s, we are not at start of string */
713 xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags;
714 if (GMATCH (s, srest, psub, pnext - 1, flags) == 0 &&
715 GMATCH (srest, se, prest, pe, xflags) == 0)
716 return (0);
717 }
718 if (pnext == prest)
719 break;
720 }
721 return (FNM_NOMATCH);
722
723 case '!': /* match anything *except* one of the patterns */
724 for (srest = s; srest <= se; srest++)
725 {
726 m1 = 0;
727 for (psub = p + 1; ; psub = pnext)
728 {
729 pnext = PATSCAN (psub, pe, L('|'));
730 /* If one of the patterns matches, just bail immediately. */
731 if (m1 = (GMATCH (s, srest, psub, pnext - 1, flags) == 0))
732 break;
733 if (pnext == prest)
734 break;
735 }
736 /* if srest > s, we are not at start of string */
737 xflags = (srest > s) ? (flags & ~FNM_PERIOD) : flags;
738 if (m1 == 0 && GMATCH (srest, se, prest, pe, xflags) == 0)
739 return (0);
740 }
741 return (FNM_NOMATCH);
742 }
743
744 return (FNM_NOMATCH);
745}
746#endif /* EXTENDED_GLOB */
747
748#undef IS_CCLASS
749#undef FOLD
750#undef CHAR
751#undef U_CHAR
752#undef XCHAR
753#undef INT
754#undef INVALID
755#undef FCT
756#undef GMATCH
757#undef COLLSYM
758#undef PARSE_COLLSYM
759#undef PATSCAN
760#undef STRCOMPARE
761#undef EXTMATCH
762#undef BRACKMATCH
763#undef STRCHR
764#undef STRCOLL
765#undef STRLEN
766#undef STRCMP
767#undef COLLEQUIV
768#undef RANGECMP
769#undef L
Note: See TracBrowser for help on using the repository browser.