From b1c9096394c9819342747f1215274af469a19483 Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Sun, 22 Nov 2020 11:22:11 +0100 Subject: [PATCH] Add bundled fnmatch from upstream ctags If we don't have `fnmatch()` (e.g. on Windows), use the bundled version from upstream ctags. --- configure.ac | 2 + ctags/Makefile.am | 15 +++- ctags/fnmatch/fnmatch.c | 190 ++++++++++++++++++++++++++++++++++++++++ ctags/fnmatch/fnmatch.h | 40 +++++++++ 4 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 ctags/fnmatch/fnmatch.c create mode 100644 ctags/fnmatch/fnmatch.h diff --git a/configure.ac b/configure.ac index 576127f9c3..557f053b36 100644 --- a/configure.ac +++ b/configure.ac @@ -52,6 +52,8 @@ AC_CHECK_FUNC([regcomp], AC_CHECK_FUNCS([memcpy isblank wcrtomb mbrtowc wcscoll]) AC_FUNC_ALLOCA]) AM_CONDITIONAL([USE_BUNDLED_REGEX], [test "xno" = "x$have_regcomp"]) +AC_CHECK_FUNC([fnmatch], [have_fnmatch=yes], [have_fnmatch=no]) +AM_CONDITIONAL([USE_BUNDLED_FNMATCH], [test "xno" = "x$have_fnmatch"]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_OFF_T diff --git a/ctags/Makefile.am b/ctags/Makefile.am index c47b352f5b..5517a6c5e2 100644 --- a/ctags/Makefile.am +++ b/ctags/Makefile.am @@ -177,6 +177,8 @@ libctags_la_SOURCES = \ main/xtag_p.h \ $(parsers) +libctags_la_LIBADD = + # build bundled GNU regex if needed if USE_BUNDLED_REGEX noinst_LTLIBRARIES += libgnu_regex.la @@ -195,6 +197,17 @@ libgnu_regex_la_CPPFLAGS = -D__USE_GNU EXTRA_DIST = \ gnu_regex/README.txt -libctags_la_LIBADD = libgnu_regex.la +libctags_la_LIBADD += libgnu_regex.la AM_CPPFLAGS += -I$(srcdir)/gnu_regex endif + +# build bundled fnmatch if needed +if USE_BUNDLED_FNMATCH +noinst_LTLIBRARIES += libfnmatch.la +libfnmatch_la_SOURCES = \ + fnmatch/fnmatch.c \ + fnmatch/fnmatch.h + +libctags_la_LIBADD += libfnmatch.la +AM_CPPFLAGS += -I$(srcdir)/fnmatch +endif diff --git a/ctags/fnmatch/fnmatch.c b/ctags/fnmatch/fnmatch.c new file mode 100644 index 0000000000..b979ad6d94 --- /dev/null +++ b/ctags/fnmatch/fnmatch.c @@ -0,0 +1,190 @@ +/* Copyright (C) 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. */ + +/* Modified slightly by Brian Berliner and + Jim Blandy for CVS use */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Some file systems are case-insensitive. If FOLD_FN_CHAR is + #defined, it maps the character C onto its "canonical" form. In a + case-insensitive system, it would map all alphanumeric characters + to lower case. Under Windows NT, / and \ are both path component + separators, so FOLD_FN_CHAR would map them both to /. */ +#ifndef FOLD_FN_CHAR +#define FOLD_FN_CHAR(c) (c) +#endif + +/* IGNORE(@ */ +/* #include */ +/* @) */ +#include +#include + +#if !defined(__GNU_LIBRARY__) \ + && !defined(STDC_HEADERS) \ + && !defined(_CRT_ERRNO_DEFINED) +extern int errno; +#endif + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +int +#if __STDC__ +fnmatch (const char *pattern, const char *string, int flags) +#else +fnmatch (pattern, string, flags) + char *pattern; + char *string; + int flags; +#endif +{ + register const char *p = pattern, *n = string; + register char c; + + if ((flags & ~__FNM_FLAGS) != 0) + { + errno = EINVAL; + return -1; + } + + while ((c = *p++) != '\0') + { + switch (c) + { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if ((flags & FNM_PATHNAME) && *n == '/') + return FNM_NOMATCH; + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + c = *p++; + if (*n != c) + return FNM_NOMATCH; + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) + if (((flags & FNM_PATHNAME) && *n == '/') || + (c == '?' && *n == '\0')) + return FNM_NOMATCH; + + if (c == '\0') + return 0; + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + for (--p; *n != '\0'; ++n) + if ((c == '[' || *n == c1) && + fnmatch(p, n, flags & ~FNM_PERIOD) == 0) + return 0; + return FNM_NOMATCH; + } + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + + if (*n == '\0') + return FNM_NOMATCH; + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + for (;;) + { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') + cstart = cend = *p++; + + if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + + if ((flags & FNM_PATHNAME) && c == '/') + /* [/] can never match. */ + return FNM_NOMATCH; + + if (c == '-' && *p != ']') + { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + c = *p++; + } + + if (*n >= cstart && *n <= cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return FNM_NOMATCH; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') + /* 1003.2d11 is unclear if this is right. %%% */ + ++p; + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (FOLD_FN_CHAR (c) != FOLD_FN_CHAR (*n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + return FNM_NOMATCH; +} diff --git a/ctags/fnmatch/fnmatch.h b/ctags/fnmatch/fnmatch.h new file mode 100644 index 0000000000..b15734721a --- /dev/null +++ b/ctags/fnmatch/fnmatch.h @@ -0,0 +1,40 @@ +/* Copyright (C) 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. */ + +#ifndef _FNMATCH_H + +#define _FNMATCH_H 1 + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#undef FNM_PATHNAME +#define FNM_PATHNAME (1 << 0)/* No wildcard can ever match `/'. */ +#undef FNM_NOESCAPE +#define FNM_NOESCAPE (1 << 1)/* Backslashes don't quote special chars. */ +#undef FNM_PERIOD +#define FNM_PERIOD (1 << 2)/* Leading `.' is matched only explicitly. */ +#undef __FNM_FLAGS +#define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD) + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#undef FNM_NOMATCH +#define FNM_NOMATCH 1 + +/* Match STRING against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +#if __STDC__ +extern int fnmatch (const char *pattern, const char *string, int flags); +#else +extern int fnmatch (); +#endif + +#endif /* fnmatch.h */