@@ -40,20 +40,6 @@ static struct grep_opt grep_defaults = {
40
40
.output = std_output ,
41
41
};
42
42
43
- #ifdef USE_LIBPCRE2
44
- static pcre2_general_context * pcre2_global_context ;
45
-
46
- static void * pcre2_malloc (PCRE2_SIZE size , MAYBE_UNUSED void * memory_data )
47
- {
48
- return malloc (size );
49
- }
50
-
51
- static void pcre2_free (void * pointer , MAYBE_UNUSED void * memory_data )
52
- {
53
- free (pointer );
54
- }
55
- #endif
56
-
57
43
static const char * color_grep_slots [] = {
58
44
[GREP_COLOR_CONTEXT ] = "context" ,
59
45
[GREP_COLOR_FILENAME ] = "filename" ,
@@ -152,20 +138,9 @@ int grep_config(const char *var, const char *value, void *cb)
152
138
* Initialize one instance of grep_opt and copy the
153
139
* default values from the template we read the configuration
154
140
* information in an earlier call to git_config(grep_config).
155
- *
156
- * If using PCRE, make sure that the library is configured
157
- * to use the same allocator as Git (e.g. nedmalloc on Windows).
158
- *
159
- * Any allocated memory needs to be released in grep_destroy().
160
141
*/
161
142
void grep_init (struct grep_opt * opt , struct repository * repo , const char * prefix )
162
143
{
163
- #if defined(USE_LIBPCRE2 )
164
- if (!pcre2_global_context )
165
- pcre2_global_context = pcre2_general_context_create (
166
- pcre2_malloc , pcre2_free , NULL );
167
- #endif
168
-
169
144
* opt = grep_defaults ;
170
145
171
146
opt -> repo = repo ;
@@ -175,13 +150,6 @@ void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix
175
150
opt -> header_tail = & opt -> header_list ;
176
151
}
177
152
178
- void grep_destroy (void )
179
- {
180
- #ifdef USE_LIBPCRE2
181
- pcre2_general_context_free (pcre2_global_context );
182
- #endif
183
- }
184
-
185
153
static void grep_set_pattern_type_option (enum grep_pattern_type pattern_type , struct grep_opt * opt )
186
154
{
187
155
/*
@@ -363,6 +331,28 @@ static int is_fixed(const char *s, size_t len)
363
331
}
364
332
365
333
#ifdef USE_LIBPCRE2
334
+ #define GREP_PCRE2_DEBUG_MALLOC 0
335
+
336
+ static void * pcre2_malloc (PCRE2_SIZE size , MAYBE_UNUSED void * memory_data )
337
+ {
338
+ void * pointer = malloc (size );
339
+ #if GREP_PCRE2_DEBUG_MALLOC
340
+ static int count = 1 ;
341
+ fprintf (stderr , "PCRE2:%p -> #%02d: alloc(%lu)\n" , pointer , count ++ , size );
342
+ #endif
343
+ return pointer ;
344
+ }
345
+
346
+ static void pcre2_free (void * pointer , MAYBE_UNUSED void * memory_data )
347
+ {
348
+ #if GREP_PCRE2_DEBUG_MALLOC
349
+ static int count = 1 ;
350
+ if (pointer )
351
+ fprintf (stderr , "PCRE2:%p -> #%02d: free()\n" , pointer , count ++ );
352
+ #endif
353
+ free (pointer );
354
+ }
355
+
366
356
static void compile_pcre2_pattern (struct grep_pat * p , const struct grep_opt * opt )
367
357
{
368
358
int error ;
@@ -373,17 +363,20 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
373
363
int patinforet ;
374
364
size_t jitsizearg ;
375
365
376
- assert (opt -> pcre2 );
377
-
378
- p -> pcre2_compile_context = NULL ;
366
+ /*
367
+ * Call pcre2_general_context_create() before calling any
368
+ * other pcre2_*(). It sets up our malloc()/free() functions
369
+ * with which everything else is allocated.
370
+ */
371
+ p -> pcre2_general_context = pcre2_general_context_create (
372
+ pcre2_malloc , pcre2_free , NULL );
373
+ if (!p -> pcre2_general_context )
374
+ die ("Couldn't allocate PCRE2 general context" );
379
375
380
- /* pcre2_global_context is initialized in append_grep_pattern */
381
376
if (opt -> ignore_case ) {
382
377
if (!opt -> ignore_locale && has_non_ascii (p -> pattern )) {
383
- if (!pcre2_global_context )
384
- BUG ("pcre2_global_context uninitialized" );
385
- p -> pcre2_tables = pcre2_maketables (pcre2_global_context );
386
- p -> pcre2_compile_context = pcre2_compile_context_create (NULL );
378
+ p -> pcre2_tables = pcre2_maketables (p -> pcre2_general_context );
379
+ p -> pcre2_compile_context = pcre2_compile_context_create (p -> pcre2_general_context );
387
380
pcre2_set_character_tables (p -> pcre2_compile_context ,
388
381
p -> pcre2_tables );
389
382
}
@@ -393,28 +386,18 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
393
386
!(!opt -> ignore_case && (p -> fixed || p -> is_fixed )))
394
387
options |= (PCRE2_UTF | PCRE2_MATCH_INVALID_UTF );
395
388
389
+ #ifdef GIT_PCRE2_VERSION_10_36_OR_HIGHER
396
390
/* Work around https://bugs.exim.org/show_bug.cgi?id=2642 fixed in 10.36 */
397
- if (PCRE2_MATCH_INVALID_UTF && options & (PCRE2_UTF | PCRE2_CASELESS )) {
398
- struct strbuf buf ;
399
- int len ;
400
- int err ;
401
-
402
- if ((len = pcre2_config (PCRE2_CONFIG_VERSION , NULL )) < 0 )
403
- BUG ("pcre2_config(..., NULL) failed: %d" , len );
404
- strbuf_init (& buf , len + 1 );
405
- if ((err = pcre2_config (PCRE2_CONFIG_VERSION , buf .buf )) < 0 )
406
- BUG ("pcre2_config(..., buf.buf) failed: %d" , err );
407
- if (versioncmp (buf .buf , "10.36" ) < 0 )
408
- options |= PCRE2_NO_START_OPTIMIZE ;
409
- strbuf_release (& buf );
410
- }
391
+ if (PCRE2_MATCH_INVALID_UTF && options & (PCRE2_UTF | PCRE2_CASELESS ))
392
+ options |= PCRE2_NO_START_OPTIMIZE ;
393
+ #endif
411
394
412
395
p -> pcre2_pattern = pcre2_compile ((PCRE2_SPTR )p -> pattern ,
413
396
p -> patternlen , options , & error , & erroffset ,
414
397
p -> pcre2_compile_context );
415
398
416
399
if (p -> pcre2_pattern ) {
417
- p -> pcre2_match_data = pcre2_match_data_create_from_pattern (p -> pcre2_pattern , NULL );
400
+ p -> pcre2_match_data = pcre2_match_data_create_from_pattern (p -> pcre2_pattern , p -> pcre2_general_context );
418
401
if (!p -> pcre2_match_data )
419
402
die ("Couldn't allocate PCRE2 match data" );
420
403
} else {
@@ -493,7 +476,12 @@ static void free_pcre2_pattern(struct grep_pat *p)
493
476
pcre2_compile_context_free (p -> pcre2_compile_context );
494
477
pcre2_code_free (p -> pcre2_pattern );
495
478
pcre2_match_data_free (p -> pcre2_match_data );
479
+ #ifdef GIT_PCRE2_VERSION_10_34_OR_HIGHER
480
+ pcre2_maketables_free (p -> pcre2_general_context , p -> pcre2_tables );
481
+ #else
496
482
free ((void * )p -> pcre2_tables );
483
+ #endif
484
+ pcre2_general_context_free (p -> pcre2_general_context );
497
485
}
498
486
#else /* !USE_LIBPCRE2 */
499
487
static void compile_pcre2_pattern (struct grep_pat * p , const struct grep_opt * opt )
@@ -555,7 +543,6 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
555
543
#endif
556
544
if (p -> fixed || p -> is_fixed ) {
557
545
#ifdef USE_LIBPCRE2
558
- opt -> pcre2 = 1 ;
559
546
if (p -> is_fixed ) {
560
547
compile_pcre2_pattern (p , opt );
561
548
} else {
0 commit comments