Repost: Shell-style wildcard matching
Bernd Felsche
bernie at metapro.DIALix.oz.au
Tue Jan 29 15:13:42 AEST 1991
[ Sorry to those of you who are seeing this again, but I think this got ]
[ zapped somewhere, on its way to the real world. (no flames or comment)]
Thanks mainly to Rich Salz, we now have a useful shell-style
wildcard matching routine. It took a little bashing to make it
behave the same way as the Bourne shell (and Korn shell).
This posting is without the permission of Rich, though I'm sure he
won't mind, as it fixes a few problems that have been unearthed.
Remember, UTSL.
--------------------cut here if you're brave----------------
#!/bin/sh
# manually shar'ed, so don't complain, all right?
# at the end of this shar you should seen the message
# "wildmat.c complete".
#
# Here's shar!
if test -f wildmat.c
then
echo wildmat.c exists, won\'t clobber.
exit 1
fi
echo extracting wildmat.c
sed 's/^X//' > wildmat.c << 'SHAR_EOF' &&
X/*
X** Do shell-style pattern matching for ?, \, [], and * characters.
X** Might not be robust in face of malformed patterns; e.g., "foo[a-"
X** could cause a segmentation violation. It is 8bit clean.
X**
X** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
X** Special thanks to Lars Mathiesen for the ABORT code. This can greatly
X** speed up failing wildcard patterns. For example:
X** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
X** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
X** text 2: -adobe-courier-bold-o-normal--12-120-75-75-p-70-iso8859-1
X** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without
X** the ABORT, then it takes 22310 calls to fail. Ugh.
X**
X** bernie 613-01 91/01/04 19:34
X** Fixed problem with terminating * not matching with (null)
X**
X** bernie 597-00 91/01/08 11:24
X** Fixed shell glob negate from '^' to '!'
X**
X** bernie 597-02 91/01/21 13:43
X** Fixed . matching * or ? on first char.
X*/
X
X#define TRUE 1
X#define FALSE 0
X#define ABORT -1
X
Xstatic int
XStar(s, p)
X register char *s;
X register char *p;
X{
X while (DoMatch(s, p) == FALSE) /* gobble up * match */
X if (*++s == '\0') return ABORT;
X return TRUE;
X}
X
X
Xstatic int
XDoMatch(s, p) /* match string "s" to pattern "p" */
X register char *s;
X register char *p;
X{
X register int last;
X register int matched;
X register int reverse;
X
X for ( ; *p; s++, p++) { /* parse the string to end */
X
X if (*s == '\0')
X return *p == '*' && *++p == '\0' ? TRUE : ABORT;
X
X switch (*p) { /* parse pattern */
X
X case '\\':
X /* Literal match with following character. */
X p++;
X /* FALLTHROUGH */
X
X default: /*literal match*/
X if (*s != *p)
X return FALSE;
X continue;
X
X case '?':
X /* Match anything. */
X continue;
X
X case '*':
X /* Trailing star matches everything. */
X return( *++p ? Star(s, p) : TRUE );
X
X case '[':
X /* [!....] means inverse character class. */
X if (reverse = p[1] == '!') p++;
X
X for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
X /* This next line requires a good C compiler. */
X /* range? (in bounds) (equal) */
X if ( ( *p == '-' ) ? (*s <= *++p && *s >= last ) : (*s == *p) )
X matched = TRUE;
X
X if (matched == reverse) return FALSE;
X continue;
X
X }
X }
X
X return *s == '\0';
X}
X
X
Xint wildmat(s, p)
X char *s;
X char *p;
X{
X if ( (*p == '?' || *p == '*' ) && *s == '.' ) {
X return FALSE;
X } else {
X return DoMatch(s, p) == TRUE;
X }
X}
SHAR_EOF
chmod 0644 wildmat.c ||
echo extract failed - squezze it yourself!
if test `wc -c < wildmat.c` -ne 2524
then
echo possible file size error with wildmat.c
exit 2
fi
echo "wildmat.c complete"
exit # because you shouldn't execute my signature
--
_--_|\ Bernd Felsche #include <std/disclaimer.h>
/ \ Metapro Systems, 328 Albany Highway, Victoria Park, Western Australia
\_.--._/ Fax: +61 9 472 3337 Phone: +61 9 362 9355 TZ=WST-8
v E-Mail: bernie at metapro.DIALix.oz.au | bernie at DIALix.oz.au
More information about the Alt.sources
mailing list