glob.c (3171B)
1 2 #include <stdio.h> 3 #include "../linux/glob.h" 4 5 /* Like glob_match, but match PATTERN against any final segment of TEXT. */ 6 static int glob_match_after_star(char *pattern, char *text) 7 { 8 register char *p = pattern, *t = text; 9 register char c, c1; 10 11 while ((c = *p++) == '?' || c == '*') 12 if (c == '?' && *t++ == '\0') 13 return 0; 14 15 if (c == '\0') 16 return 1; 17 18 if (c == '\\') 19 c1 = *p; 20 else 21 c1 = c; 22 23 while (1) { 24 if ((c == '[' || *t == c1) && glob_match(p - 1, t)) 25 return 1; 26 if (*t++ == '\0') 27 return 0; 28 } 29 } 30 31 /* Return nonzero if PATTERN has any special globbing chars in it. */ 32 static int glob_pattern_p(char *pattern) 33 { 34 register char *p = pattern; 35 register char c; 36 int open = 0; 37 38 while ((c = *p++) != '\0') 39 switch (c) { 40 case '?': 41 case '*': 42 return 1; 43 44 case '[': /* Only accept an open brace if there is a close */ 45 open++; /* brace to match it. Bracket expressions must be */ 46 continue; /* complete, according to Posix.2 */ 47 case ']': 48 if (open) 49 return 1; 50 continue; 51 52 case '\\': 53 if (*p++ == '\0') 54 return 0; 55 } 56 57 return 0; 58 } 59 60 /* Match the pattern PATTERN against the string TEXT; 61 return 1 if it matches, 0 otherwise. 62 63 A match means the entire string TEXT is used up in matching. 64 65 In the pattern string, `*' matches any sequence of characters, 66 `?' matches any character, [SET] matches any character in the specified set, 67 [!SET] matches any character not in the specified set. 68 69 A set is composed of characters or ranges; a range looks like 70 character hyphen character (as in 0-9 or A-Z). 71 [0-9a-zA-Z_] is the set of characters allowed in C identifiers. 72 Any other character in the pattern must be matched exactly. 73 74 To suppress the special syntactic significance of any of `[]*?!-\', 75 and match the character exactly, precede it with a `\'. 76 */ 77 78 int glob_match(char *pattern, char *text) 79 { 80 register char *p = pattern, *t = text; 81 register char c; 82 83 while ((c = *p++) != '\0') 84 switch (c) { 85 case '?': 86 if (*t == '\0') 87 return 0; 88 else 89 ++t; 90 break; 91 92 case '\\': 93 if (*p++ != *t++) 94 return 0; 95 break; 96 97 case '*': 98 return glob_match_after_star(p, t); 99 100 case '[': 101 { 102 register char c1 = *t++; 103 int invert; 104 105 if (!c1) 106 return (0); 107 108 invert = ((*p == '!') || (*p == '^')); 109 if (invert) 110 p++; 111 112 c = *p++; 113 while (1) { 114 register char cstart = c, cend = c; 115 116 if (c == '\\') { 117 cstart = *p++; 118 cend = cstart; 119 } 120 if (c == '\0') 121 return 0; 122 123 c = *p++; 124 if (c == '-' && *p != ']') { 125 cend = *p++; 126 if (cend == '\\') 127 cend = *p++; 128 if (cend == '\0') 129 return 0; 130 c = *p++; 131 } 132 if (c1 >= cstart && c1 <= cend) 133 goto match; 134 if (c == ']') 135 break; 136 } 137 if (!invert) 138 return 0; 139 break; 140 141 match: 142 /* Skip the rest of the [...] construct that already matched. */ 143 while (c != ']') { 144 if (c == '\0') 145 return 0; 146 c = *p++; 147 if (c == '\0') 148 return 0; 149 else if (c == '\\') 150 ++p; 151 } 152 if (invert) 153 return 0; 154 break; 155 } 156 157 default: 158 if (c != *t++) 159 return 0; 160 } 161 162 return *t == '\0'; 163 } 164