aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd2020-11-25 15:32:08 +0100
committerMattias EngdegÄrd2020-11-26 14:20:13 +0100
commit558b6dbca7bc933fe01255be9ebeffebd44a2645 (patch)
tree32f4bc6b85c11d31a513afb4b804e7502d00808d /src
parent0287c5176867628e7acb834b3d5f26a150cfaf85 (diff)
downloademacs-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')
-rw-r--r--src/search.c18
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
3034DEFUN ("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. */
3036static void 3053static 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