]> code.delx.au - gnu-emacs/blobdiff - src/fns.c
*** empty log message ***
[gnu-emacs] / src / fns.c
index 1f53ecb4a04632f6ab2577232a73a979ead77db5..f1602f0a7fb3630598465273e26d871f1f0e8e3f 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -1,5 +1,7 @@
 /* Random utility Lisp functions.
-   Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 98, 99, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1997,
+                 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+                 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -15,9 +17,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
 
@@ -26,71 +27,84 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #include <time.h>
 
+#ifndef MAC_OS
+/* On Mac OS, defining this conflicts with precompiled headers.  */
+
 /* Note on some machines this defines `vector' as a typedef,
    so make sure we don't use that name in this file.  */
 #undef vector
 #define vector *****
 
+#endif  /* ! MAC_OSX */
+
 #include "lisp.h"
 #include "commands.h"
 #include "charset.h"
-
+#include "coding.h"
 #include "buffer.h"
 #include "keyboard.h"
+#include "keymap.h"
 #include "intervals.h"
 #include "frame.h"
 #include "window.h"
-#if defined (HAVE_MENUS) && defined (HAVE_X_WINDOWS)
+#include "blockinput.h"
+#ifdef HAVE_MENUS
+#if defined (HAVE_X_WINDOWS)
 #include "xterm.h"
+#elif defined (MAC_OS)
+#include "macterm.h"
 #endif
-
-#ifndef NULL
-#define NULL (void *)0
 #endif
 
-#ifndef min
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
+#ifndef NULL
+#define NULL ((POINTER_TYPE *)0)
 #endif
 
 /* Nonzero enables use of dialog boxes for questions
    asked by mouse commands.  */
 int use_dialog_box;
 
+/* Nonzero enables use of a file dialog for file name
+   questions asked by mouse commands.  */
+int use_file_dialog;
+
 extern int minibuffer_auto_raise;
 extern Lisp_Object minibuf_window;
+extern Lisp_Object Vlocale_coding_system;
+extern int load_in_progress;
 
 Lisp_Object Qstring_lessp, Qprovide, Qrequire;
 Lisp_Object Qyes_or_no_p_history;
 Lisp_Object Qcursor_in_echo_area;
 Lisp_Object Qwidget_type;
+Lisp_Object Qcodeset, Qdays, Qmonths, Qpaper;
 
 extern Lisp_Object Qinput_method_function;
 
-static int internal_equal ();
+static int internal_equal P_ ((Lisp_Object , Lisp_Object, int, int));
 
 extern long get_random ();
-extern void seed_random ();
+extern void seed_random P_ ((long));
 
 #ifndef HAVE_UNISTD_H
 extern long time ();
 #endif
 \f
 DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
-  "Return the argument unchanged.")
-  (arg)
+       doc: /* Return the argument unchanged.  */)
+     (arg)
      Lisp_Object arg;
 {
   return arg;
 }
 
 DEFUN ("random", Frandom, Srandom, 0, 1, 0,
-  "Return a pseudo-random number.\n\
-All integers representable in Lisp are equally likely.\n\
-  On most systems, this is 28 bits' worth.\n\
-With positive integer argument N, return random number in interval [0,N).\n\
-With argument t, set the random number seed from the current time and pid.")
-  (n)
+       doc: /* Return a pseudo-random number.
+All integers representable in Lisp are equally likely.
+  On most systems, this is 29 bits' worth.
+With positive integer argument N, return random number in interval [0,N).
+With argument t, set the random number seed from the current time and pid. */)
+     (n)
      Lisp_Object n;
 {
   EMACS_INT val;
@@ -122,22 +136,24 @@ With argument t, set the random number seed from the current time and pid.")
 /* Random data-structure functions */
 
 DEFUN ("length", Flength, Slength, 1, 1, 0,
-  "Return the length of vector, list or string SEQUENCE.\n\
-A byte-code function object is also allowed.\n\
-If the string contains multibyte characters, this is not the necessarily\n\
-the number of bytes in the string; it is the number of characters.\n\
-To get the number of bytes, use `string-bytes'")
-  (sequence)
+       doc: /* Return the length of vector, list or string SEQUENCE.
+A byte-code function object is also allowed.
+If the string contains multibyte characters, this is not necessarily
+the number of bytes in the string; it is the number of characters.
+To get the number of bytes, use `string-bytes'. */)
+     (sequence)
      register Lisp_Object sequence;
 {
-  register Lisp_Object tail, val;
+  register Lisp_Object val;
   register int i;
 
  retry:
   if (STRINGP (sequence))
-    XSETFASTINT (val, XSTRING (sequence)->size);
+    XSETFASTINT (val, SCHARS (sequence));
   else if (VECTORP (sequence))
     XSETFASTINT (val, XVECTOR (sequence)->size);
+  else if (SUB_CHAR_TABLE_P (sequence))
+    XSETFASTINT (val, SUB_CHAR_TABLE_ORDINARY_SLOTS);
   else if (CHAR_TABLE_P (sequence))
     XSETFASTINT (val, MAX_CHAR);
   else if (BOOL_VECTOR_P (sequence))
@@ -175,15 +191,14 @@ To get the number of bytes, use `string-bytes'")
   return val;
 }
 
-/* This does not check for quits.  That is safe
-   since it must terminate.  */
+/* This does not check for quits.  That is safe since it must terminate.  */
 
 DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
-  "Return the length of a list, but avoid error or infinite loop.\n\
-This function never gets an error.  If LIST is not really a list,\n\
-it returns 0.  If LIST is circular, it returns a finite value\n\
-which is at least the number of distinct elements.")
-  (list)
+       doc: /* 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,
+it returns 0.  If LIST is circular, it returns a finite value
+which is at least the number of distinct elements. */)
+     (list)
      Lisp_Object list;
 {
   Lisp_Object tail, halftail, length;
@@ -205,69 +220,69 @@ which is at least the number of distinct elements.")
 }
 
 DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0,
-  "Return the number of bytes in STRING.\n\
-If STRING is a multibyte string, this is greater than the length of STRING.")
-  (string)
+       doc: /* Return the number of bytes in STRING.
+If STRING is a multibyte string, this is greater than the length of STRING. */)
+     (string)
      Lisp_Object string;
 {
-  CHECK_STRING (string, 1);
-  return make_number (STRING_BYTES (XSTRING (string)));
+  CHECK_STRING (string);
+  return make_number (SBYTES (string));
 }
 
 DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
-  "Return t if two strings have identical contents.\n\
-Case is significant, but text properties are ignored.\n\
-Symbols are also allowed; their print names are used instead.")
-  (s1, s2)
+       doc: /* Return t if two strings have identical contents.
+Case is significant, but text properties are ignored.
+Symbols are also allowed; their print names are used instead. */)
+     (s1, s2)
      register Lisp_Object s1, s2;
 {
   if (SYMBOLP (s1))
-    XSETSTRING (s1, XSYMBOL (s1)->name);
+    s1 = SYMBOL_NAME (s1);
   if (SYMBOLP (s2))
-    XSETSTRING (s2, XSYMBOL (s2)->name);
-  CHECK_STRING (s1, 0);
-  CHECK_STRING (s2, 1);
+    s2 = SYMBOL_NAME (s2);
+  CHECK_STRING (s1);
+  CHECK_STRING (s2);
 
-  if (XSTRING (s1)->size != XSTRING (s2)->size
-      || STRING_BYTES (XSTRING (s1)) != STRING_BYTES (XSTRING (s2))
-      || bcmp (XSTRING (s1)->data, XSTRING (s2)->data, STRING_BYTES (XSTRING (s1))))
+  if (SCHARS (s1) != SCHARS (s2)
+      || SBYTES (s1) != SBYTES (s2)
+      || bcmp (SDATA (s1), SDATA (s2), SBYTES (s1)))
     return Qnil;
   return Qt;
 }
 
 DEFUN ("compare-strings", Fcompare_strings,
        Scompare_strings, 6, 7, 0,
-  "Compare the contents of two strings, converting to multibyte if needed.\n\
-In string STR1, skip the first START1 characters and stop at END1.\n\
-In string STR2, skip the first START2 characters and stop at END2.\n\
-END1 and END2 default to the full lengths of the respective strings.\n\
-\n\
-Case is significant in this comparison if IGNORE-CASE is nil.\n\
-Unibyte strings are converted to multibyte for comparison.\n\
-\n\
-The value is t if the strings (or specified portions) match.\n\
-If string STR1 is less, the value is a negative number N;\n\
-  - 1 - N is the number of characters that match at the beginning.\n\
-If string STR1 is greater, the value is a positive number N;\n\
-  N - 1 is the number of characters that match at the beginning.")
-  (str1, start1, end1, str2, start2, end2, ignore_case)
+doc: /* Compare the contents of two strings, converting to multibyte if needed.
+In string STR1, skip the first START1 characters and stop at END1.
+In string STR2, skip the first START2 characters and stop at END2.
+END1 and END2 default to the full lengths of the respective strings.
+
+Case is significant in this comparison if IGNORE-CASE is nil.
+Unibyte strings are converted to multibyte for comparison.
+
+The value is t if the strings (or specified portions) match.
+If string STR1 is less, the value is a negative number N;
+  - 1 - N is the number of characters that match at the beginning.
+If string STR1 is greater, the value is a positive number N;
+  N - 1 is the number of characters that match at the beginning. */)
+     (str1, start1, end1, str2, start2, end2, ignore_case)
      Lisp_Object str1, start1, end1, start2, str2, end2, ignore_case;
 {
   register int end1_char, end2_char;
   register int i1, i1_byte, i2, i2_byte;
 
-  CHECK_STRING (str1, 0);
-  CHECK_STRING (str2, 1);
+  CHECK_STRING (str1);
+  CHECK_STRING (str2);
   if (NILP (start1))
     start1 = make_number (0);
   if (NILP (start2))
     start2 = make_number (0);
-  CHECK_NATNUM (start1, 2);
-  CHECK_NATNUM (start2, 3);
+  CHECK_NATNUM (start1);
+  CHECK_NATNUM (start2);
   if (! NILP (end1))
-    CHECK_NATNUM (end1, 4);
+    CHECK_NATNUM (end1);
   if (! NILP (end2))
-    CHECK_NATNUM (end2, 4);
+    CHECK_NATNUM (end2);
 
   i1 = XINT (start1);
   i2 = XINT (start2);
@@ -275,11 +290,11 @@ If string STR1 is greater, the value is a positive number N;\n\
   i1_byte = string_char_to_byte (str1, i1);
   i2_byte = string_char_to_byte (str2, i2);
 
-  end1_char = XSTRING (str1)->size;
+  end1_char = SCHARS (str1);
   if (! NILP (end1) && end1_char > XINT (end1))
     end1_char = XINT (end1);
 
-  end2_char = XSTRING (str2)->size;
+  end2_char = SCHARS (str2);
   if (! NILP (end2) && end2_char > XINT (end2))
     end2_char = XINT (end2);
 
@@ -293,7 +308,7 @@ If string STR1 is greater, the value is a positive number N;\n\
        FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c1, str1, i1, i1_byte);
       else
        {
-         c1 = XSTRING (str1)->data[i1++];
+         c1 = SREF (str1, i1++);
          c1 = unibyte_char_to_multibyte (c1);
        }
 
@@ -301,7 +316,7 @@ If string STR1 is greater, the value is a positive number N;\n\
        FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c2, str2, i2, i2_byte);
       else
        {
-         c2 = XSTRING (str2)->data[i2++];
+         c2 = SREF (str2, i2++);
          c2 = unibyte_char_to_multibyte (c2);
        }
 
@@ -325,9 +340,9 @@ If string STR1 is greater, the value is a positive number N;\n\
         past the character that we are comparing;
         hence we don't add or subtract 1 here.  */
       if (c1 < c2)
-       return make_number (- i1);
+       return make_number (- i1 + XINT (start1));
       else
-       return make_number (i1);
+       return make_number (i1 - XINT (start1));
     }
 
   if (i1 < end1_char)
@@ -339,27 +354,27 @@ If string STR1 is greater, the value is a positive number N;\n\
 }
 
 DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
-  "Return t if first arg string is less than second in lexicographic order.\n\
-Case is significant.\n\
-Symbols are also allowed; their print names are used instead.")
-  (s1, s2)
+       doc: /* Return t if first arg string is less than second in lexicographic order.
+Case is significant.
+Symbols are also allowed; their print names are used instead. */)
+     (s1, s2)
      register Lisp_Object s1, s2;
 {
   register int end;
   register int i1, i1_byte, i2, i2_byte;
 
   if (SYMBOLP (s1))
-    XSETSTRING (s1, XSYMBOL (s1)->name);
+    s1 = SYMBOL_NAME (s1);
   if (SYMBOLP (s2))
-    XSETSTRING (s2, XSYMBOL (s2)->name);
-  CHECK_STRING (s1, 0);
-  CHECK_STRING (s2, 1);
+    s2 = SYMBOL_NAME (s2);
+  CHECK_STRING (s1);
+  CHECK_STRING (s2);
 
   i1 = i1_byte = i2 = i2_byte = 0;
 
-  end = XSTRING (s1)->size;
-  if (end > XSTRING (s2)->size)
-    end = XSTRING (s2)->size;
+  end = SCHARS (s1);
+  if (end > SCHARS (s2))
+    end = SCHARS (s2);
 
   while (i1 < end)
     {
@@ -373,7 +388,7 @@ Symbols are also allowed; their print names are used instead.")
       if (c1 != c2)
        return c1 < c2 ? Qt : Qnil;
     }
-  return i1 < XSTRING (s2)->size ? Qt : Qnil;
+  return i1 < SCHARS (s2) ? Qt : Qnil;
 }
 \f
 static Lisp_Object concat ();
@@ -410,11 +425,12 @@ concat3 (s1, s2, s3)
 }
 
 DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
-  "Concatenate all the arguments and make the result a list.\n\
-The result is a list whose elements are the elements of all the arguments.\n\
-Each argument may be a list, vector or string.\n\
-The last argument is not copied, just used as the tail of the new list.")
-  (nargs, args)
+       doc: /* Concatenate all the arguments and make the result a list.
+The result is a list whose elements are the elements of all the arguments.
+Each argument may be a list, vector or string.
+The last argument is not copied, just used as the tail of the new list.
+usage: (append &rest SEQUENCES)  */)
+     (nargs, args)
      int nargs;
      Lisp_Object *args;
 {
@@ -422,10 +438,11 @@ The last argument is not copied, just used as the tail of the new list.")
 }
 
 DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
-  "Concatenate all the arguments and make the result a string.\n\
-The result is a string whose elements are the elements of all the arguments.\n\
-Each argument may be a string or a list or vector of characters (integers).")
-  (nargs, args)
+       doc: /* Concatenate all the arguments and make the result a string.
+The result is a string whose elements are the elements of all the arguments.
+Each argument may be a string or a list or vector of characters (integers).
+usage: (concat &rest SEQUENCES)  */)
+     (nargs, args)
      int nargs;
      Lisp_Object *args;
 {
@@ -433,25 +450,27 @@ Each argument may be a string or a list or vector of characters (integers).")
 }
 
 DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
-  "Concatenate all the arguments and make the result a vector.\n\
-The result is a vector whose elements are the elements of all the arguments.\n\
-Each argument may be a list, vector or string.")
-  (nargs, args)
+       doc: /* Concatenate all the arguments and make the result a vector.
+The result is a vector whose elements are the elements of all the arguments.
+Each argument may be a list, vector or string.
+usage: (vconcat &rest SEQUENCES)   */)
+     (nargs, args)
      int nargs;
      Lisp_Object *args;
 {
   return concat (nargs, args, Lisp_Vectorlike, 0);
 }
 
-/* Retrun a copy of a sub char table ARG.  The elements except for a
+/* Return a copy of a sub char table ARG.  The elements except for a
    nested sub char table are not copied.  */
 static Lisp_Object
 copy_sub_char_table (arg)
      Lisp_Object arg;
 {
-  Lisp_Object copy = make_sub_char_table (XCHAR_TABLE (arg)->defalt);
+  Lisp_Object copy = make_sub_char_table (Qnil);
   int i;
 
+  XCHAR_TABLE (copy)->defalt = XCHAR_TABLE (arg)->defalt;
   /* Copy all the contents.  */
   bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
         SUB_CHAR_TABLE_ORDINARY_SLOTS * sizeof (Lisp_Object));
@@ -466,10 +485,10 @@ copy_sub_char_table (arg)
 
 
 DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
-  "Return a copy of a list, vector or string.\n\
-The elements of a list or vector are not copied; they are shared\n\
-with the original.")
-  (arg)
+       doc: /* Return a copy of a list, vector, string or char-table.
+The elements of a list or vector are not copied; they are shared
+with the original. */)
+     (arg)
      Lisp_Object arg;
 {
   if (NILP (arg)) return arg;
@@ -500,7 +519,8 @@ with the original.")
     {
       Lisp_Object val;
       int size_in_chars
-       = (XBOOL_VECTOR (arg)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+       = ((XBOOL_VECTOR (arg)->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
+          / BOOL_VECTOR_BITS_PER_CHAR);
 
       val = Fmake_bool_vector (Flength (arg), Qnil);
       bcopy (XBOOL_VECTOR (arg)->data, XBOOL_VECTOR (val)->data,
@@ -513,27 +533,6 @@ with the original.")
   return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
 }
 
-/* In string STR of length LEN, see if bytes before STR[I] combine
-   with bytes after STR[I] to form a single character.  If so, return
-   the number of bytes after STR[I] which combine in this way.
-   Otherwize, return 0.  */
-
-static int
-count_combining (str, len, i)
-     unsigned char *str;
-     int len, i;
-{
-  int j = i - 1, bytes;
-
-  if (i == 0 || i == len || CHAR_HEAD_P (str[i]))
-    return 0;
-  while (j >= 0 && !CHAR_HEAD_P (str[j])) j--;
-  if (j < 0 || ! BASE_LEADING_CODE_P (str[j]))
-    return 0;
-  PARSE_MULTIBYTE_SEQ (str + j, len - j, bytes);
-  return (bytes <= i - j ? 0 : bytes - (i - j));
-}
-
 /* This structure holds information of an argument of `concat' that is
    a string and has text properties to be copied.  */
 struct textprop_rec
@@ -554,7 +553,7 @@ concat (nargs, args, target_type, last_special)
   register Lisp_Object tail;
   register Lisp_Object this;
   int toindex;
-  int toindex_byte;
+  int toindex_byte = 0;
   register int result_len;
   register int result_len_byte;
   register int argnum;
@@ -566,9 +565,12 @@ concat (nargs, args, target_type, last_special)
      string can't be decided until we finish the whole concatination.
      So, we record strings that have text properties to be copied
      here, and copy the text properties after the concatination.  */
-  struct textprop_rec  *textprops;
+  struct textprop_rec  *textprops = NULL;
   /* Number of elments in textprops.  */
   int num_textprops = 0;
+  USE_SAFE_ALLOCA;
+
+  tail = Qnil;
 
   /* In append, the last arg isn't treated like the others */
   if (last_special && nargs > 0)
@@ -639,11 +641,11 @@ concat (nargs, args, target_type, last_special)
              if (STRING_MULTIBYTE (this))
                {
                  some_multibyte = 1;
-                 result_len_byte += STRING_BYTES (XSTRING (this));
+                 result_len_byte += SBYTES (this);
                }
              else
-               result_len_byte += count_size_as_multibyte (XSTRING (this)->data,
-                                                           XSTRING (this)->size);
+               result_len_byte += count_size_as_multibyte (SDATA (this),
+                                                           SCHARS (this));
            }
        }
 
@@ -675,13 +677,12 @@ concat (nargs, args, target_type, last_special)
 
   prev = Qnil;
   if (STRINGP (val))
-    textprops
-      = (struct textprop_rec *) alloca (sizeof (struct textprop_rec) * nargs);
+    SAFE_ALLOCA (textprops, struct textprop_rec *, sizeof (struct textprop_rec) * nargs);
 
   for (argnum = 0; argnum < nargs; argnum++)
     {
       Lisp_Object thislen;
-      int thisleni;
+      int thisleni = 0;
       register unsigned int thisindex = 0;
       register unsigned int thisindex_byte = 0;
 
@@ -693,39 +694,32 @@ concat (nargs, args, target_type, last_special)
       if (STRINGP (this) && STRINGP (val)
          && STRING_MULTIBYTE (this) == some_multibyte)
        {
-         int thislen_byte = STRING_BYTES (XSTRING (this));
-         int combined;
-
-         bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte,
-                STRING_BYTES (XSTRING (this)));
-         combined =  (some_multibyte && toindex_byte > 0
-                      ? count_combining (XSTRING (val)->data,
-                                         toindex_byte + thislen_byte,
-                                         toindex_byte)
-                      : 0);
-         if (! NULL_INTERVAL_P (XSTRING (this)->intervals))
+         int thislen_byte = SBYTES (this);
+
+         bcopy (SDATA (this), SDATA (val) + toindex_byte,
+                SBYTES (this));
+         if (! NULL_INTERVAL_P (STRING_INTERVALS (this)))
            {
              textprops[num_textprops].argnum = argnum;
-             /* We ignore text properties on characters being combined.  */
-             textprops[num_textprops].from = combined;
+             textprops[num_textprops].from = 0;
              textprops[num_textprops++].to = toindex;
            }
          toindex_byte += thislen_byte;
-         toindex += thisleni - combined;
-         XSTRING (val)->size -= combined;
+         toindex += thisleni;
+         STRING_SET_CHARS (val, SCHARS (val));
        }
       /* Copy a single-byte string to a multibyte string.  */
       else if (STRINGP (this) && STRINGP (val))
        {
-         if (! NULL_INTERVAL_P (XSTRING (this)->intervals))
+         if (! NULL_INTERVAL_P (STRING_INTERVALS (this)))
            {
              textprops[num_textprops].argnum = argnum;
              textprops[num_textprops].from = 0;
              textprops[num_textprops++].to = toindex;
            }
-         toindex_byte += copy_text (XSTRING (this)->data,
-                                    XSTRING (val)->data + toindex_byte,
-                                    XSTRING (this)->size, 0, 1);
+         toindex_byte += copy_text (SDATA (this),
+                                    SDATA (val) + toindex_byte,
+                                    SCHARS (this), 0, 1);
          toindex += thisleni;
        }
       else
@@ -753,7 +747,7 @@ concat (nargs, args, target_type, last_special)
                  }
                else
                  {
-                   XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
+                   XSETFASTINT (elt, SREF (this, thisindex)); thisindex++;
                    if (some_multibyte
                        && (XINT (elt) >= 0240
                            || (XINT (elt) >= 0200
@@ -768,8 +762,8 @@ concat (nargs, args, target_type, last_special)
            else if (BOOL_VECTOR_P (this))
              {
                int byte;
-               byte = XBOOL_VECTOR (this)->data[thisindex / BITS_PER_CHAR];
-               if (byte & (1 << (thisindex % BITS_PER_CHAR)))
+               byte = XBOOL_VECTOR (this)->data[thisindex / BOOL_VECTOR_BITS_PER_CHAR];
+               if (byte & (1 << (thisindex % BOOL_VECTOR_BITS_PER_CHAR)))
                  elt = Qt;
                else
                  elt = Qnil;
@@ -781,7 +775,7 @@ concat (nargs, args, target_type, last_special)
            /* Store this element into the result.  */
            if (toindex < 0)
              {
-               XCAR (tail) = elt;
+               XSETCAR (tail, elt);
                prev = tail;
                tail = XCDR (tail);
              }
@@ -789,22 +783,16 @@ concat (nargs, args, target_type, last_special)
              XVECTOR (val)->contents[toindex++] = elt;
            else
              {
-               CHECK_NUMBER (elt, 0);
+               CHECK_NUMBER (elt);
                if (SINGLE_BYTE_CHAR_P (XINT (elt)))
                  {
                    if (some_multibyte)
                      toindex_byte
                        += CHAR_STRING (XINT (elt),
-                                       XSTRING (val)->data + toindex_byte);
-                   else
-                     XSTRING (val)->data[toindex_byte++] = XINT (elt);
-                   if (some_multibyte
-                       && toindex_byte > 0
-                       && count_combining (XSTRING (val)->data,
-                                           toindex_byte, toindex_byte - 1))
-                     XSTRING (val)->size--;
+                                       SDATA (val) + toindex_byte);
                    else
-                     toindex++;
+                     SSET (val, toindex_byte++, XINT (elt));
+                   toindex++;
                  }
                else
                  /* If we have any multibyte characters,
@@ -813,7 +801,7 @@ concat (nargs, args, target_type, last_special)
                    int c = XINT (elt);
                    /* P exists as a variable
                       to avoid a bug on the Masscomp C compiler.  */
-                   unsigned char *p = & XSTRING (val)->data[toindex_byte];
+                   unsigned char *p = SDATA (val) + toindex_byte;
 
                    toindex_byte += CHAR_STRING (c, p);
                    toindex++;
@@ -822,28 +810,31 @@ concat (nargs, args, target_type, last_special)
          }
     }
   if (!NILP (prev))
-    XCDR (prev) = last_tail;
+    XSETCDR (prev, last_tail);
 
   if (num_textprops > 0)
     {
       Lisp_Object props;
+      int last_to_end = -1;
 
       for (argnum = 0; argnum < num_textprops; argnum++)
        {
          this = args[textprops[argnum].argnum];
          props = text_property_list (this,
                                      make_number (0),
-                                     make_number (XSTRING (this)->size),
+                                     make_number (SCHARS (this)),
                                      Qnil);
          /* If successive arguments have properites, be sure that the
             value of `composition' property be the copy.  */
-         if (argnum > 0
-             && textprops[argnum - 1].argnum + 1 == textprops[argnum].argnum)
+         if (last_to_end == textprops[argnum].to)
            make_composition_value_copy (props);
          add_text_properties_from_list (val, props,
                                         make_number (textprops[argnum].to));
+         last_to_end = textprops[argnum].to + SCHARS (this);
        }
     }
+
+  SAFE_FREE ();
   return val;
 }
 \f
@@ -868,12 +859,11 @@ string_char_to_byte (string, char_index)
   int best_below, best_below_byte;
   int best_above, best_above_byte;
 
-  if (! STRING_MULTIBYTE (string))
-    return char_index;
-
   best_below = best_below_byte = 0;
-  best_above = XSTRING (string)->size;
-  best_above_byte = STRING_BYTES (XSTRING (string));
+  best_above = SCHARS (string);
+  best_above_byte = SBYTES (string);
+  if (best_above == best_above_byte)
+    return char_index;
 
   if (EQ (string, string_char_byte_cache_string))
     {
@@ -904,7 +894,7 @@ string_char_to_byte (string, char_index)
     {
       while (best_above > char_index)
        {
-         unsigned char *pend = XSTRING (string)->data + best_above_byte;
+         unsigned char *pend = SDATA (string) + best_above_byte;
          unsigned char *pbeg = pend - best_above_byte;
          unsigned char *p = pend - 1;
          int bytes;
@@ -941,12 +931,11 @@ string_byte_to_char (string, byte_index)
   int best_below, best_below_byte;
   int best_above, best_above_byte;
 
-  if (! STRING_MULTIBYTE (string))
-    return byte_index;
-
   best_below = best_below_byte = 0;
-  best_above = XSTRING (string)->size;
-  best_above_byte = STRING_BYTES (XSTRING (string));
+  best_above = SCHARS (string);
+  best_above_byte = SBYTES (string);
+  if (best_above == best_above_byte)
+    return byte_index;
 
   if (EQ (string, string_char_byte_cache_string))
     {
@@ -977,7 +966,7 @@ string_byte_to_char (string, byte_index)
     {
       while (best_above_byte > byte_index)
        {
-         unsigned char *pend = XSTRING (string)->data + best_above_byte;
+         unsigned char *pend = SDATA (string) + best_above_byte;
          unsigned char *pbeg = pend - best_above_byte;
          unsigned char *p = pend - 1;
          int bytes;
@@ -1013,87 +1002,143 @@ string_make_multibyte (string)
 {
   unsigned char *buf;
   int nbytes;
+  Lisp_Object ret;
+  USE_SAFE_ALLOCA;
 
   if (STRING_MULTIBYTE (string))
     return string;
 
-  nbytes = count_size_as_multibyte (XSTRING (string)->data,
-                                   XSTRING (string)->size);
+  nbytes = count_size_as_multibyte (SDATA (string),
+                                   SCHARS (string));
   /* If all the chars are ASCII, they won't need any more bytes
      once converted.  In that case, we can return STRING itself.  */
-  if (nbytes == STRING_BYTES (XSTRING (string)))
+  if (nbytes == SBYTES (string))
     return string;
 
-  buf = (unsigned char *) alloca (nbytes);
-  copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
+  SAFE_ALLOCA (buf, unsigned char *, nbytes);
+  copy_text (SDATA (string), buf, SBYTES (string),
             0, 1);
 
-  return make_multibyte_string (buf, XSTRING (string)->size, nbytes);
+  ret = make_multibyte_string (buf, SCHARS (string), nbytes);
+  SAFE_FREE ();
+
+  return ret;
 }
 
+
+/* Convert STRING to a multibyte string without changing each
+   character codes.  Thus, characters 0200 trough 0237 are converted
+   to eight-bit-control characters, and characters 0240 through 0377
+   are converted eight-bit-graphic characters. */
+
+Lisp_Object
+string_to_multibyte (string)
+     Lisp_Object string;
+{
+  unsigned char *buf;
+  int nbytes;
+  Lisp_Object ret;
+  USE_SAFE_ALLOCA;
+
+  if (STRING_MULTIBYTE (string))
+    return string;
+
+  nbytes = parse_str_to_multibyte (SDATA (string), SBYTES (string));
+  /* If all the chars are ASCII or eight-bit-graphic, they won't need
+     any more bytes once converted.  */
+  if (nbytes == SBYTES (string))
+    return make_multibyte_string (SDATA (string), nbytes, nbytes);
+
+  SAFE_ALLOCA (buf, unsigned char *, nbytes);
+  bcopy (SDATA (string), buf, SBYTES (string));
+  str_to_multibyte (buf, nbytes, SBYTES (string));
+
+  ret = make_multibyte_string (buf, SCHARS (string), nbytes);
+  SAFE_FREE ();
+
+  return ret;
+}
+
+
 /* Convert STRING to a single-byte string.  */
 
 Lisp_Object
 string_make_unibyte (string)
      Lisp_Object string;
 {
+  int nchars;
   unsigned char *buf;
+  Lisp_Object ret;
+  USE_SAFE_ALLOCA;
 
   if (! STRING_MULTIBYTE (string))
     return string;
 
-  buf = (unsigned char *) alloca (XSTRING (string)->size);
+  nchars = SCHARS (string);
 
-  copy_text (XSTRING (string)->data, buf, STRING_BYTES (XSTRING (string)),
+  SAFE_ALLOCA (buf, unsigned char *, nchars);
+  copy_text (SDATA (string), buf, SBYTES (string),
             1, 0);
 
-  return make_unibyte_string (buf, XSTRING (string)->size);
+  ret = make_unibyte_string (buf, nchars);
+  SAFE_FREE ();
+
+  return ret;
 }
 
 DEFUN ("string-make-multibyte", Fstring_make_multibyte, Sstring_make_multibyte,
        1, 1, 0,
-  "Return the multibyte equivalent of STRING.\n\
-The function `unibyte-char-to-multibyte' is used to convert\n\
-each unibyte character to a multibyte character.")
-  (string)
+       doc: /* Return the multibyte equivalent of STRING.
+If STRING is unibyte and contains non-ASCII characters, the function
+`unibyte-char-to-multibyte' is used to convert each unibyte character
+to a multibyte character.  In this case, the returned string is a
+newly created string with no text properties.  If STRING is multibyte
+or entirely ASCII, it is returned unchanged.  In particular, when
+STRING is unibyte and entirely ASCII, the returned string is unibyte.
+\(When the characters are all ASCII, Emacs primitives will treat the
+string the same way whether it is unibyte or multibyte.)  */)
+     (string)
      Lisp_Object string;
 {
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
 
   return string_make_multibyte (string);
 }
 
 DEFUN ("string-make-unibyte", Fstring_make_unibyte, Sstring_make_unibyte,
        1, 1, 0,
-  "Return the unibyte equivalent of STRING.\n\
-Multibyte character codes are converted to unibyte\n\
-by using just the low 8 bits.")
-  (string)
+       doc: /* Return the unibyte equivalent of STRING.
+Multibyte character codes are converted to unibyte according to
+`nonascii-translation-table' or, if that is nil, `nonascii-insert-offset'.
+If the lookup in the translation table fails, this function takes just
+the low 8 bits of each character. */)
+     (string)
      Lisp_Object string;
 {
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
 
   return string_make_unibyte (string);
 }
 
 DEFUN ("string-as-unibyte", Fstring_as_unibyte, Sstring_as_unibyte,
        1, 1, 0,
-  "Return a unibyte string with the same individual bytes as STRING.\n\
-If STRING is unibyte, the result is STRING itself.\n\
-Otherwise it is a newly created string, with no text properties.\n\
-If STRING is multibyte and contains a character of charset `binary',\n\
-it is converted to the corresponding single byte.")
-  (string)
+       doc: /* Return a unibyte string with the same individual bytes as STRING.
+If STRING is unibyte, the result is STRING itself.
+Otherwise it is a newly created string, with no text properties.
+If STRING is multibyte and contains a character of charset
+`eight-bit-control' or `eight-bit-graphic', it is converted to the
+corresponding single byte.  */)
+     (string)
      Lisp_Object string;
 {
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
 
   if (STRING_MULTIBYTE (string))
     {
-      int bytes = STRING_BYTES (XSTRING (string));
+      int bytes = SBYTES (string);
       unsigned char *str = (unsigned char *) xmalloc (bytes);
 
-      bcopy (XSTRING (string)->data, str, bytes);
+      bcopy (SDATA (string), str, bytes);
       bytes = str_as_unibyte (str, bytes);
       string = make_unibyte_string (str, bytes);
       xfree (str);
@@ -1103,50 +1148,80 @@ it is converted to the corresponding single byte.")
 
 DEFUN ("string-as-multibyte", Fstring_as_multibyte, Sstring_as_multibyte,
        1, 1, 0,
-  "Return a multibyte string with the same individual bytes as STRING.\n\
-If STRING is multibyte, the result is STRING itself.\n\
-Otherwise it is a newly created string, with no text properties.\n\
-If STRING is unibyte and contains an individual 8-bit byte (i.e. not\n\
-part of multibyte form), it is converted to the corresponding\n\
-multibyte character of charset `binary'.")
-  (string)
+       doc: /* Return a multibyte string with the same individual bytes as STRING.
+If STRING is multibyte, the result is STRING itself.
+Otherwise it is a newly created string, with no text properties.
+If STRING is unibyte and contains an individual 8-bit byte (i.e. not
+part of a multibyte form), it is converted to the corresponding
+multibyte character of charset `eight-bit-control' or `eight-bit-graphic'.
+Beware, this often doesn't really do what you think it does.
+It is similar to (decode-coding-string STRING 'emacs-mule-unix).
+If you're not sure, whether to use `string-as-multibyte' or
+`string-to-multibyte', use `string-to-multibyte'.  Beware:
+   (aref (string-as-multibyte "\\201") 0) -> 129 (aka ?\\201)
+   (aref (string-as-multibyte "\\300") 0) -> 192 (aka ?\\300)
+   (aref (string-as-multibyte "\\300\\201") 0) -> 192 (aka ?\\300)
+   (aref (string-as-multibyte "\\300\\201") 1) -> 129 (aka ?\\201)
+but
+   (aref (string-as-multibyte "\\201\\300") 0) -> 2240
+   (aref (string-as-multibyte "\\201\\300") 1) -> <error>  */)
+     (string)
      Lisp_Object string;
 {
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
 
   if (! STRING_MULTIBYTE (string))
     {
       Lisp_Object new_string;
       int nchars, nbytes;
 
-      parse_str_as_multibyte (XSTRING (string)->data,
-                             STRING_BYTES (XSTRING (string)),
+      parse_str_as_multibyte (SDATA (string),
+                             SBYTES (string),
                              &nchars, &nbytes);
       new_string = make_uninit_multibyte_string (nchars, nbytes);
-      bcopy (XSTRING (string)->data, XSTRING (new_string)->data,
-            STRING_BYTES (XSTRING (string)));
-      if (nbytes != STRING_BYTES (XSTRING (string)))
-       str_as_multibyte (XSTRING (new_string)->data, nbytes,
-                         STRING_BYTES (XSTRING (string)), NULL);
+      bcopy (SDATA (string), SDATA (new_string),
+            SBYTES (string));
+      if (nbytes != SBYTES (string))
+       str_as_multibyte (SDATA (new_string), nbytes,
+                         SBYTES (string), NULL);
       string = new_string;
-      XSTRING (string)->intervals = NULL_INTERVAL;
+      STRING_SET_INTERVALS (string, NULL_INTERVAL);
     }
   return string;
 }
+
+DEFUN ("string-to-multibyte", Fstring_to_multibyte, Sstring_to_multibyte,
+       1, 1, 0,
+       doc: /* Return a multibyte string with the same individual chars as STRING.
+If STRING is multibyte, the result is STRING itself.
+Otherwise it is a newly created string, with no text properties.
+Characters 0200 through 0237 are converted to eight-bit-control
+characters of the same character code.  Characters 0240 through 0377
+are converted to eight-bit-graphic characters of the same character
+codes.
+This is similar to (decode-coding-string STRING 'binary)  */)
+     (string)
+     Lisp_Object string;
+{
+  CHECK_STRING (string);
+
+  return string_to_multibyte (string);
+}
+
 \f
 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
-  "Return a copy of ALIST.\n\
-This is an alist which represents the same mapping from objects to objects,\n\
-but does not share the alist structure with ALIST.\n\
-The objects mapped (cars and cdrs of elements of the alist)\n\
-are shared, however.\n\
-Elements of ALIST that are not conses are also shared.")
-  (alist)
+       doc: /* Return a copy of ALIST.
+This is an alist which represents the same mapping from objects to objects,
+but does not share the alist structure with ALIST.
+The objects mapped (cars and cdrs of elements of the alist)
+are shared, however.
+Elements of ALIST that are not conses are also shared.  */)
+     (alist)
      Lisp_Object alist;
 {
   register Lisp_Object tem;
 
-  CHECK_LIST (alist, 0);
+  CHECK_LIST (alist);
   if (NILP (alist))
     return alist;
   alist = concat (1, &alist, Lisp_Cons, 0);
@@ -1156,36 +1231,36 @@ Elements of ALIST that are not conses are also shared.")
       car = XCAR (tem);
 
       if (CONSP (car))
-       XCAR (tem) = Fcons (XCAR (car), XCDR (car));
+       XSETCAR (tem, Fcons (XCAR (car), XCDR (car)));
     }
   return alist;
 }
 
 DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
-  "Return a substring of STRING, starting at index FROM and ending before TO.\n\
-TO may be nil or omitted; then the substring runs to the end of STRING.\n\
-If FROM or TO is negative, it counts from the end.\n\
-\n\
-This function allows vectors as well as strings.")
-  (string, from, to)
+       doc: /* Return a substring of STRING, starting at index FROM and ending before TO.
+TO may be nil or omitted; then the substring runs to the end of STRING.
+FROM and TO start at 0.  If either is negative, it counts from the end.
+
+This function allows vectors as well as strings.  */)
+     (string, from, to)
      Lisp_Object string;
      register Lisp_Object from, to;
 {
   Lisp_Object res;
   int size;
-  int size_byte;
+  int size_byte = 0;
   int from_char, to_char;
-  int from_byte, to_byte;
+  int from_byte = 0, to_byte = 0;
 
   if (! (STRINGP (string) || VECTORP (string)))
     wrong_type_argument (Qarrayp, string);
 
-  CHECK_NUMBER (from, 1);
+  CHECK_NUMBER (from);
 
   if (STRINGP (string))
     {
-      size = XSTRING (string)->size;
-      size_byte = STRING_BYTES (XSTRING (string));
+      size = SCHARS (string);
+      size_byte = SBYTES (string);
     }
   else
     size = XVECTOR (string)->size;
@@ -1197,7 +1272,7 @@ This function allows vectors as well as strings.")
     }
   else
     {
-      CHECK_NUMBER (to, 2);
+      CHECK_NUMBER (to);
 
       to_char = XINT (to);
       if (to_char < 0)
@@ -1219,7 +1294,7 @@ This function allows vectors as well as strings.")
 
   if (STRINGP (string))
     {
-      res = make_specified_string (XSTRING (string)->data + from_byte,
+      res = make_specified_string (SDATA (string) + from_byte,
                                   to_char - from_char, to_byte - from_byte,
                                   STRING_MULTIBYTE (string));
       copy_text_properties (make_number (from_char), make_number (to_char),
@@ -1232,6 +1307,65 @@ This function allows vectors as well as strings.")
   return res;
 }
 
+
+DEFUN ("substring-no-properties", Fsubstring_no_properties, Ssubstring_no_properties, 1, 3, 0,
+       doc: /* Return a substring of STRING, without text properties.
+It starts at index FROM and ending before TO.
+TO may be nil or omitted; then the substring runs to the end of STRING.
+If FROM is nil or omitted, the substring starts at the beginning of STRING.
+If FROM or TO is negative, it counts from the end.
+
+With one argument, just copy STRING without its properties.  */)
+     (string, from, to)
+     Lisp_Object string;
+     register Lisp_Object from, to;
+{
+  int size, size_byte;
+  int from_char, to_char;
+  int from_byte, to_byte;
+
+  CHECK_STRING (string);
+
+  size = SCHARS (string);
+  size_byte = SBYTES (string);
+
+  if (NILP (from))
+    from_char = from_byte = 0;
+  else
+    {
+      CHECK_NUMBER (from);
+      from_char = XINT (from);
+      if (from_char < 0)
+       from_char += size;
+
+      from_byte = string_char_to_byte (string, from_char);
+    }
+
+  if (NILP (to))
+    {
+      to_char = size;
+      to_byte = size_byte;
+    }
+  else
+    {
+      CHECK_NUMBER (to);
+
+      to_char = XINT (to);
+      if (to_char < 0)
+       to_char += size;
+
+      to_byte = string_char_to_byte (string, to_char);
+    }
+
+  if (!(0 <= from_char && from_char <= to_char && to_char <= size))
+    args_out_of_range_3 (string, make_number (from_char),
+                        make_number (to_char));
+
+  return make_specified_string (SDATA (string) + from_byte,
+                               to_char - from_char, to_byte - from_byte,
+                               STRING_MULTIBYTE (string));
+}
+
 /* Extract a substring of STRING, giving start and end positions
    both in characters and in bytes.  */
 
@@ -1249,8 +1383,8 @@ substring_both (string, from, from_byte, to, to_byte)
 
   if (STRINGP (string))
     {
-      size = XSTRING (string)->size;
-      size_byte = STRING_BYTES (XSTRING (string));
+      size = SCHARS (string);
+      size_byte = SBYTES (string);
     }
   else
     size = XVECTOR (string)->size;
@@ -1260,7 +1394,7 @@ substring_both (string, from, from_byte, to, to_byte)
 
   if (STRINGP (string))
     {
-      res = make_specified_string (XSTRING (string)->data + from_byte,
+      res = make_specified_string (SDATA (string) + from_byte,
                                   to - from, to_byte - from_byte,
                                   STRING_MULTIBYTE (string));
       copy_text_properties (make_number (from), make_number (to),
@@ -1274,13 +1408,13 @@ substring_both (string, from, from_byte, to, to_byte)
 }
 \f
 DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
-  "Take cdr N times on LIST, returns the result.")
-  (n, list)
+       doc: /* Take cdr N times on LIST, returns the result.  */)
+     (n, list)
      Lisp_Object n;
      register Lisp_Object list;
 {
   register int i, num;
-  CHECK_NUMBER (n, 0);
+  CHECK_NUMBER (n);
   num = XINT (n);
   for (i = 0; i < num && !NILP (list); i++)
     {
@@ -1293,20 +1427,20 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
 }
 
 DEFUN ("nth", Fnth, Snth, 2, 2, 0,
-  "Return the Nth element of LIST.\n\
-N counts from zero.  If LIST is not that long, nil is returned.")
-  (n, list)
+       doc: /* Return the Nth element of LIST.
+N counts from zero.  If LIST is not that long, nil is returned.  */)
+     (n, list)
      Lisp_Object n, list;
 {
   return Fcar (Fnthcdr (n, list));
 }
 
 DEFUN ("elt", Felt, Selt, 2, 2, 0,
-  "Return element of SEQUENCE at index N.")
-  (sequence, n)
+       doc: /* Return element of SEQUENCE at index N.  */)
+     (sequence, n)
      register Lisp_Object sequence, n;
 {
-  CHECK_NUMBER (n, 0);
+  CHECK_NUMBER (n);
   while (1)
     {
       if (CONSP (sequence) || NILP (sequence))
@@ -1320,9 +1454,9 @@ DEFUN ("elt", Felt, Selt, 2, 2, 0,
 }
 
 DEFUN ("member", Fmember, Smember, 2, 2, 0,
-  "Return non-nil if ELT is an element of LIST.  Comparison done with `equal'.\n\
-The value is actually the tail of LIST whose car is ELT.")
-  (elt, list)
+doc: /* 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)
      register Lisp_Object elt;
      Lisp_Object list;
 {
@@ -1341,10 +1475,10 @@ The value is actually the tail of LIST whose car is ELT.")
 }
 
 DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
-  "Return non-nil if ELT is an element of LIST.\n\
-Comparison done with EQ.  The value is actually the tail of LIST\n\
-whose car is ELT.")
-  (elt, list)
+       doc: /* Return non-nil if ELT is an element of LIST.
+Comparison done with `eq'.  The value is actually the tail of LIST
+whose car is ELT.  */)
+     (elt, list)
      Lisp_Object elt, list;
 {
   while (1)
@@ -1371,10 +1505,10 @@ whose car is ELT.")
 }
 
 DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
-  "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
-The value is actually the element of LIST whose car is KEY.\n\
-Elements of LIST that are not conses are ignored.")
-  (key, list)
+       doc: /* Return non-nil if KEY is `eq' to the car of an element of LIST.
+The value is actually the first element of LIST whose car is KEY.
+Elements of LIST that are not conses are ignored.  */)
+     (key, list)
      Lisp_Object key, list;
 {
   Lisp_Object result;
@@ -1428,9 +1562,9 @@ assq_no_quit (key, list)
 }
 
 DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
-  "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
-The value is actually the element of LIST whose car equals KEY.")
-  (key, list)
+       doc: /* Return non-nil if KEY is `equal' to the car of an element of LIST.
+The value is actually the first element of LIST whose car equals KEY.  */)
+     (key, list)
      Lisp_Object key, list;
 {
   Lisp_Object result, car;
@@ -1472,9 +1606,9 @@ The value is actually the element of LIST whose car equals KEY.")
 }
 
 DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
-  "Return non-nil if KEY is `eq' to the cdr of an element of LIST.\n\
-The value is actually the element of LIST whose cdr is KEY.")
-  (key, list)
+       doc: /* Return non-nil if KEY is `eq' to the cdr of an element of LIST.
+The value is actually the first element of LIST whose cdr is KEY.  */)
+     (key, list)
      register Lisp_Object key;
      Lisp_Object list;
 {
@@ -1514,9 +1648,9 @@ The value is actually the element of LIST whose cdr is KEY.")
 }
 
 DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
-  "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
-The value is actually the element of LIST whose cdr equals KEY.")
-  (key, list)
+       doc: /* Return non-nil if KEY is `equal' to the cdr of an element of LIST.
+The value is actually the first element of LIST whose cdr equals KEY.  */)
+     (key, list)
      Lisp_Object key, list;
 {
   Lisp_Object result, cdr;
@@ -1558,12 +1692,12 @@ The value is actually the element of LIST whose cdr equals KEY.")
 }
 \f
 DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
-  "Delete by side effect any occurrences of ELT as a member of LIST.\n\
-The modified LIST is returned.  Comparison is done with `eq'.\n\
-If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
-therefore, write `(setq foo (delq element foo))'\n\
-to be sure of changing the value of `foo'.")
-  (elt, list)
+       doc: /* Delete by side effect any occurrences of ELT as a member of LIST.
+The modified LIST is returned.  Comparison is done with `eq'.
+If the first member of LIST is ELT, there is no way to remove it by side effect;
+therefore, write `(setq foo (delq element foo))'
+to be sure of changing the value of `foo'.  */)
+     (elt, list)
      register Lisp_Object elt;
      Lisp_Object list;
 {
@@ -1593,19 +1727,19 @@ to be sure of changing the value of `foo'.")
 }
 
 DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
-  "Delete by side effect any occurrences of ELT as a member of SEQ.\n\
-SEQ must be a list, a vector, or a string.\n\
-The modified SEQ is returned.  Comparison is done with `equal'.\n\
-If SEQ is not a list, or the first member of SEQ is ELT, deleting it\n\
-is not a side effect; it is simply using a different sequence.\n\
-Therefore, write `(setq foo (delete element foo))'\n\
-to be sure of changing the value of `foo'.")
-  (elt, seq)
+       doc: /* Delete by side effect any occurrences of ELT as a member of SEQ.
+SEQ must be a list, a vector, or a string.
+The modified SEQ is returned.  Comparison is done with `equal'.
+If SEQ is not a list, or the first member of SEQ is ELT, deleting it
+is not a side effect; it is simply using a different sequence.
+Therefore, write `(setq foo (delete element foo))'
+to be sure of changing the value of `foo'.  */)
+     (elt, seq)
      Lisp_Object elt, seq;
 {
   if (VECTORP (seq))
     {
-      EMACS_INT i, n, size;
+      EMACS_INT i, n;
 
       for (i = n = 0; i < ASIZE (seq); ++i)
        if (NILP (Fequal (AREF (seq, i), elt)))
@@ -1613,13 +1747,12 @@ to be sure of changing the value of `foo'.")
 
       if (n != ASIZE (seq))
        {
-         struct Lisp_Vector *p = allocate_vectorlike (n);
+         struct Lisp_Vector *p = allocate_vector (n);
 
          for (i = n = 0; i < ASIZE (seq); ++i)
            if (NILP (Fequal (AREF (seq, i), elt)))
              p->contents[n++] = AREF (seq, i);
 
-         p->size = n;
          XSETVECTOR (seq, p);
        }
     }
@@ -1629,18 +1762,18 @@ to be sure of changing the value of `foo'.")
       int c;
 
       for (i = nchars = nbytes = ibyte = 0;
-          i < XSTRING (seq)->size;
+          i < SCHARS (seq);
           ++i, ibyte += cbytes)
        {
          if (STRING_MULTIBYTE (seq))
            {
-             c = STRING_CHAR (&XSTRING (seq)->data[ibyte],
-                              STRING_BYTES (XSTRING (seq)) - ibyte);
+             c = STRING_CHAR (SDATA (seq) + ibyte,
+                              SBYTES (seq) - ibyte);
              cbytes = CHAR_BYTES (c);
            }
          else
            {
-             c = XSTRING (seq)->data[i];
+             c = SREF (seq, i);
              cbytes = 1;
            }
 
@@ -1651,34 +1784,34 @@ to be sure of changing the value of `foo'.")
            }
        }
 
-      if (nchars != XSTRING (seq)->size)
+      if (nchars != SCHARS (seq))
        {
          Lisp_Object tem;
 
          tem = make_uninit_multibyte_string (nchars, nbytes);
          if (!STRING_MULTIBYTE (seq))
-           SET_STRING_BYTES (XSTRING (tem), -1);
+           STRING_SET_UNIBYTE (tem);
 
          for (i = nchars = nbytes = ibyte = 0;
-              i < XSTRING (seq)->size;
+              i < SCHARS (seq);
               ++i, ibyte += cbytes)
            {
              if (STRING_MULTIBYTE (seq))
                {
-                 c = STRING_CHAR (&XSTRING (seq)->data[ibyte],
-                                  STRING_BYTES (XSTRING (seq)) - ibyte);
+                 c = STRING_CHAR (SDATA (seq) + ibyte,
+                                  SBYTES (seq) - ibyte);
                  cbytes = CHAR_BYTES (c);
                }
              else
                {
-                 c = XSTRING (seq)->data[i];
+                 c = SREF (seq, i);
                  cbytes = 1;
                }
 
              if (!INTEGERP (elt) || c != XINT (elt))
                {
-                 unsigned char *from = &XSTRING (seq)->data[ibyte];
-                 unsigned char *to   = &XSTRING (tem)->data[nbytes];
+                 unsigned char *from = SDATA (seq) + ibyte;
+                 unsigned char *to   = SDATA (tem) + nbytes;
                  EMACS_INT n;
 
                  ++nchars;
@@ -1718,9 +1851,9 @@ to be sure of changing the value of `foo'.")
 }
 
 DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
-  "Reverse LIST by modifying cdr pointers.\n\
-Returns the beginning of the reversed list.")
-  (list)
+       doc: /* Reverse LIST by modifying cdr pointers.
+Return the reversed list.  */)
+     (list)
      Lisp_Object list;
 {
   register Lisp_Object prev, tail, next;
@@ -1742,15 +1875,18 @@ Returns the beginning of the reversed list.")
 }
 
 DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
-  "Reverse LIST, copying.  Returns the beginning of the reversed list.\n\
-See also the function `nreverse', which is used more often.")
-  (list)
+       doc: /* Reverse LIST, copying.  Return the reversed list.
+See also the function `nreverse', which is used more often.  */)
+     (list)
      Lisp_Object list;
 {
   Lisp_Object new;
 
   for (new = Qnil; CONSP (list); list = XCDR (list))
-    new = Fcons (XCAR (list), new);
+    {
+      QUIT;
+      new = Fcons (XCAR (list), new);
+    }
   if (!NILP (list))
     wrong_type_argument (Qconsp, list);
   return new;
@@ -1759,11 +1895,11 @@ See also the function `nreverse', which is used more often.")
 Lisp_Object merge ();
 
 DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
-  "Sort LIST, stably, comparing elements using PREDICATE.\n\
-Returns the sorted list.  LIST is modified by side effects.\n\
-PREDICATE is called with two elements of LIST, and should return T\n\
-if the first element is \"less\" than the second.")
-  (list, predicate)
+       doc: /* Sort LIST, stably, comparing elements using PREDICATE.
+Returns the sorted list.  LIST is modified by side effects.
+PREDICATE is called with two elements of LIST, and should return non-nil
+if the first element should sort before the second.  */)
+     (list, predicate)
      Lisp_Object list, predicate;
 {
   Lisp_Object front, back;
@@ -1848,48 +1984,90 @@ merge (org_l1, org_l2, pred)
       tail = tem;
     }
 }
+
 \f
+#if 0 /* Unsafe version.  */
+DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
+       doc: /* Extract a value from a property list.
+PLIST is a property list, which is a list of the form
+\(PROP1 VALUE1 PROP2 VALUE2...).  This function returns the value
+corresponding to the given PROP, or nil if PROP is not
+one of the properties on the list.  */)
+     (plist, prop)
+     Lisp_Object plist;
+     Lisp_Object prop;
+{
+  Lisp_Object tail;
+
+  for (tail = plist;
+       CONSP (tail) && CONSP (XCDR (tail));
+       tail = XCDR (XCDR (tail)))
+    {
+      if (EQ (prop, XCAR (tail)))
+       return XCAR (XCDR (tail));
+
+      /* This function can be called asynchronously
+        (setup_coding_system).  Don't QUIT in that case.  */
+      if (!interrupt_input_blocked)
+       QUIT;
+    }
+
+  if (!NILP (tail))
+    wrong_type_argument (Qlistp, prop);
+
+  return Qnil;
+}
+#endif
+
+/* This does not check for quits.  That is safe since it must terminate.  */
 
 DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
-  "Extract a value from a property list.\n\
-PLIST is a property list, which is a list of the form\n\
-\(PROP1 VALUE1 PROP2 VALUE2...).  This function returns the value\n\
-corresponding to the given PROP, or nil if PROP is not\n\
-one of the properties on the list.")
-  (plist, prop)
+       doc: /* Extract a value from a property list.
+PLIST is a property list, which is a list of the form
+\(PROP1 VALUE1 PROP2 VALUE2...).  This function returns the value
+corresponding to the given PROP, or nil if PROP is not one of the
+properties on the list.  This function never signals an error.  */)
+     (plist, prop)
      Lisp_Object plist;
-     register Lisp_Object prop;
+     Lisp_Object prop;
 {
-  register Lisp_Object tail;
-  for (tail = plist; !NILP (tail); tail = Fcdr (XCDR (tail)))
+  Lisp_Object tail, halftail;
+
+  /* halftail is used to detect circular lists.  */
+  tail = halftail = plist;
+  while (CONSP (tail) && CONSP (XCDR (tail)))
     {
-      register Lisp_Object tem;
-      tem = Fcar (tail);
-      if (EQ (prop, tem))
-       return Fcar (XCDR (tail));
+      if (EQ (prop, XCAR (tail)))
+       return XCAR (XCDR (tail));
+
+      tail = XCDR (XCDR (tail));
+      halftail = XCDR (halftail);
+      if (EQ (tail, halftail))
+       break;
     }
+
   return Qnil;
 }
 
 DEFUN ("get", Fget, Sget, 2, 2, 0,
-  "Return the value of SYMBOL's PROPNAME property.\n\
-This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
-  (symbol, propname)
+       doc: /* Return the value of SYMBOL's PROPNAME property.
+This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.  */)
+     (symbol, propname)
      Lisp_Object symbol, propname;
 {
-  CHECK_SYMBOL (symbol, 0);
+  CHECK_SYMBOL (symbol);
   return Fplist_get (XSYMBOL (symbol)->plist, propname);
 }
 
 DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
-  "Change value in PLIST of PROP to VAL.\n\
-PLIST is a property list, which is a list of the form\n\
-\(PROP1 VALUE1 PROP2 VALUE2 ...).  PROP is a symbol and VAL is any object.\n\
-If PROP is already a property on the list, its value is set to VAL,\n\
-otherwise the new PROP VAL pair is added.  The new plist is returned;\n\
-use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
-The PLIST is modified by side effects.")
-  (plist, prop, val)
+       doc: /* Change value in PLIST of PROP to VAL.
+PLIST is a property list, which is a list of the form
+\(PROP1 VALUE1 PROP2 VALUE2 ...).  PROP is 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 is returned;
+use `(setq x (plist-put x prop val))' to be sure to use the new value.
+The PLIST is modified by side effects.  */)
+     (plist, prop, val)
      Lisp_Object plist;
      register Lisp_Object prop;
      Lisp_Object val;
@@ -1905,7 +2083,9 @@ The PLIST is modified by side effects.")
          Fsetcar (XCDR (tail), val);
          return plist;
        }
+
       prev = tail;
+      QUIT;
     }
   newcell = Fcons (prop, Fcons (val, Qnil));
   if (NILP (prev))
@@ -1916,35 +2096,125 @@ The PLIST is modified by side effects.")
 }
 
 DEFUN ("put", Fput, Sput, 3, 3, 0,
-  "Store SYMBOL's PROPNAME property with value VALUE.\n\
-It can be retrieved with `(get SYMBOL PROPNAME)'.")
-  (symbol, propname, value)
+       doc: /* Store SYMBOL's PROPNAME property with value VALUE.
+It can be retrieved with `(get SYMBOL PROPNAME)'.  */)
+     (symbol, propname, value)
      Lisp_Object symbol, propname, value;
 {
-  CHECK_SYMBOL (symbol, 0);
+  CHECK_SYMBOL (symbol);
   XSYMBOL (symbol)->plist
     = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
   return value;
 }
+\f
+DEFUN ("lax-plist-get", Flax_plist_get, Slax_plist_get, 2, 2, 0,
+       doc: /* Extract a value from a property list, comparing with `equal'.
+PLIST is a property list, which is a list of the form
+\(PROP1 VALUE1 PROP2 VALUE2...).  This function returns the value
+corresponding to the given PROP, or nil if PROP is not
+one of the properties on the list.  */)
+     (plist, prop)
+     Lisp_Object plist;
+     Lisp_Object prop;
+{
+  Lisp_Object tail;
+
+  for (tail = plist;
+       CONSP (tail) && CONSP (XCDR (tail));
+       tail = XCDR (XCDR (tail)))
+    {
+      if (! NILP (Fequal (prop, XCAR (tail))))
+       return XCAR (XCDR (tail));
+
+      QUIT;
+    }
+
+  if (!NILP (tail))
+    wrong_type_argument (Qlistp, prop);
+
+  return Qnil;
+}
+
+DEFUN ("lax-plist-put", Flax_plist_put, Slax_plist_put, 3, 3, 0,
+       doc: /* Change value in PLIST of PROP to VAL, comparing with `equal'.
+PLIST is a property list, which is a list of the form
+\(PROP1 VALUE1 PROP2 VALUE2 ...).  PROP and VAL are any objects.
+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 is returned;
+use `(setq x (lax-plist-put x prop val))' to be sure to use the new value.
+The PLIST is modified by side effects.  */)
+     (plist, prop, val)
+     Lisp_Object plist;
+     register Lisp_Object prop;
+     Lisp_Object val;
+{
+  register Lisp_Object tail, prev;
+  Lisp_Object newcell;
+  prev = Qnil;
+  for (tail = plist; CONSP (tail) && CONSP (XCDR (tail));
+       tail = XCDR (XCDR (tail)))
+    {
+      if (! NILP (Fequal (prop, XCAR (tail))))
+       {
+         Fsetcar (XCDR (tail), val);
+         return plist;
+       }
+
+      prev = tail;
+      QUIT;
+    }
+  newcell = Fcons (prop, Fcons (val, Qnil));
+  if (NILP (prev))
+    return newcell;
+  else
+    Fsetcdr (XCDR (prev), newcell);
+  return plist;
+}
+\f
+DEFUN ("eql", Feql, Seql, 2, 2, 0,
+       doc: /* Return t if the two args are the same Lisp object.
+Floating-point numbers of equal value are `eql', but they may not be `eq'.  */)
+     (obj1, obj2)
+     Lisp_Object obj1, obj2;
+{
+  if (FLOATP (obj1))
+    return internal_equal (obj1, obj2, 0, 0) ? Qt : Qnil;
+  else
+    return EQ (obj1, obj2) ? Qt : Qnil;
+}
 
 DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
-  "Return t if two Lisp objects have similar structure and contents.\n\
-They must have the same data type.\n\
-Conses are compared by comparing the cars and the cdrs.\n\
-Vectors and strings are compared element by element.\n\
-Numbers are compared by value, but integers cannot equal floats.\n\
- (Use `=' if you want integers and floats to be able to be equal.)\n\
-Symbols must match exactly.")
-  (o1, o2)
+       doc: /* Return t if two Lisp objects have similar structure and contents.
+They must have the same data type.
+Conses are compared by comparing the cars and the cdrs.
+Vectors and strings are compared element by element.
+Numbers are compared by value, but integers cannot equal floats.
+ (Use `=' if you want integers and floats to be able to be equal.)
+Symbols must match exactly.  */)
+     (o1, o2)
+     register Lisp_Object o1, o2;
+{
+  return internal_equal (o1, o2, 0, 0) ? Qt : Qnil;
+}
+
+DEFUN ("equal-including-properties", Fequal_including_properties, Sequal_including_properties, 2, 2, 0,
+       doc: /* Return t if two Lisp objects have similar structure and contents.
+This is like `equal' except that it compares the text properties
+of strings.  (`equal' ignores text properties.)  */)
+     (o1, o2)
      register Lisp_Object o1, o2;
 {
-  return internal_equal (o1, o2, 0) ? Qt : Qnil;
+  return internal_equal (o1, o2, 0, 1) ? Qt : Qnil;
 }
 
+/* DEPTH is current depth of recursion.  Signal an error if it
+   gets too deep.
+   PROPS, if non-nil, means compare string text properties too.  */
+
 static int
-internal_equal (o1, o2, depth)
+internal_equal (o1, o2, depth, props)
      register Lisp_Object o1, o2;
-     int depth;
+     int depth, props;
 {
   if (depth > 200)
     error ("Stack overflow in equal");
@@ -1959,10 +2229,18 @@ internal_equal (o1, o2, depth)
   switch (XTYPE (o1))
     {
     case Lisp_Float:
-      return (extract_float (o1) == extract_float (o2));
+      {
+       double d1, d2;
+
+       d1 = extract_float (o1);
+       d2 = extract_float (o2);
+       /* If d is a NaN, then d != d. Two NaNs should be `equal' even
+          though they are not =. */
+       return d1 == d2 || (d1 != d1 && d2 != d2);
+      }
 
     case Lisp_Cons:
-      if (!internal_equal (XCAR (o1), XCAR (o2), depth + 1))
+      if (!internal_equal (XCAR (o1), XCAR (o2), depth + 1, props))
        return 0;
       o1 = XCDR (o1);
       o2 = XCDR (o2);
@@ -1974,9 +2252,9 @@ internal_equal (o1, o2, depth)
       if (OVERLAYP (o1))
        {
          if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2),
-                              depth + 1)
+                              depth + 1, props)
              || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2),
-                                 depth + 1))
+                                 depth + 1, props))
            return 0;
          o1 = XOVERLAY (o1)->plist;
          o2 = XOVERLAY (o2)->plist;
@@ -1992,8 +2270,8 @@ internal_equal (o1, o2, depth)
 
     case Lisp_Vectorlike:
       {
-       register int i, size;
-       size = XVECTOR (o1)->size;
+       register int i;
+       EMACS_INT size = XVECTOR (o1)->size;
        /* Pseudovectors have the type encoded in the size field, so this test
           actually checks that the objects have the same type as well as the
           same size.  */
@@ -2003,7 +2281,8 @@ internal_equal (o1, o2, depth)
        if (BOOL_VECTOR_P (o1))
          {
            int size_in_chars
-             = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+             = ((XBOOL_VECTOR (o1)->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
+                / BOOL_VECTOR_BITS_PER_CHAR);
 
            if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
              return 0;
@@ -2028,7 +2307,7 @@ internal_equal (o1, o2, depth)
            Lisp_Object v1, v2;
            v1 = XVECTOR (o1)->contents [i];
            v2 = XVECTOR (o2)->contents [i];
-           if (!internal_equal (v1, v2, depth + 1))
+           if (!internal_equal (v1, v2, depth + 1, props))
              return 0;
          }
        return 1;
@@ -2036,24 +2315,32 @@ internal_equal (o1, o2, depth)
       break;
 
     case Lisp_String:
-      if (XSTRING (o1)->size != XSTRING (o2)->size)
+      if (SCHARS (o1) != SCHARS (o2))
+       return 0;
+      if (SBYTES (o1) != SBYTES (o2))
        return 0;
-      if (STRING_BYTES (XSTRING (o1)) != STRING_BYTES (XSTRING (o2)))
+      if (bcmp (SDATA (o1), SDATA (o2),
+               SBYTES (o1)))
        return 0;
-      if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
-               STRING_BYTES (XSTRING (o1))))
+      if (props && !compare_string_intervals (o1, o2))
        return 0;
       return 1;
+
+    case Lisp_Int:
+    case Lisp_Symbol:
+    case Lisp_Type_Limit:
+      break;
     }
+
   return 0;
 }
 \f
 extern Lisp_Object Fmake_char_internal ();
 
 DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
-  "Store each element of ARRAY with ITEM.\n\
-ARRAY is a vector, string, char-table, or bool-vector.")
-  (array, item)
+       doc: /* Store each element of ARRAY with ITEM.
+ARRAY is a vector, string, char-table, or bool-vector.  */)
+     (array, item)
      Lisp_Object array, item;
 {
   register int size, index, charval;
@@ -2075,15 +2362,15 @@ ARRAY is a vector, string, char-table, or bool-vector.")
     }
   else if (STRINGP (array))
     {
-      register unsigned char *p = XSTRING (array)->data;
-      CHECK_NUMBER (item, 1);
+      register unsigned char *p = SDATA (array);
+      CHECK_NUMBER (item);
       charval = XINT (item);
-      size = XSTRING (array)->size;
+      size = SCHARS (array);
       if (STRING_MULTIBYTE (array))
        {
          unsigned char str[MAX_MULTIBYTE_LENGTH];
          int len = CHAR_STRING (charval, str);
-         int size_byte = STRING_BYTES (XSTRING (array));
+         int size_byte = SBYTES (array);
          unsigned char *p1 = p, *endp = p + size_byte;
          int i;
 
@@ -2106,11 +2393,19 @@ ARRAY is a vector, string, char-table, or bool-vector.")
     {
       register unsigned char *p = XBOOL_VECTOR (array)->data;
       int size_in_chars
-       = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+       = ((XBOOL_VECTOR (array)->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
+          / BOOL_VECTOR_BITS_PER_CHAR);
 
       charval = (! NILP (item) ? -1 : 0);
-      for (index = 0; index < size_in_chars; index++)
+      for (index = 0; index < size_in_chars - 1; index++)
        p[index] = charval;
+      if (index < size_in_chars)
+       {
+         /* Mask out bits beyond the vector size.  */
+         if (XBOOL_VECTOR (array)->size % BOOL_VECTOR_BITS_PER_CHAR)
+           charval &= (1 << (XBOOL_VECTOR (array)->size % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
+         p[index] = charval;
+       }
     }
   else
     {
@@ -2119,47 +2414,63 @@ ARRAY is a vector, string, char-table, or bool-vector.")
     }
   return array;
 }
+
+DEFUN ("clear-string", Fclear_string, Sclear_string,
+       1, 1, 0,
+       doc: /* Clear the contents of STRING.
+This makes STRING unibyte and may change its length.  */)
+     (string)
+     Lisp_Object string;
+{
+  int len;
+  CHECK_STRING (string);
+  len = SBYTES (string);
+  bzero (SDATA (string), len);
+  STRING_SET_CHARS (string, len);
+  STRING_SET_UNIBYTE (string);
+  return Qnil;
+}
 \f
 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
        1, 1, 0,
-  "Return the subtype of char-table CHAR-TABLE.   The value is a symbol.")
-  (char_table)
+       doc: /* Return the subtype of char-table CHAR-TABLE.  The value is a symbol.  */)
+     (char_table)
      Lisp_Object char_table;
 {
-  CHECK_CHAR_TABLE (char_table, 0);
+  CHECK_CHAR_TABLE (char_table);
 
   return XCHAR_TABLE (char_table)->purpose;
 }
 
 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
        1, 1, 0,
-  "Return the parent char-table of CHAR-TABLE.\n\
-The value is either nil or another char-table.\n\
-If CHAR-TABLE holds nil for a given character,\n\
-then the actual applicable value is inherited from the parent char-table\n\
-\(or from its parents, if necessary).")
-  (char_table)
+       doc: /* Return the parent char-table of CHAR-TABLE.
+The value is either nil or another char-table.
+If CHAR-TABLE holds nil for a given character,
+then the actual applicable value is inherited from the parent char-table
+\(or from its parents, if necessary).  */)
+     (char_table)
      Lisp_Object char_table;
 {
-  CHECK_CHAR_TABLE (char_table, 0);
+  CHECK_CHAR_TABLE (char_table);
 
   return XCHAR_TABLE (char_table)->parent;
 }
 
 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
        2, 2, 0,
-  "Set the parent char-table of CHAR-TABLE to PARENT.\n\
-PARENT must be either nil or another char-table.")
-  (char_table, parent)
+       doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
+Return PARENT.  PARENT must be either nil or another char-table.  */)
+     (char_table, parent)
      Lisp_Object char_table, parent;
 {
   Lisp_Object temp;
 
-  CHECK_CHAR_TABLE (char_table, 0);
+  CHECK_CHAR_TABLE (char_table);
 
   if (!NILP (parent))
     {
-      CHECK_CHAR_TABLE (parent, 0);
+      CHECK_CHAR_TABLE (parent);
 
       for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
        if (EQ (temp, char_table))
@@ -2173,12 +2484,12 @@ PARENT must be either nil or another char-table.")
 
 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
        2, 2, 0,
-  "Return the value of CHAR-TABLE's extra-slot number N.")
-  (char_table, n)
+       doc: /* Return the value of CHAR-TABLE's extra-slot number N.  */)
+     (char_table, n)
      Lisp_Object char_table, n;
 {
-  CHECK_CHAR_TABLE (char_table, 1);
-  CHECK_NUMBER (n, 2);
+  CHECK_CHAR_TABLE (char_table);
+  CHECK_NUMBER (n);
   if (XINT (n) < 0
       || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
     args_out_of_range (char_table, n);
@@ -2189,12 +2500,12 @@ DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
        Sset_char_table_extra_slot,
        3, 3, 0,
-  "Set CHAR-TABLE's extra-slot number N to VALUE.")
-  (char_table, n, value)
+       doc: /* Set CHAR-TABLE's extra-slot number N to VALUE.  */)
+     (char_table, n, value)
      Lisp_Object char_table, n, value;
 {
-  CHECK_CHAR_TABLE (char_table, 1);
-  CHECK_NUMBER (n, 2);
+  CHECK_CHAR_TABLE (char_table);
+  CHECK_NUMBER (n);
   if (XINT (n) < 0
       || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
     args_out_of_range (char_table, n);
@@ -2202,99 +2513,204 @@ DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
   return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
 }
 \f
+static Lisp_Object
+char_table_range (table, from, to, defalt)
+     Lisp_Object table;
+     int from, to;
+     Lisp_Object defalt;
+{
+  Lisp_Object val;
+
+  if (! NILP (XCHAR_TABLE (table)->defalt))
+    defalt = XCHAR_TABLE (table)->defalt;
+  val = XCHAR_TABLE (table)->contents[from];
+  if (SUB_CHAR_TABLE_P (val))
+    val = char_table_range (val, 32, 127, defalt);
+  else if (NILP (val))
+    val = defalt;
+  for (from++; from <= to; from++)
+    {
+      Lisp_Object this_val;
+
+      this_val = XCHAR_TABLE (table)->contents[from];
+      if (SUB_CHAR_TABLE_P (this_val))
+       this_val = char_table_range (this_val, 32, 127, defalt);
+      else if (NILP (this_val))
+       this_val = defalt;
+      if (! EQ (val, this_val))
+       error ("Characters in the range have inconsistent values");
+    }
+  return val;
+}
+
+
 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
        2, 2, 0,
-  "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
-RANGE should be nil (for the default value)\n\
-a vector which identifies a character set or a row of a character set,\n\
-a character set name, or a character code.")
-  (char_table, range)
+       doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
+RANGE should be nil (for the default value),
+a vector which identifies a character set or a row of a character set,
+a character set name, or a character code.
+If the characters in the specified range have different values,
+an error is signaled.
+
+Note that this function doesn't check the parent of CHAR-TABLE.  */)
+     (char_table, range)
      Lisp_Object char_table, range;
 {
-  CHECK_CHAR_TABLE (char_table, 0);
+  int charset_id, c1 = 0, c2 = 0;
+  int size;
+  Lisp_Object ch, val, current_default;
+
+  CHECK_CHAR_TABLE (char_table);
 
   if (EQ (range, Qnil))
     return XCHAR_TABLE (char_table)->defalt;
-  else if (INTEGERP (range))
-    return Faref (char_table, range);
+  if (INTEGERP (range))
+    {
+      int c = XINT (range);
+      if (! CHAR_VALID_P (c, 0))
+       error ("Invalid character code: %d", c);
+      ch = range;
+      SPLIT_CHAR (c, charset_id, c1, c2);
+    }
   else if (SYMBOLP (range))
     {
       Lisp_Object charset_info;
 
       charset_info = Fget (range, Qcharset);
-      CHECK_VECTOR (charset_info, 0);
-
-      return Faref (char_table,
-                   make_number (XINT (XVECTOR (charset_info)->contents[0])
-                                + 128));
+      CHECK_VECTOR (charset_info);
+      charset_id = XINT (XVECTOR (charset_info)->contents[0]);
+      ch = Fmake_char_internal (make_number (charset_id),
+                               make_number (0), make_number (0));
     }
   else if (VECTORP (range))
     {
-      if (XVECTOR (range)->size == 1)
-       return Faref (char_table,
-                     make_number (XINT (XVECTOR (range)->contents[0]) + 128));
-      else
+      size = ASIZE (range);
+      if (size == 0)
+       args_out_of_range (range, make_number (0));
+      CHECK_NUMBER (AREF (range, 0));
+      charset_id = XINT (AREF (range, 0));
+      if (size > 1)
        {
-         int size = XVECTOR (range)->size;
-         Lisp_Object *val = XVECTOR (range)->contents;
-         Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
-                                               size <= 1 ? Qnil : val[1],
-                                               size <= 2 ? Qnil : val[2]);
-         return Faref (char_table, ch);
+         CHECK_NUMBER (AREF (range, 1));
+         c1 = XINT (AREF (range, 1));
+         if (size > 2)
+           {
+             CHECK_NUMBER (AREF (range, 2));
+             c2 = XINT (AREF (range, 2));
+           }
        }
+
+      /* This checks if charset_id, c0, and c1 are all valid or not.  */
+      ch = Fmake_char_internal (make_number (charset_id),
+                               make_number (c1), make_number (c2));
     }
   else
     error ("Invalid RANGE argument to `char-table-range'");
-  return Qt;
+
+  if (c1 > 0 && (CHARSET_DIMENSION (charset_id) == 1 || c2 > 0))
+    {
+      /* Fully specified character.  */
+      Lisp_Object parent = XCHAR_TABLE (char_table)->parent;
+
+      XCHAR_TABLE (char_table)->parent = Qnil;
+      val = Faref (char_table, ch);
+      XCHAR_TABLE (char_table)->parent = parent;
+      return val;
+    }
+
+  current_default = XCHAR_TABLE (char_table)->defalt;
+  if (charset_id == CHARSET_ASCII
+      || charset_id == CHARSET_8_BIT_CONTROL
+      || charset_id == CHARSET_8_BIT_GRAPHIC)
+    {
+      int from, to, defalt;
+
+      if (charset_id == CHARSET_ASCII)
+       from = 0, to = 127, defalt = CHAR_TABLE_DEFAULT_SLOT_ASCII;
+      else if (charset_id == CHARSET_8_BIT_CONTROL)
+       from = 128, to = 159, defalt = CHAR_TABLE_DEFAULT_SLOT_8_BIT_CONTROL;
+      else
+       from = 160, to = 255, defalt = CHAR_TABLE_DEFAULT_SLOT_8_BIT_GRAPHIC;
+      if (! NILP (XCHAR_TABLE (char_table)->contents[defalt]))
+       current_default = XCHAR_TABLE (char_table)->contents[defalt];
+      return char_table_range (char_table, from, to, current_default);
+    }
+
+  val = XCHAR_TABLE (char_table)->contents[128 + charset_id];
+  if (! SUB_CHAR_TABLE_P (val))
+    return (NILP (val) ? current_default : val);
+  if (! NILP (XCHAR_TABLE (val)->defalt))
+    current_default = XCHAR_TABLE (val)->defalt;
+  if (c1 == 0)
+    return char_table_range (val, 32, 127, current_default);
+  val = XCHAR_TABLE (val)->contents[c1];
+  if (! SUB_CHAR_TABLE_P (val))
+    return (NILP (val) ? current_default : val);
+  if (! NILP (XCHAR_TABLE (val)->defalt))
+    current_default = XCHAR_TABLE (val)->defalt;
+  return char_table_range (val, 32, 127, current_default);
 }
 
 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
        3, 3, 0,
-  "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
-RANGE should be t (for all characters), nil (for the default value)\n\
-a vector which identifies a character set or a row of a character set,\n\
-a coding system, or a character code.")
-  (char_table, range, value)
+       doc: /* Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.
+RANGE should be t (for all characters), nil (for the default value),
+a character set, a vector which identifies a character set, a row of a
+character set, or a character code.  Return VALUE.  */)
+     (char_table, range, value)
      Lisp_Object char_table, range, value;
 {
   int i;
 
-  CHECK_CHAR_TABLE (char_table, 0);
+  CHECK_CHAR_TABLE (char_table);
 
   if (EQ (range, Qt))
     for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
-      XCHAR_TABLE (char_table)->contents[i] = value;
+      {
+       /* Don't set these special slots used for default values of
+          ascii, eight-bit-control, and eight-bit-graphic.  */
+       if (i != CHAR_TABLE_DEFAULT_SLOT_ASCII
+           && i != CHAR_TABLE_DEFAULT_SLOT_8_BIT_CONTROL
+           && i != CHAR_TABLE_DEFAULT_SLOT_8_BIT_GRAPHIC)
+         XCHAR_TABLE (char_table)->contents[i] = value;
+      }
   else if (EQ (range, Qnil))
     XCHAR_TABLE (char_table)->defalt = value;
   else if (SYMBOLP (range))
     {
       Lisp_Object charset_info;
+      int charset_id;
 
       charset_info = Fget (range, Qcharset);
-      CHECK_VECTOR (charset_info, 0);
-
-      return Faset (char_table,
-                   make_number (XINT (XVECTOR (charset_info)->contents[0])
-                                + 128),
-                   value);
+      if (! VECTORP (charset_info)
+         || ! NATNUMP (AREF (charset_info, 0))
+         || (charset_id = XINT (AREF (charset_info, 0)),
+             ! CHARSET_DEFINED_P (charset_id)))
+       error ("Invalid charset: %s", SDATA (SYMBOL_NAME (range)));
+
+      if (charset_id == CHARSET_ASCII)
+       for (i = 0; i < 128; i++)
+         XCHAR_TABLE (char_table)->contents[i] = value;
+      else if (charset_id == CHARSET_8_BIT_CONTROL)
+       for (i = 128; i < 160; i++)
+         XCHAR_TABLE (char_table)->contents[i] = value;
+      else if (charset_id == CHARSET_8_BIT_GRAPHIC)
+       for (i = 160; i < 256; i++)
+         XCHAR_TABLE (char_table)->contents[i] = value;
+      else
+       XCHAR_TABLE (char_table)->contents[charset_id + 128] = value;
     }
   else if (INTEGERP (range))
     Faset (char_table, range, value);
   else if (VECTORP (range))
     {
-      if (XVECTOR (range)->size == 1)
-       return Faset (char_table,
-                     make_number (XINT (XVECTOR (range)->contents[0]) + 128),
-                     value);
-      else
-       {
-         int size = XVECTOR (range)->size;
-         Lisp_Object *val = XVECTOR (range)->contents;
-         Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
-                                               size <= 1 ? Qnil : val[1],
-                                               size <= 2 ? Qnil : val[2]);
-         return Faset (char_table, ch, value);
-       }
+      int size = XVECTOR (range)->size;
+      Lisp_Object *val = XVECTOR (range)->contents;
+      Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
+                                           size <= 1 ? Qnil : val[1],
+                                           size <= 2 ? Qnil : val[2]);
+      Faset (char_table, ch, value);
     }
   else
     error ("Invalid RANGE argument to `set-char-table-range'");
@@ -2304,17 +2720,19 @@ a coding system, or a character code.")
 
 DEFUN ("set-char-table-default", Fset_char_table_default,
        Sset_char_table_default, 3, 3, 0,
-  "Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.\n\
-The generic character specifies the group of characters.\n\
-See also the documentation of make-char.")
-  (char_table, ch, value)
+       doc: /* Set the default value in CHAR-TABLE for generic character CH to VALUE.
+The generic character specifies the group of characters.
+If CH is a normal character, set the default value for a group of
+characters to which CH belongs.
+See also the documentation of `make-char'.  */)
+     (char_table, ch, value)
      Lisp_Object char_table, ch, value;
 {
   int c, charset, code1, code2;
   Lisp_Object temp;
 
-  CHECK_CHAR_TABLE (char_table, 0);
-  CHECK_NUMBER (ch, 1);
+  CHECK_CHAR_TABLE (char_table);
+  CHECK_NUMBER (ch);
 
   c = XINT (ch);
   SPLIT_CHAR (c, charset, code1, code2);
@@ -2325,26 +2743,34 @@ See also the documentation of make-char.")
   if (! CHARSET_VALID_P (charset))
     invalid_character (c);
 
-  if (charset == CHARSET_ASCII)
-    return (XCHAR_TABLE (char_table)->defalt = value);
+  if (SINGLE_BYTE_CHAR_P (c))
+    {
+      /* We use special slots for the default values of single byte
+        characters.  */
+      int default_slot
+       = (c < 0x80 ? CHAR_TABLE_DEFAULT_SLOT_ASCII
+          : c < 0xA0 ? CHAR_TABLE_DEFAULT_SLOT_8_BIT_CONTROL
+          : CHAR_TABLE_DEFAULT_SLOT_8_BIT_GRAPHIC);
+
+      return (XCHAR_TABLE (char_table)->contents[default_slot] = value);
+    }
 
   /* Even if C is not a generic char, we had better behave as if a
      generic char is specified.  */
-  if (CHARSET_DIMENSION (charset) == 1)
+  if (!CHARSET_DEFINED_P (charset) || CHARSET_DIMENSION (charset) == 1)
     code1 = 0;
   temp = XCHAR_TABLE (char_table)->contents[charset + 128];
+  if (! SUB_CHAR_TABLE_P (temp))
+    {
+      temp = make_sub_char_table (temp);
+      XCHAR_TABLE (char_table)->contents[charset + 128] = temp;
+    }
   if (!code1)
     {
-      if (SUB_CHAR_TABLE_P (temp))
-       XCHAR_TABLE (temp)->defalt = value;
-      else
-       XCHAR_TABLE (char_table)->contents[charset + 128] = value;
+      XCHAR_TABLE (temp)->defalt = value;
       return value;
     }
   char_table = temp;
-  if (! SUB_CHAR_TABLE_P (char_table))
-    char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
-           = make_sub_char_table (temp));
   temp = XCHAR_TABLE (char_table)->contents[code1];
   if (SUB_CHAR_TABLE_P (temp))
     XCHAR_TABLE (temp)->defalt = value;
@@ -2393,23 +2819,22 @@ optimize_sub_char_table (table, chars)
 }
 
 DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
-       1, 1, 0,
-  "Optimize char table TABLE.")
-  (table)
+       1, 1, 0, doc: /* Optimize char table TABLE.  */)
+     (table)
      Lisp_Object table;
 {
   Lisp_Object elt;
   int dim;
   int i, j;
 
-  CHECK_CHAR_TABLE (table, 0);
+  CHECK_CHAR_TABLE (table);
 
   for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
     {
       elt = XCHAR_TABLE (table)->contents[i];
       if (!SUB_CHAR_TABLE_P (elt))
        continue;
-      dim = CHARSET_DIMENSION (i);
+      dim = CHARSET_DIMENSION (i - 128);
       if (dim == 2)
        for (j = 32; j < SUB_CHAR_TABLE_ORDINARY_SLOTS; j++)
          optimize_sub_char_table (XCHAR_TABLE (elt)->contents + j, dim);
@@ -2428,19 +2853,26 @@ DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
    ARG is passed to C_FUNCTION when that is called.  */
 
 void
-map_char_table (c_function, function, subtable, arg, depth, indices)
+map_char_table (c_function, function, table, subtable, arg, depth, indices)
      void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
-     Lisp_Object function, subtable, arg, *indices;
+     Lisp_Object function, table, subtable, arg, *indices;
      int depth;
 {
   int i, to;
+  struct gcpro gcpro1, gcpro2,  gcpro3, gcpro4;
+
+  GCPRO4 (arg, table, subtable, function);
 
   if (depth == 0)
     {
       /* At first, handle ASCII and 8-bit European characters.  */
       for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
        {
-         Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
+         Lisp_Object elt= XCHAR_TABLE (subtable)->contents[i];
+         if (NILP (elt))
+           elt = XCHAR_TABLE (subtable)->defalt;
+         if (NILP (elt))
+           elt = Faref (subtable, make_number (i));
          if (c_function)
            (*c_function) (arg, make_number (i), elt);
          else
@@ -2449,7 +2881,10 @@ map_char_table (c_function, function, subtable, arg, depth, indices)
 #if 0 /* If the char table has entries for higher characters,
         we should report them.  */
       if (NILP (current_buffer->enable_multibyte_characters))
-       return;
+       {
+         UNGCPRO;
+         return;
+       }
 #endif
       to = CHAR_TABLE_ORDINARY_SLOTS;
     }
@@ -2481,39 +2916,56 @@ map_char_table (c_function, function, subtable, arg, depth, indices)
        {
          if (depth >= 3)
            error ("Too deep char table");
-         map_char_table (c_function, function, elt, arg, depth + 1, indices);
+         map_char_table (c_function, function, table, elt, arg, depth + 1, indices);
        }
       else
        {
          int c1, c2, c;
 
-         if (NILP (elt))
-           elt = XCHAR_TABLE (subtable)->defalt;
          c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
          c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
          c = MAKE_CHAR (charset, c1, c2);
+
+         if (NILP (elt))
+           elt = XCHAR_TABLE (subtable)->defalt;
+         if (NILP  (elt))
+           elt = Faref (table, make_number (c));
+
          if (c_function)
            (*c_function) (arg, make_number (c), elt);
          else
            call2 (function, make_number (c), elt);
        }
     }
+  UNGCPRO;
+}
+
+static void void_call2 P_ ((Lisp_Object a, Lisp_Object b, Lisp_Object c));
+static void
+void_call2 (a, b, c)
+     Lisp_Object a, b, c;
+{
+  call2 (a, b, c);
 }
 
 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
-  2, 2, 0,
-  "Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.\n\
-FUNCTION is called with two arguments--a key and a value.\n\
-The key is always a possible IDX argument to `aref'.")
-  (function, char_table)
+       2, 2, 0,
+       doc: /* Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.
+FUNCTION is called with two arguments--a key and a value.
+The key is always a possible IDX argument to `aref'.  */)
+     (function, char_table)
      Lisp_Object function, char_table;
 {
   /* The depth of char table is at most 3. */
   Lisp_Object indices[3];
 
-  CHECK_CHAR_TABLE (char_table, 1);
+  CHECK_CHAR_TABLE (char_table);
 
-  map_char_table (NULL, function, char_table, char_table, 0, indices);
+  /* When Lisp_Object is represented as a union, `call2' cannot directly
+     be passed to map_char_table because it returns a Lisp_Object rather
+     than returning nothing.
+     Casting leads to crashes on some architectures.  -stef  */
+  map_char_table (void_call2, Qnil, char_table, char_table, function, 0, indices);
   return Qnil;
 }
 
@@ -2568,16 +3020,17 @@ nconc2 (s1, s2)
 }
 
 DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
-  "Concatenate any number of lists by altering them.\n\
-Only the last argument is not altered, and need not be a list.")
-  (nargs, args)
+       doc: /* Concatenate any number of lists by altering them.
+Only the last argument is not altered, and need not be a list.
+usage: (nconc &rest LISTS)  */)
+     (nargs, args)
      int nargs;
      Lisp_Object *args;
 {
   register int argnum;
   register Lisp_Object tail, tem, val;
 
-  val = Qnil;
+  val = tail = Qnil;
 
   for (argnum = 0; argnum < nargs; argnum++)
     {
@@ -2595,7 +3048,7 @@ Only the last argument is not altered, and need not be a list.")
       while (CONSP (tem))
        {
          tail = tem;
-         tem = Fcdr (tail);
+         tem = XCDR (tail);
          QUIT;
        }
 
@@ -2654,8 +3107,8 @@ mapcar1 (leni, vals, fn, seq)
       for (i = 0; i < leni; i++)
        {
          int byte;
-         byte = XBOOL_VECTOR (seq)->data[i / BITS_PER_CHAR];
-         if (byte & (1 << (i % BITS_PER_CHAR)))
+         byte = XBOOL_VECTOR (seq)->data[i / BOOL_VECTOR_BITS_PER_CHAR];
+         if (byte & (1 << (i % BOOL_VECTOR_BITS_PER_CHAR)))
            dummy = Qt;
          else
            dummy = Qnil;
@@ -2684,9 +3137,9 @@ mapcar1 (leni, vals, fn, seq)
   else   /* Must be a list, since Flength did not get an error */
     {
       tail = seq;
-      for (i = 0; i < leni; i++)
+      for (i = 0; i < leni && CONSP (tail); i++)
        {
-         dummy = call1 (fn, Fcar (tail));
+         dummy = call1 (fn, XCAR (tail));
          if (vals)
            vals[i] = dummy;
          tail = XCDR (tail);
@@ -2697,11 +3150,11 @@ mapcar1 (leni, vals, fn, seq)
 }
 
 DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
-  "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
-In between each pair of results, stick in SEPARATOR.  Thus, \" \" as\n\
-SEPARATOR results in spaces between the values returned by FUNCTION.\n\
-SEQUENCE may be a list, a vector, a bool-vector, or a string.")
-  (function, sequence, separator)
+       doc: /* Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.
+In between each pair of results, stick in SEPARATOR.  Thus, " " as
+SEPARATOR results in spaces between the values returned by FUNCTION.
+SEQUENCE may be a list, a vector, a bool-vector, or a string.  */)
+     (function, sequence, separator)
      Lisp_Object function, sequence, separator;
 {
   Lisp_Object len;
@@ -2710,52 +3163,63 @@ SEQUENCE may be a list, a vector, a bool-vector, or a string.")
   register Lisp_Object *args;
   register int i;
   struct gcpro gcpro1;
+  Lisp_Object ret;
+  USE_SAFE_ALLOCA;
 
   len = Flength (sequence);
   leni = XINT (len);
   nargs = leni + leni - 1;
   if (nargs < 0) return build_string ("");
 
-  args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
+  SAFE_ALLOCA_LISP (args, nargs);
 
   GCPRO1 (separator);
   mapcar1 (leni, args, function, sequence);
   UNGCPRO;
 
-  for (i = leni - 1; i >= 0; i--)
+  for (i = leni - 1; i > 0; i--)
     args[i + i] = args[i];
 
   for (i = 1; i < nargs; i += 2)
     args[i] = separator;
 
-  return Fconcat (nargs, args);
+  ret = Fconcat (nargs, args);
+  SAFE_FREE ();
+
+  return ret;
 }
 
 DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
-  "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
-The result is a list just as long as SEQUENCE.\n\
-SEQUENCE may be a list, a vector, a bool-vector, or a string.")
-  (function, sequence)
+       doc: /* Apply FUNCTION to each element of SEQUENCE, and make a list of the results.
+The result is a list just as long as SEQUENCE.
+SEQUENCE may be a list, a vector, a bool-vector, or a string.  */)
+     (function, sequence)
      Lisp_Object function, sequence;
 {
   register Lisp_Object len;
   register int leni;
   register Lisp_Object *args;
+  Lisp_Object ret;
+  USE_SAFE_ALLOCA;
 
   len = Flength (sequence);
   leni = XFASTINT (len);
-  args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
+
+  SAFE_ALLOCA_LISP (args, leni);
 
   mapcar1 (leni, args, function, sequence);
 
-  return Flist (leni, args);
+  ret = Flist (leni, args);
+  SAFE_FREE ();
+
+  return ret;
 }
 
 DEFUN ("mapc", Fmapc, Smapc, 2, 2, 0,
-  "Apply FUNCTION to each element of SEQUENCE for side effects only.\n\
-Unlike `mapcar', don't accumulate the results.  Return SEQUENCE.\n\
-SEQUENCE may be a list, a vector, a bool-vector, or a string.")
-  (function, sequence)
+       doc: /* Apply FUNCTION to each element of SEQUENCE for side effects only.
+Unlike `mapcar', don't accumulate the results.  Return SEQUENCE.
+SEQUENCE may be a list, a vector, a bool-vector, or a string.  */)
+     (function, sequence)
      Lisp_Object function, sequence;
 {
   register int leni;
@@ -2769,18 +3233,18 @@ SEQUENCE may be a list, a vector, a bool-vector, or a string.")
 /* Anything that calls this function must protect from GC!  */
 
 DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
-  "Ask user a \"y or n\" question.  Return t if answer is \"y\".\n\
-Takes one argument, which is the string to display to ask the question.\n\
-It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
-No confirmation of the answer is requested; a single character is enough.\n\
-Also accepts Space to mean yes, or Delete to mean no.  \(Actually, it uses\n\
-the bindings in `query-replace-map'; see the documentation of that variable\n\
-for more information.  In this case, the useful bindings are `act', `skip',\n\
-`recenter', and `quit'.\)\n\
-\n\
-Under a windowing system a dialog box will be used if `last-nonmenu-event'\n\
-is nil.")
-  (prompt)
+       doc: /* Ask user a "y or n" question.  Return t if answer is "y".
+Takes one argument, which is the string to display to ask the question.
+It should end in a space; `y-or-n-p' adds `(y or n) ' to it.
+No confirmation of the answer is requested; a single character is enough.
+Also accepts Space to mean yes, or Delete to mean no.  \(Actually, it uses
+the bindings in `query-replace-map'; see the documentation of that variable
+for more information.  In this case, the useful bindings are `act', `skip',
+`recenter', and `quit'.\)
+
+Under a windowing system a dialog box will be used if `last-nonmenu-event'
+is nil and `use-dialog-box' is non-nil.  */)
+     (prompt)
      Lisp_Object prompt;
 {
   register Lisp_Object obj, key, def, map;
@@ -2788,19 +3252,19 @@ is nil.")
   Lisp_Object xprompt;
   Lisp_Object args[2];
   struct gcpro gcpro1, gcpro2;
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
 
   specbind (Qcursor_in_echo_area, Qt);
 
   map = Fsymbol_value (intern ("query-replace-map"));
 
-  CHECK_STRING (prompt, 0);
+  CHECK_STRING (prompt);
   xprompt = prompt;
   GCPRO2 (prompt, xprompt);
 
 #ifdef HAVE_X_WINDOWS
-  if (display_busy_cursor_p)
-    cancel_busy_cursor ();
+  if (display_hourglass_p)
+    cancel_hourglass ();
 #endif
 
   while (1)
@@ -2812,19 +3276,30 @@ is nil.")
          && have_menus_p ())
        {
          Lisp_Object pane, menu;
-         redisplay_preserve_echo_area ();
+         redisplay_preserve_echo_area (3);
          pane = Fcons (Fcons (build_string ("Yes"), Qt),
                        Fcons (Fcons (build_string ("No"), Qnil),
                               Qnil));
          menu = Fcons (prompt, pane);
-         obj = Fx_popup_dialog (Qt, menu);
+         obj = Fx_popup_dialog (Qt, menu, Qnil);
          answer = !NILP (obj);
          break;
        }
 #endif /* HAVE_MENUS */
       cursor_in_echo_area = 1;
       choose_minibuf_frame ();
-      message_with_string ("%s(y or n) ", xprompt, 0);
+
+      {
+       Lisp_Object pargs[3];
+
+       /* Colorize prompt according to `minibuffer-prompt' face.  */
+       pargs[0] = build_string ("%s(y or n) ");
+       pargs[1] = intern ("face");
+       pargs[2] = intern ("minibuffer-prompt");
+       args[0] = Fpropertize (3, pargs);
+       args[1] = xprompt;
+       Fmessage (2, args);
+      }
 
       if (minibuffer_auto_raise)
        {
@@ -2909,22 +3384,22 @@ do_yes_or_no_p (prompt)
 /* Anything that calls this function must protect from GC!  */
 
 DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
-  "Ask user a yes-or-no question.  Return t if answer is yes.\n\
-Takes one argument, which is the string to display to ask the question.\n\
-It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
-The user must confirm the answer with RET,\n\
-and can edit it until it has been confirmed.\n\
-\n\
-Under a windowing system a dialog box will be used if `last-nonmenu-event'\n\
-is nil.")
-  (prompt)
+       doc: /* Ask user a yes-or-no question.  Return t if answer is yes.
+Takes one argument, which is the string to display to ask the question.
+It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.
+The user must confirm the answer with RET,
+and can edit it until it has been confirmed.
+
+Under a windowing system a dialog box will be used if `last-nonmenu-event'
+is nil, and `use-dialog-box' is non-nil.  */)
+     (prompt)
      Lisp_Object prompt;
 {
   register Lisp_Object ans;
   Lisp_Object args[2];
   struct gcpro gcpro1;
 
-  CHECK_STRING (prompt, 0);
+  CHECK_STRING (prompt);
 
 #ifdef HAVE_MENUS
   if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
@@ -2932,13 +3407,13 @@ is nil.")
       && have_menus_p ())
     {
       Lisp_Object pane, menu, obj;
-      redisplay_preserve_echo_area ();
+      redisplay_preserve_echo_area (4);
       pane = Fcons (Fcons (build_string ("Yes"), Qt),
                    Fcons (Fcons (build_string ("No"), Qnil),
                           Qnil));
       GCPRO1 (pane);
       menu = Fcons (prompt, pane);
-      obj = Fx_popup_dialog (Qt, menu);
+      obj = Fx_popup_dialog (Qt, menu, Qnil);
       UNGCPRO;
       return obj;
     }
@@ -2954,13 +3429,13 @@ is nil.")
     {
       ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
                                              Qyes_or_no_p_history, Qnil,
-                                             Qnil));
-      if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
+                                             Qnil, Qnil));
+      if (SCHARS (ans) == 3 && !strcmp (SDATA (ans), "yes"))
        {
          UNGCPRO;
          return Qt;
        }
-      if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
+      if (SCHARS (ans) == 2 && !strcmp (SDATA (ans), "no"))
        {
          UNGCPRO;
          return Qnil;
@@ -2974,14 +3449,22 @@ is nil.")
 }
 \f
 DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
-  "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
-Each of the three load averages is multiplied by 100,\n\
-then converted to integer.\n\
-When USE-FLOATS is non-nil, floats will be used instead of integers.\n\
-These floats are not multiplied by 100.\n\n\
-If the 5-minute or 15-minute load averages are not available, return a\n\
-shortened list, containing only those averages which are available.")
-  (use_floats)
+       doc: /* Return list of 1 minute, 5 minute and 15 minute load averages.
+
+Each of the three load averages is multiplied by 100, then converted
+to integer.
+
+When USE-FLOATS is non-nil, floats will be used instead of integers.
+These floats are not multiplied by 100.
+
+If the 5-minute or 15-minute load averages are not available, return a
+shortened list, containing only those averages which are available.
+
+An error is thrown if the load average can't be obtained.  In some
+cases making it work would require Emacs being installed setuid or
+setgid so that it can read kernel information, and that usually isn't
+advisable.  */)
+     (use_floats)
      Lisp_Object use_floats;
 {
   double load_ave[3];
@@ -3002,78 +3485,159 @@ shortened list, containing only those averages which are available.")
   return ret;
 }
 \f
-Lisp_Object Vfeatures;
+Lisp_Object Vfeatures, Qsubfeatures;
+extern Lisp_Object Vafter_load_alist;
+
+DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 2, 0,
+       doc: /* Returns t if FEATURE is present in this Emacs.
 
-DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
-  "Returns t if FEATURE is present in this Emacs.\n\
-Use this to conditionalize execution of lisp code based on the presence or\n\
-absence of emacs or environment extensions.\n\
-Use `provide' to declare that a feature is available.\n\
-This function looks at the value of the variable `features'.")
-  (feature)
-     Lisp_Object feature;
+Use this to conditionalize execution of lisp code based on the
+presence or absence of emacs or environment extensions.
+Use `provide' to declare that a feature is available.  This function
+looks at the value of the variable `features'.  The optional argument
+SUBFEATURE can be used to check a specific subfeature of FEATURE.  */)
+     (feature, subfeature)
+     Lisp_Object feature, subfeature;
 {
   register Lisp_Object tem;
-  CHECK_SYMBOL (feature, 0);
+  CHECK_SYMBOL (feature);
   tem = Fmemq (feature, Vfeatures);
+  if (!NILP (tem) && !NILP (subfeature))
+    tem = Fmember (subfeature, Fget (feature, Qsubfeatures));
   return (NILP (tem)) ? Qnil : Qt;
 }
 
-DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
-  "Announce that FEATURE is a feature of the current Emacs.")
-  (feature)
-     Lisp_Object feature;
+DEFUN ("provide", Fprovide, Sprovide, 1, 2, 0,
+       doc: /* Announce that FEATURE is a feature of the current Emacs.
+The optional argument SUBFEATURES should be a list of symbols listing
+particular subfeatures supported in this version of FEATURE.  */)
+     (feature, subfeatures)
+     Lisp_Object feature, subfeatures;
 {
   register Lisp_Object tem;
-  CHECK_SYMBOL (feature, 0);
+  CHECK_SYMBOL (feature);
+  CHECK_LIST (subfeatures);
   if (!NILP (Vautoload_queue))
-    Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
+    Vautoload_queue = Fcons (Fcons (make_number (0), Vfeatures),
+                            Vautoload_queue);
   tem = Fmemq (feature, Vfeatures);
   if (NILP (tem))
     Vfeatures = Fcons (feature, Vfeatures);
+  if (!NILP (subfeatures))
+    Fput (feature, Qsubfeatures, subfeatures);
   LOADHIST_ATTACH (Fcons (Qprovide, feature));
+
+  /* Run any load-hooks for this file.  */
+  tem = Fassq (feature, Vafter_load_alist);
+  if (CONSP (tem))
+    Fprogn (XCDR (tem));
+
   return feature;
 }
+\f
+/* `require' and its subroutines.  */
+
+/* List of features currently being require'd, innermost first.  */
+
+Lisp_Object require_nesting_list;
+
+Lisp_Object
+require_unwind (old_value)
+     Lisp_Object old_value;
+{
+  return require_nesting_list = old_value;
+}
 
 DEFUN ("require", Frequire, Srequire, 1, 3, 0,
-  "If feature FEATURE is not loaded, load it from FILENAME.\n\
-If FEATURE is not a member of the list `features', then the feature\n\
-is not loaded; so load the file FILENAME.\n\
-If FILENAME is omitted, the printname of FEATURE is used as the file name,\n\
-but in this case `load' insists on adding the suffix `.el' or `.elc'.\n\
-If the optional third argument NOERROR is non-nil,\n\
-then return nil if the file is not found.\n\
-Normally the return value is FEATURE.")
-  (feature, file_name, noerror)
-     Lisp_Object feature, file_name, noerror;
+       doc: /* If feature FEATURE is not loaded, load it from FILENAME.
+If FEATURE is not a member of the list `features', then the feature
+is not loaded; so load the file FILENAME.
+If FILENAME is omitted, the printname of FEATURE is used as the file name,
+and `load' will try to load this name appended with the suffix `.elc' or
+`.el', in that order.  The name without appended suffix will not be used.
+If the optional third argument NOERROR is non-nil,
+then return nil if the file is not found instead of signaling an error.
+Normally the return value is FEATURE.
+The normal messages at start and end of loading FILENAME are suppressed.  */)
+     (feature, filename, noerror)
+     Lisp_Object feature, filename, noerror;
 {
   register Lisp_Object tem;
-  CHECK_SYMBOL (feature, 0);
+  struct gcpro gcpro1, gcpro2;
+  int from_file = load_in_progress;
+
+  CHECK_SYMBOL (feature);
+
+  /* Record the presence of `require' in this file
+     even if the feature specified is already loaded.
+     But not more than once in any file,
+     and not when we aren't loading or reading from a file.  */
+  if (!from_file)
+    for (tem = Vcurrent_load_list; CONSP (tem); tem = XCDR (tem))
+      if (NILP (XCDR (tem)) && STRINGP (XCAR (tem)))
+       from_file = 1;
+
+  if (from_file)
+    {
+      tem = Fcons (Qrequire, feature);
+      if (NILP (Fmember (tem, Vcurrent_load_list)))
+       LOADHIST_ATTACH (tem);
+    }
   tem = Fmemq (feature, Vfeatures);
-  LOADHIST_ATTACH (Fcons (Qrequire, feature));
+
   if (NILP (tem))
     {
-      int count = specpdl_ptr - specpdl;
+      int count = SPECPDL_INDEX ();
+      int nesting = 0;
+
+      /* This is to make sure that loadup.el gives a clear picture
+        of what files are preloaded and when.  */
+      if (! NILP (Vpurify_flag))
+       error ("(require %s) while preparing to dump",
+              SDATA (SYMBOL_NAME (feature)));
+
+      /* A certain amount of recursive `require' is legitimate,
+        but if we require the same feature recursively 3 times,
+        signal an error.  */
+      tem = require_nesting_list;
+      while (! NILP (tem))
+       {
+         if (! NILP (Fequal (feature, XCAR (tem))))
+           nesting++;
+         tem = XCDR (tem);
+       }
+      if (nesting > 3)
+       error ("Recursive `require' for feature `%s'",
+              SDATA (SYMBOL_NAME (feature)));
+
+      /* Update the list for any nested `require's that occur.  */
+      record_unwind_protect (require_unwind, require_nesting_list);
+      require_nesting_list = Fcons (feature, require_nesting_list);
 
       /* Value saved here is to be restored into Vautoload_queue */
       record_unwind_protect (un_autoload, Vautoload_queue);
       Vautoload_queue = Qt;
 
-      tem = Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
-                    noerror, Qt, Qnil, (NILP (file_name) ? Qt : Qnil));
+      /* Load the file.  */
+      GCPRO2 (feature, filename);
+      tem = Fload (NILP (filename) ? Fsymbol_name (feature) : filename,
+                  noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil));
+      UNGCPRO;
+
       /* If load failed entirely, return nil.  */
       if (NILP (tem))
        return unbind_to (count, Qnil);
 
       tem = Fmemq (feature, Vfeatures);
       if (NILP (tem))
-       error ("Required feature %s was not provided",
-              XSYMBOL (feature)->name->data);
+       error ("Required feature `%s' was not provided",
+              SDATA (SYMBOL_NAME (feature)));
 
       /* Once loading finishes, don't undo it.  */
       Vautoload_queue = Qt;
       feature = unbind_to (count, feature);
     }
+
   return feature;
 }
 \f
@@ -3085,13 +3649,13 @@ Normally the return value is FEATURE.")
    for the sole reason of efficiency.  */
 
 DEFUN ("plist-member", Fplist_member, Splist_member, 2, 2, 0,
-  "Return non-nil if PLIST has the property PROP.\n\
-PLIST is a property list, which is a list of the form\n\
-\(PROP1 VALUE1 PROP2 VALUE2 ...\).  PROP is a symbol.\n\
-Unlike `plist-get', this allows you to distinguish between a missing\n\
-property and a property with the value nil.\n\
-The value is actually the tail of PLIST whose car is PROP.")
-  (plist, prop)
+       doc: /* Return non-nil if PLIST has the property PROP.
+PLIST is a property list, which is a list of the form
+\(PROP1 VALUE1 PROP2 VALUE2 ...\).  PROP is a symbol.
+Unlike `plist-get', this allows you to distinguish between a missing
+property and a property with the value nil.
+The value is actually the tail of PLIST whose car is PROP.  */)
+     (plist, prop)
      Lisp_Object plist, prop;
 {
   while (CONSP (plist) && !EQ (XCAR (plist), prop))
@@ -3104,21 +3668,21 @@ The value is actually the tail of PLIST whose car is PROP.")
 }
 
 DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
-  "In WIDGET, set PROPERTY to VALUE.\n\
-The value can later be retrieved with `widget-get'.")
-  (widget, property, value)
+       doc: /* In WIDGET, set PROPERTY to VALUE.
+The value can later be retrieved with `widget-get'.  */)
+     (widget, property, value)
      Lisp_Object widget, property, value;
 {
-  CHECK_CONS (widget, 1);
-  XCDR (widget) = Fplist_put (XCDR (widget), property, value);
+  CHECK_CONS (widget);
+  XSETCDR (widget, Fplist_put (XCDR (widget), property, value));
   return value;
 }
 
 DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
-  "In WIDGET, get the value of PROPERTY.\n\
-The value could either be specified when the widget was created, or\n\
-later with `widget-put'.")
-  (widget, property)
+       doc: /* In WIDGET, get the value of PROPERTY.
+The value could either be specified when the widget was created, or
+later with `widget-put'.  */)
+     (widget, property)
      Lisp_Object widget, property;
 {
   Lisp_Object tmp;
@@ -3127,7 +3691,7 @@ later with `widget-put'.")
     {
       if (NILP (widget))
        return Qnil;
-      CHECK_CONS (widget, 1);
+      CHECK_CONS (widget);
       tmp = Fplist_member (XCDR (widget), property);
       if (CONSP (tmp))
        {
@@ -3142,9 +3706,10 @@ later with `widget-put'.")
 }
 
 DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
-  "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
-ARGS are passed as extra arguments to the function.")
-  (nargs, args)
+       doc: /* Apply the value of WIDGET's PROPERTY to the widget itself.
+ARGS are passed as extra arguments to the function.
+usage: (widget-apply WIDGET PROPERTY &rest ARGS)  */)
+     (nargs, args)
      int nargs;
      Lisp_Object *args;
 {
@@ -3161,8 +3726,94 @@ ARGS are passed as extra arguments to the function.")
   UNGCPRO;
   return result;
 }
+
+#ifdef HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#endif
+
+DEFUN ("locale-info", Flocale_info, Slocale_info, 1, 1, 0,
+       doc: /* Access locale data ITEM for the current C locale, if available.
+ITEM should be one of the following:
+
+`codeset', returning the character set as a string (locale item CODESET);
+
+`days', returning a 7-element vector of day names (locale items DAY_n);
+
+`months', returning a 12-element vector of month names (locale items MON_n);
+
+`paper', returning a list (WIDTH HEIGHT) for the default paper size,
+  both measured in milimeters (locale items PAPER_WIDTH, PAPER_HEIGHT).
+
+If the system can't provide such information through a call to
+`nl_langinfo', or if ITEM isn't from the list above, return nil.
+
+See also Info node `(libc)Locales'.
+
+The data read from the system are decoded using `locale-coding-system'.  */)
+     (item)
+     Lisp_Object item;
+{
+  char *str = NULL;
+#ifdef HAVE_LANGINFO_CODESET
+  Lisp_Object val;
+  if (EQ (item, Qcodeset))
+    {
+      str = nl_langinfo (CODESET);
+      return build_string (str);
+    }
+#ifdef DAY_1
+  else if (EQ (item, Qdays))   /* e.g. for calendar-day-name-array */
+    {
+      Lisp_Object v = Fmake_vector (make_number (7), Qnil);
+      int days[7] = {DAY_1, DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7};
+      int i;
+      synchronize_system_time_locale ();
+      for (i = 0; i < 7; i++)
+       {
+         str = nl_langinfo (days[i]);
+         val = make_unibyte_string (str, strlen (str));
+         /* Fixme: Is this coding system necessarily right, even if
+            it is consistent with CODESET?  If not, what to do?  */
+         Faset (v, make_number (i),
+                code_convert_string_norecord (val, Vlocale_coding_system,
+                                              0));
+       }
+      return v;
+    }
+#endif /* DAY_1 */
+#ifdef MON_1
+  else if (EQ (item, Qmonths)) /* e.g. for calendar-month-name-array */
+    {
+      struct Lisp_Vector *p = allocate_vector (12);
+      int months[12] = {MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7,
+                       MON_8, MON_9, MON_10, MON_11, MON_12};
+      int i;
+      synchronize_system_time_locale ();
+      for (i = 0; i < 12; i++)
+       {
+         str = nl_langinfo (months[i]);
+         val = make_unibyte_string (str, strlen (str));
+         p->contents[i] =
+           code_convert_string_norecord (val, Vlocale_coding_system, 0);
+       }
+      XSETVECTOR (val, p);
+      return val;
+    }
+#endif /* MON_1 */
+/* LC_PAPER stuff isn't defined as accessible in glibc as of 2.3.1,
+   but is in the locale files.  This could be used by ps-print.  */
+#ifdef PAPER_WIDTH
+  else if (EQ (item, Qpaper))
+    {
+      return list2 (make_number (nl_langinfo (PAPER_WIDTH)),
+                   make_number (nl_langinfo (PAPER_HEIGHT)));
+    }
+#endif /* PAPER_WIDTH */
+#endif /* HAVE_LANGINFO_CODESET*/
+  return Qnil;
+}
 \f
-/* base64 encode/decode functions.
+/* base64 encode/decode functions (RFC 2045).
    Based on code from GNU recode. */
 
 #define MIME_LINE_LENGTH 76
@@ -3178,19 +3829,19 @@ ARGS are passed as extra arguments to the function.")
 /* Used by base64_decode_1 to retrieve a non-base64-ignorable
    character or return retval if there are no characters left to
    process. */
-#define READ_QUADRUPLET_BYTE(retval) \
-  do \
-    { \
-      if (i == length) \
-        return (retval); \
-      c = from[i++]; \
-    } \
+#define READ_QUADRUPLET_BYTE(retval)   \
+  do                                   \
+    {                                  \
+      if (i == length)                 \
+       {                               \
+         if (nchars_return)            \
+           *nchars_return = nchars;    \
+         return (retval);              \
+       }                               \
+      c = from[i++];                   \
+    }                                  \
   while (IS_BASE64_IGNORABLE (c))
 
-/* Don't use alloca for regions larger than this, lest we overflow
-   their stack.  */
-#define MAX_ALLOCA 16*1024
-
 /* Table of characters coding the 64 values.  */
 static char base64_value_to_char[64] =
 {
@@ -3241,14 +3892,14 @@ static short base64_char_to_value[128] =
 
 
 static int base64_encode_1 P_ ((const char *, char *, int, int, int));
-static int base64_decode_1 P_ ((const char *, char *, int));
+static int base64_decode_1 P_ ((const char *, char *, int, int, int *));
 
 DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region,
        2, 3, "r",
-       "Base64-encode the region between BEG and END.\n\
-Return the length of the encoded text.\n\
-Optional third argument NO-LINE-BREAK means do not break long lines\n\
-into shorter lines.")
+       doc: /* 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)
      Lisp_Object beg, end, no_line_break;
 {
@@ -3256,6 +3907,7 @@ into shorter lines.")
   int allength, length;
   int ibeg, iend, encoded_length;
   int old_pos = PT;
+  USE_SAFE_ALLOCA;
 
   validate_region (&beg, &end);
 
@@ -3270,10 +3922,7 @@ into shorter lines.")
   allength = length + length/3 + 1;
   allength += allength / MIME_LINE_LENGTH + 1 + 6;
 
-  if (allength <= MAX_ALLOCA)
-    encoded = (char *) alloca (allength);
-  else
-    encoded = (char *) xmalloc (allength);
+  SAFE_ALLOCA (encoded, char *, allength);
   encoded_length = base64_encode_1 (BYTE_POS_ADDR (ibeg), encoded, length,
                                    NILP (no_line_break),
                                    !NILP (current_buffer->enable_multibyte_characters));
@@ -3283,17 +3932,15 @@ into shorter lines.")
   if (encoded_length < 0)
     {
       /* The encoding wasn't possible. */
-      if (length > MAX_ALLOCA)
-       xfree (encoded);
-      error ("Base64 encoding failed");
+      SAFE_FREE ();
+      error ("Multibyte character in data for base64 encoding");
     }
 
   /* Now we have encoded the region, so we insert the new contents
      and delete the old.  (Insert first in order to preserve markers.)  */
   SET_PT_BOTH (XFASTINT (beg), ibeg);
   insert (encoded, encoded_length);
-  if (allength > MAX_ALLOCA)
-    xfree (encoded);
+  SAFE_FREE ();
   del_range_byte (ibeg + encoded_length, iend + encoded_length, 1);
 
   /* If point was outside of the region, restore it exactly; else just
@@ -3310,32 +3957,30 @@ into shorter lines.")
 
 DEFUN ("base64-encode-string", Fbase64_encode_string, Sbase64_encode_string,
        1, 2, 0,
-       "Base64-encode STRING and return the result.\n\
-Optional second argument NO-LINE-BREAK means do not break long lines\n\
-into shorter lines.")
+       doc: /* Base64-encode STRING and return the result.
+Optional second argument NO-LINE-BREAK means do not break long lines
+into shorter lines.  */)
      (string, no_line_break)
      Lisp_Object string, no_line_break;
 {
   int allength, length, encoded_length;
   char *encoded;
   Lisp_Object encoded_string;
+  USE_SAFE_ALLOCA;
 
-  CHECK_STRING (string, 1);
+  CHECK_STRING (string);
 
   /* 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 = STRING_BYTES (XSTRING (string));
+  length = SBYTES (string);
   allength = length + length/3 + 1;
   allength += allength / MIME_LINE_LENGTH + 1 + 6;
 
   /* We need to allocate enough room for decoding the text. */
-  if (allength <= MAX_ALLOCA)
-    encoded = (char *) alloca (allength);
-  else
-    encoded = (char *) xmalloc (allength);
+  SAFE_ALLOCA (encoded, char *, allength);
 
-  encoded_length = base64_encode_1 (XSTRING (string)->data,
+  encoded_length = base64_encode_1 (SDATA (string),
                                    encoded, length, NILP (no_line_break),
                                    STRING_MULTIBYTE (string));
   if (encoded_length > allength)
@@ -3344,14 +3989,12 @@ into shorter lines.")
   if (encoded_length < 0)
     {
       /* The encoding wasn't possible. */
-      if (length > MAX_ALLOCA)
-       xfree (encoded);
-      error ("Base64 encoding failed");
+      SAFE_FREE ();
+      error ("Multibyte character in data for base64 encoding");
     }
 
   encoded_string = make_unibyte_string (encoded, encoded_length);
-  if (allength > MAX_ALLOCA)
-    xfree (encoded);
+  SAFE_FREE ();
 
   return encoded_string;
 }
@@ -3366,7 +4009,7 @@ base64_encode_1 (from, to, length, line_break, multibyte)
 {
   int counter = 0, i = 0;
   char *e = to;
-  unsigned char c;
+  int c;
   unsigned int value;
   int bytes;
 
@@ -3375,7 +4018,7 @@ base64_encode_1 (from, to, length, line_break, multibyte)
       if (multibyte)
        {
          c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
-         if (!SINGLE_BYTE_CHAR_P (c))
+         if (c >= 256)
            return -1;
          i += bytes;
        }
@@ -3413,6 +4056,8 @@ base64_encode_1 (from, to, length, line_break, multibyte)
       if (multibyte)
        {
          c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
+         if (c >= 256)
+           return -1;
          i += bytes;
        }
       else
@@ -3433,6 +4078,8 @@ base64_encode_1 (from, to, length, line_break, multibyte)
       if (multibyte)
        {
          c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
+         if (c >= 256)
+           return -1;
          i += bytes;
        }
       else
@@ -3447,18 +4094,20 @@ base64_encode_1 (from, to, length, line_break, multibyte)
 
 
 DEFUN ("base64-decode-region", Fbase64_decode_region, Sbase64_decode_region,
-  2, 2, "r",
-  "Base64-decode the region between BEG and END.\n\
-Return the length of the decoded text.\n\
-If the region can't be decoded, signal an error and don't modify the buffer.")
+       2, 2, "r",
+       doc: /* Base64-decode the region between BEG and END.
+Return the length of the decoded text.
+If the region can't be decoded, signal an error and don't modify the buffer.  */)
      (beg, end)
      Lisp_Object beg, end;
 {
-  int ibeg, iend, length;
+  int ibeg, iend, length, allength;
   char *decoded;
   int old_pos = PT;
   int decoded_length;
   int inserted_chars;
+  int multibyte = !NILP (current_buffer->enable_multibyte_characters);
+  USE_SAFE_ALLOCA;
 
   validate_region (&beg, &end);
 
@@ -3466,35 +4115,32 @@ If the region can't be decoded, signal an error and don't modify the buffer.")
   iend = CHAR_TO_BYTE (XFASTINT (end));
 
   length = iend - ibeg;
-  /* We need to allocate enough room for decoding the text. */
-  if (length <= MAX_ALLOCA)
-    decoded = (char *) alloca (length);
-  else
-    decoded = (char *) xmalloc (length);
+
+  /* We need to allocate enough room for decoding the text.  If we are
+     working on a multibyte buffer, each decoded code may occupy at
+     most two bytes.  */
+  allength = multibyte ? length * 2 : length;
+  SAFE_ALLOCA (decoded, char *, allength);
 
   move_gap_both (XFASTINT (beg), ibeg);
-  decoded_length = base64_decode_1 (BYTE_POS_ADDR (ibeg), decoded, length);
-  if (decoded_length > length)
+  decoded_length = base64_decode_1 (BYTE_POS_ADDR (ibeg), decoded, length,
+                                   multibyte, &inserted_chars);
+  if (decoded_length > allength)
     abort ();
 
   if (decoded_length < 0)
     {
       /* The decoding wasn't possible. */
-      if (length > MAX_ALLOCA)
-       xfree (decoded);
-      error ("Base64 decoding failed");
+      SAFE_FREE ();
+      error ("Invalid base64 data");
     }
 
-  inserted_chars = decoded_length;
-  if (!NILP (current_buffer->enable_multibyte_characters))
-    decoded_length = str_to_multibyte (decoded, length, decoded_length);
-
   /* Now we have decoded the region, so we insert the new contents
      and delete the old.  (Insert first in order to preserve markers.)  */
   TEMP_SET_PT_BOTH (XFASTINT (beg), ibeg);
   insert_1_both (decoded, inserted_chars, decoded_length, 0, 1, 0);
-  if (length > MAX_ALLOCA)
-    xfree (decoded);
+  SAFE_FREE ();
+
   /* Delete the original text.  */
   del_range_both (PT, PT_BYTE, XFASTINT (end) + inserted_chars,
                  iend + decoded_length, 1);
@@ -3512,24 +4158,24 @@ If the region can't be decoded, signal an error and don't modify the buffer.")
 
 DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string,
        1, 1, 0,
-  "Base64-decode STRING and return the result.")
-  (string)
+       doc: /* Base64-decode STRING and return the result.  */)
+     (string)
      Lisp_Object string;
 {
   char *decoded;
   int length, decoded_length;
   Lisp_Object decoded_string;
+  USE_SAFE_ALLOCA;
 
-  CHECK_STRING (string, 1);
+  CHECK_STRING (string);
 
-  length = STRING_BYTES (XSTRING (string));
+  length = SBYTES (string);
   /* We need to allocate enough room for decoding the text. */
-  if (length <= MAX_ALLOCA)
-    decoded = (char *) alloca (length);
-  else
-    decoded = (char *) xmalloc (length);
+  SAFE_ALLOCA (decoded, char *, length);
 
-  decoded_length = base64_decode_1 (XSTRING (string)->data, decoded, length);
+  /* The decoded result should be unibyte. */
+  decoded_length = base64_decode_1 (SDATA (string), decoded, length,
+                                   0, NULL);
   if (decoded_length > length)
     abort ();
   else if (decoded_length >= 0)
@@ -3537,24 +4183,31 @@ DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string,
   else
     decoded_string = Qnil;
 
-  if (length > MAX_ALLOCA)
-    xfree (decoded);
+  SAFE_FREE ();
   if (!STRINGP (decoded_string))
-    error ("Base64 decoding failed");
+    error ("Invalid base64 data");
 
   return decoded_string;
 }
 
+/* Base64-decode the data at FROM of LENGHT bytes into TO.  If
+   MULTIBYTE is nonzero, the decoded result should be in multibyte
+   form.  If NCHARS_RETRUN is not NULL, store the number of produced
+   characters in *NCHARS_RETURN.  */
+
 static int
-base64_decode_1 (from, to, length)
+base64_decode_1 (from, to, length, multibyte, nchars_return)
      const char *from;
      char *to;
      int length;
+     int multibyte;
+     int *nchars_return;
 {
   int i = 0;
   char *e = to;
   unsigned char c;
   unsigned long value;
+  int nchars = 0;
 
   while (1)
     {
@@ -3574,7 +4227,12 @@ base64_decode_1 (from, to, length)
        return -1;
       value |= base64_char_to_value[c] << 12;
 
-      *e++ = (unsigned char) (value >> 16);
+      c = (unsigned char) (value >> 16);
+      if (multibyte)
+       e += CHAR_STRING (c, e);
+      else
+       *e++ = c;
+      nchars++;
 
       /* Process third byte of a quadruplet.  */
 
@@ -3593,7 +4251,12 @@ base64_decode_1 (from, to, length)
        return -1;
       value |= base64_char_to_value[c] << 6;
 
-      *e++ = (unsigned char) (0xff & value >> 8);
+      c = (unsigned char) (0xff & value >> 8);
+      if (multibyte)
+       e += CHAR_STRING (c, e);
+      else
+       *e++ = c;
+      nchars++;
 
       /* Process fourth byte of a quadruplet.  */
 
@@ -3606,7 +4269,12 @@ base64_decode_1 (from, to, length)
        return -1;
       value |= base64_char_to_value[c];
 
-      *e++ = (unsigned char) (0xff & value);
+      c = (unsigned char) (0xff & value);
+      if (multibyte)
+       e += CHAR_STRING (c, e);
+      else
+       *e++ = c;
+      nchars++;
     }
 }
 
@@ -3633,32 +4301,6 @@ base64_decode_1 (from, to, length)
    if a `:linear-search t' argument is given to make-hash-table.  */
 
 
-/* Value is the key part of entry IDX in hash table H.  */
-
-#define HASH_KEY(H, IDX)   AREF ((H)->key_and_value, 2 * (IDX))
-
-/* Value is the value part of entry IDX in hash table H.  */
-
-#define HASH_VALUE(H, IDX) AREF ((H)->key_and_value, 2 * (IDX) + 1)
-
-/* Value is the index of the next entry following the one at IDX
-   in hash table H.  */
-
-#define HASH_NEXT(H, IDX)  AREF ((H)->next, (IDX))
-
-/* Value is the hash code computed for entry IDX in hash table H.  */
-
-#define HASH_HASH(H, IDX)  AREF ((H)->hash, (IDX))
-
-/* Value is the index of the element in hash table H that is the
-   start of the collision list at index IDX in the index vector of H.  */
-
-#define HASH_INDEX(H, IDX)  AREF ((H)->index, (IDX))
-
-/* Value is the size of hash table H.  */
-
-#define HASH_TABLE_SIZE(H) XVECTOR ((H)->next)->size
-
 /* The list of all weak hash tables.  Don't staticpro this one.  */
 
 Lisp_Object Vweak_hash_tables;
@@ -3704,7 +4346,7 @@ static struct Lisp_Hash_Table *
 check_hash_table (obj)
      Lisp_Object obj;
 {
-  CHECK_HASH_TABLE (obj, 0);
+  CHECK_HASH_TABLE (obj);
   return XHASH_TABLE (obj);
 }
 
@@ -3774,8 +4416,7 @@ larger_vector (vec, new_size, init)
   old_size = XVECTOR (vec)->size;
   xassert (new_size >= old_size);
 
-  v = allocate_vectorlike (new_size);
-  v->size = new_size;
+  v = allocate_vector (new_size);
   bcopy (XVECTOR (vec)->contents, v->contents,
         old_size * sizeof *v->contents);
   for (i = old_size; i < new_size; ++i)
@@ -3853,7 +4494,7 @@ hashfn_eq (h, key)
      Lisp_Object key;
 {
   unsigned hash = XUINT (key) ^ XGCTYPE (key);
-  xassert ((hash & ~VALMASK) == 0);
+  xassert ((hash & ~INTMASK) == 0);
   return hash;
 }
 
@@ -3872,7 +4513,7 @@ hashfn_eql (h, key)
     hash = sxhash (key, 0);
   else
     hash = XUINT (key) ^ XGCTYPE (key);
-  xassert ((hash & ~VALMASK) == 0);
+  xassert ((hash & ~INTMASK) == 0);
   return hash;
 }
 
@@ -3887,7 +4528,7 @@ hashfn_equal (h, key)
      Lisp_Object key;
 {
   unsigned hash = sxhash (key, 0);
-  xassert ((hash & ~VALMASK) == 0);
+  xassert ((hash & ~INTMASK) == 0);
   return hash;
 }
 
@@ -3944,9 +4585,8 @@ make_hash_table (test, size, rehash_size, rehash_threshold, weak,
      Lisp_Object user_test, user_hash;
 {
   struct Lisp_Hash_Table *h;
-  struct Lisp_Vector *v;
   Lisp_Object table;
-  int index_size, i, len, sz;
+  int index_size, i, sz;
 
   /* Preconditions.  */
   xassert (SYMBOLP (test));
@@ -3960,16 +4600,11 @@ make_hash_table (test, size, rehash_size, rehash_threshold, weak,
   if (XFASTINT (size) == 0)
     size = make_number (1);
 
-  /* Allocate a vector, and initialize it.  */
-  len = VECSIZE (struct Lisp_Hash_Table);
-  v = allocate_vectorlike (len);
-  v->size = len;
-  for (i = 0; i < len; ++i)
-    v->contents[i] = Qnil;
+  /* Allocate a table and initialize it.  */
+  h = allocate_hash_table ();
 
   /* Initialize hash table slots.  */
   sz = XFASTINT (size);
-  h = (struct Lisp_Hash_Table *) v;
 
   h->test = test;
   if (EQ (test, Qeql))
@@ -4037,12 +4672,9 @@ copy_hash_table (h1)
 {
   Lisp_Object table;
   struct Lisp_Hash_Table *h2;
-  struct Lisp_Vector *v, *next;
-  int len;
+  struct Lisp_Vector *next;
 
-  len = VECSIZE (struct Lisp_Hash_Table);
-  v = allocate_vectorlike (len);
-  h2 = (struct Lisp_Hash_Table *) v;
+  h2 = allocate_hash_table ();
   next = h2->vec_next;
   bcopy (h1, h2, sizeof *h2);
   h2->vec_next = next;
@@ -4083,7 +4715,7 @@ maybe_resize_hash_table (h)
       index_size = next_almost_prime ((int)
                                      (new_size
                                       / XFLOATINT (h->rehash_threshold)));
-      if (max (index_size, 2 * new_size) & ~VALMASK)
+      if (max (index_size, 2 * new_size) > MOST_POSITIVE_FIXNUM)
        error ("Hash table too large to resize");
 
       h->key_and_value = larger_vector (h->key_and_value, 2 * new_size, Qnil);
@@ -4173,7 +4805,7 @@ hash_put (h, key, value, hash)
 {
   int start_of_bucket, i;
 
-  xassert ((hash & ~VALMASK) == 0);
+  xassert ((hash & ~INTMASK) == 0);
 
   /* Increment count after resizing because resizing may fail.  */
   maybe_resize_hash_table (h);
@@ -4295,21 +4927,17 @@ sweep_weak_table (h, remove_entries_p)
 
   for (bucket = 0; bucket < n; ++bucket)
     {
-      Lisp_Object idx, prev;
+      Lisp_Object idx, next, prev;
 
       /* Follow collision chain, removing entries that
         don't survive this garbage collection.  */
-      idx = HASH_INDEX (h, bucket);
       prev = Qnil;
-      while (!GC_NILP (idx))
+      for (idx = HASH_INDEX (h, bucket); !GC_NILP (idx); idx = next)
        {
-         int remove_p;
          int i = XFASTINT (idx);
-         Lisp_Object next;
-         int key_known_to_survive_p, value_known_to_survive_p;
-
-         key_known_to_survive_p = survives_gc_p (HASH_KEY (h, i));
-         value_known_to_survive_p = survives_gc_p (HASH_VALUE (h, i));
+         int key_known_to_survive_p = survives_gc_p (HASH_KEY (h, i));
+         int value_known_to_survive_p = survives_gc_p (HASH_VALUE (h, i));
+         int remove_p;
 
          if (EQ (h->weak, Qkey))
            remove_p = !key_known_to_survive_p;
@@ -4330,7 +4958,7 @@ sweep_weak_table (h, remove_entries_p)
                {
                  /* Take out of collision chain.  */
                  if (GC_NILP (prev))
-                   HASH_INDEX (h, i) = next;
+                   HASH_INDEX (h, bucket) = next;
                  else
                    HASH_NEXT (h, XFASTINT (prev)) = next;
 
@@ -4344,6 +4972,10 @@ sweep_weak_table (h, remove_entries_p)
 
                  h->count = make_number (XFASTINT (h->count) - 1);
                }
+             else
+               {
+                 prev = idx;
+               }
            }
          else
            {
@@ -4352,19 +4984,17 @@ sweep_weak_table (h, remove_entries_p)
                  /* Make sure key and value survive.  */
                  if (!key_known_to_survive_p)
                    {
-                     mark_object (&HASH_KEY (h, i));
+                     mark_object (HASH_KEY (h, i));
                      marked = 1;
                    }
 
                  if (!value_known_to_survive_p)
                    {
-                     mark_object (&HASH_VALUE (h, i));
+                     mark_object (HASH_VALUE (h, i));
                      marked = 1;
                    }
                }
            }
-
-         idx = next;
        }
     }
 
@@ -4405,7 +5035,7 @@ sweep_weak_hash_tables ()
     {
       h = XHASH_TABLE (table);
       next = h->next_weak;
-      
+
       if (h->size & ARRAY_MARK_FLAG)
        {
          /* TABLE is marked as used.  Sweep its contents.  */
@@ -4464,7 +5094,7 @@ sxhash_string (ptr, len)
       hash = ((hash << 3) + (hash >> 28) + c);
     }
 
-  return hash & VALMASK;
+  return hash & INTMASK;
 }
 
 
@@ -4488,6 +5118,12 @@ sxhash_list (list, depth)
        hash = SXHASH_COMBINE (hash, hash2);
       }
 
+  if (!NILP (list))
+    {
+      unsigned hash2 = sxhash (list, depth + 1);
+      hash = SXHASH_COMBINE (hash, hash2);
+    }
+
   return hash;
 }
 
@@ -4532,7 +5168,7 @@ sxhash_bool_vector (vec)
 
 
 /* Return a hash code for OBJ.  DEPTH is the current depth in the Lisp
-   structure.  Value is an unsigned integer clipped to VALMASK.  */
+   structure.  Value is an unsigned integer clipped to INTMASK.  */
 
 unsigned
 sxhash (obj, depth)
@@ -4550,17 +5186,16 @@ sxhash (obj, depth)
       hash = XUINT (obj);
       break;
 
-    case Lisp_Symbol:
-      hash = sxhash_string (XSYMBOL (obj)->name->data,
-                           XSYMBOL (obj)->name->size);
-      break;
-
     case Lisp_Misc:
       hash = XUINT (obj);
       break;
 
+    case Lisp_Symbol:
+      obj = SYMBOL_NAME (obj);
+      /* Fall through.  */
+
     case Lisp_String:
-      hash = sxhash_string (XSTRING (obj)->data, XSTRING (obj)->size);
+      hash = sxhash_string (SDATA (obj), SCHARS (obj));
       break;
 
       /* This can be everything from a vector to an overlay.  */
@@ -4596,7 +5231,7 @@ sxhash (obj, depth)
       abort ();
     }
 
-  return hash & VALMASK;
+  return hash & INTMASK;
 }
 
 
@@ -4607,8 +5242,8 @@ sxhash (obj, depth)
 
 
 DEFUN ("sxhash", Fsxhash, Ssxhash, 1, 1, 0,
-  "Compute a hash code for OBJ and return it as integer.")
-  (obj)
+       doc: /* Compute a hash code for OBJ and return it as integer.  */)
+     (obj)
      Lisp_Object obj;
 {
   unsigned hash = sxhash (obj, 0);;
@@ -4617,34 +5252,38 @@ DEFUN ("sxhash", Fsxhash, Ssxhash, 1, 1, 0,
 
 
 DEFUN ("make-hash-table", Fmake_hash_table, Smake_hash_table, 0, MANY, 0,
-  "Create and return a new hash table.\n\
-Arguments are specified as keyword/argument pairs.  The following\n\
-arguments are defined:\n\
-\n\
-:test TEST -- TEST must be a symbol that specifies how to compare keys.\n\
-Default is `eql'.  Predefined are the tests `eq', `eql', and `equal'.\n\
-User-supplied test and hash functions can be specified via\n\
-`define-hash-table-test'.\n\
-\n\
-:size SIZE -- A hint as to how many elements will be put in the table.\n\
-Default is 65.\n\
-\n\
-:rehash-size REHASH-SIZE - Indicates how to expand the table when\n\
-it fills up.  If REHASH-SIZE is an integer, add that many space.\n\
-If it is a float, it must be > 1.0, and the new size is computed by\n\
-multiplying the old size with that factor.  Default is 1.5.\n\
-\n\
-:rehash-threshold THRESHOLD -- THRESHOLD must a float > 0, and <= 1.0.\n\
-Resize the hash table when ratio of the number of entries in the table.\n\
-Default is 0.8.\n\
-\n\
-:weakness WEAK -- WEAK must be one of nil, t, `key', `value',\n\
-`key-or-value', or `key-and-value'.  If WEAK is not nil, the table returned\n\
-is a weak table.  Key/value pairs are removed from a weak hash table when\n\
-there are no non-weak references pointing to their key, value, one of key\n\
-or value, or both key and value, depending on WEAK.  WEAK t is equivalent\n\
-to `key-and-value'.  Default value of WEAK is nil.")
-  (nargs, args)
+       doc: /* Create and return a new hash table.
+
+Arguments are specified as keyword/argument pairs.  The following
+arguments are defined:
+
+:test TEST -- TEST must be a symbol that specifies how to compare
+keys.  Default is `eql'.  Predefined are the tests `eq', `eql', and
+`equal'.  User-supplied test and hash functions can be specified via
+`define-hash-table-test'.
+
+:size SIZE -- A hint as to how many elements will be put in the table.
+Default is 65.
+
+:rehash-size REHASH-SIZE - Indicates how to expand the table when it
+fills up.  If REHASH-SIZE is an integer, add that many space.  If it
+is a float, it must be > 1.0, and the new size is computed by
+multiplying the old size with that factor.  Default is 1.5.
+
+:rehash-threshold THRESHOLD -- THRESHOLD must a float > 0, and <= 1.0.
+Resize the hash table when ratio of the number of entries in the
+table.  Default is 0.8.
+
+:weakness WEAK -- WEAK must be one of nil, t, `key', `value',
+`key-or-value', or `key-and-value'.  If WEAK is not nil, the table
+returned is a weak table.  Key/value pairs are removed from a weak
+hash table when there are no non-weak references pointing to their
+key, value, one of key or value, or both key and value, depending on
+WEAK.  WEAK t is equivalent to `key-and-value'.  Default value of WEAK
+is nil.
+
+usage: (make-hash-table &rest KEYWORD-ARGS)  */)
+     (nargs, args)
      int nargs;
      Lisp_Object *args;
 {
@@ -4667,19 +5306,21 @@ to `key-and-value'.  Default value of WEAK is nil.")
       Lisp_Object prop;
 
       prop = Fget (test, Qhash_table_test);
-      if (!CONSP (prop) || XFASTINT (Flength (prop)) < 2)
+      if (!CONSP (prop) || !CONSP (XCDR (prop)))
        Fsignal (Qerror, list2 (build_string ("Invalid hash table test"),
                                test));
-      user_test = Fnth (make_number (0), prop);
-      user_hash = Fnth (make_number (1), prop);
+      user_test = XCAR (prop);
+      user_hash = XCAR (XCDR (prop));
     }
   else
     user_test = user_hash = Qnil;
 
   /* See if there's a `:size SIZE' argument.  */
   i = get_key_arg (QCsize, nargs, args, used);
-  size = i < 0 ? make_number (DEFAULT_HASH_SIZE) : args[i];
-  if (!INTEGERP (size) || XINT (size) < 0)
+  size = i < 0 ? Qnil : args[i];
+  if (NILP (size))
+    size = make_number (DEFAULT_HASH_SIZE);
+  else if (!INTEGERP (size) || XINT (size) < 0)
     Fsignal (Qerror,
             list2 (build_string ("Invalid hash table size"),
                    size));
@@ -4729,33 +5370,18 @@ to `key-and-value'.  Default value of WEAK is nil.")
 
 
 DEFUN ("copy-hash-table", Fcopy_hash_table, Scopy_hash_table, 1, 1, 0,
-       "Return a copy of hash table TABLE.")
-  (table)
+       doc: /* Return a copy of hash table TABLE.  */)
+     (table)
      Lisp_Object table;
 {
   return copy_hash_table (check_hash_table (table));
 }
 
 
-DEFUN ("makehash", Fmakehash, Smakehash, 0, 1, 0,
-       "Create a new hash table.\n\
-Optional first argument TEST specifies how to compare keys in\n\
-the table.  Predefined tests are `eq', `eql', and `equal'.  Default\n\
-is `eql'.  New tests can be defined with `define-hash-table-test'.")
-  (test)
-     Lisp_Object test;
-{
-  Lisp_Object args[2];
-  args[0] = QCtest;
-  args[1] = NILP (test) ? Qeql : test;
-  return Fmake_hash_table (2, args);
-}
-
-
 DEFUN ("hash-table-count", Fhash_table_count, Shash_table_count, 1, 1, 0,
-  "Return the number of elements in TABLE.")
-  (table)
-       Lisp_Object table;
+       doc: /* Return the number of elements in TABLE.  */)
+     (table)
+     Lisp_Object table;
 {
   return check_hash_table (table)->count;
 }
@@ -4763,9 +5389,9 @@ DEFUN ("hash-table-count", Fhash_table_count, Shash_table_count, 1, 1, 0,
 
 DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size,
        Shash_table_rehash_size, 1, 1, 0,
-  "Return the current rehash size of TABLE.")
-  (table)
-       Lisp_Object table;
+       doc: /* Return the current rehash size of TABLE.  */)
+     (table)
+     Lisp_Object table;
 {
   return check_hash_table (table)->rehash_size;
 }
@@ -4773,20 +5399,20 @@ DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size,
 
 DEFUN ("hash-table-rehash-threshold", Fhash_table_rehash_threshold,
        Shash_table_rehash_threshold, 1, 1, 0,
-  "Return the current rehash threshold of TABLE.")
-  (table)
-       Lisp_Object table;
+       doc: /* Return the current rehash threshold of TABLE.  */)
+     (table)
+     Lisp_Object table;
 {
   return check_hash_table (table)->rehash_threshold;
 }
 
 
 DEFUN ("hash-table-size", Fhash_table_size, Shash_table_size, 1, 1, 0,
-  "Return the size of TABLE.\n\
-The size can be used as an argument to `make-hash-table' to create\n\
-a hash table than can hold as many elements of TABLE holds\n\
-without need for resizing.")
-  (table)
+       doc: /* Return the size of TABLE.
+The size can be used as an argument to `make-hash-table' to create
+a hash table than can hold as many elements of TABLE holds
+without need for resizing.  */)
+     (table)
        Lisp_Object table;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4795,9 +5421,9 @@ without need for resizing.")
 
 
 DEFUN ("hash-table-test", Fhash_table_test, Shash_table_test, 1, 1, 0,
-  "Return the test TABLE uses.")
-  (table)
-       Lisp_Object table;
+       doc: /* Return the test TABLE uses.  */)
+     (table)
+     Lisp_Object table;
 {
   return check_hash_table (table)->test;
 }
@@ -4805,17 +5431,17 @@ DEFUN ("hash-table-test", Fhash_table_test, Shash_table_test, 1, 1, 0,
 
 DEFUN ("hash-table-weakness", Fhash_table_weakness, Shash_table_weakness,
        1, 1, 0,
-  "Return the weakness of TABLE.")
-  (table)
-       Lisp_Object table;
+       doc: /* Return the weakness of TABLE.  */)
+     (table)
+     Lisp_Object table;
 {
   return check_hash_table (table)->weak;
 }
 
 
 DEFUN ("hash-table-p", Fhash_table_p, Shash_table_p, 1, 1, 0,
-  "Return t if OBJ is a Lisp hash table object.")
-  (obj)
+       doc: /* Return t if OBJ is a Lisp hash table object.  */)
+     (obj)
      Lisp_Object obj;
 {
   return HASH_TABLE_P (obj) ? Qt : Qnil;
@@ -4823,8 +5449,8 @@ DEFUN ("hash-table-p", Fhash_table_p, Shash_table_p, 1, 1, 0,
 
 
 DEFUN ("clrhash", Fclrhash, Sclrhash, 1, 1, 0,
-  "Clear hash table TABLE.")
-  (table)
+       doc: /* Clear hash table TABLE.  */)
+     (table)
      Lisp_Object table;
 {
   hash_clear (check_hash_table (table));
@@ -4833,9 +5459,9 @@ DEFUN ("clrhash", Fclrhash, Sclrhash, 1, 1, 0,
 
 
 DEFUN ("gethash", Fgethash, Sgethash, 2, 3, 0,
-  "Look up KEY in TABLE and return its associated value.\n\
-If KEY is not found, return DFLT which defaults to nil.")
-  (key, table, dflt)
+       doc: /* Look up KEY in TABLE and return its associated value.
+If KEY is not found, return DFLT which defaults to nil.  */)
+     (key, table, dflt)
      Lisp_Object key, table, dflt;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4845,10 +5471,10 @@ If KEY is not found, return DFLT which defaults to nil.")
 
 
 DEFUN ("puthash", Fputhash, Sputhash, 3, 3, 0,
-  "Associate KEY with VALUE in hash table TABLE.\n\
-If KEY is already present in table, replace its current value with\n\
-VALUE.")
-  (key, value, table)
+       doc: /* Associate KEY with VALUE in hash table TABLE.
+If KEY is already present in table, replace its current value with
+VALUE.  */)
+     (key, value, table)
      Lisp_Object key, value, table;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4866,8 +5492,8 @@ VALUE.")
 
 
 DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0,
-  "Remove KEY from TABLE.")
-  (key, table)
+       doc: /* Remove KEY from TABLE.  */)
+     (key, table)
      Lisp_Object key, table;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4877,9 +5503,9 @@ DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0,
 
 
 DEFUN ("maphash", Fmaphash, Smaphash, 2, 2, 0,
-  "Call FUNCTION for all entries in hash table TABLE.\n\
-FUNCTION is called with 2 arguments KEY and VALUE.")
-  (function, table)
+       doc: /* Call FUNCTION for all entries in hash table TABLE.
+FUNCTION is called with two arguments, KEY and VALUE.  */)
+     (function, table)
      Lisp_Object function, table;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4901,22 +5527,253 @@ FUNCTION is called with 2 arguments KEY and VALUE.")
 
 DEFUN ("define-hash-table-test", Fdefine_hash_table_test,
        Sdefine_hash_table_test, 3, 3, 0,
-  "Define a new hash table test with name NAME, a symbol.\n\
-In hash tables create with NAME specified as test, use TEST to compare\n\
-keys, and HASH for computing hash codes of keys.\n\
-\n\
-TEST must be a function taking two arguments and returning non-nil\n\
-if both arguments are the same.   HASH must be a function taking\n\
-one argument and return an integer that is the hash code of the\n\
-argument.  Hash code computation should use the whole value range of\n\
-integers, including negative integers.")
-  (name, test, hash)
+       doc: /* Define a new hash table test with name NAME, a symbol.
+
+In hash tables created with NAME specified as test, use TEST to
+compare keys, and HASH for computing hash codes of keys.
+
+TEST must be a function taking two arguments and returning non-nil if
+both arguments are the same.  HASH must be a function taking one
+argument and return an integer that is the hash code of the argument.
+Hash code computation should use the whole value range of integers,
+including negative integers.  */)
+     (name, test, hash)
      Lisp_Object name, test, hash;
 {
   return Fput (name, Qhash_table_test, list2 (test, hash));
 }
 
 
+\f
+/************************************************************************
+                                MD5
+ ************************************************************************/
+
+#include "md5.h"
+#include "coding.h"
+
+DEFUN ("md5", Fmd5, Smd5, 1, 5, 0,
+       doc: /* Return MD5 message digest of OBJECT, a buffer or string.
+
+A message digest is a cryptographic checksum of a document, and the
+algorithm to calculate it is defined in RFC 1321.
+
+The two optional arguments START and END are character positions
+specifying for which part of OBJECT the message digest should be
+computed.  If nil or omitted, the digest is computed for the whole
+OBJECT.
+
+The MD5 message digest is computed from the result of encoding the
+text in a coding system, not directly from the internal Emacs form of
+the text.  The optional fourth argument CODING-SYSTEM specifies which
+coding system to encode the text with.  It should be the same coding
+system that you used or will use when actually writing the text into a
+file.
+
+If CODING-SYSTEM is nil or omitted, the default depends on OBJECT.  If
+OBJECT is a buffer, the default for CODING-SYSTEM is whatever coding
+system would be chosen by default for writing this text into a file.
+
+If OBJECT is a string, the most preferred coding system (see the
+command `prefer-coding-system') is used.
+
+If NOERROR is non-nil, silently assume the `raw-text' coding if the
+guesswork fails.  Normally, an error is signaled in such case.  */)
+     (object, start, end, coding_system, noerror)
+     Lisp_Object object, start, end, coding_system, noerror;
+{
+  unsigned char digest[16];
+  unsigned char value[33];
+  int i;
+  int size;
+  int size_byte = 0;
+  int start_char = 0, end_char = 0;
+  int start_byte = 0, end_byte = 0;
+  register int b, e;
+  register struct buffer *bp;
+  int temp;
+
+  if (STRINGP (object))
+    {
+      if (NILP (coding_system))
+       {
+         /* Decide the coding-system to encode the data with.  */
+
+         if (STRING_MULTIBYTE (object))
+           /* use default, we can't guess correct value */
+           coding_system = SYMBOL_VALUE (XCAR (Vcoding_category_list));
+         else
+           coding_system = Qraw_text;
+       }
+
+      if (NILP (Fcoding_system_p (coding_system)))
+       {
+         /* Invalid coding system.  */
+
+         if (!NILP (noerror))
+           coding_system = Qraw_text;
+         else
+           while (1)
+             Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil));
+       }
+
+      if (STRING_MULTIBYTE (object))
+       object = code_convert_string1 (object, coding_system, Qnil, 1);
+
+      size = SCHARS (object);
+      size_byte = SBYTES (object);
+
+      if (!NILP (start))
+       {
+         CHECK_NUMBER (start);
+
+         start_char = XINT (start);
+
+         if (start_char < 0)
+           start_char += size;
+
+         start_byte = string_char_to_byte (object, start_char);
+       }
+
+      if (NILP (end))
+       {
+         end_char = size;
+         end_byte = size_byte;
+       }
+      else
+       {
+         CHECK_NUMBER (end);
+
+         end_char = XINT (end);
+
+         if (end_char < 0)
+           end_char += size;
+
+         end_byte = string_char_to_byte (object, end_char);
+       }
+
+      if (!(0 <= start_char && start_char <= end_char && end_char <= size))
+       args_out_of_range_3 (object, make_number (start_char),
+                            make_number (end_char));
+    }
+  else
+    {
+      struct buffer *prev = current_buffer;
+
+      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+
+      CHECK_BUFFER (object);
+
+      bp = XBUFFER (object);
+      if (bp != current_buffer)
+       set_buffer_internal (bp);
+
+      if (NILP (start))
+       b = BEGV;
+      else
+       {
+         CHECK_NUMBER_COERCE_MARKER (start);
+         b = XINT (start);
+       }
+
+      if (NILP (end))
+       e = ZV;
+      else
+       {
+         CHECK_NUMBER_COERCE_MARKER (end);
+         e = XINT (end);
+       }
+
+      if (b > e)
+       temp = b, b = e, e = temp;
+
+      if (!(BEGV <= b && e <= ZV))
+       args_out_of_range (start, end);
+
+      if (NILP (coding_system))
+       {
+         /* Decide the coding-system to encode the data with.
+            See fileio.c:Fwrite-region */
+
+         if (!NILP (Vcoding_system_for_write))
+           coding_system = Vcoding_system_for_write;
+         else
+           {
+             int force_raw_text = 0;
+
+             coding_system = XBUFFER (object)->buffer_file_coding_system;
+             if (NILP (coding_system)
+                 || NILP (Flocal_variable_p (Qbuffer_file_coding_system, Qnil)))
+               {
+                 coding_system = Qnil;
+                 if (NILP (current_buffer->enable_multibyte_characters))
+                   force_raw_text = 1;
+               }
+
+             if (NILP (coding_system) && !NILP (Fbuffer_file_name(object)))
+               {
+                 /* Check file-coding-system-alist.  */
+                 Lisp_Object args[4], val;
+
+                 args[0] = Qwrite_region; args[1] = start; args[2] = end;
+                 args[3] = Fbuffer_file_name(object);
+                 val = Ffind_operation_coding_system (4, args);
+                 if (CONSP (val) && !NILP (XCDR (val)))
+                   coding_system = XCDR (val);
+               }
+
+             if (NILP (coding_system)
+                 && !NILP (XBUFFER (object)->buffer_file_coding_system))
+               {
+                 /* If we still have not decided a coding system, use the
+                    default value of buffer-file-coding-system.  */
+                 coding_system = XBUFFER (object)->buffer_file_coding_system;
+               }
+
+             if (!force_raw_text
+                 && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
+               /* Confirm that VAL can surely encode the current region.  */
+               coding_system = call4 (Vselect_safe_coding_system_function,
+                                      make_number (b), make_number (e),
+                                      coding_system, Qnil);
+
+             if (force_raw_text)
+               coding_system = Qraw_text;
+           }
+
+         if (NILP (Fcoding_system_p (coding_system)))
+           {
+             /* Invalid coding system.  */
+
+             if (!NILP (noerror))
+               coding_system = Qraw_text;
+             else
+               while (1)
+                 Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil));
+           }
+       }
+
+      object = make_buffer_string (b, e, 0);
+      if (prev != current_buffer)
+       set_buffer_internal (prev);
+      /* Discard the unwind protect for recovering the current
+        buffer.  */
+      specpdl_ptr--;
+
+      if (STRING_MULTIBYTE (object))
+       object = code_convert_string1 (object, coding_system, Qnil, 1);
+    }
+
+  md5_buffer (SDATA (object) + start_byte,
+             SBYTES (object) - (size_byte - end_byte),
+             digest);
+
+  for (i = 0; i < 16; i++)
+    sprintf (&value[2 * i], "%02x", digest[i]);
+  value[32] = '\0';
+
+  return make_string (value, 32);
+}
 
 \f
 void
@@ -4955,7 +5812,6 @@ syms_of_fns ()
   defsubr (&Ssxhash);
   defsubr (&Smake_hash_table);
   defsubr (&Scopy_hash_table);
-  defsubr (&Smakehash);
   defsubr (&Shash_table_count);
   defsubr (&Shash_table_rehash_size);
   defsubr (&Shash_table_rehash_threshold);
@@ -4986,19 +5842,42 @@ syms_of_fns ()
   staticpro (&string_char_byte_cache_string);
   string_char_byte_cache_string = Qnil;
 
+  require_nesting_list = Qnil;
+  staticpro (&require_nesting_list);
+
   Fset (Qyes_or_no_p_history, Qnil);
 
   DEFVAR_LISP ("features", &Vfeatures,
-    "A list of symbols which are the features of the executing emacs.\n\
-Used by `featurep' and `require', and altered by `provide'.");
-  Vfeatures = Qnil;
+    doc: /* A list of symbols which are the features of the executing emacs.
+Used by `featurep' and `require', and altered by `provide'.  */);
+  Vfeatures = Fcons (intern ("emacs"), Qnil);
+  Qsubfeatures = intern ("subfeatures");
+  staticpro (&Qsubfeatures);
+
+#ifdef HAVE_LANGINFO_CODESET
+  Qcodeset = intern ("codeset");
+  staticpro (&Qcodeset);
+  Qdays = intern ("days");
+  staticpro (&Qdays);
+  Qmonths = intern ("months");
+  staticpro (&Qmonths);
+  Qpaper = intern ("paper");
+  staticpro (&Qpaper);
+#endif /* HAVE_LANGINFO_CODESET */
 
   DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
-    "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
-This applies to y-or-n and yes-or-no questions asked by commands\n\
-invoked by mouse clicks and mouse menu items.");
+    doc: /* *Non-nil means mouse commands use dialog boxes to ask questions.
+This applies to `y-or-n-p' and `yes-or-no-p' questions asked by commands
+invoked by mouse clicks and mouse menu items.  */);
   use_dialog_box = 1;
 
+  DEFVAR_BOOL ("use-file-dialog", &use_file_dialog,
+    doc: /* *Non-nil means mouse commands use a file dialog to ask for files.
+This applies to commands from menus and tool bar buttons.  The value of
+`use-dialog-box' takes precedence over this variable, so a file dialog is only
+used if both `use-dialog-box' and this variable are non-nil.  */);
+  use_file_dialog = 1;
+
   defsubr (&Sidentity);
   defsubr (&Srandom);
   defsubr (&Slength);
@@ -5015,8 +5894,10 @@ invoked by mouse clicks and mouse menu items.");
   defsubr (&Sstring_make_unibyte);
   defsubr (&Sstring_as_multibyte);
   defsubr (&Sstring_as_unibyte);
+  defsubr (&Sstring_to_multibyte);
   defsubr (&Scopy_alist);
   defsubr (&Ssubstring);
+  defsubr (&Ssubstring_no_properties);
   defsubr (&Snthcdr);
   defsubr (&Snth);
   defsubr (&Selt);
@@ -5035,8 +5916,13 @@ invoked by mouse clicks and mouse menu items.");
   defsubr (&Sget);
   defsubr (&Splist_put);
   defsubr (&Sput);
+  defsubr (&Slax_plist_get);
+  defsubr (&Slax_plist_put);
+  defsubr (&Seql);
   defsubr (&Sequal);
+  defsubr (&Sequal_including_properties);
   defsubr (&Sfillarray);
+  defsubr (&Sclear_string);
   defsubr (&Schar_table_subtype);
   defsubr (&Schar_table_parent);
   defsubr (&Sset_char_table_parent);
@@ -5065,6 +5951,8 @@ invoked by mouse clicks and mouse menu items.");
   defsubr (&Sbase64_decode_region);
   defsubr (&Sbase64_encode_string);
   defsubr (&Sbase64_decode_string);
+  defsubr (&Smd5);
+  defsubr (&Slocale_info);
 }
 
 
@@ -5073,3 +5961,6 @@ init_fns ()
 {
   Vweak_hash_tables = Qnil;
 }
+
+/* arch-tag: 787f8219-5b74-46bd-8469-7e1cc475fa31
+   (do not change this comment) */