/* 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 " 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 #include #include #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); }