]> code.delx.au - gnu-emacs/blobdiff - src/alloc.c
(start_of_text): Don't define #ifdef HAVE_TEXT_START.
[gnu-emacs] / src / alloc.c
index 63463dbbc7f2ff1814c9f08ea57970a36379b5d4..f7544ab0b7c684497f908028b38084ba7171e548 100644 (file)
@@ -1,5 +1,5 @@
 /* Storage allocation and gc for GNU Emacs Lisp interpreter.
-   Copyright (C) 1985, 1986, 1988, 1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1988, 1993 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -17,8 +17,9 @@ You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
+#include <signal.h>
 
-#include "config.h"
+#include <config.h>
 #include "lisp.h"
 #include "intervals.h"
 #include "puresize.h"
@@ -26,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "buffer.h"
 #include "window.h"
 #include "frame.h"
+#include "blockinput.h"
 #endif
 
 #include "syssignal.h"
@@ -43,7 +45,7 @@ do                                                            \
     XSET (val, Lisp_Cons, (char *) address + size);            \
     if ((char *) XCONS (val) != (char *) address + size)       \
       {                                                                \
-       free (address);                                         \
+       xfree (address);                                        \
        memory_full ();                                         \
       }                                                                \
   } while (0)
@@ -149,7 +151,7 @@ memory_full ()
   error ("Memory exhausted");
 }
 
-/* like malloc and realloc but check for no memory left */
+/* like malloc routines but check for no memory and block interrupt input.  */
 
 long *
 xmalloc (size)
@@ -157,7 +159,9 @@ xmalloc (size)
 {
   register long *val;
 
+  BLOCK_INPUT;
   val = (long *) malloc (size);
+  UNBLOCK_INPUT;
 
   if (!val && size) memory_full ();
   return val;
@@ -170,16 +174,102 @@ xrealloc (block, size)
 {
   register long *val;
 
+  BLOCK_INPUT;
   /* We must call malloc explicitly when BLOCK is 0, since some
      reallocs don't do this.  */
   if (! block)
     val = (long *) malloc (size);
   else
     val = (long *) realloc (block, size);
+  UNBLOCK_INPUT;
 
   if (!val && size) memory_full ();
   return val;
 }
+
+void
+xfree (block)
+     long *block;
+{
+  BLOCK_INPUT;
+  free (block);
+  UNBLOCK_INPUT;
+}
+
+\f
+/* Arranging to disable input signals while we're in malloc.
+
+   This only works with GNU malloc.  To help out systems which can't
+   use GNU malloc, all the calls to malloc, realloc, and free
+   elsewhere in the code should be inside a BLOCK_INPUT/UNBLOCK_INPUT
+   pairs; unfortunately, we have no idea what C library functions
+   might call malloc, so we can't really protect them unless you're
+   using GNU malloc.  Fortunately, most of the major operating can use
+   GNU malloc.  */
+
+#ifndef SYSTEM_MALLOC
+extern void * (*__malloc_hook) ();
+static void * (*old_malloc_hook) ();
+extern void * (*__realloc_hook) ();
+static void * (*old_realloc_hook) ();
+extern void (*__free_hook) ();
+static void (*old_free_hook) ();
+
+static void
+emacs_blocked_free (ptr)
+     void *ptr;
+{
+  BLOCK_INPUT;
+  __free_hook = old_free_hook;
+  free (ptr);
+  __free_hook = emacs_blocked_free;
+  UNBLOCK_INPUT;
+}
+
+static void *
+emacs_blocked_malloc (size)
+     unsigned size;
+{
+  void *value;
+
+  BLOCK_INPUT;
+  __malloc_hook = old_malloc_hook;
+  value = (void *) malloc (size);
+  __malloc_hook = emacs_blocked_malloc;
+  UNBLOCK_INPUT;
+
+  return value;
+}
+
+static void *
+emacs_blocked_realloc (ptr, size)
+     void *ptr;
+     unsigned size;
+{
+  void *value;
+
+  BLOCK_INPUT;
+  __realloc_hook = old_realloc_hook;
+  value = (void *) realloc (ptr, size);
+  __realloc_hook = emacs_blocked_realloc;
+  UNBLOCK_INPUT;
+
+  return value;
+}
+
+void
+uninterrupt_malloc ()
+{
+  old_free_hook = __free_hook;
+  __free_hook = emacs_blocked_free;
+
+  old_malloc_hook = __malloc_hook;
+  __malloc_hook = emacs_blocked_malloc;
+
+  old_realloc_hook = __realloc_hook;
+  __realloc_hook = emacs_blocked_realloc;
+}
+#endif
 \f
 /* Interval allocation.  */
 
@@ -226,10 +316,7 @@ make_interval ()
       if (interval_block_index == INTERVAL_BLOCK_SIZE)
        {
          register struct interval_block *newi
-           = (struct interval_block *) malloc (sizeof (struct interval_block));
-
-         if (!newi)
-           memory_full ();
+           = (struct interval_block *) xmalloc (sizeof (struct interval_block));
 
          VALIDATE_LISP_STORAGE (newi, sizeof *newi);
          newi->next = interval_block;
@@ -248,8 +335,9 @@ static int total_free_intervals, total_intervals;
 /* Mark the pointers of one interval. */
 
 static void
-mark_interval (i)
+mark_interval (i, dummy)
      register INTERVAL i;
+     Lisp_Object dummy;
 {
   if (XMARKBIT (i->plist))
     abort ();
@@ -261,17 +349,26 @@ static void
 mark_interval_tree (tree)
      register INTERVAL tree;
 {
-  if (XMARKBIT (tree->plist))
-    return;
+  /* No need to test if this tree has been marked already; this
+     function is always called through the MARK_INTERVAL_TREE macro,
+     which takes care of that.  */
+
+  /* XMARK expands to an assignment; the LHS of an assignment can't be
+     a cast.  */
+  XMARK (* (Lisp_Object *) &tree->parent);
 
-  traverse_intervals (tree, 1, 0, mark_interval);
+  traverse_intervals (tree, 1, 0, mark_interval, Qnil);
 }
 
-#define MARK_INTERVAL_TREE(i) \
-  { if (!NULL_INTERVAL_P (i)) mark_interval_tree (i); }
+#define MARK_INTERVAL_TREE(i)                          \
+  do {                                                 \
+    if (!NULL_INTERVAL_P (i)                           \
+       && ! XMARKBIT ((Lisp_Object) i->parent))        \
+      mark_interval_tree (i);                          \
+  } while (0)
 
 /* The oddity in the call to XUNMARK is necessary because XUNMARK
-   expands to an assigment to its argument, and most C compilers don't
+   expands to an assignment to its argument, and most C compilers don't
    support casts on the left operand of `='.  */
 #define UNMARK_BALANCE_INTERVALS(i)                            \
 {                                                              \
@@ -351,8 +448,7 @@ make_float (float_value)
     {
       if (float_block_index == FLOAT_BLOCK_SIZE)
        {
-         register struct float_block *new = (struct float_block *) malloc (sizeof (struct float_block));
-         if (!new) memory_full ();
+         register struct float_block *new = (struct float_block *) xmalloc (sizeof (struct float_block));
          VALIDATE_LISP_STORAGE (new, sizeof *new);
          new->next = float_block;
          float_block = new;
@@ -426,8 +522,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
     {
       if (cons_block_index == CONS_BLOCK_SIZE)
        {
-         register struct cons_block *new = (struct cons_block *) malloc (sizeof (struct cons_block));
-         if (!new) memory_full ();
+         register struct cons_block *new = (struct cons_block *) xmalloc (sizeof (struct cons_block));
          VALIDATE_LISP_STORAGE (new, sizeof *new);
          new->next = cons_block;
          cons_block = new;
@@ -497,9 +592,7 @@ See also the function `vector'.")
     length = wrong_type_argument (Qnatnump, length);
   sizei = XINT (length);
 
-  p = (struct Lisp_Vector *) malloc (sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object));
-  if (p == 0)
-    memory_full ();
+  p = (struct Lisp_Vector *) xmalloc (sizeof (struct Lisp_Vector) + (sizei - 1) * sizeof (Lisp_Object));
   VALIDATE_LISP_STORAGE (p, 0);
 
   XSET (vector, Lisp_Vector, p);
@@ -616,8 +709,7 @@ Its value and function definition are void, and its property list is nil.")
     {
       if (symbol_block_index == SYMBOL_BLOCK_SIZE)
        {
-         struct symbol_block *new = (struct symbol_block *) malloc (sizeof (struct symbol_block));
-         if (!new) memory_full ();
+         struct symbol_block *new = (struct symbol_block *) xmalloc (sizeof (struct symbol_block));
          VALIDATE_LISP_STORAGE (new, sizeof *new);
          new->next = symbol_block;
          symbol_block = new;
@@ -679,8 +771,7 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
     {
       if (marker_block_index == MARKER_BLOCK_SIZE)
        {
-         struct marker_block *new = (struct marker_block *) malloc (sizeof (struct marker_block));
-         if (!new) memory_full ();
+         struct marker_block *new = (struct marker_block *) xmalloc (sizeof (struct marker_block));
          VALIDATE_LISP_STORAGE (new, sizeof *new);
          new->next = marker_block;
          marker_block = new;
@@ -829,9 +920,8 @@ make_uninit_string (length)
     /* This string gets its own string block */
     {
       register struct string_block *new
-       = (struct string_block *) malloc (sizeof (struct string_block_head) + fullsize);
+       = (struct string_block *) xmalloc (sizeof (struct string_block_head) + fullsize);
       VALIDATE_LISP_STORAGE (new, 0);
-      if (!new) memory_full ();
       consing_since_gc += sizeof (struct string_block_head) + fullsize;
       new->pos = fullsize;
       new->next = large_string_blocks;
@@ -843,8 +933,7 @@ make_uninit_string (length)
     /* Make a new current string block and start it off with this string */
     {
       register struct string_block *new
-       = (struct string_block *) malloc (sizeof (struct string_block));
-      if (!new) memory_full ();
+       = (struct string_block *) xmalloc (sizeof (struct string_block));
       VALIDATE_LISP_STORAGE (new, sizeof *new);
       consing_since_gc += sizeof (struct string_block);
       current_string_block->next = new;
@@ -864,20 +953,24 @@ make_uninit_string (length)
 }
 
 /* Return a newly created vector or string with specified arguments as
-   elements.  If all the arguments are characters, make a string;
-   otherwise, make a vector.  Any number of arguments, even zero
-   arguments, are allowed.  */
+   elements.  If all the arguments are characters that can fit
+   in a string of events, make a string; otherwise, make a vector.
+
+   Any number of arguments, even zero arguments, are allowed.  */
 
 Lisp_Object
-make_array (nargs, args)
+make_event_array (nargs, args)
      register int nargs;
      Lisp_Object *args;
 {
   int i;
 
   for (i = 0; i < nargs; i++)
+    /* The things that fit in a string
+       are characters that are in 0...127,
+       after discarding the meta bit and all the bits above it.  */
     if (XTYPE (args[i]) != Lisp_Int
-       || (unsigned) XINT (args[i]) >= 0400)
+       || (XUINT (args[i]) & ~(-CHAR_META)) >= 0200)
       return Fvector (nargs, args);
 
   /* Since the loop exited, we know that all the things in it are
@@ -886,63 +979,17 @@ make_array (nargs, args)
     Lisp_Object result = Fmake_string (nargs, make_number (0));
     
     for (i = 0; i < nargs; i++)
-      XSTRING (result)->data[i] = XINT (args[i]);
+      {
+       XSTRING (result)->data[i] = XINT (args[i]);
+       /* Move the meta bit to the right place for a string char.  */
+       if (XINT (args[i]) & CHAR_META)
+         XSTRING (result)->data[i] |= 0x80;
+      }
     
     return result;
   }
 }
 \f
-/* Allocation of ropes.  */
-
-/* Note: the user cannot manipulate ropes portably by referring
-   to the chars of the string, because combining two chars to make a GLYPH
-   depends on endianness.  */
-
-DEFUN ("make-rope", Fmake_rope, Smake_rope, 0, MANY, 0,
-  "Return a newly created rope containing the arguments of this function.\n\
-A rope is a string, except that its contents will be treated as an\n\
-array of glyphs, where a glyph is an integer type that may be larger\n\
-than a character.  Emacs is normally configured to use 8-bit glyphs,\n\
-so ropes are normally no different from strings.  But Emacs may be\n\
-configured to use 16-bit glyphs, to allow the use of larger fonts.\n\
-\n\
-Each argument (which must be an integer) specifies one glyph, whatever\n\
-size glyphs may be.\n\
-\n\
-See variable `buffer-display-table' for the uses of ropes.")
-  (nargs, args)
-     register int nargs;
-     Lisp_Object *args;
-{
-  register int i;
-  register Lisp_Object val;
-  register GLYPH *p;
-
-  val = make_uninit_string (nargs * sizeof (GLYPH));
-
-  p = (GLYPH *) XSTRING (val)->data;
-  for (i = 0; i < nargs; i++)
-    {
-      CHECK_NUMBER (args[i], i);
-      p[i] = XFASTINT (args[i]);
-    }
-  return val;
-}
-
-DEFUN ("rope-elt", Frope_elt, Srope_elt, 2, 2, 0,
-  "Return an element of rope R at index N.\n\
-A rope is a string in which each pair of bytes is considered an element.\n\
-See variable `buffer-display-table' for the uses of ropes.")
-  (r, n)
-    Lisp_Object r, n;
-{
-  CHECK_STRING (r, 0);
-  CHECK_NUMBER (n, 1);
-  if ((XSTRING (r)->size / sizeof (GLYPH)) <= XINT (n) || XINT (n) < 0)
-    args_out_of_range (r, n);
-  return ((GLYPH *) XSTRING (r)->data)[XFASTINT (n)];
-}
-\f
 /* Pure storage management.  */
 
 /* Must get an error if pure storage is full,
@@ -964,6 +1011,12 @@ make_pure_string (data, length)
   XSTRING (new)->size = length;
   bcopy (data, XSTRING (new)->data, length);
   XSTRING (new)->data[length] = 0;
+
+  /* We must give strings in pure storage some kind of interval.  So we
+     give them a null one.  */
+#if defined (USE_TEXT_PROPERTIES)
+  XSTRING (new)->intervals = NULL_INTERVAL;
+#endif
   pureptr += (size + sizeof (int) - 1)
             / sizeof (int) * sizeof (int);
   return new;
@@ -992,11 +1045,26 @@ make_pure_float (num)
 {
   register Lisp_Object new;
 
-  /* Make sure that pureptr is aligned on at least a sizeof (double)
-     boundary.  Some architectures (like the sparc) require this, and
-     I suspect that floats are rare enough that it's no tragedy for
-     those that do.  */
-  pureptr = (pureptr + sizeof (num) - 1) & - sizeof (num);
+  /* Make sure that PUREBEG + pureptr is aligned on at least a sizeof
+     (double) boundary.  Some architectures (like the sparc) require
+     this, and I suspect that floats are rare enough that it's no
+     tragedy for those that do.  */
+  {
+    int alignment;
+    char *p = PUREBEG + pureptr;
+
+#ifdef __GNUC__
+#if __GNUC__ >= 2
+    alignment = __alignof (struct Lisp_Float);
+#else
+    alignment = sizeof (struct Lisp_Float);
+#endif
+#else
+    alignment = sizeof (struct Lisp_Float);
+#endif  
+    p = (char *) (((unsigned long) p + alignment - 1) & - alignment);
+    pureptr = p - PUREBEG;
+  }
 
   if (pureptr + sizeof (struct Lisp_Float) > PURESIZE)
     error ("Pure Lisp storage exhausted");
@@ -1164,6 +1232,7 @@ Garbage collection happens automatically if you cons more than\n\
   register struct backtrace *backlist;
   register Lisp_Object tem;
   char *omessage = echo_area_glyphs;
+  int omessage_length = echo_area_glyphs_length;
   char stack_top_variable;
   register int i;
 
@@ -1176,9 +1245,9 @@ Garbage collection happens automatically if you cons more than\n\
       if (i < MAX_SAVE_STACK)
        {
          if (stack_copy == 0)
-           stack_copy = (char *) malloc (stack_copy_size = i);
+           stack_copy = (char *) xmalloc (stack_copy_size = i);
          else if (stack_copy_size < i)
-           stack_copy = (char *) realloc (stack_copy, (stack_copy_size = i));
+           stack_copy = (char *) xrealloc (stack_copy, (stack_copy_size = i));
          if (stack_copy)
            {
              if ((int) (&stack_top_variable - stack_bottom) > 0)
@@ -1305,8 +1374,8 @@ Garbage collection happens automatically if you cons more than\n\
   if (gc_cons_threshold < 10000)
     gc_cons_threshold = 10000;
 
-  if (omessage)
-    message1 (omessage);
+  if (omessage || minibuf_level > 0)
+    message2 (omessage, omessage_length);
   else if (!noninteractive)
     message1 ("Garbage collecting...done");
 
@@ -1391,7 +1460,7 @@ clear_marks ()
   If the object referred to has not been seen yet, recursively mark
   all the references contained in it.
 
-   If the object referenced is a short string, the referrencing slot
+   If the object referenced is a short string, the referencing slot
    is threaded into a chain of such slots, pointed to from
    the `size' field of the string.  The actual string size
    lives in the last slot in the chain.  We recognize the end
@@ -1407,11 +1476,11 @@ mark_object (objptr)
 {
   register Lisp_Object obj;
 
+ loop:
   obj = *objptr;
+ loop2:
   XUNMARK (obj);
 
- loop:
-
   if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE)
       && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure)
     return;
@@ -1464,17 +1533,19 @@ mark_object (objptr)
       {
        register struct Lisp_Vector *ptr = XVECTOR (obj);
        register int size = ptr->size;
+       /* The reason we use ptr1 is to avoid an apparent hardware bug
+          that happens occasionally on the FSF's HP 300s.
+          The bug is that a2 gets clobbered by recursive calls to mark_object.
+          The clobberage seems to happen during function entry,
+          perhaps in the moveml instruction.
+          Yes, this is a crock, but we have to do it.  */
        struct Lisp_Vector *volatile ptr1 = ptr;
        register int i;
 
        if (size & ARRAY_MARK_FLAG) break;   /* Already marked */
        ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
        for (i = 0; i < size; i++)     /* and then mark its elements */
-         {
-           if (ptr != ptr1)
-             abort ();
-           mark_object (&ptr->contents[i]);
-         }
+         mark_object (&ptr1->contents[i]);
       }
       break;
 
@@ -1485,6 +1556,7 @@ mark_object (objptr)
       {
        register struct Lisp_Vector *ptr = XVECTOR (obj);
        register int size = ptr->size;
+       /* See comment above under Lisp_Vector.  */
        struct Lisp_Vector *volatile ptr1 = ptr;
        register int i;
 
@@ -1492,20 +1564,18 @@ mark_object (objptr)
        ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */
        for (i = 0; i < size; i++)     /* and then mark its elements */
          {
-           if (ptr != ptr1)
-             abort ();
            if (i != COMPILED_CONSTANTS)
-             mark_object (&ptr->contents[i]);
+             mark_object (&ptr1->contents[i]);
          }
-       objptr = &ptr->contents[COMPILED_CONSTANTS];
-       obj = *objptr;
+       objptr = &ptr1->contents[COMPILED_CONSTANTS];
        goto loop;
       }
 
 #ifdef MULTI_FRAME
     case Lisp_Frame:
       {
-       register struct frame *ptr = XFRAME (obj);
+       /* See comment above under Lisp_Vector for why this is volatile.  */
+       register struct frame *volatile ptr = XFRAME (obj);
        register int size = ptr->size;
 
        if (size & ARRAY_MARK_FLAG) break;   /* Already marked */
@@ -1518,15 +1588,18 @@ mark_object (objptr)
        mark_object (&ptr->selected_window);
        mark_object (&ptr->minibuffer_window);
        mark_object (&ptr->param_alist);
-       mark_object (&ptr->scrollbars);
-       mark_object (&ptr->condemned_scrollbars);
+       mark_object (&ptr->scroll_bars);
+       mark_object (&ptr->condemned_scroll_bars);
+       mark_object (&ptr->menu_bar_items);
+       mark_object (&ptr->face_alist);
       }
       break;
-#endif /* not MULTI_FRAME */
+#endif /* MULTI_FRAME */
 
     case Lisp_Symbol:
       {
-       register struct Lisp_Symbol *ptr = XSYMBOL (obj);
+       /* See comment above under Lisp_Vector for why this is volatile.  */
+       register struct Lisp_Symbol *volatile ptr = XSYMBOL (obj);
        struct Lisp_Symbol *ptrx;
 
        if (XMARKBIT (ptr->plist)) break;
@@ -1539,9 +1612,13 @@ mark_object (objptr)
        ptr = ptr->next;
        if (ptr)
          {
-           ptrx = ptr;         /* Use pf ptrx avoids compiler bug on Sun */
+           /* For the benefit of the last_marked log.  */
+           objptr = (Lisp_Object *)&XSYMBOL (obj)->next;
+           ptrx = ptr;         /* Use of ptrx avoids compiler bug on Sun */
            XSETSYMBOL (obj, ptrx);
-           goto loop;
+           /* We can't goto loop here because *objptr doesn't contain an
+              actual Lisp_Object with valid datatype field.  */
+           goto loop2;
          }
       }
       break;
@@ -1556,6 +1633,7 @@ mark_object (objptr)
     case Lisp_Cons:
     case Lisp_Buffer_Local_Value:
     case Lisp_Some_Buffer_Local_Value:
+    case Lisp_Overlay:
       {
        register struct Lisp_Cons *ptr = XCONS (obj);
        if (XMARKBIT (ptr->car)) break;
@@ -1564,13 +1642,11 @@ mark_object (objptr)
        if (EQ (ptr->cdr, Qnil))
          {
            objptr = &ptr->car;
-           obj = ptr->car;
-           XUNMARK (obj);
            goto loop;
          }
        mark_object (&ptr->car);
-       objptr = &ptr->cdr;
-       obj = ptr->cdr;
+       /* See comment above under Lisp_Vector for why not use ptr here.  */
+       objptr = &XCONS (obj)->cdr;
        goto loop;
       }
 
@@ -1829,7 +1905,7 @@ gc_sweep ()
          else
            all_buffers = buffer->next;
          next = buffer->next;
-         free (buffer);
+         xfree (buffer);
          buffer = next;
        }
       else
@@ -1870,7 +1946,7 @@ gc_sweep ()
          else
            all_vectors = vector->next;
          next = vector->next;
-         free (vector);
+         xfree (vector);
          vector = next;
        }
       else
@@ -1884,25 +1960,30 @@ gc_sweep ()
   /* Free all "large strings" not marked with ARRAY_MARK_FLAG.  */
   {
     register struct string_block *sb = large_string_blocks, *prev = 0, *next;
+    struct Lisp_String *s;
 
     while (sb)
-      if (!(((struct Lisp_String *)(&sb->chars[0]))->size & ARRAY_MARK_FLAG))
-       {
-         if (prev)
-           prev->next = sb->next;
-         else
-           large_string_blocks = sb->next;
-         next = sb->next;
-         free (sb);
-         sb = next;
-       }
-      else
-       {
-         ((struct Lisp_String *)(&sb->chars[0]))->size
-           &= ~ARRAY_MARK_FLAG & ~MARKBIT;
-         total_string_size += ((struct Lisp_String *)(&sb->chars[0]))->size;
-         prev = sb, sb = sb->next;
-       }
+      {
+       s = (struct Lisp_String *) &sb->chars[0];
+       if (s->size & ARRAY_MARK_FLAG)
+         {
+           ((struct Lisp_String *)(&sb->chars[0]))->size
+             &= ~ARRAY_MARK_FLAG & ~MARKBIT;
+           UNMARK_BALANCE_INTERVALS (s->intervals);
+           total_string_size += ((struct Lisp_String *)(&sb->chars[0]))->size;
+           prev = sb, sb = sb->next;
+         }
+       else
+         {
+           if (prev)
+             prev->next = sb->next;
+           else
+             large_string_blocks = sb->next;
+           next = sb->next;
+           xfree (sb);
+           sb = next;
+         }
+      }
   }
 }
 \f
@@ -1994,6 +2075,18 @@ compact_strings ()
                }
              /* Store the actual size in the size field.  */
              newaddr->size = size;
+
+#ifdef USE_TEXT_PROPERTIES
+             /* Now that the string has been relocated, rebalance its
+                 interval tree, and update the tree's parent pointer. */
+             if (! NULL_INTERVAL_P (newaddr->intervals))
+               {
+                 UNMARK_BALANCE_INTERVALS (newaddr->intervals);
+                 XSET (* (Lisp_Object *) &newaddr->intervals->parent,
+                       Lisp_String,
+                       newaddr);
+               }
+#endif /* USE_TEXT_PROPERTIES */
            }
          pos += STRING_FULLSIZE (size);
        }
@@ -2008,7 +2101,7 @@ compact_strings ()
   while (from_sb)
     {
       to_sb = from_sb->next;
-      free (from_sb);
+      xfree (from_sb);
       from_sb = to_sb;
     }
 
@@ -2023,7 +2116,7 @@ compact_strings ()
        {
          if (from_sb->next = to_sb->next)
            from_sb->next->prev = from_sb;
-         free (to_sb);
+         xfree (to_sb);
        }
       else
        from_sb = to_sb;
@@ -2032,7 +2125,7 @@ compact_strings ()
 \f
 /* Debugging aids.  */
 
-DEFUN ("memory-limit", Fmemory_limit, Smemory_limit, 0, 0, "",
+DEFUN ("memory-limit", Fmemory_limit, Smemory_limit, 0, 0, 0,
   "Return the address of the last byte Emacs has allocated, divided by 1024.\n\
 This may be helpful in debugging Emacs's memory usage.\n\
 We divide the value by 1024 to make sure it fits in a Lisp integer.")
@@ -2130,8 +2223,6 @@ which includes both saved text and other data.");
   defsubr (&Smake_list);
   defsubr (&Smake_vector);
   defsubr (&Smake_string);
-  defsubr (&Smake_rope);
-  defsubr (&Srope_elt);
   defsubr (&Smake_symbol);
   defsubr (&Smake_marker);
   defsubr (&Spurecopy);