yquake2remaster/src/common/glob.c

239 lines
4 KiB
C
Raw Normal View History

/*
2010-10-18 07:18:23 +00:00
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Global string matching
*
* =======================================================================
2012-04-29 13:57:33 +00:00
*/
#include <stdio.h>
2010-10-18 15:17:31 +00:00
#include "header/glob.h"
2012-04-29 13:57:33 +00:00
/*
* Like glob_match, but match PATTERN against any final segment of TEXT.
2010-10-18 07:18:23 +00:00
*/
static int
glob_match_after_star ( char *pattern, char *text )
{
register char *p = pattern, *t = text;
register char c, c1;
2010-10-18 07:18:23 +00:00
while ( ( c = *p++ ) == '?' || c == '*' )
{
if ( ( c == '?' ) && ( *t++ == '\0' ) )
{
return ( 0 );
}
}
2010-10-18 07:18:23 +00:00
if ( c == '\0' )
{
return ( 1 );
}
2010-10-18 07:18:23 +00:00
if ( c == '\\' )
{
c1 = *p;
2010-10-18 07:18:23 +00:00
}
else
2010-10-18 07:18:23 +00:00
{
c1 = c;
2010-10-18 07:18:23 +00:00
}
2010-10-18 07:18:23 +00:00
while ( 1 )
{
if ( ( ( c == '[' ) || ( *t == c1 ) ) && glob_match( p - 1, t ) )
{
return ( 1 );
}
if ( *t++ == '\0' )
{
return ( 0 );
}
}
}
/* Match the pattern PATTERN against the string TEXT;
2010-10-18 07:18:23 +00:00
* 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;
2010-10-18 07:18:23 +00:00
while ( ( c = *p++ ) != '\0' )
{
switch ( c )
{
case '?':
2010-10-18 07:18:23 +00:00
if ( *t == '\0' )
{
return ( 0 );
}
else
{
++t;
}
2010-10-18 07:18:23 +00:00
break;
2010-10-18 07:18:23 +00:00
case '\\':
2010-10-18 07:18:23 +00:00
if ( *p++ != *t++ )
{
return ( 0 );
}
2010-10-18 07:18:23 +00:00
break;
2010-10-18 07:18:23 +00:00
case '*':
return ( glob_match_after_star( p, t ) );
2010-10-18 07:18:23 +00:00
case '[':
{
register char c1 = *t++;
int invert;
2010-10-18 07:18:23 +00:00
if ( !c1 )
{
return ( 0 );
}
invert = ( ( *p == '!' ) || ( *p == '^' ) );
2010-10-18 07:18:23 +00:00
if ( invert )
{
p++;
2010-10-18 07:18:23 +00:00
}
c = *p++;
2010-10-18 07:18:23 +00:00
while ( 1 )
{
register char cstart = c, cend = c;
2010-10-18 07:18:23 +00:00
if ( c == '\\' )
{
cstart = *p++;
cend = cstart;
}
2010-10-18 07:18:23 +00:00
if ( c == '\0' )
{
return ( 0 );
}
c = *p++;
2010-10-18 07:18:23 +00:00
if ( ( c == '-' ) && ( *p != ']' ) )
{
cend = *p++;
2010-10-18 07:18:23 +00:00
if ( cend == '\\' )
{
cend = *p++;
2010-10-18 07:18:23 +00:00
}
if ( cend == '\0' )
{
return ( 0 );
}
c = *p++;
}
2010-10-18 07:18:23 +00:00
if ( ( c1 >= cstart ) && ( c1 <= cend ) )
{
goto match;
2010-10-18 07:18:23 +00:00
}
if ( c == ']' )
{
break;
2010-10-18 07:18:23 +00:00
}
}
if ( !invert )
{
return ( 0 );
}
2010-10-18 07:18:23 +00:00
break;
2010-10-18 07:18:23 +00:00
match:
/* Skip the rest of the [...] construct that already matched. */
2010-10-18 07:18:23 +00:00
while ( c != ']' )
{
if ( c == '\0' )
{
return ( 0 );
}
c = *p++;
2010-10-18 07:18:23 +00:00
if ( c == '\0' )
{
return ( 0 );
}
else if ( c == '\\' )
{
++p;
2010-10-18 07:18:23 +00:00
}
}
2010-10-18 07:18:23 +00:00
if ( invert )
{
return ( 0 );
}
break;
}
2010-10-18 07:18:23 +00:00
default:
if ( c != *t++ )
{
return ( 0 );
}
}
2010-10-18 07:18:23 +00:00
}
2010-10-18 07:18:23 +00:00
return ( *t == '\0' );
}