diff options
| author | Alan Mackenzie | 2019-03-01 17:35:12 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2019-03-01 17:37:56 +0000 |
| commit | 31182c1d17f6f7bc946d5e4576e025c9b975e0b5 (patch) | |
| tree | 49f54fc69a83fbc5f7a7c01a82fe1e1417a94a59 /src | |
| parent | 287f2a676405009a6927fe7c33e36299a86b2827 (diff) | |
| download | emacs-31182c1d17f6f7bc946d5e4576e025c9b975e0b5.tar.gz emacs-31182c1d17f6f7bc946d5e4576e025c9b975e0b5.zip | |
Maintain interval ->position fields correctly in update_interval
Also fix some anomalies in the handling of byte positions in regexp-emacs.c
This fixes bug #34525.
* src/intervals.c (SET_PARENT_POSITION): New macro.
(update_interval): When moving to an interval's parent, set that parent's
->position field, to maintain the consistency of the tree.
* src/intervals.h (struct interval): Amend the comment describing when
->position is valid.
* src/pdumper.c: Update the hash associated with struct interval.
* src/regex-emacs.c: (re_match_2_internal): Only invoke POINTER_TO_OFFSET on a
known character boundary. Only perform arithmetic on character positions, not
on byte positions. Correct the argument to an invocation of
UPDATE_SYNTAX_TABLE_FORWARD by adding 1 to it (in case wordend:).
* src/syntax.c: (update_syntax_table): Remove the now redundant code that set
the ->position field of all parents of the interval found by update_interval.
Diffstat (limited to 'src')
| -rw-r--r-- | src/intervals.c | 30 | ||||
| -rw-r--r-- | src/intervals.h | 14 | ||||
| -rw-r--r-- | src/pdumper.c | 2 | ||||
| -rw-r--r-- | src/regex-emacs.c | 14 | ||||
| -rw-r--r-- | src/syntax.c | 14 |
5 files changed, 40 insertions, 34 deletions
diff --git a/src/intervals.c b/src/intervals.c index 524bb944e51..8f39c45762f 100644 --- a/src/intervals.c +++ b/src/intervals.c | |||
| @@ -713,11 +713,21 @@ previous_interval (register INTERVAL interval) | |||
| 713 | return NULL; | 713 | return NULL; |
| 714 | } | 714 | } |
| 715 | 715 | ||
| 716 | /* Find the interval containing POS given some non-NULL INTERVAL | 716 | /* Set the ->position field of I's parent, based on I->position. */ |
| 717 | in the same tree. Note that we need to update interval->position | 717 | #define SET_PARENT_POSITION(i) \ |
| 718 | if we go down the tree. | 718 | if (AM_LEFT_CHILD (i)) \ |
| 719 | To speed up the process, we assume that the ->position of | 719 | INTERVAL_PARENT (i)->position = \ |
| 720 | I and all its parents is already uptodate. */ | 720 | i->position + TOTAL_LENGTH (i) - LEFT_TOTAL_LENGTH (i); \ |
| 721 | else \ | ||
| 722 | INTERVAL_PARENT (i)->position = \ | ||
| 723 | i->position - LEFT_TOTAL_LENGTH (i) \ | ||
| 724 | - LENGTH (INTERVAL_PARENT (i)) | ||
| 725 | |||
| 726 | /* Find the interval containing POS, given some non-NULL INTERVAL in | ||
| 727 | the same tree. Note that we update interval->position in each | ||
| 728 | interval we traverse, assuming it is already correctly set for the | ||
| 729 | argument I. We don't assume that any other interval already has a | ||
| 730 | correctly set ->position. */ | ||
| 721 | INTERVAL | 731 | INTERVAL |
| 722 | update_interval (register INTERVAL i, ptrdiff_t pos) | 732 | update_interval (register INTERVAL i, ptrdiff_t pos) |
| 723 | { | 733 | { |
| @@ -738,7 +748,10 @@ update_interval (register INTERVAL i, ptrdiff_t pos) | |||
| 738 | else if (NULL_PARENT (i)) | 748 | else if (NULL_PARENT (i)) |
| 739 | error ("Point before start of properties"); | 749 | error ("Point before start of properties"); |
| 740 | else | 750 | else |
| 741 | i = INTERVAL_PARENT (i); | 751 | { |
| 752 | SET_PARENT_POSITION (i); | ||
| 753 | i = INTERVAL_PARENT (i); | ||
| 754 | } | ||
| 742 | continue; | 755 | continue; |
| 743 | } | 756 | } |
| 744 | else if (pos >= INTERVAL_LAST_POS (i)) | 757 | else if (pos >= INTERVAL_LAST_POS (i)) |
| @@ -753,7 +766,10 @@ update_interval (register INTERVAL i, ptrdiff_t pos) | |||
| 753 | else if (NULL_PARENT (i)) | 766 | else if (NULL_PARENT (i)) |
| 754 | error ("Point %"pD"d after end of properties", pos); | 767 | error ("Point %"pD"d after end of properties", pos); |
| 755 | else | 768 | else |
| 756 | i = INTERVAL_PARENT (i); | 769 | { |
| 770 | SET_PARENT_POSITION (i); | ||
| 771 | i = INTERVAL_PARENT (i); | ||
| 772 | } | ||
| 757 | continue; | 773 | continue; |
| 758 | } | 774 | } |
| 759 | else | 775 | else |
diff --git a/src/intervals.h b/src/intervals.h index 9c5adf33a14..e9166946d9a 100644 --- a/src/intervals.h +++ b/src/intervals.h | |||
| @@ -31,11 +31,15 @@ struct interval | |||
| 31 | /* The first group of entries deal with the tree structure. */ | 31 | /* The first group of entries deal with the tree structure. */ |
| 32 | ptrdiff_t total_length; /* Length of myself and both children. */ | 32 | ptrdiff_t total_length; /* Length of myself and both children. */ |
| 33 | ptrdiff_t position; /* Cache of interval's character position. */ | 33 | ptrdiff_t position; /* Cache of interval's character position. */ |
| 34 | /* This field is usually updated | 34 | /* This field is valid in the final |
| 35 | simultaneously with an interval | 35 | target interval returned by |
| 36 | traversal, there is no guarantee | 36 | find_interval, next_interval, |
| 37 | that it is valid for a random | 37 | previous_interval and |
| 38 | interval. */ | 38 | update_interval. It cannot be |
| 39 | depended upon in any intermediate | ||
| 40 | intervals traversed by these | ||
| 41 | functions, or any other | ||
| 42 | interval. */ | ||
| 39 | struct interval *left; /* Intervals which precede me. */ | 43 | struct interval *left; /* Intervals which precede me. */ |
| 40 | struct interval *right; /* Intervals which succeed me. */ | 44 | struct interval *right; /* Intervals which succeed me. */ |
| 41 | 45 | ||
diff --git a/src/pdumper.c b/src/pdumper.c index 4d35fd1233f..bba43370a14 100644 --- a/src/pdumper.c +++ b/src/pdumper.c | |||
| @@ -2064,7 +2064,7 @@ dump_interval_tree (struct dump_context *ctx, | |||
| 2064 | INTERVAL tree, | 2064 | INTERVAL tree, |
| 2065 | dump_off parent_offset) | 2065 | dump_off parent_offset) |
| 2066 | { | 2066 | { |
| 2067 | #if CHECK_STRUCTS && !defined (HASH_interval_9110163DA0) | 2067 | #if CHECK_STRUCTS && !defined (HASH_interval_1B38941C37) |
| 2068 | # error "interval changed. See CHECK_STRUCTS comment." | 2068 | # error "interval changed. See CHECK_STRUCTS comment." |
| 2069 | #endif | 2069 | #endif |
| 2070 | // TODO: output tree breadth-first? | 2070 | // TODO: output tree breadth-first? |
diff --git a/src/regex-emacs.c b/src/regex-emacs.c index b667a43a37f..45b4f8107c7 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c | |||
| @@ -4732,8 +4732,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1, | |||
| 4732 | int c1, c2; | 4732 | int c1, c2; |
| 4733 | int s1, s2; | 4733 | int s1, s2; |
| 4734 | int dummy; | 4734 | int dummy; |
| 4735 | ptrdiff_t offset = PTR_TO_OFFSET (d - 1); | 4735 | ptrdiff_t offset = PTR_TO_OFFSET (d); |
| 4736 | ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset); | 4736 | ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1; |
| 4737 | UPDATE_SYNTAX_TABLE (charpos); | 4737 | UPDATE_SYNTAX_TABLE (charpos); |
| 4738 | GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); | 4738 | GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); |
| 4739 | s1 = SYNTAX (c1); | 4739 | s1 = SYNTAX (c1); |
| @@ -4811,8 +4811,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1, | |||
| 4811 | int c1, c2; | 4811 | int c1, c2; |
| 4812 | int s1, s2; | 4812 | int s1, s2; |
| 4813 | int dummy; | 4813 | int dummy; |
| 4814 | ptrdiff_t offset = PTR_TO_OFFSET (d) - 1; | 4814 | ptrdiff_t offset = PTR_TO_OFFSET (d); |
| 4815 | ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset); | 4815 | ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1; |
| 4816 | UPDATE_SYNTAX_TABLE (charpos); | 4816 | UPDATE_SYNTAX_TABLE (charpos); |
| 4817 | GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); | 4817 | GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); |
| 4818 | s1 = SYNTAX (c1); | 4818 | s1 = SYNTAX (c1); |
| @@ -4826,7 +4826,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1, | |||
| 4826 | { | 4826 | { |
| 4827 | PREFETCH_NOLIMIT (); | 4827 | PREFETCH_NOLIMIT (); |
| 4828 | GET_CHAR_AFTER (c2, d, dummy); | 4828 | GET_CHAR_AFTER (c2, d, dummy); |
| 4829 | UPDATE_SYNTAX_TABLE_FORWARD (charpos); | 4829 | UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1); |
| 4830 | s2 = SYNTAX (c2); | 4830 | s2 = SYNTAX (c2); |
| 4831 | 4831 | ||
| 4832 | /* ... and S2 is Sword, and WORD_BOUNDARY_P (C1, C2) | 4832 | /* ... and S2 is Sword, and WORD_BOUNDARY_P (C1, C2) |
| @@ -4890,8 +4890,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp, re_char *string1, | |||
| 4890 | is the character at D, and S2 is the syntax of C2. */ | 4890 | is the character at D, and S2 is the syntax of C2. */ |
| 4891 | int c1, c2; | 4891 | int c1, c2; |
| 4892 | int s1, s2; | 4892 | int s1, s2; |
| 4893 | ptrdiff_t offset = PTR_TO_OFFSET (d) - 1; | 4893 | ptrdiff_t offset = PTR_TO_OFFSET (d); |
| 4894 | ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset); | 4894 | ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1; |
| 4895 | UPDATE_SYNTAX_TABLE (charpos); | 4895 | UPDATE_SYNTAX_TABLE (charpos); |
| 4896 | GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); | 4896 | GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); |
| 4897 | s1 = SYNTAX (c1); | 4897 | s1 = SYNTAX (c1); |
diff --git a/src/syntax.c b/src/syntax.c index dd2f56f2cfa..fe1e2d236b9 100644 --- a/src/syntax.c +++ b/src/syntax.c | |||
| @@ -340,20 +340,6 @@ update_syntax_table (ptrdiff_t charpos, EMACS_INT count, bool init, | |||
| 340 | invalidate = false; | 340 | invalidate = false; |
| 341 | if (!i) | 341 | if (!i) |
| 342 | return; | 342 | return; |
| 343 | /* interval_of updates only ->position of the return value, so | ||
| 344 | update the parents manually to speed up update_interval. */ | ||
| 345 | while (!NULL_PARENT (i)) | ||
| 346 | { | ||
| 347 | if (AM_RIGHT_CHILD (i)) | ||
| 348 | INTERVAL_PARENT (i)->position = i->position | ||
| 349 | - LEFT_TOTAL_LENGTH (i) + TOTAL_LENGTH (i) /* right end */ | ||
| 350 | - TOTAL_LENGTH (INTERVAL_PARENT (i)) | ||
| 351 | + LEFT_TOTAL_LENGTH (INTERVAL_PARENT (i)); | ||
| 352 | else | ||
| 353 | INTERVAL_PARENT (i)->position = i->position - LEFT_TOTAL_LENGTH (i) | ||
| 354 | + TOTAL_LENGTH (i); | ||
| 355 | i = INTERVAL_PARENT (i); | ||
| 356 | } | ||
| 357 | i = gl_state.forward_i; | 343 | i = gl_state.forward_i; |
| 358 | gl_state.b_property = i->position - gl_state.offset; | 344 | gl_state.b_property = i->position - gl_state.offset; |
| 359 | gl_state.e_property = INTERVAL_LAST_POS (i) - gl_state.offset; | 345 | gl_state.e_property = INTERVAL_LAST_POS (i) - gl_state.offset; |