use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / buffer.c
index 61b685e..7f0f2cc 100644 (file)
@@ -1,7 +1,6 @@
 /* Buffer manipulation primitives for GNU Emacs.
 
-Copyright (C) 1985-1989, 1993-1995, 1997-2013 Free Software Foundation,
-Inc.
+Copyright (C) 1985-1989, 1993-1995, 1997-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -42,6 +41,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "keymap.h"
 #include "frame.h"
 
+#ifdef WINDOWSNT
+#include "w32heap.h"           /* for mmap_* */
+#endif
+
 struct buffer *current_buffer;         /* The current buffer.  */
 
 /* First buffer in chain of all buffers (in reverse order of creation).
@@ -573,7 +576,8 @@ even if it is dead.  The return value is never nil.  */)
   BUF_END_UNCHANGED (b) = 0;
   BUF_BEG_UNCHANGED (b) = 0;
   *(BUF_GPT_ADDR (b)) = *(BUF_Z_ADDR (b)) = 0; /* Put an anchor '\0'.  */
-  b->text->inhibit_shrinking = 0;
+  b->text->inhibit_shrinking = false;
+  b->text->redisplay = false;
 
   b->newline_cache = 0;
   b->width_run_cache = 0;
@@ -1158,10 +1162,10 @@ DEFUN ("buffer-local-value", Fbuffer_local_value,
        Sbuffer_local_value, 2, 2, 0,
        doc: /* Return the value of VARIABLE in BUFFER.
 If VARIABLE does not have a buffer-local binding in BUFFER, the value
-is the default binding of the variable. */)
+is the default binding of the variable.  */)
   (register Lisp_Object variable, register Lisp_Object buffer)
 {
-  register Lisp_Object result = buffer_local_value_1 (variable, buffer);
+  register Lisp_Object result = buffer_local_value (variable, buffer);
 
   if (EQ (result, Qunbound))
     xsignal1 (Qvoid_variable, variable);
@@ -1174,7 +1178,7 @@ is the default binding of the variable. */)
    locally unbound.  */
 
 Lisp_Object
-buffer_local_value_1 (Lisp_Object variable, Lisp_Object buffer)
+buffer_local_value (Lisp_Object variable, Lisp_Object buffer)
 {
   register struct buffer *buf;
   register Lisp_Object result;
@@ -1336,10 +1340,16 @@ header lines.  This function also forces recomputation of the
 menu bar menus and the frame title.  */)
      (Lisp_Object all)
 {
-  if (!NILP (all) || buffer_window_count (current_buffer))
+  if (!NILP (all))
     {
       update_mode_lines = 10;
-      current_buffer->prevent_redisplay_optimizations_p = 1;
+      /* FIXME: This can't be right.  */
+      current_buffer->prevent_redisplay_optimizations_p = true;
+    }
+  else if (buffer_window_count (current_buffer))
+    {
+      bset_update_mode_line (current_buffer);
+      current_buffer->prevent_redisplay_optimizations_p = true;
     }
   return all;
 }
@@ -1373,7 +1383,6 @@ It is not ensured that mode lines will be updated to show the modified
 state of the current buffer.  Use with care.  */)
   (Lisp_Object flag)
 {
-#ifdef CLASH_DETECTION
   Lisp_Object fn;
 
   /* If buffer becoming modified, lock the file.
@@ -1393,7 +1402,6 @@ state of the current buffer.  Use with care.  */)
       else if (already && NILP (flag))
        unlock_file (fn);
     }
-#endif /* CLASH_DETECTION */
 
   /* Here we have a problem.  SAVE_MODIFF is used here to encode
      buffer-modified-p (as SAVE_MODIFF<MODIFF) as well as
@@ -1713,7 +1721,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
 
   /* Run hooks with the buffer to be killed the current buffer.  */
   {
-    ptrdiff_t count = SPECPDL_INDEX ();
+    dynwind_begin ();
     Lisp_Object arglist[1];
 
     record_unwind_protect (save_excursion_restore, save_excursion_save ());
@@ -1723,8 +1731,11 @@ cleaning up all windows currently displaying the buffer to be killed. */)
        don't kill the buffer.  */
     arglist[0] = Qkill_buffer_query_functions;
     tem = Frun_hook_with_args_until_failure (1, arglist);
-    if (NILP (tem))
-      return unbind_to (count, Qnil);
+    if (NILP (tem)){
+      
+        dynwind_end ();
+        return Qnil;
+      }
 
     /* Query if the buffer is still modified.  */
     if (INTERACTIVE && !NILP (BVAR (b, filename))
@@ -1734,17 +1745,23 @@ cleaning up all windows currently displaying the buffer to be killed. */)
         tem = do_yes_or_no_p (format2 ("Buffer %s modified; kill anyway? ",
                                       BVAR (b, name), make_number (0)));
        UNGCPRO;
-       if (NILP (tem))
-         return unbind_to (count, Qnil);
+       if (NILP (tem)){
+         
+           dynwind_end ();
+         return Qnil;
+         }
       }
 
     /* If the hooks have killed the buffer, exit now.  */
-    if (!BUFFER_LIVE_P (b))
-      return unbind_to (count, Qt);
+    if (!BUFFER_LIVE_P (b)){
+      
+        dynwind_end ();
+        return Qt;
+      }
 
     /* Then run the hooks.  */
     Frun_hooks (1, &Qkill_buffer_hook);
-    unbind_to (count, Qnil);
+    dynwind_end ();
   }
 
   /* If the hooks have killed the buffer, exit now.  */
@@ -1813,10 +1830,8 @@ cleaning up all windows currently displaying the buffer to be killed. */)
 
   /* Now there is no question: we can kill the buffer.  */
 
-#ifdef CLASH_DETECTION
   /* Unlock this buffer's file, if it is locked.  */
   unlock_buffer (b);
-#endif /* CLASH_DETECTION */
 
   GCPRO1 (buffer);
   kill_buffer_processes (buffer);
@@ -1861,6 +1876,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
 
   if (b->base_buffer)
     {
+      INTERVAL i;
       /* Unchain all markers that belong to this indirect buffer.
         Don't unchain the markers that belong to the base buffer
         or its other indirect buffers.  */
@@ -1875,6 +1891,14 @@ cleaning up all windows currently displaying the buffer to be killed. */)
          else
            mp = &m->next;
        }
+      /* Intervals should be owned by the base buffer (Bug#16502).  */
+      i = buffer_intervals (b);
+      if (i)
+       {
+         Lisp_Object owner;
+         XSETBUFFER (owner, b->base_buffer);
+         set_interval_object (i, owner);
+       }
     }
   else
     {
@@ -2060,7 +2084,7 @@ the current buffer's major mode.  */)
   if (NILP (function) || EQ (function, Qfundamental_mode))
     return Qnil;
 
-  count = SPECPDL_INDEX ();
+  dynwind_begin ();
 
   /* To select a nonfundamental mode,
      select the buffer temporarily and then call the mode function.  */
@@ -2070,7 +2094,8 @@ the current buffer's major mode.  */)
   Fset_buffer (buffer);
   call0 (function);
 
-  return unbind_to (count, Qnil);
+  dynwind_end ();
+  return Qnil;
 }
 
 DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
@@ -2171,11 +2196,12 @@ set_buffer_temp (struct buffer *b)
 
 DEFUN ("set-buffer", Fset_buffer, Sset_buffer, 1, 1, 0,
        doc: /* Make buffer BUFFER-OR-NAME current for editing operations.
-BUFFER-OR-NAME may be a buffer or the name of an existing buffer.  See
-also `with-current-buffer' when you want to make a buffer current
+BUFFER-OR-NAME may be a buffer or the name of an existing buffer.
+See also `with-current-buffer' when you want to make a buffer current
 temporarily.  This function does not display the buffer, so its effect
 ends when the current command terminates.  Use `switch-to-buffer' or
-`pop-to-buffer' to switch buffers permanently.  */)
+`pop-to-buffer' to switch buffers permanently.
+The return value is the buffer made current.  */)
   (register Lisp_Object buffer_or_name)
 {
   register Lisp_Object buffer;
@@ -2245,7 +2271,7 @@ validate_region (register Lisp_Object *b, register Lisp_Object *e)
     }
 
   if (! (BEGV <= XINT (*b) && XINT (*e) <= ZV))
-    args_out_of_range (*b, *e);
+    args_out_of_range_3 (Fcurrent_buffer (), *b, *e);
 }
 \f
 /* Advance BYTE_POS up to a character boundary
@@ -2476,6 +2502,8 @@ current buffer is cleared.  */)
   if (narrowed)
     error ("Changing multibyteness in a narrowed buffer");
 
+  invalidate_buffer_caches (current_buffer, BEGV, ZV);
+
   if (NILP (flag))
     {
       ptrdiff_t pos, stop;
@@ -2512,7 +2540,7 @@ current buffer is cleared.  */)
              p = GAP_END_ADDR;
              stop = Z;
            }
-         if (ASCII_BYTE_P (*p))
+         if (ASCII_CHAR_P (*p))
            p++, pos++;
          else if (CHAR_BYTE8_HEAD_P (*p))
            {
@@ -2584,7 +2612,7 @@ current buffer is cleared.  */)
              stop = Z;
            }
 
-         if (ASCII_BYTE_P (*p))
+         if (ASCII_CHAR_P (*p))
            p++, pos++;
          else if (EQ (flag, Qt)
                   && ! CHAR_BYTE8_HEAD_P (*p)
@@ -3128,6 +3156,7 @@ struct sortvec
   Lisp_Object overlay;
   ptrdiff_t beg, end;
   EMACS_INT priority;
+  EMACS_INT spriority;         /* Secondary priority.  */
 };
 
 static int
@@ -3135,19 +3164,28 @@ compare_overlays (const void *v1, const void *v2)
 {
   const struct sortvec *s1 = v1;
   const struct sortvec *s2 = v2;
+  /* Return 1 if s1 should take precedence, -1 if v2 should take precedence,
+     and 0 if they're equal.  */
   if (s1->priority != s2->priority)
     return s1->priority < s2->priority ? -1 : 1;
-  if (s1->beg != s2->beg)
-    return s1->beg < s2->beg ? -1 : 1;
-  if (s1->end != s2->end)
+  /* If the priority is equal, give precedence to the one not covered by the
+     other.  If neither covers the other, obey spriority.  */
+  else if (s1->beg < s2->beg)
+    return (s1->end < s2->end && s1->spriority > s2->spriority ? 1 : -1);
+  else if (s1->beg > s2->beg)
+    return (s1->end > s2->end && s1->spriority < s2->spriority ? -1 : 1);
+  else if (s1->end != s2->end)
     return s2->end < s1->end ? -1 : 1;
-  /* Avoid the non-determinism of qsort by choosing an arbitrary ordering
-     between "equal" overlays.  The result can still change between
-     invocations of Emacs, but it won't change in the middle of
-     `find_field' (bug#6830).  */
-  if (!EQ (s1->overlay, s2->overlay))
+  else if (s1->spriority != s2->spriority)
+    return (s1->spriority < s2->spriority ? -1 : 1);
+  else if (EQ (s1->overlay, s2->overlay))
+    return 0;
+  else
+    /* Avoid the non-determinism of qsort by choosing an arbitrary ordering
+       between "equal" overlays.  The result can still change between
+       invocations of Emacs, but it won't change in the middle of
+       `find_field' (bug#6830).  */
     return XLI (s1->overlay) < XLI (s2->overlay) ? -1 : 1;
-  return 0;
 }
 
 /* Sort an array of overlays by priority.  The array is modified in place.
@@ -3190,10 +3228,23 @@ sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w)
          sortvec[j].beg = OVERLAY_POSITION (OVERLAY_START (overlay));
          sortvec[j].end = OVERLAY_POSITION (OVERLAY_END (overlay));
          tem = Foverlay_get (overlay, Qpriority);
-         if (INTEGERP (tem))
-           sortvec[j].priority = XINT (tem);
-         else
-           sortvec[j].priority = 0;
+         if (NILP (tem))
+           {
+             sortvec[j].priority = 0;
+             sortvec[j].spriority = 0;
+           }
+         else if (INTEGERP (tem))
+           {
+             sortvec[j].priority = XINT (tem);
+             sortvec[j].spriority = 0;
+           }
+         else if (CONSP (tem))
+           {
+             Lisp_Object car = XCAR (tem);
+             Lisp_Object cdr = XCDR (tem);
+             sortvec[j].priority  = INTEGERP (car) ? XINT (car) : 0;
+             sortvec[j].spriority = INTEGERP (cdr) ? XINT (cdr) : 0;
+           }
          j++;
        }
     }
@@ -3291,17 +3342,18 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str,
     }
 }
 
-/* Return the concatenation of the strings associated with overlays that
-   begin or end at POS, ignoring overlays that are specific to a window
-   other than W.  The strings are concatenated in the appropriate order:
-   shorter overlays nest inside longer ones, and higher priority inside
-   lower.  Normally all of the after-strings come first, but zero-sized
-   overlays have their after-strings ride along with the before-strings
-   because it would look strange to print them inside-out.
+/* Concatenate the strings associated with overlays that begin or end
+   at POS, ignoring overlays that are specific to windows other than W.
+   The strings are concatenated in the appropriate order: shorter
+   overlays nest inside longer ones, and higher priority inside lower.
+   Normally all of the after-strings come first, but zero-sized
+   overlays have their after-strings ride along with the
+   before-strings because it would look strange to print them
+   inside-out.
 
-   Returns the string length, and stores the contents indirectly through
-   PSTR, if that variable is non-null.  The string may be overwritten by
-   subsequent calls.  */
+   Returns the concatenated string's length, and return the pointer to
+   that string via PSTR, if that variable is non-NULL.  The storage of
+   the concatenated strings may be overwritten by subsequent calls.  */
 
 ptrdiff_t
 overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
@@ -3812,7 +3864,7 @@ DEFUN ("overlayp", Foverlayp, Soverlayp, 1, 1, 0,
 }
 
 DEFUN ("make-overlay", Fmake_overlay, Smake_overlay, 2, 5, 0,
-       doc: /* Create a new overlay with range BEG to END in BUFFER.
+       doc: /* Create a new overlay with range BEG to END in BUFFER and return it.
 If omitted, BUFFER defaults to the current buffer.
 BEG and END may be integers or markers.
 The fourth arg FRONT-ADVANCE, if non-nil, makes the marker
@@ -3895,17 +3947,7 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
 
   BUF_COMPUTE_UNCHANGED (buf, start, end);
 
-  /* If BUF is visible, consider updating the display if ...  */
-  if (buffer_window_count (buf) > 0)
-    {
-      /* ... it's visible in other window than selected,  */
-      if (buf != XBUFFER (XWINDOW (selected_window)->contents))
-       windows_or_buffers_changed = 11;
-      /* ... or if we modify an overlay at the end of the buffer
-        and so we cannot be sure that window end is still valid.  */
-      else if (end >= ZV && start <= ZV)
-       windows_or_buffers_changed = 12;
-    }
+  bset_redisplay (buf);
 
   ++BUF_OVERLAY_MODIFF (buf);
 }
@@ -3948,7 +3990,7 @@ buffer.  */)
 {
   struct buffer *b, *ob = 0;
   Lisp_Object obuffer;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
   ptrdiff_t n_beg, n_end, o_beg IF_LINT (= 0), o_end IF_LINT (= 0);
 
   CHECK_OVERLAY (overlay);
@@ -4020,8 +4062,12 @@ buffer.  */)
 
   /* Delete the overlay if it is empty after clipping and has the
      evaporate property.  */
-  if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate)))
-    return unbind_to (count, Fdelete_overlay (overlay));
+  if (n_beg == n_end && !NILP (Foverlay_get (overlay, Qevaporate))){
+    
+      Lisp_Object tem0 = Fdelete_overlay (overlay);
+      dynwind_end ();
+      return tem0;
+    }
 
   /* Put the overlay into the new buffer's overlay lists, first on the
      wrong list.  */
@@ -4039,7 +4085,8 @@ buffer.  */)
   /* This puts it in the right list, and in the right order.  */
   recenter_overlay_lists (b, b->overlay_center);
 
-  return unbind_to (count, overlay);
+  dynwind_end ();
+  return overlay;
 }
 
 DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
@@ -4048,13 +4095,15 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
 {
   Lisp_Object buffer;
   struct buffer *b;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
 
   CHECK_OVERLAY (overlay);
 
   buffer = Fmarker_buffer (OVERLAY_START (overlay));
-  if (NILP (buffer))
+  if (NILP (buffer)) {
+    dynwind_end ();
     return Qnil;
+  }
 
   b = XBUFFER (buffer);
   specbind (Qinhibit_quit, Qt);
@@ -4071,7 +4120,8 @@ DEFUN ("delete-overlay", Fdelete_overlay, Sdelete_overlay, 1, 1, 0,
          || !NILP (Foverlay_get (overlay, Qafter_string))))
     b->prevent_redisplay_optimizations_p = 1;
 
-  return unbind_to (count, Qnil);
+  dynwind_end ();
+  return Qnil;
 }
 
 DEFUN ("delete-all-overlays", Fdelete_all_overlays, Sdelete_all_overlays, 0, 1, 0,
@@ -4136,9 +4186,10 @@ OVERLAY.  */)
 }
 
 \f
-DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0,
-       doc: /* Return a list of the overlays that contain the character at POS.  */)
-  (Lisp_Object pos)
+DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 2, 0,
+       doc: /* Return a list of the overlays that contain the character at POS.
+If SORTED is non-nil, then sort them by decreasing priority.  */)
+  (Lisp_Object pos, Lisp_Object sorted)
 {
   ptrdiff_t len, noverlays;
   Lisp_Object *overlay_vec;
@@ -4158,6 +4209,10 @@ DEFUN ("overlays-at", Foverlays_at, Soverlays_at, 1, 1, 0,
   noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
                           NULL, NULL, 0);
 
+  if (!NILP (sorted))
+    noverlays = sort_overlays (overlay_vec, noverlays,
+                              WINDOWP (sorted) ? XWINDOW (sorted) : NULL);
+
   /* Make a list of them all.  */
   result = Flist (noverlays, overlay_vec);
 
@@ -4599,7 +4654,8 @@ evaporate_overlays (ptrdiff_t pos)
                         Allocation with mmap
  ***********************************************************************/
 
-#ifdef USE_MMAP_FOR_BUFFERS
+/* Note: WINDOWSNT implements this stuff on w32heap.c.  */
+#if defined USE_MMAP_FOR_BUFFERS && !defined WINDOWSNT
 
 #include <sys/mman.h>
 
@@ -4665,11 +4721,6 @@ static struct mmap_region *mmap_regions;
 
 static int mmap_fd;
 
-/* Temporary storage for mmap_set_vars, see there.  */
-
-static struct mmap_region *mmap_regions_1;
-static int mmap_fd_1;
-
 /* Page size on this system.  */
 
 static int mmap_page_size;
@@ -4741,36 +4792,6 @@ mmap_init (void)
   mmap_page_size = getpagesize ();
 }
 
-/* Return a region overlapping address range START...END, or null if
-   none.  END is not including, i.e. the last byte in the range
-   is at END - 1.  */
-
-static struct mmap_region *
-mmap_find (void *start, void *end)
-{
-  struct mmap_region *r;
-  char *s = start, *e = end;
-
-  for (r = mmap_regions; r; r = r->next)
-    {
-      char *rstart = (char *) r;
-      char *rend   = rstart + r->nbytes_mapped;
-
-      if (/* First byte of range, i.e. START, in this region?  */
-         (s >= rstart && s < rend)
-         /* Last byte of range, i.e. END - 1, in this region?  */
-         || (e > rstart && e <= rend)
-         /* First byte of this region in the range?  */
-         || (rstart >= s && rstart < e)
-         /* Last byte of this region in the range?  */
-         || (rend > s && rend <= e))
-       break;
-    }
-
-  return r;
-}
-
-
 /* Unmap a region.  P is a pointer to the start of the user-araa of
    the region.  */
 
@@ -4847,38 +4868,6 @@ mmap_enlarge (struct mmap_region *r, int npages)
 }
 
 
-/* Set or reset variables holding references to mapped regions.
-   If not RESTORE_P, set all variables to null.  If RESTORE_P, set all
-   variables to the start of the user-areas of mapped regions.
-
-   This function is called from Fdump_emacs to ensure that the dumped
-   Emacs doesn't contain references to memory that won't be mapped
-   when Emacs starts.  */
-
-void
-mmap_set_vars (bool restore_p)
-{
-  struct mmap_region *r;
-
-  if (restore_p)
-    {
-      mmap_regions = mmap_regions_1;
-      mmap_fd = mmap_fd_1;
-      for (r = mmap_regions; r; r = r->next)
-       *r->var = MMAP_USER_AREA (r);
-    }
-  else
-    {
-      for (r = mmap_regions; r; r = r->next)
-       *r->var = NULL;
-      mmap_regions_1 = mmap_regions;
-      mmap_regions = NULL;
-      mmap_fd_1 = mmap_fd;
-      mmap_fd = -1;
-    }
-}
-
-
 /* Allocate a block of storage large enough to hold NBYTES bytes of
    data.  A pointer to the data is returned in *VAR.  VAR is thus the
    address of some variable which will use the data area.
@@ -5039,7 +5028,7 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes)
 #elif defined REL_ALLOC
   p = r_alloc ((void **) &b->text->beg, nbytes);
 #else
-  p = xmalloc (nbytes);
+  p = xmalloc_atomic (nbytes);
 #endif
 
   if (p == NULL)
@@ -5296,23 +5285,57 @@ init_buffer_once (void)
 }
 
 void
-init_buffer (void)
+init_buffer (int initialized)
 {
   char *pwd;
   Lisp_Object temp;
   ptrdiff_t len;
 
 #ifdef USE_MMAP_FOR_BUFFERS
- {
-   /* When using the ralloc implementation based on mmap(2), buffer
-      text pointers will have been set to null in the dumped Emacs.
-      Map new memory.  */
-   struct buffer *b;
-
-   FOR_EACH_BUFFER (b)
-     if (b->text->beg == NULL)
-       enlarge_buffer_text (b, 0);
- }
+  if (initialized)
+    {
+      struct buffer *b;
+
+#ifndef WINDOWSNT
+      /* These must be reset in the dumped Emacs, to avoid stale
+        references to mmap'ed memory from before the dump.
+
+        WINDOWSNT doesn't need this because it doesn't track mmap'ed
+        regions by hand (see w32heap.c, which uses system APIs for
+        that purpose), and thus doesn't use mmap_regions.  */
+      mmap_regions = NULL;
+      mmap_fd = -1;
+#endif
+
+      /* The dumped buffers reference addresses of buffer text
+        recorded by temacs, that cannot be used by the dumped Emacs.
+        We map new memory for their text here.
+
+        Implementation note: the buffers we carry from temacs are:
+        " prin1", "*scratch*", " *Minibuf-0*", "*Messages*", and
+        " *code-conversion-work*".  They are created by
+        init_buffer_once and init_window_once (which are not called
+        in the dumped Emacs), and by the first call to coding.c routines.  */
+      FOR_EACH_BUFFER (b)
+        {
+         b->text->beg = NULL;
+         enlarge_buffer_text (b, 0);
+       }
+    }
+  else
+    {
+      struct buffer *b;
+
+      /* Only buffers with allocated buffer text should be present at
+        this point in temacs.  */
+      FOR_EACH_BUFFER (b)
+        {
+         eassert (b->text->beg != NULL);
+       }
+    }
+#else  /* not USE_MMAP_FOR_BUFFERS */
+  /* Avoid compiler warnings.  */
+  initialized = initialized;
 #endif /* USE_MMAP_FOR_BUFFERS */
 
   Fset_buffer (Fget_buffer_create (build_string ("*scratch*")));
@@ -5405,6 +5428,8 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
 void
 syms_of_buffer (void)
 {
+#include "buffer.x"
+
   staticpro (&last_overlay_modification_hooks);
   last_overlay_modification_hooks
     = Fmake_vector (make_number (10), Qnil);
@@ -6122,6 +6147,8 @@ If the value of the variable is t, undo information is not recorded.  */);
   DEFVAR_PER_BUFFER ("cache-long-scans", &BVAR (current_buffer, cache_long_scans), Qnil,
                     doc: /* Non-nil means that Emacs should use caches in attempt to speedup buffer scans.
 
+There is no reason to set this to nil except for debugging purposes.
+
 Normally, the line-motion functions work by scanning the buffer for
 newlines.  Columnar operations (like `move-to-column' and
 `compute-motion') also work by scanning the buffer, summing character
@@ -6171,15 +6198,16 @@ same format as a regular save would use.  */);
   DEFVAR_PER_BUFFER ("buffer-invisibility-spec",
                     &BVAR (current_buffer, invisibility_spec), Qnil,
                     doc: /* Invisibility spec of this buffer.
-The default is t, which means that text is invisible
-if it has a non-nil `invisible' property.
-If the value is a list, a text character is invisible if its `invisible'
-property is an element in that list (or is a list with members in common).
-If an element is a cons cell of the form (PROP . ELLIPSIS),
-then characters with property value PROP are invisible,
-and they have an ellipsis as well if ELLIPSIS is non-nil.
-Setting this variable is very fast, much faster than scanning all the
-text in the buffer looking for properties to change.  */);
+The default is t, which means that text is invisible if it has a non-nil
+`invisible' property.
+This variable can also be a list.  The list can have two kinds of elements:
+`ATOM' and `(ATOM . ELLIPSIS)'.  A text character is invisible if its
+`invisible' property is `ATOM', or has an `invisible' property that is a list
+that contains `ATOM'.
+If the `(ATOM . ELLIPSIS)' form is used, and `ELLIPSIS' is non-nil, an
+ellipsis will be displayed after the invisible characters.
+Setting this variable is very fast, much faster than scanning all the text in
+the buffer looking for properties to change.  */);
 
   DEFVAR_PER_BUFFER ("buffer-display-count",
                     &BVAR (current_buffer, display_count), Qintegerp,
@@ -6273,61 +6301,11 @@ The function `kill-all-local-variables' runs this before doing anything else.  *
 
   DEFVAR_LISP ("buffer-list-update-hook", Vbuffer_list_update_hook,
               doc: /* Hook run when the buffer list changes.
-Functions running this hook are `get-buffer-create',
+Functions running this hook are, `get-buffer-create',
 `make-indirect-buffer', `rename-buffer', `kill-buffer',
-and `bury-buffer-internal'.  */);
+`bury-buffer-internal' and `select-window'.  */);
   Vbuffer_list_update_hook = Qnil;
   DEFSYM (Qbuffer_list_update_hook, "buffer-list-update-hook");
-
-  defsubr (&Sbuffer_live_p);
-  defsubr (&Sbuffer_list);
-  defsubr (&Sget_buffer);
-  defsubr (&Sget_file_buffer);
-  defsubr (&Sget_buffer_create);
-  defsubr (&Smake_indirect_buffer);
-  defsubr (&Sgenerate_new_buffer_name);
-  defsubr (&Sbuffer_name);
-  defsubr (&Sbuffer_file_name);
-  defsubr (&Sbuffer_base_buffer);
-  defsubr (&Sbuffer_local_value);
-  defsubr (&Sbuffer_local_variables);
-  defsubr (&Sbuffer_modified_p);
-  defsubr (&Sforce_mode_line_update);
-  defsubr (&Sset_buffer_modified_p);
-  defsubr (&Sbuffer_modified_tick);
-  defsubr (&Sbuffer_chars_modified_tick);
-  defsubr (&Srename_buffer);
-  defsubr (&Sother_buffer);
-  defsubr (&Sbuffer_enable_undo);
-  defsubr (&Skill_buffer);
-  defsubr (&Sbury_buffer_internal);
-  defsubr (&Sset_buffer_major_mode);
-  defsubr (&Scurrent_buffer);
-  defsubr (&Sset_buffer);
-  defsubr (&Sbarf_if_buffer_read_only);
-  defsubr (&Serase_buffer);
-  defsubr (&Sbuffer_swap_text);
-  defsubr (&Sset_buffer_multibyte);
-  defsubr (&Skill_all_local_variables);
-
-  defsubr (&Soverlayp);
-  defsubr (&Smake_overlay);
-  defsubr (&Sdelete_overlay);
-  defsubr (&Sdelete_all_overlays);
-  defsubr (&Smove_overlay);
-  defsubr (&Soverlay_start);
-  defsubr (&Soverlay_end);
-  defsubr (&Soverlay_buffer);
-  defsubr (&Soverlay_properties);
-  defsubr (&Soverlays_at);
-  defsubr (&Soverlays_in);
-  defsubr (&Snext_overlay_change);
-  defsubr (&Sprevious_overlay_change);
-  defsubr (&Soverlay_recenter);
-  defsubr (&Soverlay_lists);
-  defsubr (&Soverlay_get);
-  defsubr (&Soverlay_put);
-  defsubr (&Srestore_buffer_modified_p);
 }
 
 void