From 14925245d3d459822bf31816551422dc3fd17155 Mon Sep 17 00:00:00 2001 From: jtc Date: Tue, 9 Nov 1993 18:22:05 +0000 Subject: [PATCH] Fixed the most major defect in fnmatch(): backslash-escape processing in bracket expressions. Still need to implement FNM_PERIOD... --- lib/libc/gen/fnmatch.3 | 10 ++++--- lib/libc/gen/fnmatch.c | 63 ++++++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/lib/libc/gen/fnmatch.3 b/lib/libc/gen/fnmatch.3 index 74cf803b3800..abb6cf24c47a 100644 --- a/lib/libc/gen/fnmatch.3 +++ b/lib/libc/gen/fnmatch.3 @@ -32,7 +32,7 @@ .\" SUCH DAMAGE. .\" .\" from: @(#)fnmatch.3 8.1 (Berkeley) 6/9/93 -.\" $Id: fnmatch.3,v 1.5 1993/11/06 00:34:46 cgd Exp $ +.\" $Id: fnmatch.3,v 1.6 1993/11/09 18:22:05 jtc Exp $ .\" .Dd June 9, 1993 .Dt FNMATCH 3 @@ -111,14 +111,16 @@ otherwise, it returns the value .Xr glob 3 , .Xr wordexp 3 , .Xr regexp 3 +.Sh STANDARDS +The +.Fn fnmatch +function is expected to conform to +.St -p1003.2-92 . .Sh HISTORY The .Fn fnmatch function first appeared in 4.4BSD. .Sh BUGS -Quotes and slashes in range patterns are not handled correctly by -this implementation. -.Pp The .Dv FNM_PERIOD flag is not implemented. diff --git a/lib/libc/gen/fnmatch.c b/lib/libc/gen/fnmatch.c index 3e9e7d597326..d8d600cdf431 100644 --- a/lib/libc/gen/fnmatch.c +++ b/lib/libc/gen/fnmatch.c @@ -36,11 +36,11 @@ #if defined(LIBC_SCCS) && !defined(lint) /* from: static char sccsid[] = "@(#)fnmatch.c 8.1 (Berkeley) 6/4/93"; */ -static char *rcsid = "$Id: fnmatch.c,v 1.6 1993/11/06 00:52:40 cgd Exp $"; +static char *rcsid = "$Id: fnmatch.c,v 1.7 1993/11/09 18:22:09 jtc Exp $"; #endif /* LIBC_SCCS and not lint */ /* - * Function fnmatch() as proposed in POSIX 1003.2 B.6 (D11.2). + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. * Compares a filename or pathname to a pattern. */ @@ -49,7 +49,7 @@ static char *rcsid = "$Id: fnmatch.c,v 1.6 1993/11/06 00:52:40 cgd Exp $"; #define EOS '\0' -static const char *rangematch __P((const char *, int)); +static const char *rangematch __P((const char *, int, int)); fnmatch(pattern, string, flags) register const char *pattern, *string; @@ -99,7 +99,7 @@ fnmatch(pattern, string, flags) if ((test = *string++) == EOS || test == '/' && flags & FNM_PATHNAME) return (FNM_NOMATCH); - if ((pattern = rangematch(pattern, test)) == NULL) + if ((pattern = rangematch(pattern, test, flags)) == NULL) return (FNM_NOMATCH); break; case '\\': @@ -108,9 +108,6 @@ fnmatch(pattern, string, flags) c = '\\'; --pattern; } - if (c != *string++) - return (FNM_NOMATCH); - break; } /* FALLTHROUGH */ default: @@ -122,30 +119,48 @@ fnmatch(pattern, string, flags) } static const char * -rangematch(pattern, test) +rangematch(pattern, test, flags) register const char *pattern; register int test; + int flags; { register char c, c2; int negate, ok; - if (negate = (*pattern == '!')) - ++pattern; - - /* - * XXX - * TO DO: quoting + /* A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). I have chosen to treat it like '!', for + * consistancy with regular expression syntax. */ - for (ok = 0; (c = *pattern++) != ']';) { - if (c == EOS) - return (NULL); /* Illegal pattern. */ - if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') { - if (c <= test && test <= c2) - ok = 1; - pattern += 2; - } - else if (c == test) - ok = 1; + if (negate = (*pattern == '!' || *pattern == '^')) { + pattern++; } + + for (ok = 0; (c = *pattern++) != ']';) { + if (c == '\\' && !(flags & FNM_NOESCAPE)) { + c = *pattern++; + } + if (c == EOS) { + return (NULL); + } + + if (*pattern == '-' + && (c2 = *(pattern+1)) != EOS && c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) { + c2 = *pattern++; + } + if (c2 == EOS) { + return (NULL); + } + + if (c <= test && test <= c2) { + ok = 1; + } + } else if (c == test) { + ok = 1; + } + } + return (ok == negate ? NULL : pattern); }