summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/grep.c1
-rw-r--r--grep.c34
-rw-r--r--grep.h1
3 files changed, 35 insertions, 1 deletions
diff --git a/builtin/grep.c b/builtin/grep.c
index 560051784e..e49c20df60 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -1145,5 +1145,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
run_pager(&opt, prefix);
clear_pathspec(&pathspec);
free_grep_patterns(&opt);
+ grep_destroy();
return !hit;
}
diff --git a/grep.c b/grep.c
index db6e0d895f..296edbb56f 100644
--- a/grep.c
+++ b/grep.c
@@ -16,6 +16,20 @@ static int grep_source_is_binary(struct grep_source *gs,
static struct grep_opt grep_defaults;
+#ifdef USE_LIBPCRE2
+static pcre2_general_context *pcre2_global_context;
+
+static void *pcre2_malloc(PCRE2_SIZE size, MAYBE_UNUSED void *memory_data)
+{
+ return malloc(size);
+}
+
+static void pcre2_free(void *pointer, MAYBE_UNUSED void *memory_data)
+{
+ return free(pointer);
+}
+#endif
+
static const char *color_grep_slots[] = {
[GREP_COLOR_CONTEXT] = "context",
[GREP_COLOR_FILENAME] = "filename",
@@ -153,12 +167,20 @@ int grep_config(const char *var, const char *value, void *cb)
*
* If using PCRE, make sure that the library is configured
* to use the same allocator as Git (e.g. nedmalloc on Windows).
+ *
+ * Any allocated memory needs to be released in grep_destroy().
*/
void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix)
{
struct grep_opt *def = &grep_defaults;
int i;
+#if defined(USE_LIBPCRE2)
+ if (!pcre2_global_context)
+ pcre2_global_context = pcre2_general_context_create(
+ pcre2_malloc, pcre2_free, NULL);
+#endif
+
#ifdef USE_LIBPCRE1
pcre_malloc = malloc;
pcre_free = free;
@@ -186,6 +208,13 @@ void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix
color_set(opt->colors[i], def->colors[i]);
}
+void grep_destroy(void)
+{
+#ifdef USE_LIBPCRE2
+ pcre2_general_context_free(pcre2_global_context);
+#endif
+}
+
static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt)
{
/*
@@ -505,9 +534,12 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
p->pcre2_compile_context = NULL;
+ /* pcre2_global_context is initialized in append_grep_pattern */
if (opt->ignore_case) {
if (has_non_ascii(p->pattern)) {
- character_tables = pcre2_maketables(NULL);
+ if (!pcre2_global_context)
+ BUG("pcre2_global_context uninitialized");
+ character_tables = pcre2_maketables(pcre2_global_context);
p->pcre2_compile_context = pcre2_compile_context_create(NULL);
pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
}
diff --git a/grep.h b/grep.h
index 1875880f37..526c2db9ef 100644
--- a/grep.h
+++ b/grep.h
@@ -189,6 +189,7 @@ struct grep_opt {
void init_grep_defaults(struct repository *);
int grep_config(const char *var, const char *value, void *);
void grep_init(struct grep_opt *, struct repository *repo, const char *prefix);
+void grep_destroy(void);
void grep_commit_pattern_type(enum grep_pattern_type, struct grep_opt *opt);
void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t);