summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog7
-rw-r--r--src/buffer.c11
-rw-r--r--src/ralloc.c28
3 files changed, 46 insertions, 0 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index e7d44c35b51..56bb534e457 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2008-12-24 Jason Rumney <jasonr@gnu.org>
+
+ * ralloc.c (r_alloc_reset_variable): New function.
+
+ * buffer.c (Fbuffer_swap_text) [REL_ALLOC]: Reset ralloc's internal
+ record of what points where.
+
2008-12-22 Dan Nicolaescu <dann@ics.uci.edu>
* minibuf.c (read_minibuf): Follow the non-interactive case when
diff --git a/src/buffer.c b/src/buffer.c
index 110cb4f7faf..33667b79ead 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2182,6 +2182,10 @@ advance_to_char_boundary (byte_pos)
return byte_pos;
}
+#ifdef REL_ALLOC
+extern void r_alloc_reset_variable P_ ((PTR *, PTR *));
+#endif /* REL_ALLOC */
+
DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
1, 1, 0,
doc: /* Swap the text between current buffer and BUFFER. */)
@@ -2223,6 +2227,13 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
swapfield (own_text, struct buffer_text);
eassert (current_buffer->text == &current_buffer->own_text);
eassert (other_buffer->text == &other_buffer->own_text);
+#ifdef REL_ALLOC
+ r_alloc_reset_variable ((PTR *) &current_buffer->own_text.beg,
+ (PTR *) &other_buffer->own_text.beg);
+ r_alloc_reset_variable ((PTR *) &other_buffer->own_text.beg,
+ (PTR *) &current_buffer->own_text.beg);
+#endif /* REL_ALLOC */
+
swapfield (pt, EMACS_INT);
swapfield (pt_byte, EMACS_INT);
swapfield (begv, EMACS_INT);
diff --git a/src/ralloc.c b/src/ralloc.c
index 30ed888697f..61f7aff95f5 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -1223,6 +1223,34 @@ r_alloc_check ()
#endif /* DEBUG */
+/* Update the internal record of which variable points to some data to NEW.
+ Used by buffer-swap-text in Emacs to restore consistency after it
+ swaps the buffer text between two buffer objects. The OLD pointer
+ is checked to ensure that memory corruption does not occur due to
+ misuse. */
+void
+r_alloc_reset_variable (old, new)
+ POINTER *old, *new;
+{
+ bloc_ptr bloc = first_bloc;
+
+ /* Find the bloc that corresponds to the data pointed to by pointer.
+ find_bloc cannot be used, as it has internal consistency checks
+ which fail when the variable needs reseting. */
+ while (bloc != NIL_BLOC)
+ {
+ if (bloc->data == *new)
+ break;
+
+ bloc = bloc->next;
+ }
+
+ if (bloc == NIL_BLOC || bloc->variable != old)
+ abort ();
+
+ /* Update variable to point to the new location. */
+ bloc->variable = new;
+}
/***********************************************************************