diff options
| author | Mattias EngdegÄrd | 2020-11-25 15:32:08 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2020-11-26 14:20:13 +0100 |
| commit | 558b6dbca7bc933fe01255be9ebeffebd44a2645 (patch) | |
| tree | 32f4bc6b85c11d31a513afb4b804e7502d00808d /src/search.c | |
| parent | 0287c5176867628e7acb834b3d5f26a150cfaf85 (diff) | |
| download | emacs-558b6dbca7bc933fe01255be9ebeffebd44a2645.tar.gz emacs-558b6dbca7bc933fe01255be9ebeffebd44a2645.zip | |
Fix replace-regexp-in-string substring match data translation
For certain patterns, re-matching the same regexp on the matched
substring does not produce correctly translated match data
(bug#15107 and bug#44861).
Using a new builtin function also improves performance since the
number of calls to string-match is halved.
Reported by Kevin Ryde and Shigeru Fukaya.
* lisp/subr.el (replace-regexp-in-string): Translate the match data
using match-data--translate instead of trusting a call to string-match
on the matched string to do the job.
* test/lisp/subr-tests.el (subr-replace-regexp-in-string):
Add test cases.
* src/search.c (Fmatch_data__translate): New internal function.
(syms_of_search): Register it as a subroutine.
Diffstat (limited to 'src/search.c')
| -rw-r--r-- | src/search.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/search.c b/src/search.c index e7f90949464..4eb634a3c03 100644 --- a/src/search.c +++ b/src/search.c | |||
| @@ -3031,6 +3031,23 @@ If optional arg RESEAT is non-nil, make markers on LIST point nowhere. */) | |||
| 3031 | return Qnil; | 3031 | return Qnil; |
| 3032 | } | 3032 | } |
| 3033 | 3033 | ||
| 3034 | DEFUN ("match-data--translate", Fmatch_data__translate, Smatch_data__translate, | ||
| 3035 | 1, 1, 0, | ||
| 3036 | doc: /* Add N to all string positions in the match data. Internal. */) | ||
| 3037 | (Lisp_Object n) | ||
| 3038 | { | ||
| 3039 | CHECK_FIXNUM (n); | ||
| 3040 | EMACS_INT delta = XFIXNUM (n); | ||
| 3041 | if (EQ (last_thing_searched, Qt)) /* String match data only. */ | ||
| 3042 | for (ptrdiff_t i = 0; i < search_regs.num_regs; i++) | ||
| 3043 | if (search_regs.start[i] >= 0) | ||
| 3044 | { | ||
| 3045 | search_regs.start[i] = max (0, search_regs.start[i] + delta); | ||
| 3046 | search_regs.end[i] = max (0, search_regs.end[i] + delta); | ||
| 3047 | } | ||
| 3048 | return Qnil; | ||
| 3049 | } | ||
| 3050 | |||
| 3034 | /* Called from Flooking_at, Fstring_match, search_buffer, Fstore_match_data | 3051 | /* Called from Flooking_at, Fstring_match, search_buffer, Fstore_match_data |
| 3035 | if asynchronous code (filter or sentinel) is running. */ | 3052 | if asynchronous code (filter or sentinel) is running. */ |
| 3036 | static void | 3053 | static void |
| @@ -3388,6 +3405,7 @@ is to bind it with `let' around a small expression. */); | |||
| 3388 | defsubr (&Smatch_end); | 3405 | defsubr (&Smatch_end); |
| 3389 | defsubr (&Smatch_data); | 3406 | defsubr (&Smatch_data); |
| 3390 | defsubr (&Sset_match_data); | 3407 | defsubr (&Sset_match_data); |
| 3408 | defsubr (&Smatch_data__translate); | ||
| 3391 | defsubr (&Sregexp_quote); | 3409 | defsubr (&Sregexp_quote); |
| 3392 | defsubr (&Snewline_cache_check); | 3410 | defsubr (&Snewline_cache_check); |
| 3393 | 3411 | ||