Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site brl-tgr.ARPA Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!ihnp4!zehntel!hplabs!hao!seismo!brl-tgr!tgr!moss@Brl-Vld.ARPA From: "Gary S. Moss (AMXBR-VLD-V)"Newsgroups: net.lang.c Subject: Re: Pattern recognition in C (wanted) Message-ID: <7453@brl-tgr.ARPA> Date: Wed, 16-Jan-85 22:02:21 EST Article-I.D.: brl-tgr.7453 Posted: Wed Jan 16 22:02:21 1985 Date-Received: Mon, 21-Jan-85 03:49:01 EST Sender: news@brl-tgr.ARPA Organization: Ballistic Research Lab Lines: 268 #!/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 #include #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 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