diff --git a/CMakeLists.txt b/CMakeLists.txt index 635842f25..ed106e405 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Mo INCLUDE(CheckLibraryExists) INCLUDE(CheckFunctionExists) +INCLUDE(CheckSymbolExists) INCLUDE(CheckStructHasMember) INCLUDE(AddCFlagIfSupported) INCLUDE(FindPkgConfig) @@ -507,6 +508,11 @@ ELSE () ENDIF () ENDIF() +CHECK_SYMBOL_EXISTS(regcomp_l "xlocale.h" HAVE_REGCOMP_L) +IF (HAVE_REGCOMP_L) + ADD_DEFINITIONS(-DHAVE_REGCOMP_L) +ENDIF () + CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS) IF (HAVE_FUTIMENS) ADD_DEFINITIONS(-DHAVE_FUTIMENS) diff --git a/src/config.c b/src/config.c index f4d4cb2b9..403b7090d 100644 --- a/src/config.c +++ b/src/config.c @@ -478,7 +478,7 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf iter = git__calloc(1, sizeof(all_iter)); GITERR_CHECK_ALLOC(iter); - if ((result = regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) { + if ((result = p_regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) { giterr_set_regex(&iter->regex, result); git__free(iter); return -1; @@ -512,7 +512,7 @@ int git_config_backend_foreach_match( int error = 0; if (regexp != NULL) { - if ((error = regcomp(®ex, regexp, REG_EXTENDED)) != 0) { + if ((error = p_regcomp(®ex, regexp, REG_EXTENDED)) != 0) { giterr_set_regex(®ex, error); regfree(®ex); return -1; @@ -1003,7 +1003,7 @@ int git_config_multivar_iterator_new(git_config_iterator **out, const git_config goto on_error; if (regexp != NULL) { - error = regcomp(&iter->regex, regexp, REG_EXTENDED); + error = p_regcomp(&iter->regex, regexp, REG_EXTENDED); if (error != 0) { giterr_set_regex(&iter->regex, error); error = -1; diff --git a/src/config_file.c b/src/config_file.c index e33b83738..9ff021e7e 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -570,7 +570,7 @@ static int config_set_multivar( if ((result = git_config__normalize_name(name, &key)) < 0) return result; - result = regcomp(&preg, regexp, REG_EXTENDED); + result = p_regcomp(&preg, regexp, REG_EXTENDED); if (result != 0) { giterr_set_regex(&preg, result); result = -1; @@ -657,7 +657,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con refcounted_strmap_free(map); - result = regcomp(&preg, regexp, REG_EXTENDED); + result = p_regcomp(&preg, regexp, REG_EXTENDED); if (result != 0) { giterr_set_regex(&preg, result); result = -1; @@ -1957,4 +1957,3 @@ done: git_buf_free(&reader->buffer); return result; } - diff --git a/src/diff_driver.c b/src/diff_driver.c index 14a898c4f..1a7f09a44 100644 --- a/src/diff_driver.c +++ b/src/diff_driver.c @@ -114,7 +114,7 @@ static int diff_driver_add_patterns( if (error < 0) break; - if ((error = regcomp(&pat->re, buf.ptr, regex_flags)) != 0) { + if ((error = p_regcomp(&pat->re, buf.ptr, regex_flags)) != 0) { /* * TODO: issue a warning */ @@ -210,7 +210,7 @@ static int git_diff_driver_builtin( goto done; if (ddef->words && - (error = regcomp( + (error = p_regcomp( &drv->word_pattern, ddef->words, ddef->flags | REG_EXTENDED))) { error = giterr_set_regex(&drv->word_pattern, error); @@ -314,7 +314,7 @@ static int git_diff_driver_load( goto done; if (!ce || !ce->value) /* no diff..wordregex, so just continue */; - else if (!(error = regcomp(&drv->word_pattern, ce->value, REG_EXTENDED))) + else if (!(error = p_regcomp(&drv->word_pattern, ce->value, REG_EXTENDED))) found_driver = true; else { /* TODO: warn about bad regex instead of failure */ @@ -519,4 +519,3 @@ void git_diff_find_context_clear(git_diff_find_context_payload *payload) payload->driver = NULL; } } - diff --git a/src/revparse.c b/src/revparse.c index e0ec3941d..aa7e0bd98 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -50,7 +50,7 @@ static int build_regex(regex_t *regex, const char *pattern) return GIT_EINVALIDSPEC; } - error = regcomp(regex, pattern, REG_EXTENDED); + error = p_regcomp(regex, pattern, REG_EXTENDED); if (!error) return 0; diff --git a/src/unix/posix.h b/src/unix/posix.h index 482d2c803..ad13291e8 100644 --- a/src/unix/posix.h +++ b/src/unix/posix.h @@ -80,4 +80,14 @@ GIT_INLINE(int) p_futimes(int f, const struct p_timeval t[2]) # define p_futimes futimes #endif +#ifdef HAVE_REGCOMP_L +#include +GIT_INLINE(int) p_regcomp(regex_t *preg, const char *pattern, int cflags) +{ + return regcomp_l(preg, pattern, cflags, (locale_t) 0); +} +#else +# define p_regcomp regcomp +#endif + #endif diff --git a/src/win32/posix.h b/src/win32/posix.h index 5fab267c2..73705fb2b 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -57,4 +57,7 @@ extern int p_lstat_posixly(const char *filename, struct stat *buf); extern struct tm * p_localtime_r(const time_t *timer, struct tm *result); extern struct tm * p_gmtime_r(const time_t *timer, struct tm *result); +/* Use the bundled regcomp */ +#define p_regcomp regcomp + #endif diff --git a/tests/core/posix.c b/tests/core/posix.c index 34a67bf47..4e177b1f9 100644 --- a/tests/core/posix.c +++ b/tests/core/posix.c @@ -11,6 +11,7 @@ #include "clar_libgit2.h" #include "posix.h" +#include "userdiff.h" void test_core_posix__initialize(void) { @@ -39,7 +40,7 @@ void test_core_posix__inet_pton(void) struct in_addr addr; struct in6_addr addr6; size_t i; - + struct in_addr_data { const char *p; const uint8_t n[4]; @@ -146,3 +147,27 @@ void test_core_posix__utimes(void) p_unlink("foo"); } + +void test_core_posix__p_regcomp_compile_single_byte_regexps(void) +{ + regex_t preg; + + cl_must_pass(p_regcomp(&preg, "[\xc0-\xff][\x80-\xbf]", REG_EXTENDED)); + + regfree(&preg); +} + +void test_core_posix__p_regcomp_compile_userdiff_regexps(void) +{ + regex_t preg; + size_t idx; + + for (idx = 0; idx < ARRAY_SIZE(builtin_defs); ++idx) { + git_diff_driver_definition ddef = builtin_defs[idx]; + + cl_must_pass(p_regcomp(&preg, ddef.fns, REG_EXTENDED | ddef.flags)); + cl_must_pass(p_regcomp(&preg, ddef.words, REG_EXTENDED)); + } + + regfree(&preg); +}