home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
prog
/
source
/
cp.lha
/
patmatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-03-03
|
7KB
|
275 lines
/* PatMatch.c - Implements AmigaDos Regular Expression Pattern Matching.
**
** This program will test whether a string is an AmigaDos regular expression
** It may be used to implement wild expressions such as:
**
** "copy #?.c to <dir>" to copy any file ending in .c
**
** The program has two entry points: CmplPat, and Match.
**
** CmplPat - takes a pattern and returns an auxilliary integer vector
** which is used by Match. The pattern is not modified in
** any way. CmplPat returns 1 if no errors were detected
** while compiling the pattern; otherwise it returns 0;
**
** Match - takes the pattern, the auxilliary vector, and the string
** to be matched. It returns 1 if the string matches the
** pattern; otherwise it returns 0;
**
** Translated from BCPL by:
** Jeff Lydiatt
** Richmond B.C. Canada
** 16 May 1986.
**
** Source: "A Compact Function for Regular Expression Pattern Matching",
** Software - Practice and Experience, September 1979.
**
** Useage:
** To test if "file.c" matches the regular expression "#?.c"
** char *Pat = "#?.c";
** char *Str = "file.c";
** WORD Aux[128];
**
** if ( CmplPat( Pat, Aux ) == 0 )
** {
** printf("Bad Wildcard Expression\n");
** exit(1);
** }
** if ( Match( Pat, Aux, Str ) == 1 )
** printf("String matches the pattern\n");
** else
** printf("String does NOT match the pattern\n");
**/
/*--- Included files ----*/
#include <stdio.h>
#include <exec/types.h>
#include <ctype.h>
#define EOS '\0'
/*--- Global Variables ---*/
static char Ch; /* The current character in Pattern */
static char *Pat; /* Pointer to the Pattern */
static int *Aux; /* Pointer to returned auxilliary vector */
static int PatP; /* Current position in Pat */
static int Patlen; /* strlen(pat) */
static BOOL Errflag; /* TRUE if error */
static int *Work; /* Pointer to Active work area */
static int Wp; /* Current position in work */
static BOOL Succflag;/* True if "str" matches "pat" */
/*----------------------------------------------------------------*/
/* The Interpreter */
/*----------------------------------------------------------------*/
static void Put(N)
int N;
{
register int *ip;
register int *to;
if ( N == 0 )
Succflag = TRUE;
else
{
for ( ip = &Work[ 1 ], to = &Work[ Wp ]; ip <= to; ip++)
if ( *ip == N )
return;
Work[ ++Wp ] = N;
}
}
int Match( Pat, Aux, Str )
char Pat[];
int Aux[];
char Str[];
{
int W[ 128 ];
int S = 0;
int I, N, Q, P, Strlength;
char K;
int strlen();
void Put();
Work = W;
Wp = 0;
Succflag = FALSE;
Strlength = strlen( Str );
Put( 1 );
if ( Aux[ 0 ] != 0 )
Put( Aux[ 0 ] );
for(;;)
{
/* First complete the closure */
for( N=1; N <= Wp; N++ )
{
P = Work[ N ];
K = Pat[ P-1 ];
Q = Aux[ P ];
switch( K )
{
case '#': Put( P + 1 );
case '%': Put( Q );
default : break;
case '(':
case '|': Put( P + 1);
if ( Q != 0 )
Put( Q );
}
}
if ( S >= Strlength )
return Succflag;
if ( Wp == 0 )
return FALSE;
Ch = Str[ S++ ];
/* Now deal with the match items */
N = Wp;
Wp = 0;
Succflag = FALSE;
for ( I = 1; I <= N; I++)
{
P = Work[ I ];
K = Pat[ P - 1 ];
switch( K )
{
case '#':
case '|':
case '%':
case '(': break;
case '\'': K = Pat[ P ];
default : if ( _toupper( Ch ) != _toupper( K ) )
break;
case '?': /* Successful match */
Put ( Aux[ P ] );
} /* End Switch */
} /* End For I */
} /* End for(;;) */
}
/*----------------------------------------------------------------*/
/* The Compiler */
/*----------------------------------------------------------------*/
static void Rch() /* Read next character from Pat */
{
if ( PatP >= Patlen )
Ch = EOS;
else
Ch = Pat[ PatP++ ];
}
static void Nextitem() /* Get next char from Pat; recognize the ' escape char */
{
if ( Ch == '\'' )
Rch();
Rch();
}
static void Setexits( List, Val )
int List;
int Val;
{
int A;
do
{
A = Aux[ List ];
Aux[ List ] = Val;
List = A;
}
while ( List != 0 );
}
static int Join( A, B )
int A, B;
{
int T = A;
if ( A == 0 )
return B;
while ( Aux[ A ] != 0 )
A = Aux[ A ];
Aux[ A ] = B;
return T;
}
static int Prim() /* Parse a Prim symbol */
{
int A = PatP;
char Op = Ch;
int Exp();
void Setexits(), Nextitem();
Nextitem();
switch( Op )
{
case EOS:
case ')':
case '|': Errflag = TRUE;
default : return A;
case '#': Setexits( Prim(), A ); return A;
case '(': A = Exp( A );
if ( Ch != ')' )
{
Errflag = TRUE;
}
Nextitem();
return A;
}
}
static int Exp( AltP ) /* Parse an expression */
int AltP;
{
int Exits = 0;
int A;
int Prim(), Exits(), Join();
void Nextitem(), Setexits();
for (;;)
{
A = Prim();
if ( Ch == '|' || Ch == ')' || Ch == EOS )
{
Exits = Join( Exits, A );
if ( Ch != '|' )
return Exits;
Aux[ AltP ] = PatP;
AltP = PatP;
Nextitem();
}
else
Setexits( A, PatP );
}
}
int CmplPat( Pattern, CmplPattern)
char Pattern[];
int CmplPattern[];
{
int i, strlen();
void Rch(), Setexits();
Pat = Pattern;
Aux = CmplPattern;
PatP = 0;
Patlen = strlen( Pat );
Errflag = FALSE;
for ( i = 0; i <= Patlen; i++ )
Aux[ i ] = 0;
Rch();
Setexits( Exp(0), 0 );
return (!Errflag);
}