diff options
author | Ron Yorston <rmy@pobox.com> | 2021-06-21 11:30:39 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-21 15:37:28 +0200 |
commit | 51358757c709f9c489aa6b13b34141edf84183fa (patch) | |
tree | a1649e684229819cd5bab9a0ed0f195adb737957 | |
parent | ac4786ba002620eb4c046c847e69d6a12ea0e322 (diff) |
vi: fix backward search with GNU regex
With FEATURE_VI_REGEX_SEARCH enabled backward searches don't work.
This is problematic on distros that enable regexes, such as Tiny
Core Linux and Fedora.
When calling GNU re_search() with a negative range parameter
(indicating a backward search) the start offset must be set to
the end of the area being searched.
The return value of re_search() is the offset of the matched pattern
from the start of the area being searched. For a successful search
(positive return value) char_search() can return the pointer to
the start of the area plus the offset.
FEATURE_VI_REGEX_SEARCH isn't enabled by default but when it is:
function old new delta
char_search 256 247 -9
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-9) Total: -9 bytes
Signed-off-by: Andrey Dobrovolsky <andrey.dobrovolsky.odessa@gmail.com>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/vi.c | 33 |
1 files changed, 13 insertions, 20 deletions
diff --git a/editors/vi.c b/editors/vi.c index b06270dfd..0baea615b 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2376,9 +2376,7 @@ static char *char_search(char *p, const char *pat, int dir_and_range) struct re_pattern_buffer preg; const char *err; char *q; - int i; - int size; - int range; + int i, size, range, start; re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; if (ignorecase) @@ -2403,31 +2401,26 @@ static char *char_search(char *p, const char *pat, int dir_and_range) // RANGE could be negative if we are searching backwards range = q - p; - q = p; - size = range; if (range < 0) { - size = -size; - q = p - size; - if (q < text) - q = text; + size = -range; + start = size; + } else { + size = range; + start = 0; } + q = p - start; + if (q < text) + q = text; // search for the compiled pattern, preg, in p[] - // range < 0: search backward - // range > 0: search forward - // 0 < start < size + // range < 0, start == size: search backward + // range > 0, start == 0: search forward // re_search() < 0: not found or error // re_search() >= 0: index of found pattern // struct pattern char int int int struct reg // re_search(*pattern_buffer, *string, size, start, range, *regs) - i = re_search(&preg, q, size, /*start:*/ 0, range, /*struct re_registers*:*/ NULL); + i = re_search(&preg, q, size, start, range, /*struct re_registers*:*/ NULL); regfree(&preg); - if (i < 0) - return NULL; - if (dir_and_range > 0) // FORWARD? - p = p + i; - else - p = p - i; - return p; + return i < 0 ? NULL : q + i; } # else # if ENABLE_FEATURE_VI_SETOPTS |