This commit was generated by cvs2svn to compensate for changes in r5670,
[chise/xemacs-chise.git.1] / src / fns.c
index c1fa079..22cba39 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -43,14 +43,12 @@ Boston, MA 02111-1307, USA.  */
 
 #include "buffer.h"
 #include "bytecode.h"
+#include "commands.h"
 #include "device.h"
 #include "events.h"
 #include "extents.h"
 #include "frame.h"
 #include "systime.h"
-#include "insdel.h"
-#include "lstream.h"
-#include "opaque.h"
 
 /* NOTE: This symbol is also used in lread.c */
 #define FEATUREP_SYNTAX
@@ -90,10 +88,10 @@ print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
 }
 
 static int
-bit_vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
+bit_vector_equal (Lisp_Object o1, Lisp_Object o2, int depth)
 {
-  struct Lisp_Bit_Vector *v1 = XBIT_VECTOR (obj1);
-  struct Lisp_Bit_Vector *v2 = XBIT_VECTOR (obj2);
+  struct Lisp_Bit_Vector *v1 = XBIT_VECTOR (o1);
+  struct Lisp_Bit_Vector *v2 = XBIT_VECTOR (o2);
 
   return ((bit_vector_length (v1) == bit_vector_length (v2)) &&
          !memcmp (v1->bits, v2->bits,
@@ -177,10 +175,10 @@ length_with_bytecode_hack (Lisp_Object seq)
     return XINT (Flength (seq));
   else
     {
-      struct Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (seq);
+      struct Lisp_Compiled_Function *b = XCOMPILED_FUNCTION (seq);
 
-      return (f->flags.interactivep ? COMPILED_INTERACTIVE :
-             f->flags.domainp      ? COMPILED_DOMAIN :
+      return (b->flags.interactivep ? COMPILED_INTERACTIVE :
+             b->flags.domainp      ? COMPILED_DOMAIN :
              COMPILED_DOC_STRING)
        + 1;
     }
@@ -208,9 +206,16 @@ Return the length of vector, bit vector, list or string SEQUENCE.
     return make_int (XSTRING_CHAR_LENGTH (sequence));
   else if (CONSP (sequence))
     {
-      int len;
-      GET_EXTERNAL_LIST_LENGTH (sequence, len);
-      return make_int (len);
+      Lisp_Object tail;
+      int i = 0;
+
+      EXTERNAL_LIST_LOOP (tail, sequence)
+       {
+         QUIT;
+         i++;
+       }
+
+      return make_int (i);
     }
   else if (VECTORP (sequence))
     return make_int (XVECTOR_LENGTH (sequence));
@@ -226,6 +231,9 @@ Return the length of vector, bit vector, list or string SEQUENCE.
     }
 }
 
+/* This does not check for quits.  That is safe
+   since it must terminate.  */
+
 DEFUN ("safe-length", Fsafe_length, 1, 1, 0, /*
 Return the length of a list, but avoid error or infinite loop.
 This function never gets an error.  If LIST is not really a list,
@@ -234,15 +242,17 @@ which is at least the number of distinct elements.
 */
        (list))
 {
-  Lisp_Object hare, tortoise;
-  int len;
+  Lisp_Object halftail = list; /* Used to detect circular lists. */
+  Lisp_Object tail;
+  int len = 0;
 
-  for (hare = tortoise = list, len = 0;
-       CONSP (hare) && (! EQ (hare, tortoise) || len == 0);
-       hare = XCDR (hare), len++)
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
-      if (len & 1)
-       tortoise = XCDR (tortoise);
+      if (EQ (tail, halftail) && len != 0)
+       break;
+      len++;
+      if ((len & 1) == 0)
+       halftail = XCDR (halftail);
     }
 
   return make_int (len);
@@ -498,65 +508,38 @@ arguments.  Each argument may be a list, vector, bit vector, or string.
   return concat (nargs, args, c_bit_vector, 0);
 }
 
-/* Copy a (possibly dotted) list.  LIST must be a cons.
-   Can't use concat (1, &alist, c_cons, 0) - doesn't handle dotted lists. */
-static Lisp_Object
-copy_list (Lisp_Object list)
-{
-  Lisp_Object list_copy = Fcons (XCAR (list), XCDR (list));
-  Lisp_Object last = list_copy;
-  Lisp_Object hare, tortoise;
-  int len;
-
-  for (tortoise = hare = XCDR (list), len = 1;
-       CONSP (hare);
-       hare = XCDR (hare), len++)
-    {
-      XCDR (last) = Fcons (XCAR (hare), XCDR (hare));
-      last = XCDR (last);
-
-      if (len < CIRCULAR_LIST_SUSPICION_LENGTH)
-       continue;
-      if (len & 1)
-       tortoise = XCDR (tortoise);
-      if (EQ (tortoise, hare))
-       signal_circular_list_error (list);
-    }
-
-  return list_copy;
-}
-
-DEFUN ("copy-list", Fcopy_list, 1, 1, 0, /*
-Return a copy of list LIST, which may be a dotted list.
-The elements of LIST are not copied; they are shared
+DEFUN ("copy-sequence", Fcopy_sequence, 1, 1, 0, /*
+Return a copy of a list, vector, bit vector or string.
+The elements of a list or vector are not copied; they are shared
 with the original.
 */
-       (list))
+       (arg))
 {
  again:
-  if (NILP  (list)) return list;
-  if (CONSP (list)) return copy_list (list);
+  if (NILP (arg)) return arg;
+  /* We handle conses separately because concat() is big and hairy and
+     doesn't handle (copy-sequence '(a b . c)) and it's easier to redo this
+     than to fix concat() without worrying about breaking other things.
+   */
+  if (CONSP (arg))
+    {
+      Lisp_Object head = Fcons (XCAR (arg), XCDR (arg));
+      Lisp_Object tail = head;
 
-  list = wrong_type_argument (Qlistp, list);
-  goto again;
-}
+      for (arg = XCDR (arg); CONSP (arg); arg = XCDR (arg))
+       {
+         XCDR (tail) = Fcons (XCAR (arg), XCDR (arg));
+         tail = XCDR (tail);
+         QUIT;
+       }
+      return head;
+    }
+  if (STRINGP     (arg)) return concat (1, &arg, c_string,     0);
+  if (VECTORP     (arg)) return concat (1, &arg, c_vector,     0);
+  if (BIT_VECTORP (arg)) return concat (1, &arg, c_bit_vector, 0);
 
-DEFUN ("copy-sequence", Fcopy_sequence, 1, 1, 0, /*
-Return a copy of list, vector, bit vector or string SEQUENCE.
-The elements of a list or vector are not copied; they are shared
-with the original. SEQUENCE may be a dotted list.
-*/
-       (sequence))
-{
- again:
-  if (NILP        (sequence)) return sequence;
-  if (CONSP       (sequence)) return copy_list (sequence);
-  if (STRINGP     (sequence)) return concat (1, &sequence, c_string,     0);
-  if (VECTORP     (sequence)) return concat (1, &sequence, c_vector,     0);
-  if (BIT_VECTORP (sequence)) return concat (1, &sequence, c_bit_vector, 0);
-
-  check_losing_bytecode ("copy-sequence", sequence);
-  sequence = wrong_type_argument (Qsequencep, sequence);
+  check_losing_bytecode ("copy-sequence", arg);
+  arg = wrong_type_argument (Qsequencep, arg);
   goto again;
 }
 
@@ -885,6 +868,7 @@ Relevant parts of the string-extent-data are copied in the new string.
   Lisp_Object val;
 
   CHECK_STRING (string);
+  /* Historically, FROM could not be omitted.  Whatever ... */
   CHECK_INT (from);
   get_string_range_char (string, from, to, &ccfr, &ccto,
                         GB_HISTORICAL_STRING_BEHAVIOR);
@@ -1036,9 +1020,9 @@ Return element of SEQUENCE at index N.
         args_out_of_range (sequence, n);
 #endif
     }
-  else if (STRINGP     (sequence) ||
-           VECTORP     (sequence) ||
-           BIT_VECTORP (sequence))
+  else if (STRINGP (sequence)
+           || VECTORP (sequence)
+           || BIT_VECTORP (sequence))
     return Faref (sequence, n);
 #ifdef LOSING_BYTECODE
   else if (COMPILED_FUNCTIONP (sequence))
@@ -1051,24 +1035,24 @@ Return element of SEQUENCE at index N.
         }
       /* Utter perversity */
       {
-       Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (sequence);
+        struct Lisp_Compiled_Function *b = XCOMPILED_FUNCTION (sequence);
         switch (idx)
           {
           case COMPILED_ARGLIST:
-            return compiled_function_arglist (f);
-          case COMPILED_INSTRUCTIONS:
-            return compiled_function_instructions (f);
+            return b->arglist;
+          case COMPILED_BYTECODE:
+            return b->bytecodes;
           case COMPILED_CONSTANTS:
-            return compiled_function_constants (f);
+            return b->constants;
           case COMPILED_STACK_DEPTH:
-            return compiled_function_stack_depth (f);
+            return make_int (b->maxdepth);
           case COMPILED_DOC_STRING:
-           return compiled_function_documentation (f);
+           return compiled_function_documentation (b);
           case COMPILED_DOMAIN:
-           return compiled_function_domain (f);
+           return compiled_function_domain (b);
           case COMPILED_INTERACTIVE:
-           if (f->flags.interactivep)
-             return compiled_function_interactive (f);
+           if (b->flags.interactivep)
+             return compiled_function_interactive (b);
            /* if we return nil, can't tell interactive with no args
               from noninteractive. */
            goto lose;
@@ -1086,126 +1070,19 @@ Return element of SEQUENCE at index N.
     }
 }
 
-DEFUN ("last", Flast, 1, 2, 0, /*
-Return the tail of list LIST, of length N (default 1).
-LIST may be a dotted list, but not a circular list.
-Optional argument N must be a non-negative integer.
-If N is zero, then the atom that terminates the list is returned.
-If N is greater than the length of LIST, then LIST itself is returned.
-*/
-       (list, n))
-{
-  int int_n, count;
-  Lisp_Object retval, tortoise, hare;
-
-  CHECK_LIST (list);
-
-  if (NILP (n))
-    int_n = 1;
-  else
-    {
-      CHECK_NATNUM (n);
-      int_n = XINT (n);
-    }
-
-  for (retval = tortoise = hare = list, count = 0;
-       CONSP (hare);
-       hare = XCDR (hare),
-        (int_n-- <= 0 ? ((void) (retval = XCDR (retval))) : (void)0),
-        count++)
-    {
-      if (count < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
-
-      if (count & 1)
-       tortoise = XCDR (tortoise);
-      if (EQ (hare, tortoise))
-       signal_circular_list_error (list);
-    }
-
-  return retval;
-}
-
-DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /*
-Modify LIST to remove the last N (default 1) elements.
-If LIST has N or fewer elements, nil is returned and LIST is unmodified.
-*/
-       (list, n))
-{
-  int int_n;
-
-  CHECK_LIST (list);
-
-  if (NILP (n))
-    int_n = 1;
-  else
-    {
-      CHECK_NATNUM (n);
-      int_n = XINT (n);
-    }
-
-  {
-    Lisp_Object last_cons = list;
-
-    EXTERNAL_LIST_LOOP_1 (list)
-      {
-       if (int_n-- < 0)
-         last_cons = XCDR (last_cons);
-      }
-
-    if (int_n >= 0)
-      return Qnil;
-
-    XCDR (last_cons) = Qnil;
-    return list;
-  }
-}
-
-DEFUN ("butlast", Fbutlast, 1, 2, 0, /*
-Return a copy of LIST with the last N (default 1) elements removed.
-If LIST has N or fewer elements, nil is returned.
-*/
-       (list, n))
-{
-  int int_n;
-
-  CHECK_LIST (list);
-
-  if (NILP (n))
-    int_n = 1;
-  else
-    {
-      CHECK_NATNUM (n);
-      int_n = XINT (n);
-    }
-
-  {
-    Lisp_Object retval = Qnil;
-    Lisp_Object tail = list;
-
-    EXTERNAL_LIST_LOOP_1 (list)
-      {
-       if (--int_n < 0)
-         {
-           retval = Fcons (XCAR (tail), retval);
-           tail = XCDR (tail);
-         }
-      }
-
-    return Fnreverse (retval);
-  }
-}
-
 DEFUN ("member", Fmember, 2, 2, 0, /*
 Return non-nil if ELT is an element of LIST.  Comparison done with `equal'.
 The value is actually the tail of LIST whose car is ELT.
 */
        (elt, list))
 {
-  Lisp_Object list_elt, tail;
-  EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (internal_equal (elt, list_elt, 0))
+      CONCHECK_CONS (tail);
+      if (internal_equal (elt, XCAR (tail), 0))
         return tail;
+      QUIT;
     }
   return Qnil;
 }
@@ -1218,11 +1095,13 @@ Do not use it.
 */
        (elt, list))
 {
-  Lisp_Object list_elt, tail;
-  EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (internal_old_equal (elt, list_elt, 0))
+      CONCHECK_CONS (tail);
+      if (internal_old_equal (elt, XCAR (tail), 0))
         return tail;
+      QUIT;
     }
   return Qnil;
 }
@@ -1233,11 +1112,14 @@ The value is actually the tail of LIST whose car is ELT.
 */
        (elt, list))
 {
-  Lisp_Object list_elt, tail;
-  EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (EQ_WITH_EBOLA_NOTICE (elt, list_elt))
+      REGISTER Lisp_Object tem;
+      CONCHECK_CONS (tail);
+      if (tem = XCAR (tail), EQ_WITH_EBOLA_NOTICE (elt, tem))
         return tail;
+      QUIT;
     }
   return Qnil;
 }
@@ -1250,11 +1132,14 @@ Do not use it.
 */
        (elt, list))
 {
-  Lisp_Object list_elt, tail;
-  EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (HACKEQ_UNSAFE (elt, list_elt))
+      REGISTER Lisp_Object tem;
+      CONCHECK_CONS (tail);
+      if (tem = XCAR (tail), HACKEQ_UNSAFE (elt, tem))
         return tail;
+      QUIT;
     }
   return Qnil;
 }
@@ -1262,10 +1147,11 @@ Do not use it.
 Lisp_Object
 memq_no_quit (Lisp_Object elt, Lisp_Object list)
 {
-  Lisp_Object list_elt, tail;
-  LIST_LOOP_3 (list_elt, list, tail)
+  REGISTER Lisp_Object tail;
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
-      if (EQ_WITH_EBOLA_NOTICE (elt, list_elt))
+      REGISTER Lisp_Object tem;
+      if (tem = XCAR (tail), EQ_WITH_EBOLA_NOTICE (elt, tem))
         return tail;
     }
   return Qnil;
@@ -1278,11 +1164,15 @@ The value is actually the element of LIST whose car equals KEY.
        (key, list))
 {
   /* This function can GC. */
-  Lisp_Object elt, elt_car, elt_cdr;
-  EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (internal_equal (key, elt_car, 0))
+      REGISTER Lisp_Object elt;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && internal_equal (XCAR (elt), key, 0))
        return elt;
+      QUIT;
     }
   return Qnil;
 }
@@ -1294,11 +1184,15 @@ The value is actually the element of LIST whose car equals KEY.
        (key, list))
 {
   /* This function can GC. */
-  Lisp_Object elt, elt_car, elt_cdr;
-  EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (internal_old_equal (key, elt_car, 0))
+      REGISTER Lisp_Object elt;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && internal_old_equal (XCAR (elt), key, 0))
        return elt;
+      QUIT;
     }
   return Qnil;
 }
@@ -1318,11 +1212,15 @@ Elements of LIST that are not conses are ignored.
 */
        (key, list))
 {
-  Lisp_Object elt, elt_car, elt_cdr;
-  EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (EQ_WITH_EBOLA_NOTICE (key, elt_car))
+      REGISTER Lisp_Object elt, tem;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCAR (elt), EQ_WITH_EBOLA_NOTICE (key, tem)))
        return elt;
+      QUIT;
     }
   return Qnil;
 }
@@ -1336,11 +1234,15 @@ Do not use it.
 */
        (key, list))
 {
-  Lisp_Object elt, elt_car, elt_cdr;
-  EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (HACKEQ_UNSAFE (key, elt_car))
+      REGISTER Lisp_Object elt, tem;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCAR (elt), HACKEQ_UNSAFE (key, tem)))
        return elt;
+      QUIT;
     }
   return Qnil;
 }
@@ -1352,12 +1254,13 @@ Lisp_Object
 assq_no_quit (Lisp_Object key, Lisp_Object list)
 {
   /* This cannot GC. */
-  Lisp_Object elt;
-  LIST_LOOP_2 (elt, list)
+  REGISTER Lisp_Object tail;
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
-      Lisp_Object elt_car = XCAR (elt);
-      if (EQ_WITH_EBOLA_NOTICE (key, elt_car))
-       return elt;
+      REGISTER Lisp_Object tem, elt;
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCAR (elt), EQ_WITH_EBOLA_NOTICE (key, tem)))
+         return elt;
     }
   return Qnil;
 }
@@ -1368,11 +1271,15 @@ The value is actually the element of LIST whose cdr equals KEY.
 */
        (key, list))
 {
-  Lisp_Object elt, elt_car, elt_cdr;
-  EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (internal_equal (key, elt_cdr, 0))
+      REGISTER Lisp_Object elt;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && internal_equal (XCDR (elt), key, 0))
        return elt;
+      QUIT;
     }
   return Qnil;
 }
@@ -1383,11 +1290,15 @@ The value is actually the element of LIST whose cdr equals KEY.
 */
        (key, list))
 {
-  Lisp_Object elt, elt_car, elt_cdr;
-  EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (internal_old_equal (key, elt_cdr, 0))
+      REGISTER Lisp_Object elt;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && internal_old_equal (XCDR (elt), key, 0))
        return elt;
+      QUIT;
     }
   return Qnil;
 }
@@ -1398,11 +1309,15 @@ The value is actually the element of LIST whose cdr is KEY.
 */
        (key, list))
 {
-  Lisp_Object elt, elt_car, elt_cdr;
-  EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (EQ_WITH_EBOLA_NOTICE (key, elt_cdr))
+      REGISTER Lisp_Object elt, tem;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCDR (elt), EQ_WITH_EBOLA_NOTICE (key, tem)))
        return elt;
+      QUIT;
     }
   return Qnil;
 }
@@ -1413,25 +1328,28 @@ The value is actually the element of LIST whose cdr is KEY.
 */
        (key, list))
 {
-  Lisp_Object elt, elt_car, elt_cdr;
-  EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, list)
+  REGISTER Lisp_Object tail;
+  LIST_LOOP (tail, list)
     {
-      if (HACKEQ_UNSAFE (key, elt_cdr))
+      REGISTER Lisp_Object elt, tem;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCDR (elt), HACKEQ_UNSAFE (key, tem)))
        return elt;
+      QUIT;
     }
   return Qnil;
 }
 
-/* Like Frassq, but caller must ensure that LIST is properly
-   nil-terminated and ebola-free. */
 Lisp_Object
 rassq_no_quit (Lisp_Object key, Lisp_Object list)
 {
-  Lisp_Object elt;
-  LIST_LOOP_2 (elt, list)
+  REGISTER Lisp_Object tail;
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
-      Lisp_Object elt_cdr = XCDR (elt);
-      if (EQ_WITH_EBOLA_NOTICE (key, elt_cdr))
+      REGISTER Lisp_Object elt, tem;
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCDR (elt), EQ_WITH_EBOLA_NOTICE (key, tem)))
        return elt;
     }
   return Qnil;
@@ -1448,9 +1366,24 @@ Also see: `remove'.
 */
        (elt, list))
 {
-  Lisp_Object list_elt;
-  EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
-                               (internal_equal (elt, list_elt, 0)));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (!NILP (tail))
+    {
+      CONCHECK_CONS (tail);
+      if (internal_equal (elt, XCAR (tail), 0))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+      QUIT;
+    }
   return list;
 }
 
@@ -1463,9 +1396,24 @@ of changing the value of `foo'.
 */
        (elt, list))
 {
-  Lisp_Object list_elt;
-  EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
-                               (internal_old_equal (elt, list_elt, 0)));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (!NILP (tail))
+    {
+      CONCHECK_CONS (tail);
+      if (internal_old_equal (elt, XCAR (tail), 0))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+      QUIT;
+    }
   return list;
 }
 
@@ -1478,9 +1426,25 @@ changing the value of `foo'.
 */
        (elt, list))
 {
-  Lisp_Object list_elt;
-  EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
-                               (EQ_WITH_EBOLA_NOTICE (elt, list_elt)));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (!NILP (tail))
+    {
+      REGISTER Lisp_Object tem;
+      CONCHECK_CONS (tail);
+      if (tem = XCAR (tail), EQ_WITH_EBOLA_NOTICE (elt, tem))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+      QUIT;
+    }
   return list;
 }
 
@@ -1493,21 +1457,50 @@ changing the value of `foo'.
 */
        (elt, list))
 {
-  Lisp_Object list_elt;
-  EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
-                               (HACKEQ_UNSAFE (elt, list_elt)));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (!NILP (tail))
+    {
+      REGISTER Lisp_Object tem;
+      CONCHECK_CONS (tail);
+      if (tem = XCAR (tail), HACKEQ_UNSAFE (elt, tem))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+      QUIT;
+    }
   return list;
 }
 
-/* Like Fdelq, but caller must ensure that LIST is properly
-   nil-terminated and ebola-free. */
+/* no quit, no errors; be careful */
 
 Lisp_Object
 delq_no_quit (Lisp_Object elt, Lisp_Object list)
 {
-  Lisp_Object list_elt;
-  LIST_LOOP_DELETE_IF (list_elt, list,
-                      (EQ_WITH_EBOLA_NOTICE (elt, list_elt)));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (CONSP (tail))
+    {
+      REGISTER Lisp_Object tem;
+      if (tem = XCAR (tail), EQ_WITH_EBOLA_NOTICE (elt, tem))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+    }
   return list;
 }
 
@@ -1523,24 +1516,26 @@ delq_no_quit_and_free_cons (Lisp_Object elt, Lisp_Object list)
 {
   REGISTER Lisp_Object tail = list;
   REGISTER Lisp_Object prev = Qnil;
+  struct Lisp_Cons *cons_to_free = NULL;
 
-  while (!NILP (tail))
+  while (CONSP (tail))
     {
-      REGISTER Lisp_Object tem = XCAR (tail);
-      if (EQ (elt, tem))
+      REGISTER Lisp_Object tem;
+      if (tem = XCAR (tail), EQ_WITH_EBOLA_NOTICE (elt, tem))
        {
-         Lisp_Object cons_to_free = tail;
          if (NILP (prev))
            list = XCDR (tail);
          else
            XCDR (prev) = XCDR (tail);
-         tail = XCDR (tail);
-         free_cons (XCONS (cons_to_free));
+         cons_to_free = XCONS (tail);
        }
       else
+       prev = tail;
+      tail = XCDR (tail);
+      if (cons_to_free)
        {
-         prev = tail;
-         tail = XCDR (tail);
+         free_cons (cons_to_free);
+         cons_to_free = NULL;
        }
     }
   return list;
@@ -1555,10 +1550,26 @@ the value of `foo'.
 */
        (key, list))
 {
-  Lisp_Object elt;
-  EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
-                               (CONSP (elt) &&
-                                internal_equal (key, XCAR (elt), 0)));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (!NILP (tail))
+    {
+      REGISTER Lisp_Object elt;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && internal_equal (key, XCAR (elt), 0))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+      QUIT;
+    }
   return list;
 }
 
@@ -1579,10 +1590,26 @@ the value of `foo'.
 */
        (key, list))
 {
-  Lisp_Object elt;
-  EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
-                               (CONSP (elt) &&
-                                EQ_WITH_EBOLA_NOTICE (key, XCAR (elt))));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (!NILP (tail))
+    {
+      REGISTER Lisp_Object elt, tem;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCAR (elt), EQ_WITH_EBOLA_NOTICE (key, tem)))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+      QUIT;
+    }
   return list;
 }
 
@@ -1591,10 +1618,24 @@ the value of `foo'.
 Lisp_Object
 remassq_no_quit (Lisp_Object key, Lisp_Object list)
 {
-  Lisp_Object elt;
-  LIST_LOOP_DELETE_IF (elt, list,
-                      (CONSP (elt) &&
-                       EQ_WITH_EBOLA_NOTICE (key, XCAR (elt))));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (CONSP (tail))
+    {
+      REGISTER Lisp_Object elt, tem;
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCAR (elt), EQ_WITH_EBOLA_NOTICE (key, tem)))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+    }
   return list;
 }
 
@@ -1607,10 +1648,26 @@ the value of `foo'.
 */
        (value, list))
 {
-  Lisp_Object elt;
-  EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
-                               (CONSP (elt) &&
-                                internal_equal (value, XCDR (elt), 0)));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (!NILP (tail))
+    {
+      REGISTER Lisp_Object elt;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && internal_equal (value, XCDR (elt), 0))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+      QUIT;
+    }
   return list;
 }
 
@@ -1623,21 +1680,52 @@ the value of `foo'.
 */
        (value, list))
 {
-  Lisp_Object elt;
-  EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
-                               (CONSP (elt) &&
-                                EQ_WITH_EBOLA_NOTICE (value, XCDR (elt))));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (!NILP (tail))
+    {
+      REGISTER Lisp_Object elt, tem;
+      CONCHECK_CONS (tail);
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCAR (elt), EQ_WITH_EBOLA_NOTICE (value, tem)))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+      QUIT;
+    }
   return list;
 }
 
-/* Like Fremrassq, fast and unsafe; be careful */
+/* no quit, no errors; be careful */
+
 Lisp_Object
 remrassq_no_quit (Lisp_Object value, Lisp_Object list)
 {
-  Lisp_Object elt;
-  LIST_LOOP_DELETE_IF (elt, list,
-                      (CONSP (elt) &&
-                       EQ_WITH_EBOLA_NOTICE (value, XCDR (elt))));
+  REGISTER Lisp_Object tail = list;
+  REGISTER Lisp_Object prev = Qnil;
+
+  while (CONSP (tail))
+    {
+      REGISTER Lisp_Object elt, tem;
+      elt = XCAR (tail);
+      if (CONSP (elt) && (tem = XCAR (elt), EQ_WITH_EBOLA_NOTICE (value, tem)))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XCDR (prev) = XCDR (tail);
+       }
+      else
+       prev = tail;
+      tail = XCDR (tail);
+    }
   return list;
 }
 
@@ -1657,6 +1745,7 @@ Also see: `reverse'.
   while (!NILP (tail))
     {
       REGISTER Lisp_Object next;
+      QUIT;
       CONCHECK_CONS (tail);
       next = XCDR (tail);
       XCDR (tail) = prev;
@@ -1673,13 +1762,17 @@ See also the function `nreverse', which is used more often.
 */
        (list))
 {
-  Lisp_Object reversed_list = Qnil;
-  Lisp_Object elt;
-  EXTERNAL_LIST_LOOP_2 (elt, list)
+  REGISTER Lisp_Object tail;
+  Lisp_Object new = Qnil;
+
+  for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
-      reversed_list = Fcons (elt, reversed_list);
+      new = Fcons (XCAR (tail), new);
+      QUIT;
     }
-  return reversed_list;
+  if (!NILP (tail))
+    dead_wrong_type_argument (Qlistp, tail);
+  return new;
 }
 \f
 static Lisp_Object list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
@@ -1985,12 +2078,13 @@ If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with
 Lisp_Object
 internal_plist_get (Lisp_Object plist, Lisp_Object property)
 {
-  Lisp_Object tail;
+  Lisp_Object tail = plist;
 
-  for (tail = plist; !NILP (tail); tail = XCDR (XCDR (tail)))
+  for (; !NILP (tail); tail = XCDR (XCDR (tail)))
     {
-      if (EQ (XCAR (tail), property))
-       return XCAR (XCDR (tail));
+      struct Lisp_Cons *c = XCONS (tail);
+      if (EQ (c->car, property))
+       return XCAR (c->cdr);
     }
 
   return Qunbound;
@@ -2020,22 +2114,26 @@ internal_plist_put (Lisp_Object *plist, Lisp_Object property,
 int
 internal_remprop (Lisp_Object *plist, Lisp_Object property)
 {
-  Lisp_Object tail, prev;
+  Lisp_Object tail = *plist;
 
-  for (tail = *plist, prev = Qnil;
-       !NILP (tail);
+  if (NILP (tail))
+    return 0;
+
+  if (EQ (XCAR (tail), property))
+    {
+      *plist = XCDR (XCDR (tail));
+      return 1;
+    }
+
+  for (tail = XCDR (tail); !NILP (XCDR (tail));
        tail = XCDR (XCDR (tail)))
     {
-      if (EQ (XCAR (tail), property))
+      struct Lisp_Cons *c = XCONS (tail);
+      if (EQ (XCAR (c->cdr), property))
        {
-         if (NILP (prev))
-           *plist = XCDR (XCDR (tail));
-         else
-           XCDR (XCDR (prev)) = XCDR (XCDR (tail));
+         c->cdr = XCDR (XCDR (c->cdr));
          return 1;
        }
-      else
-       prev = tail;
     }
 
   return 0;
@@ -2110,7 +2208,7 @@ advance_plist_pointers (Lisp_Object *plist,
   Lisp_Object *tortsave = *tortoise;
 
   /* Note that our "fixing" may be more brutal than necessary,
-     but it's the user's own problem, not ours, if they went in and
+     but it's the user's own problem, not ours. if they went in and
      manually fucked up a plist. */
 
   for (i = 0; i < 2; i++)
@@ -2284,7 +2382,9 @@ one of the properties on the list.
        (plist, prop, default_))
 {
   Lisp_Object val = external_plist_get (&plist, prop, 0, ERROR_ME);
-  return UNBOUNDP (val) ? default_ : val;
+  if (UNBOUNDP (val))
+    return default_;
+  return val;
 }
 
 DEFUN ("plist-put", Fplist_put, 3, 3, 0, /*
@@ -2320,8 +2420,7 @@ Return t if PROP has a value specified in PLIST.
 */
        (plist, prop))
 {
-  Lisp_Object val = Fplist_get (plist, prop, Qunbound);
-  return UNBOUNDP (val) ? Qnil : Qt;
+  return UNBOUNDP (Fplist_get (plist, prop, Qunbound)) ? Qnil : Qt;
 }
 
 DEFUN ("check-valid-plist", Fcheck_valid_plist, 1, 1, 0, /*
@@ -2410,8 +2509,7 @@ The new plist is returned.  If NIL-MEANS-NOT-PRESENT is given, the
       /* external_remprop returns 1 if it removed any property.
         We have to loop till it didn't remove anything, in case
         the property occurs many times. */
-      while (external_remprop (&XCDR (next), prop, 0, ERROR_ME))
-       DO_NOTHING;
+      while (external_remprop (&XCDR (next), prop, 0, ERROR_ME));
       plist = Fcdr (next);
     }
 
@@ -2422,7 +2520,7 @@ DEFUN ("lax-plist-get", Flax_plist_get, 2, 3, 0, /*
 Extract a value from a lax property list.
 
 LAX-PLIST is a lax property list, which is a list of the form \(PROP1
-VALUE1 PROP2 VALUE2...), where comparisons between properties is done
+VALUE1 PROP2 VALUE2...), where comparions between properties is done
 using `equal' instead of `eq'.  This function returns the value
 corresponding to the given PROP, or DEFAULT if PROP is not one of the
 properties on the list.
@@ -2438,7 +2536,7 @@ properties on the list.
 DEFUN ("lax-plist-put", Flax_plist_put, 3, 3, 0, /*
 Change value in LAX-PLIST of PROP to VAL.
 LAX-PLIST is a lax property list, which is a list of the form \(PROP1
-VALUE1 PROP2 VALUE2...), where comparisons between properties is done
+VALUE1 PROP2 VALUE2...), where comparions between properties is done
 using `equal' instead of `eq'.  PROP is usually a symbol and VAL is
 any object.  If PROP is already a property on the list, its value is
 set to VAL, otherwise the new PROP VAL pair is added.  The new plist
@@ -2454,7 +2552,7 @@ use the new value.  The LAX-PLIST is modified by side effects.
 DEFUN ("lax-plist-remprop", Flax_plist_remprop, 2, 2, 0, /*
 Remove from LAX-PLIST the property PROP and its value.
 LAX-PLIST is a lax property list, which is a list of the form \(PROP1
-VALUE1 PROP2 VALUE2...), where comparisons between properties is done
+VALUE1 PROP2 VALUE2...), where comparions between properties is done
 using `equal' instead of `eq'.  PROP is usually a symbol.  The new
 plist is returned; use `(setq x (lax-plist-remprop x prop val))' to be
 sure to use the new value.  The LAX-PLIST is modified by side effects.
@@ -2468,7 +2566,7 @@ sure to use the new value.  The LAX-PLIST is modified by side effects.
 DEFUN ("lax-plist-member", Flax_plist_member, 2, 2, 0, /*
 Return t if PROP has a value specified in LAX-PLIST.
 LAX-PLIST is a lax property list, which is a list of the form \(PROP1
-VALUE1 PROP2 VALUE2...), where comparisons between properties is done
+VALUE1 PROP2 VALUE2...), where comparions between properties is done
 using `equal' instead of `eq'.
 */
        (lax_plist, prop))
@@ -2511,8 +2609,7 @@ The new plist is returned.  If NIL-MEANS-NOT-PRESENT is given, the
       /* external_remprop returns 1 if it removed any property.
         We have to loop till it didn't remove anything, in case
         the property occurs many times. */
-      while (external_remprop (&XCDR (next), prop, 1, ERROR_ME))
-       DO_NOTHING;
+      while (external_remprop (&XCDR (next), prop, 1, ERROR_ME));
       lax_plist = Fcdr (next);
     }
 
@@ -2633,35 +2730,37 @@ or string.  See also `put', `remprop', and `object-plist'.
 */
        (object, propname, default_))
 {
+  Lisp_Object val;
+
   /* Various places in emacs call Fget() and expect it not to quit,
      so don't quit. */
 
   /* It's easiest to treat symbols specially because they may not
      be an lrecord */
   if (SYMBOLP (object))
-    return symbol_getprop (object, propname, default_);
+    val = symbol_getprop (object, propname, default_);
   else if (STRINGP (object))
-    return string_getprop (XSTRING (object), propname, default_);
+    val = string_getprop (XSTRING (object), propname, default_);
   else if (LRECORDP (object))
     {
-      CONST struct lrecord_implementation *imp
-       = XRECORD_LHEADER_IMPLEMENTATION (object);
-      if (!imp->getprop)
+      CONST struct lrecord_implementation
+       *imp = XRECORD_LHEADER_IMPLEMENTATION (object);
+      if (imp->getprop)
+       {
+         val = (imp->getprop) (object, propname);
+         if (UNBOUNDP (val))
+           val = default_;
+       }
+      else
        goto noprops;
-
-      {
-       Lisp_Object val = (imp->getprop) (object, propname);
-       if (UNBOUNDP (val))
-         val = default_;
-       return val;
-      }
     }
   else
     {
     noprops:
       signal_simple_error ("Object type has no properties", object);
-      return Qnil;             /* Not reached */
     }
+
+  return val;
 }
 
 DEFUN ("put", Fput, 3, 3, 0, /*
@@ -2782,7 +2881,7 @@ interpretation, this will probably have no effect at all.)
 
 \f
 int
-internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
+internal_equal (Lisp_Object o1, Lisp_Object o2, int depth)
 {
   if (depth > 200)
     error ("Stack overflow in equal");
@@ -2790,28 +2889,28 @@ internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
  do_cdr:
 #endif
   QUIT;
-  if (EQ_WITH_EBOLA_NOTICE (obj1, obj2))
+  if (EQ_WITH_EBOLA_NOTICE (o1, o2))
     return 1;
   /* Note that (equal 20 20.0) should be nil */
-  if (XTYPE (obj1) != XTYPE (obj2))
+  else if (XTYPE (o1) != XTYPE (o2))
     return 0;
 #ifndef LRECORD_CONS
-  if (CONSP (obj1))
+  else if (CONSP (o1))
     {
-      if (!internal_equal (XCAR (obj1), XCAR (obj2), depth + 1))
+      if (!internal_equal (XCAR (o1), XCAR (o2), depth + 1))
         return 0;
-      obj1 = XCDR (obj1);
-      obj2 = XCDR (obj2);
+      o1 = XCDR (o1);
+      o2 = XCDR (o2);
       goto do_cdr;
     }
 #endif
 #ifndef LRECORD_VECTOR
-  if (VECTORP (obj1))
+  else if (VECTORP (o1))
     {
-      Lisp_Object *v1 = XVECTOR_DATA (obj1);
-      Lisp_Object *v2 = XVECTOR_DATA (obj2);
-      int len = XVECTOR_LENGTH (obj1);
-      if (len != XVECTOR_LENGTH (obj2))
+      Lisp_Object *v1 = XVECTOR_DATA (o1);
+      Lisp_Object *v2 = XVECTOR_DATA (o2);
+      int len = XVECTOR_LENGTH (o1);
+      if (len != XVECTOR_LENGTH (o2))
        return 0;
       while (len--)
        if (!internal_equal (*v1++, *v2++, depth + 1))
@@ -2820,22 +2919,25 @@ internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
     }
 #endif
 #ifndef LRECORD_STRING
-  if (STRINGP (obj1))
+  else if (STRINGP (o1))
     {
       Bytecount len;
-      return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) &&
-             !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len));
+      return (((len = XSTRING_LENGTH (o1)) == XSTRING_LENGTH (o2)) &&
+             !memcmp (XSTRING_DATA (o1), XSTRING_DATA (o2), len));
     }
 #endif
-  if (LRECORDP (obj1))
+  else if (LRECORDP (o1))
     {
       CONST struct lrecord_implementation
-       *imp1 = XRECORD_LHEADER_IMPLEMENTATION (obj1),
-       *imp2 = XRECORD_LHEADER_IMPLEMENTATION (obj2);
-
-      return (imp1 == imp2) &&
+       *imp1 = XRECORD_LHEADER_IMPLEMENTATION (o1),
+       *imp2 = XRECORD_LHEADER_IMPLEMENTATION (o2);
+      if (imp1 != imp2)
+       return 0;
+      else if (imp1->equal == 0)
        /* EQ-ness of the objects was noticed above */
-       (imp1->equal && (imp1->equal) (obj1, obj2, depth));
+       return 0;
+      else
+       return (imp1->equal) (o1, o2, depth);
     }
 
   return 0;
@@ -2847,7 +2949,7 @@ internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
    but that seems unlikely. */
 
 static int
-internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
+internal_old_equal (Lisp_Object o1, Lisp_Object o2, int depth)
 {
   if (depth > 200)
     error ("Stack overflow in equal");
@@ -2855,37 +2957,64 @@ internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
  do_cdr:
 #endif
   QUIT;
-  if (HACKEQ_UNSAFE (obj1, obj2))
+  if (HACKEQ_UNSAFE (o1, o2))
     return 1;
   /* Note that (equal 20 20.0) should be nil */
-  if (XTYPE (obj1) != XTYPE (obj2))
+  else if (XTYPE (o1) != XTYPE (o2))
     return 0;
 #ifndef LRECORD_CONS
-  if (CONSP (obj1))
+  else if (CONSP (o1))
     {
-      if (!internal_old_equal (XCAR (obj1), XCAR (obj2), depth + 1))
+      if (!internal_old_equal (XCAR (o1), XCAR (o2), depth + 1))
         return 0;
-      obj1 = XCDR (obj1);
-      obj2 = XCDR (obj2);
+      o1 = XCDR (o1);
+      o2 = XCDR (o2);
       goto do_cdr;
     }
 #endif
 #ifndef LRECORD_VECTOR
-  if (VECTORP (obj1))
+  else if (VECTORP (o1))
     {
-      Lisp_Object *v1 = XVECTOR_DATA (obj1);
-      Lisp_Object *v2 = XVECTOR_DATA (obj2);
-      int len = XVECTOR_LENGTH (obj1);
-      if (len != XVECTOR_LENGTH (obj2))
+      int indice;
+      int len = XVECTOR_LENGTH (o1);
+      if (len != XVECTOR_LENGTH (o2))
        return 0;
-      while (len--)
-       if (!internal_old_equal (*v1++, *v2++, depth + 1))
-         return 0;
+      for (indice = 0; indice < len; indice++)
+       {
+         if (!internal_old_equal (XVECTOR_DATA (o1) [indice],
+                                  XVECTOR_DATA (o2) [indice],
+                                  depth + 1))
+            return 0;
+       }
       return 1;
     }
 #endif
+#ifndef LRECORD_STRING
+  else if (STRINGP (o1))
+    {
+      Bytecount len = XSTRING_LENGTH (o1);
+      if (len != XSTRING_LENGTH (o2))
+       return 0;
+      if (memcmp (XSTRING_DATA (o1), XSTRING_DATA (o2), len))
+       return 0;
+      return 1;
+    }
+#endif
+  else if (LRECORDP (o1))
+    {
+      CONST struct lrecord_implementation
+       *imp1 = XRECORD_LHEADER_IMPLEMENTATION (o1),
+       *imp2 = XRECORD_LHEADER_IMPLEMENTATION (o2);
+      if (imp1 != imp2)
+       return 0;
+      else if (imp1->equal == 0)
+       /* EQ-ness of the objects was noticed above */
+       return 0;
+      else
+       return (imp1->equal) (o1, o2, depth);
+    }
 
-  return internal_equal (obj1, obj2, depth);
+  return 0;
 }
 
 DEFUN ("equal", Fequal, 2, 2, 0, /*
@@ -2895,9 +3024,9 @@ Conses are compared by comparing the cars and the cdrs.
 Vectors and strings are compared element by element.
 Numbers are compared by value.  Symbols must match exactly.
 */
-       (obj1, obj2))
+       (o1, o2))
 {
-  return internal_equal (obj1, obj2, 0) ? Qt : Qnil;
+  return internal_equal (o1, o2, 0) ? Qt : Qnil;
 }
 
 DEFUN ("old-equal", Fold_equal, 2, 2, 0, /*
@@ -2909,9 +3038,9 @@ this is known as the "char-int confoundance disease." See `eq' and
 This function is provided only for byte-code compatibility with v19.
 Do not use it.
 */
-       (obj1, obj2))
+       (o1, o2))
 {
-  return internal_old_equal (obj1, obj2, 0) ? Qt : Qnil;
+  return internal_old_equal (o1, o2, 0) ? Qt : Qnil;
 }
 
 \f
@@ -2963,53 +3092,12 @@ ARRAY is a vector, bit vector, or string.
 }
 
 Lisp_Object
-nconc2 (Lisp_Object arg1, Lisp_Object arg2)
+nconc2 (Lisp_Object s1, Lisp_Object s2)
 {
   Lisp_Object args[2];
-  struct gcpro gcpro1;
-  args[0] = arg1;
-  args[1] = arg2;
-
-  GCPRO1 (args[0]);
-  gcpro1.nvars = 2;
-
-  RETURN_UNGCPRO (bytecode_nconc2 (args));
-}
-
-Lisp_Object
-bytecode_nconc2 (Lisp_Object *args)
-{
- retry:
-
-  if (CONSP (args[0]))
-    {
-      /* (setcdr (last args[0]) args[1]) */
-      Lisp_Object tortoise, hare;
-      int count;
-
-      for (hare = tortoise = args[0], count = 0;
-          CONSP (XCDR (hare));
-          hare = XCDR (hare), count++)
-       {
-         if (count < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
-
-         if (count & 1)
-           tortoise = XCDR (tortoise);
-         if (EQ (hare, tortoise))
-           signal_circular_list_error (args[0]);
-       }
-      XCDR (hare) = args[1];
-      return args[0];
-    }
-  else if (NILP (args[0]))
-    {
-      return args[1];
-    }
-  else
-    {
-      args[0] = wrong_type_argument (args[0], Qlistp);
-      goto retry;
-    }
+  args[0] = s1;
+  args[1] = s2;
+  return Fnconc (2, args);
 }
 
 DEFUN ("nconc", Fnconc, 0, MANY, 0, /*
@@ -3037,37 +3125,25 @@ changing the value of `foo'.
 
   while (argnum < nargs)
     {
-      Lisp_Object val;
-    retry:
-      val = args[argnum];
+      Lisp_Object val = args[argnum];
       if (CONSP (val))
        {
-         /* `val' is the first cons, which will be our return value.  */
-         /* `last_cons' will be the cons cell to mutate.  */
-         Lisp_Object last_cons = val;
-         Lisp_Object tortoise = val;
+         /* Found the first cons, which will be our return value.  */
+         Lisp_Object last = val;
 
          for (argnum++; argnum < nargs; argnum++)
            {
              Lisp_Object next = args[argnum];
-           retry_next:
+           redo:
              if (CONSP (next) || argnum == nargs -1)
                {
                  /* (setcdr (last val) next) */
-                 int count;
-
-                 for (count = 0;
-                      CONSP (XCDR (last_cons));
-                      last_cons = XCDR (last_cons), count++)
+                 while (CONSP (XCDR (last)))
                    {
-                     if (count < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
-
-                     if (count & 1)
-                       tortoise = XCDR (tortoise);
-                     if (EQ (last_cons, tortoise))
-                       signal_circular_list_error (args[argnum-1]);
+                     last = XCDR (last);
+                     QUIT;
                    }
-                 XCDR (last_cons) = next;
+                 XCDR (last) = next;
                }
              else if (NILP (next))
                {
@@ -3075,8 +3151,8 @@ changing the value of `foo'.
                }
              else
                {
-                 next = wrong_type_argument (Qlistp, next);
-                 goto retry_next;
+                 next = wrong_type_argument (next, Qlistp);
+                 goto redo;
                }
            }
          RETURN_UNGCPRO (val);
@@ -3086,84 +3162,86 @@ changing the value of `foo'.
       else if (argnum == nargs - 1) /* last arg? */
        RETURN_UNGCPRO (val);
       else
-       {
-         args[argnum] = wrong_type_argument (Qlistp, val);
-         goto retry;
-       }
+       args[argnum] = wrong_type_argument (val, Qlistp);
     }
   RETURN_UNGCPRO (Qnil);  /* No non-nil args provided. */
 }
 
 \f
 /* This is the guts of all mapping functions.
-   Apply fn to each element of seq, one by one,
-   storing the results into elements of vals, a C vector of Lisp_Objects.
-   leni is the length of vals, which should also be the length of seq.
+ Apply fn to each element of seq, one by one,
+ storing the results into elements of vals, a C vector of Lisp_Objects.
+ leni is the length of vals, which should also be the length of seq.
 
-   If VALS is a null pointer, do not accumulate the results. */
+ If VALS is a null pointer, do not accumulate the results. */
 
 static void
-mapcar1 (size_t leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
+mapcar1 (int leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq)
 {
-  Lisp_Object result;
-  Lisp_Object args[2];
+  Lisp_Object tail;
+  Lisp_Object dummy = Qnil;
   int i;
-  struct gcpro gcpro1;
+  struct gcpro gcpro1, gcpro2, gcpro3;
+  Lisp_Object result;
+
+  GCPRO3 (dummy, fn, seq);
 
   if (vals)
     {
-      GCPRO1 (vals[0]);
-      gcpro1.nvars = 0;
+      /* Don't let vals contain any garbage when GC happens.  */
+      for (i = 0; i < leni; i++)
+       vals[i] = Qnil;
+      gcpro1.var = vals;
+      gcpro1.nvars = leni;
     }
 
-  args[0] = fn;
+  /* We need not explicitly protect `tail' because it is used only on
+    lists, and 1) lists are not relocated and 2) the list is marked
+    via `seq' so will not be freed */
 
-  if (LISTP (seq))
+  if (VECTORP (seq))
     {
       for (i = 0; i < leni; i++)
        {
-         args[1] = XCAR (seq);
-         seq = XCDR (seq);
-         result = Ffuncall (2, args);
-         if (vals) vals[gcpro1.nvars++] = result;
+         dummy = XVECTOR_DATA (seq)[i];
+         result = call1 (fn, dummy);
+         if (vals)
+           vals[i] = result;
        }
     }
-  else if (VECTORP (seq))
+  else if (BIT_VECTORP (seq))
     {
-      Lisp_Object *objs = XVECTOR_DATA (seq);
+      struct Lisp_Bit_Vector *v = XBIT_VECTOR (seq);
       for (i = 0; i < leni; i++)
        {
-         args[1] = *objs++;
-         result = Ffuncall (2, args);
-         if (vals) vals[gcpro1.nvars++] = result;
+         XSETINT (dummy, bit_vector_bit (v, i));
+         result = call1 (fn, dummy);
+         if (vals)
+           vals[i] = result;
        }
     }
   else if (STRINGP (seq))
     {
-      Bufbyte *p = XSTRING_DATA (seq);
       for (i = 0; i < leni; i++)
        {
-         args[1] = make_char (charptr_emchar (p));
-         INC_CHARPTR (p);
-         result = Ffuncall (2, args);
-         if (vals) vals[gcpro1.nvars++] = result;
+         result = call1 (fn, make_char (string_char (XSTRING (seq), i)));
+         if (vals)
+           vals[i] = result;
        }
     }
-  else if (BIT_VECTORP (seq))
+  else   /* Must be a list, since Flength did not get an error */
     {
-      struct Lisp_Bit_Vector *v = XBIT_VECTOR (seq);
+      tail = seq;
       for (i = 0; i < leni; i++)
        {
-         args[1] = make_int (bit_vector_bit (v, i));
-         result = Ffuncall (2, args);
-         if (vals) vals[gcpro1.nvars++] = result;
+         result = call1 (fn, Fcar (tail));
+         if (vals)
+           vals[i] = result;
+         tail = Fcdr (tail);
        }
     }
-  else
-    abort(); /* cannot get here since Flength(seq) did not get an error */
 
-  if (vals)
-    UNGCPRO;
+  UNGCPRO;
 }
 
 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /*
@@ -3173,7 +3251,7 @@ Thus, " " as SEP results in spaces between the values returned by FN.
 */
        (fn, seq, sep))
 {
-  size_t len = XINT (Flength (seq));
+  int len = XINT (Flength (seq));
   Lisp_Object *args;
   int i;
   struct gcpro gcpro1;
@@ -3203,7 +3281,7 @@ SEQUENCE may be a list, a vector, a bit vector, or a string.
 */
        (fn, seq))
 {
-  size_t len = XINT (Flength (seq));
+  int len = XINT (Flength (seq));
   Lisp_Object *args = alloca_array (Lisp_Object, len);
 
   mapcar1 (len, args, fn, seq);
@@ -3218,7 +3296,9 @@ SEQUENCE may be a list, a vector or a string.
 */
        (fn, seq))
 {
-  size_t len = XINT (Flength (seq));
+  int len = XINT (Flength (seq));
+  /* Ideally, this should call make_vector_internal, because we don't
+     need initialization.  */
   Lisp_Object result = make_vector (len, Qnil);
   struct gcpro gcpro1;
 
@@ -3442,429 +3522,7 @@ If FILENAME is omitted, the printname of FEATURE is used as the file name.
       return unbind_to (speccount, feature);
     }
 }
-\f
-/* base64 encode/decode functions.
-   Based on code from GNU recode. */
-
-#define MIME_LINE_LENGTH 76
-
-#define IS_ASCII(Character) \
-  ((Character) < 128)
-#define IS_BASE64(Character) \
-  (IS_ASCII (Character) && base64_char_to_value[Character] >= 0)
-
-/* Table of characters coding the 64 values.  */
-static char base64_value_to_char[64] =
-{
-  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',    /*  0- 9 */
-  'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',    /* 10-19 */
-  'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',    /* 20-29 */
-  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',    /* 30-39 */
-  'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',    /* 40-49 */
-  'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',    /* 50-59 */
-  '8', '9', '+', '/'                                   /* 60-63 */
-};
-
-/* Table of base64 values for first 128 characters.  */
-static short base64_char_to_value[128] =
-{
-  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,     /*   0-  9 */
-  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,     /*  10- 19 */
-  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,     /*  20- 29 */
-  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,     /*  30- 39 */
-  -1,  -1,  -1,  62,  -1,  -1,  -1,  63,  52,  53,     /*  40- 49 */
-  54,  55,  56,  57,  58,  59,  60,  61,  -1,  -1,     /*  50- 59 */
-  -1,  -1,  -1,  -1,  -1,  0,   1,   2,   3,   4,      /*  60- 69 */
-  5,   6,   7,   8,   9,   10,  11,  12,  13,  14,     /*  70- 79 */
-  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,     /*  80- 89 */
-  25,  -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28,     /*  90- 99 */
-  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,     /* 100-109 */
-  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,     /* 110-119 */
-  49,  50,  51,  -1,  -1,  -1,  -1,  -1                        /* 120-127 */
-};
-
-/* The following diagram shows the logical steps by which three octets
-   get transformed into four base64 characters.
-
-                .--------.  .--------.  .--------.
-                |aaaaaabb|  |bbbbcccc|  |ccdddddd|
-                `--------'  `--------'  `--------'
-                    6   2      4   4       2   6
-              .--------+--------+--------+--------.
-              |00aaaaaa|00bbbbbb|00cccccc|00dddddd|
-              `--------+--------+--------+--------'
-
-              .--------+--------+--------+--------.
-              |AAAAAAAA|BBBBBBBB|CCCCCCCC|DDDDDDDD|
-              `--------+--------+--------+--------'
-
-   The octets are divided into 6 bit chunks, which are then encoded into
-   base64 characters.  */
-
-#define ADVANCE_INPUT(c, stream)                               \
- (ec = Lstream_get_emchar (stream),                            \
-  ec == -1 ? 0 :                                               \
-  ((ec > 255) ?                                                        \
-   (error ("Non-ascii character detected in base64 input"), 0) \
-   : (c = (Bufbyte)ec, 1)))
-
-static Bytind
-base64_encode_1 (Lstream *istream, Bufbyte *to, int line_break)
-{
-  EMACS_INT counter = 0;
-  Bufbyte *e = to;
-  Emchar ec;
-  unsigned int value;
-
-  while (1)
-    {
-      Bufbyte c;
-      if (!ADVANCE_INPUT (c, istream))
-       break;
-
-      /* Wrap line every 76 characters.  */
-      if (line_break)
-       {
-         if (counter < MIME_LINE_LENGTH / 4)
-           counter++;
-         else
-           {
-             *e++ = '\n';
-             counter = 1;
-           }
-       }
-
-      /* Process first byte of a triplet.  */
-      *e++ = base64_value_to_char[0x3f & c >> 2];
-      value = (0x03 & c) << 4;
-
-      /* Process second byte of a triplet.  */
-      if (!ADVANCE_INPUT (c, istream))
-       {
-         *e++ = base64_value_to_char[value];
-         *e++ = '=';
-         *e++ = '=';
-         break;
-       }
-
-      *e++ = base64_value_to_char[value | (0x0f & c >> 4)];
-      value = (0x0f & c) << 2;
-
-      /* Process third byte of a triplet.  */
-      if (!ADVANCE_INPUT (c, istream))
-       {
-         *e++ = base64_value_to_char[value];
-         *e++ = '=';
-         break;
-       }
-
-      *e++ = base64_value_to_char[value | (0x03 & c >> 6)];
-      *e++ = base64_value_to_char[0x3f & c];
-    }
-
-  return e - to;
-}
-#undef ADVANCE_INPUT
-
-#define ADVANCE_INPUT(c, stream)               \
- (ec = Lstream_get_emchar (stream),            \
-  ec == -1 ? 0 : (c = (Bufbyte)ec, 1))
-
-#define INPUT_EOF_P(stream)                            \
- (ADVANCE_INPUT (c2, stream)                           \
-  ? (Lstream_unget_emchar (stream, (Emchar)c2), 0)     \
-  : 1)
-
-#define STORE_BYTE(pos, val) do {                                      \
-  pos += set_charptr_emchar (pos, (Emchar)((unsigned char)(val)));     \
-  ++*ccptr;                                                            \
-} while (0)
-
-static Bytind
-base64_decode_1 (Lstream *istream, Bufbyte *to, Charcount *ccptr)
-{
-  EMACS_INT counter = 0;
-  Emchar ec;
-  Bufbyte *e = to;
-  unsigned long value;
-
-  *ccptr = 0;
-  while (1)
-    {
-      Bufbyte c, c2;
-
-      if (!ADVANCE_INPUT (c, istream))
-       break;
-
-      /* Accept wrapping lines, reversibly if at each 76 characters.  */
-      if (c == '\n')
-       {
-         if (!ADVANCE_INPUT (c, istream))
-           break;
-         if (INPUT_EOF_P (istream))
-           break;
-         /* FSF Emacs has this check, apparently inherited from
-             recode.  However, I see no reason to be this picky about
-             line length -- why reject base64 with say 72-byte lines?
-             (yes, there are programs that generate them.)  */
-         /*if (counter != MIME_LINE_LENGTH / 4) return -1;*/
-         counter = 1;
-       }
-      else
-       counter++;
-
-      /* Process first byte of a quadruplet.  */
-      if (!IS_BASE64 (c))
-       return -1;
-      value = base64_char_to_value[c] << 18;
-
-      /* Process second byte of a quadruplet.  */
-      if (!ADVANCE_INPUT (c, istream))
-       return -1;
-
-      if (!IS_BASE64 (c))
-       return -1;
-      value |= base64_char_to_value[c] << 12;
-
-      STORE_BYTE (e, value >> 16);
-
-      /* Process third byte of a quadruplet.  */
-      if (!ADVANCE_INPUT (c, istream))
-       return -1;
-
-      if (c == '=')
-       {
-         if (!ADVANCE_INPUT (c, istream))
-           return -1;
-         if (c != '=')
-           return -1;
-         continue;
-       }
-
-      if (!IS_BASE64 (c))
-       return -1;
-      value |= base64_char_to_value[c] << 6;
-
-      STORE_BYTE (e, 0xff & value >> 8);
-
-      /* Process fourth byte of a quadruplet.  */
-      if (!ADVANCE_INPUT (c, istream))
-       return -1;
-
-      if (c == '=')
-       continue;
-
-      if (!IS_BASE64 (c))
-       return -1;
-      value |= base64_char_to_value[c];
-
-      STORE_BYTE (e, 0xff & value);
-    }
-
-  return e - to;
-}
-#undef ADVANCE_INPUT
-#undef INPUT_EOF_P
-
-static Lisp_Object
-free_malloced_ptr (Lisp_Object unwind_obj)
-{
-  void *ptr = (void *)get_opaque_ptr (unwind_obj);
-  xfree (ptr);
-  free_opaque_ptr (unwind_obj);
-  return Qnil;
-}
-
-/* Don't use alloca for regions larger than this, lest we overflow
-   the stack.  */
-#define MAX_ALLOCA 65536
-
-/* We need to setup proper unwinding, because there is a number of
-   ways these functions can blow up, and we don't want to have memory
-   leaks in those cases.  */
-#define XMALLOC_OR_ALLOCA(ptr, len, type) do {                 \
-  size_t XOA_len = (len);                                      \
-  if (XOA_len > MAX_ALLOCA)                                    \
-    {                                                          \
-      ptr = xnew_array (type, XOA_len);                                \
-      record_unwind_protect (free_malloced_ptr,                        \
-                            make_opaque_ptr ((void *)ptr));    \
-    }                                                          \
-  else                                                         \
-    ptr = alloca_array (type, XOA_len);                                \
-} while (0)
-
-#define XMALLOC_UNBIND(ptr, len, speccount) do {               \
-  if ((len) > MAX_ALLOCA)                                      \
-    unbind_to (speccount, Qnil);                               \
-} while (0)
-
-DEFUN ("base64-encode-region", Fbase64_encode_region, 2, 3, "r", /*
-Base64-encode the region between BEG and END.
-Return the length of the encoded text.
-Optional third argument NO-LINE-BREAK means do not break long lines
-into shorter lines.
-*/
-       (beg, end, no_line_break))
-{
-  Bufbyte *encoded;
-  Bytind encoded_length;
-  Charcount allength, length;
-  struct buffer *buf = current_buffer;
-  Bufpos begv, zv, old_pt = BUF_PT (buf);
-  Lisp_Object input;
-  int speccount = specpdl_depth();
-
-  get_buffer_range_char (buf, beg, end, &begv, &zv, 0);
-  barf_if_buffer_read_only (buf, begv, zv);
-
-  /* We need to allocate enough room for encoding the text.
-     We need 33 1/3% more space, plus a newline every 76
-     characters, and then we round up. */
-  length = zv - begv;
-  allength = length + length/3 + 1;
-  allength += allength / MIME_LINE_LENGTH + 1 + 6;
-
-  input = make_lisp_buffer_input_stream (buf, begv, zv, 0);
-  /* We needn't multiply allength with MAX_EMCHAR_LEN because all the
-     base64 characters will be single-byte.  */
-  XMALLOC_OR_ALLOCA (encoded, allength, Bufbyte);
-  encoded_length = base64_encode_1 (XLSTREAM (input), encoded,
-                                   NILP (no_line_break));
-  if (encoded_length > allength)
-    abort ();
-  Lstream_delete (XLSTREAM (input));
-
-  /* Now we have encoded the region, so we insert the new contents
-     and delete the old.  (Insert first in order to preserve markers.)  */
-  buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0);
-  XMALLOC_UNBIND (encoded, allength, speccount);
-  buffer_delete_range (buf, begv + encoded_length, zv + encoded_length, 0);
-
-  /* Simulate FSF Emacs: if point was in the region, place it at the
-     beginning.  */
-  if (old_pt >= begv && old_pt < zv)
-    BUF_SET_PT (buf, begv);
-
-  /* We return the length of the encoded text. */
-  return make_int (encoded_length);
-}
-
-DEFUN ("base64-encode-string", Fbase64_encode_string, 1, 2, 0, /*
-Base64 encode STRING and return the result.
-*/
-       (string, no_line_break))
-{
-  Charcount allength, length;
-  Bytind encoded_length;
-  Bufbyte *encoded;
-  Lisp_Object input, result;
-  int speccount = specpdl_depth();
-
-  CHECK_STRING (string);
-
-  length = XSTRING_CHAR_LENGTH (string);
-  allength = length + length/3 + 1;
-  allength += allength / MIME_LINE_LENGTH + 1 + 6;
-
-  input = make_lisp_string_input_stream (string, 0, -1);
-  XMALLOC_OR_ALLOCA (encoded, allength, Bufbyte);
-  encoded_length = base64_encode_1 (XLSTREAM (input), encoded,
-                                   NILP (no_line_break));
-  if (encoded_length > allength)
-    abort ();
-  Lstream_delete (XLSTREAM (input));
-  result = make_string (encoded, encoded_length);
-  XMALLOC_UNBIND (encoded, allength, speccount);
-  return result;
-}
-
-DEFUN ("base64-decode-region", Fbase64_decode_region, 2, 2, "r", /*
-Base64-decode the region between BEG and END.
-Return the length of the decoded text.
-If the region can't be decoded, return nil and don't modify the buffer.
-*/
-       (beg, end))
-{
-  struct buffer *buf = current_buffer;
-  Bufpos begv, zv, old_pt = BUF_PT (buf);
-  Bufbyte *decoded;
-  Bytind decoded_length;
-  Charcount length, cc_decoded_length;
-  Lisp_Object input;
-  int speccount = specpdl_depth();
-
-  get_buffer_range_char (buf, beg, end, &begv, &zv, 0);
-  barf_if_buffer_read_only (buf, begv, zv);
-
-  length = zv - begv;
-
-  input = make_lisp_buffer_input_stream (buf, begv, zv, 0);
-  /* We need to allocate enough room for decoding the text. */
-  XMALLOC_OR_ALLOCA (decoded, length * MAX_EMCHAR_LEN, Bufbyte);
-  decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length);
-  if (decoded_length > length * MAX_EMCHAR_LEN)
-    abort ();
-  Lstream_delete (XLSTREAM (input));
-
-  if (decoded_length < 0)
-    {
-      /* The decoding wasn't possible. */
-      XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
-      return Qnil;
-    }
-
-  /* Now we have decoded the region, so we insert the new contents
-     and delete the old.  (Insert first in order to preserve markers.)  */
-  BUF_SET_PT (buf, begv);
-  buffer_insert_raw_string_1 (buf, begv, decoded, decoded_length, 0);
-  XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
-  buffer_delete_range (buf, begv + cc_decoded_length,
-                      zv + cc_decoded_length, 0);
-
-  /* Simulate FSF Emacs: if point was in the region, place it at the
-     beginning.  */
-  if (old_pt >= begv && old_pt < zv)
-    BUF_SET_PT (buf, begv);
-
-  return make_int (cc_decoded_length);
-}
-
-DEFUN ("base64-decode-string", Fbase64_decode_string, 1, 1, 0, /*
-Base64-decode STRING and return the result.
-*/
-       (string))
-{
-  Bufbyte *decoded;
-  Bytind decoded_length;
-  Charcount length, cc_decoded_length;
-  Lisp_Object input, result;
-  int speccount = specpdl_depth();
-
-  CHECK_STRING (string);
 
-  length = XSTRING_CHAR_LENGTH (string);
-  /* We need to allocate enough room for decoding the text. */
-  XMALLOC_OR_ALLOCA (decoded, length * MAX_EMCHAR_LEN, Bufbyte);
-
-  input = make_lisp_string_input_stream (string, 0, -1);
-  decoded_length = base64_decode_1 (XLSTREAM (input), decoded,
-                                   &cc_decoded_length);
-  if (decoded_length > length * MAX_EMCHAR_LEN)
-    abort ();
-  Lstream_delete (XLSTREAM (input));
-
-  if (decoded_length < 0)
-    {
-      /* The decoding wasn't possible. */
-      XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
-      return Qnil;
-    }
-
-  result = make_string (decoded, decoded_length);
-  XMALLOC_UNBIND (decoded, length * MAX_EMCHAR_LEN, speccount);
-  return result;
-}
 \f
 Lisp_Object Qyes_or_no_p;
 
@@ -3886,7 +3544,6 @@ syms_of_fns (void)
   DEFSUBR (Fconcat);
   DEFSUBR (Fvconcat);
   DEFSUBR (Fbvconcat);
-  DEFSUBR (Fcopy_list);
   DEFSUBR (Fcopy_sequence);
   DEFSUBR (Fcopy_alist);
   DEFSUBR (Fcopy_tree);
@@ -3895,9 +3552,6 @@ syms_of_fns (void)
   DEFSUBR (Fnthcdr);
   DEFSUBR (Fnth);
   DEFSUBR (Felt);
-  DEFSUBR (Flast);
-  DEFSUBR (Fbutlast);
-  DEFSUBR (Fnbutlast);
   DEFSUBR (Fmember);
   DEFSUBR (Fold_member);
   DEFSUBR (Fmemq);
@@ -3954,10 +3608,6 @@ syms_of_fns (void)
   DEFSUBR (Ffeaturep);
   DEFSUBR (Frequire);
   DEFSUBR (Fprovide);
-  DEFSUBR (Fbase64_encode_region);
-  DEFSUBR (Fbase64_encode_string);
-  DEFSUBR (Fbase64_decode_region);
-  DEFSUBR (Fbase64_decode_string);
 }
 
 void