@@ -16,6 +16,20 @@ static int grep_source_is_binary(struct grep_source *gs,
1616
1717static struct grep_opt grep_defaults ;
1818
19+ #ifdef USE_LIBPCRE2
20+ static pcre2_general_context * pcre2_global_context ;
21+
22+ static void * pcre2_malloc (PCRE2_SIZE size , MAYBE_UNUSED void * memory_data )
23+ {
24+ return malloc (size );
25+ }
26+
27+ static void pcre2_free (void * pointer , MAYBE_UNUSED void * memory_data )
28+ {
29+ return free (pointer );
30+ }
31+ #endif
32+
1933static const char * color_grep_slots [] = {
2034 [GREP_COLOR_CONTEXT ] = "context" ,
2135 [GREP_COLOR_FILENAME ] = "filename" ,
@@ -150,12 +164,28 @@ int grep_config(const char *var, const char *value, void *cb)
150164 * Initialize one instance of grep_opt and copy the
151165 * default values from the template we read the configuration
152166 * information in an earlier call to git_config(grep_config).
167+ *
168+ * If using PCRE, make sure that the library is configured
169+ * to use the same allocator as Git (e.g. nedmalloc on Windows).
170+ *
171+ * Any allocated memory needs to be released in grep_destroy().
153172 */
154173void grep_init (struct grep_opt * opt , struct repository * repo , const char * prefix )
155174{
156175 struct grep_opt * def = & grep_defaults ;
157176 int i ;
158177
178+ #if defined(USE_LIBPCRE2 )
179+ if (!pcre2_global_context )
180+ pcre2_global_context = pcre2_general_context_create (
181+ pcre2_malloc , pcre2_free , NULL );
182+ #endif
183+
184+ #ifdef USE_LIBPCRE1
185+ pcre_malloc = malloc ;
186+ pcre_free = free ;
187+ #endif
188+
159189 memset (opt , 0 , sizeof (* opt ));
160190 opt -> repo = repo ;
161191 opt -> prefix = prefix ;
@@ -178,6 +208,13 @@ void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix
178208 color_set (opt -> colors [i ], def -> colors [i ]);
179209}
180210
211+ void grep_destroy (void )
212+ {
213+ #ifdef USE_LIBPCRE2
214+ pcre2_general_context_free (pcre2_global_context );
215+ #endif
216+ }
217+
181218static void grep_set_pattern_type_option (enum grep_pattern_type pattern_type , struct grep_opt * opt )
182219{
183220 /*
@@ -461,7 +498,6 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
461498 PCRE2_UCHAR errbuf [256 ];
462499 PCRE2_SIZE erroffset ;
463500 int options = PCRE2_MULTILINE ;
464- const uint8_t * character_tables = NULL ;
465501 int jitret ;
466502 int patinforet ;
467503 size_t jitsizearg ;
@@ -470,11 +506,15 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
470506
471507 p -> pcre2_compile_context = NULL ;
472508
509+ /* pcre2_global_context is initialized in append_grep_pattern */
473510 if (opt -> ignore_case ) {
474511 if (!opt -> ignore_locale && has_non_ascii (p -> pattern )) {
475- character_tables = pcre2_maketables (NULL );
512+ if (!pcre2_global_context )
513+ BUG ("pcre2_global_context uninitialized" );
514+ p -> pcre2_tables = pcre2_maketables (pcre2_global_context );
476515 p -> pcre2_compile_context = pcre2_compile_context_create (NULL );
477- pcre2_set_character_tables (p -> pcre2_compile_context , character_tables );
516+ pcre2_set_character_tables (p -> pcre2_compile_context ,
517+ p -> pcre2_tables );
478518 }
479519 options |= PCRE2_CASELESS ;
480520 }
@@ -571,6 +611,7 @@ static void free_pcre2_pattern(struct grep_pat *p)
571611 pcre2_compile_context_free (p -> pcre2_compile_context );
572612 pcre2_code_free (p -> pcre2_pattern );
573613 pcre2_match_data_free (p -> pcre2_match_data );
614+ free ((void * )p -> pcre2_tables );
574615}
575616#else /* !USE_LIBPCRE2 */
576617static void compile_pcre2_pattern (struct grep_pat * p , const struct grep_opt * opt )
0 commit comments