139734Sbostic /* 239734Sbostic * Copyright (c) 1989 The Regents of the University of California. 339734Sbostic * All rights reserved. 439734Sbostic * 539734Sbostic * This code is derived from software contributed to Berkeley by 639734Sbostic * Guido van Rossum. 739734Sbostic * 842624Sbostic * %sccs.include.redist.c% 939734Sbostic */ 1039734Sbostic 1139734Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*54534Sbostic static char sccsid[] = "@(#)fnmatch.c 5.5 (Berkeley) 06/28/92"; 1339734Sbostic #endif /* LIBC_SCCS and not lint */ 1439734Sbostic 1539734Sbostic /* 1639734Sbostic * Function fnmatch() as proposed in Posix 1003.2 B.6 (rev. 9). 1739734Sbostic * Compares a filename or pathname to a pattern. 1839734Sbostic */ 1939734Sbostic 20*54534Sbostic #include <fnmatch.h> 2139734Sbostic #include <string.h> 2239734Sbostic 2339734Sbostic #define EOS '\0' 2439734Sbostic 25*54534Sbostic static char *rangematch __P((char *, int)); 2643528Sbostic 2739734Sbostic fnmatch(pattern, string, flags) 28*54534Sbostic register const char *pattern, *string; 2939734Sbostic int flags; 3039734Sbostic { 3139734Sbostic register char c; 32*54534Sbostic char test; 3339734Sbostic 3439734Sbostic for (;;) 3539734Sbostic switch (c = *pattern++) { 3639734Sbostic case EOS: 37*54534Sbostic return (*string == EOS ? 0 : FNM_NOMATCH); 3839734Sbostic case '?': 3939734Sbostic if ((test = *string++) == EOS || 4039734Sbostic test == '/' && flags & FNM_PATHNAME) 41*54534Sbostic return (FNM_NOMATCH); 4239734Sbostic break; 4339734Sbostic case '*': 4439734Sbostic c = *pattern; 45*54534Sbostic /* Collapse multiple stars. */ 4639734Sbostic while (c == '*') 4739734Sbostic c = *++pattern; 4839734Sbostic 49*54534Sbostic /* Optimize for pattern with * at end or before /. */ 5039734Sbostic if (c == EOS) 5139734Sbostic if (flags & FNM_PATHNAME) 52*54534Sbostic return (index(string, '/') == NULL ? 53*54534Sbostic 0 : FNM_NOMATCH); 5439734Sbostic else 55*54534Sbostic return (0); 5639734Sbostic else if (c == '/' && flags & FNM_PATHNAME) { 5739734Sbostic if ((string = index(string, '/')) == NULL) 58*54534Sbostic return (FNM_NOMATCH); 5939734Sbostic break; 6039734Sbostic } 6139734Sbostic 62*54534Sbostic /* General case, use recursion. */ 6339734Sbostic while ((test = *string) != EOS) { 64*54534Sbostic if (!fnmatch(pattern, string, flags)) 65*54534Sbostic return (0); 6639734Sbostic if (test == '/' && flags & FNM_PATHNAME) 6739734Sbostic break; 6839734Sbostic ++string; 6939734Sbostic } 70*54534Sbostic return (FNM_NOMATCH); 7139734Sbostic case '[': 7239734Sbostic if ((test = *string++) == EOS || 7339734Sbostic test == '/' && flags & FNM_PATHNAME) 74*54534Sbostic return (FNM_NOMATCH); 7539734Sbostic if ((pattern = rangematch(pattern, test)) == NULL) 76*54534Sbostic return (FNM_NOMATCH); 7739734Sbostic break; 7839734Sbostic case '\\': 79*54534Sbostic if (!(flags & FNM_NOESCAPE)) { 8039734Sbostic if ((c = *pattern++) == EOS) { 8139734Sbostic c = '\\'; 8239734Sbostic --pattern; 8339734Sbostic } 8439734Sbostic if (c != *string++) 85*54534Sbostic return (FNM_NOMATCH); 8639734Sbostic break; 8739734Sbostic } 8839734Sbostic /* FALLTHROUGH */ 8939734Sbostic default: 9039734Sbostic if (c != *string++) 91*54534Sbostic return (FNM_NOMATCH); 9239734Sbostic break; 9339734Sbostic } 94*54534Sbostic /* NOTREACHED */ 9539734Sbostic } 96*54534Sbostic 97*54534Sbostic static char * 98*54534Sbostic rangematch(pattern, test) 99*54534Sbostic register char *pattern; 100*54534Sbostic register int test; 101*54534Sbostic { 102*54534Sbostic register char c, c2; 103*54534Sbostic int negate, ok; 104*54534Sbostic 105*54534Sbostic if (negate = (*pattern == '!')) 106*54534Sbostic ++pattern; 107*54534Sbostic 108*54534Sbostic /* 109*54534Sbostic * XXX 110*54534Sbostic * TO DO: quoting 111*54534Sbostic */ 112*54534Sbostic for (ok = 0; (c = *pattern++) != ']';) { 113*54534Sbostic if (c == EOS) 114*54534Sbostic return (NULL); /* Illegal pattern. */ 115*54534Sbostic if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') { 116*54534Sbostic if (c <= test && test <= c2) 117*54534Sbostic ok = 1; 118*54534Sbostic pattern += 2; 119*54534Sbostic } 120*54534Sbostic else if (c == test) 121*54534Sbostic ok = 1; 122*54534Sbostic } 123*54534Sbostic return (ok == negate ? NULL : pattern); 124*54534Sbostic } 125