diff options
| author | Edward Thomson <ethomson@edwardthomson.com> | 2019-05-21 14:59:55 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-05-21 14:59:55 +0200 |
| commit | 3d9e82fdd5619985b56ca25fb1f89de3dfabc029 (patch) | |
| tree | 689c3f2a148574fdaeb48f8d04648707c61230ed /src | |
| parent | 954f5357282233ecdfea226c819f3f3884949cdb (diff) | |
| parent | afb04a95af939295d9baebac5bea72c070001d9e (diff) | |
| download | libgit2-3d9e82fdd5619985b56ca25fb1f89de3dfabc029.tar.gz | |
Merge pull request #4935 from libgit2/ethomson/pcre
Use PCRE for our fallback regex engine when regcomp_l is unavailable
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 67 | ||||
| -rw-r--r-- | src/common.h | 79 | ||||
| -rw-r--r-- | src/config.c | 28 | ||||
| -rw-r--r-- | src/config_file.c | 21 | ||||
| -rw-r--r-- | src/diff_driver.c | 33 | ||||
| -rw-r--r-- | src/errors.c | 6 | ||||
| -rw-r--r-- | src/errors.h | 88 | ||||
| -rw-r--r-- | src/features.h.in | 7 | ||||
| -rw-r--r-- | src/posix_regex.h | 73 | ||||
| -rw-r--r-- | src/revparse.c | 28 | ||||
| -rw-r--r-- | src/unix/posix.h | 10 | ||||
| -rw-r--r-- | src/userdiff.h | 2 | ||||
| -rw-r--r-- | src/win32/path_w32.h | 29 | ||||
| -rw-r--r-- | src/win32/posix.h | 3 | ||||
| -rw-r--r-- | src/win32/precompiled.h | 2 | ||||
| -rw-r--r-- | src/win32/w32_common.h | 39 |
16 files changed, 322 insertions, 193 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 00021b828..bf51c45bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,23 +48,6 @@ IF (ENABLE_TRACE STREQUAL "ON") ENDIF() ADD_FEATURE_INFO(tracing GIT_TRACE "tracing support") -# Use `regcomp_l` if available -CHECK_SYMBOL_EXISTS(regcomp_l "regex.h;xlocale.h" HAVE_REGCOMP_L) -IF (HAVE_REGCOMP_L) - SET(GIT_USE_REGCOMP_L 1) -ENDIF () - -# Otherwise, we either want to use system's `regcomp` or our -# bundled regcomp code, if system doesn't provide `regcomp`. -IF(NOT HAVE_REGCOMP_L) - CHECK_FUNCTION_EXISTS(regcomp HAVE_REGCOMP) - IF(NOT HAVE_REGCOMP) - ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/regex" "${libgit2_BINARY_DIR}/deps/regex") - LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/regex") - LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:regex>) - ENDIF() -ENDIF() - CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS) IF (HAVE_FUTIMENS) SET(GIT_USE_FUTIMENS 1) @@ -306,6 +289,56 @@ ELSE() MESSAGE(FATAL_ERROR "Asked for unknown SHA1 backend ${SHA1_BACKEND}") ENDIF() +# Specify regular expression implementation +FIND_PACKAGE(PCRE) + +IF(REGEX_BACKEND STREQUAL "") + CHECK_SYMBOL_EXISTS(regcomp_l "regex.h;xlocale.h" HAVE_REGCOMP_L) + + IF(HAVE_REGCOMP_L) + SET(REGEX_BACKEND "regcomp_l") + ELSEIF(PCRE_FOUND) + SET(REGEX_BACKEND "pcre") + ELSE() + SET(REGEX_BACKEND "builtin") + ENDIF() +ENDIF() + +IF(REGEX_BACKEND STREQUAL "regcomp_l") + ADD_FEATURE_INFO(regex ON "using system regcomp_l") + SET(GIT_REGEX_REGCOMP_L 1) +ELSEIF(REGEX_BACKEND STREQUAL "pcre2") + FIND_PACKAGE(PCRE2) + + IF(NOT PCRE2_FOUND) + MESSAGE(FATAL_ERROR "PCRE2 support was requested but not found") + ENDIF() + + ADD_FEATURE_INFO(regex ON "using system PCRE2") + SET(GIT_REGEX_PCRE2 1) + + LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${PCRE2_INCLUDE_DIRS}) + LIST(APPEND LIBGIT2_LIBS ${PCRE2_LIBRARIES}) +ELSEIF(REGEX_BACKEND STREQUAL "pcre") + ADD_FEATURE_INFO(regex ON "using system PCRE") + SET(GIT_REGEX_PCRE 1) + + LIST(APPEND LIBGIT2_SYSTEM_INCLUDES ${PCRE_INCLUDE_DIRS}) + LIST(APPEND LIBGIT2_LIBS ${PCRE_LIBRARIES}) +ELSEIF(REGEX_BACKEND STREQUAL "regcomp") + ADD_FEATURE_INFO(regex ON "using system regcomp") + SET(GIT_REGEX_REGCOMP 1) +ELSEIF(REGEX_BACKEND STREQUAL "builtin") + ADD_FEATURE_INFO(regex ON "using bundled PCRE") + SET(GIT_REGEX_BUILTIN 1) + + ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/pcre" "${libgit2_BINARY_DIR}/deps/pcre") + LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/pcre") + LIST(APPEND LIBGIT2_OBJECTS $<TARGET_OBJECTS:pcre>) +ELSE() + MESSAGE(FATAL_ERROR "The REGEX_BACKEND option provided is not supported") +ENDIF() + # Optional external dependency: http-parser FIND_PACKAGE(HTTP_Parser) IF (USE_EXT_HTTP_PARSER AND HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2) diff --git a/src/common.h b/src/common.h index 18ba72dd1..8a5761abc 100644 --- a/src/common.h +++ b/src/common.h @@ -47,6 +47,7 @@ # include <ws2tcpip.h> # include "win32/msvc-compat.h" # include "win32/mingw-compat.h" +# include "win32/w32_common.h" # include "win32/win32-compat.h" # include "win32/error.h" # include "win32/version.h" @@ -76,6 +77,7 @@ #include "git2/types.h" #include "git2/errors.h" +#include "errors.h" #include "thread-utils.h" #include "integer.h" @@ -85,7 +87,8 @@ */ #include "git2/deprecated.h" -#include <regex.h> +#include "posix.h" +#include "posix_regex.h" #define DEFAULT_BUFSIZE 65536 #define FILEIO_BUFSIZE DEFAULT_BUFSIZE @@ -109,80 +112,6 @@ do { int _err = (code); if (_err) return _err; } while (0) /** - * Set the error message for this thread, formatting as needed. - */ - -void git_error_set(int error_class, const char *string, ...) GIT_FORMAT_PRINTF(2, 3); - -/** - * Set the error message for a regex failure, using the internal regex - * error code lookup and return a libgit error code. - */ -int git_error_set_regex(const regex_t *regex, int error_code); - -/** - * Set error message for user callback if needed. - * - * If the error code in non-zero and no error message is set, this - * sets a generic error message. - * - * @return This always returns the `error_code` parameter. - */ -GIT_INLINE(int) git_error_set_after_callback_function( - int error_code, const char *action) -{ - if (error_code) { - const git_error *e = git_error_last(); - if (!e || !e->message) - git_error_set(e ? e->klass : GIT_ERROR_CALLBACK, - "%s callback returned %d", action, error_code); - } - return error_code; -} - -#ifdef GIT_WIN32 -#define git_error_set_after_callback(code) \ - git_error_set_after_callback_function((code), __FUNCTION__) -#else -#define git_error_set_after_callback(code) \ - git_error_set_after_callback_function((code), __func__) -#endif - -/** - * Gets the system error code for this thread. - */ -int git_error_system_last(void); - -/** - * Sets the system error code for this thread. - */ -void git_error_system_set(int code); - -/** - * Structure to preserve libgit2 error state - */ -typedef struct { - int error_code; - unsigned int oom : 1; - git_error error_msg; -} git_error_state; - -/** - * Capture current error state to restore later, returning error code. - * If `error_code` is zero, this does not clear the current error state. - * You must either restore this error state, or free it. - */ -extern int git_error_state_capture(git_error_state *state, int error_code); - -/** - * Restore error state to a previous value, returning saved error code. - */ -extern int git_error_state_restore(git_error_state *state); - -/** Free an error state. */ -extern void git_error_state_free(git_error_state *state); - -/** * Check a versioned structure for validity */ GIT_INLINE(int) git_error__check_version(const void *structure, unsigned int expected_max, const char *name) diff --git a/src/config.c b/src/config.c index fce1aad3b..5519fe19c 100644 --- a/src/config.c +++ b/src/config.c @@ -345,7 +345,7 @@ typedef struct { git_config_iterator parent; git_config_iterator *current; const git_config *cfg; - regex_t regex; + p_regex_t regex; size_t i; } all_iter; @@ -423,7 +423,7 @@ static int all_iter_glob_next(git_config_entry **entry, git_config_iterator *_it */ while ((error = all_iter_next(entry, _iter)) == 0) { /* skip non-matching keys if regexp was provided */ - if (regexec(&iter->regex, (*entry)->name, 0, NULL, 0) != 0) + if (p_regexec(&iter->regex, (*entry)->name, 0, NULL, 0) != 0) continue; /* and simply return if we like the entry's name */ @@ -447,7 +447,7 @@ static void all_iter_glob_free(git_config_iterator *_iter) { all_iter *iter = (all_iter *) _iter; - regfree(&iter->regex); + p_regfree(&iter->regex); all_iter_free(_iter); } @@ -480,7 +480,7 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf iter = git__calloc(1, sizeof(all_iter)); GIT_ERROR_CHECK_ALLOC(iter); - if ((result = p_regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) { + if ((result = p_regcomp(&iter->regex, regexp, P_REG_EXTENDED)) != 0) { git_error_set_regex(&iter->regex, result); git__free(iter); return -1; @@ -510,15 +510,15 @@ int git_config_backend_foreach_match( { git_config_entry *entry; git_config_iterator* iter; - regex_t regex; + p_regex_t regex; int error = 0; assert(backend && cb); if (regexp != NULL) { - if ((error = p_regcomp(®ex, regexp, REG_EXTENDED)) != 0) { + if ((error = p_regcomp(®ex, regexp, P_REG_EXTENDED)) != 0) { git_error_set_regex(®ex, error); - regfree(®ex); + p_regfree(®ex); return -1; } } @@ -530,7 +530,7 @@ int git_config_backend_foreach_match( while (!(iter->next(&entry, iter) < 0)) { /* skip non-matching keys if regexp was provided */ - if (regexp && regexec(®ex, entry->name, 0, NULL, 0) != 0) + if (regexp && p_regexec(®ex, entry->name, 0, NULL, 0) != 0) continue; /* abort iterator on non-zero return value */ @@ -541,7 +541,7 @@ int git_config_backend_foreach_match( } if (regexp != NULL) - regfree(®ex); + p_regfree(®ex); iter->free(iter); @@ -981,7 +981,7 @@ typedef struct { git_config_iterator parent; git_config_iterator *iter; char *name; - regex_t regex; + p_regex_t regex; int have_regex; } multivar_iter; @@ -997,7 +997,7 @@ static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_it if (!iter->have_regex) return 0; - if (regexec(&iter->regex, (*entry)->value, 0, NULL, 0) == 0) + if (p_regexec(&iter->regex, (*entry)->value, 0, NULL, 0) == 0) return 0; } @@ -1012,7 +1012,7 @@ void multivar_iter_free(git_config_iterator *_iter) git__free(iter->name); if (iter->have_regex) - regfree(&iter->regex); + p_regfree(&iter->regex); git__free(iter); } @@ -1032,11 +1032,11 @@ int git_config_multivar_iterator_new(git_config_iterator **out, const git_config goto on_error; if (regexp != NULL) { - error = p_regcomp(&iter->regex, regexp, REG_EXTENDED); + error = p_regcomp(&iter->regex, regexp, P_REG_EXTENDED); if (error != 0) { git_error_set_regex(&iter->regex, error); error = -1; - regfree(&iter->regex); + p_regfree(&iter->regex); goto on_error; } diff --git a/src/config_file.c b/src/config_file.c index 48a9a26d4..716205851 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -21,7 +21,6 @@ #include <ctype.h> #include <sys/types.h> -#include <regex.h> /* Max depth for [include] directives */ #define MAX_INCLUDE_DEPTH 10 @@ -62,7 +61,7 @@ typedef struct { } diskfile_parse_state; static int config_read(git_config_entries *entries, const git_repository *repo, git_config_file *file, git_config_level_t level, int depth); -static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const regex_t *preg, const char *value); +static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const p_regex_t *preg, const char *value); static char *escape_value(const char *ptr); static int config_snapshot(git_config_backend **out, git_config_backend *in); @@ -329,7 +328,7 @@ static int config_set_multivar( { diskfile_backend *b = (diskfile_backend *)cfg; char *key; - regex_t preg; + p_regex_t preg; int result; assert(regexp); @@ -337,7 +336,7 @@ static int config_set_multivar( if ((result = git_config__normalize_name(name, &key)) < 0) return result; - result = p_regcomp(&preg, regexp, REG_EXTENDED); + result = p_regcomp(&preg, regexp, P_REG_EXTENDED); if (result != 0) { git_error_set_regex(&preg, result); result = -1; @@ -352,7 +351,7 @@ static int config_set_multivar( out: git__free(key); - regfree(&preg); + p_regfree(&preg); return result; } @@ -395,7 +394,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con diskfile_backend *b = (diskfile_backend *)cfg; git_config_entries *entries = NULL; git_config_entry *entry = NULL; - regex_t preg = { 0 }; + p_regex_t preg = { 0 }; char *key = NULL; int result; @@ -413,7 +412,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con goto out; } - if ((result = p_regcomp(&preg, regexp, REG_EXTENDED)) != 0) { + if ((result = p_regcomp(&preg, regexp, P_REG_EXTENDED)) != 0) { git_error_set_regex(&preg, result); result = -1; goto out; @@ -428,7 +427,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con out: git_config_entries_free(entries); git__free(key); - regfree(&preg); + p_regfree(&preg); return result; } @@ -954,7 +953,7 @@ struct write_data { const char *section; const char *orig_name; const char *name; - const regex_t *preg; + const p_regex_t *preg; const char *value; }; @@ -1059,7 +1058,7 @@ static int write_on_variable( /* If we have a regex to match the value, see if it matches */ if (has_matched && write_data->preg != NULL) - has_matched = (regexec(write_data->preg, var_value, 0, NULL, 0) == 0); + has_matched = (p_regexec(write_data->preg, var_value, 0, NULL, 0) == 0); /* If this isn't the name/value we're looking for, simply dump the * existing data back out and continue on. @@ -1120,7 +1119,7 @@ static int write_on_eof( /* * This is pretty much the parsing, except we write out anything we don't have */ -static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const regex_t *preg, const char* value) +static int config_write(diskfile_backend *cfg, const char *orig_key, const char *key, const p_regex_t *preg, const char* value) { int result; char *orig_section, *section, *orig_name, *name, *ldot; diff --git a/src/diff_driver.c b/src/diff_driver.c index 959cf6258..740b5c9a3 100644 --- a/src/diff_driver.c +++ b/src/diff_driver.c @@ -9,6 +9,7 @@ #include "git2/attr.h" +#include "common.h" #include "diff.h" #include "strmap.h" #include "map.h" @@ -24,7 +25,7 @@ typedef enum { } git_diff_driver_t; typedef struct { - regex_t re; + p_regex_t re; int flags; } git_diff_driver_pattern; @@ -38,7 +39,7 @@ struct git_diff_driver { uint32_t binary_flags; uint32_t other_flags; git_array_t(git_diff_driver_pattern) fn_patterns; - regex_t word_pattern; + p_regex_t word_pattern; char name[GIT_FLEX_ARRAY]; }; @@ -129,7 +130,7 @@ static int diff_driver_add_patterns( static int diff_driver_xfuncname(const git_config_entry *entry, void *payload) { - return diff_driver_add_patterns(payload, entry->value, REG_EXTENDED); + return diff_driver_add_patterns(payload, entry->value, P_REG_EXTENDED); } static int diff_driver_funcname(const git_config_entry *entry, void *payload) @@ -204,12 +205,12 @@ static int git_diff_driver_builtin( if (ddef->fns && (error = diff_driver_add_patterns( - drv, ddef->fns, ddef->flags | REG_EXTENDED)) < 0) + drv, ddef->fns, ddef->flags | P_REG_EXTENDED)) < 0) goto done; if (ddef->words && (error = p_regcomp( - &drv->word_pattern, ddef->words, ddef->flags | REG_EXTENDED))) + &drv->word_pattern, ddef->words, ddef->flags | P_REG_EXTENDED))) { error = git_error_set_regex(&drv->word_pattern, error); goto done; @@ -280,7 +281,9 @@ static int git_diff_driver_load( /* TODO: warn if diff.<name>.command or diff.<name>.textconv are set */ git_buf_truncate(&name, namelen + strlen("diff..")); - git_buf_put(&name, "xfuncname", strlen("xfuncname")); + if ((error = git_buf_PUTS(&name, "xfuncname")) < 0) + goto done; + if ((error = git_config_get_multivar_foreach( cfg, name.ptr, NULL, diff_driver_xfuncname, drv)) < 0) { if (error != GIT_ENOTFOUND) @@ -289,7 +292,9 @@ static int git_diff_driver_load( } git_buf_truncate(&name, namelen + strlen("diff..")); - git_buf_put(&name, "funcname", strlen("funcname")); + if ((error = git_buf_PUTS(&name, "funcname")) < 0) + goto done; + if ((error = git_config_get_multivar_foreach( cfg, name.ptr, NULL, diff_driver_funcname, drv)) < 0) { if (error != GIT_ENOTFOUND) @@ -304,12 +309,14 @@ static int git_diff_driver_load( } git_buf_truncate(&name, namelen + strlen("diff..")); - git_buf_put(&name, "wordregex", strlen("wordregex")); + if ((error = git_buf_PUTS(&name, "wordregex")) < 0) + goto done; + if ((error = git_config__lookup_entry(&ce, cfg, name.ptr, false)) < 0) goto done; if (!ce || !ce->value) /* no diff.<driver>.wordregex, so just continue */; - else if (!(error = p_regcomp(&drv->word_pattern, ce->value, REG_EXTENDED))) + else if (!(error = p_regcomp(&drv->word_pattern, ce->value, P_REG_EXTENDED))) found_driver = true; else { /* TODO: warn about bad regex instead of failure */ @@ -393,10 +400,10 @@ void git_diff_driver_free(git_diff_driver *driver) return; for (i = 0; i < git_array_size(driver->fn_patterns); ++i) - regfree(& git_array_get(driver->fn_patterns, i)->re); + p_regfree(& git_array_get(driver->fn_patterns, i)->re); git_array_clear(driver->fn_patterns); - regfree(&driver->word_pattern); + p_regfree(&driver->word_pattern); git__free(driver); } @@ -444,12 +451,12 @@ static int diff_context_line__pattern_match( git_diff_driver *driver, git_buf *line) { size_t i, maxi = git_array_size(driver->fn_patterns); - regmatch_t pmatch[2]; + p_regmatch_t pmatch[2]; for (i = 0; i < maxi; ++i) { git_diff_driver_pattern *pat = git_array_get(driver->fn_patterns, i); - if (!regexec(&pat->re, line->ptr, 2, pmatch, 0)) { + if (!p_regexec(&pat->re, line->ptr, 2, pmatch, 0)) { if (pat->flags & REG_NEGATE) return false; diff --git a/src/errors.c b/src/errors.c index afa340936..8ef491916 100644 --- a/src/errors.c +++ b/src/errors.c @@ -105,16 +105,16 @@ void git_error_set_str(int error_class, const char *string) set_error_from_buffer(error_class); } -int git_error_set_regex(const regex_t *regex, int error_code) +int git_error_set_regex(const p_regex_t *regex, int error_code) { char error_buf[1024]; assert(error_code); - regerror(error_code, regex, error_buf, sizeof(error_buf)); + p_regerror(error_code, regex, error_buf, sizeof(error_buf)); git_error_set_str(GIT_ERROR_REGEX, error_buf); - if (error_code == REG_NOMATCH) + if (error_code == P_REG_NOMATCH) return GIT_ENOTFOUND; return GIT_EINVALIDSPEC; diff --git a/src/errors.h b/src/errors.h new file mode 100644 index 000000000..f2af1e37d --- /dev/null +++ b/src/errors.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_errors_h__ +#define INCLUDE_errors_h__ + +#include "posix_regex.h" +#include "common.h" + +/* + * Set the error message for this thread, formatting as needed. + */ + +void git_error_set(int error_class, const char *string, ...) GIT_FORMAT_PRINTF(2, 3); + +/** + * Set the error message for a regex failure, using the internal regex + * error code lookup and return a libgit error code. + */ +int git_error_set_regex(const p_regex_t *regex, int error_code); + +/** + * Set error message for user callback if needed. + * + * If the error code in non-zero and no error message is set, this + * sets a generic error message. + * + * @return This always returns the `error_code` parameter. + */ +GIT_INLINE(int) git_error_set_after_callback_function( + int error_code, const char *action) +{ + if (error_code) { + const git_error *e = git_error_last(); + if (!e || !e->message) + git_error_set(e ? e->klass : GIT_ERROR_CALLBACK, + "%s callback returned %d", action, error_code); + } + return error_code; +} + +#ifdef GIT_WIN32 +#define git_error_set_after_callback(code) \ + git_error_set_after_callback_function((code), __FUNCTION__) +#else +#define git_error_set_after_callback(code) \ + git_error_set_after_callback_function((code), __func__) +#endif + +/** + * Gets the system error code for this thread. + */ +int git_error_system_last(void); + +/** + * Sets the system error code for this thread. + */ +void git_error_system_set(int code); + +/** + * Structure to preserve libgit2 error state + */ +typedef struct { + int error_code; + unsigned int oom : 1; + git_error error_msg; +} git_error_state; + +/** + * Capture current error state to restore later, returning error code. + * If `error_code` is zero, this does not clear the current error state. + * You must either restore this error state, or free it. + */ +extern int git_error_state_capture(git_error_state *state, int error_code); + +/** + * Restore error state to a previous value, returning saved error code. + */ +extern int git_error_state_restore(git_error_state *state); + +/** Free an error state. */ +extern void git_error_state_free(git_error_state *state); + +#endif diff --git a/src/features.h.in b/src/features.h.in index 694a61c02..4090fadb5 100644 --- a/src/features.h.in +++ b/src/features.h.in @@ -15,7 +15,12 @@ #cmakedefine GIT_USE_STAT_MTIMESPEC 1 #cmakedefine GIT_USE_STAT_MTIME_NSEC 1 #cmakedefine GIT_USE_FUTIMENS 1 -#cmakedefine GIT_USE_REGCOMP_L 1 + +#cmakedefine GIT_REGEX_REGCOMP_L +#cmakedefine GIT_REGEX_REGCOMP +#cmakedefine GIT_REGEX_PCRE +#cmakedefine GIT_REGEX_PCRE2 +#cmakedefine GIT_REGEX_BUILTIN 1 #cmakedefine GIT_SSH 1 #cmakedefine GIT_SSH_MEMORY_CREDENTIALS 1 diff --git a/src/posix_regex.h b/src/posix_regex.h new file mode 100644 index 000000000..421ffeba1 --- /dev/null +++ b/src/posix_regex.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_posix_regex_h__ +#define INCLUDE_posix_regex_h__ + +#include "common.h" + +/* + * Regular expressions: if we were asked to use PCRE (either our + * bundled version or a system version) then use their regcomp + * compatible implementation. + */ + +#ifdef GIT_REGEX_BUILTIN + +# include "pcreposix.h" + +# define P_REG_EXTENDED PCRE_REG_EXTENDED +# define P_REG_ICASE PCRE_REG_ICASE +# define P_REG_NOMATCH PCRE_REG_NOMATCH + +# define p_regex_t pcre_regex_t +# define p_regmatch_t pcre_regmatch_t +# define p_regcomp pcre_regcomp +# define p_regerror pcre_regerror +# define p_regexec pcre_regexec +# define p_regfree pcre_regfree + +/* + * Use the system-provided `regex` routines, whether that's via the + * PCRE emulation layer, or libc, preferring `regcomp_l` it's available. + */ + +#else + +# if defined(GIT_REGEX_PCRE2) +# include <pcre2posix.h> +# elif defined(GIT_REGEX_PCRE) +# include <pcreposix.h> +# else +# include <regex.h> +# endif + +# define P_REG_EXTENDED REG_EXTENDED +# define P_REG_ICASE REG_ICASE +# define P_REG_NOMATCH REG_NOMATCH + +# define p_regex_t regex_t +# define p_regmatch_t regmatch_t + +# define p_regerror regerror +# define p_regexec regexec +# define p_regfree regfree + +# ifdef GIT_REGEX_REGCOMP_L +# include <xlocale.h> + +GIT_INLINE(int) p_regcomp(p_regex_t *preg, const char *pattern, int cflags) +{ + return regcomp_l(preg, pattern, cflags, (locale_t) 0); +} + +# else +# define p_regcomp regcomp +# endif /* GIT_REGEX_REGCOMP_L */ + +#endif + +#endif diff --git a/src/revparse.c b/src/revparse.c index 50ee31ca0..4bde0d7f2 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -42,7 +42,7 @@ static int maybe_abbrev(git_object** out, git_repository *repo, const char *spec return maybe_sha_or_abbrev(out, repo, spec, speclen); } -static int build_regex(regex_t *regex, const char *pattern) +static int build_regex(p_regex_t *regex, const char *pattern) { int error; @@ -51,13 +51,13 @@ static int build_regex(regex_t *regex, const char *pattern) return GIT_EINVALIDSPEC; } - error = p_regcomp(regex, pattern, REG_EXTENDED); + error = p_regcomp(regex, pattern, P_REG_EXTENDED); if (!error) return 0; error = git_error_set_regex(regex, error); - regfree(regex); + p_regfree(regex); return error; } @@ -66,7 +66,7 @@ static int maybe_describe(git_object**out, git_repository *repo, const char *spe { const char *substr; int error; - regex_t regex; + p_regex_t regex; substr = strstr(spec, "-g"); @@ -76,8 +76,8 @@ static int maybe_describe(git_object**out, git_repository *repo, const char *spe if (build_regex(®ex, ".+-[0-9]+-g[0-9a-fA-F]+") < 0) return -1; - error = regexec(®ex, spec, 0, NULL, 0); - regfree(®ex); + error = p_regexec(®ex, spec, 0, NULL, 0); + p_regfree(®ex); if (error) return GIT_ENOTFOUND; @@ -143,12 +143,12 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out, { git_reference *ref = NULL; git_reflog *reflog = NULL; - regex_t preg; + p_regex_t preg; int error = -1; size_t i, numentries, cur; const git_reflog_entry *entry; const char *msg; - regmatch_t regexmatches[2]; + p_regmatch_t regexmatches[2]; git_buf buf = GIT_BUF_INIT; cur = position; @@ -173,7 +173,7 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out, if (!msg) continue; - if (regexec(&preg, msg, 2, regexmatches, 0)) + if (p_regexec(&preg, msg, 2, regexmatches, 0)) continue; cur--; @@ -199,7 +199,7 @@ static int retrieve_previously_checked_out_branch_or_revision(git_object **out, cleanup: git_reference_free(ref); git_buf_dispose(&buf); - regfree(&preg); + p_regfree(&preg); git_reflog_free(reflog); return error; } @@ -448,7 +448,7 @@ cleanup: return error; } -static int walk_and_search(git_object **out, git_revwalk *walk, regex_t *regex) +static int walk_and_search(git_object **out, git_revwalk *walk, p_regex_t *regex) { int error; git_oid oid; @@ -460,7 +460,7 @@ static int walk_and_search(git_object **out, git_revwalk *walk, regex_t *regex) if ((error < 0) && (error != GIT_ENOTFOUND)) return -1; - if (!regexec(regex, git_commit_message((git_commit*)obj), 0, NULL, 0)) { + if (!p_regexec(regex, git_commit_message((git_commit*)obj), 0, NULL, 0)) { *out = obj; return 0; } @@ -476,7 +476,7 @@ static int walk_and_search(git_object **out, git_revwalk *walk, regex_t *regex) static int handle_grep_syntax(git_object **out, git_repository *repo, const git_oid *spec_oid, const char *pattern) { - regex_t preg; + p_regex_t preg; git_revwalk *walk = NULL; int error; @@ -497,7 +497,7 @@ static int handle_grep_syntax(git_object **out, git_repository *repo, const git_ error = walk_and_search(out, walk, &preg); cleanup: - regfree(&preg); + p_regfree(&preg); git_revwalk_free(walk); return error; diff --git a/src/unix/posix.h b/src/unix/posix.h index f2fffd5c9..f969f8362 100644 --- a/src/unix/posix.h +++ b/src/unix/posix.h @@ -89,14 +89,4 @@ GIT_INLINE(int) p_futimes(int f, const struct p_timeval t[2]) # define p_futimes futimes #endif -#ifdef GIT_USE_REGCOMP_L -#include <xlocale.h> -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/userdiff.h b/src/userdiff.h index 91c1f42dc..8bde6303f 100644 --- a/src/userdiff.h +++ b/src/userdiff.h @@ -29,7 +29,7 @@ typedef struct { #define PATTERNS(NAME, FN_PATS, WORD_PAT) \ { NAME, FN_PATS, WORD_PAT WORD_DEFAULT, 0 } #define IPATTERN(NAME, FN_PATS, WORD_PAT) \ - { NAME, FN_PATS, WORD_PAT WORD_DEFAULT, REG_ICASE } + { NAME, FN_PATS, WORD_PAT WORD_DEFAULT, P_REG_ICASE } /* * The table of diff driver patterns diff --git a/src/win32/path_w32.h b/src/win32/path_w32.h index facbced81..afd0aa155 100644 --- a/src/win32/path_w32.h +++ b/src/win32/path_w32.h @@ -8,37 +8,8 @@ #define INCLUDE_win32_path_w32_h__ #include "common.h" - #include "vector.h" -/* - * Provides a large enough buffer to support Windows paths: MAX_PATH is - * 260, corresponding to a maximum path length of 259 characters plus a - * NULL terminator. Prefixing with "\\?\" adds 4 characters, but if the - * original was a UNC path, then we turn "\\server\share" into - * "\\?\UNC\server\share". So we replace the first two characters with - * 8 characters, a net gain of 6, so the maximum length is MAX_PATH+6. - */ -#define GIT_WIN_PATH_UTF16 MAX_PATH+6 - -/* Maximum size of a UTF-8 Win32 path. We remove the "\\?\" or "\\?\UNC\" - * prefixes for presentation, bringing us back to 259 (non-NULL) - * characters. UTF-8 does have 4-byte sequences, but they are encoded in - * UTF-16 using surrogate pairs, which takes up the space of two characters. - * Two characters in the range U+0800 -> U+FFFF take up more space in UTF-8 - * (6 bytes) than one surrogate pair (4 bytes). - */ -#define GIT_WIN_PATH_UTF8 (259 * 3 + 1) - -/* - * The length of a Windows "shortname", for 8.3 compatibility. - */ -#define GIT_WIN_PATH_SHORTNAME 13 - -/* Win32 path types */ -typedef wchar_t git_win32_path[GIT_WIN_PATH_UTF16]; -typedef char git_win32_utf8_path[GIT_WIN_PATH_UTF8]; - /** * Create a Win32 path (in UCS-2 format) from a UTF-8 string. * diff --git a/src/win32/posix.h b/src/win32/posix.h index d5ab2e8f5..e427d64c3 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -60,7 +60,4 @@ 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/src/win32/precompiled.h b/src/win32/precompiled.h index 851a083d5..314383d31 100644 --- a/src/win32/precompiled.h +++ b/src/win32/precompiled.h @@ -13,8 +13,6 @@ #include <sys/types.h> #include <sys/stat.h> -#include <regex.h> - #include <io.h> #include <direct.h> #ifdef GIT_THREADS diff --git a/src/win32/w32_common.h b/src/win32/w32_common.h new file mode 100644 index 000000000..f9e74b947 --- /dev/null +++ b/src/win32/w32_common.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_win32_w32_common_h__ +#define INCLUDE_win32_w32_common_h__ + +/* + * Provides a large enough buffer to support Windows paths: MAX_PATH is + * 260, corresponding to a maximum path length of 259 characters plus a + * NULL terminator. Prefixing with "\\?\" adds 4 characters, but if the + * original was a UNC path, then we turn "\\server\share" into + * "\\?\UNC\server\share". So we replace the first two characters with + * 8 characters, a net gain of 6, so the maximum length is MAX_PATH+6. + */ +#define GIT_WIN_PATH_UTF16 MAX_PATH+6 + +/* Maximum size of a UTF-8 Win32 path. We remove the "\\?\" or "\\?\UNC\" + * prefixes for presentation, bringing us back to 259 (non-NULL) + * characters. UTF-8 does have 4-byte sequences, but they are encoded in + * UTF-16 using surrogate pairs, which takes up the space of two characters. + * Two characters in the range U+0800 -> U+FFFF take up more space in UTF-8 + * (6 bytes) than one surrogate pair (4 bytes). + */ +#define GIT_WIN_PATH_UTF8 (259 * 3 + 1) + +/* + * The length of a Windows "shortname", for 8.3 compatibility. + */ +#define GIT_WIN_PATH_SHORTNAME 13 + +/* Win32 path types */ +typedef wchar_t git_win32_path[GIT_WIN_PATH_UTF16]; +typedef char git_win32_utf8_path[GIT_WIN_PATH_UTF8]; + +#endif |
