1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * 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 5.2 (Berkeley) 06/01/90"; 13 #endif /* LIBC_SCCS and not lint */ 14 15 /* 16 * Function fnmatch() as proposed in Posix 1003.2 B.6 (rev. 9). 17 * Compares a filename or pathname to a pattern. 18 */ 19 20 #include <unistd.h> 21 #include <string.h> 22 23 #define EOS '\0' 24 25 fnmatch(pattern, string, flags) 26 register char *pattern, *string; 27 int flags; 28 { 29 register char c; 30 char test, *rangematch(); 31 32 for (;;) 33 switch (c = *pattern++) { 34 case EOS: 35 return(*string == EOS); 36 case '?': 37 if ((test = *string++) == EOS || 38 test == '/' && flags & FNM_PATHNAME) 39 return(0); 40 break; 41 case '*': 42 c = *pattern; 43 /* collapse multiple stars */ 44 while (c == '*') 45 c = *++pattern; 46 47 /* optimize for pattern with * at end or before / */ 48 if (c == EOS) 49 if (flags & FNM_PATHNAME) 50 return(!index(string, '/')); 51 else 52 return(1); 53 else if (c == '/' && flags & FNM_PATHNAME) { 54 if ((string = index(string, '/')) == NULL) 55 return(0); 56 break; 57 } 58 59 /* general case, use recursion */ 60 while ((test = *string) != EOS) { 61 if (fnmatch(pattern, string, flags)) 62 return(1); 63 if (test == '/' && flags & FNM_PATHNAME) 64 break; 65 ++string; 66 } 67 return(0); 68 case '[': 69 if ((test = *string++) == EOS || 70 test == '/' && flags & FNM_PATHNAME) 71 return(0); 72 if ((pattern = rangematch(pattern, test)) == NULL) 73 return(0); 74 break; 75 case '\\': 76 if (flags & FNM_QUOTE) { 77 if ((c = *pattern++) == EOS) { 78 c = '\\'; 79 --pattern; 80 } 81 if (c != *string++) 82 return(0); 83 break; 84 } 85 /* FALLTHROUGH */ 86 default: 87 if (c != *string++) 88 return(0); 89 break; 90 } 91 } 92 93 static char * 94 rangematch(pattern, test) 95 register char *pattern, test; 96 { 97 register char c, c2; 98 int negate, ok; 99 100 if (negate = (*pattern == '!')) 101 ++pattern; 102 103 /* 104 * TO DO: quoting 105 */ 106 107 for (ok = 0; (c = *pattern++) != ']';) { 108 if (c == EOS) 109 return(NULL); /* illegal pattern */ 110 if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') { 111 if (c <= test && test <= c2) 112 ok = 1; 113 pattern += 2; 114 } 115 else if (c == test) 116 ok = 1; 117 } 118 return(ok == negate ? NULL : pattern); 119 } 120