pattern/wild card matching

Karl Heuer karl at ima.isc.com
Wed Feb 13 13:35:48 AEST 1991


In answer to the question:
>where I can find such for the pattern/wild card matching routines

Someone suggested looking at GNU grep; someone else mentioned the routine
re_comp() (without observing that it's BSD-specific).  But I think the
original question is about shell-style wildcard matching (aka globbing), not
RE matching.  On some systems, there's a gmatch() function in libgen.a; if you
don't have that, the enclosed source ought to be useful.

Karl W. Z. Heuer (karl at ima.isc.com or uunet!ima!karl), The Walking Lint
--------cut here--------
#include "bool.h"
/*
 * Wildcard matching routine by Karl Heuer.  Public Domain.
 *
 * Test whether string s is matched by pattern p.
 * Supports "?", "*", "[", each of which may be escaped with "\";
 * Character classes may use "!" for negation and "-" for range.
 * Not yet supported: internationalization; "\" inside brackets.
 */
bool wildmatch(char const *s, char const *p) {
    register char c;
    while ((c = *p++) != '\0') {
	if (c == '?') {
	    if (*s++ == '\0') return (NO);
	} else if (c == '[') {
	    register bool wantit = YES;
	    register bool seenit = NO;
	    if (*p == '!') {
		wantit = NO;
		++p;
	    }
	    c = *p++;
	    do {
		if (c == '\0') return (NO);
		if (*p == '-' && p[1] != '\0') {
		    if (*s >= c && *s <= p[1]) seenit = YES;
		    p += 2;
		} else {
		    if (c == *s) seenit = YES;
		}
	    } while ((c = *p++) != ']');
	    if (wantit != seenit) return (NO);
	    ++s;
	} else if (c == '*') {
	    if (*p == '\0') return (YES); /* optimize common case */
	    do {
		if (wildmatch(s, p)) return (YES);
	    } while (*s++ != '\0');
	    return (NO);
	} else if (c == '\\') {
	    if (*p == '\0' || *p++ != *s++) return (NO);
	} else {
	    if (c != *s++) return (NO);
	}
    }
    return (*s == '\0');
}



More information about the Comp.lang.c mailing list