wildmat.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:5k
- /*
- ** Do shell-style pattern matching for ?, , [], and * characters.
- ** Might not be robust in face of malformed patterns; e.g., "foo[a-"
- ** could cause a segmentation violation. It is 8bit clean.
- **
- ** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
- ** Special thanks to Lars Mathiesen for the ABORT code. This can greatly
- ** speed up failing wildcard patterns. For example:
- ** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
- ** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
- ** text 2: -adobe-courier-bold-o-normal--12-120-75-75-p-70-iso8859-1
- ** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without
- ** the ABORT, then it takes 22310 calls to fail. Ugh.
- **
- ** bernie 613-01 91/01/04 19:34
- ** Fixed problem with terminating * not matching with (null)
- **
- ** bernie 597-00 91/01/08 11:24
- ** Fixed shell glob negate from '^' to '!'
- **
- ** bernie 597-02 91/01/21 13:43
- ** Fixed . matching * or ? on first char.
- **
- ** jseymour 91/02/05 22:56
- ** Fixed problems with ill-formed sets in pattern yielding false
- ** matches. Should now be robust in such cases (not all possibilities
- ** tested - standard disclaimer). Added stand-alone debug code.
- **
- ** jseymour 91/03/28 20:50
- ** Re-fixed problems with ill-formed sets in pattern yielding false
- ** matches - one hopes correctly this time.
- **
- ** jseymour 1998/04/04 17:45 EST
- ** Before adding this to minicom (as part of my "getsdir()" addition),
- ** I emailed a request to Rich $alz, asking if I could "GPL" it. Here
- ** is his reply:
- **
- ** Date: Mon, 30 Mar 1998 10:50:06 -0500 (EST)
- ** Message-Id: <199803301550.KAA14018@<anonymized>.com>
- ** From: Rich Salz <salzr@<anonymized>.com>
- ** To: jseymour@jimsun.LinxNet.com
- ** Subject: Re: A Little Thing Named "Wildmat"
- **
- ** Wildmat is in the public domain -- enjoy it.
- **
- ** I would rather it not get encumbered with various licenses,
- ** but since it is in the public domain you can do what you want...
- **
- ** So there you go. (I anonymized his email address as I don't know
- ** that he was particularly interested in having it "advertised".)
- */
- #include "port.h" /* from minicom: for needed for _PROTO macro only */
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
- #define ABORT -1
- _PROTO(static int Star, (char *, char *));
- _PROTO(static int DoMatch, (char *, char *));
- _PROTO(extern int wildmat, (char *, char *)); /* pattern matcher */
- static int
- Star(s, p)
- register char *s;
- register char *p;
- {
- int retval;
- while ((retval = DoMatch(s, p)) == FALSE) /* gobble up * match */
- if (*++s == ' ')
- return ABORT;
- return retval;
- }
- static int
- DoMatch(s, p) /* match string "s" to pattern "p" */
- register char *s;
- register char *p;
- {
- register int last;
- register int matched;
- register int reverse;
- char *ss;
- int escaped;
- for (; *p; s++, p++)
- { /* parse the string to end */
- if (*s == ' ')
- return *p == '*' && *++p == ' ' ? TRUE : ABORT;
- switch (*p)
- { /* parse pattern */
- case '\':
- /* Literal match with following character. */
- p++;
- /* FALLTHROUGH */
- default: /*literal match*/
- if (*s != *p)
- return FALSE;
- continue;
- case '?':
- /* Match anything. */
- continue;
- case '*':
- /* Trailing star matches everything. */
- return (*++p ? Star(s, p) : TRUE);
- case '[':
- /* [!....] means inverse character class. */
- if ((reverse = (p[1] == '!')))
- p++;
- ss = p + 1; /* set start point */
- for (last = 0400, escaped = matched = FALSE; *++p; last = *p)
- {
- if (*p == ']' && !(escaped || p == ss))
- break;
- if (escaped)
- escaped = FALSE;
- else if (*p == '\')
- {
- escaped = TRUE;
- continue;
- }
- /* This next line requires a good C compiler. */
- /* range? (in bounds) (equal) */
- if ((*p == '-') ? (*s <= *++p && *s >= last) : (*s == *p))
- matched = TRUE;
- }
- if (matched == reverse)
- return FALSE;
- continue;
- }
- }
- return *s == ' ';
- }
- /*
- * usage: wildmat(string, pattern)
- *
- * returns: non-0 on match
- */
- int
- wildmat(s, p)
- char *s;
- char *p;
- {
- if ((*p == '?' || *p == '*') && *s == '.')
- {
- return FALSE;
- }
- else
- {
- return DoMatch(s, p) == TRUE;
- }
- }
- #ifdef STAND_ALONE_TEST
- #include <stdio.h>
- /*
- * usage: wildmat <pattern> <test arg(s)>
- */
- void
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int index;
- int status = FALSE;
- for (index = 2; index < argc; ++index)
- {
- if (wildmat(argv[index], argv[1]))
- {
- if (status)
- fputs(" ", stdout);
- printf("%s", argv[index]);
- status = TRUE;
- }
- }
- printf("%sn", status ? "" : argv[1]);
- }
- #endif