aboutsummaryrefslogtreecommitdiffstats
path: root/src/search.c
diff options
context:
space:
mode:
authorNoam Postavsky2016-07-20 20:15:14 -0400
committerNoam Postavsky2016-07-22 23:55:23 -0400
commit66f95e0dabf750e9d2eff59b2bb6e593618cd48a (patch)
treea8cd27828bfef2459b70e446cdf1de346327fc3e /src/search.c
parent52cf0d5d98c51c3591ca5d376fd4e85cd9b72d7f (diff)
downloademacs-66f95e0dabf750e9d2eff59b2bb6e593618cd48a.tar.gz
emacs-66f95e0dabf750e9d2eff59b2bb6e593618cd48a.zip
Adjust match data before calling after-change-funs
It's important to adjust the match data in between calling before-change-functions and after-change-functions, so that buffer change hooks will always see match-data consistent with buffer content. (Bug #23917) * src/insdel.c (replace_range): Add new parameter ADJUST_MATCH_DATA, if true call update_search_regs. Update all callers (except Freplace_match) to pass 0 for the new parameter. * src/search.c (update_search_regs): New function, extracted from Freplace_match. (Freplace_match): Remove match data adjustment code, pass 1 for ADJUST_MATCH_DATA to replace_range instead.
Diffstat (limited to 'src/search.c')
-rw-r--r--src/search.c56
1 files changed, 32 insertions, 24 deletions
diff --git a/src/search.c b/src/search.c
index 5c949ad00a4..b70f02097b7 100644
--- a/src/search.c
+++ b/src/search.c
@@ -2719,16 +2719,23 @@ since only regular expressions have distinguished subexpressions. */)
2719 2719
2720 /* The functions below modify the buffer, so they could trigger 2720 /* The functions below modify the buffer, so they could trigger
2721 various modification hooks (see signal_before_change and 2721 various modification hooks (see signal_before_change and
2722 signal_after_change), which might clobber the match data we need 2722 signal_after_change). If these hooks clobber the match data we
2723 to adjust after the replacement. If that happens, we error out. */ 2723 error out since otherwise this will result in confusing bugs. */
2724 ptrdiff_t sub_start = search_regs.start[sub]; 2724 ptrdiff_t sub_start = search_regs.start[sub];
2725 ptrdiff_t sub_end = search_regs.end[sub]; 2725 ptrdiff_t sub_end = search_regs.end[sub];
2726 unsigned num_regs = search_regs.num_regs; 2726 unsigned num_regs = search_regs.num_regs;
2727 newpoint = search_regs.start[sub] + SCHARS (newtext);
2727 2728
2728 /* Replace the old text with the new in the cleanest possible way. */ 2729 /* Replace the old text with the new in the cleanest possible way. */
2729 replace_range (search_regs.start[sub], search_regs.end[sub], 2730 replace_range (search_regs.start[sub], search_regs.end[sub],
2730 newtext, 1, 0, 1); 2731 newtext, 1, 0, 1, 1);
2731 newpoint = search_regs.start[sub] + SCHARS (newtext); 2732 /* Update saved data to match adjustment made by replace_range. */
2733 {
2734 ptrdiff_t change = newpoint - sub_end;
2735 if (sub_start >= sub_end)
2736 sub_start += change;
2737 sub_end += change;
2738 }
2732 2739
2733 if (case_action == all_caps) 2740 if (case_action == all_caps)
2734 Fupcase_region (make_number (search_regs.start[sub]), 2741 Fupcase_region (make_number (search_regs.start[sub]),
@@ -2742,26 +2749,6 @@ since only regular expressions have distinguished subexpressions. */)
2742 || search_regs.num_regs != num_regs) 2749 || search_regs.num_regs != num_regs)
2743 error ("Match data clobbered by buffer modification hooks"); 2750 error ("Match data clobbered by buffer modification hooks");
2744 2751
2745 /* Adjust search data for this change. */
2746 {
2747 ptrdiff_t oldend = search_regs.end[sub];
2748 ptrdiff_t oldstart = search_regs.start[sub];
2749 ptrdiff_t change = newpoint - search_regs.end[sub];
2750 ptrdiff_t i;
2751
2752 for (i = 0; i < search_regs.num_regs; i++)
2753 {
2754 if (search_regs.start[i] >= oldend)
2755 search_regs.start[i] += change;
2756 else if (search_regs.start[i] > oldstart)
2757 search_regs.start[i] = oldstart;
2758 if (search_regs.end[i] >= oldend)
2759 search_regs.end[i] += change;
2760 else if (search_regs.end[i] > oldstart)
2761 search_regs.end[i] = oldstart;
2762 }
2763 }
2764
2765 /* Put point back where it was in the text. */ 2752 /* Put point back where it was in the text. */
2766 if (opoint <= 0) 2753 if (opoint <= 0)
2767 TEMP_SET_PT (opoint + ZV); 2754 TEMP_SET_PT (opoint + ZV);
@@ -3102,6 +3089,27 @@ restore_search_regs (void)
3102 } 3089 }
3103} 3090}
3104 3091
3092/* Called from replace-match via replace_range. */
3093void
3094update_search_regs (ptrdiff_t oldstart, ptrdiff_t oldend, ptrdiff_t newend)
3095{
3096 /* Adjust search data for this change. */
3097 ptrdiff_t change = newend - oldend;
3098 ptrdiff_t i;
3099
3100 for (i = 0; i < search_regs.num_regs; i++)
3101 {
3102 if (search_regs.start[i] >= oldend)
3103 search_regs.start[i] += change;
3104 else if (search_regs.start[i] > oldstart)
3105 search_regs.start[i] = oldstart;
3106 if (search_regs.end[i] >= oldend)
3107 search_regs.end[i] += change;
3108 else if (search_regs.end[i] > oldstart)
3109 search_regs.end[i] = oldstart;
3110 }
3111}
3112
3105static void 3113static void
3106unwind_set_match_data (Lisp_Object list) 3114unwind_set_match_data (Lisp_Object list)
3107{ 3115{