зеркало из https://github.com/microsoft/git.git
Merge branch 'ab/pcre-v2'
Update "perl-compatible regular expression" support to enable JIT and also allow linking with the newer PCRE v2 library. * ab/pcre-v2: grep: add support for PCRE v2 grep: un-break building with PCRE >= 8.32 without --enable-jit grep: un-break building with PCRE < 8.20 grep: un-break building with PCRE < 8.32 grep: add support for the PCRE v1 JIT API log: add -P as a synonym for --perl-regexp grep: skip pthreads overhead when using one thread grep: don't redundantly compile throwaway patterns under threading
This commit is contained in:
Коммит
ae7e4d4fed
|
@ -91,6 +91,7 @@ endif::git-rev-list[]
|
|||
Consider the limiting patterns to be fixed strings (don't interpret
|
||||
pattern as a regular expression).
|
||||
|
||||
-P::
|
||||
--perl-regexp::
|
||||
Consider the limiting patterns to be Perl-compatible regular
|
||||
expressions.
|
||||
|
|
49
Makefile
49
Makefile
|
@ -29,8 +29,23 @@ all::
|
|||
# Perl-compatible regular expressions instead of standard or extended
|
||||
# POSIX regular expressions.
|
||||
#
|
||||
# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
|
||||
# /foo/bar/include and /foo/bar/lib directories.
|
||||
# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
|
||||
# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
|
||||
# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
|
||||
# default in future releases.
|
||||
#
|
||||
# When using USE_LIBPCRE1, define NO_LIBPCRE1_JIT if the PCRE v1
|
||||
# library is compiled without --enable-jit. We will auto-detect
|
||||
# whether the version of the PCRE v1 library in use has JIT support at
|
||||
# all, but we unfortunately can't auto-detect whether JIT support
|
||||
# hasn't been compiled in in an otherwise JIT-supporting version. If
|
||||
# you have link-time errors about a missing `pcre_jit_exec` define
|
||||
# this, or recompile PCRE v1 with --enable-jit.
|
||||
#
|
||||
# Define LIBPCREDIR=/foo/bar if your PCRE header and library files are
|
||||
# in /foo/bar/include and /foo/bar/lib directories. Which version of
|
||||
# PCRE this points to determined by the USE_LIBPCRE1 and USE_LIBPCRE2
|
||||
# variables.
|
||||
#
|
||||
# Define HAVE_ALLOCA_H if you have working alloca(3) defined in that header.
|
||||
#
|
||||
|
@ -1089,13 +1104,29 @@ ifdef NO_LIBGEN_H
|
|||
COMPAT_OBJS += compat/basename.o
|
||||
endif
|
||||
|
||||
ifdef USE_LIBPCRE
|
||||
BASIC_CFLAGS += -DUSE_LIBPCRE1
|
||||
ifdef LIBPCREDIR
|
||||
BASIC_CFLAGS += -I$(LIBPCREDIR)/include
|
||||
EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
|
||||
USE_LIBPCRE1 ?= $(USE_LIBPCRE)
|
||||
|
||||
ifneq (,$(USE_LIBPCRE1))
|
||||
ifdef USE_LIBPCRE2
|
||||
$(error Only set USE_LIBPCRE1 (or its alias USE_LIBPCRE) or USE_LIBPCRE2, not both!)
|
||||
endif
|
||||
|
||||
BASIC_CFLAGS += -DUSE_LIBPCRE1
|
||||
EXTLIBS += -lpcre
|
||||
|
||||
ifdef NO_LIBPCRE1_JIT
|
||||
BASIC_CFLAGS += -DNO_LIBPCRE1_JIT
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef USE_LIBPCRE2
|
||||
BASIC_CFLAGS += -DUSE_LIBPCRE2
|
||||
EXTLIBS += -lpcre2-8
|
||||
endif
|
||||
|
||||
ifdef LIBPCREDIR
|
||||
BASIC_CFLAGS += -I$(LIBPCREDIR)/include
|
||||
EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
|
||||
endif
|
||||
|
||||
ifdef HAVE_ALLOCA_H
|
||||
|
@ -2249,7 +2280,9 @@ GIT-BUILD-OPTIONS: FORCE
|
|||
@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@+
|
||||
@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@+
|
||||
@echo NO_EXPAT=\''$(subst ','\'',$(subst ','\'',$(NO_EXPAT)))'\' >>$@+
|
||||
@echo USE_LIBPCRE1=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE)))'\' >>$@+
|
||||
@echo USE_LIBPCRE1=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE1)))'\' >>$@+
|
||||
@echo USE_LIBPCRE2=\''$(subst ','\'',$(subst ','\'',$(USE_LIBPCRE2)))'\' >>$@+
|
||||
@echo NO_LIBPCRE1_JIT=\''$(subst ','\'',$(subst ','\'',$(NO_LIBPCRE1_JIT)))'\' >>$@+
|
||||
@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@+
|
||||
@echo NO_PTHREADS=\''$(subst ','\'',$(subst ','\'',$(NO_PTHREADS)))'\' >>$@+
|
||||
@echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@+
|
||||
|
|
|
@ -224,7 +224,8 @@ static void start_threads(struct grep_opt *opt)
|
|||
int err;
|
||||
struct grep_opt *o = grep_opt_dup(opt);
|
||||
o->output = strbuf_out;
|
||||
o->debug = 0;
|
||||
if (i)
|
||||
o->debug = 0;
|
||||
compile_grep_patterns(o);
|
||||
err = pthread_create(&threads[i], NULL, run, o);
|
||||
|
||||
|
@ -1170,8 +1171,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||
if (!opt.fixed && opt.ignore_case)
|
||||
opt.regflags |= REG_ICASE;
|
||||
|
||||
compile_grep_patterns(&opt);
|
||||
|
||||
/*
|
||||
* We have to find "--" in a separate pass, because its presence
|
||||
* influences how we will parse arguments that come before it.
|
||||
|
@ -1244,12 +1243,23 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
|||
num_threads = GREP_NUM_THREADS_DEFAULT;
|
||||
else if (num_threads < 0)
|
||||
die(_("invalid number of threads specified (%d)"), num_threads);
|
||||
if (num_threads == 1)
|
||||
num_threads = 0;
|
||||
#else
|
||||
if (num_threads)
|
||||
warning(_("no threads support, ignoring --threads"));
|
||||
num_threads = 0;
|
||||
#endif
|
||||
|
||||
if (!num_threads)
|
||||
/*
|
||||
* The compiled patterns on the main path are only
|
||||
* used when not using threading. Otherwise
|
||||
* start_threads() below calls compile_grep_patterns()
|
||||
* for each thread.
|
||||
*/
|
||||
compile_grep_patterns(&opt);
|
||||
|
||||
#ifndef NO_PTHREADS
|
||||
if (num_threads) {
|
||||
if (!(opt.name_only || opt.unmatch_name_only || opt.count)
|
||||
|
|
|
@ -555,6 +555,7 @@ else
|
|||
NO_GETTEXT =
|
||||
USE_GETTEXT_SCHEME = fallthrough
|
||||
USE_LIBPCRE= YesPlease
|
||||
NO_LIBPCRE1_JIT = UnfortunatelyYes
|
||||
NO_CURL =
|
||||
USE_NED_ALLOCATOR = YesPlease
|
||||
else
|
||||
|
|
79
configure.ac
79
configure.ac
|
@ -255,21 +255,61 @@ GIT_PARSE_WITH([openssl]))
|
|||
# Perl-compatible regular expressions instead of standard or extended
|
||||
# POSIX regular expressions.
|
||||
#
|
||||
# Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
|
||||
# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
|
||||
# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
|
||||
# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
|
||||
# default in future releases.
|
||||
#
|
||||
# Define LIBPCREDIR=/foo/bar if your PCRE header and library files are in
|
||||
# /foo/bar/include and /foo/bar/lib directories.
|
||||
#
|
||||
AC_ARG_WITH(libpcre,
|
||||
AS_HELP_STRING([--with-libpcre],[support Perl-compatible regexes (default is NO)])
|
||||
AS_HELP_STRING([], [ARG can be also prefix for libpcre library and headers]),
|
||||
AS_HELP_STRING([--with-libpcre],[synonym for --with-libpcre1]),
|
||||
if test "$withval" = "no"; then
|
||||
USE_LIBPCRE=
|
||||
USE_LIBPCRE1=
|
||||
elif test "$withval" = "yes"; then
|
||||
USE_LIBPCRE=YesPlease
|
||||
USE_LIBPCRE1=YesPlease
|
||||
else
|
||||
USE_LIBPCRE=YesPlease
|
||||
USE_LIBPCRE1=YesPlease
|
||||
LIBPCREDIR=$withval
|
||||
AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
|
||||
dnl USE_LIBPCRE can still be modified below, so don't substitute
|
||||
dnl USE_LIBPCRE1 can still be modified below, so don't substitute
|
||||
dnl it yet.
|
||||
GIT_CONF_SUBST([LIBPCREDIR])
|
||||
fi)
|
||||
|
||||
AC_ARG_WITH(libpcre1,
|
||||
AS_HELP_STRING([--with-libpcre1],[support Perl-compatible regexes via libpcre1 (default is NO)])
|
||||
AS_HELP_STRING([], [ARG can be also prefix for libpcre library and headers]),
|
||||
if test "$withval" = "no"; then
|
||||
USE_LIBPCRE1=
|
||||
elif test "$withval" = "yes"; then
|
||||
USE_LIBPCRE1=YesPlease
|
||||
else
|
||||
USE_LIBPCRE1=YesPlease
|
||||
LIBPCREDIR=$withval
|
||||
AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
|
||||
dnl USE_LIBPCRE1 can still be modified below, so don't substitute
|
||||
dnl it yet.
|
||||
GIT_CONF_SUBST([LIBPCREDIR])
|
||||
fi)
|
||||
|
||||
AC_ARG_WITH(libpcre2,
|
||||
AS_HELP_STRING([--with-libpcre2],[support Perl-compatible regexes via libpcre2 (default is NO)])
|
||||
AS_HELP_STRING([], [ARG can be also prefix for libpcre library and headers]),
|
||||
if test -n "$USE_LIBPCRE1"; then
|
||||
AC_MSG_ERROR([Only supply one of --with-libpcre1 or --with-libpcre2!])
|
||||
fi
|
||||
|
||||
if test "$withval" = "no"; then
|
||||
USE_LIBPCRE2=
|
||||
elif test "$withval" = "yes"; then
|
||||
USE_LIBPCRE2=YesPlease
|
||||
else
|
||||
USE_LIBPCRE2=YesPlease
|
||||
LIBPCREDIR=$withval
|
||||
AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
|
||||
dnl USE_LIBPCRE2 can still be modified below, so don't substitute
|
||||
dnl it yet.
|
||||
GIT_CONF_SUBST([LIBPCREDIR])
|
||||
fi)
|
||||
|
@ -501,13 +541,11 @@ GIT_CONF_SUBST([NEEDS_SSL_WITH_CRYPTO])
|
|||
GIT_CONF_SUBST([NO_OPENSSL])
|
||||
|
||||
#
|
||||
# Define USE_LIBPCRE if you have and want to use libpcre. Various
|
||||
# commands such as log and grep offer runtime options to use
|
||||
# Perl-compatible regular expressions instead of standard or extended
|
||||
# POSIX regular expressions.
|
||||
# Handle the USE_LIBPCRE1 and USE_LIBPCRE2 options potentially set
|
||||
# above.
|
||||
#
|
||||
|
||||
if test -n "$USE_LIBPCRE"; then
|
||||
if test -n "$USE_LIBPCRE1"; then
|
||||
|
||||
GIT_STASH_FLAGS($LIBPCREDIR)
|
||||
|
||||
|
@ -517,7 +555,22 @@ AC_CHECK_LIB([pcre], [pcre_version],
|
|||
|
||||
GIT_UNSTASH_FLAGS($LIBPCREDIR)
|
||||
|
||||
GIT_CONF_SUBST([USE_LIBPCRE])
|
||||
GIT_CONF_SUBST([USE_LIBPCRE1])
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if test -n "$USE_LIBPCRE2"; then
|
||||
|
||||
GIT_STASH_FLAGS($LIBPCREDIR)
|
||||
|
||||
AC_CHECK_LIB([pcre2-8], [pcre2_config_8],
|
||||
[USE_LIBPCRE2=YesPlease],
|
||||
[USE_LIBPCRE2=])
|
||||
|
||||
GIT_UNSTASH_FLAGS($LIBPCREDIR)
|
||||
|
||||
GIT_CONF_SUBST([USE_LIBPCRE2])
|
||||
|
||||
fi
|
||||
|
||||
|
|
185
grep.c
185
grep.c
|
@ -179,22 +179,37 @@ static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, st
|
|||
case GREP_PATTERN_TYPE_BRE:
|
||||
opt->fixed = 0;
|
||||
opt->pcre1 = 0;
|
||||
opt->pcre2 = 0;
|
||||
break;
|
||||
|
||||
case GREP_PATTERN_TYPE_ERE:
|
||||
opt->fixed = 0;
|
||||
opt->pcre1 = 0;
|
||||
opt->pcre2 = 0;
|
||||
opt->regflags |= REG_EXTENDED;
|
||||
break;
|
||||
|
||||
case GREP_PATTERN_TYPE_FIXED:
|
||||
opt->fixed = 1;
|
||||
opt->pcre1 = 0;
|
||||
opt->pcre2 = 0;
|
||||
break;
|
||||
|
||||
case GREP_PATTERN_TYPE_PCRE:
|
||||
opt->fixed = 0;
|
||||
#ifdef USE_LIBPCRE2
|
||||
opt->pcre1 = 0;
|
||||
opt->pcre2 = 1;
|
||||
#else
|
||||
/*
|
||||
* It's important that pcre1 always be assigned to
|
||||
* even when there's no USE_LIBPCRE* defined. We still
|
||||
* call the PCRE stub function, it just dies with
|
||||
* "cannot use Perl-compatible regexes[...]".
|
||||
*/
|
||||
opt->pcre1 = 1;
|
||||
opt->pcre2 = 0;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -365,9 +380,22 @@ static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
|
|||
if (!p->pcre1_regexp)
|
||||
compile_regexp_failed(p, error);
|
||||
|
||||
p->pcre1_extra_info = pcre_study(p->pcre1_regexp, 0, &error);
|
||||
p->pcre1_extra_info = pcre_study(p->pcre1_regexp, PCRE_STUDY_JIT_COMPILE, &error);
|
||||
if (!p->pcre1_extra_info && error)
|
||||
die("%s", error);
|
||||
|
||||
#ifdef GIT_PCRE1_USE_JIT
|
||||
pcre_config(PCRE_CONFIG_JIT, &p->pcre1_jit_on);
|
||||
if (p->pcre1_jit_on == 1) {
|
||||
p->pcre1_jit_stack = pcre_jit_stack_alloc(1, 1024 * 1024);
|
||||
if (!p->pcre1_jit_stack)
|
||||
die("Couldn't allocate PCRE JIT stack");
|
||||
pcre_assign_jit_stack(p->pcre1_extra_info, NULL, p->pcre1_jit_stack);
|
||||
} else if (p->pcre1_jit_on != 0) {
|
||||
die("BUG: The pcre1_jit_on variable should be 0 or 1, not %d",
|
||||
p->pcre1_jit_on);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
|
||||
|
@ -378,8 +406,19 @@ static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
|
|||
if (eflags & REG_NOTBOL)
|
||||
flags |= PCRE_NOTBOL;
|
||||
|
||||
ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line, eol - line,
|
||||
0, flags, ovector, ARRAY_SIZE(ovector));
|
||||
#ifdef GIT_PCRE1_USE_JIT
|
||||
if (p->pcre1_jit_on) {
|
||||
ret = pcre_jit_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
|
||||
eol - line, 0, flags, ovector,
|
||||
ARRAY_SIZE(ovector), p->pcre1_jit_stack);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
|
||||
eol - line, 0, flags, ovector,
|
||||
ARRAY_SIZE(ovector));
|
||||
}
|
||||
|
||||
if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
|
||||
die("pcre_exec failed with error code %d", ret);
|
||||
if (ret > 0) {
|
||||
|
@ -394,7 +433,15 @@ static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
|
|||
static void free_pcre1_regexp(struct grep_pat *p)
|
||||
{
|
||||
pcre_free(p->pcre1_regexp);
|
||||
pcre_free(p->pcre1_extra_info);
|
||||
#ifdef GIT_PCRE1_USE_JIT
|
||||
if (p->pcre1_jit_on) {
|
||||
pcre_free_study(p->pcre1_extra_info);
|
||||
pcre_jit_stack_free(p->pcre1_jit_stack);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
pcre_free(p->pcre1_extra_info);
|
||||
}
|
||||
pcre_free((void *)p->pcre1_tables);
|
||||
}
|
||||
#else /* !USE_LIBPCRE1 */
|
||||
|
@ -414,6 +461,127 @@ static void free_pcre1_regexp(struct grep_pat *p)
|
|||
}
|
||||
#endif /* !USE_LIBPCRE1 */
|
||||
|
||||
#ifdef USE_LIBPCRE2
|
||||
static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
|
||||
{
|
||||
int error;
|
||||
PCRE2_UCHAR errbuf[256];
|
||||
PCRE2_SIZE erroffset;
|
||||
int options = PCRE2_MULTILINE;
|
||||
const uint8_t *character_tables = NULL;
|
||||
int jitret;
|
||||
|
||||
assert(opt->pcre2);
|
||||
|
||||
p->pcre2_compile_context = NULL;
|
||||
|
||||
if (opt->ignore_case) {
|
||||
if (has_non_ascii(p->pattern)) {
|
||||
character_tables = pcre2_maketables(NULL);
|
||||
p->pcre2_compile_context = pcre2_compile_context_create(NULL);
|
||||
pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
|
||||
}
|
||||
options |= PCRE2_CASELESS;
|
||||
}
|
||||
if (is_utf8_locale() && has_non_ascii(p->pattern))
|
||||
options |= PCRE2_UTF;
|
||||
|
||||
p->pcre2_pattern = pcre2_compile((PCRE2_SPTR)p->pattern,
|
||||
p->patternlen, options, &error, &erroffset,
|
||||
p->pcre2_compile_context);
|
||||
|
||||
if (p->pcre2_pattern) {
|
||||
p->pcre2_match_data = pcre2_match_data_create_from_pattern(p->pcre2_pattern, NULL);
|
||||
if (!p->pcre2_match_data)
|
||||
die("Couldn't allocate PCRE2 match data");
|
||||
} else {
|
||||
pcre2_get_error_message(error, errbuf, sizeof(errbuf));
|
||||
compile_regexp_failed(p, (const char *)&errbuf);
|
||||
}
|
||||
|
||||
pcre2_config(PCRE2_CONFIG_JIT, &p->pcre2_jit_on);
|
||||
if (p->pcre2_jit_on == 1) {
|
||||
jitret = pcre2_jit_compile(p->pcre2_pattern, PCRE2_JIT_COMPLETE);
|
||||
if (jitret)
|
||||
die("Couldn't JIT the PCRE2 pattern '%s', got '%d'\n", p->pattern, jitret);
|
||||
p->pcre2_jit_stack = pcre2_jit_stack_create(1, 1024 * 1024, NULL);
|
||||
if (!p->pcre2_jit_stack)
|
||||
die("Couldn't allocate PCRE2 JIT stack");
|
||||
p->pcre2_match_context = pcre2_match_context_create(NULL);
|
||||
if (!p->pcre2_jit_stack)
|
||||
die("Couldn't allocate PCRE2 match context");
|
||||
pcre2_jit_stack_assign(p->pcre2_match_context, NULL, p->pcre2_jit_stack);
|
||||
} else if (p->pcre2_jit_on != 0) {
|
||||
die("BUG: The pcre2_jit_on variable should be 0 or 1, not %d",
|
||||
p->pcre1_jit_on);
|
||||
}
|
||||
}
|
||||
|
||||
static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
|
||||
regmatch_t *match, int eflags)
|
||||
{
|
||||
int ret, flags = 0;
|
||||
PCRE2_SIZE *ovector;
|
||||
PCRE2_UCHAR errbuf[256];
|
||||
|
||||
if (eflags & REG_NOTBOL)
|
||||
flags |= PCRE2_NOTBOL;
|
||||
|
||||
if (p->pcre2_jit_on)
|
||||
ret = pcre2_jit_match(p->pcre2_pattern, (unsigned char *)line,
|
||||
eol - line, 0, flags, p->pcre2_match_data,
|
||||
NULL);
|
||||
else
|
||||
ret = pcre2_match(p->pcre2_pattern, (unsigned char *)line,
|
||||
eol - line, 0, flags, p->pcre2_match_data,
|
||||
NULL);
|
||||
|
||||
if (ret < 0 && ret != PCRE2_ERROR_NOMATCH) {
|
||||
pcre2_get_error_message(ret, errbuf, sizeof(errbuf));
|
||||
die("%s failed with error code %d: %s",
|
||||
(p->pcre2_jit_on ? "pcre2_jit_match" : "pcre2_match"), ret,
|
||||
errbuf);
|
||||
}
|
||||
if (ret > 0) {
|
||||
ovector = pcre2_get_ovector_pointer(p->pcre2_match_data);
|
||||
ret = 0;
|
||||
match->rm_so = (int)ovector[0];
|
||||
match->rm_eo = (int)ovector[1];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void free_pcre2_pattern(struct grep_pat *p)
|
||||
{
|
||||
pcre2_compile_context_free(p->pcre2_compile_context);
|
||||
pcre2_code_free(p->pcre2_pattern);
|
||||
pcre2_match_data_free(p->pcre2_match_data);
|
||||
pcre2_jit_stack_free(p->pcre2_jit_stack);
|
||||
pcre2_match_context_free(p->pcre2_match_context);
|
||||
}
|
||||
#else /* !USE_LIBPCRE2 */
|
||||
static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
|
||||
{
|
||||
/*
|
||||
* Unreachable until USE_LIBPCRE2 becomes synonymous with
|
||||
* USE_LIBPCRE. See the sibling comment in
|
||||
* grep_set_pattern_type_option().
|
||||
*/
|
||||
die("cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE");
|
||||
}
|
||||
|
||||
static int pcre2match(struct grep_pat *p, const char *line, const char *eol,
|
||||
regmatch_t *match, int eflags)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void free_pcre2_pattern(struct grep_pat *p)
|
||||
{
|
||||
}
|
||||
#endif /* !USE_LIBPCRE2 */
|
||||
|
||||
static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
@ -479,6 +647,11 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
|
|||
return;
|
||||
}
|
||||
|
||||
if (opt->pcre2) {
|
||||
compile_pcre2_pattern(p, opt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt->pcre1) {
|
||||
compile_pcre1_regexp(p, opt);
|
||||
return;
|
||||
|
@ -838,6 +1011,8 @@ void free_grep_patterns(struct grep_opt *opt)
|
|||
kwsfree(p->kws);
|
||||
else if (p->pcre1_regexp)
|
||||
free_pcre1_regexp(p);
|
||||
else if (p->pcre2_pattern)
|
||||
free_pcre2_pattern(p);
|
||||
else
|
||||
regfree(&p->regexp);
|
||||
free(p->pattern);
|
||||
|
@ -918,6 +1093,8 @@ static int patmatch(struct grep_pat *p, char *line, char *eol,
|
|||
hit = !fixmatch(p, line, eol, match);
|
||||
else if (p->pcre1_regexp)
|
||||
hit = !pcre1match(p, line, eol, match, eflags);
|
||||
else if (p->pcre2_pattern)
|
||||
hit = !pcre2match(p, line, eol, match, eflags);
|
||||
else
|
||||
hit = !regexec_buf(&p->regexp, line, eol - line, 1, match,
|
||||
eflags);
|
||||
|
|
33
grep.h
33
grep.h
|
@ -3,9 +3,33 @@
|
|||
#include "color.h"
|
||||
#ifdef USE_LIBPCRE1
|
||||
#include <pcre.h>
|
||||
#ifdef PCRE_CONFIG_JIT
|
||||
#if PCRE_MAJOR >= 8 && PCRE_MINOR >= 32
|
||||
#ifndef NO_LIBPCRE1_JIT
|
||||
#define GIT_PCRE1_USE_JIT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifndef PCRE_STUDY_JIT_COMPILE
|
||||
#define PCRE_STUDY_JIT_COMPILE 0
|
||||
#endif
|
||||
#if PCRE_MAJOR <= 8 && PCRE_MINOR < 20
|
||||
typedef int pcre_jit_stack;
|
||||
#endif
|
||||
#else
|
||||
typedef int pcre;
|
||||
typedef int pcre_extra;
|
||||
typedef int pcre_jit_stack;
|
||||
#endif
|
||||
#ifdef USE_LIBPCRE2
|
||||
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
#include <pcre2.h>
|
||||
#else
|
||||
typedef int pcre2_code;
|
||||
typedef int pcre2_match_data;
|
||||
typedef int pcre2_compile_context;
|
||||
typedef int pcre2_match_context;
|
||||
typedef int pcre2_jit_stack;
|
||||
#endif
|
||||
#include "kwset.h"
|
||||
#include "thread-utils.h"
|
||||
|
@ -48,7 +72,15 @@ struct grep_pat {
|
|||
regex_t regexp;
|
||||
pcre *pcre1_regexp;
|
||||
pcre_extra *pcre1_extra_info;
|
||||
pcre_jit_stack *pcre1_jit_stack;
|
||||
const unsigned char *pcre1_tables;
|
||||
int pcre1_jit_on;
|
||||
pcre2_code *pcre2_pattern;
|
||||
pcre2_match_data *pcre2_match_data;
|
||||
pcre2_compile_context *pcre2_compile_context;
|
||||
pcre2_match_context *pcre2_match_context;
|
||||
pcre2_jit_stack *pcre2_jit_stack;
|
||||
uint32_t pcre2_jit_on;
|
||||
kwset_t kws;
|
||||
unsigned fixed:1;
|
||||
unsigned ignore_case:1;
|
||||
|
@ -112,6 +144,7 @@ struct grep_opt {
|
|||
int extended;
|
||||
int use_reflog_filter;
|
||||
int pcre1;
|
||||
int pcre2;
|
||||
int relative;
|
||||
int pathname;
|
||||
int null_following_name;
|
||||
|
|
|
@ -2031,7 +2031,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
|
|||
DIFF_OPT_SET(&revs->diffopt, PICKAXE_IGNORE_CASE);
|
||||
} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
|
||||
revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_FIXED;
|
||||
} else if (!strcmp(arg, "--perl-regexp")) {
|
||||
} else if (!strcmp(arg, "--perl-regexp") || !strcmp(arg, "-P")) {
|
||||
revs->grep_filter.pattern_type_option = GREP_PATTERN_TYPE_PCRE;
|
||||
} else if (!strcmp(arg, "--all-match")) {
|
||||
revs->grep_filter.all_match = 1;
|
||||
|
|
|
@ -404,8 +404,20 @@ test_expect_success 'log with various grep.patternType configurations & command-
|
|||
--grep="(1|2)" >actual.fixed.short-arg &&
|
||||
git log --pretty=tformat:%s -E \
|
||||
--grep="\|2" >actual.extended.short-arg &&
|
||||
if test_have_prereq PCRE
|
||||
then
|
||||
git log --pretty=tformat:%s -P \
|
||||
--grep="[\d]\|" >actual.perl.short-arg
|
||||
else
|
||||
test_must_fail git log -P \
|
||||
--grep="[\d]\|"
|
||||
fi &&
|
||||
test_cmp expect.fixed actual.fixed.short-arg &&
|
||||
test_cmp expect.extended actual.extended.short-arg &&
|
||||
if test_have_prereq PCRE
|
||||
then
|
||||
test_cmp expect.perl actual.perl.short-arg
|
||||
fi &&
|
||||
|
||||
git log --pretty=tformat:%s --fixed-strings \
|
||||
--grep="(1|2)" >actual.fixed.long-arg &&
|
||||
|
|
|
@ -1020,7 +1020,7 @@ esac
|
|||
test -z "$NO_PERL" && test_set_prereq PERL
|
||||
test -z "$NO_PTHREADS" && test_set_prereq PTHREADS
|
||||
test -z "$NO_PYTHON" && test_set_prereq PYTHON
|
||||
test -n "$USE_LIBPCRE1" && test_set_prereq PCRE
|
||||
test -n "$USE_LIBPCRE1$USE_LIBPCRE2" && test_set_prereq PCRE
|
||||
test -z "$NO_GETTEXT" && test_set_prereq GETTEXT
|
||||
|
||||
# Can we rely on git's output in the C locale?
|
||||
|
|
Загрузка…
Ссылка в новой задаче