1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Guido van Rossum. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #if defined(LIBC_SCCS) && !defined(lint) 12 static char sccsid[] = "@(#)fnmatch.c 8.1 (Berkeley) 06/04/93"; 13 #endif /* LIBC_SCCS and not lint */ 14 15 /* 16 * Function fnmatch() as proposed in POSIX 1003.2 B.6 (D11.2). 17 * Compares a filename or pathname to a pattern. 18 */ 19 20 #include <fnmatch.h> 21 #include <string.h> 22 23 #define EOS '\0' 24 25 static const char *rangematch __P((const char *, int)); 26 27 fnmatch(pattern, string, flags) 28 register const char *pattern, *string; 29 int flags; 30 { 31 register char c; 32 char test; 33 34 for (;;) 35 switch (c = *pattern++) { 36 case EOS: 37 return (*string == EOS ? 0 : FNM_NOMATCH); 38 case '?': 39 if ((test = *string++) == EOS || 40 test == '/' && flags & FNM_PATHNAME) 41 return (FNM_NOMATCH); 42 break; 43 case '*': 44 c = *pattern; 45 /* Collapse multiple stars. */ 46 while (c == '*') 47 c = *++pattern; 48 49 /* Optimize for pattern with * at end or before /. */ 50 if (c == EOS) 51 if (flags & FNM_PATHNAME) 52 return (index(string, '/') == NULL ? 53 0 : FNM_NOMATCH); 54 else 55 return (0); 56 else if (c == '/' && flags & FNM_PATHNAME) { 57 if ((string = index(string, '/')) == NULL) 58 return (FNM_NOMATCH); 59 break; 60 } 61 62 /* General case, use recursion. */ 63 while ((test = *string) != EOS) { 64 if (!fnmatch(pattern, string, flags)) 65 return (0); 66 if (test == '/' && flags & FNM_PATHNAME) 67 break; 68 ++string; 69 } 70 return (FNM_NOMATCH); 71 case '[': 72 if ((test = *string++) == EOS || 73 test == '/' && flags & FNM_PATHNAME) 74 return (FNM_NOMATCH); 75 if ((pattern = rangematch(pattern, test)) == NULL) 76 return (FNM_NOMATCH); 77 break; 78 case '\\': 79 if (!(flags & FNM_NOESCAPE)) { 80 if ((c = *pattern++) == EOS) { 81 c = '\\'; 82 --pattern; 83 } 84 if (c != *string++) 85 return (FNM_NOMATCH); 86 break; 87 } 88 /* FALLTHROUGH */ 89 default: 90 if (c != *string++) 91 return (FNM_NOMATCH); 92 break; 93 } 94 /* NOTREACHED */ 95 } 96 97 static const char * 98 rangematch(pattern, test) 99 register const char *pattern; 100 register int test; 101 { 102 register char c, c2; 103 int negate, ok; 104 105 if (negate = (*pattern == '!')) 106 ++pattern; 107 108 /* 109 * XXX 110 * TO DO: quoting 111 */ 112 for (ok = 0; (c = *pattern++) != ']';) { 113 if (c == EOS) 114 return (NULL); /* Illegal pattern. */ 115 if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') { 116 if (c <= test && test <= c2) 117 ok = 1; 118 pattern += 2; 119 } 120 else if (c == test) 121 ok = 1; 122 } 123 return (ok == negate ? NULL : pattern); 124 } 125