diff src/insdel.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents de805c49cfc1
children 11054d720c21
line wrap: on
line diff
--- a/src/insdel.c	Mon Aug 13 11:19:22 2007 +0200
+++ b/src/insdel.c	Mon Aug 13 11:20:41 2007 +0200
@@ -200,6 +200,7 @@
 
 #include <config.h>
 #include "lisp.h"
+#include <limits.h>
 
 #include "buffer.h"
 #include "device.h"
@@ -303,64 +304,65 @@
    the equivalent length in characters. */
 
 Charcount
-bytecount_to_charcount (const Bufbyte *ptr, Bytecount len)
+bytecount_to_charcount (CONST Bufbyte *ptr, Bytecount len)
 {
   Charcount count = 0;
-  const Bufbyte *end = ptr + len;
-
-#if SIZEOF_LONG == 8
-# define STRIDE_TYPE long
-# define HIGH_BIT_MASK 0x8080808080808080UL
-#elif SIZEOF_LONG_LONG == 8 && !(defined (i386) || defined (__i386__))
-# define STRIDE_TYPE long long
-# define HIGH_BIT_MASK 0x8080808080808080ULL
-#elif SIZEOF_LONG == 4
-# define STRIDE_TYPE long
-# define HIGH_BIT_MASK 0x80808080UL
-#else
-# error Add support for 128-bit systems here
-#endif
-
-#define ALIGN_BITS ((EMACS_UINT) (ALIGNOF (STRIDE_TYPE) - 1))
-#define ALIGN_MASK (~ ALIGN_BITS)
-#define ALIGNED(ptr) ((((EMACS_UINT) ptr) & ALIGN_BITS) == 0)
-#define STRIDE sizeof (STRIDE_TYPE)
-
+  CONST Bufbyte *end = ptr + len;
+
+#if (LONGBITS == 32 || LONGBITS == 64)
+
+# if (LONGBITS == 32)
+#  define LONG_BYTES 4
+#  define ALIGN_MASK 0xFFFFFFFCU
+#  define HIGH_BIT_MASK 0x80808080U
+# else
+#  define LONG_BYTES 8
+#  define ALIGN_MASK 0xFFFFFFFFFFFFFFF8UL
+   /* I had a dream, I was being overrun with early Intel processors ... */
+#  define HIGH_BIT_MASK 0x8080808080808080UL
+# endif
+
+  /* When we have a large number of bytes to scan, we can be trickier
+     and significantly faster by scanning them in chunks of the CPU word
+     size (assuming that they're all ASCII -- we cut out as soon as
+     we find something non-ASCII). */
+  if (len >= 12)
+    {
+      /* Determine the section in the middle of the string that's
+	 amenable to this treatment.  Everything has to be aligned
+	 on CPU word boundaries. */
+      CONST Bufbyte *aligned_ptr =
+	(CONST Bufbyte *) (((unsigned long) (ptr + LONG_BYTES - 1)) &
+			   ALIGN_MASK);
+      CONST Bufbyte *aligned_end =
+	(CONST Bufbyte *) (((unsigned long) end) & ALIGN_MASK);
+
+      /* Handle unaligned stuff at the beginning. */
+      while (ptr < aligned_ptr)
+	{
+	  if (!BYTE_ASCII_P (*ptr))
+	    goto bail;
+	  count++, ptr++;
+	}
+      /* Now do it. */
+      while (ptr < aligned_end)
+	{
+
+	  if ((* (unsigned long *) ptr) & HIGH_BIT_MASK)
+	    goto bail;
+	  ptr += LONG_BYTES;
+	  count += LONG_BYTES;
+	}
+    }
+
+#endif /* LONGBITS == 32 || LONGBITS == 64 */
+
+ bail:
   while (ptr < end)
     {
-      if (BYTE_ASCII_P (*ptr))
-	{
-	  /* optimize for long stretches of ASCII */
-	  if (! ALIGNED (ptr))
-	    ptr++, count++;
-	  else
-	    {
-	      const unsigned STRIDE_TYPE *ascii_end =
-		(const unsigned STRIDE_TYPE *) ptr;
-	      /* This loop screams, because we can typically
-		 detect ASCII characters 8 at a time. */
-	      while ((const Bufbyte *) ascii_end + STRIDE <= end
-		     && !(*ascii_end & HIGH_BIT_MASK))
-		ascii_end++;
-	      if ((Bufbyte *) ascii_end == ptr)
-		ptr++, count++;
-	      else
-		{
-		  count += (Bufbyte *) ascii_end - ptr;
-		  ptr = (Bufbyte *) ascii_end;
-		}
-	    }
-	}
-      else
-	{
-	  /* optimize for successive characters from the same charset */
-	  Bufbyte leading_byte = *ptr;
-	  size_t bytes = REP_BYTES_BY_FIRST_BYTE (leading_byte);
-	  while ((ptr < end) && (*ptr == leading_byte))
-	    ptr += bytes, count++;
-	}
+      count++;
+      INC_CHARPTR (ptr);
     }
-
 #ifdef ERROR_CHECK_BUFPOS
   /* Bomb out if the specified substring ends in the middle
      of a character.  Note that we might have already gotten
@@ -376,9 +378,9 @@
    the equivalent length in bytes. */
 
 Bytecount
-charcount_to_bytecount (const Bufbyte *ptr, Charcount len)
+charcount_to_bytecount (CONST Bufbyte *ptr, Charcount len)
 {
-  const Bufbyte *newptr = ptr;
+  CONST Bufbyte *newptr = ptr;
 
   while (len > 0)
     {
@@ -1603,7 +1605,7 @@
 adjust_markers (struct buffer *buf, Memind from, Memind to,
 		Bytecount amount)
 {
-  Lisp_Marker *m;
+  struct Lisp_Marker *m;
 
   for (m = BUF_MARKERS (buf); m; m = marker_next (m))
     m->memind = do_marker_adjustment (m->memind, from, to, amount);
@@ -1615,7 +1617,7 @@
 static void
 adjust_markers_for_insert (struct buffer *buf, Memind ind, Bytecount amount)
 {
-  Lisp_Marker *m;
+  struct Lisp_Marker *m;
 
   for (m = BUF_MARKERS (buf); m; m = marker_next (m))
     {
@@ -1629,6 +1631,18 @@
 /*                  Routines for dealing with the gap                   */
 /************************************************************************/
 
+/* XEmacs requires an ANSI C compiler, and it damn well better have a
+   working memmove() */
+#define GAP_USE_BCOPY
+#ifdef BCOPY_UPWARD_SAFE
+# undef BCOPY_UPWARD_SAFE
+#endif
+#ifdef BCOPY_DOWNWARD_SAFE
+# undef BCOPY_DOWNWARD_SAFE
+#endif
+#define BCOPY_UPWARD_SAFE 1
+#define BCOPY_DOWNWARD_SAFE 1
+
 /* maximum amount of memory moved in a single chunk.  Increasing this
    value improves gap-motion efficiency but decreases QUIT responsiveness
    time.  Was 32000 but today's processors are faster and files are
@@ -1669,15 +1683,23 @@
       /* Move at most GAP_MOVE_CHUNK chars before checking again for a quit. */
       if (i > GAP_MOVE_CHUNK)
 	i = GAP_MOVE_CHUNK;
-
-      if (i >= 128)
+#ifdef GAP_USE_BCOPY
+      if (i >= 128
+	  /* bcopy is safe if the two areas of memory do not overlap
+	     or on systems where bcopy is always safe for moving upward.  */
+	  && (BCOPY_UPWARD_SAFE
+	      || to - from >= 128))
 	{
+	  /* If overlap is not safe, avoid it by not moving too many
+	     characters at once.  */
+	  if (!BCOPY_UPWARD_SAFE && i > to - from)
+	    i = to - from;
 	  new_s1 -= i;
-	  from   -= i;
-	  to     -= i;
+	  from -= i, to -= i;
 	  memmove (to, from, i);
 	}
       else
+#endif
 	{
 	  new_s1 -= i;
 	  while (--i >= 0)
@@ -1740,15 +1762,23 @@
       /* Move at most GAP_MOVE_CHUNK chars before checking again for a quit. */
       if (i > GAP_MOVE_CHUNK)
 	i = GAP_MOVE_CHUNK;
-
-      if (i >= 128)
+#ifdef GAP_USE_BCOPY
+      if (i >= 128
+	  /* bcopy is safe if the two areas of memory do not overlap
+	     or on systems where bcopy is always safe for moving downward. */
+	  && (BCOPY_DOWNWARD_SAFE
+	      || from - to >= 128))
 	{
+	  /* If overlap is not safe, avoid it by not moving too many
+	     characters at once.  */
+	  if (!BCOPY_DOWNWARD_SAFE && i > from - to)
+	    i = from - to;
 	  new_s1 += i;
 	  memmove (to, from, i);
-	  from += i;
-	  to   += i;
+	  from += i, to += i;
 	}
       else
+#endif
 	{
 	  new_s1 += i;
 	  while (--i >= 0)
@@ -2027,12 +2057,7 @@
    of the specified region, that will also be handled correctly.
 
    begin_multiple_change() returns a number (actually a specpdl depth)
-   that you must pass to end_multiple_change() when you are done.
-
-   FSF Emacs 20 implements a similar feature, accessible from Lisp
-   through a `combine-after-change-calls' special form, which is
-   essentially equivalent to this function.  We should consider
-   whether we want to introduce a similar Lisp form.  */
+   that you must pass to end_multiple_change() when you are done. */
 
 int
 begin_multiple_change (struct buffer *buf, Bufpos start, Bufpos end)
@@ -2080,8 +2105,7 @@
   /* We should first reset the variable and then change the buffer,
      because Fset_buffer() can throw.  */
   inside_change_hook = 0;
-  if (XBUFFER (buffer) != current_buffer)
-    Fset_buffer (buffer);
+  Fset_buffer (buffer);
   return Qnil;
 }
 
@@ -2131,7 +2155,6 @@
   if (!inside_change_hook)
     {
       Lisp_Object buffer;
-      int speccount;
 
       /* Are we in a multiple-change session? */
       if (buf->text->changes->in_multiple_change &&
@@ -2169,9 +2192,6 @@
 	}
 
       /* Now in any case run the before-change-functions if any.  */
-      speccount = specpdl_depth ();
-      record_unwind_protect (change_function_restore, Fcurrent_buffer ());
-      inside_change_hook = 1;
 
       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
 	{
@@ -2180,28 +2200,25 @@
 	      /* Obsolete, for compatibility */
 	      || !NILP (symbol_value_in_buffer (Qbefore_change_function, buffer)))
 	    {
+	      int speccount = specpdl_depth ();
+	      record_unwind_protect (change_function_restore, Fcurrent_buffer ());
 	      set_buffer_internal (buf);
+	      inside_change_hook = 1;
 	      va_run_hook_with_args (Qbefore_change_functions, 2,
 				     make_int (start), make_int (end));
 	      /* Obsolete, for compatibility */
 	      va_run_hook_with_args (Qbefore_change_function, 2,
 				     make_int (start), make_int (end));
+	      unbind_to (speccount, Qnil);
 	    }
 	}
 
-      /* Make sure endpoints remain valid.  before-change-functions
-	 might have modified the buffer. */
-      if (start < BUF_BEGV (buf)) start = BUF_BEGV (buf);
-      if (start > BUF_ZV (buf))   start = BUF_ZV (buf);
-      if (end < BUF_BEGV (buf)) end = BUF_BEGV (buf);
-      if (end > BUF_ZV (buf))   end = BUF_ZV (buf);
-
       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
 	{
 	  XSETBUFFER (buffer, mbuf);
-	  report_extent_modification (buffer, start, end, 0);
+	  report_extent_modification (buffer, start, end,
+				      &inside_change_hook, 0);
 	}
-      unbind_to (speccount, Qnil);
 
       /* Only now do we indicate that the before-change-functions have
 	 been called, in case some function throws out. */
@@ -2238,7 +2255,6 @@
   if (!inside_change_hook)
     {
       Lisp_Object buffer;
-      int speccount;
 
       if (buf->text->changes->in_multiple_change &&
 	  buf->text->changes->mc_begin != 0)
@@ -2251,9 +2267,6 @@
 	  return; /* after-change-functions signalled when all changes done */
 	}
 
-      speccount = specpdl_depth ();
-      record_unwind_protect (change_function_restore, Fcurrent_buffer ());
-      inside_change_hook = 1;
       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
 	{
 	  XSETBUFFER (buffer, mbuf);
@@ -2262,7 +2275,10 @@
 	      /* Obsolete, for compatibility */
 	      || !NILP (symbol_value_in_buffer (Qafter_change_function, buffer)))
 	    {
+	      int speccount = specpdl_depth ();
+	      record_unwind_protect (change_function_restore, Fcurrent_buffer ());
 	      set_buffer_internal (buf);
+	      inside_change_hook = 1;
 	      /* The actual after-change functions take slightly
 		 different arguments than what we were passed. */
 	      va_run_hook_with_args (Qafter_change_functions, 3,
@@ -2272,24 +2288,16 @@
 	      va_run_hook_with_args (Qafter_change_function, 3,
 				     make_int (start), make_int (new_end),
 				     make_int (orig_end - start));
+	      unbind_to (speccount, Qnil);
 	    }
 	}
 
-      /* Make sure endpoints remain valid.  after-change-functions
-	 might have modified the buffer. */
-      if (start < BUF_BEGV (buf)) start = BUF_BEGV (buf);
-      if (start > BUF_ZV (buf))   start = BUF_ZV (buf);
-      if (new_end < BUF_BEGV (buf)) new_end = BUF_BEGV (buf);
-      if (new_end > BUF_ZV (buf))   new_end = BUF_ZV (buf);
-      if (orig_end < BUF_BEGV (buf)) orig_end = BUF_BEGV (buf);
-      if (orig_end > BUF_ZV (buf))   orig_end = BUF_ZV (buf);
-
       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
 	{
 	  XSETBUFFER (buffer, mbuf);
-	  report_extent_modification (buffer, start, new_end, 1);
+	  report_extent_modification (buffer, start, new_end,
+				      &inside_change_hook, 1);
 	}
-      unbind_to (speccount, Qnil); /* sets inside_change_hook back to 0 */
     }
 }
 
@@ -2369,7 +2377,7 @@
 /************************************************************************/
 
 void
-fixup_internal_substring (const Bufbyte *nonreloc, Lisp_Object reloc,
+fixup_internal_substring (CONST Bufbyte *nonreloc, Lisp_Object reloc,
 			  Bytecount offset, Bytecount *len)
 {
   assert ((nonreloc && NILP (reloc)) || (!nonreloc && STRINGP (reloc)));
@@ -2377,7 +2385,7 @@
   if (*len < 0)
     {
       if (nonreloc)
-	*len = strlen ((const char *) nonreloc) - offset;
+	*len = strlen ((CONST char *) nonreloc) - offset;
       else
 	*len = XSTRING_LENGTH (reloc) - offset;
     }
@@ -2411,7 +2419,7 @@
 
 Charcount
 buffer_insert_string_1 (struct buffer *buf, Bufpos pos,
-			const Bufbyte *nonreloc, Lisp_Object reloc,
+			CONST Bufbyte *nonreloc, Lisp_Object reloc,
 			Bytecount offset, Bytecount length,
 			int flags)
 {
@@ -2576,7 +2584,7 @@
 
 Charcount
 buffer_insert_raw_string_1 (struct buffer *buf, Bufpos pos,
-			    const Bufbyte *nonreloc, Bytecount length,
+			    CONST Bufbyte *nonreloc, Bytecount length,
 			    int flags)
 {
   /* This function can GC */
@@ -2600,12 +2608,12 @@
 /* Insert the null-terminated string S (in external format). */
 
 Charcount
-buffer_insert_c_string_1 (struct buffer *buf, Bufpos pos, const char *s,
+buffer_insert_c_string_1 (struct buffer *buf, Bufpos pos, CONST char *s,
 			  int flags)
 {
   /* This function can GC */
-  const char *translated = GETTEXT (s);
-  return buffer_insert_string_1 (buf, pos, (const Bufbyte *) translated, Qnil,
+  CONST char *translated = GETTEXT (s);
+  return buffer_insert_string_1 (buf, pos, (CONST Bufbyte *) translated, Qnil,
 				 0, strlen (translated), flags);
 }
 
@@ -3071,23 +3079,16 @@
 }
 
 void
-find_charsets_in_bufbyte_string (unsigned char *charsets, const Bufbyte *str,
+find_charsets_in_bufbyte_string (unsigned char *charsets, CONST Bufbyte *str,
 				 Bytecount len)
 {
 #ifndef MULE
   /* Telescope this. */
   charsets[0] = 1;
 #else
-  const Bufbyte *strend = str + len;
+  CONST Bufbyte *strend = str + len;
   memset (charsets, 0, NUM_LEADING_BYTES);
 
-  /* #### SJT doesn't like this. */
-  if (len == 0)
-    {
-      charsets[XCHARSET_LEADING_BYTE (Vcharset_ascii) - 128] = 1;
-      return;
-    }
-
   while (str < strend)
     {
       charsets[CHAR_LEADING_BYTE (charptr_emchar (str)) - 128] = 1;
@@ -3097,7 +3098,7 @@
 }
 
 void
-find_charsets_in_emchar_string (unsigned char *charsets, const Emchar *str,
+find_charsets_in_emchar_string (unsigned char *charsets, CONST Emchar *str,
 				Charcount len)
 {
 #ifndef MULE
@@ -3107,14 +3108,6 @@
   int i;
 
   memset (charsets, 0, NUM_LEADING_BYTES);
-
-  /* #### SJT doesn't like this. */
-  if (len == 0)
-    {
-      charsets[XCHARSET_LEADING_BYTE (Vcharset_ascii) - 128] = 1;
-      return;
-    }
-
   for (i = 0; i < len; i++)
     {
       charsets[CHAR_LEADING_BYTE (str[i]) - 128] = 1;
@@ -3123,10 +3116,10 @@
 }
 
 int
-bufbyte_string_displayed_columns (const Bufbyte *str, Bytecount len)
+bufbyte_string_displayed_columns (CONST Bufbyte *str, Bytecount len)
 {
   int cols = 0;
-  const Bufbyte *end = str + len;
+  CONST Bufbyte *end = str + len;
 
   while (str < end)
     {
@@ -3143,7 +3136,7 @@
 }
 
 int
-emchar_string_displayed_columns (const Emchar *str, Charcount len)
+emchar_string_displayed_columns (CONST Emchar *str, Charcount len)
 {
 #ifdef MULE
   int cols = 0;
@@ -3161,10 +3154,10 @@
 /* NOTE: Does not reset the Dynarr. */
 
 void
-convert_bufbyte_string_into_emchar_dynarr (const Bufbyte *str, Bytecount len,
+convert_bufbyte_string_into_emchar_dynarr (CONST Bufbyte *str, Bytecount len,
 					   Emchar_dynarr *dyn)
 {
-  const Bufbyte *strend = str + len;
+  CONST Bufbyte *strend = str + len;
 
   while (str < strend)
     {
@@ -3175,10 +3168,10 @@
 }
 
 Charcount
-convert_bufbyte_string_into_emchar_string (const Bufbyte *str, Bytecount len,
+convert_bufbyte_string_into_emchar_string (CONST Bufbyte *str, Bytecount len,
 					   Emchar *arr)
 {
-  const Bufbyte *strend = str + len;
+  CONST Bufbyte *strend = str + len;
   Charcount newlen = 0;
   while (str < strend)
     {
@@ -3241,7 +3234,7 @@
 /************************************************************************/
 
 void
-reinit_vars_of_insdel (void)
+vars_of_insdel (void)
 {
   int i;
 
@@ -3253,12 +3246,6 @@
 }
 
 void
-vars_of_insdel (void)
-{
-  reinit_vars_of_insdel ();
-}
-
-void
 init_buffer_text (struct buffer *b)
 {
   if (!b->base_buffer)