Pattern recognition in C (wanted)

Gary S. Moss (AMXBR-VLD-V) moss at Brl-Vld.ARPA
Thu Jan 17 13:02:21 AEST 1985


#!/bin/sh
#	Josh -
#	I wrote a boolean function which mimics UNIX shell file name
#	expansion in the attempt to match its first argument with its
#	second.  Matchtest.c is a test driver for it.
#
#
# Self-unpacking archive format.  To unbundle, sh this file.
echo 'match.c' 1>&2
cat >'match.c' <<'END OF match.c'
/*
	SCCS id:	@(#) match.c	1.3
	Last edit: 	1/16/85 at 21:18:57
	Retrieved: 	1/16/85 at 21:19:58
	SCCS archive:	/vld/moss/work/libWIND/s.match.c

	Author:		Gary S. Moss
			U. S. Army Ballistic Research Laboratory
			Aberdeen Proving Ground
			Maryland 21005-5066
			(301)278-6647 or AV-283-6647
 */
static
char	sccsTag[] = "@(#) match.c	1.3	last edit 1/16/85 at 21:18:57";
#include <stdio.h>
#include <string.h>
#include "./ascii.h"
extern void	prnt1Err();

/*	 m a t c h ( )
	if string matches pattern, return 1, else return 0
	special characters:
		*	Matches any string including the null string.
		?	Matches any single character.
		[...]	Matches any one of the characters enclosed.
		[!..]	Matchea any character NOT enclosed.
		-	May be used inside brackets to specify range
			(i.e. str[1-58] matches str1, str2, ... str5, str8)
		\	Escapes special characters.
 */
match(	 pattern,  string )
register
char	*pattern, *string;
	{
	do
		{
		switch( pattern[0] )
		{
		case '*': /* Match any string including null string.	*/
			if( pattern[1] == NUL || string[0] == NUL )
				return	1;
			while( string[0] != NUL )
				{
				if( match( &pattern[1], string ) )
					return	1;
				++string;
				}
			return	0;
		case '?': /* Match any character.			*/
			break;
		case '[': /* Match one of the characters in brackets
				unless first is a '!', then match
				any character not inside brackets.
			   */
			{ register char	*rgtBracket;
			  static int	negation;

			++pattern; /* Skip over left bracket.		*/
			/* Find matching right bracket.			*/
			if( (rgtBracket = strchr( pattern, ']' )) == NULL )
				{
				prnt1Err( "Unmatched '['." );
				return	0;
				}
			/* Check for negation operator.			*/
			if( pattern[0] == '!' )
				{
				++pattern;
				negation = 1;
				}
			else	{
				negation = 0;
				}	
			/* Traverse pattern inside brackets.		*/
			for(	;
				pattern < rgtBracket
			     &&	pattern[0] != string[0];
				++pattern
				)
				{
				if(	pattern[ 0] == '-'
				    &&	pattern[-1] != '\\'
					)
					{
					if(	pattern[-1] <= string[0]
					    &&	pattern[-1] != '['
					    &&	pattern[ 1] >= string[0]
					    &&	pattern[ 1] != ']'
					)
						break;
					}
				}
			if( pattern == rgtBracket )
				{
				if( ! negation )
					{
					return	0;
					}
				}
			else
				{
				if( negation )
					{
					return	0;
					}
				}
			pattern = rgtBracket; /* Skip to right bracket.	*/
			break;
			}
		case '\\': /* Escape special character.			*/
			++pattern;
			/* WARNING: falls through to default case.	*/
		default:  /* Compare characters.			*/
			if( pattern[0] != string[0] )
				return	0;
		}
		++pattern;
		++string;
		}
	while( pattern[0] != NUL && string[0]  != NUL );
	if( (pattern[0] == NUL || pattern[0] == '*' ) && string[0]  == NUL )
		{
		return	1;
		}
	else
		{
		return	0;
		}
	}
END OF match.c
echo 'matchtest.c' 1>&2
cat >'matchtest.c' <<'END OF matchtest.c'
/*
	SCCS id:	@(#) matchtest.c	1.2
	Last edit: 	1/16/85 at 21:19:12
	Retrieved: 	1/16/85 at 21:20:06
	SCCS archive:	/vld/moss/work/libWIND/s.matchtest.c

	Author:		Gary S. Moss
			U. S. Army Ballistic Research Laboratory
			Aberdeen Proving Ground
			Maryland 21005-5066
			(301)278-6647 or AV-283-6647
 */
#if ! defined( lint )
static
char	sccsTag[] = "@(#) matchtest.c	1.2	last edit 1/16/85 at 21:19:12";
#endif
#include <stdio.h>
extern int	match();
char	*usage[] = {
"",
"matchtest(1.2)",
"",
"Usage: matchtest [pattern string]",
"",
"If no arguments are given, the program reads words on its standard input.",
"The program writes to its standard output.",
0
};
void		prntUsage(), prnt1Err();
static char	*pattern, *string;
static char	patbuf[BUFSIZ], strbuf[BUFSIZ];
/*	m a i n ( )
 */
main( argc, argv )
char	*argv[];
	{
	if( ! parsArgv( argc, argv ) )
		{
		prntUsage();
		exit( 1 );
		}
	if( pattern != NULL )
		{
		if( match( pattern, string ) )
			{
			(void) printf( "'%s' matches '%s'.\n", pattern, string );
			exit( 0 );
			}
		else
			{
			(void) printf(	"'%s' does not match '%s'.\n",
					pattern,
					string
					);
			exit( 1 );
			}
		}
	while( scanf( "%s %s", patbuf, strbuf ) == 2 )
		{
		if( match( patbuf, strbuf ) )
			{
			(void) printf( "'%s' matches '%s'.\n", patbuf, strbuf );
			}
		else
			{
			(void) printf(	"'%s' does not match '%s'.\n",
					patbuf,
					strbuf
					);
			}
		}		
	exit( 0 );
	}


/*	p a r s A r g v ( )
 */
parsArgv( argc, argv )
register char	**argv;
	{
	register int	c;
	extern int	optind;
	extern char	*optarg;

	/* Parse options.					*/
	while( (c = getopt( argc, argv, "" )) != EOF )
		{
		switch( c )
			{
			case '?' :
				return	0;
			}
		}
	if( argc - optind != 2 )
		{
		if( argc == optind )
			{
			pattern = string = NULL;
			} 
		else 
			{
			(void) fprintf( stderr, "Arg count wrong!\n" );
			return	0;
			}
		} 
	else
		{
		pattern = argv[optind++];
		string = argv[optind++];
		}
	return	1;
	}

/*	p r n t U s a g e ( )
	Print usage message.
 */
void
prntUsage()
	{
	register char	**p = usage;
	while( *p )
		(void) fprintf( stderr, "%s\n", *p++ );
	return;
	}

END OF matchtest.c



More information about the Comp.lang.c mailing list