]> code.delx.au - gnu-emacs/blobdiff - src/fns.c
*** empty log message ***
[gnu-emacs] / src / fns.c
index ceda1cfbf41d515418f50e1b7e5d6fe1394ff22d..06d04781789f37c97e29a6a60a6df545ebd44360 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -1,5 +1,5 @@
 /* Random utility Lisp functions.
 /* Random utility Lisp functions.
-   Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 98, 99, 2000, 2001
+   Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 98, 99, 2000, 2001, 02, 03, 2004
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -19,7 +19,6 @@ 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., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-
 #include <config.h>
 
 #ifdef HAVE_UNISTD_H
 #include <config.h>
 
 #ifdef HAVE_UNISTD_H
@@ -27,44 +26,52 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #include <time.h>
 
 #endif
 #include <time.h>
 
+#ifndef MAC_OSX
+/* On Mac OS X, 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 *****
 
 /* 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 "lisp.h"
 #include "commands.h"
 #include "charset.h"
-
+#include "coding.h"
 #include "buffer.h"
 #include "keyboard.h"
 #include "buffer.h"
 #include "keyboard.h"
+#include "keymap.h"
 #include "intervals.h"
 #include "frame.h"
 #include "window.h"
 #include "intervals.h"
 #include "frame.h"
 #include "window.h"
+#include "blockinput.h"
 #if defined (HAVE_MENUS) && defined (HAVE_X_WINDOWS)
 #include "xterm.h"
 #endif
 
 #ifndef NULL
 #if defined (HAVE_MENUS) && defined (HAVE_X_WINDOWS)
 #include "xterm.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))
+#define NULL ((POINTER_TYPE *)0)
 #endif
 
 /* Nonzero enables use of dialog boxes for questions
    asked by mouse commands.  */
 int use_dialog_box;
 
 #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 int minibuffer_auto_raise;
 extern Lisp_Object minibuf_window;
+extern Lisp_Object Vlocale_coding_system;
 
 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 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;
 
 
 extern Lisp_Object Qinput_method_function;
 
@@ -78,20 +85,20 @@ extern long time ();
 #endif
 \f
 DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
 #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,
      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;
      Lisp_Object n;
 {
   EMACS_INT val;
@@ -123,12 +130,12 @@ 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,
 /* 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 val;
      register Lisp_Object sequence;
 {
   register Lisp_Object val;
@@ -136,9 +143,11 @@ To get the number of bytes, use `string-bytes'")
 
  retry:
   if (STRINGP (sequence))
 
  retry:
   if (STRINGP (sequence))
-    XSETFASTINT (val, XSTRING (sequence)->size);
+    XSETFASTINT (val, SCHARS (sequence));
   else if (VECTORP (sequence))
     XSETFASTINT (val, XVECTOR (sequence)->size);
   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))
   else if (CHAR_TABLE_P (sequence))
     XSETFASTINT (val, MAX_CHAR);
   else if (BOOL_VECTOR_P (sequence))
@@ -180,11 +189,11 @@ To get the number of bytes, use `string-bytes'")
    since it must terminate.  */
 
 DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
    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;
      Lisp_Object list;
 {
   Lisp_Object tail, halftail, length;
@@ -206,69 +215,69 @@ which is at least the number of distinct elements.")
 }
 
 DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0,
 }
 
 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;
 {
      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,
 }
 
 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))
      register Lisp_Object s1, s2;
 {
   if (SYMBOLP (s1))
-    XSETSTRING (s1, XSYMBOL (s1)->name);
+    s1 = SYMBOL_NAME (s1);
   if (SYMBOLP (s2))
   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,
     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;
 
      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);
   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))
   if (! NILP (end1))
-    CHECK_NATNUM (end1, 4);
+    CHECK_NATNUM (end1);
   if (! NILP (end2))
   if (! NILP (end2))
-    CHECK_NATNUM (end2, 4);
+    CHECK_NATNUM (end2);
 
   i1 = XINT (start1);
   i2 = XINT (start2);
 
   i1 = XINT (start1);
   i2 = XINT (start2);
@@ -276,11 +285,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);
 
   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);
 
   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);
 
   if (! NILP (end2) && end2_char > XINT (end2))
     end2_char = XINT (end2);
 
@@ -294,7 +303,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
        {
        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);
        }
 
          c1 = unibyte_char_to_multibyte (c1);
        }
 
@@ -302,7 +311,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
        {
        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);
        }
 
          c2 = unibyte_char_to_multibyte (c2);
        }
 
@@ -340,27 +349,27 @@ If string STR1 is greater, the value is a positive number N;\n\
 }
 
 DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
 }
 
 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))
      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))
   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;
 
 
   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)
     {
 
   while (i1 < end)
     {
@@ -374,7 +383,7 @@ Symbols are also allowed; their print names are used instead.")
       if (c1 != c2)
        return c1 < c2 ? Qt : Qnil;
     }
       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 ();
 }
 \f
 static Lisp_Object concat ();
@@ -411,11 +420,12 @@ concat3 (s1, s2, s3)
 }
 
 DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
 }
 
 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;
 {
      int nargs;
      Lisp_Object *args;
 {
@@ -423,10 +433,11 @@ The last argument is not copied, just used as the tail of the new list.")
 }
 
 DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
 }
 
 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;
 {
      int nargs;
      Lisp_Object *args;
 {
@@ -434,17 +445,18 @@ Each argument may be a string or a list or vector of characters (integers).")
 }
 
 DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
 }
 
 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);
 }
 
      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)
    nested sub char table are not copied.  */
 static Lisp_Object
 copy_sub_char_table (arg)
@@ -467,10 +479,10 @@ copy_sub_char_table (arg)
 
 
 DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
 
 
 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;
      Lisp_Object arg;
 {
   if (NILP (arg)) return arg;
@@ -501,7 +513,8 @@ with the original.")
     {
       Lisp_Object val;
       int size_in_chars
     {
       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,
 
       val = Fmake_bool_vector (Flength (arg), Qnil);
       bcopy (XBOOL_VECTOR (arg)->data, XBOOL_VECTOR (val)->data,
@@ -514,27 +527,6 @@ with the original.")
   return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
 }
 
   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
 /* This structure holds information of an argument of `concat' that is
    a string and has text properties to be copied.  */
 struct textprop_rec
@@ -642,11 +634,11 @@ concat (nargs, args, target_type, last_special)
              if (STRING_MULTIBYTE (this))
                {
                  some_multibyte = 1;
              if (STRING_MULTIBYTE (this))
                {
                  some_multibyte = 1;
-                 result_len_byte += STRING_BYTES (XSTRING (this));
+                 result_len_byte += SBYTES (this);
                }
              else
                }
              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));
            }
        }
 
            }
        }
 
@@ -696,39 +688,32 @@ concat (nargs, args, target_type, last_special)
       if (STRINGP (this) && STRINGP (val)
          && STRING_MULTIBYTE (this) == some_multibyte)
        {
       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;
            {
              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;
              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))
        {
        }
       /* 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;
            }
            {
              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
          toindex += thisleni;
        }
       else
@@ -756,7 +741,7 @@ concat (nargs, args, target_type, last_special)
                  }
                else
                  {
                  }
                else
                  {
-                   XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
+                   XSETFASTINT (elt, SREF (this, thisindex++));
                    if (some_multibyte
                        && (XINT (elt) >= 0240
                            || (XINT (elt) >= 0200
                    if (some_multibyte
                        && (XINT (elt) >= 0240
                            || (XINT (elt) >= 0200
@@ -771,8 +756,8 @@ concat (nargs, args, target_type, last_special)
            else if (BOOL_VECTOR_P (this))
              {
                int byte;
            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;
                  elt = Qt;
                else
                  elt = Qnil;
@@ -784,7 +769,7 @@ concat (nargs, args, target_type, last_special)
            /* Store this element into the result.  */
            if (toindex < 0)
              {
            /* Store this element into the result.  */
            if (toindex < 0)
              {
-               XCAR (tail) = elt;
+               XSETCAR (tail, elt);
                prev = tail;
                tail = XCDR (tail);
              }
                prev = tail;
                tail = XCDR (tail);
              }
@@ -792,22 +777,16 @@ concat (nargs, args, target_type, last_special)
              XVECTOR (val)->contents[toindex++] = elt;
            else
              {
              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),
                if (SINGLE_BYTE_CHAR_P (XINT (elt)))
                  {
                    if (some_multibyte)
                      toindex_byte
                        += CHAR_STRING (XINT (elt),
-                                       XSTRING (val)->data + toindex_byte);
+                                       SDATA (val) + toindex_byte);
                    else
                    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--;
-                   else
-                     toindex++;
+                     SSET (val, toindex_byte++, XINT (elt));
+                   toindex++;
                  }
                else
                  /* If we have any multibyte characters,
                  }
                else
                  /* If we have any multibyte characters,
@@ -816,7 +795,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.  */
                    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++;
 
                    toindex_byte += CHAR_STRING (c, p);
                    toindex++;
@@ -825,7 +804,7 @@ concat (nargs, args, target_type, last_special)
          }
     }
   if (!NILP (prev))
          }
     }
   if (!NILP (prev))
-    XCDR (prev) = last_tail;
+    XSETCDR (prev, last_tail);
 
   if (num_textprops > 0)
     {
 
   if (num_textprops > 0)
     {
@@ -837,7 +816,7 @@ concat (nargs, args, target_type, last_special)
          this = args[textprops[argnum].argnum];
          props = text_property_list (this,
                                      make_number (0),
          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.  */
                                      Qnil);
          /* If successive arguments have properites, be sure that the
             value of `composition' property be the copy.  */
@@ -845,7 +824,7 @@ concat (nargs, args, target_type, last_special)
            make_composition_value_copy (props);
          add_text_properties_from_list (val, props,
                                         make_number (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 + XSTRING (this)->size;
+         last_to_end = textprops[argnum].to + SCHARS (this);
        }
     }
   return val;
        }
     }
   return val;
@@ -872,12 +851,11 @@ string_char_to_byte (string, char_index)
   int best_below, best_below_byte;
   int best_above, best_above_byte;
 
   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_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))
     {
 
   if (EQ (string, string_char_byte_cache_string))
     {
@@ -908,7 +886,7 @@ string_char_to_byte (string, char_index)
     {
       while (best_above > 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;
          unsigned char *pbeg = pend - best_above_byte;
          unsigned char *p = pend - 1;
          int bytes;
@@ -945,12 +923,11 @@ string_byte_to_char (string, byte_index)
   int best_below, best_below_byte;
   int best_above, best_above_byte;
 
   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_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))
     {
 
   if (EQ (string, string_char_byte_cache_string))
     {
@@ -981,7 +958,7 @@ string_byte_to_char (string, byte_index)
     {
       while (best_above_byte > 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;
          unsigned char *pbeg = pend - best_above_byte;
          unsigned char *p = pend - 1;
          int bytes;
@@ -1017,88 +994,143 @@ string_make_multibyte (string)
 {
   unsigned char *buf;
   int nbytes;
 {
   unsigned char *buf;
   int nbytes;
+  Lisp_Object ret;
+  USE_SAFE_ALLOCA;
 
   if (STRING_MULTIBYTE (string))
     return string;
 
 
   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 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;
 
     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);
 
             0, 1);
 
-  return make_multibyte_string (buf, XSTRING (string)->size, nbytes);
+  ret = make_multibyte_string (buf, SCHARS (string), nbytes);
+  SAFE_FREE (nbytes);
+
+  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 (nbytes);
+
+  return ret;
+}
+
+
 /* Convert STRING to a single-byte string.  */
 
 Lisp_Object
 string_make_unibyte (string)
      Lisp_Object string;
 {
 /* Convert STRING to a single-byte string.  */
 
 Lisp_Object
 string_make_unibyte (string)
      Lisp_Object string;
 {
+  int nchars;
   unsigned char *buf;
   unsigned char *buf;
+  Lisp_Object ret;
+  USE_SAFE_ALLOCA;
 
   if (! STRING_MULTIBYTE (string))
     return string;
 
 
   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);
 
             1, 0);
 
-  return make_unibyte_string (buf, XSTRING (string)->size);
+  ret = make_unibyte_string (buf, nchars);
+  SAFE_FREE (nchars);
+
+  return ret;
 }
 
 DEFUN ("string-make-multibyte", Fstring_make_multibyte, Sstring_make_multibyte,
        1, 1, 0,
 }
 
 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;
 {
      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 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;
 {
      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 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\n\
-`eight-bit-control' or `eight-bit-graphic', it is converted to the\n\
-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;
 {
      Lisp_Object string;
 {
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
 
   if (STRING_MULTIBYTE (string))
     {
 
   if (STRING_MULTIBYTE (string))
     {
-      int bytes = STRING_BYTES (XSTRING (string));
+      int bytes = SBYTES (string);
       unsigned char *str = (unsigned char *) xmalloc (bytes);
 
       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);
       bytes = str_as_unibyte (str, bytes);
       string = make_unibyte_string (str, bytes);
       xfree (str);
@@ -1108,50 +1140,68 @@ corresponding single byte.")
 
 DEFUN ("string-as-multibyte", Fstring_as_multibyte, Sstring_as_multibyte,
        1, 1, 0,
 
 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 a multibyte form), it is converted to the corresponding\n\
-multibyte character of charset `eight-bit-control' or `eight-bit-graphic'.")
-  (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'.  */)
+     (string)
      Lisp_Object string;
 {
      Lisp_Object string;
 {
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
 
   if (! STRING_MULTIBYTE (string))
     {
       Lisp_Object new_string;
       int nchars, nbytes;
 
 
   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);
                              &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;
       string = new_string;
-      XSTRING (string)->intervals = NULL_INTERVAL;
+      STRING_SET_INTERVALS (string, NULL_INTERVAL);
     }
   return string;
 }
     }
   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.  */)
+     (string)
+     Lisp_Object string;
+{
+  CHECK_STRING (string);
+
+  return string_to_multibyte (string);
+}
+
 \f
 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
 \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;
 
      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);
   if (NILP (alist))
     return alist;
   alist = concat (1, &alist, Lisp_Cons, 0);
@@ -1161,18 +1211,18 @@ Elements of ALIST that are not conses are also shared.")
       car = XCAR (tem);
 
       if (CONSP (car))
       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 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 string;
      register Lisp_Object from, to;
 {
@@ -1185,12 +1235,12 @@ This function allows vectors as well as strings.")
   if (! (STRINGP (string) || VECTORP (string)))
     wrong_type_argument (Qarrayp, string);
 
   if (! (STRINGP (string) || VECTORP (string)))
     wrong_type_argument (Qarrayp, string);
 
-  CHECK_NUMBER (from, 1);
+  CHECK_NUMBER (from);
 
   if (STRINGP (string))
     {
 
   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;
     }
   else
     size = XVECTOR (string)->size;
@@ -1202,7 +1252,7 @@ This function allows vectors as well as strings.")
     }
   else
     {
     }
   else
     {
-      CHECK_NUMBER (to, 2);
+      CHECK_NUMBER (to);
 
       to_char = XINT (to);
       if (to_char < 0)
 
       to_char = XINT (to);
       if (to_char < 0)
@@ -1224,7 +1274,7 @@ This function allows vectors as well as strings.")
 
   if (STRINGP (string))
     {
 
   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),
                                   to_char - from_char, to_byte - from_byte,
                                   STRING_MULTIBYTE (string));
       copy_text_properties (make_number (from_char), make_number (to_char),
@@ -1237,6 +1287,65 @@ This function allows vectors as well as strings.")
   return res;
 }
 
   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.  */
 
 /* Extract a substring of STRING, giving start and end positions
    both in characters and in bytes.  */
 
@@ -1254,8 +1363,8 @@ substring_both (string, from, from_byte, to, to_byte)
 
   if (STRINGP (string))
     {
 
   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;
     }
   else
     size = XVECTOR (string)->size;
@@ -1265,7 +1374,7 @@ substring_both (string, from, from_byte, to, to_byte)
 
   if (STRINGP (string))
     {
 
   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),
                                   to - from, to_byte - from_byte,
                                   STRING_MULTIBYTE (string));
       copy_text_properties (make_number (from), make_number (to),
@@ -1279,13 +1388,13 @@ substring_both (string, from, from_byte, to, to_byte)
 }
 \f
 DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
 }
 \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;
      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++)
     {
   num = XINT (n);
   for (i = 0; i < num && !NILP (list); i++)
     {
@@ -1298,20 +1407,20 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
 }
 
 DEFUN ("nth", Fnth, Snth, 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,
      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;
 {
      register Lisp_Object sequence, n;
 {
-  CHECK_NUMBER (n, 0);
+  CHECK_NUMBER (n);
   while (1)
     {
       if (CONSP (sequence) || NILP (sequence))
   while (1)
     {
       if (CONSP (sequence) || NILP (sequence))
@@ -1325,9 +1434,9 @@ DEFUN ("elt", Felt, Selt, 2, 2, 0,
 }
 
 DEFUN ("member", Fmember, Smember, 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;
 {
      register Lisp_Object elt;
      Lisp_Object list;
 {
@@ -1346,10 +1455,10 @@ The value is actually the tail of LIST whose car is ELT.")
 }
 
 DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
 }
 
 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)
      Lisp_Object elt, list;
 {
   while (1)
@@ -1376,10 +1485,10 @@ whose car is ELT.")
 }
 
 DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
 }
 
 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;
      Lisp_Object key, list;
 {
   Lisp_Object result;
@@ -1433,9 +1542,9 @@ assq_no_quit (key, list)
 }
 
 DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
 }
 
 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;
      Lisp_Object key, list;
 {
   Lisp_Object result, car;
@@ -1477,9 +1586,9 @@ The value is actually the element of LIST whose car equals KEY.")
 }
 
 DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
 }
 
 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;
 {
      register Lisp_Object key;
      Lisp_Object list;
 {
@@ -1519,9 +1628,9 @@ The value is actually the element of LIST whose cdr is KEY.")
 }
 
 DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
 }
 
 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;
      Lisp_Object key, list;
 {
   Lisp_Object result, cdr;
@@ -1563,12 +1672,12 @@ The value is actually the element of LIST whose cdr equals KEY.")
 }
 \f
 DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
 }
 \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;
 {
      register Lisp_Object elt;
      Lisp_Object list;
 {
@@ -1598,14 +1707,14 @@ to be sure of changing the value of `foo'.")
 }
 
 DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
 }
 
 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))
      Lisp_Object elt, seq;
 {
   if (VECTORP (seq))
@@ -1633,18 +1742,18 @@ to be sure of changing the value of `foo'.")
       int c;
 
       for (i = nchars = nbytes = ibyte = 0;
       int c;
 
       for (i = nchars = nbytes = ibyte = 0;
-          i < XSTRING (seq)->size;
+          i < SCHARS (seq);
           ++i, ibyte += cbytes)
        {
          if (STRING_MULTIBYTE (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
            {
              cbytes = CHAR_BYTES (c);
            }
          else
            {
-             c = XSTRING (seq)->data[i];
+             c = SREF (seq, i);
              cbytes = 1;
            }
 
              cbytes = 1;
            }
 
@@ -1655,34 +1764,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))
        {
          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;
 
          for (i = nchars = nbytes = ibyte = 0;
-              i < XSTRING (seq)->size;
+              i < SCHARS (seq);
               ++i, ibyte += cbytes)
            {
              if (STRING_MULTIBYTE (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
                {
                  cbytes = CHAR_BYTES (c);
                }
              else
                {
-                 c = XSTRING (seq)->data[i];
+                 c = SREF (seq, i);
                  cbytes = 1;
                }
 
              if (!INTEGERP (elt) || c != XINT (elt))
                {
                  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;
                  EMACS_INT n;
 
                  ++nchars;
@@ -1722,9 +1831,9 @@ to be sure of changing the value of `foo'.")
 }
 
 DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
 }
 
 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;
      Lisp_Object list;
 {
   register Lisp_Object prev, tail, next;
@@ -1746,15 +1855,18 @@ Returns the beginning of the reversed list.")
 }
 
 DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
 }
 
 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))
      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;
   if (!NILP (list))
     wrong_type_argument (Qconsp, list);
   return new;
@@ -1763,11 +1875,11 @@ See also the function `nreverse', which is used more often.")
 Lisp_Object merge ();
 
 DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
 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 t
+if the first element is "less" than the second.  */)
+     (list, predicate)
      Lisp_Object list, predicate;
 {
   Lisp_Object front, back;
      Lisp_Object list, predicate;
 {
   Lisp_Object front, back;
@@ -1855,51 +1967,55 @@ merge (org_l1, org_l2, pred)
 
 \f
 DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
 
 \f
 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.  */)
+     (plist, prop)
      Lisp_Object plist;
      Lisp_Object prop;
 {
   Lisp_Object tail;
      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));
   for (tail = plist;
        CONSP (tail) && CONSP (XCDR (tail));
        tail = XCDR (XCDR (tail)))
     {
       if (EQ (prop, XCAR (tail)))
        return XCAR (XCDR (tail));
-      QUIT;
+
+      /* 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);
     }
 
   if (!NILP (tail))
     wrong_type_argument (Qlistp, prop);
-  
+
   return Qnil;
 }
 
 DEFUN ("get", Fget, Sget, 2, 2, 0,
   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;
 {
      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,
   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;
      Lisp_Object plist;
      register Lisp_Object prop;
      Lisp_Object val;
@@ -1915,6 +2031,7 @@ The PLIST is modified by side effects.")
          Fsetcar (XCDR (tail), val);
          return plist;
        }
          Fsetcar (XCDR (tail), val);
          return plist;
        }
+
       prev = tail;
       QUIT;
     }
       prev = tail;
       QUIT;
     }
@@ -1927,35 +2044,125 @@ The PLIST is modified by side effects.")
 }
 
 DEFUN ("put", Fput, Sput, 3, 3, 0,
 }
 
 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;
 {
      Lisp_Object symbol, propname, value;
 {
-  CHECK_SYMBOL (symbol, 0);
+  CHECK_SYMBOL (symbol);
   XSYMBOL (symbol)->plist
     = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
   return value;
 }
   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,
 
 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;
 {
      register Lisp_Object o1, o2;
 {
-  return internal_equal (o1, o2, 0) ? Qt : Qnil;
+  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, 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
 static int
-internal_equal (o1, o2, depth)
+internal_equal (o1, o2, depth, props)
      register Lisp_Object o1, o2;
      register Lisp_Object o1, o2;
-     int depth;
+     int depth, props;
 {
   if (depth > 200)
     error ("Stack overflow in equal");
 {
   if (depth > 200)
     error ("Stack overflow in equal");
@@ -1970,10 +2177,18 @@ internal_equal (o1, o2, depth)
   switch (XTYPE (o1))
     {
     case Lisp_Float:
   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:
 
     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);
        return 0;
       o1 = XCDR (o1);
       o2 = XCDR (o2);
@@ -1985,7 +2200,7 @@ internal_equal (o1, o2, depth)
       if (OVERLAYP (o1))
        {
          if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o2),
       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))
            return 0;
              || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o2),
                                  depth + 1))
            return 0;
@@ -2003,8 +2218,8 @@ internal_equal (o1, o2, depth)
 
     case Lisp_Vectorlike:
       {
 
     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.  */
        /* 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.  */
@@ -2014,7 +2229,8 @@ internal_equal (o1, o2, depth)
        if (BOOL_VECTOR_P (o1))
          {
            int size_in_chars
        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;
 
            if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
              return 0;
@@ -2039,7 +2255,7 @@ internal_equal (o1, o2, depth)
            Lisp_Object v1, v2;
            v1 = XVECTOR (o1)->contents [i];
            v2 = XVECTOR (o2)->contents [i];
            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;
              return 0;
          }
        return 1;
@@ -2047,12 +2263,14 @@ internal_equal (o1, o2, depth)
       break;
 
     case Lisp_String:
       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;
        return 0;
-      if (STRING_BYTES (XSTRING (o1)) != STRING_BYTES (XSTRING (o2)))
+      if (bcmp (SDATA (o1), SDATA (o2),
+               SBYTES (o1)))
        return 0;
        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;
 
        return 0;
       return 1;
 
@@ -2061,16 +2279,16 @@ internal_equal (o1, o2, depth)
     case Lisp_Type_Limit:
       break;
     }
     case Lisp_Type_Limit:
       break;
     }
-  
+
   return 0;
 }
 \f
 extern Lisp_Object Fmake_char_internal ();
 
 DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
   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;
      Lisp_Object array, item;
 {
   register int size, index, charval;
@@ -2092,15 +2310,15 @@ ARRAY is a vector, string, char-table, or bool-vector.")
     }
   else if (STRINGP (array))
     {
     }
   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);
       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);
       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;
 
          unsigned char *p1 = p, *endp = p + size_byte;
          int i;
 
@@ -2123,11 +2341,19 @@ ARRAY is a vector, string, char-table, or bool-vector.")
     {
       register unsigned char *p = XBOOL_VECTOR (array)->data;
       int size_in_chars
     {
       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);
 
       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;
        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
     {
     }
   else
     {
@@ -2136,47 +2362,63 @@ ARRAY is a vector, string, char-table, or bool-vector.")
     }
   return array;
 }
     }
   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,
 \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;
 {
      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 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;
 {
      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,
 
   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;
 
      Lisp_Object char_table, parent;
 {
   Lisp_Object temp;
 
-  CHECK_CHAR_TABLE (char_table, 0);
+  CHECK_CHAR_TABLE (char_table);
 
   if (!NILP (parent))
     {
 
   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))
 
       for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
        if (EQ (temp, char_table))
@@ -2190,12 +2432,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,
 
 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;
 {
      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);
   if (XINT (n) < 0
       || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
     args_out_of_range (char_table, n);
@@ -2206,12 +2448,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,
 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;
 {
      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);
   if (XINT (n) < 0
       || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
     args_out_of_range (char_table, n);
@@ -2221,14 +2463,14 @@ DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
 \f
 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
        2, 2, 0,
 \f
 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.  */)
+     (char_table, range)
      Lisp_Object char_table, range;
 {
      Lisp_Object char_table, range;
 {
-  CHECK_CHAR_TABLE (char_table, 0);
+  CHECK_CHAR_TABLE (char_table);
 
   if (EQ (range, Qnil))
     return XCHAR_TABLE (char_table)->defalt;
 
   if (EQ (range, Qnil))
     return XCHAR_TABLE (char_table)->defalt;
@@ -2239,7 +2481,7 @@ a character set name, or a character code.")
       Lisp_Object charset_info;
 
       charset_info = Fget (range, Qcharset);
       Lisp_Object charset_info;
 
       charset_info = Fget (range, Qcharset);
-      CHECK_VECTOR (charset_info, 0);
+      CHECK_VECTOR (charset_info);
 
       return Faref (char_table,
                    make_number (XINT (XVECTOR (charset_info)->contents[0])
 
       return Faref (char_table,
                    make_number (XINT (XVECTOR (charset_info)->contents[0])
@@ -2267,16 +2509,16 @@ a character set name, or a character code.")
 
 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
        3, 3, 0,
 
 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;
 
      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++)
 
   if (EQ (range, Qt))
     for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
@@ -2286,14 +2528,26 @@ a coding system, or a character code.")
   else if (SYMBOLP (range))
     {
       Lisp_Object charset_info;
   else if (SYMBOLP (range))
     {
       Lisp_Object charset_info;
+      int charset_id;
 
       charset_info = Fget (range, Qcharset);
 
       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 (INTEGERP (range))
     Faset (char_table, range, value);
@@ -2321,17 +2575,17 @@ a coding system, or a character code.")
 
 DEFUN ("set-char-table-default", Fset_char_table_default,
        Sset_char_table_default, 3, 3, 0,
 
 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.
+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;
 
      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);
 
   c = XINT (ch);
   SPLIT_CHAR (c, charset, code1, code2);
@@ -2347,7 +2601,7 @@ See also the documentation of make-char.")
 
   /* Even if C is not a generic char, we had better behave as if a
      generic char is specified.  */
 
   /* 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 (!code1)
     code1 = 0;
   temp = XCHAR_TABLE (char_table)->contents[charset + 128];
   if (!code1)
@@ -2411,16 +2665,15 @@ optimize_sub_char_table (table, chars)
 }
 
 DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
 }
 
 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;
 
      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++)
     {
 
   for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
     {
@@ -2446,9 +2699,9 @@ DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
    ARG is passed to C_FUNCTION when that is called.  */
 
 void
    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));
      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;
      int depth;
 {
   int i, to;
@@ -2458,7 +2711,11 @@ map_char_table (c_function, function, subtable, arg, depth, indices)
       /* At first, handle ASCII and 8-bit European characters.  */
       for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
        {
       /* 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
          if (c_function)
            (*c_function) (arg, make_number (i), elt);
          else
@@ -2499,17 +2756,21 @@ map_char_table (c_function, function, subtable, arg, depth, indices)
        {
          if (depth >= 3)
            error ("Too deep char table");
        {
          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;
 
        }
       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);
          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
          if (c_function)
            (*c_function) (arg, make_number (c), elt);
          else
@@ -2518,20 +2779,32 @@ map_char_table (c_function, function, subtable, arg, depth, indices)
     }
 }
 
     }
 }
 
+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,
 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];
 
      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;
 }
 
   return Qnil;
 }
 
@@ -2586,9 +2859,10 @@ nconc2 (s1, s2)
 }
 
 DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
 }
 
 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;
 {
      int nargs;
      Lisp_Object *args;
 {
@@ -2613,7 +2887,7 @@ Only the last argument is not altered, and need not be a list.")
       while (CONSP (tem))
        {
          tail = tem;
       while (CONSP (tem))
        {
          tail = tem;
-         tem = Fcdr (tail);
+         tem = XCDR (tail);
          QUIT;
        }
 
          QUIT;
        }
 
@@ -2672,8 +2946,8 @@ mapcar1 (leni, vals, fn, seq)
       for (i = 0; i < leni; i++)
        {
          int byte;
       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;
            dummy = Qt;
          else
            dummy = Qnil;
@@ -2715,11 +2989,11 @@ mapcar1 (leni, vals, fn, seq)
 }
 
 DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
 }
 
 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;
      Lisp_Object function, sequence, separator;
 {
   Lisp_Object len;
@@ -2728,13 +3002,15 @@ SEQUENCE may be a list, a vector, a bool-vector, or a string.")
   register Lisp_Object *args;
   register int i;
   struct gcpro gcpro1;
   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 ("");
 
 
   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);
 
   GCPRO1 (separator);
   mapcar1 (leni, args, function, sequence);
@@ -2746,34 +3022,43 @@ SEQUENCE may be a list, a vector, a bool-vector, or a string.")
   for (i = 1; i < nargs; i += 2)
     args[i] = separator;
 
   for (i = 1; i < nargs; i += 2)
     args[i] = separator;
 
-  return Fconcat (nargs, args);
+  ret = Fconcat (nargs, args);
+  SAFE_FREE_LISP (nargs);
+
+  return ret;
 }
 
 DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
 }
 
 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 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);
 
   len = Flength (sequence);
   leni = XFASTINT (len);
-  args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
+
+  SAFE_ALLOCA_LISP (args, leni);
 
   mapcar1 (leni, args, function, sequence);
 
 
   mapcar1 (leni, args, function, sequence);
 
-  return Flist (leni, args);
+  ret = Flist (leni, args);
+  SAFE_FREE_LISP (leni);
+
+  return ret;
 }
 
 DEFUN ("mapc", Fmapc, Smapc, 2, 2, 0,
 }
 
 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;
      Lisp_Object function, sequence;
 {
   register int leni;
@@ -2787,18 +3072,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,
 /* 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 and `use-dialog-box' is non-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;
      Lisp_Object prompt;
 {
   register Lisp_Object obj, key, def, map;
@@ -2806,13 +3091,13 @@ is nil and `use-dialog-box' is non-nil.")
   Lisp_Object xprompt;
   Lisp_Object args[2];
   struct gcpro gcpro1, gcpro2;
   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"));
 
 
   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);
 
   xprompt = prompt;
   GCPRO2 (prompt, xprompt);
 
@@ -2842,7 +3127,18 @@ is nil and `use-dialog-box' is non-nil.")
 #endif /* HAVE_MENUS */
       cursor_in_echo_area = 1;
       choose_minibuf_frame ();
 #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)
        {
 
       if (minibuffer_auto_raise)
        {
@@ -2927,22 +3223,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,
 /* 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, and `use-dialog-box' is non-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;
 
      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))
 
 #ifdef HAVE_MENUS
   if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
@@ -2973,12 +3269,12 @@ is nil, and `use-dialog-box' is non-nil.")
       ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
                                              Qyes_or_no_p_history, Qnil,
                                              Qnil));
       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"))
+      if (SCHARS (ans) == 3 && !strcmp (SDATA (ans), "yes"))
        {
          UNGCPRO;
          return Qt;
        }
        {
          UNGCPRO;
          return Qt;
        }
-      if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
+      if (SCHARS (ans) == 2 && !strcmp (SDATA (ans), "no"))
        {
          UNGCPRO;
          return Qnil;
        {
          UNGCPRO;
          return Qnil;
@@ -2992,14 +3288,22 @@ is nil, and `use-dialog-box' is non-nil.")
 }
 \f
 DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
 }
 \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];
      Lisp_Object use_floats;
 {
   double load_ave[3];
@@ -3020,82 +3324,144 @@ shortened list, containing only those averages which are available.")
   return ret;
 }
 \f
   return ret;
 }
 \f
-Lisp_Object Vfeatures;
+Lisp_Object Vfeatures, Qsubfeatures;
+extern Lisp_Object Vafter_load_alist;
 
 
-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;
+DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 2, 0,
+       doc: /* Returns t if FEATURE is present in this Emacs.
+
+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;
 {
   register Lisp_Object tem;
-  CHECK_SYMBOL (feature, 0);
+  CHECK_SYMBOL (feature);
   tem = Fmemq (feature, Vfeatures);
   tem = Fmemq (feature, Vfeatures);
+  if (!NILP (tem) && !NILP (subfeature))
+    tem = Fmember (subfeature, Fget (feature, Qsubfeatures));
   return (NILP (tem)) ? Qnil : Qt;
 }
 
   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;
 {
   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);
   tem = Fmemq (feature, Vfeatures);
   if (NILP (tem))
     Vfeatures = Fcons (feature, Vfeatures);
   if (!NILP (Vautoload_queue))
     Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), 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));
   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;
 }
   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,
 
 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\
-and `load' will try to load this name appended with the suffix `.elc',\n\
-`.el' or the unmodified name, in that order.\n\
-If the optional third argument NOERROR is non-nil,\n\
-then return nil if the file is not found instead of signaling an error.\n\
-Normally the return value is FEATURE.\n\
-The normal messages at start and end of loading FILENAME are suppressed.")
-  (feature, filename, 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;
      Lisp_Object feature, filename, noerror;
 {
   register Lisp_Object tem;
-  CHECK_SYMBOL (feature, 0);
+  struct gcpro gcpro1, gcpro2;
+
+  CHECK_SYMBOL (feature);
+
   tem = Fmemq (feature, Vfeatures);
 
   tem = Fmemq (feature, Vfeatures);
 
-  LOADHIST_ATTACH (Fcons (Qrequire, feature));
-  
   if (NILP (tem))
     {
   if (NILP (tem))
     {
-      int count = specpdl_ptr - specpdl;
+      int count = SPECPDL_INDEX ();
+      int nesting = 0;
+
+      LOADHIST_ATTACH (Fcons (Qrequire, feature));
+
+      /* 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;
 
 
       /* Value saved here is to be restored into Vautoload_queue */
       record_unwind_protect (un_autoload, Vautoload_queue);
       Vautoload_queue = Qt;
 
+      /* Load the file.  */
+      GCPRO2 (feature, filename);
       tem = Fload (NILP (filename) ? Fsymbol_name (feature) : filename,
                   noerror, Qt, Qnil, (NILP (filename) ? Qt : Qnil));
       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))
       /* 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);
     }
 
       /* Once loading finishes, don't undo it.  */
       Vautoload_queue = Qt;
       feature = unbind_to (count, feature);
     }
+
   return feature;
 }
 \f
   return feature;
 }
 \f
@@ -3107,13 +3473,13 @@ The normal messages at start and end of loading FILENAME are suppressed.")
    for the sole reason of efficiency.  */
 
 DEFUN ("plist-member", Fplist_member, Splist_member, 2, 2, 0,
    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))
      Lisp_Object plist, prop;
 {
   while (CONSP (plist) && !EQ (XCAR (plist), prop))
@@ -3126,21 +3492,21 @@ The value is actually the tail of PLIST whose car is PROP.")
 }
 
 DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
 }
 
 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;
 {
      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,
   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;
      Lisp_Object widget, property;
 {
   Lisp_Object tmp;
@@ -3149,7 +3515,7 @@ later with `widget-put'.")
     {
       if (NILP (widget))
        return Qnil;
     {
       if (NILP (widget))
        return Qnil;
-      CHECK_CONS (widget, 1);
+      CHECK_CONS (widget);
       tmp = Fplist_member (XCDR (widget), property);
       if (CONSP (tmp))
        {
       tmp = Fplist_member (XCDR (widget), property);
       if (CONSP (tmp))
        {
@@ -3164,9 +3530,10 @@ later with `widget-put'.")
 }
 
 DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
 }
 
 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;
 {
      int nargs;
      Lisp_Object *args;
 {
@@ -3183,6 +3550,92 @@ ARGS are passed as extra arguments to the function.")
   UNGCPRO;
   return result;
 }
   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 (RFC 2045).
    Based on code from GNU recode. */
 \f
 /* base64 encode/decode functions (RFC 2045).
    Based on code from GNU recode. */
@@ -3213,10 +3666,6 @@ ARGS are passed as extra arguments to the function.")
     }                                  \
   while (IS_BASE64_IGNORABLE (c))
 
     }                                  \
   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] =
 {
 /* Table of characters coding the 64 values.  */
 static char base64_value_to_char[64] =
 {
@@ -3271,10 +3720,10 @@ 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",
 
 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;
 {
      (beg, end, no_line_break)
      Lisp_Object beg, end, no_line_break;
 {
@@ -3282,6 +3731,7 @@ into shorter lines.")
   int allength, length;
   int ibeg, iend, encoded_length;
   int old_pos = PT;
   int allength, length;
   int ibeg, iend, encoded_length;
   int old_pos = PT;
+  USE_SAFE_ALLOCA;
 
   validate_region (&beg, &end);
 
 
   validate_region (&beg, &end);
 
@@ -3296,10 +3746,7 @@ into shorter lines.")
   allength = length + length/3 + 1;
   allength += allength / MIME_LINE_LENGTH + 1 + 6;
 
   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));
   encoded_length = base64_encode_1 (BYTE_POS_ADDR (ibeg), encoded, length,
                                    NILP (no_line_break),
                                    !NILP (current_buffer->enable_multibyte_characters));
@@ -3309,8 +3756,7 @@ into shorter lines.")
   if (encoded_length < 0)
     {
       /* The encoding wasn't possible. */
   if (encoded_length < 0)
     {
       /* The encoding wasn't possible. */
-      if (length > MAX_ALLOCA)
-       xfree (encoded);
+      SAFE_FREE (allength);
       error ("Multibyte character in data for base64 encoding");
     }
 
       error ("Multibyte character in data for base64 encoding");
     }
 
@@ -3318,8 +3764,7 @@ into shorter lines.")
      and delete the old.  (Insert first in order to preserve markers.)  */
   SET_PT_BOTH (XFASTINT (beg), ibeg);
   insert (encoded, encoded_length);
      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 (allength);
   del_range_byte (ibeg + encoded_length, iend + encoded_length, 1);
 
   /* If point was outside of the region, restore it exactly; else just
   del_range_byte (ibeg + encoded_length, iend + encoded_length, 1);
 
   /* If point was outside of the region, restore it exactly; else just
@@ -3336,32 +3781,30 @@ into shorter lines.")
 
 DEFUN ("base64-encode-string", Fbase64_encode_string, Sbase64_encode_string,
        1, 2, 0,
 
 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;
      (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. */
 
   /* 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. */
   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)
                                    encoded, length, NILP (no_line_break),
                                    STRING_MULTIBYTE (string));
   if (encoded_length > allength)
@@ -3370,14 +3813,12 @@ into shorter lines.")
   if (encoded_length < 0)
     {
       /* The encoding wasn't possible. */
   if (encoded_length < 0)
     {
       /* The encoding wasn't possible. */
-      if (length > MAX_ALLOCA)
-       xfree (encoded);
+      SAFE_FREE (allength);
       error ("Multibyte character in data for base64 encoding");
     }
 
   encoded_string = make_unibyte_string (encoded, encoded_length);
       error ("Multibyte character in data for base64 encoding");
     }
 
   encoded_string = make_unibyte_string (encoded, encoded_length);
-  if (allength > MAX_ALLOCA)
-    xfree (encoded);
+  SAFE_FREE (allength);
 
   return encoded_string;
 }
 
   return encoded_string;
 }
@@ -3477,10 +3918,10 @@ base64_encode_1 (from, to, length, line_break, multibyte)
 
 
 DEFUN ("base64-decode-region", Fbase64_decode_region, Sbase64_decode_region,
 
 
 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;
 {
      (beg, end)
      Lisp_Object beg, end;
 {
@@ -3490,6 +3931,7 @@ If the region can't be decoded, signal an error and don't modify the buffer.")
   int decoded_length;
   int inserted_chars;
   int multibyte = !NILP (current_buffer->enable_multibyte_characters);
   int decoded_length;
   int inserted_chars;
   int multibyte = !NILP (current_buffer->enable_multibyte_characters);
+  USE_SAFE_ALLOCA;
 
   validate_region (&beg, &end);
 
 
   validate_region (&beg, &end);
 
@@ -3502,10 +3944,7 @@ If the region can't be decoded, signal an error and don't modify the buffer.")
      working on a multibyte buffer, each decoded code may occupy at
      most two bytes.  */
   allength = multibyte ? length * 2 : length;
      working on a multibyte buffer, each decoded code may occupy at
      most two bytes.  */
   allength = multibyte ? length * 2 : length;
-  if (allength <= MAX_ALLOCA)
-    decoded = (char *) alloca (allength);
-  else
-    decoded = (char *) xmalloc (allength);
+  SAFE_ALLOCA (decoded, char *, allength);
 
   move_gap_both (XFASTINT (beg), ibeg);
   decoded_length = base64_decode_1 (BYTE_POS_ADDR (ibeg), decoded, length,
 
   move_gap_both (XFASTINT (beg), ibeg);
   decoded_length = base64_decode_1 (BYTE_POS_ADDR (ibeg), decoded, length,
@@ -3516,8 +3955,7 @@ If the region can't be decoded, signal an error and don't modify the buffer.")
   if (decoded_length < 0)
     {
       /* The decoding wasn't possible. */
   if (decoded_length < 0)
     {
       /* The decoding wasn't possible. */
-      if (allength > MAX_ALLOCA)
-       xfree (decoded);
+      SAFE_FREE (allength);
       error ("Invalid base64 data");
     }
 
       error ("Invalid base64 data");
     }
 
@@ -3525,8 +3963,8 @@ If the region can't be decoded, signal an error and don't modify the buffer.")
      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);
      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 (allength > MAX_ALLOCA)
-    xfree (decoded);
+  SAFE_FREE (allength);
+
   /* Delete the original text.  */
   del_range_both (PT, PT_BYTE, XFASTINT (end) + inserted_chars,
                  iend + decoded_length, 1);
   /* Delete the original text.  */
   del_range_both (PT, PT_BYTE, XFASTINT (end) + inserted_chars,
                  iend + decoded_length, 1);
@@ -3544,25 +3982,23 @@ 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,
 
 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;
      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. */
   /* 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);
 
   /* The decoded result should be unibyte. */
 
   /* The decoded result should be unibyte. */
-  decoded_length = base64_decode_1 (XSTRING (string)->data, decoded, length,
+  decoded_length = base64_decode_1 (SDATA (string), decoded, length,
                                    0, NULL);
   if (decoded_length > length)
     abort ();
                                    0, NULL);
   if (decoded_length > length)
     abort ();
@@ -3571,8 +4007,7 @@ DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string,
   else
     decoded_string = Qnil;
 
   else
     decoded_string = Qnil;
 
-  if (length > MAX_ALLOCA)
-    xfree (decoded);
+  SAFE_FREE (length);
   if (!STRINGP (decoded_string))
     error ("Invalid base64 data");
 
   if (!STRINGP (decoded_string))
     error ("Invalid base64 data");
 
@@ -3690,32 +4125,6 @@ base64_decode_1 (from, to, length, multibyte, nchars_return)
    if a `:linear-search t' argument is given to make-hash-table.  */
 
 
    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;
 /* The list of all weak hash tables.  Don't staticpro this one.  */
 
 Lisp_Object Vweak_hash_tables;
@@ -3761,7 +4170,7 @@ static struct Lisp_Hash_Table *
 check_hash_table (obj)
      Lisp_Object obj;
 {
 check_hash_table (obj)
      Lisp_Object obj;
 {
-  CHECK_HASH_TABLE (obj, 0);
+  CHECK_HASH_TABLE (obj);
   return XHASH_TABLE (obj);
 }
 
   return XHASH_TABLE (obj);
 }
 
@@ -3909,7 +4318,7 @@ hashfn_eq (h, key)
      Lisp_Object key;
 {
   unsigned hash = XUINT (key) ^ XGCTYPE (key);
      Lisp_Object key;
 {
   unsigned hash = XUINT (key) ^ XGCTYPE (key);
-  xassert ((hash & ~VALMASK) == 0);
+  xassert ((hash & ~INTMASK) == 0);
   return hash;
 }
 
   return hash;
 }
 
@@ -3928,7 +4337,7 @@ hashfn_eql (h, key)
     hash = sxhash (key, 0);
   else
     hash = XUINT (key) ^ XGCTYPE (key);
     hash = sxhash (key, 0);
   else
     hash = XUINT (key) ^ XGCTYPE (key);
-  xassert ((hash & ~VALMASK) == 0);
+  xassert ((hash & ~INTMASK) == 0);
   return hash;
 }
 
   return hash;
 }
 
@@ -3943,7 +4352,7 @@ hashfn_equal (h, key)
      Lisp_Object key;
 {
   unsigned hash = sxhash (key, 0);
      Lisp_Object key;
 {
   unsigned hash = sxhash (key, 0);
-  xassert ((hash & ~VALMASK) == 0);
+  xassert ((hash & ~INTMASK) == 0);
   return hash;
 }
 
   return hash;
 }
 
@@ -4087,7 +4496,7 @@ copy_hash_table (h1)
 {
   Lisp_Object table;
   struct Lisp_Hash_Table *h2;
 {
   Lisp_Object table;
   struct Lisp_Hash_Table *h2;
-  struct Lisp_Vector *v, *next;
+  struct Lisp_Vector *next;
 
   h2 = allocate_hash_table ();
   next = h2->vec_next;
 
   h2 = allocate_hash_table ();
   next = h2->vec_next;
@@ -4130,7 +4539,7 @@ maybe_resize_hash_table (h)
       index_size = next_almost_prime ((int)
                                      (new_size
                                       / XFLOATINT (h->rehash_threshold)));
       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);
        error ("Hash table too large to resize");
 
       h->key_and_value = larger_vector (h->key_and_value, 2 * new_size, Qnil);
@@ -4220,7 +4629,7 @@ hash_put (h, key, value, hash)
 {
   int start_of_bucket, i;
 
 {
   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);
 
   /* Increment count after resizing because resizing may fail.  */
   maybe_resize_hash_table (h);
@@ -4395,13 +4804,13 @@ sweep_weak_table (h, remove_entries_p)
                  /* Make sure key and value survive.  */
                  if (!key_known_to_survive_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)
                    {
                      marked = 1;
                    }
 
                  if (!value_known_to_survive_p)
                    {
-                     mark_object (&HASH_VALUE (h, i));
+                     mark_object (HASH_VALUE (h, i));
                      marked = 1;
                    }
                }
                      marked = 1;
                    }
                }
@@ -4446,7 +4855,7 @@ sweep_weak_hash_tables ()
     {
       h = XHASH_TABLE (table);
       next = h->next_weak;
     {
       h = XHASH_TABLE (table);
       next = h->next_weak;
-      
+
       if (h->size & ARRAY_MARK_FLAG)
        {
          /* TABLE is marked as used.  Sweep its contents.  */
       if (h->size & ARRAY_MARK_FLAG)
        {
          /* TABLE is marked as used.  Sweep its contents.  */
@@ -4505,7 +4914,7 @@ sxhash_string (ptr, len)
       hash = ((hash << 3) + (hash >> 28) + c);
     }
 
       hash = ((hash << 3) + (hash >> 28) + c);
     }
 
-  return hash & VALMASK;
+  return hash & INTMASK;
 }
 
 
 }
 
 
@@ -4573,7 +4982,7 @@ sxhash_bool_vector (vec)
 
 
 /* Return a hash code for OBJ.  DEPTH is the current depth in the Lisp
 
 
 /* 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)
 
 unsigned
 sxhash (obj, depth)
@@ -4592,8 +5001,8 @@ sxhash (obj, depth)
       break;
 
     case Lisp_Symbol:
       break;
 
     case Lisp_Symbol:
-      hash = sxhash_string (XSYMBOL (obj)->name->data,
-                           XSYMBOL (obj)->name->size);
+      hash = sxhash_string (SDATA (SYMBOL_NAME (obj)),
+                           SCHARS (SYMBOL_NAME (obj)));
       break;
 
     case Lisp_Misc:
       break;
 
     case Lisp_Misc:
@@ -4601,7 +5010,7 @@ sxhash (obj, depth)
       break;
 
     case Lisp_String:
       break;
 
     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.  */
       break;
 
       /* This can be everything from a vector to an overlay.  */
@@ -4637,7 +5046,7 @@ sxhash (obj, depth)
       abort ();
     }
 
       abort ();
     }
 
-  return hash & VALMASK;
+  return hash & INTMASK;
 }
 
 
 }
 
 
@@ -4648,8 +5057,8 @@ sxhash (obj, depth)
 
 
 DEFUN ("sxhash", Fsxhash, Ssxhash, 1, 1, 0,
 
 
 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);;
      Lisp_Object obj;
 {
   unsigned hash = sxhash (obj, 0);;
@@ -4658,34 +5067,38 @@ DEFUN ("sxhash", Fsxhash, Ssxhash, 1, 1, 0,
 
 
 DEFUN ("make-hash-table", Fmake_hash_table, Smake_hash_table, 0, MANY, 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;
 {
      int nargs;
      Lisp_Object *args;
 {
@@ -4708,19 +5121,21 @@ to `key-and-value'.  Default value of WEAK is nil.")
       Lisp_Object prop;
 
       prop = Fget (test, Qhash_table_test);
       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));
        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);
     }
   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));
     Fsignal (Qerror,
             list2 (build_string ("Invalid hash table size"),
                    size));
@@ -4770,33 +5185,18 @@ to `key-and-value'.  Default value of WEAK is nil.")
 
 
 DEFUN ("copy-hash-table", Fcopy_hash_table, Scopy_hash_table, 1, 1, 0,
 
 
 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));
 }
 
 
      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,
 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;
 }
 {
   return check_hash_table (table)->count;
 }
@@ -4804,9 +5204,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,
 
 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;
 }
 {
   return check_hash_table (table)->rehash_size;
 }
@@ -4814,20 +5214,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,
 
 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 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);
        Lisp_Object table;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4836,9 +5236,9 @@ without need for resizing.")
 
 
 DEFUN ("hash-table-test", Fhash_table_test, Shash_table_test, 1, 1, 0,
 
 
 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;
 }
 {
   return check_hash_table (table)->test;
 }
@@ -4846,17 +5246,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,
 
 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 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;
      Lisp_Object obj;
 {
   return HASH_TABLE_P (obj) ? Qt : Qnil;
@@ -4864,8 +5264,8 @@ DEFUN ("hash-table-p", Fhash_table_p, Shash_table_p, 1, 1, 0,
 
 
 DEFUN ("clrhash", Fclrhash, Sclrhash, 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));
      Lisp_Object table;
 {
   hash_clear (check_hash_table (table));
@@ -4874,9 +5274,9 @@ DEFUN ("clrhash", Fclrhash, Sclrhash, 1, 1, 0,
 
 
 DEFUN ("gethash", Fgethash, Sgethash, 2, 3, 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);
      Lisp_Object key, table, dflt;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4886,10 +5286,10 @@ If KEY is not found, return DFLT which defaults to nil.")
 
 
 DEFUN ("puthash", Fputhash, Sputhash, 3, 3, 0,
 
 
 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);
      Lisp_Object key, value, table;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4907,8 +5307,8 @@ VALUE.")
 
 
 DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0,
 
 
 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);
      Lisp_Object key, table;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4918,9 +5318,9 @@ DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0,
 
 
 DEFUN ("maphash", Fmaphash, Smaphash, 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 2 arguments KEY and VALUE.  */)
+     (function, table)
      Lisp_Object function, table;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
      Lisp_Object function, table;
 {
   struct Lisp_Hash_Table *h = check_hash_table (table);
@@ -4942,16 +5342,17 @@ 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,
 
 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));
      Lisp_Object name, test, hash;
 {
   return Fput (name, Qhash_table_test, list2 (test, hash));
@@ -4967,32 +5368,33 @@ integers, including negative integers.")
 #include "coding.h"
 
 DEFUN ("md5", Fmd5, Smd5, 1, 5, 0,
 #include "coding.h"
 
 DEFUN ("md5", Fmd5, Smd5, 1, 5, 0,
-  "Return MD5 message digest of OBJECT, a buffer or string.\n\
-A message digest is a cryptographic checksum of a document,\n\
-and the algorithm to calculate it is defined in RFC 1321.\n\
-\n\
-The two optional arguments START and END are character positions\n\
-specifying for which part of OBJECT the message digest should be computed.\n\
-If nil or omitted, the digest is computed for the whole OBJECT.\n\
-\n\
-The MD5 message digest is computed from the result of encoding the\n\
-text in a coding system, not directly from the internal Emacs form\n\
-of the text.  The optional fourth argument CODING-SYSTEM specifies\n\
-which coding system to encode the text with.  It should be the same\n\
-coding system that you used or will use when actually writing the text\n\
-into a file.\n\
-\n\
-If CODING-SYSTEM is nil or omitted, the default depends on OBJECT.\n\
-If OBJECT is a buffer, the default for CODING-SYSTEM is whatever\n\
-coding system would be chosen by default for writing this text\n\
-into a file.\n\
-\n\
-If OBJECT is a string, the most preferred coding system (see the\n\
-command `prefer-coding-system') is used.\n\
-\n\
-If NOERROR is non-nil, silently assume the `raw_text' coding if the\n\
-guesswork fails.  Normally, an error is signaled in such case.")
-  (object, start, end, coding_system, noerror)
+       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];
      Lisp_Object object, start, end, coding_system, noerror;
 {
   unsigned char digest[16];
@@ -5014,15 +5416,15 @@ guesswork fails.  Normally, an error is signaled in such case.")
 
          if (STRING_MULTIBYTE (object))
            /* use default, we can't guess correct value */
 
          if (STRING_MULTIBYTE (object))
            /* use default, we can't guess correct value */
-           coding_system = XSYMBOL (XCAR (Vcoding_category_list))->value;
-         else 
+           coding_system = SYMBOL_VALUE (XCAR (Vcoding_category_list));
+         else
            coding_system = Qraw_text;
        }
            coding_system = Qraw_text;
        }
-      
+
       if (NILP (Fcoding_system_p (coding_system)))
        {
          /* Invalid coding system.  */
       if (NILP (Fcoding_system_p (coding_system)))
        {
          /* Invalid coding system.  */
-         
+
          if (!NILP (noerror))
            coding_system = Qraw_text;
          else
          if (!NILP (noerror))
            coding_system = Qraw_text;
          else
@@ -5033,12 +5435,12 @@ guesswork fails.  Normally, an error is signaled in such case.")
       if (STRING_MULTIBYTE (object))
        object = code_convert_string1 (object, coding_system, Qnil, 1);
 
       if (STRING_MULTIBYTE (object))
        object = code_convert_string1 (object, coding_system, Qnil, 1);
 
-      size = XSTRING (object)->size;
-      size_byte = STRING_BYTES (XSTRING (object));
+      size = SCHARS (object);
+      size_byte = SBYTES (object);
 
       if (!NILP (start))
        {
 
       if (!NILP (start))
        {
-         CHECK_NUMBER (start, 1);
+         CHECK_NUMBER (start);
 
          start_char = XINT (start);
 
 
          start_char = XINT (start);
 
@@ -5055,51 +5457,57 @@ guesswork fails.  Normally, an error is signaled in such case.")
        }
       else
        {
        }
       else
        {
-         CHECK_NUMBER (end, 2);
-         
+         CHECK_NUMBER (end);
+
          end_char = XINT (end);
 
          if (end_char < 0)
            end_char += size;
          end_char = XINT (end);
 
          if (end_char < 0)
            end_char += size;
-         
+
          end_byte = string_char_to_byte (object, end_char);
        }
          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
     {
       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
     {
-      CHECK_BUFFER (object, 0);
+      struct buffer *prev = current_buffer;
+
+      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+
+      CHECK_BUFFER (object);
 
       bp = XBUFFER (object);
 
       bp = XBUFFER (object);
-         
+      if (bp != current_buffer)
+       set_buffer_internal (bp);
+
       if (NILP (start))
       if (NILP (start))
-       b = BUF_BEGV (bp);
+       b = BEGV;
       else
        {
       else
        {
-         CHECK_NUMBER_COERCE_MARKER (start, 0);
+         CHECK_NUMBER_COERCE_MARKER (start);
          b = XINT (start);
        }
 
       if (NILP (end))
          b = XINT (start);
        }
 
       if (NILP (end))
-       e = BUF_ZV (bp);
+       e = ZV;
       else
        {
       else
        {
-         CHECK_NUMBER_COERCE_MARKER (end, 1);
+         CHECK_NUMBER_COERCE_MARKER (end);
          e = XINT (end);
        }
          e = XINT (end);
        }
-      
+
       if (b > e)
        temp = b, b = e, e = temp;
       if (b > e)
        temp = b, b = e, e = temp;
-      
-      if (!(BUF_BEGV (bp) <= b && e <= BUF_ZV (bp)))
+
+      if (!(BEGV <= b && e <= ZV))
        args_out_of_range (start, end);
        args_out_of_range (start, end);
-      
+
       if (NILP (coding_system))
        {
       if (NILP (coding_system))
        {
-         /* Decide the coding-system to encode the data with. 
+         /* Decide the coding-system to encode the data with.
             See fileio.c:Fwrite-region */
 
          if (!NILP (Vcoding_system_for_write))
             See fileio.c:Fwrite-region */
 
          if (!NILP (Vcoding_system_for_write))
@@ -5121,7 +5529,7 @@ guesswork fails.  Normally, an error is signaled in such case.")
                {
                  /* Check file-coding-system-alist.  */
                  Lisp_Object args[4], val;
                {
                  /* 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);
                  args[0] = Qwrite_region; args[1] = start; args[2] = end;
                  args[3] = Fbuffer_file_name(object);
                  val = Ffind_operation_coding_system (4, args);
@@ -5140,9 +5548,9 @@ guesswork fails.  Normally, an error is signaled in such case.")
              if (!force_raw_text
                  && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
                /* Confirm that VAL can surely encode the current region.  */
              if (!force_raw_text
                  && !NILP (Ffboundp (Vselect_safe_coding_system_function)))
                /* Confirm that VAL can surely encode the current region.  */
-               coding_system = call3 (Vselect_safe_coding_system_function,
+               coding_system = call4 (Vselect_safe_coding_system_function,
                                       make_number (b), make_number (e),
                                       make_number (b), make_number (e),
-                                      coding_system);
+                                      coding_system, Qnil);
 
              if (force_raw_text)
                coding_system = Qraw_text;
 
              if (force_raw_text)
                coding_system = Qraw_text;
@@ -5161,13 +5569,18 @@ guesswork fails.  Normally, an error is signaled in such case.")
        }
 
       object = make_buffer_string (b, e, 0);
        }
 
       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);
     }
 
 
       if (STRING_MULTIBYTE (object))
        object = code_convert_string1 (object, coding_system, Qnil, 1);
     }
 
-  md5_buffer (XSTRING (object)->data + start_byte, 
-             STRING_BYTES(XSTRING (object)) - (size_byte - end_byte), 
+  md5_buffer (SDATA (object) + start_byte,
+             SBYTES (object) - (size_byte - end_byte),
              digest);
 
   for (i = 0; i < 16; i++)
              digest);
 
   for (i = 0; i < 16; i++)
@@ -5214,7 +5627,6 @@ syms_of_fns ()
   defsubr (&Ssxhash);
   defsubr (&Smake_hash_table);
   defsubr (&Scopy_hash_table);
   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);
   defsubr (&Shash_table_count);
   defsubr (&Shash_table_rehash_size);
   defsubr (&Shash_table_rehash_threshold);
@@ -5245,19 +5657,42 @@ syms_of_fns ()
   staticpro (&string_char_byte_cache_string);
   string_char_byte_cache_string = Qnil;
 
   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,
   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'.");
+    doc: /* A list of symbols which are the features of the executing emacs.
+Used by `featurep' and `require', and altered by `provide'.  */);
   Vfeatures = Qnil;
   Vfeatures = 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,
 
   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;
 
   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);
   defsubr (&Sidentity);
   defsubr (&Srandom);
   defsubr (&Slength);
@@ -5274,8 +5709,10 @@ invoked by mouse clicks and mouse menu items.");
   defsubr (&Sstring_make_unibyte);
   defsubr (&Sstring_as_multibyte);
   defsubr (&Sstring_as_unibyte);
   defsubr (&Sstring_make_unibyte);
   defsubr (&Sstring_as_multibyte);
   defsubr (&Sstring_as_unibyte);
+  defsubr (&Sstring_to_multibyte);
   defsubr (&Scopy_alist);
   defsubr (&Ssubstring);
   defsubr (&Scopy_alist);
   defsubr (&Ssubstring);
+  defsubr (&Ssubstring_no_properties);
   defsubr (&Snthcdr);
   defsubr (&Snth);
   defsubr (&Selt);
   defsubr (&Snthcdr);
   defsubr (&Snth);
   defsubr (&Selt);
@@ -5294,8 +5731,13 @@ invoked by mouse clicks and mouse menu items.");
   defsubr (&Sget);
   defsubr (&Splist_put);
   defsubr (&Sput);
   defsubr (&Sget);
   defsubr (&Splist_put);
   defsubr (&Sput);
+  defsubr (&Slax_plist_get);
+  defsubr (&Slax_plist_put);
+  defsubr (&Seql);
   defsubr (&Sequal);
   defsubr (&Sequal);
+  defsubr (&Sequal_including_properties);
   defsubr (&Sfillarray);
   defsubr (&Sfillarray);
+  defsubr (&Sclear_string);
   defsubr (&Schar_table_subtype);
   defsubr (&Schar_table_parent);
   defsubr (&Sset_char_table_parent);
   defsubr (&Schar_table_subtype);
   defsubr (&Schar_table_parent);
   defsubr (&Sset_char_table_parent);
@@ -5325,6 +5767,7 @@ invoked by mouse clicks and mouse menu items.");
   defsubr (&Sbase64_encode_string);
   defsubr (&Sbase64_decode_string);
   defsubr (&Smd5);
   defsubr (&Sbase64_encode_string);
   defsubr (&Sbase64_decode_string);
   defsubr (&Smd5);
+  defsubr (&Slocale_info);
 }
 
 
 }
 
 
@@ -5333,3 +5776,6 @@ init_fns ()
 {
   Vweak_hash_tables = Qnil;
 }
 {
   Vweak_hash_tables = Qnil;
 }
+
+/* arch-tag: 787f8219-5b74-46bd-8469-7e1cc475fa31
+   (do not change this comment) */