blob: 527d6c80885235aa4b08fcc0cac0440fb6ec1852 [file] [log] [blame]
/*
* Copyright 1994 Christopher Seiwald. All rights reserved.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
/*
* glob.c - match a string against a simple pattern
*
* Understands the following patterns:
*
* * any number of characters
* ? any single character
* [a-z] any single character in the range a-z
* [^a-z] any single character not in the range a-z
* \x match x
*
* External functions:
*
* glob() - match a string against a simple pattern
*
* Internal functions:
*
* globchars() - build a bitlist to check for character group match
*/
# include "jam.h"
# define CHECK_BIT( tab, bit ) ( tab[ (bit)/8 ] & (1<<( (bit)%8 )) )
# define BITLISTSIZE 16 /* bytes used for [chars] in compiled expr */
static void globchars( char * s, char * e, char * b );
/*
* glob() - match a string against a simple pattern.
*/
int glob( char * c, char * s )
{
char bitlist[ BITLISTSIZE ];
char * here;
for ( ; ; )
switch ( *c++ )
{
case '\0':
return *s ? -1 : 0;
case '?':
if ( !*s++ )
return 1;
break;
case '[':
/* Scan for matching ]. */
here = c;
do if ( !*c++ ) return 1;
while ( ( here == c ) || ( *c != ']' ) );
++c;
/* Build character class bitlist. */
globchars( here, c, bitlist );
if ( !CHECK_BIT( bitlist, *(unsigned char *)s ) )
return 1;
++s;
break;
case '*':
here = s;
while ( *s )
++s;
/* Try to match the rest of the pattern in a recursive */
/* call. If the match fails we'll back up chars, retrying. */
while ( s != here )
{
int r;
/* A fast path for the last token in a pattern. */
r = *c ? glob( c, s ) : *s ? -1 : 0;
if ( !r )
return 0;
if ( r < 0 )
return 1;
--s;
}
break;
case '\\':
/* Force literal match of next char. */
if ( !*c || ( *s++ != *c++ ) )
return 1;
break;
default:
if ( *s++ != c[ -1 ] )
return 1;
break;
}
}
/*
* globchars() - build a bitlist to check for character group match.
*/
static void globchars( char * s, char * e, char * b )
{
int neg = 0;
memset( b, '\0', BITLISTSIZE );
if ( *s == '^' )
{
++neg;
++s;
}
while ( s < e )
{
int c;
if ( ( s + 2 < e ) && ( s[1] == '-' ) )
{
for ( c = s[0]; c <= s[2]; ++c )
b[ c/8 ] |= ( 1 << ( c % 8 ) );
s += 3;
}
else
{
c = *s++;
b[ c/8 ] |= ( 1 << ( c % 8 ) );
}
}
if ( neg )
{
int i;
for ( i = 0; i < BITLISTSIZE; ++i )
b[ i ] ^= 0377;
}
/* Do not include \0 in either $[chars] or $[^chars]. */
b[0] &= 0376;
}