mirror of https://github.com/postgres/postgres
This uses the function fnmatch() which is not available on all platforms (notably Windows), so import the implementation from NetBSD into src/port.REL8_5_ALPHA1_BRANCH
parent
a378555501
commit
cb10467d30
@ -0,0 +1,27 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* fnmatchstub.h |
||||
* Stubs for fnmatch() in port/fnmatch.c |
||||
* |
||||
* |
||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* $PostgreSQL: pgsql/src/include/fnmatchstub.h,v 1.1 2008/11/24 09:15:16 mha Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef FNMATCHSTUB_H |
||||
#define FNMATCHSTUB_H |
||||
|
||||
extern int fnmatch(const char *, const char *, int); |
||||
#define FNM_NOMATCH 1 /* Match failed. */ |
||||
#define FNM_NOSYS 2 /* Function not implemented. */ |
||||
#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ |
||||
#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ |
||||
#define FNM_PERIOD 0x04 /* Period must be matched by period. */ |
||||
#define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */ |
||||
#define FNM_LEADING_DIR 0x10 /* Ignore /<tail> after Imatch. */ |
||||
|
||||
|
||||
#endif |
@ -0,0 +1,198 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* fnmatch.c |
||||
* fnmatch() - wildcard matching function |
||||
* |
||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group |
||||
* |
||||
* |
||||
* IDENTIFICATION |
||||
* $PostgreSQL: pgsql/src/port/fnmatch.c,v 1.1 2008/11/24 09:15:16 mha Exp $ |
||||
* |
||||
* This file was taken from NetBSD and is used on platforms that don't |
||||
* provide fnmatch(). The NetBSD copyright terms follow. |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
/* $NetBSD: fnmatch.c,v 1.21 2005/12/24 21:11:16 perry Exp $ */ |
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1994 |
||||
* The Regents of the University of California. All rights reserved. |
||||
* |
||||
* This code is derived from software contributed to Berkeley by |
||||
* Guido van Rossum. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions |
||||
* are met: |
||||
* 1. Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright |
||||
* notice, this list of conditions and the following disclaimer in the |
||||
* documentation and/or other materials provided with the distribution. |
||||
* 3. Neither the name of the University nor the names of its contributors |
||||
* may be used to endorse or promote products derived from this software |
||||
* without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||||
* SUCH DAMAGE. |
||||
*/ |
||||
|
||||
/*
|
||||
* Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. |
||||
* Compares a filename or pathname to a pattern. |
||||
*/ |
||||
|
||||
#include "c.h" |
||||
#include "fnmatchstub.h" |
||||
|
||||
#define EOS '\0' |
||||
|
||||
static const char *rangematch (const char *, int, int); |
||||
|
||||
static inline int |
||||
foldcase(int ch, int flags) |
||||
{ |
||||
|
||||
if ((flags & FNM_CASEFOLD) != 0 && isupper(ch)) |
||||
return (tolower(ch)); |
||||
return (ch); |
||||
} |
||||
|
||||
#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags)) |
||||
|
||||
int |
||||
fnmatch(pattern, string, flags) |
||||
const char *pattern, *string; |
||||
int flags; |
||||
{ |
||||
const char *stringstart; |
||||
char c, test; |
||||
|
||||
for (stringstart = string;;) |
||||
switch (c = FOLDCASE(*pattern++, flags)) { |
||||
case EOS: |
||||
if ((flags & FNM_LEADING_DIR) && *string == '/') |
||||
return (0); |
||||
return (*string == EOS ? 0 : FNM_NOMATCH); |
||||
case '?': |
||||
if (*string == EOS) |
||||
return (FNM_NOMATCH); |
||||
if (*string == '/' && (flags & FNM_PATHNAME)) |
||||
return (FNM_NOMATCH); |
||||
if (*string == '.' && (flags & FNM_PERIOD) && |
||||
(string == stringstart || |
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/'))) |
||||
return (FNM_NOMATCH); |
||||
++string; |
||||
break; |
||||
case '*': |
||||
c = FOLDCASE(*pattern, flags); |
||||
/* Collapse multiple stars. */ |
||||
while (c == '*') |
||||
c = FOLDCASE(*++pattern, flags); |
||||
|
||||
if (*string == '.' && (flags & FNM_PERIOD) && |
||||
(string == stringstart || |
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/'))) |
||||
return (FNM_NOMATCH); |
||||
|
||||
/* Optimize for pattern with * at end or before /. */ |
||||
if (c == EOS) { |
||||
if (flags & FNM_PATHNAME) |
||||
return ((flags & FNM_LEADING_DIR) || |
||||
strchr(string, '/') == NULL ? |
||||
0 : FNM_NOMATCH); |
||||
else |
||||
return (0); |
||||
} else if (c == '/' && flags & FNM_PATHNAME) { |
||||
if ((string = strchr(string, '/')) == NULL) |
||||
return (FNM_NOMATCH); |
||||
break; |
||||
} |
||||
|
||||
/* General case, use recursion. */ |
||||
while ((test = FOLDCASE(*string, flags)) != EOS) { |
||||
if (!fnmatch(pattern, string, |
||||
flags & ~FNM_PERIOD)) |
||||
return (0); |
||||
if (test == '/' && flags & FNM_PATHNAME) |
||||
break; |
||||
++string; |
||||
} |
||||
return (FNM_NOMATCH); |
||||
case '[': |
||||
if (*string == EOS) |
||||
return (FNM_NOMATCH); |
||||
if (*string == '/' && flags & FNM_PATHNAME) |
||||
return (FNM_NOMATCH); |
||||
if ((pattern = |
||||
rangematch(pattern, FOLDCASE(*string, flags), |
||||
flags)) == NULL) |
||||
return (FNM_NOMATCH); |
||||
++string; |
||||
break; |
||||
case '\\': |
||||
if (!(flags & FNM_NOESCAPE)) { |
||||
if ((c = FOLDCASE(*pattern++, flags)) == EOS) { |
||||
c = '\\'; |
||||
--pattern; |
||||
} |
||||
} |
||||
/* FALLTHROUGH */ |
||||
default: |
||||
if (c != FOLDCASE(*string++, flags)) |
||||
return (FNM_NOMATCH); |
||||
break; |
||||
} |
||||
/* NOTREACHED */ |
||||
} |
||||
|
||||
static const char * |
||||
rangematch(pattern, test, flags) |
||||
const char *pattern; |
||||
int test, flags; |
||||
{ |
||||
int negate, ok; |
||||
char c, c2; |
||||
|
||||
/*
|
||||
* A bracket expression starting with an unquoted circumflex |
||||
* character produces unspecified results (IEEE 1003.2-1992, |
||||
* 3.13.2). This implementation treats it like '!', for |
||||
* consistency with the regular expression syntax. |
||||
* J.T. Conklin (conklin@ngai.kaleida.com) |
||||
*/ |
||||
if ((negate = (*pattern == '!' || *pattern == '^')) != 0) |
||||
++pattern; |
||||
|
||||
for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) { |
||||
if (c == '\\' && !(flags & FNM_NOESCAPE)) |
||||
c = FOLDCASE(*pattern++, flags); |
||||
if (c == EOS) |
||||
return (NULL); |
||||
if (*pattern == '-'
|
||||
&& (c2 = FOLDCASE(*(pattern+1), flags)) != EOS && |
||||
c2 != ']') { |
||||
pattern += 2; |
||||
if (c2 == '\\' && !(flags & FNM_NOESCAPE)) |
||||
c2 = FOLDCASE(*pattern++, flags); |
||||
if (c2 == EOS) |
||||
return (NULL); |
||||
if (c <= test && test <= c2) |
||||
ok = 1; |
||||
} else if (c == test) |
||||
ok = 1; |
||||
} |
||||
return (ok == negate ? NULL : pattern); |
||||
} |
Loading…
Reference in new issue