quake2forge/linux/glob.c
2001-12-22 04:27:19 +00:00

164 lines
3.1 KiB
C

#include <stdio.h>
#include "../linux/glob.h"
/* Like glob_match, but match PATTERN against any final segment of TEXT. */
static int glob_match_after_star(char *pattern, char *text)
{
register char *p = pattern, *t = text;
register char c, c1;
while ((c = *p++) == '?' || c == '*')
if (c == '?' && *t++ == '\0')
return 0;
if (c == '\0')
return 1;
if (c == '\\')
c1 = *p;
else
c1 = c;
while (1) {
if ((c == '[' || *t == c1) && glob_match(p - 1, t))
return 1;
if (*t++ == '\0')
return 0;
}
}
/* Return nonzero if PATTERN has any special globbing chars in it. */
static int glob_pattern_p(char *pattern)
{
register char *p = pattern;
register char c;
int open = 0;
while ((c = *p++) != '\0')
switch (c) {
case '?':
case '*':
return 1;
case '[': /* Only accept an open brace if there is a close */
open++; /* brace to match it. Bracket expressions must be */
continue; /* complete, according to Posix.2 */
case ']':
if (open)
return 1;
continue;
case '\\':
if (*p++ == '\0')
return 0;
}
return 0;
}
/* Match the pattern PATTERN against the string TEXT;
return 1 if it matches, 0 otherwise.
A match means the entire string TEXT is used up in matching.
In the pattern string, `*' matches any sequence of characters,
`?' matches any character, [SET] matches any character in the specified set,
[!SET] matches any character not in the specified set.
A set is composed of characters or ranges; a range looks like
character hyphen character (as in 0-9 or A-Z).
[0-9a-zA-Z_] is the set of characters allowed in C identifiers.
Any other character in the pattern must be matched exactly.
To suppress the special syntactic significance of any of `[]*?!-\',
and match the character exactly, precede it with a `\'.
*/
int glob_match(char *pattern, char *text)
{
register char *p = pattern, *t = text;
register char c;
while ((c = *p++) != '\0')
switch (c) {
case '?':
if (*t == '\0')
return 0;
else
++t;
break;
case '\\':
if (*p++ != *t++)
return 0;
break;
case '*':
return glob_match_after_star(p, t);
case '[':
{
register char c1 = *t++;
int invert;
if (!c1)
return (0);
invert = ((*p == '!') || (*p == '^'));
if (invert)
p++;
c = *p++;
while (1) {
register char cstart = c, cend = c;
if (c == '\\') {
cstart = *p++;
cend = cstart;
}
if (c == '\0')
return 0;
c = *p++;
if (c == '-' && *p != ']') {
cend = *p++;
if (cend == '\\')
cend = *p++;
if (cend == '\0')
return 0;
c = *p++;
}
if (c1 >= cstart && c1 <= cend)
goto match;
if (c == ']')
break;
}
if (!invert)
return 0;
break;
match:
/* Skip the rest of the [...] construct that already matched. */
while (c != ']') {
if (c == '\0')
return 0;
c = *p++;
if (c == '\0')
return 0;
else if (c == '\\')
++p;
}
if (invert)
return 0;
break;
}
default:
if (c != *t++)
return 0;
}
return *t == '\0';
}