diff src/fns.c @ 5475:248176c74e6b

Merge with trunk.
author Mats Lidell <matsl@xemacs.org>
date Sat, 23 Apr 2011 23:47:13 +0200
parents ac37a5f7e5be ccf7e84fe265
children d3e0482c7899
line wrap: on
line diff
--- a/src/fns.c	Tue Mar 29 00:02:47 2011 +0200
+++ b/src/fns.c	Sat Apr 23 23:47:13 2011 +0200
@@ -997,7 +997,7 @@
       assert (counting >= 0);
       /* And we're not prepared to handle COUNT from any other caller at the
 	 moment. */
-      assert (EQ (caller, QremoveX));
+      assert (EQ (caller, QremoveX)|| EQ (caller, QdeleteX));
     }
 
   check_test = get_check_test_function (item, &test, test_not, if_, if_not,
@@ -1007,9 +1007,6 @@
 
   if (CONSP (sequence))
     {
-      Lisp_Object elt, tail = Qnil;
-      struct gcpro gcpro1;
-
       if (EQ (caller, Qcount) && !NILP (from_end)
           && (!EQ (key, Qnil) ||
               check_test == check_other_nokey || check_test == check_if_nokey))
@@ -1024,8 +1021,6 @@
                                       start, end);
         }
 
-      GCPRO1 (tail);
-
       /* If COUNT is non-nil and FROM-END is t, we can give the tail
          containing the last match, since that's what #'remove* is
          interested in (a zero or negative COUNT won't ever reach
@@ -1037,7 +1032,7 @@
         }
 
       {
-        EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len)
+	GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
           {
             if (!(ii < ending))
               {
@@ -1058,10 +1053,9 @@
 
             ii++;
           }
+	END_GC_EXTERNAL_LIST_LOOP (elt);
       }
 
-      UNGCPRO;
-
       if ((ii < starting || (ii < ending && !NILP (end))) &&
           encountered != counting)
         {
@@ -2620,18 +2614,18 @@
                            Boolint reverse_test_order,
                            Lisp_Object start, Lisp_Object end)
 {
-  struct gcpro gcpro1, gcpro2;
-  Lisp_Object elt = Qnil, tail = list, tail_before = Qnil;
-  Elemcount len, ii = 0, starting = XINT (start);
+  struct gcpro gcpro1;
+  Lisp_Object tail_before = Qnil;
+  Elemcount ii = 0, starting = XINT (start);
   Elemcount ending = NILP (end) ? EMACS_INT_MAX : XINT (end);
 
-  GCPRO2 (elt, tail);
+  GCPRO1 (tail_before);
 
   if (check_test == check_eq_nokey)
     {
       /* TEST is #'eq, no need to call any C functions, and the test order
          won't be visible. */
-      EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len)
+      EXTERNAL_LIST_LOOP_3 (elt, list, tail)
 	{
           if (starting <= ii && ii < ending &&
               EQ (item, elt) == test_not_unboundp)
@@ -2652,15 +2646,17 @@
     }
   else
     {
-      EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len)
+      GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail)
         {
           if (starting <= ii && ii < ending &&
               (reverse_test_order ? 
                check_test (test, key, elt, item) :
-               check_test (test, key, item, elt)) == test_not_unboundp) 
+               check_test (test, key, item, elt)) == test_not_unboundp)
             {
               *cons_out = tail_before;
-              RETURN_UNGCPRO (make_integer (ii));
+	      XUNGCPRO (elt);
+	      UNGCPRO;
+	      return make_integer (ii);
             }
           else
             {
@@ -2672,6 +2668,7 @@
           ii++;
           tail_before = tail;
         }
+      END_GC_EXTERNAL_LIST_LOOP (elt);
     }
 
   RETURN_UNGCPRO (Qnil);
@@ -2858,22 +2855,16 @@
     }
   else
     {
-      Lisp_Object tailed = alist;
-      struct gcpro gcpro1;
-
-      GCPRO1 (tailed);
-      {
-        EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail)
-          {
-            tailed = tail;
-
-            if (check_test (test, key, item, elt_car) == test_not_unboundp)
+      GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
+	{
+	  if (CONSP (elt) && 
+	      check_test (test, key, item, XCAR (elt)) == test_not_unboundp)
               {
-                RETURN_UNGCPRO (elt);
+		XUNGCPRO (elt);
+		return elt;
               }
-          }
-      }
-      UNGCPRO;
+	}
+      END_GC_EXTERNAL_LIST_LOOP (elt);
     }
 		  
   return Qnil;
@@ -2967,22 +2958,16 @@
     }
   else
     {
-      struct gcpro gcpro1;
-      Lisp_Object tailed = alist;
-
-      GCPRO1 (tailed);
-      {
-        EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail)
-          {
-            tailed = tail;
-
-            if (check_test (test, key, item, elt_cdr) == test_not_unboundp)
-              {
-                RETURN_UNGCPRO (elt);
-              }
-          }
-      }
-      UNGCPRO;
+      GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
+	{
+	  if (CONSP (elt) &&
+	      check_test (test, key, item, XCDR (elt)) == test_not_unboundp)
+	    {
+	      XUNGCPRO (elt);
+	      return elt;
+	    }
+	}
+      END_GC_EXTERNAL_LIST_LOOP (elt);
     }
 		  
   return Qnil;
@@ -3012,9 +2997,6 @@
 
   if (CONSP (sequence))
     {
-      Lisp_Object elt, tail = Qnil;
-      struct gcpro gcpro1;
-
       if (!(starting < ending))
 	{
 	  check_sequence_range (sequence, start, end, Flength (sequence));
@@ -3023,10 +3005,8 @@
 	  return Qnil;
 	}
 
-      GCPRO1 (tail);
-
       {
-        EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len)
+	GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
           {
             if (starting <= ii && ii < ending
                 && check_test (test, key, item, elt) == test_not_unboundp)
@@ -3036,7 +3016,7 @@
 
                 if (NILP (from_end))
                   {
-                    UNGCPRO;
+		    XUNGCPRO (elt);
                     return result;
                   }
               }
@@ -3047,10 +3027,9 @@
             
             ii++;
           }
+	END_GC_EXTERNAL_LIST_LOOP (elt);
       }
 
-      UNGCPRO;
-
       if (ii < starting || (ii < ending && !NILP (end)))
 	{
 	  check_sequence_range (sequence, start, end, Flength (sequence));
@@ -3257,12 +3236,11 @@
 */
        (int nargs, Lisp_Object *args))
 {
-  Lisp_Object item = args[0], sequence = args[1], tail = sequence;
+  Lisp_Object item = args[0], sequence = args[1];
   Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX;
   Elemcount len, ii = 0, encountered = 0, presenting = 0;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_test = NULL;
-  struct gcpro gcpro1;
 
   PARSE_KEYWORDS (FdeleteX, nargs, args, 9,
 		  (test, if_not, if_, test_not, key, start, end, from_end,
@@ -3299,7 +3277,25 @@
 	    {
 	      return sequence;
 	    }
-	}
+
+          if (!NILP (from_end))
+            {
+              /* Sigh, this is inelegant. Force count_with_tail () to ignore
+                 the count keyword, so we get the actual number of matching
+                 elements, and can start removing from the beginning for the
+                 from-end case.  */
+              for (ii = XSUBR (GET_DEFUN_LISP_OBJECT (FdeleteX))->min_args;
+                   ii < nargs; ii += 2)
+                {
+                  if (EQ (args[ii], Q_count))
+                    {
+                      args[ii + 1] = Qnil;
+                      break;
+                    }
+                }
+              ii = 0;
+            }
+        }
     }
 
   check_test = get_check_test_function (item, &test, test_not, if_, if_not,
@@ -3307,14 +3303,15 @@
 
   if (CONSP (sequence))
     {
-      Lisp_Object prev_tail_list_elt = Qnil, list_elt = Qnil;
+      Lisp_Object prev_tail_list_elt = Qnil, ignore = Qnil;
       Elemcount list_len = 0, deleted = 0;
+      struct gcpro gcpro1;
 
       if (!NILP (count) && !NILP (from_end))
 	{
 	  /* Both COUNT and FROM-END were specified; we need to traverse the
 	     list twice. */
-	  Lisp_Object present = count_with_tail (&list_elt, nargs, args,
+	  Lisp_Object present = count_with_tail (&ignore, nargs, args,
 						 QdeleteX);
 
 	  if (ZEROP (present))
@@ -3332,11 +3329,11 @@
 	  presenting = presenting <= counting ? 0 : presenting - counting;
 	}
 
-      GCPRO1 (tail);
+      GCPRO1 (prev_tail_list_elt);
       ii = -1;
 
       {
-        EXTERNAL_LIST_LOOP_4_NO_DECLARE (list_elt, sequence, tail, list_len)
+	GC_EXTERNAL_LIST_LOOP_4 (list_elt, sequence, tail, list_len)
           {
             ii++;
 
@@ -3367,6 +3364,7 @@
                   }
               }
           }
+	END_GC_EXTERNAL_LIST_LOOP (list_elt);
       }
 
       UNGCPRO;
@@ -3604,10 +3602,9 @@
   Lisp_Object item = args[0], sequence = args[1], matched_count = Qnil,
     tail = Qnil;
   Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX;
-  Elemcount len, ii = 0, encountered = 0, presenting = 0;
+  Elemcount ii = 0, encountered = 0, presenting = 0;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_test = NULL;
-  struct gcpro gcpro1;
 
   PARSE_KEYWORDS (FremoveX, nargs, args, 9,
 		  (test, if_not, if_, test_not, key, start, end, from_end,
@@ -3646,6 +3643,24 @@
 	{
 	  return sequence;
 	}
+
+      if (!NILP (from_end))
+        {
+	  /* Sigh, this is inelegant. Force count_with_tail () to ignore the
+	     count keyword, so we get the actual number of matching
+	     elements, and can start removing from the beginning for the
+	     from-end case.  */
+          for (ii = XSUBR (GET_DEFUN_LISP_OBJECT (FremoveX))->min_args;
+               ii < nargs; ii += 2)
+            {
+              if (EQ (args[ii], Q_count))
+                {
+                  args[ii + 1] = Qnil;
+                  break;
+                }
+            }
+          ii = 0;
+        }
     }
 
   check_test = get_check_test_function (item, &test, test_not, if_, if_not,
@@ -3655,8 +3670,8 @@
 
   if (!ZEROP (matched_count))
     {
-      Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil;
-      GCPRO1 (tailing);
+      Lisp_Object result = Qnil, result_tail = Qnil;
+      struct gcpro gcpro1, gcpro2;
 
       if (!NILP (count) && !NILP (from_end))
 	{
@@ -3670,18 +3685,22 @@
 	  presenting = presenting <= counting ? 0 : presenting - counting;
 	}
 
+      GCPRO2 (result, tail);
       {
-        EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len)
+	GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing)
           {
             if (EQ (tail, tailing))
               {
+		XUNGCPRO (elt);
+		UNGCPRO;
+
                 if (NILP (result))
                   {
-                    RETURN_UNGCPRO (XCDR (tail));
+                    return XCDR (tail);
                   }
 
                 XSETCDR (result_tail, XCDR (tail));
-                RETURN_UNGCPRO (result);
+		return result;
               }
             else if (starting <= ii && ii < ending &&
                      (check_test (test, key, item, elt) == test_not_unboundp)
@@ -3707,8 +3726,8 @@
 
             ii++;
           }
+	END_GC_EXTERNAL_LIST_LOOP (elt); 
       }
-
       UNGCPRO;
 
       if (ii < starting || (ii < ending && !NILP (end)))
@@ -3827,12 +3846,12 @@
 				 Lisp_Object start,
 				 Lisp_Object end, Boolint copy)
 {
-  Lisp_Object checking = Qnil, elt, tail, result = list;
+  Lisp_Object checking = Qnil, result = list;
   Lisp_Object keyed, positioned, position_cons = Qnil, result_tail;
   Elemcount len = XINT (Flength (list)), pos, starting = XINT (start);
   Elemcount ending = (NILP (end) ? len : XINT (end)), greatest_pos_seen = -1;
   Elemcount ii = 0;
-  struct gcpro gcpro1, gcpro2;
+  struct gcpro gcpro1;
 
   /* We can't delete (or remove) as we go, because that breaks START and
      END.  We could if END were nil, and that would change an ON(N + 2)
@@ -3852,10 +3871,10 @@
   memset (&(deleting->bits), 0,
 	  sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
 
-  GCPRO2 (tail, keyed);
+  GCPRO1 (keyed);
 
   {
-    EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len)
+    GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail)
       {
         if (!(starting <= ii && ii <= ending) || bit_vector_bit (deleting, ii))
           {
@@ -3882,6 +3901,7 @@
           }
         ii++;
       }
+    END_GC_EXTERNAL_LIST_LOOP (elt); 
   }
 
   UNGCPRO;
@@ -3897,7 +3917,7 @@
 	  ii = 1;
 
 	  {
-            EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len)
+            EXTERNAL_LIST_LOOP_3 (elt, list, tail)
 	      {
 		if (ii == greatest_pos_seen)
 		  {
@@ -3915,7 +3935,7 @@
 	}
       else
 	{
-	  EXTERNAL_LIST_LOOP_DELETE_IF (elt0, list,
+	  EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
 					bit_vector_bit (deleting, ii++));
 	}
     }
@@ -3943,8 +3963,8 @@
 */
        (int nargs, Lisp_Object *args))
 {
-  Lisp_Object sequence = args[0], tail = sequence, keyed = Qnil, elt = Qnil;
-  Lisp_Object elt0 = Qnil, positioned = Qnil, ignore = Qnil;
+  Lisp_Object sequence = args[0], keyed = Qnil;
+  Lisp_Object positioned = Qnil, ignore = Qnil;
   Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0, jj = 0;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_test = NULL;
@@ -3976,10 +3996,10 @@
 	  Lisp_Object prev_tail = Qnil;
           Elemcount deleted = 0;
 
-	  GCPRO2 (tail, keyed);
+	  GCPRO2 (keyed, prev_tail);
 
           {
-            EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len)
+	    GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
               {
                 if (starting <= ii && ii < ending)
                   {
@@ -4010,9 +4030,10 @@
 
                 ii++;
               }
+	    END_GC_EXTERNAL_LIST_LOOP (elt);
           }
           {
-            EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len)
+	    GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
               {
                 if (!(starting <= ii && ii <= ending))
                   {
@@ -4021,7 +4042,7 @@
                     continue;
                   }
 
-                keyed = KEY (key, elt0);
+                keyed = KEY (key, elt);
                 positioned
                   = list_position_cons_before (&ignore, keyed, XCDR (tail),
                                                check_test, test_not_unboundp,
@@ -4050,7 +4071,9 @@
 
                 ii++;
               }
+	    END_GC_EXTERNAL_LIST_LOOP (elt);
           }
+
 	  UNGCPRO;
 
 	  if ((ii < starting || (ii < ending && !NILP (end))))
@@ -4070,6 +4093,8 @@
     }
   else if (STRINGP (sequence))
     {
+      Lisp_Object elt = Qnil;
+
       if (EQ (Qidentity, key))
 	{
 	  /* We know all the elements will be characters; set check_test to
@@ -4088,7 +4113,6 @@
 	  Ibyte *cursor = XSTRING_DATA (sequence), *startp = cursor;
 	  Elemcount deleted = 0;
 
-          elt = Qnil;
 	  GCPRO1 (elt);
 
 	  while (cursor_offset < byte_len)
@@ -4243,6 +4267,7 @@
       Elemcount deleted = 0;
       Lisp_Object *content = XVECTOR_DATA (sequence);
       struct Lisp_Bit_Vector *deleting;
+      Lisp_Object elt = Qnil;
 
       len = XVECTOR_LENGTH (sequence);
       check_sequence_range (sequence, start, end, make_integer (len));
@@ -4326,6 +4351,7 @@
 	 and KEY arguments, which may be non-deterministic from our
 	 perspective, we need the same algorithm as for vectors. */
       struct Lisp_Bit_Vector *deleting;
+      Lisp_Object elt = Qnil;
 
       len = bit_vector_length (bv);
 
@@ -4427,13 +4453,13 @@
 */
        (int nargs, Lisp_Object *args))
 {
-  Lisp_Object sequence = args[0], tail = sequence, keyed, positioned = Qnil;
+  Lisp_Object sequence = args[0], keyed, positioned = Qnil;
   Lisp_Object result = sequence, result_tail = result, cursor = Qnil;
-  Lisp_Object cons_with_shared_tail = Qnil, elt, elt0;
-  Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0;
+  Lisp_Object cons_with_shared_tail = Qnil;
+  Elemcount starting = 0, ending = EMACS_INT_MAX, ii = 0;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_test = NULL;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2;
 
   PARSE_KEYWORDS (Fremove_duplicates, nargs, args, 6,
 		  (test, key, test_not, start, end, from_end),
@@ -4467,10 +4493,10 @@
     {
       Lisp_Object ignore = Qnil;
 
-      GCPRO3 (tail, keyed, result);
+      GCPRO2 (keyed, result);
 
       {
-        EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len)
+	GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
           {
             if (starting <= ii && ii <= ending)
               {
@@ -4498,10 +4524,11 @@
 
             ii++;
           }
+	END_GC_EXTERNAL_LIST_LOOP (elt);
       }
 
       {
-        EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len)
+	GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
           {
             if (!(starting <= ii && ii <= ending))
               {
@@ -4514,7 +4541,7 @@
                removed cons to this one. Otherwise, the tail of the output list
                is shared with the input list, which is OK. */
 
-            keyed = KEY (key, elt0);
+            keyed = KEY (key, elt);
             positioned
               = list_position_cons_before (&ignore, keyed, XCDR (tail),
                                            check_test, test_not_unboundp,
@@ -4546,7 +4573,9 @@
 
             ii++;
           }
+	END_GC_EXTERNAL_LIST_LOOP (elt);
       }
+
       UNGCPRO;
 
       if ((ii < starting || (ii < ending && !NILP (end))))
@@ -7930,10 +7959,9 @@
     {
       if (NILP (from_end))
         {
-	  struct gcpro gcpro1, gcpro2;
-	  Lisp_Object tailed = Qnil;
-
-	  GCPRO2 (tailed, accum);
+	  struct gcpro gcpro1;
+
+	  GCPRO1 (accum);
 
           if (!UNBOUNDP (initial_value))
             {
@@ -7941,11 +7969,8 @@
             }
           else if (ending - starting)
             {
-              EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
+	      GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
                 {
-		  /* KEY may amputate the list behind us; make sure what
-		     remains to be processed is still reachable.  */
-		  tailed = tail;
                   if (ii == starting)
                     {
                       accum = KEY (key, elt);
@@ -7954,18 +7979,15 @@
                     }
                   ++ii;
                 }
+	      END_GC_EXTERNAL_LIST_LOOP (elt);
             }
 
 	  ii = 0;
 
           if (ending - starting)
             {
-              EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
+	      GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
                 {
-		  /* KEY or FUNCTION may amputate the list behind us; make
-		     sure what remains to be processed is still
-		     reachable.  */
-		  tailed = tail;
                   if (ii >= starting)
                     {
                       if (ii < ending)
@@ -7979,6 +8001,7 @@
                     }
                   ++ii;
                 }
+	      END_GC_EXTERNAL_LIST_LOOP (elt);
             }
 
 	  UNGCPRO;
@@ -8701,13 +8724,12 @@
 */
        (int nargs, Lisp_Object *args))
 {
-  Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil;
+  Lisp_Object new_ = args[0], item = args[1], sequence = args[2];
   Lisp_Object object_, position0;
   Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0;
   Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_test = NULL;
-  struct gcpro gcpro1;
 
   PARSE_KEYWORDS (Fnsubstitute, nargs, args, 9,
 		  (test, if_, if_not, test_not, key, start, end, count,
@@ -8749,11 +8771,9 @@
 
   if (CONSP (sequence))
     {
-      Lisp_Object elt;
-
       if (!NILP (count) && !NILP (from_end))
 	{
-	  Lisp_Object present = count_with_tail (&elt, nargs - 1, args + 1,
+	  Lisp_Object present = count_with_tail (&object_, nargs - 1, args + 1,
 						 Qnsubstitute);
 
 	  if (ZEROP (present))
@@ -8765,9 +8785,8 @@
 	  presenting = presenting <= counting ? 0 : presenting - counting;
 	}
 
-      GCPRO1 (tail);
       {
-        EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len)
+	GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
           {
             if (!(ii < ending))
               {
@@ -8789,8 +8808,8 @@
 
             ii++;
           }
+	END_GC_EXTERNAL_LIST_LOOP (elt);
       }
-      UNGCPRO;
 
       if ((ii < starting || (ii < ending && !NILP (end)))
 	  && encountered < counting)
@@ -8962,10 +8981,10 @@
        (int nargs, Lisp_Object *args))
 {
   Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil;
-  Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil;
+  Lisp_Object result = Qnil, result_tail = Qnil;
   Lisp_Object object, position0, matched_count;
   Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0;
-  Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0;
+  Elemcount ii = 0, counting = EMACS_INT_MAX, presenting = 0;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_test = NULL;
   struct gcpro gcpro1;
@@ -9042,19 +9061,22 @@
       presenting = presenting <= counting ? 0 : presenting - counting;
     }
 
-  GCPRO1 (tailing);
+  GCPRO1 (result);
   {
-    EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len)
+    GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing)
       {
         if (EQ (tail, tailing))
           {
+	    XUNGCPRO (elt);
+	    UNGCPRO;
+
             if (NILP (result))
               {
-                RETURN_UNGCPRO (XCDR (tail));
+                return XCDR (tail);
               }
 	  
             XSETCDR (result_tail, XCDR (tail));
-            RETURN_UNGCPRO (result);
+	    return result;
           }
         else if (starting <= ii && ii < ending &&
                  (check_test (test, key, item, elt) == test_not_unboundp)
@@ -9088,6 +9110,7 @@
 
         ii++;
       }
+    END_GC_EXTERNAL_LIST_LOOP (elt);
   }
   UNGCPRO;
 
@@ -9136,31 +9159,30 @@
 	check_test_func_t check_test, Boolint test_not_unboundp,
 	Lisp_Object test, Lisp_Object key, int depth)
 {
-  Lisp_Object keyed = KEY (key, tree), tailed = alist, aa, dd;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  Lisp_Object keyed = KEY (key, tree), aa, dd;
+  struct gcpro gcpro1;
 
   if (depth + lisp_eval_depth > max_lisp_eval_depth)
     {
       stack_overflow ("Stack overflow in sublis", tree); 
     }
 
-  GCPRO3 (tailed, alist, tree);
   {
-    EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail)
+    GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
       {
-        tailed = tail;
-
-        if (check_test (test, key, elt_car, keyed) == test_not_unboundp)
+        if (CONSP (elt) &&
+	    check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
           {
-            /* Don't use elt_cdr, it is helpful to allow TEST or KEY to
-               modify the alist while it executes. */
-            RETURN_UNGCPRO (XCDR (elt));
+	    XUNGCPRO (elt);
+	    return XCDR (elt);
           }
       }
+    END_GC_EXTERNAL_LIST_LOOP (elt);
   }
+
   if (!CONSP (tree))
     {
-      RETURN_UNGCPRO (tree);
+      return tree;
     }
 
   aa = sublis (alist, XCAR (tree), check_test, test_not_unboundp, test, key,
@@ -9170,10 +9192,10 @@
 
   if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree)))
     {
-      RETURN_UNGCPRO (tree);
-    }
-
-  RETURN_UNGCPRO (Fcons (aa, dd));
+      return tree;
+    }
+
+  return Fcons (aa, dd);
 }
 
 DEFUN ("sublis", Fsublis, 2, MANY, 0, /*
@@ -9223,8 +9245,8 @@
 	 Boolint test_not_unboundp,
 	 Lisp_Object test, Lisp_Object key, int depth)
 {
-  Lisp_Object tree_saved = tree, tailed = alist, tortoise = tree, keyed = Qnil;
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+  Lisp_Object tree_saved = tree, tortoise = tree, keyed = Qnil;
+  struct gcpro gcpro1, gcpro2;
   int count = 0;
 
   if (depth + lisp_eval_depth > max_lisp_eval_depth)
@@ -9232,7 +9254,7 @@
       stack_overflow ("Stack overflow in nsublis", tree); 
     }
 
-  GCPRO4 (tailed, alist, tree_saved, keyed);
+  GCPRO2 (tree_saved, keyed);
 
   while (CONSP (tree))
     {
@@ -9240,11 +9262,10 @@
       keyed = KEY (key, XCAR (tree));
 
       {
-	EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail)
+	GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
 	  {
-	    tailed = tail;
-
-	    if (check_test (test, key, elt_car, keyed) == test_not_unboundp)
+	    if (CONSP (elt) &&
+		check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
 	      {
 		CHECK_LISP_WRITEABLE (tree);
 		/* See comment in sublis() on using elt_cdr. */
@@ -9253,6 +9274,7 @@
 		break;
 	      }
 	  }
+	END_GC_EXTERNAL_LIST_LOOP (elt);
       }
 
       if (!replaced)
@@ -9268,19 +9290,18 @@
       replaced = 0;
 
       {
-	EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail)
+	GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
 	  {
-	    tailed = tail;
-
-	    if (check_test (test, key, elt_car, keyed) == test_not_unboundp)
+	    if (CONSP (elt) &&
+		check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
 	      {
 		CHECK_LISP_WRITEABLE (tree);
-		/* See comment in sublis() on using elt_cdr. */
 		XSETCDR (tree, XCDR (elt));
 		tree = Qnil;
 		break;
 	      }
 	  }
+	END_GC_EXTERNAL_LIST_LOOP (elt);
       }
 
       if (!NILP (tree))
@@ -9341,16 +9362,16 @@
   {
     /* nsublis() won't attempt to replace a cons handed to it, do that
        ourselves. */
-    EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail)
+    GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
       {
-        tailed = tail;
-
-        if (check_test (test, key, elt_car, keyed) == test_not_unboundp)
+        if (CONSP (elt) &&
+	    check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
           {
-            /* See comment in sublis() on using elt_cdr. */
-            RETURN_UNGCPRO (XCDR (elt));
+	    XUNGCPRO (elt);
+            return XCDR (elt);
           }
       }
+    END_GC_EXTERNAL_LIST_LOOP (elt);
   }
 
   UNGCPRO;
@@ -10521,13 +10542,12 @@
 static Lisp_Object
 venn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp)
 {
-  Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil;
+  Lisp_Object liszt1 = args[0], liszt2 = args[1];
   Lisp_Object result = EQ (caller, Qsubsetp) ? Qt : Qnil, result_tail = Qnil;
   Lisp_Object keyed = Qnil, ignore = Qnil;
-  Elemcount len;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_test = NULL;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2;
 
   PARSE_KEYWORDS_8 (caller, nargs, args, 4, (test, key, test_not, stable),
                     NULL, 2, 0);
@@ -10550,10 +10570,10 @@
   get_check_match_function (&test, test_not, Qnil, Qnil, key,
                             &test_not_unboundp, &check_test);
 
-  GCPRO3 (tail, keyed, result);
+  GCPRO2 (keyed, result);
 
   {
-    EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len)
+    GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
       {
         keyed = KEY (key, elt);
         if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
@@ -10581,6 +10601,7 @@
               }
           }
       }
+    END_GC_EXTERNAL_LIST_LOOP (elt);
   }
 
   UNGCPRO;
@@ -10596,7 +10617,7 @@
   Elemcount count;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_test = NULL;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
   PARSE_KEYWORDS_8 (caller, nargs, args, 3, (test, key, test_not),
                     NULL, 2, 0);
@@ -10619,9 +10640,9 @@
   get_check_match_function (&test, test_not, Qnil, Qnil, key,
                             &test_not_unboundp, &check_test);
 
-  GCPRO3 (tail, keyed, liszt1);
-
-  tortoise_elt = tail = liszt1, count = 0; 
+  tortoise_elt = tail = liszt1, count = 0;
+
+  GCPRO4 (tail, keyed, liszt1, tortoise_elt);
 
   while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
          (signal_malformed_list_error (liszt1), 0))
@@ -10793,11 +10814,10 @@
        (int nargs, Lisp_Object *args))
 {
   Lisp_Object liszt1 = args[0], liszt2 = args[1], ignore = Qnil;
-  Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, result, result_tail;
-  Elemcount len;
+  Lisp_Object keyed = Qnil, result, result_tail;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_test = NULL, check_match = NULL;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2;
 
   PARSE_KEYWORDS (Funion, nargs, args, 4, (test, key, test_not, stable), NULL);
 
@@ -10819,13 +10839,13 @@
   check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
                                           &test_not_unboundp, &check_test);
 
-  GCPRO3 (tail, keyed, result);
+  GCPRO2 (keyed, result);
 
   if (NILP (stable))
     {
       result = liszt2;
       {
-        EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len)
+	GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
           {
             keyed = KEY (key, elt);
             if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
@@ -10843,6 +10863,7 @@
                 result = Fcons (elt, result);
               }
           }
+	END_GC_EXTERNAL_LIST_LOOP (elt);
       }
     }
   else
@@ -10856,7 +10877,7 @@
          elements in any fashion; providing the functionality for a stable
          union is an XEmacs extension. */
       {
-        EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len)
+	GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2)
           {
             if (NILP (list_position_cons_before (&ignore, elt, liszt1,
                                                  check_match, test_not_unboundp,
@@ -10873,6 +10894,7 @@
                   }
               }
           }
+	END_GC_EXTERNAL_LIST_LOOP (elt);
       }
 
       result = NILP (result) ? liszt1 : nconc2 (Fcopy_list (liszt1), result);
@@ -10900,12 +10922,11 @@
 */
        (int nargs, Lisp_Object *args))
 {
-  Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil;
+  Lisp_Object liszt1 = args[0], liszt2 = args[1];
   Lisp_Object result = Qnil, result_tail = Qnil, keyed = Qnil, ignore = Qnil;
-  Elemcount len;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_match = NULL, check_test = NULL;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2;
 
   PARSE_KEYWORDS (Fset_exclusive_or, nargs, args, 4,
                   (test, key, test_not, stable), NULL);
@@ -10923,9 +10944,9 @@
   check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
                                           &test_not_unboundp, &check_test);
 
-  GCPRO3 (tail, keyed, result);
+  GCPRO2 (keyed, result);
   {
-    EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len)
+    GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
       {
         keyed = KEY (key, elt);
         if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
@@ -10947,10 +10968,11 @@
               }
           }
       }
+    END_GC_EXTERNAL_LIST_LOOP (elt);
   }
 
   {
-    EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len)
+    GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2)
       {
         if (NILP (list_position_cons_before (&ignore, elt, liszt1,
                                              check_match, test_not_unboundp,
@@ -10971,7 +10993,9 @@
               }
           }
       }
+    END_GC_EXTERNAL_LIST_LOOP (elt);
   }
+
   UNGCPRO;
 
   return result;
@@ -10996,7 +11020,7 @@
   Elemcount count;
   Boolint test_not_unboundp = 1;
   check_test_func_t check_match = NULL, check_test = NULL;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
 
   PARSE_KEYWORDS (Fnset_exclusive_or, nargs, args, 4,
                   (test, key, test_not, stable), NULL);
@@ -11014,10 +11038,10 @@
   check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
                                           &test_not_unboundp, &check_test);
 
-  GCPRO3 (tail, keyed, result);
-
   tortoise_elt = tail = liszt1, count = 0; 
 
+  GCPRO4 (tail, keyed, result, tortoise_elt);
+
   while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
          (signal_malformed_list_error (liszt1), 0))
     {