Merge from trunk.
[bpt/emacs.git] / src / buffer.c
index 7030fea..05e96e8 100644 (file)
@@ -27,6 +27,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <setjmp.h>
 #include <unistd.h>
 
+#include <verify.h>
+
 #include "lisp.h"
 #include "intervals.h"
 #include "window.h"
@@ -92,6 +94,11 @@ static Lisp_Object Vbuffer_local_symbols;
 #define PER_BUFFER_SYMBOL(OFFSET) \
       (*(Lisp_Object *)((OFFSET) + (char *) &buffer_local_symbols))
 
+/* Maximum length of an overlay vector.  */
+#define OVERLAY_COUNT_MAX                                              \
+  ((ptrdiff_t) min (MOST_POSITIVE_FIXNUM,                              \
+                   min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Lisp_Object)))
+
 /* Flags indicating which built-in buffer-local variables
    are permanent locals.  */
 static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS];
@@ -145,7 +152,7 @@ Lisp_Object Qmodification_hooks;
 Lisp_Object Qinsert_in_front_hooks;
 Lisp_Object Qinsert_behind_hooks;
 
-static void alloc_buffer_text (struct buffer *, size_t);
+static void alloc_buffer_text (struct buffer *, ptrdiff_t);
 static void free_buffer_text (struct buffer *b);
 static struct Lisp_Overlay * copy_overlays (struct buffer *, struct Lisp_Overlay *);
 static void modify_overlay (struct buffer *, EMACS_INT, EMACS_INT);
@@ -464,8 +471,8 @@ clone_per_buffer_values (struct buffer *from, struct buffer *to)
 
   /* buffer-local Lisp variables start at `undo_list',
      tho only the ones from `name' on are GC'd normally.  */
-  for (offset = PER_BUFFER_VAR_OFFSET (undo_list);
-       offset < sizeof *to;
+  for (offset = PER_BUFFER_VAR_OFFSET (FIRST_FIELD_PER_BUFFER);
+       offset <= PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER);
        offset += sizeof (Lisp_Object))
     {
       Lisp_Object obj;
@@ -823,8 +830,8 @@ reset_buffer_local_variables (register struct buffer *b, int permanent_too)
 
   /* buffer-local Lisp variables start at `undo_list',
      tho only the ones from `name' on are GC'd normally.  */
-  for (offset = PER_BUFFER_VAR_OFFSET (undo_list);
-       offset < sizeof *b;
+  for (offset = PER_BUFFER_VAR_OFFSET (FIRST_FIELD_PER_BUFFER);
+       offset <= PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER);
        offset += sizeof (Lisp_Object))
     {
       int idx = PER_BUFFER_IDX (offset);
@@ -850,8 +857,8 @@ it is in the sequence to be tried) even if a buffer with that name exists.  */)
   (register Lisp_Object name, Lisp_Object ignore)
 {
   register Lisp_Object gentemp, tem;
-  int count;
-  char number[10];
+  EMACS_INT count;
+  char number[INT_BUFSIZE_BOUND (EMACS_INT) + sizeof "<>"];
 
   CHECK_STRING (name);
 
@@ -865,7 +872,7 @@ it is in the sequence to be tried) even if a buffer with that name exists.  */)
   count = 1;
   while (1)
     {
-      sprintf (number, "<%d>", ++count);
+      sprintf (number, "<%"pI"d>", ++count);
       gentemp = concat2 (name, build_string (number));
       tem = Fstring_equal (gentemp, ignore);
       if (!NILP (tem))
@@ -1048,8 +1055,8 @@ No argument or nil as argument means use current buffer as BUFFER.  */)
 
     /* buffer-local Lisp variables start at `undo_list',
        tho only the ones from `name' on are GC'd normally.  */
-    for (offset = PER_BUFFER_VAR_OFFSET (undo_list);
-        offset < sizeof (struct buffer);
+    for (offset = PER_BUFFER_VAR_OFFSET (FIRST_FIELD_PER_BUFFER);
+        offset <= PER_BUFFER_VAR_OFFSET (LAST_FIELD_PER_BUFFER);
         /* sizeof EMACS_INT == sizeof Lisp_Object */
         offset += (sizeof (EMACS_INT)))
       {
@@ -1969,7 +1976,7 @@ validate_region (register Lisp_Object *b, register Lisp_Object *e)
 /* Advance BYTE_POS up to a character boundary
    and return the adjusted position.  */
 
-static int
+static EMACS_INT
 advance_to_char_boundary (EMACS_INT byte_pos)
 {
   int c;
@@ -2516,14 +2523,15 @@ swap_out_buffer_local_variables (struct buffer *b)
    *NEXT_PTR is guaranteed to be not equal to POS, unless it is the
    default (BEGV or ZV).  */
 
-int
-overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, int *len_ptr,
+ptrdiff_t
+overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr,
+            ptrdiff_t *len_ptr,
             EMACS_INT *next_ptr, EMACS_INT *prev_ptr, int change_req)
 {
   Lisp_Object overlay, start, end;
   struct Lisp_Overlay *tail;
-  int idx = 0;
-  int len = *len_ptr;
+  ptrdiff_t idx = 0;
+  ptrdiff_t len = *len_ptr;
   Lisp_Object *vec = *vec_ptr;
   EMACS_INT next = ZV;
   EMACS_INT prev = BEGV;
@@ -2559,10 +2567,10 @@ overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, int *len_ptr,
                 Either make it bigger, or don't store any more in it.  */
              if (extend)
                {
+                 if ((OVERLAY_COUNT_MAX - 4) / 2 < len)
+                   memory_full (SIZE_MAX);
                  /* Make it work with an initial len == 0.  */
-                 len *= 2;
-                 if (len == 0)
-                   len = 4;
+                 len = len * 2 + 4;
                  *len_ptr = len;
                  vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
                  *vec_ptr = vec;
@@ -2602,10 +2610,10 @@ overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, int *len_ptr,
            {
              if (extend)
                {
+                 if ((OVERLAY_COUNT_MAX - 4) / 2 < len)
+                   memory_full (SIZE_MAX);
                  /* Make it work with an initial len == 0.  */
-                 len *= 2;
-                 if (len == 0)
-                   len = 4;
+                 len = len * 2 + 4;
                  *len_ptr = len;
                  vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
                  *vec_ptr = vec;
@@ -2655,15 +2663,15 @@ overlays_at (EMACS_INT pos, int extend, Lisp_Object **vec_ptr, int *len_ptr,
    and we store only as many overlays as will fit.
    But we still return the total number of overlays.  */
 
-static int
+static ptrdiff_t
 overlays_in (EMACS_INT beg, EMACS_INT end, int extend,
-            Lisp_Object **vec_ptr, int *len_ptr,
+            Lisp_Object **vec_ptr, ptrdiff_t *len_ptr,
             EMACS_INT *next_ptr, EMACS_INT *prev_ptr)
 {
   Lisp_Object overlay, ostart, oend;
   struct Lisp_Overlay *tail;
-  int idx = 0;
-  int len = *len_ptr;
+  ptrdiff_t idx = 0;
+  ptrdiff_t len = *len_ptr;
   Lisp_Object *vec = *vec_ptr;
   EMACS_INT next = ZV;
   EMACS_INT prev = BEGV;
@@ -2699,10 +2707,10 @@ overlays_in (EMACS_INT beg, EMACS_INT end, int extend,
                 Either make it bigger, or don't store any more in it.  */
              if (extend)
                {
+                 if ((OVERLAY_COUNT_MAX - 4) / 2 < len)
+                   memory_full (SIZE_MAX);
                  /* Make it work with an initial len == 0.  */
-                 len *= 2;
-                 if (len == 0)
-                   len = 4;
+                 len = len * 2 + 4;
                  *len_ptr = len;
                  vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
                  *vec_ptr = vec;
@@ -2747,10 +2755,10 @@ overlays_in (EMACS_INT beg, EMACS_INT end, int extend,
            {
              if (extend)
                {
+                 if ((OVERLAY_COUNT_MAX - 4) / 2 < len)
+                   memory_full (SIZE_MAX);
                  /* Make it work with an initial len == 0.  */
-                 len *= 2;
-                 if (len == 0)
-                   len = 4;
+                 len = len * 2 + 4;
                  *len_ptr = len;
                  vec = (Lisp_Object *) xrealloc (vec, len * sizeof (Lisp_Object));
                  *vec_ptr = vec;
@@ -2783,7 +2791,7 @@ mouse_face_overlay_overlaps (Lisp_Object overlay)
 {
   EMACS_INT start = OVERLAY_POSITION (OVERLAY_START (overlay));
   EMACS_INT end = OVERLAY_POSITION (OVERLAY_END (overlay));
-  int n, i, size;
+  ptrdiff_t n, i, size;
   Lisp_Object *v, tem;
 
   size = 10;
@@ -2849,7 +2857,7 @@ struct sortvec
 {
   Lisp_Object overlay;
   EMACS_INT beg, end;
-  int priority;
+  EMACS_INT priority;
 };
 
 static int
@@ -2858,21 +2866,21 @@ compare_overlays (const void *v1, const void *v2)
   const struct sortvec *s1 = (const struct sortvec *) v1;
   const struct sortvec *s2 = (const struct sortvec *) v2;
   if (s1->priority != s2->priority)
-    return s1->priority - s2->priority;
+    return s1->priority < s2->priority ? -1 : 1;
   if (s1->beg != s2->beg)
-    return s1->beg - s2->beg;
+    return s1->beg < s2->beg ? -1 : 1;
   if (s1->end != s2->end)
-    return s2->end - s1->end;
+    return s2->end < s1->end ? -1 : 1;
   return 0;
 }
 
 /* Sort an array of overlays by priority.  The array is modified in place.
    The return value is the new size; this may be smaller than the original
    size if some of the overlays were invalid or were window-specific.  */
-int
-sort_overlays (Lisp_Object *overlay_vec, int noverlays, struct window *w)
+ptrdiff_t
+sort_overlays (Lisp_Object *overlay_vec, ptrdiff_t noverlays, struct window *w)
 {
-  int i, j;
+  ptrdiff_t i, j;
   struct sortvec *sortvec;
   sortvec = (struct sortvec *) alloca (noverlays * sizeof (struct sortvec));
 
@@ -2926,15 +2934,15 @@ sort_overlays (Lisp_Object *overlay_vec, int noverlays, struct window *w)
 struct sortstr
 {
   Lisp_Object string, string2;
-  int size;
-  int priority;
+  ptrdiff_t size;
+  EMACS_INT priority;
 };
 
 struct sortstrlist
 {
   struct sortstr *buf; /* An array that expands as needed; never freed.  */
-  int size;            /* Allocated length of that array.  */
-  int used;            /* How much of the array is currently in use.  */
+  ptrdiff_t size;      /* Allocated length of that array.  */
+  ptrdiff_t used;      /* How much of the array is currently in use.  */
   EMACS_INT bytes;             /* Total length of the strings in buf.  */
 };
 
@@ -2955,20 +2963,24 @@ cmp_for_strings (const void *as1, const void *as2)
   struct sortstr *s1 = (struct sortstr *)as1;
   struct sortstr *s2 = (struct sortstr *)as2;
   if (s1->size != s2->size)
-    return s2->size - s1->size;
+    return s2->size < s1->size ? -1 : 1;
   if (s1->priority != s2->priority)
-    return s1->priority - s2->priority;
+    return s1->priority < s2->priority ? -1 : 1;
   return 0;
 }
 
 static void
-record_overlay_string (struct sortstrlist *ssl, Lisp_Object str, Lisp_Object str2, Lisp_Object pri, int size)
+record_overlay_string (struct sortstrlist *ssl, Lisp_Object str,
+                      Lisp_Object str2, Lisp_Object pri, ptrdiff_t size)
 {
   EMACS_INT nbytes;
 
   if (ssl->used == ssl->size)
     {
-      if (ssl->buf)
+      if (min (PTRDIFF_MAX, SIZE_MAX) / (sizeof (struct sortstr) * 2)
+         < ssl->size)
+       memory_full (SIZE_MAX);
+      else if (0 < ssl->size)
        ssl->size *= 2;
       else
        ssl->size = 5;
@@ -3874,9 +3886,8 @@ 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)
 {
-  int noverlays;
+  ptrdiff_t len, noverlays;
   Lisp_Object *overlay_vec;
-  int len;
   Lisp_Object result;
 
   CHECK_NUMBER_COERCE_MARKER (pos);
@@ -3906,9 +3917,8 @@ between BEG and END, or at END provided END denotes the position at the
 end of the buffer.  */)
   (Lisp_Object beg, Lisp_Object end)
 {
-  int noverlays;
+  ptrdiff_t len, noverlays;
   Lisp_Object *overlay_vec;
-  int len;
   Lisp_Object result;
 
   CHECK_NUMBER_COERCE_MARKER (beg);
@@ -3936,11 +3946,9 @@ If there are no overlay boundaries from POS to (point-max),
 the value is (point-max).  */)
   (Lisp_Object pos)
 {
-  int noverlays;
+  ptrdiff_t i, len, noverlays;
   EMACS_INT endpos;
   Lisp_Object *overlay_vec;
-  int len;
-  int i;
 
   CHECK_NUMBER_COERCE_MARKER (pos);
 
@@ -3979,7 +3987,7 @@ the value is (point-min).  */)
 {
   EMACS_INT prevpos;
   Lisp_Object *overlay_vec;
-  int len;
+  ptrdiff_t len;
 
   CHECK_NUMBER_COERCE_MARKER (pos);
 
@@ -4048,7 +4056,8 @@ DEFUN ("overlay-get", Foverlay_get, Soverlay_get, 2, 2, 0,
 }
 
 DEFUN ("overlay-put", Foverlay_put, Soverlay_put, 3, 3, 0,
-       doc: /* Set one property of overlay OVERLAY: give property PROP value VALUE.  */)
+       doc: /* Set one property of overlay OVERLAY: give property PROP value VALUE.
+VALUE will be returned.*/)
   (Lisp_Object overlay, Lisp_Object prop, Lisp_Object value)
 {
   Lisp_Object tail, buffer;
@@ -4457,24 +4466,40 @@ static int mmap_initialized_p;
 #define MMAP_ALLOCATED_P(start, end) 1
 #endif
 
-/* Function prototypes.  */
+/* Perform necessary intializations for the use of mmap.  */
+
+static void
+mmap_init (void)
+{
+#if MAP_ANON == 0
+  /* The value of mmap_fd is initially 0 in temacs, and -1
+     in a dumped Emacs.  */
+  if (mmap_fd <= 0)
+    {
+      /* No anonymous mmap -- we need the file descriptor.  */
+      mmap_fd = open ("/dev/zero", O_RDONLY);
+      if (mmap_fd == -1)
+       fatal ("Cannot open /dev/zero: %s", emacs_strerror (errno));
+    }
+#endif /* MAP_ANON == 0 */
+
+  if (mmap_initialized_p)
+    return;
+  mmap_initialized_p = 1;
 
-static int mmap_free_1 (struct mmap_region *);
-static int mmap_enlarge (struct mmap_region *, int);
-static struct mmap_region *mmap_find (POINTER_TYPE *, POINTER_TYPE *);
-static POINTER_TYPE *mmap_alloc (POINTER_TYPE **, size_t);
-static POINTER_TYPE *mmap_realloc (POINTER_TYPE **, size_t);
-static void mmap_free (POINTER_TYPE **ptr);
-static void mmap_init (void);
+#if MAP_ANON != 0
+  mmap_fd = -1;
+#endif
 
+  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 (start, end)
-     POINTER_TYPE *start, *end;
+mmap_find (POINTER_TYPE *start, POINTER_TYPE *end);
 {
   struct mmap_region *r;
   char *s = (char *) start, *e = (char *) end;
@@ -4503,8 +4528,7 @@ mmap_find (start, end)
    the region.  Value is non-zero if successful.  */
 
 static int
-mmap_free_1 (r)
-     struct mmap_region *r;
+mmap_free_1 (struct mmap_region *r)
 {
   if (r->next)
     r->next->prev = r->prev;
@@ -4527,9 +4551,7 @@ mmap_free_1 (r)
    Value is non-zero if successful.  */
 
 static int
-mmap_enlarge (r, npages)
-     struct mmap_region *r;
-     int npages;
+mmap_enlarge (struct mmap_region *r, int npages)
 {
   char *region_end = (char *) r + r->nbytes_mapped;
   size_t nbytes;
@@ -4593,8 +4615,7 @@ mmap_enlarge (r, npages)
    when Emacs starts.  */
 
 void
-mmap_set_vars (restore_p)
-     int restore_p;
+mmap_set_vars (int restore_p)
 {
   struct mmap_region *r;
 
@@ -4627,9 +4648,7 @@ mmap_set_vars (restore_p)
    return null.  */
 
 static POINTER_TYPE *
-mmap_alloc (var, nbytes)
-     POINTER_TYPE **var;
-     size_t nbytes;
+mmap_alloc (POINTER_TYPE **var, size_t nbytes)
 {
   void *p;
   size_t map;
@@ -4666,15 +4685,29 @@ mmap_alloc (var, nbytes)
 }
 
 
+/* Free a block of relocatable storage whose data is pointed to by
+   PTR.  Store 0 in *PTR to show there's no block allocated.  */
+
+static void
+mmap_free (POINTER_TYPE **var)
+{
+  mmap_init ();
+
+  if (*var)
+    {
+      mmap_free_1 (MMAP_REGION (*var));
+      *var = NULL;
+    }
+}
+
+
 /* Given a pointer at address VAR to data allocated with mmap_alloc,
    resize it to size NBYTES.  Change *VAR to reflect the new block,
    and return this value.  If more memory cannot be allocated, then
    leave *VAR unchanged, and return null.  */
 
 static POINTER_TYPE *
-mmap_realloc (var, nbytes)
-     POINTER_TYPE **var;
-     size_t nbytes;
+mmap_realloc (POINTER_TYPE **var, size_t nbytes)
 {
   POINTER_TYPE *result;
 
@@ -4744,51 +4777,6 @@ mmap_realloc (var, nbytes)
 }
 
 
-/* Free a block of relocatable storage whose data is pointed to by
-   PTR.  Store 0 in *PTR to show there's no block allocated.  */
-
-static void
-mmap_free (var)
-     POINTER_TYPE **var;
-{
-  mmap_init ();
-
-  if (*var)
-    {
-      mmap_free_1 (MMAP_REGION (*var));
-      *var = NULL;
-    }
-}
-
-
-/* Perform necessary intializations for the use of mmap.  */
-
-static void
-mmap_init ()
-{
-#if MAP_ANON == 0
-  /* The value of mmap_fd is initially 0 in temacs, and -1
-     in a dumped Emacs.  */
-  if (mmap_fd <= 0)
-    {
-      /* No anonymous mmap -- we need the file descriptor.  */
-      mmap_fd = open ("/dev/zero", O_RDONLY);
-      if (mmap_fd == -1)
-       fatal ("Cannot open /dev/zero: %s", emacs_strerror (errno));
-    }
-#endif /* MAP_ANON == 0 */
-
-  if (mmap_initialized_p)
-    return;
-  mmap_initialized_p = 1;
-
-#if MAP_ANON != 0
-  mmap_fd = -1;
-#endif
-
-  mmap_page_size = getpagesize ();
-}
-
 #endif /* USE_MMAP_FOR_BUFFERS */
 
 
@@ -4807,7 +4795,7 @@ extern void r_alloc_free (POINTER_TYPE **ptr);
 /* Allocate NBYTES bytes for buffer B's text buffer.  */
 
 static void
-alloc_buffer_text (struct buffer *b, size_t nbytes)
+alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes)
 {
   POINTER_TYPE *p;
 
@@ -4837,8 +4825,8 @@ void
 enlarge_buffer_text (struct buffer *b, EMACS_INT delta)
 {
   POINTER_TYPE *p;
-  size_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1
-                  + delta);
+  ptrdiff_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1
+                     + delta);
   BLOCK_INPUT;
 #if defined USE_MMAP_FOR_BUFFERS
   p = mmap_realloc ((POINTER_TYPE **) &b->text->beg, nbytes);
@@ -4971,7 +4959,7 @@ init_buffer_once (void)
      The local flag bits are in the local_var_flags slot of the buffer.  */
 
   /* Nothing can work if this isn't true */
-  if (sizeof (EMACS_INT) != sizeof (Lisp_Object)) abort ();
+  { verify (sizeof (EMACS_INT) == sizeof (Lisp_Object)); }
 
   /* 0 means not a lisp var, -1 means always local, else mask */
   memset (&buffer_local_flags, 0, sizeof buffer_local_flags);
@@ -5077,7 +5065,7 @@ init_buffer (void)
 {
   char *pwd;
   Lisp_Object temp;
-  int len;
+  ptrdiff_t len;
 
 #ifdef USE_MMAP_FOR_BUFFERS
  {
@@ -5201,39 +5189,26 @@ syms_of_buffer (void)
   staticpro (&Vbuffer_alist);
   staticpro (&Qprotected_field);
   staticpro (&Qpermanent_local);
-  Qpermanent_local_hook = intern_c_string ("permanent-local-hook");
-  staticpro (&Qpermanent_local_hook);
   staticpro (&Qkill_buffer_hook);
-  Qoverlayp = intern_c_string ("overlayp");
-  staticpro (&Qoverlayp);
-  Qevaporate = intern_c_string ("evaporate");
-  staticpro (&Qevaporate);
-  Qmodification_hooks = intern_c_string ("modification-hooks");
-  staticpro (&Qmodification_hooks);
-  Qinsert_in_front_hooks = intern_c_string ("insert-in-front-hooks");
-  staticpro (&Qinsert_in_front_hooks);
-  Qinsert_behind_hooks = intern_c_string ("insert-behind-hooks");
-  staticpro (&Qinsert_behind_hooks);
-  Qget_file_buffer = intern_c_string ("get-file-buffer");
-  staticpro (&Qget_file_buffer);
-  Qpriority = intern_c_string ("priority");
-  staticpro (&Qpriority);
-  Qbefore_string = intern_c_string ("before-string");
-  staticpro (&Qbefore_string);
-  Qafter_string = intern_c_string ("after-string");
-  staticpro (&Qafter_string);
-  Qfirst_change_hook = intern_c_string ("first-change-hook");
-  staticpro (&Qfirst_change_hook);
-  Qbefore_change_functions = intern_c_string ("before-change-functions");
-  staticpro (&Qbefore_change_functions);
-  Qafter_change_functions = intern_c_string ("after-change-functions");
-  staticpro (&Qafter_change_functions);
+
+  DEFSYM (Qpermanent_local_hook, "permanent-local-hook");
+  DEFSYM (Qoverlayp, "overlayp");
+  DEFSYM (Qevaporate, "evaporate");
+  DEFSYM (Qmodification_hooks, "modification-hooks");
+  DEFSYM (Qinsert_in_front_hooks, "insert-in-front-hooks");
+  DEFSYM (Qinsert_behind_hooks, "insert-behind-hooks");
+  DEFSYM (Qget_file_buffer, "get-file-buffer");
+  DEFSYM (Qpriority, "priority");
+  DEFSYM (Qbefore_string, "before-string");
+  DEFSYM (Qafter_string, "after-string");
+  DEFSYM (Qfirst_change_hook, "first-change-hook");
+  DEFSYM (Qbefore_change_functions, "before-change-functions");
+  DEFSYM (Qafter_change_functions, "after-change-functions");
+  DEFSYM (Qkill_buffer_query_functions, "kill-buffer-query-functions");
+
   /* The next one is initialized in init_buffer_once.  */
   staticpro (&Qucs_set_table_for_input);
 
-  Qkill_buffer_query_functions = intern_c_string ("kill-buffer-query-functions");
-  staticpro (&Qkill_buffer_query_functions);
-
   Fput (Qprotected_field, Qerror_conditions,
        pure_cons (Qprotected_field, pure_cons (Qerror, Qnil)));
   Fput (Qprotected_field, Qerror_message,
@@ -6027,8 +6002,7 @@ If any of them returns nil, the buffer is not killed.  */);
               doc: /* Normal hook run before changing the major mode of a buffer.
 The function `kill-all-local-variables' runs this before doing anything else.  */);
   Vchange_major_mode_hook = Qnil;
-  Qchange_major_mode_hook = intern_c_string ("change-major-mode-hook");
-  staticpro (&Qchange_major_mode_hook);
+  DEFSYM (Qchange_major_mode_hook, "change-major-mode-hook");
 
   DEFVAR_LISP ("buffer-list-update-hook", Vbuffer_list_update_hook,
               doc: /* Hook run when the buffer list changes.
@@ -6036,8 +6010,7 @@ Functions running this hook are `get-buffer-create',
 `make-indirect-buffer', `rename-buffer', `kill-buffer',
 `record-buffer' and `unrecord-buffer'.  */);
   Vbuffer_list_update_hook = Qnil;
-  Qbuffer_list_update_hook = intern_c_string ("buffer-list-update-hook");
-  staticpro (&Qbuffer_list_update_hook);
+  DEFSYM (Qbuffer_list_update_hook, "buffer-list-update-hook");
 
   defsubr (&Sbuffer_live_p);
   defsubr (&Sbuffer_list);