Disallow bool vector operations on mixed-length operands.
[bpt/emacs.git] / src / editfns.c
index 911cd41..d4c1f99 100644 (file)
@@ -1,6 +1,6 @@
 /* Lisp functions pertaining to editing.
 
-Copyright (C) 1985-1987, 1989, 1993-2012 Free Software Foundation, Inc.
+Copyright (C) 1985-1987, 1989, 1993-2013 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -64,7 +64,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 extern Lisp_Object w32_get_internal_run_time (void);
 #endif
 
-static Lisp_Object format_time_string (char const *, ptrdiff_t, EMACS_TIME,
+static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec,
                                       bool, struct tm *);
 static int tm_diff (struct tm *, struct tm *);
 static void update_buffer_properties (ptrdiff_t, ptrdiff_t);
@@ -233,26 +233,12 @@ Beginning of buffer is position (point-min), end is (point-max).
 The return value is POSITION.  */)
   (register Lisp_Object position)
 {
-  ptrdiff_t pos;
-
-  if (MARKERP (position)
-      && current_buffer == XMARKER (position)->buffer)
-    {
-      pos = marker_position (position);
-      if (pos < BEGV)
-       SET_PT_BOTH (BEGV, BEGV_BYTE);
-      else if (pos > ZV)
-       SET_PT_BOTH (ZV, ZV_BYTE);
-      else
-       SET_PT_BOTH (pos, marker_byte_position (position));
-
-      return position;
-    }
-
-  CHECK_NUMBER_COERCE_MARKER (position);
-
-  pos = clip_to_bounds (BEGV, XINT (position), ZV);
-  SET_PT (pos);
+  if (MARKERP (position))
+    set_point_from_marker (position);
+  else if (INTEGERP (position))
+    SET_PT (clip_to_bounds (BEGV, XINT (position), ZV));
+  else
+    wrong_type_argument (Qinteger_or_marker_p, position);
   return position;
 }
 
@@ -373,7 +359,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o
   if (NILP (object))
     XSETBUFFER (object, current_buffer);
   else if (WINDOWP (object))
-    object = XWINDOW (object)->buffer;
+    object = XWINDOW (object)->contents;
 
   if (!BUFFERP (object))
     /* pos-property only makes sense in buffers right now, since strings
@@ -386,6 +372,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o
       ptrdiff_t noverlays;
       Lisp_Object *overlay_vec, tem;
       struct buffer *obuf = current_buffer;
+      USE_SAFE_ALLOCA;
 
       set_buffer_temp (XBUFFER (object));
 
@@ -398,7 +385,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o
         make enough space for all, and try again.  */
       if (noverlays > 40)
        {
-         overlay_vec = alloca (noverlays * sizeof *overlay_vec);
+         SAFE_ALLOCA_LISP (overlay_vec, noverlays);
          noverlays = overlays_around (posn, overlay_vec, noverlays);
        }
       noverlays = sort_overlays (overlay_vec, noverlays, NULL);
@@ -421,10 +408,12 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o
                ; /* The overlay will not cover a char inserted at point.  */
              else
                {
+                 SAFE_FREE ();
                  return tem;
                }
            }
        }
+      SAFE_FREE ();
 
       { /* Now check the text properties.  */
        int stickiness = text_property_stickiness (prop, position, object);
@@ -666,7 +655,8 @@ If the optional argument INHIBIT-CAPTURE-PROPERTY is non-nil, and OLD-POS has
 a non-nil property of that name, then any field boundaries are ignored.
 
 Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil.  */)
-  (Lisp_Object new_pos, Lisp_Object old_pos, Lisp_Object escape_from_edge, Lisp_Object only_in_line, Lisp_Object inhibit_capture_property)
+  (Lisp_Object new_pos, Lisp_Object old_pos, Lisp_Object escape_from_edge,
+   Lisp_Object only_in_line, Lisp_Object inhibit_capture_property)
 {
   /* If non-zero, then the original point, before re-positioning.  */
   ptrdiff_t orig_point = 0;
@@ -732,9 +722,9 @@ Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil.  */)
              /* This is the ONLY_IN_LINE case, check that NEW_POS and
                 FIELD_BOUND are on the same line by seeing whether
                 there's an intervening newline or not.  */
-             || (scan_buffer ('\n',
-                              XFASTINT (new_pos), XFASTINT (field_bound),
-                              fwd ? -1 : 1, &shortage, 1),
+             || (find_newline (XFASTINT (new_pos), -1,
+                               XFASTINT (field_bound), -1,
+                               fwd ? -1 : 1, &shortage, NULL, 1),
                  shortage != 0)))
        /* Constrain NEW_POS to FIELD_BOUND.  */
        new_pos = field_bound;
@@ -819,7 +809,8 @@ This function does not move point.  */)
     CHECK_NUMBER (n);
 
   clipped_n = clip_to_bounds (PTRDIFF_MIN + 1, XINT (n), PTRDIFF_MAX);
-  end_pos = find_before_next_newline (orig, 0, clipped_n - (clipped_n <= 0));
+  end_pos = find_before_next_newline (orig, 0, clipped_n - (clipped_n <= 0),
+                                     NULL);
 
   /* Return END_POS constrained to the current input field.  */
   return Fconstrain_to_field (make_number (end_pos), make_number (orig),
@@ -833,32 +824,27 @@ This function does not move point.  */)
 Lisp_Object
 save_excursion_save (void)
 {
-  Lisp_Object save, *data = xmalloc (word_size * 4);
-
-  data[0] = Fpoint_marker ();
-  /* Do not copy the mark if it points to nowhere.  */
-  data[1] = (XMARKER (BVAR (current_buffer, mark))->buffer
-            ? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
-            : Qnil);
-  /* Selected window if current buffer is shown in it, nil otherwise.  */
-  data[2] = ((XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
-            ? selected_window : Qnil);
-  data[3] = BVAR (current_buffer, mark_active);
-
-  save = make_save_value (data, 4);
-  XSAVE_VALUE (save)->dogc = 1;
-  return save;
+  return make_save_obj_obj_obj_obj
+    (Fpoint_marker (),
+     /* Do not copy the mark if it points to nowhere.  */
+     (XMARKER (BVAR (current_buffer, mark))->buffer
+      ? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
+      : Qnil),
+     /* Selected window if current buffer is shown in it, nil otherwise.  */
+     (EQ (XWINDOW (selected_window)->contents, Fcurrent_buffer ())
+      ? selected_window : Qnil),
+     BVAR (current_buffer, mark_active));
 }
 
 /* Restore saved buffer before leaving `save-excursion' special form.  */
 
-Lisp_Object
+void
 save_excursion_restore (Lisp_Object info)
 {
-  Lisp_Object tem, tem1, omark, nmark, *data = XSAVE_VALUE (info)->pointer;
+  Lisp_Object tem, tem1, omark, nmark;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
-  tem = Fmarker_buffer (data[0]);
+  tem = Fmarker_buffer (XSAVE_OBJECT (info, 0));
   /* If we're unwinding to top level, saved buffer may be deleted.  This
      means that all of its markers are unchained and so tem is nil.  */
   if (NILP (tem))
@@ -870,12 +856,12 @@ save_excursion_restore (Lisp_Object info)
   Fset_buffer (tem);
 
   /* Point marker.  */
-  tem = data[0];
+  tem = XSAVE_OBJECT (info, 0);
   Fgoto_char (tem);
   unchain_marker (XMARKER (tem));
 
   /* Mark marker.  */
-  tem = data[1];
+  tem = XSAVE_OBJECT (info, 1);
   omark = Fmarker_position (BVAR (current_buffer, mark));
   if (NILP (tem))
     unchain_marker (XMARKER (BVAR (current_buffer, mark)));
@@ -887,7 +873,7 @@ save_excursion_restore (Lisp_Object info)
     }
 
   /* Mark active.  */
-  tem = data[3];
+  tem = XSAVE_OBJECT (info, 3);
   tem1 = BVAR (current_buffer, mark_active);
   bset_mark_active (current_buffer, tem);
 
@@ -911,10 +897,10 @@ save_excursion_restore (Lisp_Object info)
   /* If buffer was visible in a window, and a different window was
      selected, and the old selected window is still showing this
      buffer, restore point in that window.  */
-  tem = data[2];
+  tem = XSAVE_OBJECT (info, 2);
   if (WINDOWP (tem)
       && !EQ (tem, selected_window)
-      && (tem1 = XWINDOW (tem)->buffer,
+      && (tem1 = XWINDOW (tem)->contents,
          (/* Window is live...  */
           BUFFERP (tem1)
           /* ...and it shows the current buffer.  */
@@ -925,8 +911,7 @@ save_excursion_restore (Lisp_Object info)
 
  out:
 
-  free_save_value (info);
-  return Qnil;
+  free_misc (info);
 }
 
 DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
@@ -968,7 +953,7 @@ usage: (save-current-buffer &rest BODY)  */)
   return unbind_to (count, Fprogn (args));
 }
 \f
-DEFUN ("buffer-size", Fbufsize, Sbufsize, 0, 1, 0,
+DEFUN ("buffer-size", Fbuffer_size, Sbuffer_size, 0, 1, 0,
        doc: /* Return the number of characters in the current buffer.
 If BUFFER, return the number of characters in that buffer instead.  */)
   (Lisp_Object buffer)
@@ -1421,7 +1406,7 @@ least significant 16 bits.  USEC and PSEC are the microsecond and
 picosecond counts.  */)
   (void)
 {
-  return make_lisp_time (current_emacs_time ());
+  return make_lisp_time (current_timespec ());
 }
 
 DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
@@ -1451,7 +1436,7 @@ does the same thing as `current-time'.  */)
       usecs -= 1000000;
       secs++;
     }
-  return make_lisp_time (make_emacs_time (secs, usecs * 1000));
+  return make_lisp_time (make_timespec (secs, usecs * 1000));
 #else /* ! HAVE_GETRUSAGE  */
 #ifdef WINDOWSNT
   return w32_get_internal_run_time ();
@@ -1482,12 +1467,10 @@ make_time (time_t t)
    UNKNOWN_MODTIME_NSECS; in that case, the Lisp list contains a
    correspondingly negative picosecond count.  */
 Lisp_Object
-make_lisp_time (EMACS_TIME t)
+make_lisp_time (struct timespec t)
 {
-  int ns = EMACS_NSECS (t);
-  return make_time_tail (EMACS_SECS (t),
-                        list2 (make_number (ns / 1000),
-                               make_number (ns % 1000 * 1000)));
+  int ns = t.tv_nsec;
+  return make_time_tail (t.tv_sec, list2i (ns / 1000, ns % 1000 * 1000));
 }
 
 /* Decode a Lisp list SPECIFIED_TIME that represents a time.
@@ -1532,7 +1515,7 @@ disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
    list, generate the corresponding time value.
 
    If RESULT is not null, store into *RESULT the converted time;
-   this can fail if the converted time does not fit into EMACS_TIME.
+   this can fail if the converted time does not fit into struct timespec.
    If *DRESULT is not null, store into *DRESULT the number of
    seconds since the start of the POSIX Epoch.
 
@@ -1540,7 +1523,7 @@ disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
 bool
 decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
                        Lisp_Object psec,
-                       EMACS_TIME *result, double *dresult)
+                       struct timespec *result, double *dresult)
 {
   EMACS_INT hi, lo, us, ps;
   if (! (INTEGERP (high) && INTEGERP (low)
@@ -1568,7 +1551,7 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
          /* Return the greatest representable time that is not greater
             than the requested time.  */
          time_t sec = hi;
-         *result = make_emacs_time ((sec << 16) + lo, us * 1000 + ps / 1000);
+         *result = make_timespec ((sec << 16) + lo, us * 1000 + ps / 1000);
        }
       else
        {
@@ -1586,15 +1569,15 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
 /* Decode a Lisp list SPECIFIED_TIME that represents a time.
    If SPECIFIED_TIME is nil, use the current time.
 
-   Round the time down to the nearest EMACS_TIME value.
+   Round the time down to the nearest struct timespec value.
    Return seconds since the Epoch.
    Signal an error if unsuccessful.  */
-EMACS_TIME
+struct timespec
 lisp_time_argument (Lisp_Object specified_time)
 {
-  EMACS_TIME t;
+  struct timespec t;
   if (NILP (specified_time))
-    t = current_emacs_time ();
+    t = current_timespec ();
   else
     {
       Lisp_Object high, low, usec, psec;
@@ -1616,12 +1599,12 @@ lisp_seconds_argument (Lisp_Object specified_time)
   else
     {
       Lisp_Object high, low, usec, psec;
-      EMACS_TIME t;
+      struct timespec t;
       if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
             && decode_time_components (high, low, make_number (0),
                                        make_number (0), &t, 0)))
        error ("Invalid time specification");
-      return EMACS_SECS (t);
+      return t.tv_sec;
     }
 }
 
@@ -1642,8 +1625,8 @@ or (if you need time as a string) `format-time-string'.  */)
   double t;
   if (NILP (specified_time))
     {
-      EMACS_TIME now = current_emacs_time ();
-      t = EMACS_SECS (now) + EMACS_NSECS (now) / 1e9;
+      struct timespec now = current_timespec ();
+      t = now.tv_sec + now.tv_nsec / 1e9;
     }
   else
     {
@@ -1761,7 +1744,7 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z".
 usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL)  */)
   (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal)
 {
-  EMACS_TIME t = lisp_time_argument (timeval);
+  struct timespec t = lisp_time_argument (timeval);
   struct tm tm;
 
   CHECK_STRING (format_string);
@@ -1773,20 +1756,20 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL)  */)
 
 static Lisp_Object
 format_time_string (char const *format, ptrdiff_t formatlen,
-                   EMACS_TIME t, bool ut, struct tm *tmp)
+                   struct timespec t, bool ut, struct tm *tmp)
 {
   char buffer[4000];
   char *buf = buffer;
   ptrdiff_t size = sizeof buffer;
   size_t len;
   Lisp_Object bufstring;
-  int ns = EMACS_NSECS (t);
+  int ns = t.tv_nsec;
   struct tm *tm;
   USE_SAFE_ALLOCA;
 
   while (1)
     {
-      time_t *taddr = emacs_secs_addr (&t);
+      time_t *taddr = &t.tv_sec;
       block_input ();
 
       synchronize_system_time_locale ();
@@ -1947,7 +1930,7 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE)  */)
          EMACS_INT zone_hr = abszone / (60*60);
          int zone_min = (abszone/60) % 60;
          int zone_sec = abszone % 60;
-         sprintf (tzbuf, tzbuf_format, "-" + (XINT (zone) < 0),
+         sprintf (tzbuf, tzbuf_format, &"-"[XINT (zone) < 0],
                   zone_hr, zone_min, zone_sec);
          tzstring = tzbuf;
        }
@@ -2071,17 +2054,17 @@ in this case, `current-time-zone' returns a list containing nil for
 the data it can't find.  */)
   (Lisp_Object specified_time)
 {
-  EMACS_TIME value;
+  struct timespec value;
   int offset;
   struct tm *t;
   struct tm localtm;
   Lisp_Object zone_offset, zone_name;
 
   zone_offset = Qnil;
-  value = make_emacs_time (lisp_seconds_argument (specified_time), 0);
+  value = make_timespec (lisp_seconds_argument (specified_time), 0);
   zone_name = format_time_string ("%Z", sizeof "%Z" - 1, value, 0, &localtm);
   block_input ();
-  t = gmtime (emacs_secs_addr (&value));
+  t = gmtime (&value.tv_sec);
   if (t)
     offset = tm_diff (&localtm, t);
   unblock_input ();
@@ -2188,6 +2171,7 @@ set_time_zone_rule (const char *tzstring)
       xputenv (set_time_zone_rule_tz[1]);
     }
   tzset ();
+  tzvalbuf_in_environ = 0;
 #endif
 
   if (!tzstring)
@@ -2332,6 +2316,10 @@ to multibyte for insertion (see `unibyte-char-to-multibyte').
 If the current buffer is unibyte, multibyte strings are converted
 to unibyte for insertion.
 
+If an overlay begins at the insertion point, the inserted text falls
+outside the overlay; if a nonempty overlay ends at the insertion
+point, the inserted text falls inside that overlay.
+
 usage: (insert-before-markers &rest ARGS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
@@ -2361,10 +2349,9 @@ usage: (insert-before-markers-and-inherit &rest ARGS)  */)
 }
 \f
 DEFUN ("insert-char", Finsert_char, Sinsert_char, 1, 3,
-       "(list (or (read-char-by-name \"Insert character (Unicode name or hex): \")\
-         (error \"You did not specify a valid character\"))\
-      (prefix-numeric-value current-prefix-arg)\
-      t))",
+       "(list (read-char-by-name \"Insert character (Unicode name or hex): \")\
+              (prefix-numeric-value current-prefix-arg)\
+              t))",
        doc: /* Insert COUNT copies of CHARACTER.
 Interactively, prompt for CHARACTER.  You can specify CHARACTER in one
 of these ways:
@@ -2501,7 +2488,7 @@ make_buffer_string_both (ptrdiff_t start, ptrdiff_t start_byte,
   Lisp_Object result, tem, tem1;
 
   if (start < GPT && GPT < end)
-    move_gap (start);
+    move_gap_both (start, start_byte);
 
   if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
     result = make_uninit_multibyte_string (end - start, end_byte - start_byte);
@@ -2599,7 +2586,7 @@ If narrowing is in effect, this function returns only the visible part
 of the buffer.  */)
   (void)
 {
-  return make_buffer_string (BEGV, ZV, 1);
+  return make_buffer_string_both (BEGV, BEGV_BYTE, ZV, ZV_BYTE, 1);
 }
 
 DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
@@ -2810,18 +2797,16 @@ determines whether case is significant or ignored.  */)
   return make_number (0);
 }
 \f
-static Lisp_Object
+static void
 subst_char_in_region_unwind (Lisp_Object arg)
 {
   bset_undo_list (current_buffer, arg);
-  return arg;
 }
 
-static Lisp_Object
+static void
 subst_char_in_region_unwind_1 (Lisp_Object arg)
 {
   bset_filename (current_buffer, arg);
-  return arg;
 }
 
 DEFUN ("subst-char-in-region", Fsubst_char_in_region,
@@ -2933,7 +2918,7 @@ Both characters must have the same length of multi-byte form.  */)
          else if (!changed)
            {
              changed = -1;
-             modify_region_1 (pos, XINT (end), false);
+             modify_text (pos, XINT (end));
 
              if (! NILP (noundo))
                {
@@ -3109,7 +3094,7 @@ It returns the number of characters changed.  */)
   pos = XINT (start);
   pos_byte = CHAR_TO_BYTE (pos);
   end_pos = XINT (end);
-  modify_region_1 (pos, end_pos, false);
+  modify_text (pos, end_pos);
 
   cnt = 0;
   for (; pos < end_pos; )
@@ -3332,7 +3317,7 @@ save_restriction_save (void)
     }
 }
 
-Lisp_Object
+void
 save_restriction_restore (Lisp_Object data)
 {
   struct buffer *cur = NULL;
@@ -3399,8 +3384,6 @@ save_restriction_restore (Lisp_Object data)
 
   if (cur)
     set_buffer_internal (cur);
-
-  return Qnil;
 }
 
 DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
@@ -3430,18 +3413,15 @@ usage: (save-restriction &rest BODY)  */)
   return unbind_to (count, val);
 }
 \f
-/* Buffer for the most recent text displayed by Fmessage_box.  */
-static char *message_text;
-
-/* Allocated length of that buffer.  */
-static ptrdiff_t message_length;
-
 DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
        doc: /* Display a message at the bottom of the screen.
 The message also goes into the `*Messages*' buffer, if `message-log-max'
 is non-nil.  (In keyboard macros, that's all it does.)
 Return the message.
 
+In batch mode, the message is printed to the standard error stream,
+followed by a newline.
+
 The first argument is a format control string, and the rest are data
 to be formatted under control of the string.  See `format' for details.
 
@@ -3459,14 +3439,14 @@ usage: (message FORMAT-STRING &rest ARGS)  */)
       || (STRINGP (args[0])
          && SBYTES (args[0]) == 0))
     {
-      message (0);
+      message1 (0);
       return args[0];
     }
   else
     {
       register Lisp_Object val;
       val = Fformat (nargs, args);
-      message3 (val, SBYTES (val), STRING_MULTIBYTE (val));
+      message3 (val);
       return val;
     }
 }
@@ -3485,39 +3465,24 @@ usage: (message-box FORMAT-STRING &rest ARGS)  */)
 {
   if (NILP (args[0]))
     {
-      message (0);
+      message1 (0);
       return Qnil;
     }
   else
     {
-      register Lisp_Object val;
-      val = Fformat (nargs, args);
+      Lisp_Object val = Fformat (nargs, args);
 #ifdef HAVE_MENUS
-      /* The MS-DOS frames support popup menus even though they are
-        not FRAME_WINDOW_P.  */
-      if (FRAME_WINDOW_P (XFRAME (selected_frame))
-         || FRAME_MSDOS_P (XFRAME (selected_frame)))
-      {
-       Lisp_Object pane, menu;
-       struct gcpro gcpro1;
-       pane = Fcons (Fcons (build_string ("OK"), Qt), Qnil);
-       GCPRO1 (pane);
-       menu = Fcons (val, pane);
-       Fx_popup_dialog (Qt, menu, Qt);
-       UNGCPRO;
-       return val;
-      }
-#endif /* HAVE_MENUS */
-      /* Copy the data so that it won't move when we GC.  */
-      if (SBYTES (val) > message_length)
-       {
-         ptrdiff_t new_length = SBYTES (val) + 80;
-         message_text = xrealloc (message_text, new_length);
-         message_length = new_length;
-       }
-      memcpy (message_text, SDATA (val), SBYTES (val));
-      message2 (message_text, SBYTES (val),
-               STRING_MULTIBYTE (val));
+      Lisp_Object pane, menu;
+      struct gcpro gcpro1;
+
+      pane = list1 (Fcons (build_string ("OK"), Qt));
+      GCPRO1 (pane);
+      menu = Fcons (val, pane);
+      Fx_popup_dialog (Qt, menu, Qt);
+      UNGCPRO;
+#else /* !HAVE_MENUS */
+      message3 (val);
+#endif
       return val;
     }
 }
@@ -3644,7 +3609,7 @@ usage: (format STRING &rest OBJECTS)  */)
   ptrdiff_t bufsize = sizeof initial_buffer;
   ptrdiff_t max_bufsize = STRING_BYTES_BOUND + 1;
   char *p;
-  Lisp_Object buf_save_value IF_LINT (= {0});
+  ptrdiff_t buf_save_value_index IF_LINT (= 0);
   char *format, *end, *format_start;
   ptrdiff_t formatlen, nchars;
   /* True if the format is multibyte.  */
@@ -3975,7 +3940,7 @@ usage: (format STRING &rest OBJECTS)  */)
                   trailing "d").  */
                pMlen = sizeof pMd - 2
              };
-             verify (0 < USEFUL_PRECISION_MAX);
+             verify (USEFUL_PRECISION_MAX > 0);
 
              int prec;
              ptrdiff_t padding, sprintf_bytes;
@@ -4253,12 +4218,15 @@ usage: (format STRING &rest OBJECTS)  */)
          {
            buf = xmalloc (bufsize);
            sa_must_free = 1;
-           buf_save_value = make_save_value (buf, 0);
-           record_unwind_protect (safe_alloca_unwind, buf_save_value);
+           buf_save_value_index = SPECPDL_INDEX ();
+           record_unwind_protect_ptr (xfree, buf);
            memcpy (buf, initial_buffer, used);
          }
        else
-         XSAVE_VALUE (buf_save_value)->pointer = buf = xrealloc (buf, bufsize);
+         {
+           buf = xrealloc (buf, bufsize);
+           set_unwind_protect_ptr (buf_save_value_index, xfree, buf);
+         }
 
        p = buf + used;
       }
@@ -4523,7 +4491,7 @@ Transposing beyond buffer boundaries is an error.  */)
   (Lisp_Object startr1, Lisp_Object endr1, Lisp_Object startr2, Lisp_Object endr2, Lisp_Object leave_markers)
 {
   register ptrdiff_t start1, end1, start2, end2;
-  ptrdiff_t start1_byte, start2_byte, len1_byte, len2_byte;
+  ptrdiff_t start1_byte, start2_byte, len1_byte, len2_byte, end2_byte;
   ptrdiff_t gap, len1, len_mid, len2;
   unsigned char *start1_addr, *start2_addr, *temp;
 
@@ -4584,20 +4552,22 @@ Transposing beyond buffer boundaries is an error.  */)
      the gap the minimum distance to get it out of the way, and then
      deal with an unbroken array.  */
 
+  start1_byte = CHAR_TO_BYTE (start1);
+  end2_byte = CHAR_TO_BYTE (end2);
+
   /* Make sure the gap won't interfere, by moving it out of the text
      we will operate on.  */
   if (start1 < gap && gap < end2)
     {
       if (gap - start1 < end2 - gap)
-       move_gap (start1);
+       move_gap_both (start1, start1_byte);
       else
-       move_gap (end2);
+       move_gap_both (end2, end2_byte);
     }
 
-  start1_byte = CHAR_TO_BYTE (start1);
   start2_byte = CHAR_TO_BYTE (start2);
   len1_byte = CHAR_TO_BYTE (end1) - start1_byte;
-  len2_byte = CHAR_TO_BYTE (end2) - start2_byte;
+  len2_byte = end2_byte - start2_byte;
 
 #ifdef BYTE_COMBINING_DEBUG
   if (end1 == start2)
@@ -4633,7 +4603,7 @@ Transposing beyond buffer boundaries is an error.  */)
 
   if (end1 == start2)          /* adjacent regions */
     {
-      modify_region_1 (start1, end2, false);
+      modify_text (start1, end2);
       record_change (start1, len1 + len2);
 
       tmp_interval1 = copy_intervals (cur_intv, start1, len1);
@@ -4692,8 +4662,8 @@ Transposing beyond buffer boundaries is an error.  */)
         {
          USE_SAFE_ALLOCA;
 
-          modify_region_1 (start1, end1, false);
-          modify_region_1 (start2, end2, false);
+          modify_text (start1, end1);
+          modify_text (start2, end2);
           record_change (start1, len1);
           record_change (start2, len2);
           tmp_interval1 = copy_intervals (cur_intv, start1, len1);
@@ -4726,7 +4696,7 @@ Transposing beyond buffer boundaries is an error.  */)
         {
          USE_SAFE_ALLOCA;
 
-          modify_region_1 (start1, end2, false);
+          modify_text (start1, end2);
           record_change (start1, (end2 - start1));
           tmp_interval1 = copy_intervals (cur_intv, start1, len1);
           tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
@@ -4759,7 +4729,7 @@ Transposing beyond buffer boundaries is an error.  */)
          USE_SAFE_ALLOCA;
 
           record_change (start1, (end2 - start1));
-          modify_region_1 (start1, end2, false);
+          modify_text (start1, end2);
 
           tmp_interval1 = copy_intervals (cur_intv, start1, len1);
           tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
@@ -4884,12 +4854,10 @@ functions if all the text being accessed has this property.  */);
   defsubr (&Sline_beginning_position);
   defsubr (&Sline_end_position);
 
-/*  defsubr (&Smark); */
-/*  defsubr (&Sset_mark); */
   defsubr (&Ssave_excursion);
   defsubr (&Ssave_current_buffer);
 
-  defsubr (&Sbufsize);
+  defsubr (&Sbuffer_size);
   defsubr (&Spoint_max);
   defsubr (&Spoint_min);
   defsubr (&Spoint_min_marker);