Replace `iff' in comments.
[bpt/emacs.git] / src / charset.c
index 4701db6..1a85cd3 100644 (file)
@@ -1,13 +1,16 @@
 /* Basic multilingual character support.
 /* Basic multilingual character support.
-   Copyright (C) 1995, 1997, 1998 Electrotechnical Laboratory, JAPAN.
-   Licensed to the Free Software Foundation.
-   Copyright (C) 2001 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005,
+                 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+     2005, 2006, 2007
+     National Institute of Advanced Industrial Science and Technology (AIST)
+     Registration Number H14PRO021
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -17,8 +20,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* At first, see the document in `charset.h' to understand the code in
    this file.  */
 
 /* At first, see the document in `charset.h' to understand the code in
    this file.  */
@@ -63,6 +66,9 @@ int charset_katakana_jisx0201;        /* JISX0201.Kana (Japanese Katakana) */
 int charset_latin_jisx0201;    /* JISX0201.Roman (Japanese Roman) */
 int charset_big5_1;            /* Big5 Level 1 (Chinese Traditional) */
 int charset_big5_2;            /* Big5 Level 2 (Chinese Traditional) */
 int charset_latin_jisx0201;    /* JISX0201.Roman (Japanese Roman) */
 int charset_big5_1;            /* Big5 Level 1 (Chinese Traditional) */
 int charset_big5_2;            /* Big5 Level 2 (Chinese Traditional) */
+int charset_mule_unicode_0100_24ff;
+int charset_mule_unicode_2500_33ff;
+int charset_mule_unicode_e000_ffff;
 
 Lisp_Object Qcharset_table;
 
 
 Lisp_Object Qcharset_table;
 
@@ -112,7 +118,7 @@ void
 invalid_character (c)
      int c;
 {
 invalid_character (c)
      int c;
 {
-  error ("Invalid character: 0%o, %d, 0x%x", c, c, c);
+  error ("Invalid character: %d, #o%o, #x%x", c, c, c);
 }
 
 /* Parse string STR of length LENGTH and fetch information of a
 }
 
 /* Parse string STR of length LENGTH and fetch information of a
@@ -210,7 +216,7 @@ char_to_string_1 (c, str)
       /* If C still has any modifier bits, just ignore it.  */
       c &= ~CHAR_MODIFIER_MASK;
     }
       /* If C still has any modifier bits, just ignore it.  */
       c &= ~CHAR_MODIFIER_MASK;
     }
-  
+
   if (SINGLE_BYTE_CHAR_P (c))
     {
       if (ASCII_BYTE_P (c) || c >= 0xA0)
   if (SINGLE_BYTE_CHAR_P (c))
     {
       if (ASCII_BYTE_P (c) || c >= 0xA0)
@@ -331,7 +337,7 @@ split_string (str, len, charset, c1, c2)
   return 0;
 }
 
   return 0;
 }
 
-/* Return 1 iff character C has valid printable glyph.
+/* Return 1 if character C has valid printable glyph.
    Use the macro CHAR_PRINTABLE_P instead.  */
 int
 char_printable_p (c)
    Use the macro CHAR_PRINTABLE_P instead.  */
 int
 char_printable_p (c)
@@ -345,7 +351,7 @@ char_printable_p (c)
     return 0;
   else if (c >= MAX_CHAR)
     return 0;
     return 0;
   else if (c >= MAX_CHAR)
     return 0;
-  
+
   SPLIT_CHAR (c, charset, c1, c2);
   if (! CHARSET_DEFINED_P (charset))
     return 0;
   SPLIT_CHAR (c, charset, c1, c2);
   if (! CHARSET_DEFINED_P (charset))
     return 0;
@@ -700,14 +706,14 @@ DESCRIPTION (string) is the description string of the charset.  */)
       || !STRINGP (vec[7])
       || !STRINGP (vec[8]))
     error ("Invalid info-vector argument for defining charset %s",
       || !STRINGP (vec[7])
       || !STRINGP (vec[8]))
     error ("Invalid info-vector argument for defining charset %s",
-          XSTRING (SYMBOL_NAME (charset_symbol))->data);
+          SDATA (SYMBOL_NAME (charset_symbol)));
 
   if (NILP (charset_id))
     {
       charset_id = get_new_private_charset_id (XINT (vec[0]), XINT (vec[2]));
       if (XINT (charset_id) == 0)
        error ("There's no room for a new private charset %s",
 
   if (NILP (charset_id))
     {
       charset_id = get_new_private_charset_id (XINT (vec[0]), XINT (vec[2]));
       if (XINT (charset_id) == 0)
        error ("There's no room for a new private charset %s",
-              XSTRING (SYMBOL_NAME (charset_symbol))->data);
+              SDATA (SYMBOL_NAME (charset_symbol)));
     }
 
   update_charset_table (charset_id, vec[0], vec[1], vec[2], vec[3],
     }
 
   update_charset_table (charset_id, vec[0], vec[1], vec[2], vec[3],
@@ -730,7 +736,7 @@ It includes a generic character for a charset not yet defined.  */)
 
 DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char,
        Sget_unused_iso_final_char, 2, 2, 0,
 
 DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char,
        Sget_unused_iso_final_char, 2, 2, 0,
-       doc: /* Return an unsed ISO's final char for a charset of DIMENISION and CHARS.
+       doc: /* Return an unused ISO's final char for a charset of DIMENSION and CHARS.
 DIMENSION is the number of bytes to represent a character: 1 or 2.
 CHARS is the number of characters in a dimension: 94 or 96.
 
 DIMENSION is the number of bytes to represent a character: 1 or 2.
 CHARS is the number of characters in a dimension: 94 or 96.
 
@@ -760,17 +766,20 @@ return nil.  */)
 
 DEFUN ("declare-equiv-charset", Fdeclare_equiv_charset, Sdeclare_equiv_charset,
        4, 4, 0,
 
 DEFUN ("declare-equiv-charset", Fdeclare_equiv_charset, Sdeclare_equiv_charset,
        4, 4, 0,
-       doc: /* Declare a charset of DIMENSION, CHARS, FINAL-CHAR is the same as CHARSET.
-CHARSET should be defined by `defined-charset' in advance.  */)
-     (dimension, chars, final_char, charset_symbol)
-     Lisp_Object dimension, chars, final_char, charset_symbol;
+       doc: /* Declare an equivalent charset for ISO-2022 decoding.
+
+On decoding by an ISO-2022 base coding system, when a charset
+specified by DIMENSION, CHARS, and FINAL-CHAR is designated, behave as
+if CHARSET is designated instead.  */)
+     (dimension, chars, final_char, charset)
+     Lisp_Object dimension, chars, final_char, charset;
 {
 {
-  int charset;
+  int charset_id;
 
   CHECK_NUMBER (dimension);
   CHECK_NUMBER (chars);
   CHECK_NUMBER (final_char);
 
   CHECK_NUMBER (dimension);
   CHECK_NUMBER (chars);
   CHECK_NUMBER (final_char);
-  CHECK_SYMBOL (charset_symbol);
+  CHECK_SYMBOL (charset);
 
   if (XINT (dimension) != 1 && XINT (dimension) != 2)
     error ("Invalid DIMENSION %d, it should be 1 or 2", XINT (dimension));
 
   if (XINT (dimension) != 1 && XINT (dimension) != 2)
     error ("Invalid DIMENSION %d, it should be 1 or 2", XINT (dimension));
@@ -778,10 +787,10 @@ CHARSET should be defined by `defined-charset' in advance.  */)
     error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars));
   if (XINT (final_char) < '0' || XFASTINT (final_char) > '~')
     error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars));
     error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars));
   if (XINT (final_char) < '0' || XFASTINT (final_char) > '~')
     error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars));
-  if ((charset = get_charset_id (charset_symbol)) < 0)
-    error ("Invalid charset %s", XSTRING (SYMBOL_NAME (charset_symbol))->data);
+  if ((charset_id = get_charset_id (charset)) < 0)
+    error ("Invalid charset %s", SDATA (SYMBOL_NAME (charset)));
 
 
-  ISO_CHARSET_TABLE (dimension, chars, final_char) = charset;
+  ISO_CHARSET_TABLE (dimension, chars, final_char) = charset_id;
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -802,7 +811,7 @@ CHARSET should be defined by `defined-charset' in advance.  */)
 
 int
 find_charset_in_text (ptr, nchars, nbytes, charsets, table)
 
 int
 find_charset_in_text (ptr, nchars, nbytes, charsets, table)
-     unsigned char *ptr;
+     const unsigned char *ptr;
      int nchars, nbytes, *charsets;
      Lisp_Object table;
 {
      int nchars, nbytes, *charsets;
      Lisp_Object table;
 {
@@ -810,14 +819,14 @@ find_charset_in_text (ptr, nchars, nbytes, charsets, table)
     {
       if (charsets && nbytes > 0)
        {
     {
       if (charsets && nbytes > 0)
        {
-         unsigned char *endp = ptr + nbytes;
+         const unsigned char *endp = ptr + nbytes;
          int maskbits = 0;
 
          while (ptr < endp && maskbits != 7)
            {
              maskbits |= (*ptr < 0x80 ? 1 : *ptr < 0xA0 ? 2 : 4);
              ptr++;
          int maskbits = 0;
 
          while (ptr < endp && maskbits != 7)
            {
              maskbits |= (*ptr < 0x80 ? 1 : *ptr < 0xA0 ? 2 : 4);
              ptr++;
-           }         
+           }
 
          if (maskbits & 1)
            charsets[CHARSET_ASCII] = 1;
 
          if (maskbits & 1)
            charsets[CHARSET_ASCII] = 1;
@@ -943,8 +952,8 @@ only `ascii', `eight-bit-control', and `eight-bit-graphic'.  */)
   CHECK_STRING (str);
 
   bzero (charsets, (MAX_CHARSET + 1) * sizeof (int));
   CHECK_STRING (str);
 
   bzero (charsets, (MAX_CHARSET + 1) * sizeof (int));
-  find_charset_in_text (XSTRING (str)->data, XSTRING (str)->size,
-                       STRING_BYTES (XSTRING (str)), charsets, table);
+  find_charset_in_text (SDATA (str), SCHARS (str),
+                       SBYTES (str), charsets, table);
 
   val = Qnil;
   if (charsets[1])
 
   val = Qnil;
   if (charsets[1])
@@ -1025,9 +1034,9 @@ Internal use only.  */)
 }
 
 DEFUN ("split-char", Fsplit_char, Ssplit_char, 1, 1, 0,
 }
 
 DEFUN ("split-char", Fsplit_char, Ssplit_char, 1, 1, 0,
-       doc: /* Return list of charset and one or two position-codes of CHAR.
-If CHAR is invalid as a character code,
-return a list of symbol `unknown' and CHAR.  */)
+       doc: /* Return list of charset and one or two position-codes of CH.
+If CH is invalid as a character code,
+return a list of symbol `unknown' and CH.  */)
      (ch)
      Lisp_Object ch;
 {
      (ch)
      Lisp_Object ch;
 {
@@ -1045,7 +1054,7 @@ return a list of symbol `unknown' and CHAR.  */)
 }
 
 DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 1, 0,
 }
 
 DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 1, 0,
-       doc: /* Return charset of CHAR.  */)
+       doc: /* Return charset of CH.  */)
      (ch)
      Lisp_Object ch;
 {
      (ch)
      Lisp_Object ch;
 {
@@ -1093,8 +1102,8 @@ DIMENSION, CHARS, and FINAL-CHAR.  */)
   return CHARSET_SYMBOL (charset);
 }
 
   return CHARSET_SYMBOL (charset);
 }
 
-/* If GENERICP is nonzero, return nonzero iff C is a valid normal or
-   generic character.  If GENERICP is zero, return nonzero iff C is a
+/* If GENERICP is nonzero, return nonzero if C is a valid normal or
+   generic character.  If GENERICP is zero, return nonzero if C is a
    valid normal character.  Do not call this function directly,
    instead use macro CHAR_VALID_P.  */
 int
    valid normal character.  Do not call this function directly,
    instead use macro CHAR_VALID_P.  */
 int
@@ -1176,8 +1185,7 @@ The conversion is done based on `nonascii-translation-table' (which see)
 }
 
 DEFUN ("char-bytes", Fchar_bytes, Schar_bytes, 1, 1, 0,
 }
 
 DEFUN ("char-bytes", Fchar_bytes, Schar_bytes, 1, 1, 0,
-       doc: /* Return 1 regardless of the argument CHAR.
-This is now an obsolete function.  We keep it just for backward compatibility.  */)
+       doc: /* Return 1 regardless of the argument CH.  */)
      (ch)
      Lisp_Object ch;
 {
      (ch)
      Lisp_Object ch;
 {
@@ -1221,7 +1229,7 @@ char_bytes (c)
            : 4))))
 
 DEFUN ("char-width", Fchar_width, Schar_width, 1, 1, 0,
            : 4))))
 
 DEFUN ("char-width", Fchar_width, Schar_width, 1, 1, 0,
-       doc: /* Return width of CHAR when displayed in the current buffer.
+       doc: /* Return width of CH when displayed in the current buffer.
 The width is measured by how many columns it occupies on the screen.
 Tab is taken to occupy `tab-width' columns.  */)
      (ch)
 The width is measured by how many columns it occupies on the screen.
 Tab is taken to occupy `tab-width' columns.  */)
      (ch)
@@ -1272,8 +1280,8 @@ strwidth (str, len)
 
 int
 c_string_width (str, len, precision, nchars, nbytes)
 
 int
 c_string_width (str, len, precision, nchars, nbytes)
-     unsigned char *str;
-     int precision, *nchars, *nbytes;
+     const unsigned char *str;
+     int len, precision, *nchars, *nbytes;
 {
   int i = 0, i_byte = 0;
   int width = 0;
 {
   int i = 0, i_byte = 0;
   int width = 0;
@@ -1336,9 +1344,13 @@ lisp_string_width (string, precision, nchars, nbytes)
      Lisp_Object string;
      int precision, *nchars, *nbytes;
 {
      Lisp_Object string;
      int precision, *nchars, *nbytes;
 {
-  int len = XSTRING (string)->size;
-  int len_byte = STRING_BYTES (XSTRING (string));
-  unsigned char *str = XSTRING (string)->data;
+  int len = SCHARS (string);
+  int len_byte = SBYTES (string);
+  /* This set multibyte to 0 even if STRING is multibyte when it
+     contains only ascii and eight-bit-graphic, but that's
+     intentional.  */
+  int multibyte = len < len_byte;
+  const unsigned char *str = SDATA (string);
   int i = 0, i_byte = 0;
   int width = 0;
   struct Lisp_Char_Table *dp = buffer_display_table ();
   int i = 0, i_byte = 0;
   int width = 0;
   struct Lisp_Char_Table *dp = buffer_display_table ();
@@ -1360,8 +1372,12 @@ lisp_string_width (string, precision, nchars, nbytes)
        }
       else if (dp)
        {
        }
       else if (dp)
        {
-         int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes);
+         int c;
 
 
+         if (multibyte)
+           c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes);
+         else
+           c = str[i_byte], bytes = 1;
          chars = 1;
          val = DISP_CHAR_VECTOR (dp, c);
          if (VECTORP (val))
          chars = 1;
          val = DISP_CHAR_VECTOR (dp, c);
          if (VECTORP (val))
@@ -1372,7 +1388,10 @@ lisp_string_width (string, precision, nchars, nbytes)
       else
        {
          chars = 1;
       else
        {
          chars = 1;
-         PARSE_MULTIBYTE_SEQ (str + i_byte, len_byte - i_byte, bytes);
+         if (multibyte)
+           PARSE_MULTIBYTE_SEQ (str + i_byte, len_byte - i_byte, bytes);
+         else
+           bytes = 1;
          thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
        }
 
          thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
        }
 
@@ -1404,18 +1423,18 @@ When calculating width of a multibyte character in STRING,
 only the base leading-code is considered; the validity of
 the following bytes is not checked.  Tabs in STRING are always
 taken to occupy `tab-width' columns.  */)
 only the base leading-code is considered; the validity of
 the following bytes is not checked.  Tabs in STRING are always
 taken to occupy `tab-width' columns.  */)
-     (str)
-     Lisp_Object str;
+     (string)
+     Lisp_Object string;
 {
   Lisp_Object val;
 
 {
   Lisp_Object val;
 
-  CHECK_STRING (str);
-  XSETFASTINT (val, lisp_string_width (str, -1, NULL, NULL));
+  CHECK_STRING (string);
+  XSETFASTINT (val, lisp_string_width (string, -1, NULL, NULL));
   return val;
 }
 
 DEFUN ("char-direction", Fchar_direction, Schar_direction, 1, 1, 0,
   return val;
 }
 
 DEFUN ("char-direction", Fchar_direction, Schar_direction, 1, 1, 0,
-       doc: /* Return the direction of CHAR.
+       doc: /* Return the direction of CH.
 The returned value is 0 for left-to-right and 1 for right-to-left.  */)
      (ch)
      Lisp_Object ch;
 The returned value is 0 for left-to-right and 1 for right-to-left.  */)
      (ch)
      Lisp_Object ch;
@@ -1429,22 +1448,6 @@ The returned value is 0 for left-to-right and 1 for right-to-left.  */)
   return CHARSET_TABLE_INFO (charset, CHARSET_DIRECTION_IDX);
 }
 
   return CHARSET_TABLE_INFO (charset, CHARSET_DIRECTION_IDX);
 }
 
-DEFUN ("chars-in-region", Fchars_in_region, Schars_in_region, 2, 2, 0,
-       doc: /* Return number of characters between BEG and END.  */)
-     (beg, end)
-     Lisp_Object beg, end;
-{
-  int from, to;
-
-  CHECK_NUMBER_COERCE_MARKER (beg);
-  CHECK_NUMBER_COERCE_MARKER (end);
-
-  from = min (XFASTINT (beg), XFASTINT (end));
-  to = max (XFASTINT (beg), XFASTINT (end));
-
-  return make_number (to - from);
-}
-
 /* Return the number of characters in the NBYTES bytes at PTR.
    This works by looking at the contents and checking for multibyte sequences.
    However, if the current buffer has enable-multibyte-characters = nil,
 /* Return the number of characters in the NBYTES bytes at PTR.
    This works by looking at the contents and checking for multibyte sequences.
    However, if the current buffer has enable-multibyte-characters = nil,
@@ -1452,7 +1455,7 @@ DEFUN ("chars-in-region", Fchars_in_region, Schars_in_region, 2, 2, 0,
 
 int
 chars_in_text (ptr, nbytes)
 
 int
 chars_in_text (ptr, nbytes)
-     unsigned char *ptr;
+     const unsigned char *ptr;
      int nbytes;
 {
   /* current_buffer is null at early stages of Emacs initialization.  */
      int nbytes;
 {
   /* current_buffer is null at early stages of Emacs initialization.  */
@@ -1469,10 +1472,10 @@ chars_in_text (ptr, nbytes)
 
 int
 multibyte_chars_in_text (ptr, nbytes)
 
 int
 multibyte_chars_in_text (ptr, nbytes)
-     unsigned char *ptr;
+     const unsigned char *ptr;
      int nbytes;
 {
      int nbytes;
 {
-  unsigned char *endp;
+  const unsigned char *endp;
   int chars, bytes;
 
   endp = ptr + nbytes;
   int chars, bytes;
 
   endp = ptr + nbytes;
@@ -1494,10 +1497,10 @@ multibyte_chars_in_text (ptr, nbytes)
    0x80..0x9F are represented by 2 bytes in multibyte text.  */
 void
 parse_str_as_multibyte (str, len, nchars, nbytes)
    0x80..0x9F are represented by 2 bytes in multibyte text.  */
 void
 parse_str_as_multibyte (str, len, nchars, nbytes)
-     unsigned char *str;
+     const unsigned char *str;
      int len, *nchars, *nbytes;
 {
      int len, *nchars, *nbytes;
 {
-  unsigned char *endp = str + len;
+  const unsigned char *endp = str + len;
   int n, chars = 0, bytes = 0;
 
   while (str < endp)
   int n, chars = 0, bytes = 0;
 
   while (str < endp)
@@ -1549,7 +1552,7 @@ str_as_multibyte (str, len, nbytes, nchars)
        {
          while (n--)
            *to++ = *p++;
        {
          while (n--)
            *to++ = *p++;
-       }         
+       }
       else
        {
          *to++ = LEADING_CODE_8_BIT_CONTROL;
       else
        {
          *to++ = LEADING_CODE_8_BIT_CONTROL;
@@ -1601,7 +1604,7 @@ str_to_multibyte (str, len, bytes)
   endp = str + len;
   safe_bcopy (p, endp - bytes, bytes);
   p = endp - bytes;
   endp = str + len;
   safe_bcopy (p, endp - bytes, bytes);
   p = endp - bytes;
-  while (p < endp)      
+  while (p < endp)
     {
       if (*p < 0x80 || *p >= 0xA0)
        *to++ = *p++;
     {
       if (*p < 0x80 || *p >= 0xA0)
        *to++ = *p++;
@@ -1625,7 +1628,7 @@ str_as_unibyte (str, bytes)
 
   while (p < endp && *p != LEADING_CODE_8_BIT_CONTROL) p++;
   to = p;
 
   while (p < endp && *p != LEADING_CODE_8_BIT_CONTROL) p++;
   to = p;
-  while (p < endp)      
+  while (p < endp)
     {
       if (*p == LEADING_CODE_8_BIT_CONTROL)
        *to++ = *(p + 1) - 0x20, p += 2;
     {
       if (*p == LEADING_CODE_8_BIT_CONTROL)
        *to++ = *(p + 1) - 0x20, p += 2;
@@ -1643,11 +1646,16 @@ usage: (string &rest CHARACTERS)  */)
      int n;
      Lisp_Object *args;
 {
      int n;
      Lisp_Object *args;
 {
-  int i;
-  unsigned char *buf = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH * n);
-  unsigned char *p = buf;
+  int i, bufsize;
+  unsigned char *buf, *p;
   int c;
   int multibyte = 0;
   int c;
   int multibyte = 0;
+  Lisp_Object ret;
+  USE_SAFE_ALLOCA;
+
+  bufsize = MAX_MULTIBYTE_LENGTH * n;
+  SAFE_ALLOCA (buf, unsigned char *, bufsize);
+  p = buf;
 
   for (i = 0; i < n; i++)
     {
 
   for (i = 0; i < n; i++)
     {
@@ -1665,7 +1673,10 @@ usage: (string &rest CHARACTERS)  */)
        *p++ = c;
     }
 
        *p++ = c;
     }
 
-  return make_string_from_bytes (buf, n, p - buf);
+  ret = make_string_from_bytes (buf, n, p - buf);
+  SAFE_FREE ();
+
+  return ret;
 }
 
 #endif /* emacs */
 }
 
 #endif /* emacs */
@@ -1694,6 +1705,12 @@ DEFUN ("setup-special-charsets", Fsetup_special_charsets,
   charset_latin_jisx0201 = charset_id_internal ("latin-jisx0201");
   charset_big5_1 = charset_id_internal ("chinese-big5-1");
   charset_big5_2 = charset_id_internal ("chinese-big5-2");
   charset_latin_jisx0201 = charset_id_internal ("latin-jisx0201");
   charset_big5_1 = charset_id_internal ("chinese-big5-1");
   charset_big5_2 = charset_id_internal ("chinese-big5-2");
+  charset_mule_unicode_0100_24ff
+    = charset_id_internal ("mule-unicode-0100-24ff");
+  charset_mule_unicode_2500_33ff
+    = charset_id_internal ("mule-unicode-2500-33ff");
+  charset_mule_unicode_e000_ffff
+    = charset_id_internal ("mule-unicode-e000-ffff");
   return Qnil;
 }
 
   return Qnil;
 }
 
@@ -1845,7 +1862,6 @@ syms_of_charset ()
   defsubr (&Schar_width);
   defsubr (&Sstring_width);
   defsubr (&Schar_direction);
   defsubr (&Schar_width);
   defsubr (&Sstring_width);
   defsubr (&Schar_direction);
-  defsubr (&Schars_in_region);
   defsubr (&Sstring);
   defsubr (&Ssetup_special_charsets);
 
   defsubr (&Sstring);
   defsubr (&Ssetup_special_charsets);
 
@@ -1909,3 +1925,6 @@ Such characters have value t in this table.  */);
 }
 
 #endif /* emacs */
 }
 
 #endif /* emacs */
+
+/* arch-tag: 66a89b8d-4c28-47d3-9ca1-56f78440d69f
+   (do not change this comment) */