version 1.13, 2000/07/17 22:57:37 |
version 1.14, 2000/07/17 23:01:20 |
|
|
* |
* |
* See if a particular string matches a particular pattern. |
* See if a particular string matches a particular pattern. |
* |
* |
* Results: Non-zero is returned if string matches pattern, 0 otherwise. The |
* Results: TRUE is returned if string matches pattern, FALSE otherwise. The |
* matching operation permits the following special characters in the |
* matching operation permits the following special characters in the |
* pattern: *?\[] (see the man page for details on what these mean). |
* pattern: *?\[] (see the man page for details on what these mean). |
* |
|
* Side effects: None. |
|
*/ |
*/ |
int |
Boolean |
Str_Match(string, pattern) |
Str_Match(string, pattern) |
const char *string; /* String */ |
const char *string; /* String */ |
const char *pattern; /* Pattern */ |
const char *pattern; /* Pattern */ |
{ |
{ |
char c2; |
while (*pattern != '\0') { |
|
/* Check for a "*" as the next pattern character. It matches |
for (;;) { |
* any substring. We handle this by calling ourselves |
/* |
* recursively for each postfix of string, until either we |
* See if we're at the end of both the pattern and the |
* match or we reach the end of the string. */ |
* string. If, we succeeded. If we're at the end of the |
if (*pattern == '*') { |
* pattern but not at the end of the string, we failed. |
pattern++; |
*/ |
/* Skip over contiguous sequences of `?*', so that recursive |
if (*pattern == 0) |
* calls only occur on `real' characters. */ |
return(!*string); |
while (*pattern == '?' || *pattern == '*') { |
if (*string == 0 && *pattern != '*') |
if (*pattern == '?') { |
return(0); |
if (*string == '\0') |
/* |
return FALSE; |
* Check for a "*" as the next pattern character. It matches |
else |
* any substring. We handle this by calling ourselves |
string++; |
* recursively for each postfix of string, until either we |
|
* match or we reach the end of the string. |
|
*/ |
|
if (*pattern == '*') { |
|
pattern += 1; |
|
if (*pattern == 0) |
|
return(1); |
|
while (*string != 0) { |
|
if (Str_Match(string, pattern)) |
|
return(1); |
|
++string; |
|
} |
|
return(0); |
|
} |
} |
/* |
pattern++; |
* Check for a "?" as the next pattern character. It matches |
} |
* any single character. |
if (*pattern == '\0') |
*/ |
return TRUE; |
if (*pattern == '?') |
for (; *string != '\0'; string++) |
goto thisCharOK; |
if (Str_Match(string, pattern)) |
/* |
return TRUE; |
* Check for a "[" as the next pattern character. It is |
return FALSE; |
* followed by a list of characters that are acceptable, or |
} else if (*string == '\0') |
* by a range (two characters separated by "-"). |
return FALSE; |
*/ |
/* Check for a "[" as the next pattern character. It is |
if (*pattern == '[') { |
* followed by a list of characters that are acceptable, or |
++pattern; |
* by a range (two characters separated by "-"). */ |
for (;;) { |
else if (*pattern == '[') { |
if ((*pattern == ']') || (*pattern == 0)) |
pattern++; |
return(0); |
if (*pattern == '\0') |
if (*pattern == *string) |
return FALSE; |
break; |
if (*pattern == '!' || *pattern == '^') { |
if (pattern[1] == '-') { |
pattern++; |
c2 = pattern[2]; |
if (*pattern == '\0') |
if (c2 == 0) |
return FALSE; |
return(0); |
/* Negative match */ |
if ((*pattern <= *string) && |
for (;;) { |
(c2 >= *string)) |
if (*pattern == '\\') { |
break; |
if (*++pattern == '\0') |
if ((*pattern >= *string) && |
return FALSE; |
(c2 <= *string)) |
} |
break; |
if (*pattern == *string) |
pattern += 2; |
return FALSE; |
} |
if (pattern[1] == '-') { |
++pattern; |
if (pattern[2] == '\0') |
} |
return FALSE; |
while ((*pattern != ']') && (*pattern != 0)) |
if (*pattern < *string && *string <= pattern[2]) |
++pattern; |
return FALSE; |
goto thisCharOK; |
if (pattern[2] <= *string && *string < *pattern) |
|
return FALSE; |
|
pattern += 3; |
|
} else |
|
pattern++; |
|
if (*pattern == '\0') |
|
return FALSE; |
|
/* The test for ']' is done at the end so that ']' |
|
* can be used at the start of the range without '\' */ |
|
if (*pattern == ']') |
|
break; |
} |
} |
/* |
} else { |
* If the next pattern character is '/', just strip off the |
for (;;) { |
* '/' so we do exact matching on the character that follows. |
if (*pattern == '\\') { |
*/ |
if (*++pattern == '\0') |
if (*pattern == '\\') { |
return FALSE; |
++pattern; |
} |
if (*pattern == 0) |
if (*pattern == *string) |
return(0); |
break; |
|
if (pattern[1] == '-') { |
|
if (pattern[2] == '\0') |
|
return FALSE; |
|
if (*pattern < *string && *string <= pattern[2]) |
|
break; |
|
if (pattern[2] <= *string && *string < *pattern) |
|
break; |
|
pattern += 3; |
|
} else |
|
pattern++; |
|
/* The test for ']' is done at the end so that ']' |
|
* can be used at the start of the range without '\' */ |
|
if (*pattern == '\0' || *pattern == ']') |
|
return FALSE; |
} |
} |
/* |
/* Found matching character, skip over rest of class. */ |
* There's no special character. Just make sure that the |
while (*pattern != ']') { |
* next characters of each string match. |
if (*pattern == '\\') |
*/ |
pattern++; |
if (*pattern != *string) |
/* A non-terminated character class is ok. */ |
return(0); |
if (*pattern == '\0') |
thisCharOK: ++pattern; |
break; |
++string; |
pattern++; |
|
} |
|
} |
} |
} |
|
/* '?' matches any single character, so shunt test. */ |
|
else if (*pattern != '?') { |
|
/* If the next pattern character is '\', just strip off the |
|
* '\' so we do exact matching on the character that follows. */ |
|
if (*pattern == '\\') { |
|
if (*++pattern == '\0') |
|
return FALSE; |
|
} |
|
/* There's no special character. Just make sure that |
|
* the next characters of each string match. */ |
|
if (*pattern != *string) |
|
return FALSE; |
|
} |
|
pattern++; |
|
string++; |
|
} |
|
if (*string == '\0') |
|
return TRUE; |
|
else |
|
return FALSE; |
} |
} |
|
|
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |