changeset 5038:9410323e4b0d

major dynarr fixes -------------------- ChangeLog entries follow: -------------------- src/ChangeLog addition: 2010-02-20 Ben Wing <ben@xemacs.org> * device-x.c (Fx_get_resource): * dynarr.c: * dynarr.c (Dynarr_realloc): * dynarr.c (Dynarr_newf): * dynarr.c (Dynarr_lisp_realloc): * dynarr.c (Dynarr_lisp_newf): * dynarr.c (Dynarr_resize): * dynarr.c (Dynarr_insert_many): * dynarr.c (Dynarr_delete_many): * dynarr.c (Dynarr_memory_usage): * dynarr.c (stack_like_free): * file-coding.c (coding_reader): * file-coding.c (gzip_convert): * gutter.c (output_gutter): * lisp.h: * lisp.h (Dynarr_declare): * lisp.h (DYNARR_SET_LISP_IMP): * lisp.h (CHECK_NATNUM): * profile.c (create_timing_profile_table): * redisplay-output.c (sync_rune_structs): * redisplay-output.c (sync_display_line_structs): * redisplay-output.c (redisplay_output_window): * redisplay.c: * redisplay.c (get_display_block_from_line): * redisplay.c (add_ichar_rune_1): * redisplay.c (ensure_modeline_generated): * redisplay.c (generate_displayable_area): * redisplay.c (regenerate_window): * redisplay.c (update_line_start_cache): * signal.c: * signal.c (check_quit): Lots of rewriting of dynarr code. (1) Lots of documentation added. Also fix places that referenced a now-bogus internals node concerning redisplay critical sections. (2) Rename: Dynarr_add_lisp_string -> Dynarr_add_ext_lisp_string Dynarr_set_length -> Dynarr_set_lengthr ("restricted") Dynarr_increment -> Dynarr_incrementr Dynarr_resize_if -> Dynarr_resize_to_add (3) New functions: Dynarr_elsize = dy->elsize_ Dynarr_set_length(): Set length, resizing as necessary Dynarr_set_length_and_zero(): Set length, resizing as necessary, zeroing out new elements Dynarr_increase_length(), Dynarr_increase_length_and_zero(): Optimization of Dynarr_set_length(), Dynarr_set_length_and_zero() when size is known to increase Dynarr_resize_to_fit(): Resize as necessary to fit a given length. Dynarr_set(): Set element at a given position, increasing length as necessary and setting any newly created positions to 0 (4) Use Elemcount, Bytecount. (5) Rewrite many macros as inline functions.
author Ben Wing <ben@xemacs.org>
date Sat, 20 Feb 2010 03:46:22 -0600
parents e70a73f9243d
children f8ae1031c706
files src/ChangeLog src/device-x.c src/dynarr.c src/file-coding.c src/gutter.c src/lisp.h src/profile.c src/redisplay-output.c src/redisplay.c src/signal.c
diffstat 10 files changed, 625 insertions(+), 221 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/ChangeLog	Sat Feb 20 03:46:22 2010 -0600
@@ -1,3 +1,67 @@
+2010-02-20  Ben Wing  <ben@xemacs.org>
+
+	* device-x.c (Fx_get_resource):
+	* dynarr.c:
+	* dynarr.c (Dynarr_realloc):
+	* dynarr.c (Dynarr_newf):
+	* dynarr.c (Dynarr_lisp_realloc):
+	* dynarr.c (Dynarr_lisp_newf):
+	* dynarr.c (Dynarr_resize):
+	* dynarr.c (Dynarr_insert_many):
+	* dynarr.c (Dynarr_delete_many):
+	* dynarr.c (Dynarr_memory_usage):
+	* dynarr.c (stack_like_free):
+	* file-coding.c (coding_reader):
+	* file-coding.c (gzip_convert):
+	* gutter.c (output_gutter):
+	* lisp.h:
+	* lisp.h (Dynarr_declare):
+	* lisp.h (DYNARR_SET_LISP_IMP):
+	* lisp.h (CHECK_NATNUM):
+	* profile.c (create_timing_profile_table):
+	* redisplay-output.c (sync_rune_structs):
+	* redisplay-output.c (sync_display_line_structs):
+	* redisplay-output.c (redisplay_output_window):
+	* redisplay.c:
+	* redisplay.c (get_display_block_from_line):
+	* redisplay.c (add_ichar_rune_1):
+	* redisplay.c (ensure_modeline_generated):
+	* redisplay.c (generate_displayable_area):
+	* redisplay.c (regenerate_window):
+	* redisplay.c (update_line_start_cache):
+	* signal.c:
+	* signal.c (check_quit):
+
+	Lots of rewriting of dynarr code.
+
+	(1) Lots of documentation added.  Also fix places that
+	referenced a now-bogus internals node concerning redisplay
+	critical sections.
+	
+	(2) Rename:
+
+	Dynarr_add_lisp_string -> Dynarr_add_ext_lisp_string
+	Dynarr_set_length -> Dynarr_set_lengthr ("restricted")
+	Dynarr_increment -> Dynarr_incrementr
+	Dynarr_resize_if -> Dynarr_resize_to_add
+
+	(3) New functions:
+
+	Dynarr_elsize = dy->elsize_
+	Dynarr_set_length(): Set length, resizing as necessary
+	Dynarr_set_length_and_zero(): Set length, resizing as necessary,
+	  zeroing out new elements
+	Dynarr_increase_length(), Dynarr_increase_length_and_zero():
+	  Optimization of Dynarr_set_length(), Dynarr_set_length_and_zero()
+	  when size is known to increase
+	Dynarr_resize_to_fit(): Resize as necessary to fit a given length.
+	Dynarr_set(): Set element at a given position, increasing length
+	  as necessary and setting any newly created positions to 0
+	
+	(4) Use Elemcount, Bytecount.
+
+	(5) Rewrite many macros as inline functions.
+
 2010-02-20  Ben Wing  <ben@xemacs.org>
 
 	* tests.c:
--- a/src/device-x.c	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/device-x.c	Sat Feb 20 03:46:22 2010 -0600
@@ -1564,9 +1564,9 @@
   db = XtDatabase (display);
   codesys = coding_system_of_xrm_database (db);
   Dynarr_add (name_Extbyte_dynarr, '.');
-  Dynarr_add_lisp_string (name_Extbyte_dynarr, name, Qbinary);
+  Dynarr_add_ext_lisp_string (name_Extbyte_dynarr, name, Qbinary);
   Dynarr_add (class_Extbyte_dynarr, '.');
-  Dynarr_add_lisp_string (class_Extbyte_dynarr, class_, Qbinary);
+  Dynarr_add_ext_lisp_string (class_Extbyte_dynarr, class_, Qbinary);
   Dynarr_add (name_Extbyte_dynarr,  '\0');
   Dynarr_add (class_Extbyte_dynarr, '\0');
 
--- a/src/dynarr.c	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/dynarr.c	Sat Feb 20 03:46:22 2010 -0600
@@ -25,16 +25,16 @@
 
 /*
 
-A "dynamic array" is a contiguous array of fixed-size elements where there
-is no upper limit (except available memory) on the number of elements in the
-array.  Because the elements are maintained contiguously, space is used
-efficiently (no per-element pointers necessary) and random access to a
-particular element is in constant time.  At any one point, the block of memory
-that holds the array has an upper limit; if this limit is exceeded, the
-memory is realloc()ed into a new array that is twice as big.  Assuming that
-the time to grow the array is on the order of the new size of the array
-block, this scheme has a provably constant amortized time (i.e. average
-time over all additions).
+A "dynamic array" or "dynarr" is a contiguous array of fixed-size elements
+where there is no upper limit (except available memory) on the number of
+elements in the array.  Because the elements are maintained contiguously,
+space is used efficiently (no per-element pointers necessary) and random
+access to a particular element is in constant time.  At any one point, the
+block of memory that holds the array has an upper limit; if this limit is
+exceeded, the memory is realloc()ed into a new array that is twice as big.
+Assuming that the time to grow the array is on the order of the new size of
+the array block, this scheme has a provably constant amortized time
+\(i.e. average time over all additions).
 
 When you add elements or retrieve elements, pointers are used.  Note that
 the element itself (of whatever size it is), and not the pointer to it,
@@ -52,12 +52,129 @@
 
 Use the following functions/macros:
 
+
+  ************* Dynarr creation *************
+
    void *Dynarr_new(type)
       [MACRO] Create a new dynamic-array object, with each element of the
       specified type.  The return value is cast to (type##_dynarr).
       This requires following the convention that types are declared in
       such a way that this type concatenation works.  In particular, TYPE
-      must be a symbol, not an arbitrary C type.
+      must be a symbol, not an arbitrary C type.  To make dynarrs of
+      complex types, a typedef must be declared, e.g.
+
+      typedef unsigned char *unsigned_char_ptr;
+
+      and then you can say
+
+      unsigned_char_ptr_dynarr *dyn = Dynarr_new (unsigned_char_ptr);
+
+   void *Dynarr_new2(dynarr_type, type)
+      [MACRO] Create a new dynamic-array object, with each element of the
+      specified type.  The array itself is of type DYNARR_TYPE.  This makes
+      it possible to create dynarrs over complex types without the need
+      to create typedefs, as described above.  Use is as follows:
+
+      ucharptr_dynarr *dyn = Dynarr_new2 (ucharptr_dynarr *, unsigned char *);
+
+   Dynarr_free(d)
+      Destroy a dynamic array and the memory allocated to it.
+
+  ************* Dynarr access *************
+
+   type Dynarr_at(d, i)
+      [MACRO] Return the element at the specified index.  The index must be
+      between 0 and Dynarr_largest(d), inclusive.  With error-checking
+      enabled, bounds checking on the index is in the form of asserts() --
+      an out-of-bounds index causes an abort.  The element itself is
+      returned, not a pointer to it.
+
+   type *Dynarr_atp(d, i)
+      [MACRO] Return a pointer to the element at the specified index.
+      Restrictions and bounds checking on the index is as for Dynarr_at.
+      The pointer may not be valid after an element is added to or
+      (conceivably) removed from the array, because this may trigger a
+      realloc() performed on the underlying dynarr storage, which may
+      involve moving the entire underlying storage to a new location in
+      memory.
+
+   type *Dynarr_begin(d)
+      [MACRO] Return a pointer to the first element in the dynarr.  See
+      Dynarr_atp() for warnings about when the pointer might become invalid.
+
+   type *Dynarr_lastp(d)
+      [MACRO] Return a pointer to the last element in the dynarr.  See
+      Dynarr_atp() for warnings about when the pointer might become invalid.
+
+   type *Dynarr_past_lastp(d)
+      [MACRO] Return a pointer to the beginning of the element just past the
+      last one.  WARNING: This may not point to valid memory; however, the
+      byte directly before will be pointer will be valid memory.  This macro
+      might be useful for various reasons, e.g. as a stopping point in a loop
+      (although Dynarr_lastp() could be used just as well) or as a place to
+      start writing elements if Dynarr_length() < Dynarr_largest().
+
+  ************* Dynarr length/size retrieval and setting *************
+
+   int Dynarr_length(d)
+      [MACRO] Return the number of elements currently in a dynamic array.
+
+   int Dynarr_largest(d)
+      [MACRO] Return the maximum value that Dynarr_length(d) would
+      ever have returned.  This is used esp. in the redisplay code,
+      which reuses dynarrs for performance reasons.
+
+   int Dynarr_max(d)
+      [MACRO] Return the maximum number of elements that can fit in the
+      dynarr before it needs to be resized.
+
+      Note that Dynarr_length(d) <= Dynarr_largest(d) <= Dynarr_max(d).
+   
+   Bytecount Dynarr_sizeof(d)
+      [MACRO] Return the total size of the elements currently in dynarr
+      D.  This 
+
+   Dynarr_set_lengthr(d, len)
+      [MACRO] Set the length of D to LEN, which must be between 0 and
+      Dynarr_largest(d), inclusive.  With error-checking enabled, an
+      assertion failure will result from trying to set the length
+      to less than zero or greater than Dynarr_largest(d).  The
+      restriction to Dynarr_largest() is to ensure that
+
+   Dynarr_set_length(d, len)
+      [MACRO] Set the length of D to LEN, resizing the dynarr as
+      necessary to make sure enough space is available.  there are no
+      restrictions on LEN other than available memory and that it must
+      be at least 0.  Note that
+
+   Dynarr_set_length_and_zero(d, len)
+      [MACRO] Like Dynarr_set_length(d, len) but also, if increasing
+      the length, zero out the memory between the old and new lengths,
+      i.e. starting just past the previous last element and up through
+      the new last element.
+
+   Dynarr_incrementr(d)
+      [MACRO] Increments the length of D by 1.  Equivalent to
+      Dynarr_set_lengthr(d, Dynarr_length(d) + 1).
+
+   Dynarr_increment(d)
+      [MACRO] Increments the length of D by 1.  Equivalent to
+      Dynarr_set_length(d, Dynarr_length(d) + 1).
+
+   Dynarr_reset(d)
+      [MACRO] Reset the length of a dynamic array to 0.
+
+   Dynarr_resize(d, maxval)
+      Resize the internal dynarr storage to so that it can hold at least
+      MAXVAL elements.  Resizing is done using a geometric series
+      (repeatedly multiply the old maximum by a constant, normally 1.5,
+      till a large enough size is reached), so this will be efficient
+      even if resizing larger by one element at a time.  This is mostly
+      an internal function.
+
+
+
+  ************* Adding/deleting elements to/from a dynarr *************
 
    Dynarr_add(d, el)
       [MACRO] Add an element to the end of a dynamic array.  EL is a pointer
@@ -69,55 +186,47 @@
       should be contiguous in memory, starting at BASE.  If BASE if NULL,
       just make space for the elements; don't actually add them.
 
-   Dynarr_insert_many_at_start(d, base, len)
-      [MACRO] Append LEN elements to the beginning of the dynamic array.
+   Dynarr_prepend_many(d, base, len)
+      [MACRO] Prepend LEN elements to the beginning of the dynamic array.
       The elements should be contiguous in memory, starting at BASE.
       If BASE if NULL, just make space for the elements; don't actually
       add them.
 
-   Dynarr_insert_many(d, base, len, start)
+   Dynarr_insert_many(d, base, len, pos)
       Insert LEN elements to the dynamic array starting at position
-      START.  The elements should be contiguous in memory, starting at BASE.
+      POS.  The elements should be contiguous in memory, starting at BASE.
       If BASE if NULL, just make space for the elements; don't actually
       add them.
 
+   type Dynarr_pop(d)
+      [MACRO] Pop the last element off the dynarr and return it.
+
    Dynarr_delete(d, i)
       [MACRO] Delete an element from the dynamic array at position I.
 
-   Dynarr_delete_many(d, start, len)
+   Dynarr_delete_many(d, pos, len)
       Delete LEN elements from the dynamic array starting at position
-      START.
+      POS.
+
+   Dynarr_zero_many(d, pos, len)
+      Zero out LEN elements in the dynarr D starting at position POS.
 
    Dynarr_delete_by_pointer(d, p)
       [MACRO] Delete an element from the dynamic array at pointer P,
       which must point within the block of memory that stores the data.
       P should be obtained using Dynarr_atp().
 
-   int Dynarr_length(d)
-      [MACRO] Return the number of elements currently in a dynamic array.
-
-   int Dynarr_largest(d)
-      [MACRO] Return the maximum value that Dynarr_length(d) would
-      ever have returned.  This is used esp. in the redisplay code,
-      which reuses dynarrs for performance reasons.
-
-   type Dynarr_at(d, i)
-      [MACRO] Return the element at the specified index (no bounds checking
-      done on the index).  The element itself is returned, not a pointer
-      to it.
+  ************* Dynarr locking *************
 
-   type *Dynarr_atp(d, i)
-      [MACRO] Return a pointer to the element at the specified index (no
-      bounds checking done on the index).  The pointer may not be valid
-      after an element is added to or removed from the array.
+   Dynarr_lock(d)
+      Lock the dynarr against further locking or writing.  With error-checking
+      enabled, any attempts to write into a locked dynarr or re-lock an
+      already locked one will cause an assertion failure and abort.
 
-   Dynarr_reset(d)
-      [MACRO] Reset the length of a dynamic array to 0.
+   Dynarr_unlock(d)
+      Unlock a locked dynarr, allowing writing into it.
 
-   Dynarr_free(d)
-      Destroy a dynamic array and the memory allocated to it.
-
-Use the following global variable:
+  ************* Dynarr global variables *************
 
    Dynarr_min_size
       Minimum allowable size for a dynamic array when it is resized.
@@ -148,28 +257,28 @@
 };
 
 
-static int Dynarr_min_size = 8;
+static Elemcount Dynarr_min_size = 8;
 
 static void
-Dynarr_realloc (Dynarr *dy, int new_size)
+Dynarr_realloc (Dynarr *dy, Elemcount new_size)
 {
   if (DUMPEDP (dy->base))
     {
-      void *new_base = malloc (new_size * dy->elsize);
+      void *new_base = malloc (new_size * Dynarr_elsize (dy));
       memcpy (new_base, dy->base, 
 	      (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) *
-	      dy->elsize);
+	      Dynarr_elsize (dy));
       dy->base = new_base;
     }
   else
-    dy->base = xrealloc (dy->base, new_size * dy->elsize);
+    dy->base = xrealloc (dy->base, new_size * Dynarr_elsize (dy));
 }
 
 void *
-Dynarr_newf (int elsize)
+Dynarr_newf (Bytecount elsize)
 {
   Dynarr *d = xnew_and_zero (Dynarr);
-  d->elsize = elsize;
+  d->elsize_ = elsize;
 
   return d;
 }
@@ -182,23 +291,24 @@
 			       Dynarr);
 
 static void
-Dynarr_lisp_realloc (Dynarr *dy, int new_size)
+Dynarr_lisp_realloc (Dynarr *dy, Elemcount new_size)
 {
-  void *new_base = alloc_lrecord_array (dy->elsize, new_size, dy->lisp_imp);
+  void *new_base = alloc_lrecord_array (Dynarr_elsize (dy), new_size,
+					dy->lisp_imp);
   if (dy->base)
     memcpy (new_base, dy->base, 
 	    (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) *
-	    dy->elsize);
+	    Dynarr_elsize (dy));
   dy->base = new_base;
 }
 
 void *
-Dynarr_lisp_newf (int elsize, 
+Dynarr_lisp_newf (Bytecount elsize, 
 		  const struct lrecord_implementation *dynarr_imp, 
 		  const struct lrecord_implementation *imp)
 {
   Dynarr *d = (Dynarr *) alloc_lrecord (sizeof (Dynarr), dynarr_imp);
-  d->elsize = elsize;
+  d->elsize_ = elsize;
   d->lisp_imp = imp;
 
   return d;
@@ -208,7 +318,7 @@
 void
 Dynarr_resize (void *d, Elemcount size)
 {
-  int newsize;
+  Elemcount newsize;
   double multiplier;
   Dynarr *dy = (Dynarr *) Dynarr_verify (d);
 
@@ -218,7 +328,7 @@
     multiplier = 1.5;
 
   for (newsize = Dynarr_max (dy); newsize < size;)
-    newsize = max (Dynarr_min_size, (int) (multiplier * newsize));
+    newsize = max (Dynarr_min_size, (Elemcount) (multiplier * newsize));
 
   /* Don't do anything if the array is already big enough. */
   if (newsize > Dynarr_max (dy))
@@ -235,47 +345,46 @@
     }
 }
 
-/* Add a number of contiguous elements to the array starting at START. */
+/* Add a number of contiguous elements to the array starting at POS. */
+
 void
-Dynarr_insert_many (void *d, const void *el, int len, int start)
+Dynarr_insert_many (void *d, const void *base, Elemcount len, Elemcount pos)
 {
   Dynarr *dy = Dynarr_verify_mod (d);
-
-  Dynarr_resize_if (dy, len);
+  Elemcount old_len = Dynarr_length (dy);
 
   /* #### This could conceivably be wrong, if code wants to access stuff
      between len and largest. */
-  dynarr_checking_assert (start >= 0 && start <= Dynarr_length (dy));
+  dynarr_checking_assert (pos >= 0 && pos <= old_len);
+  dynarr_checking_assert (len >= 0);
+  Dynarr_increase_length (dy, old_len + len);
 
-  if (start != Dynarr_length (dy))
+  if (pos != old_len)
     {
-      memmove ((char *) dy->base + (start + len)*dy->elsize,
-	       (char *) dy->base + start*dy->elsize,
-	       (Dynarr_length (dy) - start)*dy->elsize);
+      memmove ((Rawbyte *) dy->base + (pos + len)*Dynarr_elsize (dy),
+	       (Rawbyte *) dy->base + pos*Dynarr_elsize (dy),
+	       (old_len - pos)*Dynarr_elsize (dy));
     }
   /* Some functions call us with a value of 0 to mean "reserve space but
      don't write into it" */
-  if (el)
-    memcpy ((char *) dy->base + start*dy->elsize, el, len*dy->elsize);
-
-  Dynarr_set_length_1 (dy, Dynarr_length (dy) + len);
-  (void) Dynarr_verify_mod (dy);
+  if (base)
+    memcpy ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), base,
+	    len*Dynarr_elsize (dy));
 }
 
 void
-Dynarr_delete_many (void *d, int start, int len)
+Dynarr_delete_many (void *d, Elemcount pos, Elemcount len)
 {
   Dynarr *dy = Dynarr_verify_mod (d);
 
-  dynarr_checking_assert (start >= 0 && len >= 0 &&
-			  start + len <= Dynarr_length (dy));
+  dynarr_checking_assert (pos >= 0 && len >= 0 &&
+			  pos + len <= Dynarr_length (dy));
 
-  memmove ((char *) dy->base + start*dy->elsize,
-	   (char *) dy->base + (start + len)*dy->elsize,
-	   (Dynarr_length (dy) - start - len)*dy->elsize);
+  memmove ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy),
+	   (Rawbyte *) dy->base + (pos + len)*Dynarr_elsize (dy),
+	   (Dynarr_length (dy) - pos - len)*Dynarr_elsize (dy));
 
   Dynarr_set_length_1 (dy, Dynarr_length (dy) - len);
-  (void) Dynarr_verify_mod (dy);
 }
 
 void
@@ -304,9 +413,9 @@
 
 #ifdef MEMORY_USAGE_STATS
 
-/* Return memory usage for Dynarr D.  The returned value is the total
-   amount of bytes actually being used for the Dynarr, including all
-   overhead.  The extra amount of space in the Dynarr that is
+/* Return memory usage for dynarr D.  The returned value is the total
+   amount of bytes actually being used for the dynarr, including all
+   overhead.  The extra amount of space in the dynarr that is
    allocated beyond what was requested is returned in DYNARR_OVERHEAD
    in STATS.  The extra amount of space that malloc() allocates beyond
    what was requested of it is returned in MALLOC_OVERHEAD in STATS.
@@ -325,12 +434,13 @@
   if (dy->base)
     {
       Bytecount malloc_used =
-	malloced_storage_size (dy->base, dy->elsize * Dynarr_max (dy), 0);
-      /* #### This may or may not be correct.  Some Dynarrs would
+	malloced_storage_size (dy->base, Dynarr_elsize (dy) * Dynarr_max (dy),
+			       0);
+      /* #### This may or may not be correct.  Some dynarrs would
 	 prefer that we use dy->len instead of dy->largest here. */
-      Bytecount was_requested = dy->elsize * Dynarr_largest (dy);
+      Bytecount was_requested = Dynarr_elsize (dy) * Dynarr_largest (dy);
       Bytecount dynarr_overhead =
-	dy->elsize * (Dynarr_max (dy) - Dynarr_largest (dy));
+	Dynarr_elsize (dy) * (Dynarr_max (dy) - Dynarr_largest (dy));
 
       total += malloc_used;
       stats->was_requested += was_requested;
@@ -385,7 +495,7 @@
 void
 stack_like_free (void *val)
 {
-  int len = Dynarr_length (stack_like_in_use_list);
+  Elemcount len = Dynarr_length (stack_like_in_use_list);
   assert (len > 0);
   /* The vast majority of times, we will be called in a last-in first-out
      order, and the item at the end of the list will be the one we're
--- a/src/file-coding.c	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/file-coding.c	Sat Feb 20 03:46:22 2010 -0600
@@ -1864,7 +1864,7 @@
 				  Dynarr_atp (str->convert_from, rejected),
 				  readmore);
 	/* Trim size down to how much we actually got */
-	Dynarr_set_length (str->convert_from, rejected + max (0, read_size));
+	Dynarr_set_lengthr (str->convert_from, rejected + max (0, read_size));
       }
 
       if (read_size < 0) /* LSTREAM_ERROR */
@@ -1898,7 +1898,7 @@
 	  memmove (Dynarr_begin (str->convert_from),
 		   Dynarr_atp (str->convert_from, processed),
 		   to_process - processed);
-	Dynarr_set_length (str->convert_from, to_process - processed);
+	Dynarr_set_lengthr (str->convert_from, to_process - processed);
       }
     }
 
@@ -4423,7 +4423,7 @@
 	  data->stream.avail_out = reserved;
 	  zerr = inflate (&data->stream, Z_NO_FLUSH);
 	  /* Lop off the unused portion */
-	  Dynarr_set_length (dst, Dynarr_length (dst) - data->stream.avail_out);
+	  Dynarr_set_lengthr (dst, Dynarr_length (dst) - data->stream.avail_out);
 	  if (zerr != Z_OK)
 	    break;
 	}
@@ -4483,7 +4483,7 @@
 	    deflate (&data->stream,
 		     str->eof ? Z_FINISH : Z_NO_FLUSH);
 	  /* Lop off the unused portion */
-	  Dynarr_set_length (dst, Dynarr_length (dst) - data->stream.avail_out);
+	  Dynarr_set_lengthr (dst, Dynarr_length (dst) - data->stream.avail_out);
 	  if (zerr != Z_OK)
 	    break;
 	}
--- a/src/gutter.c	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/gutter.c	Sat Feb 20 03:46:22 2010 -0600
@@ -450,7 +450,7 @@
       /* If the number of display lines has shrunk, adjust. */
       if (cdla_len > Dynarr_length (ddla))
 	{
-	  Dynarr_set_length (cdla, Dynarr_length (ddla));
+	  Dynarr_set_lengthr (cdla, Dynarr_length (ddla));
 	}
 
       /* grab coordinates of last line and blank after it. */
--- a/src/lisp.h	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/lisp.h	Sat Feb 20 03:46:22 2010 -0600
@@ -317,8 +317,8 @@
 #ifdef ERROR_CHECK_STRUCTURES
 /* Check for problems with the catch list and specbind stack */
 #define ERROR_CHECK_CATCH
-/* Check for incoherent Dynarr structures, attempts to access Dynarr
-   positions out of range, reentrant use of Dynarrs through Dynarr locking,
+/* Check for incoherent dynarr structures, attempts to access Dynarr
+   positions out of range, reentrant use of dynarrs through dynarr locking,
    etc. */
 #define ERROR_CHECK_DYNARR
 /* Check for insufficient use of call_trapping_problems(), particularly
@@ -1455,7 +1455,7 @@
 
 /* We put typedefs here so that prototype declarations don't choke.
    Note that we don't actually declare the structures here (except
-   maybe for simple structures like Dynarrs); that keeps them private
+   maybe for simple structures like dynarrs); that keeps them private
    to the routines that actually use them. */
 
 /* ------------------------------- */
@@ -1721,7 +1721,7 @@
 }
 
 /************************************************************************/
-/**    Definitions of dynamic arrays (Dynarrs) and other allocators    **/
+/**    Definitions of dynamic arrays (dynarrs) and other allocators    **/
 /************************************************************************/
 
 BEGIN_C_DECLS
@@ -1747,7 +1747,7 @@
   type *base;					\
   DECLARE_DYNARR_LISP_IMP ()			\
   DECLARE_DYNARR_LOCKED ()			\
-  int elsize;					\
+  int elsize_;					\
   int len_;					\
   int largest_;					\
   int max_
@@ -1775,10 +1775,81 @@
 
 /************* Dynarr verification *************/
 
+/* Dynarr locking and verification.
+
+   [I] VERIFICATION
+
+   Verification routines simply return their basic argument, possibly
+   casted, but in the process perform some verification on it, aborting if
+   the verification fails.  The verification routines take FILE and LINE
+   parameters, and use them to output the file and line of the caller
+   when an abort occurs, rather than the file and line of the inline
+   function, which is less than useful.
+
+   There are three basic types of verification routines:
+
+   (1) Verify the dynarr itself.  This verifies the basic invariant
+   involving the length/size values:
+
+   0 <= Dynarr_length(d) <= Dynarr_largest(d) <= Dynarr_max(d)
+
+   (2) Verify the dynarr itself prior to modifying it.  This performs
+   the same verification as previously, but also checks that the
+   dynarr is not locked (see below).
+
+   (3) Verify a dynarr position.  Unfortunately we have to have
+   different verification routines depending on which kind of operation
+   is being performed:
+
+   (a) For Dynarr_at(), we check that the POS is bounded by Dynarr_largest(),
+       i.e. 0 <= POS < Dynarr_largest().
+   (b) For Dynarr_atp_allow_end(), we also have to allow
+       POS == Dynarr_largest().
+   (c) For Dynarr_atp(), we behave largely like Dynarr_at() but make a
+       special exception when POS == 0 and Dynarr_largest() == 0 -- see
+       comment below.
+   (d) Some other routines contain the POS verification within their code,
+       and make the check 0 <= POS < Dynarr_length() or
+       0 <= POS <= Dynarr_length().
+
+   #### It is not well worked-out whether and in what circumstances it's
+   allowed to use a position that is between Dynarr_length() and
+   Dynarr_largest().  The ideal solution is to never allow this, and require
+   instead that code first change the length before accessing higher
+   positions.  That would require looking through all the code that accesses
+   dynarrs and fixing it appropriately (especially redisplay code, and
+   especially redisplay code in the vicinity of a reference to
+   Dynarr_largest(), since such code usually checks explicitly to see whether
+   there is extra stuff between Dynarr_length() and Dynarr_largest().)
+
+   [II] LOCKING
+
+   The idea behind dynarr locking is simple: Locking a dynarr prevents
+   any modification from occurring, or rather, leads to an abort upon
+   any attempt to modify a dynarr.
+
+   Dynarr locking was originally added to catch some sporadic and hard-to-
+   debug crashes in the redisplay code where dynarrs appeared to be getting
+   corrupted in an unexpected fashion.  The solution was to lock the
+   dynarrs that were getting corrupted (in this case, the display-line
+   dynarrs) around calls to routines that weren't supposed to be changing
+   these dynarrs but might somehow be calling code that modified them.
+   This eventually revealed that there was a reentrancy problem with
+   redisplay that involved the QUIT mechanism and the processing done in
+   order to determine whether C-g had been pressed -- this processing
+   involves retrieving, processing and queueing pending events to see
+   whether any of them result in a C-g keypress.  However, at least under
+   MS Windows this can result in redisplay being called reentrantly.
+   For more info:--
+   
+  (Info-goto-node "(internals)Critical Redisplay Sections")
+
+*/
+
 #ifdef ERROR_CHECK_DYNARR
 DECLARE_INLINE_HEADER (
 int
-Dynarr_verify_pos_at (void *d, int pos, const Ascbyte *file, int line)
+Dynarr_verify_pos_at (void *d, Elemcount pos, const Ascbyte *file, int line)
 )
 {
   Dynarr *dy = (Dynarr *) d;
@@ -1790,7 +1861,7 @@
 
 DECLARE_INLINE_HEADER (
 int
-Dynarr_verify_pos_atp (void *d, int pos, const Ascbyte *file, int line)
+Dynarr_verify_pos_atp (void *d, Elemcount pos, const Ascbyte *file, int line)
 )
 {
   Dynarr *dy = (Dynarr *) d;
@@ -1830,7 +1901,7 @@
 
 DECLARE_INLINE_HEADER (
 int
-Dynarr_verify_pos_atp_allow_end (void *d, int pos, const Ascbyte *file,
+Dynarr_verify_pos_atp_allow_end (void *d, Elemcount pos, const Ascbyte *file,
 				 int line)
 )
 {
@@ -1873,30 +1944,42 @@
 
 #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__)
 #define Dynarr_verify_mod(d) Dynarr_verify_mod_1 (d, __FILE__, __LINE__)
-#define Dynarr_lock(d)				\
-do {						\
-  Dynarr *dy = Dynarr_verify_mod (d);		\
-  dy->locked = 1;				\
-} while (0)
-#define Dynarr_unlock(d)			\
-do {						\
-  Dynarr *dy = Dynarr_verify (d);		\
-  dy->locked = 0;				\
-} while (0)
-#else
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_lock (void *d)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  dy->locked = 1;
+}
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_unlock (void *d)
+)
+{
+  Dynarr *dy = Dynarr_verify (d);
+  assert (dy->locked);
+  dy->locked = 0;
+}
+
+#else /* not ERROR_CHECK_DYNARR */
+
 #define Dynarr_verify(d) ((Dynarr *) d)
 #define Dynarr_verify_mod(d) ((Dynarr *) d)
 #define Dynarr_lock(d) DO_NOTHING
 #define Dynarr_unlock(d) DO_NOTHING
+
 #endif /* ERROR_CHECK_DYNARR */
 
 /************* Dynarr creation *************/
 
-MODULE_API void *Dynarr_newf (int elsize);
+MODULE_API void *Dynarr_newf (Bytecount elsize);
 MODULE_API void Dynarr_free (void *d);
 
 #ifdef NEW_GC
-MODULE_API void *Dynarr_lisp_newf (int elsize,
+MODULE_API void *Dynarr_lisp_newf (Bytecount elsize,
 				   const struct lrecord_implementation 
 				   *dynarr_imp,
 				   const struct lrecord_implementation *imp);
@@ -1933,97 +2016,245 @@
 
 /************* Dynarr length/size retrieval and setting *************/
 
-/* Retrieve the length of a Dynarr.  The `+ 0' is to ensure that this cannot
+/* Retrieve the length of a dynarr.  The `+ 0' is to ensure that this cannot
    be used as an lvalue. */
 #define Dynarr_length(d) (Dynarr_verify (d)->len_ + 0)
-/* Retrieve the largest ever length seen of a Dynarr.  The `+ 0' is to
+/* Retrieve the largest ever length seen of a dynarr.  The `+ 0' is to
    ensure that this cannot be used as an lvalue. */
 #define Dynarr_largest(d) (Dynarr_verify (d)->largest_ + 0)
 /* Retrieve the number of elements that fit in the currently allocated
    space.  The `+ 0' is to ensure that this cannot be used as an lvalue. */
 #define Dynarr_max(d) (Dynarr_verify (d)->max_ + 0)
-/* Retrieve the advertised memory usage of a Dynarr, i.e. the number of
-   bytes occupied by the elements in the Dynarr, not counting any overhead. */
-#define Dynarr_sizeof(d) (Dynarr_length (d) * (d)->elsize)
-/* Actually set the length of a Dynarr.  This is a low-level routine that
-   should not be directly used; use Dynarr_set_length() instead if you need
-   to, but be very careful when doing so! */
-#define Dynarr_set_length_1(d, n)					\
-do {									\
-  Elemcount _dsl1_n = (n);						\
-  dynarr_checking_assert (_dsl1_n >= 0 && _dsl1_n <= Dynarr_max (d));	\
-  (void) Dynarr_verify_mod (d);						\
-  (d)->len_ = _dsl1_n;							\
-  /* Use the raw field references here otherwise we get a crash because	\
-     we've set the length but not yet fixed up the largest value. */	\
-  if ((d)->len_ > (d)->largest_)					\
-    (d)->largest_ = (d)->len_;						\
-  (void) Dynarr_verify_mod (d);						\
-} while (0)
-
-/* The following two defines will get you into real trouble if you aren't
-   careful.  But they can save a lot of execution time when used wisely. */
-#define Dynarr_set_length(d, n)						\
-do {									\
-  Elemcount _dsl_n = (n);						\
-  dynarr_checking_assert (_dsl_n >= 0 && _dsl_n <= Dynarr_largest (d)); \
-  Dynarr_set_length_1 (d, _dsl_n);					\
-} while (0)
-#define Dynarr_increment(d) \
-  Dynarr_set_length (d, Dynarr_length (d) + 1)
-
-/* Reset the Dynarr's length to 0. */
-#define Dynarr_reset(d) Dynarr_set_length (d, 0)
-
-MODULE_API void Dynarr_resize (void *dy, Elemcount size);
-
-#define Dynarr_resize_if(d, numels)			\
-do {							\
-  Elemcount _dri_numels = (numels);			\
-  if (Dynarr_length (d) + _dri_numels > Dynarr_max (d))	\
-    Dynarr_resize (d, Dynarr_length (d) + _dri_numels);	\
-} while (0)
+/* Return the size in bytes of an element in a dynarr. */
+#define Dynarr_elsize(d) (Dynarr_verify (d)->elsize_ + 0)
+/* Retrieve the advertised memory usage of a dynarr, i.e. the number of
+   bytes occupied by the elements in the dynarr, not counting any overhead. */
+#define Dynarr_sizeof(d) (Dynarr_length (d) * Dynarr_elsize (d))
+
+/* Actually set the length of a dynarr.  This is a low-level routine that
+   should not be directly used; use Dynarr_set_length() or
+   Dynarr_set_lengthr() instead. */
+DECLARE_INLINE_HEADER (
+void
+Dynarr_set_length_1 (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  dynarr_checking_assert (len >= 0 && len <= Dynarr_max (dy));
+  /* Use the raw field references here otherwise we get a crash because
+     we've set the length but not yet fixed up the largest value. */
+  dy->len_ = len;
+  if (dy->len_ > dy->largest_)
+    dy->largest_ = dy->len_;
+  (void) Dynarr_verify_mod (d);
+}
+
+/* "Restricted set-length": Set the length of dynarr D to LEN,
+    which must be in the range [0, Dynarr_largest(d)]. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_set_lengthr (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  dynarr_checking_assert (len >= 0 && len <= Dynarr_largest (dy));
+  Dynarr_set_length_1 (dy, len);
+}
+
+/* "Restricted increment": Increment the length of dynarr D by 1; the resulting
+    length must be in the range [0, Dynarr_largest(d)]. */
+
+#define Dynarr_incrementr(d) Dynarr_set_lengthr (d, Dynarr_length (d) + 1)
+
+
+MODULE_API void Dynarr_resize (void *d, Elemcount size);
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_resize_to_fit (void *d, Elemcount size)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  if (size > Dynarr_max (dy))
+    Dynarr_resize (dy, size);
+}
+
+#define Dynarr_resize_to_add(d, numels)			\
+  Dynarr_resize_to_fit (d, Dynarr_length (d) + numels)
+
+/* This is an optimization.  This is like Dynarr_set_length() but the length
+   is guaranteed to be at least as big as the existing length. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_increase_length (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  dynarr_checking_assert (len >= Dynarr_length (dy));
+  Dynarr_resize_to_fit (dy, len);
+  Dynarr_set_length_1 (dy, len);
+}
+
+/* Set the length of dynarr D to LEN.  If the length increases, resize as
+   necessary to fit. (NOTE: This will leave uninitialized memory.  If you
+   aren't planning on immediately overwriting the memory, use
+   Dynarr_set_length_and_zero() to zero out all the memory that would
+   otherwise be uninitialized.) */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_set_length (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  Elemcount old_len = Dynarr_length (dy);
+  if (old_len >= len)
+    Dynarr_set_lengthr (dy, len);
+  else
+    Dynarr_increase_length (d, len);
+}
+
+#define Dynarr_increment(d) Dynarr_increase_length (d, Dynarr_length (d) + 1)
+
+/* Zero LEN contiguous elements starting at POS. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_zero_many (void *d, Elemcount pos, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  memset ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), 0,
+	  len*Dynarr_elsize (dy));
+}
+
+/* This is an optimization.  This is like Dynarr_set_length_and_zero() but
+   the length is guaranteed to be at least as big as the existing
+   length. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_increase_length_and_zero (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  Elemcount old_len = Dynarr_length (dy);
+  Dynarr_increase_length (dy, len);
+  Dynarr_zero_many (dy, old_len, len - old_len);
+}
+
+/* Set the length of dynarr D to LEN.  If the length increases, resize as
+   necessary to fit and zero out all the elements between the old and new
+   lengths. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_set_length_and_zero (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  Elemcount old_len = Dynarr_length (dy);
+  if (old_len >= len)
+    Dynarr_set_lengthr (dy, len);
+  else
+    Dynarr_increase_length_and_zero (d, len);
+}
+
+/* Reset the dynarr's length to 0. */
+#define Dynarr_reset(d) Dynarr_set_lengthr (d, 0)
 
 #ifdef MEMORY_USAGE_STATS
 struct overhead_stats;
 Bytecount Dynarr_memory_usage (void *d, struct overhead_stats *stats);
 #endif
 
-/************* Adding/deleting elements to/from a Dynarr *************/
+/************* Adding/deleting elements to/from a dynarr *************/
+
+/* Set the Lisp implementation of the element at POS in dynarr D.  Only
+   does this if the dynarr holds Lisp objects of a particular type (the
+   objects themselves, not pointers to them), and only under NEW_GC. */
 
 #ifdef NEW_GC
-#define Dynarr_add(d, el)						\
+#define DYNARR_SET_LISP_IMP(d, pos)					\
 do {									\
-  const struct lrecord_implementation *imp = (d)->lisp_imp;		\
-  (void) Dynarr_verify_mod (d);						\
-  Dynarr_resize_if (d, 1);						\
-  ((d)->base)[Dynarr_length (d)] = (el);				\
-  if (imp)								\
+  if ((d)->lisp_imp)							\
     set_lheader_implementation						\
-     ((struct lrecord_header *)&(((d)->base)[Dynarr_length (d)]), imp);	\
-  Dynarr_set_length_1 (d, Dynarr_length (d) + 1);			\
-  (void) Dynarr_verify_mod (d);						\
+      ((struct lrecord_header *)&(((d)->base)[pos]), (d)->lisp_imp);	\
+} while (0)  
+#else
+#define DYNARR_SET_LISP_IMP(d, pos) DO_NOTHING
+#endif /* (not) NEW_GC */
+
+/* Add Element EL to the end of dynarr D. */
+
+#define Dynarr_add(d, el)			\
+do {						\
+  Elemcount _da_pos = Dynarr_length (d);	\
+  (void) Dynarr_verify_mod (d);			\
+  Dynarr_increment (d);				\
+  ((d)->base)[_da_pos] = (el);			\
+  DYNARR_SET_LISP_IMP (d, _da_pos);		\
 } while (0)
-#else /* not NEW_GC */
-#define Dynarr_add(d, el)				\
+
+/* Set EL as the element at position POS in dynarr D.
+   Expand the dynarr as necessary so that its length is enough to include
+   position POS within it, and zero out any new elements created as a
+   result of expansion, other than the one at POS. */
+
+#define Dynarr_set(d, pos, el)				\
 do {							\
+  Elemcount _ds_pos = (pos);				\
   (void) Dynarr_verify_mod (d);				\
-  Dynarr_resize_if (d, 1);				\
-  ((d)->base)[Dynarr_length (d)] = (el);		\
-  Dynarr_set_length_1 (d, Dynarr_length (d) + 1);	\
-  (void) Dynarr_verify_mod (d);				\
+  if (Dynarr_length (d) < _ds_pos + 1)			\
+    Dynarr_increase_length_and_zero (d, _ds_pos + 1);	\
+  ((d)->base)[_ds_pos] = (el);				\
+  DYNARR_SET_LISP_IMP (d, _ds_pos);			\
 } while (0)
-#endif /* not NEW_GC */
-
-
-MODULE_API void Dynarr_insert_many (void *d, const void *el, int len,
-				    int start);
-MODULE_API void Dynarr_delete_many (void *d, int start, int len);
-
-#define Dynarr_insert_many_at_start(d, el, len)	\
-  Dynarr_insert_many (d, el, len, 0)
+
+/* Add LEN contiguous elements, stored at BASE, to dynarr D.  If BASE is
+   NULL, reserve space but don't store anything. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_add_many (void *d, const void *base, Elemcount len)
+)
+{
+  /* This duplicates Dynarr_insert_many to some extent; but since it is
+     called so often, it seemed useful to remove the unnecessary stuff
+     from that function and to make it inline */
+  Dynarr *dy = Dynarr_verify_mod (d);
+  Elemcount pos = Dynarr_length (dy);
+  Dynarr_increase_length (dy, Dynarr_length (dy) + len);
+  if (base)
+    memcpy ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), base,
+	    len*Dynarr_elsize (dy));
+}
+
+/* Insert LEN elements, currently pointed to by BASE, into dynarr D
+   starting at position POS. */
+
+MODULE_API void Dynarr_insert_many (void *d, const void *base, Elemcount len,
+				    Elemcount pos);
+
+/* Prepend LEN elements, currently pointed to by BASE, to the beginning. */
+
+#define Dynarr_prepend_many(d, base, len) Dynarr_insert_many (d, base, len, 0)
+
+/* Add literal string S to dynarr D, which should hold chars or unsigned
+   chars.  The final zero byte is not stored. */
+
 #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1)
-#define Dynarr_add_lisp_string(d, s, codesys)			\
+
+/* Convert Lisp string S to an external encoding according to CODESYS and
+   add to dynarr D, which should hold chars or unsigned chars.  No final
+   zero byte is appended. */
+
+/* #### This should be an inline function but LISP_STRING_TO_SIZED_EXTERNAL
+   isn't declared yet. */
+
+#define Dynarr_add_ext_lisp_string(d, s, codesys)		\
 do {								\
   Lisp_Object dyna_ls_s = (s);					\
   Lisp_Object dyna_ls_cs = (codesys);				\
@@ -2035,34 +2266,28 @@
   Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc);			\
 } while (0)
 
-/* Add LEN contiguous elements to a Dynarr */
-
-DECLARE_INLINE_HEADER (
-void
-Dynarr_add_many (void *d, const void *el, int len)
-)
-{
-  /* This duplicates Dynarr_insert_many to some extent; but since it is
-     called so often, it seemed useful to remove the unnecessary stuff
-     from that function and to make it inline */
-  Dynarr *dy = Dynarr_verify_mod (d);
-  Dynarr_resize_if (dy, len);
-  /* Some functions call us with a value of 0 to mean "reserve space but
-     don't write into it" */
-  if (el)
-    memcpy ((char *) dy->base + Dynarr_sizeof (dy), el, len*dy->elsize);
-  Dynarr_set_length_1 (dy, Dynarr_length (dy) + len);
-  (void) Dynarr_verify_mod (dy);
-}
+/* Delete LEN elements starting at position POS. */
+
+MODULE_API void Dynarr_delete_many (void *d, Elemcount pos, Elemcount len);
+
+/* Pop off (i.e. delete) the last element from the dynarr and return it */
 
 #define Dynarr_pop(d)					\
   (dynarr_checking_assert (Dynarr_length (d) > 0),	\
    Dynarr_verify_mod (d)->len_--,			\
    Dynarr_at (d, Dynarr_length (d)))
-#define Dynarr_delete(d, i) Dynarr_delete_many (d, i, 1)
+
+/* Delete the item at POS */
+
+#define Dynarr_delete(d, pos) Dynarr_delete_many (d, pos, 1)
+
+/* Delete the item located at memory address P, which must be a `type *'
+   pointer, where `type' is the type of the elements of the dynarr. */
 #define Dynarr_delete_by_pointer(d, p) \
   Dynarr_delete_many (d, (p) - ((d)->base), 1)
 
+/* Delete all elements that are numerically equal to EL. */
+
 #define Dynarr_delete_object(d, el)		\
 do						\
 {						\
@@ -3200,11 +3425,11 @@
   return XREALINT (obj);
 }
 
-#else /* no error checking */
+#else /* not ERROR_CHECK_TYPES */
 
 #define XINT(obj) XREALINT (obj)
 
-#endif /* no error checking */
+#endif /* (not) ERROR_CHECK_TYPES */
 
 #define CHECK_INT(x) do {			\
   if (!INTP (x))				\
@@ -3216,6 +3441,10 @@
     x = wrong_type_argument (Qintegerp, x);	\
 } while (0)
 
+/* NOTE NOTE NOTE! This definition of "natural number" is mathematically
+   wrong.  Mathematically, a natural number is a positive integer; 0
+   isn't included.  This would be better called NONNEGINT(). */
+
 #define NATNUMP(x) (INTP (x) && XINT (x) >= 0)
 
 #define CHECK_NATNUM(x) do {			\
--- a/src/profile.c	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/profile.c	Sat Feb 20 03:46:22 2010 -0600
@@ -125,7 +125,7 @@
 {
   /* The hash code can safely be called from a signal handler except when
      it has to grow the hash table.  In this case, it calls realloc(),
-     which is not (in general) re-entrant.  The way we deal with this is
+     which is not (in general) reentrant.  The way we deal with this is
      documented at the top of this file. */
   if (!big_profile_table)
     big_profile_table = make_hash_table (2000);
--- a/src/redisplay-output.c	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/redisplay-output.c	Sat Feb 20 03:46:22 2010 -0600
@@ -83,7 +83,7 @@
 	 redisplay performance so avoiding all excess overhead is a
 	 good thing.  Is all of this true? */
       memcpy (cra->base, dra->base, sizeof (struct rune) * max_move);
-      Dynarr_set_length (cra, max_move);
+      Dynarr_set_lengthr (cra, max_move);
     }
   else
     Dynarr_reset (cra);
@@ -171,7 +171,7 @@
 	      tr = cdb->runes;
 	      memcpy (cdb, ddb, sizeof (struct display_block));
 	      cdb->runes = tr;
-	      Dynarr_increment (clp->display_blocks);
+	      Dynarr_incrementr (clp->display_blocks);
 	    }
 
 	  sync_rune_structs (w, cdb->runes, ddb->runes);
@@ -183,7 +183,7 @@
   else if (line >= Dynarr_length (cdla))
     {
       assert (line == Dynarr_length (cdla));
-      Dynarr_increment (cdla);
+      Dynarr_incrementr (cdla);
     }
 }
 
@@ -2464,7 +2464,7 @@
   /* If the number of display lines has shrunk, adjust. */
   if (cdla_len > ddla_len)
     {
-      Dynarr_set_length (cdla, ddla_len);
+      Dynarr_set_lengthr (cdla, ddla_len);
     }
 
   /* Output a vertical divider between windows, if necessary. */
--- a/src/redisplay.c	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/redisplay.c	Sat Feb 20 03:46:22 2010 -0600
@@ -728,7 +728,7 @@
 	  struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
 
 	  /* "add" the block to the list */
-	  Dynarr_increment (dl->display_blocks);
+	  Dynarr_incrementr (dl->display_blocks);
 
 	  /* initialize and return */
 	  dbp->type = type;
@@ -1221,7 +1221,7 @@
   if (local)
     Dynarr_add (data->db->runes, *crb);
   else
-    Dynarr_increment (data->db->runes);
+    Dynarr_incrementr (data->db->runes);
 
   data->pixpos += width;
 
@@ -4532,7 +4532,7 @@
       if (Dynarr_length (dla) == 0)
 	{
 	  if (Dynarr_largest (dla) > 0)
-	    Dynarr_increment (dla);
+	    Dynarr_incrementr (dla);
 	  else
 	    {
 	      struct display_line modeline;
@@ -5301,9 +5301,10 @@
 
 /*
 
-Info on Re-entrancy crashes, with backtraces given:
-
-  (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT")
+Info on reentrancy crashes, with backtraces given:
+
+  (Info-goto-node "(internals)Critical Redisplay Sections")
+
 */
 
 
@@ -5405,7 +5406,7 @@
       if (pos_of_dlp < 0)
 	Dynarr_add (dla, *dlp);
       else if (pos_of_dlp == Dynarr_length (dla))
-	Dynarr_increment (dla);
+	Dynarr_incrementr (dla);
       else
 	ABORT ();
 
@@ -5459,13 +5460,13 @@
   if (!in_display)
     depth = enter_redisplay_critical_section ();
 
-  /* This is one spot where a re-entrancy crash will occur, due to a check
+  /* This is one spot where a reentrancy crash will occur, due to a check
      in the dynarr to make sure it isn't "locked" */
 /*
 
-Info on Re-entrancy crashes, with backtraces given:
-
-  (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT")
+Info on reentrancy crashes, with backtraces given:
+
+  (Info-goto-node "(internals)Critical Redisplay Sections")
 */
 
   Dynarr_reset (dla);
@@ -5628,7 +5629,7 @@
       if (pos_of_dlp < 0)
 	Dynarr_add (dla, *dlp);
       else if (pos_of_dlp == Dynarr_length (dla))
-	Dynarr_increment (dla);
+	Dynarr_incrementr (dla);
       else
 	ABORT ();
 
@@ -8469,7 +8470,7 @@
 	      return;
 	    }
 
-	  Dynarr_insert_many_at_start (cache, Dynarr_begin (internal_cache),
+	  Dynarr_prepend_many (cache, Dynarr_begin (internal_cache),
 			      ic_elt + 1);
 	}
 
--- a/src/signal.c	Sat Feb 20 03:45:15 2010 -0600
+++ b/src/signal.c	Sat Feb 20 03:46:22 2010 -0600
@@ -1,6 +1,6 @@
 /* Handling asynchronous signals.
    Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
-   Copyright (C) 1995, 1996, 2001, 2002, 2004 Ben Wing.
+   Copyright (C) 1995, 1996, 2001, 2002, 2004, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -727,7 +727,7 @@
 
 Backtrace given in
 
-  (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT")
+  (Info-goto-node "(internals)Critical Redisplay Sections")
 
     */
       assert_with_message