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