(translate_char): Accept list of translation tables.
[bpt/emacs.git] / src / fns.c
index ce8efbf..fa99293 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -1,5 +1,5 @@
 /* Random utility Lisp functions.
-   Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 98, 99, 2000, 2001, 2002
+   Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 98, 99, 2000, 2001, 02, 2003
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -26,15 +26,20 @@ Boston, MA 02111-1307, USA.  */
 #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 *****
 
+#endif  /* ! MAC_OSX */
+
 #include "lisp.h"
 #include "commands.h"
-#include "charset.h"
-
+#include "character.h"
+#include "coding.h"
 #include "buffer.h"
 #include "keyboard.h"
 #include "keymap.h"
@@ -47,7 +52,7 @@ Boston, MA 02111-1307, USA.  */
 #endif
 
 #ifndef NULL
-#define NULL (void *)0
+#define NULL ((POINTER_TYPE *)0)
 #endif
 
 /* Nonzero enables use of dialog boxes for questions
@@ -56,11 +61,13 @@ int use_dialog_box;
 
 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 Qcodeset, Qdays, Qmonths, Qpaper;
 
 extern Lisp_Object Qinput_method_function;
 
@@ -201,7 +208,7 @@ which is at least the number of distinct elements. */)
   return length;
 }
 
-DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0, 
+DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0,
        doc: /* Return the number of bytes in STRING.
 If STRING is a multibyte string, this is greater than the length of STRING. */)
      (string)
@@ -443,27 +450,6 @@ usage: (vconcat &rest SEQUENCES)   */)
   return concat (nargs, args, Lisp_Vectorlike, 0);
 }
 
-/* Return a copy of a sub char table ARG.  The elements except for a
-   nested sub char table are not copied.  */
-static Lisp_Object
-copy_sub_char_table (arg)
-     Lisp_Object arg;
-{
-  Lisp_Object copy = make_sub_char_table (XCHAR_TABLE (arg)->defalt);
-  int i;
-
-  /* Copy all the contents.  */
-  bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
-        SUB_CHAR_TABLE_ORDINARY_SLOTS * sizeof (Lisp_Object));
-  /* Recursively copy any sub char-tables in the ordinary slots.  */
-  for (i = 32; i < SUB_CHAR_TABLE_ORDINARY_SLOTS; i++)
-    if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
-      XCHAR_TABLE (copy)->contents[i]
-       = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
-
-  return copy;
-}
-
 
 DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
        doc: /* Return a copy of a list, vector, string or char-table.
@@ -476,24 +462,7 @@ with the original. */)
 
   if (CHAR_TABLE_P (arg))
     {
-      int i;
-      Lisp_Object copy;
-
-      copy = Fmake_char_table (XCHAR_TABLE (arg)->purpose, Qnil);
-      /* Copy all the slots, including the extra ones.  */
-      bcopy (XVECTOR (arg)->contents, XVECTOR (copy)->contents,
-            ((XCHAR_TABLE (arg)->size & PSEUDOVECTOR_SIZE_MASK)
-             * sizeof (Lisp_Object)));
-
-      /* Recursively copy any sub char tables in the ordinary slots
-         for multibyte characters.  */
-      for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS;
-          i < CHAR_TABLE_ORDINARY_SLOTS; i++)
-       if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
-         XCHAR_TABLE (copy)->contents[i]
-           = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
-
-      return copy;
+      return copy_char_table (arg);
     }
 
   if (BOOL_VECTOR_P (arg))
@@ -513,6 +482,7 @@ with the original. */)
   return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
 }
 
+#if 0                          /* unused */
 /* 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.
@@ -533,6 +503,7 @@ count_combining (str, len, i)
   PARSE_MULTIBYTE_SEQ (str + j, len - j, bytes);
   return (bytes <= i - j ? 0 : bytes - (i - j));
 }
+#endif
 
 /* This structure holds information of an argument of `concat' that is
    a string and has text properties to be copied.  */
@@ -616,11 +587,11 @@ concat (nargs, args, target_type, last_special)
            for (i = 0; i < len; i++)
              {
                ch = XVECTOR (this)->contents[i];
-               if (! INTEGERP (ch))
-                 wrong_type_argument (Qintegerp, ch);
+               if (! CHARACTERP (ch))
+                 wrong_type_argument (Qcharacterp, ch);
                this_len_byte = CHAR_BYTES (XINT (ch));
                result_len_byte += this_len_byte;
-               if (!SINGLE_BYTE_CHAR_P (XINT (ch)))
+               if (! ASCII_CHAR_P (XINT (ch)) && ! CHAR_BYTE8_P (XINT (ch)))
                  some_multibyte = 1;
              }
          else if (BOOL_VECTOR_P (this) && XBOOL_VECTOR (this)->size > 0)
@@ -629,11 +600,11 @@ concat (nargs, args, target_type, last_special)
            for (; CONSP (this); this = XCDR (this))
              {
                ch = XCAR (this);
-               if (! INTEGERP (ch))
-                 wrong_type_argument (Qintegerp, ch);
+               if (! CHARACTERP (ch))
+                 wrong_type_argument (Qcharacterp, ch);
                this_len_byte = CHAR_BYTES (XINT (ch));
                result_len_byte += this_len_byte;
-               if (!SINGLE_BYTE_CHAR_P (XINT (ch)))
+               if (! ASCII_CHAR_P (XINT (ch)) && ! CHAR_BYTE8_P (XINT (ch)))
                  some_multibyte = 1;
              }
          else if (STRINGP (this))
@@ -696,25 +667,17 @@ concat (nargs, args, target_type, last_special)
          && STRING_MULTIBYTE (this) == some_multibyte)
        {
          int thislen_byte = SBYTES (this);
-         int combined;
 
          bcopy (SDATA (this), SDATA (val) + toindex_byte,
                 SBYTES (this));
-         combined =  (some_multibyte && toindex_byte > 0
-                      ? count_combining (SDATA (val),
-                                         toindex_byte + thislen_byte,
-                                         toindex_byte)
-                      : 0);
          if (! NULL_INTERVAL_P (STRING_INTERVALS (this)))
            {
              textprops[num_textprops].argnum = argnum;
-             /* We ignore text properties on characters being combined.  */
-             textprops[num_textprops].from = combined;
+             textprops[num_textprops].from = 0;
              textprops[num_textprops++].to = toindex;
            }
          toindex_byte += thislen_byte;
-         toindex += thisleni - combined;
-         STRING_SET_CHARS (val, SCHARS (val) - combined);
+         toindex += thisleni;
        }
       /* Copy a single-byte string to a multibyte string.  */
       else if (STRINGP (this) && STRINGP (val))
@@ -757,9 +720,7 @@ concat (nargs, args, target_type, last_special)
                  {
                    XSETFASTINT (elt, SREF (this, thisindex++));
                    if (some_multibyte
-                       && (XINT (elt) >= 0240
-                           || (XINT (elt) >= 0200
-                               && ! NILP (Vnonascii_translation_table)))
+                       && XINT (elt) >= 0200
                        && XINT (elt) < 0400)
                      {
                        c = unibyte_char_to_multibyte (XINT (elt));
@@ -792,34 +753,12 @@ concat (nargs, args, target_type, last_special)
            else
              {
                CHECK_NUMBER (elt);
-               if (SINGLE_BYTE_CHAR_P (XINT (elt)))
-                 {
-                   if (some_multibyte)
-                     toindex_byte
-                       += CHAR_STRING (XINT (elt),
-                                       SDATA (val) + toindex_byte);
-                   else
-                     SSET (val, toindex_byte++, XINT (elt));
-                   if (some_multibyte
-                       && toindex_byte > 0
-                       && count_combining (SDATA (val),
-                                           toindex_byte, toindex_byte - 1))
-                     STRING_SET_CHARS (val, SCHARS (val) - 1);
-                   else
-                     toindex++;
-                 }
+               if (some_multibyte)
+                 toindex_byte += CHAR_STRING (XINT (elt),
+                                              SDATA (val) + toindex_byte);
                else
-                 /* If we have any multibyte characters,
-                    we already decided to make a multibyte string.  */
-                 {
-                   int c = XINT (elt);
-                   /* P exists as a variable
-                      to avoid a bug on the Masscomp C compiler.  */
-                   unsigned char *p = SDATA (val) + toindex_byte;
-
-                   toindex_byte += CHAR_STRING (c, p);
-                   toindex++;
-                 }
+                 SSET (val, toindex_byte++, XINT (elt));
+               toindex++;
              }
          }
     }
@@ -867,7 +806,7 @@ string_char_to_byte (string, char_index)
      Lisp_Object string;
      int char_index;
 {
-  int i, i_byte;
+  int i_byte;
   int best_below, best_below_byte;
   int best_above, best_above_byte;
 
@@ -894,40 +833,30 @@ string_char_to_byte (string, char_index)
 
   if (char_index - best_below < best_above - char_index)
     {
+      unsigned char *p = SDATA (string) + best_below_byte;
+
       while (best_below < char_index)
        {
-         int c;
-         FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string,
-                                             best_below, best_below_byte);
+         p += BYTES_BY_CHAR_HEAD (*p);
+         best_below++;
        }
-      i = best_below;
-      i_byte = best_below_byte;
+      i_byte = p - SDATA (string);
     }
   else
     {
+      unsigned char *p = SDATA (string) + best_above_byte;
+
       while (best_above > char_index)
        {
-         unsigned char *pend = SDATA (string) + best_above_byte;
-         unsigned char *pbeg = pend - best_above_byte;
-         unsigned char *p = pend - 1;
-         int bytes;
-
-         while (p > pbeg  && !CHAR_HEAD_P (*p)) p--;
-         PARSE_MULTIBYTE_SEQ (p, pend - p, bytes);
-         if (bytes == pend - p)
-           best_above_byte -= bytes;
-         else if (bytes > pend - p)
-           best_above_byte -= (pend - p);
-         else
-           best_above_byte--;
+         p--;
+         while (!CHAR_HEAD_P (*p)) p--;
          best_above--;
        }
-      i = best_above;
-      i_byte = best_above_byte;
+      i_byte = p - SDATA (string);
     }
 
   string_char_byte_cache_bytepos = i_byte;
-  string_char_byte_cache_charpos = i;
+  string_char_byte_cache_charpos = char_index;
   string_char_byte_cache_string = string;
 
   return i_byte;
@@ -967,36 +896,30 @@ string_byte_to_char (string, byte_index)
 
   if (byte_index - best_below_byte < best_above_byte - byte_index)
     {
-      while (best_below_byte < byte_index)
+      unsigned char *p = SDATA (string) + best_below_byte;
+      unsigned char *pend = SDATA (string) + byte_index;
+
+      while (p < pend)
        {
-         int c;
-         FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string,
-                                             best_below, best_below_byte);
+         p += BYTES_BY_CHAR_HEAD (*p);
+         best_below++;
        }
       i = best_below;
-      i_byte = best_below_byte;
+      i_byte = p - SDATA (string);
     }
   else
     {
-      while (best_above_byte > byte_index)
+      unsigned char *p = SDATA (string) + best_above_byte;
+      unsigned char *pbeg = SDATA (string) + byte_index;
+
+      while (p > pbeg)
        {
-         unsigned char *pend = SDATA (string) + best_above_byte;
-         unsigned char *pbeg = pend - best_above_byte;
-         unsigned char *p = pend - 1;
-         int bytes;
-
-         while (p > pbeg  && !CHAR_HEAD_P (*p)) p--;
-         PARSE_MULTIBYTE_SEQ (p, pend - p, bytes);
-         if (bytes == pend - p)
-           best_above_byte -= bytes;
-         else if (bytes > pend - p)
-           best_above_byte -= (pend - p);
-         else
-           best_above_byte--;
+         p--;
+         while (!CHAR_HEAD_P (*p)) p--;
          best_above--;
        }
       i = best_above;
-      i_byte = best_above_byte;
+      i_byte = p - SDATA (string);
     }
 
   string_char_byte_cache_bytepos = i_byte;
@@ -1006,9 +929,7 @@ string_byte_to_char (string, byte_index)
   return i;
 }
 \f
-/* Convert STRING to a multibyte string.
-   Single-byte characters 0240 through 0377 are converted
-   by adding nonascii_insert_offset to each.  */
+/* Convert STRING to a multibyte string.  */
 
 Lisp_Object
 string_make_multibyte (string)
@@ -1034,6 +955,35 @@ string_make_multibyte (string)
   return make_multibyte_string (buf, SCHARS (string), nbytes);
 }
 
+
+/* Convert STRING (if unibyte) to a multibyte string without changing
+   the number of characters.  Characters 0200 trough 0237 are
+   converted to eight-bit characters. */
+
+Lisp_Object
+string_to_multibyte (string)
+     Lisp_Object string;
+{
+  unsigned char *buf;
+  int nbytes;
+
+  if (STRING_MULTIBYTE (string))
+    return string;
+
+  nbytes = parse_str_to_multibyte (SDATA (string), SBYTES (string));
+  /* If all the chars are ASCII, they won't need any more bytes once
+     converted.  */
+  if (nbytes == SBYTES (string))
+    return make_multibyte_string (SDATA (string), nbytes, nbytes);
+
+  buf = (unsigned char *) alloca (nbytes);
+  bcopy (SDATA (string), buf, SBYTES (string));
+  str_to_multibyte (buf, nbytes, SBYTES (string));
+
+  return make_multibyte_string (buf, SCHARS (string), nbytes);
+}
+
+
 /* Convert STRING to a single-byte string.  */
 
 Lisp_Object
@@ -1112,9 +1062,11 @@ DEFUN ("string-as-multibyte", Fstring_as_multibyte, Sstring_as_multibyte,
        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'.  */)
+part of a correct utf-8 sequence), it is converted to the corresponding
+multibyte character of charset `eight-bit'.
+See also `string-to-multibyte'.  */)
      (string)
      Lisp_Object string;
 {
@@ -1139,6 +1091,27 @@ multibyte character of charset `eight-bit-control' or `eight-bit-graphic'.  */)
     }
   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.
+
+If STRING is unibyte and contains an 8-bit byte, it is converted to
+the corresponding multibyte character of charset `eight-bit'.
+
+This differs from `string-as-multibyte' by converting each byte of a correct
+utf-8 sequence to an eight-bit character, not just bytes that don't form a
+correct sequence.  */)
+     (string)
+     Lisp_Object string;
+{
+  CHECK_STRING (string);
+
+  return string_to_multibyte (string);
+}
+
 \f
 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
        doc: /* Return a copy of ALIST.
@@ -1170,7 +1143,7 @@ Elements of ALIST that are not conses are also shared.  */)
 DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
        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.
-If FROM or TO is negative, it counts from the end.
+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)
@@ -1814,7 +1787,10 @@ See also the function `nreverse', which is used more often.  */)
   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;
@@ -1925,7 +1901,7 @@ one of the properties on the list.  */)
      Lisp_Object prop;
 {
   Lisp_Object tail;
-  
+
   for (tail = plist;
        CONSP (tail) && CONSP (XCDR (tail));
        tail = XCDR (XCDR (tail)))
@@ -1941,7 +1917,7 @@ one of the properties on the list.  */)
 
   if (!NILP (tail))
     wrong_type_argument (Qlistp, prop);
-  
+
   return Qnil;
 }
 
@@ -1979,7 +1955,7 @@ The PLIST is modified by side effects.  */)
          Fsetcar (XCDR (tail), val);
          return plist;
        }
-      
+
       prev = tail;
       QUIT;
     }
@@ -2014,7 +1990,7 @@ one of the properties on the list.  */)
      Lisp_Object prop;
 {
   Lisp_Object tail;
-  
+
   for (tail = plist;
        CONSP (tail) && CONSP (XCDR (tail));
        tail = XCDR (XCDR (tail)))
@@ -2027,7 +2003,7 @@ one of the properties on the list.  */)
 
   if (!NILP (tail))
     wrong_type_argument (Qlistp, prop);
-  
+
   return Qnil;
 }
 
@@ -2055,7 +2031,7 @@ The PLIST is modified by side effects.  */)
          Fsetcar (XCDR (tail), val);
          return plist;
        }
-      
+
       prev = tail;
       QUIT;
     }
@@ -2159,7 +2135,8 @@ internal_equal (o1, o2, depth)
           functions are sensible to compare, so eliminate the others now.  */
        if (size & PSEUDOVECTOR_FLAG)
          {
-           if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
+           if (!(size & (PVEC_COMPILED
+                         | PVEC_CHAR_TABLE | PVEC_SUB_CHAR_TABLE)))
              return 0;
            size &= PSEUDOVECTOR_SIZE_MASK;
          }
@@ -2190,7 +2167,7 @@ internal_equal (o1, o2, depth)
     case Lisp_Type_Limit:
       break;
     }
-  
+
   return 0;
 }
 \f
@@ -2213,11 +2190,11 @@ ARRAY is a vector, string, char-table, or bool-vector.  */)
     }
   else if (CHAR_TABLE_P (array))
     {
-      register Lisp_Object *p = XCHAR_TABLE (array)->contents;
-      size = CHAR_TABLE_ORDINARY_SLOTS;
-      for (index = 0; index < size; index++)
-       p[index] = item;
-      XCHAR_TABLE (array)->defalt = Qnil;
+      int i;
+
+      for (i = 0; i < (1 << CHARTAB_SIZE_BITS_0); i++)
+       XCHAR_TABLE (array)->contents[i] = item;
+      XCHAR_TABLE (array)->defalt = item;
     }
   else if (STRINGP (array))
     {
@@ -2265,438 +2242,20 @@ ARRAY is a vector, string, char-table, or bool-vector.  */)
     }
   return array;
 }
-\f
-DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
-       1, 1, 0,
-       doc: /* Return the subtype of char-table CHAR-TABLE.  The value is a symbol.  */)
-     (char_table)
-     Lisp_Object char_table;
-{
-  CHECK_CHAR_TABLE (char_table);
-
-  return XCHAR_TABLE (char_table)->purpose;
-}
 
-DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
+DEFUN ("clear-string", Fclear_string, Sclear_string,
        1, 1, 0,
-       doc: /* Return the parent char-table of CHAR-TABLE.
-The value is either nil or another char-table.
-If CHAR-TABLE holds nil for a given character,
-then the actual applicable value is inherited from the parent char-table
-\(or from its parents, if necessary).  */)
-     (char_table)
-     Lisp_Object char_table;
-{
-  CHECK_CHAR_TABLE (char_table);
-
-  return XCHAR_TABLE (char_table)->parent;
-}
-
-DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
-       2, 2, 0,
-       doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
-PARENT must be either nil or another char-table.  */)
-     (char_table, parent)
-     Lisp_Object char_table, parent;
-{
-  Lisp_Object temp;
-
-  CHECK_CHAR_TABLE (char_table);
-
-  if (!NILP (parent))
-    {
-      CHECK_CHAR_TABLE (parent);
-
-      for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
-       if (EQ (temp, char_table))
-         error ("Attempt to make a chartable be its own parent");
-    }
-
-  XCHAR_TABLE (char_table)->parent = parent;
-
-  return parent;
-}
-
-DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
-       2, 2, 0,
-       doc: /* Return the value of CHAR-TABLE's extra-slot number N.  */)
-     (char_table, n)
-     Lisp_Object char_table, n;
-{
-  CHECK_CHAR_TABLE (char_table);
-  CHECK_NUMBER (n);
-  if (XINT (n) < 0
-      || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
-    args_out_of_range (char_table, n);
-
-  return XCHAR_TABLE (char_table)->extras[XINT (n)];
-}
-
-DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
-       Sset_char_table_extra_slot,
-       3, 3, 0,
-       doc: /* Set CHAR-TABLE's extra-slot number N to VALUE.  */)
-     (char_table, n, value)
-     Lisp_Object char_table, n, value;
-{
-  CHECK_CHAR_TABLE (char_table);
-  CHECK_NUMBER (n);
-  if (XINT (n) < 0
-      || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
-    args_out_of_range (char_table, n);
-
-  return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
-}
-\f
-DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
-       2, 2, 0,
-       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;
-{
-  CHECK_CHAR_TABLE (char_table);
-
-  if (EQ (range, Qnil))
-    return XCHAR_TABLE (char_table)->defalt;
-  else if (INTEGERP (range))
-    return Faref (char_table, range);
-  else if (SYMBOLP (range))
-    {
-      Lisp_Object charset_info;
-
-      charset_info = Fget (range, Qcharset);
-      CHECK_VECTOR (charset_info);
-
-      return Faref (char_table,
-                   make_number (XINT (XVECTOR (charset_info)->contents[0])
-                                + 128));
-    }
-  else if (VECTORP (range))
-    {
-      if (XVECTOR (range)->size == 1)
-       return Faref (char_table,
-                     make_number (XINT (XVECTOR (range)->contents[0]) + 128));
-      else
-       {
-         int size = XVECTOR (range)->size;
-         Lisp_Object *val = XVECTOR (range)->contents;
-         Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
-                                               size <= 1 ? Qnil : val[1],
-                                               size <= 2 ? Qnil : val[2]);
-         return Faref (char_table, ch);
-       }
-    }
-  else
-    error ("Invalid RANGE argument to `char-table-range'");
-  return Qt;
-}
-
-DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
-       3, 3, 0,
-       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 vector which identifies a character set or a row of a character set,
-a coding system, or a character code.  */)
-     (char_table, range, value)
-     Lisp_Object char_table, range, value;
-{
-  int i;
-
-  CHECK_CHAR_TABLE (char_table);
-
-  if (EQ (range, Qt))
-    for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
-      XCHAR_TABLE (char_table)->contents[i] = value;
-  else if (EQ (range, Qnil))
-    XCHAR_TABLE (char_table)->defalt = value;
-  else if (SYMBOLP (range))
-    {
-      Lisp_Object charset_info;
-
-      charset_info = Fget (range, Qcharset);
-      CHECK_VECTOR (charset_info);
-
-      return Faset (char_table,
-                   make_number (XINT (XVECTOR (charset_info)->contents[0])
-                                + 128),
-                   value);
-    }
-  else if (INTEGERP (range))
-    Faset (char_table, range, value);
-  else if (VECTORP (range))
-    {
-      if (XVECTOR (range)->size == 1)
-       return Faset (char_table,
-                     make_number (XINT (XVECTOR (range)->contents[0]) + 128),
-                     value);
-      else
-       {
-         int size = XVECTOR (range)->size;
-         Lisp_Object *val = XVECTOR (range)->contents;
-         Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
-                                               size <= 1 ? Qnil : val[1],
-                                               size <= 2 ? Qnil : val[2]);
-         return Faset (char_table, ch, value);
-       }
-    }
-  else
-    error ("Invalid RANGE argument to `set-char-table-range'");
-
-  return value;
-}
-
-DEFUN ("set-char-table-default", Fset_char_table_default,
-       Sset_char_table_default, 3, 3, 0,
-       doc: /* Set the default value in CHAR-TABLE for a generic character CHAR 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;
-
-  CHECK_CHAR_TABLE (char_table);
-  CHECK_NUMBER (ch);
-
-  c = XINT (ch);
-  SPLIT_CHAR (c, charset, code1, code2);
-
-  /* Since we may want to set the default value for a character set
-     not yet defined, we check only if the character set is in the
-     valid range or not, instead of it is already defined or not.  */
-  if (! CHARSET_VALID_P (charset))
-    invalid_character (c);
-
-  if (charset == CHARSET_ASCII)
-    return (XCHAR_TABLE (char_table)->defalt = value);
-
-  /* Even if C is not a generic char, we had better behave as if a
-     generic char is specified.  */
-  if (!CHARSET_DEFINED_P (charset) || CHARSET_DIMENSION (charset) == 1)
-    code1 = 0;
-  temp = XCHAR_TABLE (char_table)->contents[charset + 128];
-  if (!code1)
-    {
-      if (SUB_CHAR_TABLE_P (temp))
-       XCHAR_TABLE (temp)->defalt = value;
-      else
-       XCHAR_TABLE (char_table)->contents[charset + 128] = value;
-      return value;
-    }
-  if (SUB_CHAR_TABLE_P (temp))
-    char_table = temp;
-  else
-    char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
-                 = make_sub_char_table (temp));
-  temp = XCHAR_TABLE (char_table)->contents[code1];
-  if (SUB_CHAR_TABLE_P (temp))
-    XCHAR_TABLE (temp)->defalt = value;
-  else
-    XCHAR_TABLE (char_table)->contents[code1] = value;
-  return value;
-}
-
-/* Look up the element in TABLE at index CH,
-   and return it as an integer.
-   If the element is nil, return CH itself.
-   (Actually we do that for any non-integer.)  */
-
-int
-char_table_translate (table, ch)
-     Lisp_Object table;
-     int ch;
-{
-  Lisp_Object value;
-  value = Faref (table, make_number (ch));
-  if (! INTEGERP (value))
-    return ch;
-  return XINT (value);
-}
-
-static void
-optimize_sub_char_table (table, chars)
-     Lisp_Object *table;
-     int chars;
-{
-  Lisp_Object elt;
-  int from, to;
-
-  if (chars == 94)
-    from = 33, to = 127;
-  else
-    from = 32, to = 128;
-
-  if (!SUB_CHAR_TABLE_P (*table))
-    return;
-  elt = XCHAR_TABLE (*table)->contents[from++];
-  for (; from < to; from++)
-    if (NILP (Fequal (elt, XCHAR_TABLE (*table)->contents[from])))
-      return;
-  *table = elt;
-}
-
-DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
-       1, 1, 0, doc: /* Optimize char table TABLE.  */)
-     (table)
-     Lisp_Object table;
-{
-  Lisp_Object elt;
-  int dim;
-  int i, j;
-
-  CHECK_CHAR_TABLE (table);
-
-  for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
-    {
-      elt = XCHAR_TABLE (table)->contents[i];
-      if (!SUB_CHAR_TABLE_P (elt))
-       continue;
-      dim = CHARSET_DIMENSION (i - 128);
-      if (dim == 2)
-       for (j = 32; j < SUB_CHAR_TABLE_ORDINARY_SLOTS; j++)
-         optimize_sub_char_table (XCHAR_TABLE (elt)->contents + j, dim);
-      optimize_sub_char_table (XCHAR_TABLE (table)->contents + i, dim);
-    }
-  return Qnil;
-}
-
-\f
-/* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
-   character or group of characters that share a value.
-   DEPTH is the current depth in the originally specified
-   chartable, and INDICES contains the vector indices
-   for the levels our callers have descended.
-
-   ARG is passed to C_FUNCTION when that is called.  */
-
-void
-map_char_table (c_function, function, subtable, arg, depth, indices)
-     void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
-     Lisp_Object function, subtable, arg, *indices;
-     int depth;
-{
-  int i, to;
-
-  if (depth == 0)
-    {
-      /* At first, handle ASCII and 8-bit European characters.  */
-      for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
-       {
-         Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
-         if (c_function)
-           (*c_function) (arg, make_number (i), elt);
-         else
-           call2 (function, make_number (i), elt);
-       }
-#if 0 /* If the char table has entries for higher characters,
-        we should report them.  */
-      if (NILP (current_buffer->enable_multibyte_characters))
-       return;
-#endif
-      to = CHAR_TABLE_ORDINARY_SLOTS;
-    }
-  else
-    {
-      int charset = XFASTINT (indices[0]) - 128;
-
-      i = 32;
-      to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
-      if (CHARSET_CHARS (charset) == 94)
-       i++, to--;
-    }
-
-  for (; i < to; i++)
-    {
-      Lisp_Object elt;
-      int charset;
-
-      elt = XCHAR_TABLE (subtable)->contents[i];
-      XSETFASTINT (indices[depth], i);
-      charset = XFASTINT (indices[0]) - 128;
-      if (depth == 0
-         && (!CHARSET_DEFINED_P (charset)
-             || charset == CHARSET_8_BIT_CONTROL
-             || charset == CHARSET_8_BIT_GRAPHIC))
-       continue;
-
-      if (SUB_CHAR_TABLE_P (elt))
-       {
-         if (depth >= 3)
-           error ("Too deep char table");
-         map_char_table (c_function, function, elt, arg, depth + 1, indices);
-       }
-      else
-       {
-         int c1, c2, c;
-
-         if (NILP (elt))
-           elt = XCHAR_TABLE (subtable)->defalt;
-         c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
-         c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
-         c = MAKE_CHAR (charset, c1, c2);
-         if (c_function)
-           (*c_function) (arg, make_number (c), elt);
-         else
-           call2 (function, make_number (c), elt);
-       }
-    }
-}
-
-DEFUN ("map-char-table", Fmap_char_table, Smap_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;
+       doc: /* Clear the contents of STRING.
+This makes STRING unibyte and may change its length.  */)
+     (string)
+     Lisp_Object string;
 {
-  /* The depth of char table is at most 3. */
-  Lisp_Object indices[3];
-
-  CHECK_CHAR_TABLE (char_table);
-
-  map_char_table ((void *) call2, Qnil, char_table, function, 0, indices);
+  int len = SBYTES (string);
+  bzero (SDATA (string), len);
+  STRING_SET_CHARS (string, len);
+  STRING_SET_UNIBYTE (string);
   return Qnil;
 }
-
-/* Return a value for character C in char-table TABLE.  Store the
-   actual index for that value in *IDX.  Ignore the default value of
-   TABLE.  */
-
-Lisp_Object
-char_table_ref_and_index (table, c, idx)
-     Lisp_Object table;
-     int c, *idx;
-{
-  int charset, c1, c2;
-  Lisp_Object elt;
-
-  if (SINGLE_BYTE_CHAR_P (c))
-    {
-      *idx = c;
-      return XCHAR_TABLE (table)->contents[c];
-    }
-  SPLIT_CHAR (c, charset, c1, c2);
-  elt = XCHAR_TABLE (table)->contents[charset + 128];
-  *idx = MAKE_CHAR (charset, 0, 0);
-  if (!SUB_CHAR_TABLE_P (elt))
-    return elt;
-  if (c1 < 32 || NILP (XCHAR_TABLE (elt)->contents[c1]))
-    return XCHAR_TABLE (elt)->defalt;
-  elt = XCHAR_TABLE (elt)->contents[c1];
-  *idx = MAKE_CHAR (charset, c1, 0);
-  if (!SUB_CHAR_TABLE_P (elt))
-    return elt;
-  if (c2 < 32 || NILP (XCHAR_TABLE (elt)->contents[c2]))
-    return XCHAR_TABLE (elt)->defalt;
-  *idx = c;
-  return XCHAR_TABLE (elt)->contents[c2];
-}
-
 \f
 /* ARGSUSED */
 Lisp_Object
@@ -2859,6 +2418,8 @@ SEQUENCE may be a list, a vector, a bool-vector, or a string.  */)
   struct gcpro gcpro1;
 
   len = Flength (sequence);
+  if (CHAR_TABLE_P (sequence))
+    wrong_type_argument (Qlistp, sequence);
   leni = XINT (len);
   nargs = leni + leni - 1;
   if (nargs < 0) return build_string ("");
@@ -2890,6 +2451,8 @@ SEQUENCE may be a list, a vector, a bool-vector, or a string.  */)
   register Lisp_Object *args;
 
   len = Flength (sequence);
+  if (CHAR_TABLE_P (sequence))
+    wrong_type_argument (Qlistp, sequence);
   leni = XFASTINT (len);
   args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
 
@@ -2908,6 +2471,8 @@ SEQUENCE may be a list, a vector, a bool-vector, or a string.  */)
   register int leni;
 
   leni = XFASTINT (Flength (sequence));
+  if (CHAR_TABLE_P (sequence))
+    wrong_type_argument (Qlistp, sequence);
   mapcar1 (leni, 0, function, sequence);
 
   return sequence;
@@ -3133,7 +2698,7 @@ is nil, and `use-dialog-box' is non-nil.  */)
 \f
 DEFUN ("load-average", Fload_average, Sload_average, 0, 1, 0,
        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.
 
@@ -3141,7 +2706,12 @@ 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.  */)
+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;
 {
@@ -3168,7 +2738,7 @@ extern Lisp_Object Vafter_load_alist;
 
 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
@@ -3245,7 +2815,7 @@ The normal messages at start and end of loading FILENAME are suppressed.  */)
   CHECK_SYMBOL (feature);
 
   tem = Fmemq (feature, Vfeatures);
-  
+
   if (NILP (tem))
     {
       int count = SPECPDL_INDEX ();
@@ -3258,7 +2828,7 @@ The normal messages at start and end of loading FILENAME are suppressed.  */)
       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.  */
@@ -3389,6 +2959,92 @@ usage: (widget-apply WIDGET PROPERTY &rest ARGS)  */)
   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. */
@@ -3607,7 +3263,9 @@ base64_encode_1 (from, to, length, line_break, multibyte)
       if (multibyte)
        {
          c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
-         if (c >= 256)
+         if (CHAR_BYTE8_P (c))
+           c = CHAR_TO_BYTE8 (c);
+         else if (c >= 256)
            return -1;
          i += bytes;
        }
@@ -3645,7 +3303,9 @@ base64_encode_1 (from, to, length, line_break, multibyte)
       if (multibyte)
        {
          c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
-         if (c >= 256)
+         if (CHAR_BYTE8_P (c))
+           c = CHAR_TO_BYTE8 (c);
+         else if (c >= 256)
            return -1;
          i += bytes;
        }
@@ -3667,7 +3327,9 @@ base64_encode_1 (from, to, length, line_break, multibyte)
       if (multibyte)
        {
          c = STRING_CHAR_AND_LENGTH (from + i, length - i, bytes);
-         if (c >= 256)
+         if (CHAR_BYTE8_P (c))
+           c = CHAR_TO_BYTE8 (c);
+         else if (c >= 256)
            return -1;
          i += bytes;
        }
@@ -3823,8 +3485,8 @@ base64_decode_1 (from, to, length, multibyte, nchars_return)
       value |= base64_char_to_value[c] << 12;
 
       c = (unsigned char) (value >> 16);
-      if (multibyte)
-       e += CHAR_STRING (c, e);
+      if (multibyte && c >= 128)
+       e += BYTE8_STRING (c, e);
       else
        *e++ = c;
       nchars++;
@@ -3847,8 +3509,8 @@ base64_decode_1 (from, to, length, multibyte, nchars_return)
       value |= base64_char_to_value[c] << 6;
 
       c = (unsigned char) (0xff & value >> 8);
-      if (multibyte)
-       e += CHAR_STRING (c, e);
+      if (multibyte && c >= 128)
+       e += BYTE8_STRING (c, e);
       else
        *e++ = c;
       nchars++;
@@ -3865,8 +3527,8 @@ base64_decode_1 (from, to, length, multibyte, nchars_return)
       value |= base64_char_to_value[c];
 
       c = (unsigned char) (0xff & value);
-      if (multibyte)
-       e += CHAR_STRING (c, e);
+      if (multibyte && c >= 128)
+       e += BYTE8_STRING (c, e);
       else
        *e++ = c;
       nchars++;
@@ -4575,13 +4237,13 @@ sweep_weak_table (h, remove_entries_p)
                  /* Make sure key and value survive.  */
                  if (!key_known_to_survive_p)
                    {
-                     mark_object (&HASH_KEY (h, i));
+                     mark_object (HASH_KEY (h, i));
                      marked = 1;
                    }
 
                  if (!value_known_to_survive_p)
                    {
-                     mark_object (&HASH_VALUE (h, i));
+                     mark_object (HASH_VALUE (h, i));
                      marked = 1;
                    }
                }
@@ -4626,7 +4288,7 @@ sweep_weak_hash_tables ()
     {
       h = XHASH_TABLE (table);
       next = h->next_weak;
-      
+
       if (h->size & ARRAY_MARK_FLAG)
        {
          /* TABLE is marked as used.  Sweep its contents.  */
@@ -4839,7 +4501,7 @@ DEFUN ("sxhash", Fsxhash, Ssxhash, 1, 1, 0,
 
 DEFUN ("make-hash-table", Fmake_hash_table, Smake_hash_table, 0, MANY, 0,
        doc: /* Create and return a new hash table.
-         
+
 Arguments are specified as keyword/argument pairs.  The following
 arguments are defined:
 
@@ -5114,7 +4776,7 @@ 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,
        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.
 
@@ -5136,11 +4798,10 @@ including negative integers.  */)
  ************************************************************************/
 
 #include "md5.h"
-#include "coding.h"
 
 DEFUN ("md5", Fmd5, Smd5, 1, 5, 0,
        doc: /* Return MD5 message digest of OBJECT, a buffer or string.
-         
+
 A message digest is a cryptographic checksum of a document, and the
 algorithm to calculate it is defined in RFC 1321.
 
@@ -5187,15 +4848,15 @@ guesswork fails.  Normally, an error is signaled in such case.  */)
 
          if (STRING_MULTIBYTE (object))
            /* use default, we can't guess correct value */
-           coding_system = SYMBOL_VALUE (XCAR (Vcoding_category_list));
-         else 
+           coding_system = preferred_coding_system ();
+         else
            coding_system = Qraw_text;
        }
-      
+
       if (NILP (Fcoding_system_p (coding_system)))
        {
          /* Invalid coding system.  */
-         
+
          if (!NILP (noerror))
            coding_system = Qraw_text;
          else
@@ -5204,7 +4865,7 @@ guesswork fails.  Normally, an error is signaled in such case.  */)
        }
 
       if (STRING_MULTIBYTE (object))
-       object = code_convert_string1 (object, coding_system, Qnil, 1);
+       object = code_convert_string (object, coding_system, Qnil, 1, 0, 1);
 
       size = SCHARS (object);
       size_byte = SBYTES (object);
@@ -5229,15 +4890,15 @@ guesswork fails.  Normally, an error is signaled in such case.  */)
       else
        {
          CHECK_NUMBER (end);
-         
+
          end_char = XINT (end);
 
          if (end_char < 0)
            end_char += size;
-         
+
          end_byte = string_char_to_byte (object, end_char);
        }
-      
+
       if (!(0 <= start_char && start_char <= end_char && end_char <= size))
        args_out_of_range_3 (object, make_number (start_char),
                             make_number (end_char));
@@ -5247,7 +4908,7 @@ guesswork fails.  Normally, an error is signaled in such case.  */)
       CHECK_BUFFER (object);
 
       bp = XBUFFER (object);
-         
+
       if (NILP (start))
        b = BUF_BEGV (bp);
       else
@@ -5263,16 +4924,16 @@ guesswork fails.  Normally, an error is signaled in such case.  */)
          CHECK_NUMBER_COERCE_MARKER (end);
          e = XINT (end);
        }
-      
+
       if (b > e)
        temp = b, b = e, e = temp;
-      
+
       if (!(BUF_BEGV (bp) <= b && e <= BUF_ZV (bp)))
        args_out_of_range (start, end);
-      
+
       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))
@@ -5294,7 +4955,7 @@ guesswork fails.  Normally, an error is signaled in such case.  */)
                {
                  /* 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);
@@ -5336,11 +4997,11 @@ guesswork fails.  Normally, an error is signaled in such case.  */)
       object = make_buffer_string (b, e, 0);
 
       if (STRING_MULTIBYTE (object))
-       object = code_convert_string1 (object, coding_system, Qnil, 1);
+       object = code_convert_string (object, coding_system, Qnil, 1, 0, 0);
     }
 
-  md5_buffer (SDATA (object) + start_byte, 
-             SBYTES (object) - (size_byte - end_byte), 
+  md5_buffer (SDATA (object) + start_byte,
+             SBYTES (object) - (size_byte - end_byte),
              digest);
 
   for (i = 0; i < 16; i++)
@@ -5429,6 +5090,17 @@ Used by `featurep' and `require', and altered by `provide'.  */);
   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,
     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
@@ -5451,6 +5123,7 @@ invoked by mouse clicks and mouse menu items.  */);
   defsubr (&Sstring_make_unibyte);
   defsubr (&Sstring_as_multibyte);
   defsubr (&Sstring_as_unibyte);
+  defsubr (&Sstring_to_multibyte);
   defsubr (&Scopy_alist);
   defsubr (&Ssubstring);
   defsubr (&Ssubstring_no_properties);
@@ -5476,16 +5149,7 @@ invoked by mouse clicks and mouse menu items.  */);
   defsubr (&Slax_plist_put);
   defsubr (&Sequal);
   defsubr (&Sfillarray);
-  defsubr (&Schar_table_subtype);
-  defsubr (&Schar_table_parent);
-  defsubr (&Sset_char_table_parent);
-  defsubr (&Schar_table_extra_slot);
-  defsubr (&Sset_char_table_extra_slot);
-  defsubr (&Schar_table_range);
-  defsubr (&Sset_char_table_range);
-  defsubr (&Sset_char_table_default);
-  defsubr (&Soptimize_char_table);
-  defsubr (&Smap_char_table);
+  defsubr (&Sclear_string);
   defsubr (&Snconc);
   defsubr (&Smapcar);
   defsubr (&Smapc);
@@ -5505,6 +5169,7 @@ invoked by mouse clicks and mouse menu items.  */);
   defsubr (&Sbase64_encode_string);
   defsubr (&Sbase64_decode_string);
   defsubr (&Smd5);
+  defsubr (&Slocale_info);
 }