]> code.delx.au - gnu-emacs/blobdiff - src/coding.c
(Ffind_operation_coding_system): Fix Lisp_Object/int mixup.
[gnu-emacs] / src / coding.c
index 2301470cb816c48f730c62cc93e3adc1be706422..57d7e4b21fdf3cb5d0bc979263c11666648726e7 100644 (file)
@@ -1,5 +1,5 @@
 /* Coding system handler (conversion, detection, and etc).
-   Copyright (C) 1995, 1997, 1998 Electrotechnical Laboratory, JAPAN.
+   Copyright (C) 1995, 1997, 1998, 2002 Electrotechnical Laboratory, JAPAN.
    Licensed to the Free Software Foundation.
    Copyright (C) 2001 Free Software Foundation, Inc.
 
@@ -60,7 +60,7 @@ Boston, MA 02111-1307, USA.  */
   all variants of ISO2022.  Details are described in section 3.
 
   2. SJIS (or Shift-JIS or MS-Kanji-Code)
-   
+
   A coding system to encode character sets: ASCII, JISX0201, and
   JISX0208.  Widely used for PC's in Japan.  Details are described in
   section 4.
@@ -503,7 +503,7 @@ coding_safe_chars (coding)
      struct coding_system *coding;
 {
   Lisp_Object coding_spec, plist, safe_chars;
-  
+
   coding_spec = Fget (coding->symbol, Qcoding_system);
   plist = XVECTOR (coding_spec)->contents[3];
   safe_chars = Fplist_get (XVECTOR (coding_spec)->contents[3], Qsafe_chars);
@@ -811,6 +811,10 @@ decode_composition_emacs_mule (coding, src, src_end,
        return 0;
       for (ncomponent = 0; src < src_base + data_len; ncomponent++)
        {
+         /* If it is longer than this, it can't be valid.  */
+         if (ncomponent >= COMPOSITION_DATA_MAX_BUNCH_LENGTH)
+           return 0;
+
          if (ncomponent % 2 && with_rule)
            {
              ONE_MORE_BYTE (gref);
@@ -889,7 +893,7 @@ decode_composition_emacs_mule (coding, src, src_end,
       CODING_ADD_COMPOSITION_START (coding, coding->produced_char, method);
       for (i = 0; i < ncomponent; i++)
        CODING_ADD_COMPOSITION_COMPONENT (coding, component[i]);
-      CODING_ADD_COMPOSITION_END (coding, coding->produced_char + nchars);  
+      CODING_ADD_COMPOSITION_END (coding, coding->produced_char + nchars);
       if (buf < bufp)
        {
          unsigned char *p = buf;
@@ -1055,9 +1059,9 @@ decode_coding_emacs_mule (coding, source, destination, src_bytes, dst_bytes)
        coding->cmp_data_start = 0;                                     \
       }                                                                        \
   } while (0)
-  
 
-static void encode_eol P_ ((struct coding_system *, unsigned char *,
+
+static void encode_eol P_ ((struct coding_system *, const unsigned char *,
                            unsigned char *, int, int));
 
 static void
@@ -1345,6 +1349,7 @@ detect_coding_iso2022 (src, src_end, multibytep)
   while (mask && src < src_end)
     {
       ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep);
+    retry:
       switch (c)
        {
        case ISO_CODE_ESC:
@@ -1433,7 +1438,7 @@ detect_coding_iso2022 (src, src_end, multibytep)
              mask_found |= CODING_CATEGORY_MASK_ISO_SHIFT;
            }
          break;
-         
+
        case ISO_CODE_SI:
          if (inhibit_iso_escape_detection)
            break;
@@ -1519,6 +1524,8 @@ detect_coding_iso2022 (src, src_end, multibytep)
                  && mask & CODING_CATEGORY_MASK_ISO_8_2)
                {
                  int i = 1;
+
+                 c = -1;
                  while (src < src_end)
                    {
                      ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep);
@@ -1531,6 +1538,9 @@ detect_coding_iso2022 (src, src_end, multibytep)
                    mask &= ~CODING_CATEGORY_MASK_ISO_8_2;
                  else
                    mask_found |= CODING_CATEGORY_MASK_ISO_8_2;
+                 if (c >= 0)
+                   /* This means that we have read one extra byte.  */
+                   goto retry;
                }
            }
          break;
@@ -1665,7 +1675,7 @@ coding_allocate_composition_data (coding, char_offset)
 
 #define DECODE_COMPOSITION_END(c1)                                     \
   do {                                                                 \
-    if (coding->composing == COMPOSITION_DISABLED)                     \
+    if (! COMPOSING_P (coding))                                                \
       {                                                                        \
        *dst++ = ISO_CODE_ESC;                                          \
        *dst++ = c1;                                                    \
@@ -2439,7 +2449,7 @@ encode_designation_at_bol (coding, translation_table, src, src_end, dst)
       ONE_MORE_CHAR (c);
       if (c == '\n')
        break;
-      
+
       charset = CHAR_CHARSET (c);
       reg = CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset);
       if (reg != CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION && r[reg] < 0)
@@ -2609,7 +2619,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
                *dst++ = ISO_CODE_CR;
              CODING_SPEC_ISO_BOL (coding) = 1;
            }
-         else 
+         else
            {
              if (coding->flags & CODING_FLAG_ISO_RESET_AT_CNTL)
                ENCODE_RESET_PLANE_AND_REGISTER;
@@ -2681,7 +2691,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
 
 /* Macros to decode or encode a character of Big5 in BIG5.  B1 and B2
    are the 1st and 2nd position-codes of Big5 in BIG5 coding system.
-   C1 and C2 are the 1st and 2nd position-codes of of Emacs' internal
+   C1 and C2 are the 1st and 2nd position-codes of Emacs' internal
    format.  CHARSET is `charset_big5_1' or `charset_big5_2'.  */
 
 /* Number of Big5 characters which have the same code in 1st byte.  */
@@ -3032,14 +3042,14 @@ encode_coding_sjis_big5 (coding, source, destination,
 
       src_base = src;
       ONE_MORE_CHAR (c);
-      
+
       /* Now encode the character C.  */
       if (SINGLE_BYTE_CHAR_P (c))
        {
          switch (c)
            {
            case '\r':
-             if (!coding->mode & CODING_MODE_SELECTIVE_DISPLAY)
+             if (!(coding->mode & CODING_MODE_SELECTIVE_DISPLAY))
                {
                  EMIT_ONE_BYTE (c);
                  break;
@@ -3232,12 +3242,13 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
 static void
 encode_eol (coding, source, destination, src_bytes, dst_bytes)
      struct coding_system *coding;
-     unsigned char *source, *destination;
+     const unsigned char *source;
+     unsigned char *destination;
      int src_bytes, dst_bytes;
 {
-  unsigned char *src = source;
+  const unsigned char *src = source;
   unsigned char *dst = destination;
-  unsigned char *src_end = src + src_bytes;
+  const unsigned char *src_end = src + src_bytes;
   unsigned char *dst_end = dst + dst_bytes;
   Lisp_Object translation_table;
   /* SRC_BASE remembers the start position in source in each loop.
@@ -3245,7 +3256,8 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes)
      analyze multi-byte codes (within macro ONE_MORE_CHAR), or when
      there's not enough destination area to produce encoded codes
      (within macro EMIT_BYTES).  */
-  unsigned char *src_base;
+  const unsigned char *src_base;
+  unsigned char *tmp;
   int c;
   int selective_display = coding->mode & CODING_MODE_SELECTIVE_DISPLAY;
 
@@ -3295,13 +3307,13 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes)
        }
       if (coding->eol_type == CODING_EOL_CR)
        {
-         for (src = destination; src < dst; src++)
-           if (*src == '\n') *src = '\r';
+         for (tmp = destination; tmp < dst; tmp++)
+           if (*tmp == '\n') *tmp = '\r';
        }
       else if (selective_display)
        {
-         for (src = destination; src < dst; src++)
-           if (*src == '\r') *src = '\n';
+         for (tmp = destination; tmp < dst; tmp++)
+           if (*tmp == '\r') *tmp = '\n';
        }
     }
   if (coding->src_multibyte)
@@ -3357,7 +3369,7 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes)
 
        If the value is nil, graphic register N is never used on
        encoding.
-   
+
    sub-element[N] where N is 4 through 11: to be set in `coding->flags'
        Each value takes t or nil.  See the section ISO2022 of
        `coding.h' for more information.
@@ -3481,7 +3493,7 @@ setup_coding_system (coding_system, coding)
     }
   else
     goto label_invalid_coding_system;
-  
+
   /* If the coding system has non-nil `composition' property, enable
      composition handling.  */
   val = Fplist_get (plist, Qcomposition);
@@ -3576,8 +3588,8 @@ setup_coding_system (coding_system, coding)
            = CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION;
        for (i = 0; i < 4; i++)
          {
-           if (INTEGERP (flags[i])
-               && (charset = XINT (flags[i]), CHARSET_VALID_P (charset))
+           if ((INTEGERP (flags[i])
+                && (charset = XINT (flags[i]), CHARSET_VALID_P (charset)))
                || (charset = get_charset_id (flags[i])) >= 0)
              {
                CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = charset;
@@ -3595,9 +3607,9 @@ setup_coding_system (coding_system, coding)
                tail = flags[i];
 
                coding->flags |= CODING_FLAG_ISO_DESIGNATION;
-               if (INTEGERP (XCAR (tail))
-                   && (charset = XINT (XCAR (tail)),
-                       CHARSET_VALID_P (charset))
+               if ((INTEGERP (XCAR (tail))
+                    && (charset = XINT (XCAR (tail)),
+                        CHARSET_VALID_P (charset)))
                    || (charset = get_charset_id (XCAR (tail))) >= 0)
                  {
                    CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = charset;
@@ -3608,9 +3620,9 @@ setup_coding_system (coding_system, coding)
                tail = XCDR (tail);
                while (CONSP (tail))
                  {
-                   if (INTEGERP (XCAR (tail))
-                       && (charset = XINT (XCAR (tail)),
-                           CHARSET_VALID_P (charset))
+                   if ((INTEGERP (XCAR (tail))
+                        && (charset = XINT (XCAR (tail)),
+                            CHARSET_VALID_P (charset)))
                        || (charset = get_charset_id (XCAR (tail))) >= 0)
                      CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset)
                        = i;
@@ -3621,7 +3633,7 @@ setup_coding_system (coding_system, coding)
              }
            else
              CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = -1;
-           
+
            CODING_SPEC_ISO_DESIGNATION (coding, i)
              = CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i);
          }
@@ -3994,7 +4006,7 @@ detect_coding_mask (source, src_bytes, priorities, skip, multibytep)
                  | CODING_CATEGORY_MASK_UTF_16_LE);
 
          /* Or, if C is a special latin extra code,
-            or is an ISO2022 specific control code of C1 (SS2 or SS3), 
+            or is an ISO2022 specific control code of C1 (SS2 or SS3),
             or is an ISO2022 control-sequence-introducer (CSI),
             we should also consider the possibility of ISO2022 codings.  */
          if ((VECTORP (Vlatin_extra_code_table)
@@ -4037,7 +4049,7 @@ detect_coding_mask (source, src_bytes, priorities, skip, multibytep)
              if (!iso2022_examined_p
                  && (priorities[i] & try & CODING_CATEGORY_MASK_ISO))
                {
-                 mask |= detect_coding_iso2022 (src, src_end);
+                 mask |= detect_coding_iso2022 (src, src_end, multibytep);
                  iso2022_examined_p = 1;
                }
              else if (priorities[i] & try & CODING_CATEGORY_MASK_SJIS)
@@ -4090,7 +4102,7 @@ detect_coding_mask (source, src_bytes, priorities, skip, multibytep)
 void
 detect_coding (coding, src, src_bytes)
      struct coding_system *coding;
-     unsigned char *src;
+     const unsigned char *src;
      int src_bytes;
 {
   unsigned int idx;
@@ -4263,7 +4275,7 @@ detect_eol_type_in_2_octet_form (source, src_bytes, skip, big_endian_p)
 void
 detect_eol (coding, src, src_bytes)
      struct coding_system *coding;
-     unsigned char *src;
+     const unsigned char *src;
      int src_bytes;
 {
   Lisp_Object val;
@@ -4313,11 +4325,13 @@ detect_eol (coding, src, src_bytes)
     {
       int src_multibyte = coding->src_multibyte;
       int dst_multibyte = coding->dst_multibyte;
+      struct composition_data *cmp_data = coding->cmp_data;
 
       setup_coding_system (XVECTOR (val)->contents[eol_type], coding);
       coding->src_multibyte = src_multibyte;
       coding->dst_multibyte = dst_multibyte;
       coding->heading_ascii = skip;
+      coding->cmp_data = cmp_data;
     }
 }
 
@@ -4586,7 +4600,7 @@ decode_eol_post_ccl (coding, ptr, bytes)
        {
          /* If the last character is CR, we can't handle it here
             because LF will be in the not-yet-decoded source text.
-            Recorded that the CR is not yet processed.  */
+            Record that the CR is not yet processed.  */
          coding->spec.ccl.cr_carryover = 1;
          coding->produced--;
          coding->produced_char--;
@@ -4679,9 +4693,12 @@ decode_eol_post_ccl (coding, ptr, bytes)
 int
 decode_coding (coding, source, destination, src_bytes, dst_bytes)
      struct coding_system *coding;
-     unsigned char *source, *destination;
+     const unsigned char *source;
+     unsigned char *destination;
      int src_bytes, dst_bytes;
 {
+  int extra = 0;
+
   if (coding->type == coding_type_undecided)
     detect_coding (coding, source, src_bytes);
 
@@ -4724,18 +4741,24 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
     case coding_type_ccl:
       if (coding->spec.ccl.cr_carryover)
        {
-         /* Set the CR which is not processed by the previous call of
-            decode_eol_post_ccl in DESTINATION.  */
+         /* Put the CR which was not processed by the previous call
+            of decode_eol_post_ccl in DESTINATION.  It will be
+            decoded together with the following LF by the call to
+            decode_eol_post_ccl below.  */
          *destination = '\r';
          coding->produced++;
          coding->produced_char++;
          dst_bytes--;
+         extra = coding->spec.ccl.cr_carryover;
        }
-      ccl_coding_driver (coding, source,
-                        destination + coding->spec.ccl.cr_carryover,
+      ccl_coding_driver (coding, source, destination + extra,
                         src_bytes, dst_bytes, 0);
       if (coding->eol_type != CODING_EOL_LF)
-       decode_eol_post_ccl (coding, destination, coding->produced);
+       {
+         coding->produced += extra;
+         coding->produced_char += extra;
+         decode_eol_post_ccl (coding, destination, coding->produced);
+       }
       break;
 
     default:
@@ -4750,7 +4773,7 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
   if (coding->mode & CODING_MODE_LAST_BLOCK
       && coding->result == CODING_FINISH_INSUFFICIENT_SRC)
     {
-      unsigned char *src = source + coding->consumed;
+      const unsigned char *src = source + coding->consumed;
       unsigned char *dst = destination + coding->produced;
 
       src_bytes -= coding->consumed;
@@ -4784,7 +4807,8 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
 int
 encode_coding (coding, source, destination, src_bytes, dst_bytes)
      struct coding_system *coding;
-     unsigned char *source, *destination;
+     const unsigned char *source;
+     unsigned char *destination;
      int src_bytes, dst_bytes;
 {
   coding->produced = coding->produced_char = 0;
@@ -4826,7 +4850,7 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes)
   if (coding->mode & CODING_MODE_LAST_BLOCK
       && coding->result == CODING_FINISH_INSUFFICIENT_SRC)
     {
-      unsigned char *src = source + coding->consumed;
+      const unsigned char *src = source + coding->consumed;
       unsigned char *dst = destination + coding->produced;
 
       if (coding->type == coding_type_iso2022)
@@ -5047,7 +5071,7 @@ shrink_encoding_region (beg, end, coding, str)
   if (coding->type == coding_type_ccl
       || coding->eol_type == CODING_EOL_CRLF
       || coding->eol_type == CODING_EOL_CR
-      || coding->cmp_data && coding->cmp_data->used > 0)
+      || (coding->cmp_data && coding->cmp_data->used > 0))
     {
       /* We can't skip any data.  */
       return;
@@ -5101,7 +5125,7 @@ shrink_encoding_region (beg, end, coding, str)
        break;
       if (coding->flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL)
        {
-         unsigned char *bol = begp; 
+         unsigned char *bol = begp;
          while (begp < endp && *begp < 0x80)
            {
              begp++;
@@ -5210,7 +5234,7 @@ coding_save_composition (coding, from, to, obj)
              else if (VECTORP (val) || STRINGP (val))
                {
                  int len = (VECTORP (val)
-                            ? XVECTOR (val)->size : XSTRING (val)->size);
+                            ? XVECTOR (val)->size : SCHARS (val));
                  int i;
                  for (i = 0; i < len; i++)
                    {
@@ -5305,6 +5329,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
      struct coding_system *coding;
 {
   int len = to - from, len_byte = to_byte - from_byte;
+  int nchars_del = 0, nbytes_del = 0;
   int require, inserted, inserted_byte;
   int head_skip, tail_skip, total_skip = 0;
   Lisp_Object saved_coding_symbol;
@@ -5427,7 +5452,15 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
     }
 
   if (replace)
-    deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
+    {
+      if (! EQ (current_buffer->undo_list, Qt))
+       deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
+      else
+       {
+         nchars_del = to - from;
+         nbytes_del = to_byte - from_byte;
+       }
+    }
 
   if (coding->composing != COMPOSITION_DISABLED)
     {
@@ -5516,7 +5549,11 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
       if (encodep)
        result = encode_coding (coding, src, dst, len_byte, 0);
       else
-       result = decode_coding (coding, src, dst, len_byte, 0);
+       {
+         if (coding->composing != COMPOSITION_DISABLED)
+           coding->cmp_data->char_offset = from + inserted;
+         result = decode_coding (coding, src, dst, len_byte, 0);
+       }
 
       /* The buffer memory is now:
         +--------+-------converted-text----+--+------original-text----+---+
@@ -5599,7 +5636,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
            coding->symbol = XVECTOR (eol_type)->contents[CODING_EOL_LF];
          else
            coding->symbol = saved_coding_symbol;
-         
+
          continue;
        }
       if (len_byte <= 0)
@@ -5617,7 +5654,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
          if (multibyte_p)
            {
              unsigned char *start = dst;
-             
+
              inserted += len_byte;
              while (len_byte--)
                {
@@ -5700,7 +5737,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
       inserted_byte = str_to_multibyte (GPT_ADDR, GAP_SIZE, inserted_byte);
     }
 
-  /* If we shrank the conversion area, adjust it now.  */ 
+  /* If we shrank the conversion area, adjust it now.  */
   if (total_skip > 0)
     {
       if (tail_skip > 0)
@@ -5715,7 +5752,11 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
     }
 
   prev_Z = Z;
-  adjust_after_replace (from, from_byte, deletion, inserted, inserted_byte);
+  if (! EQ (current_buffer->undo_list, Qt))
+    adjust_after_replace (from, from_byte, deletion, inserted, inserted_byte);
+  else
+    adjust_after_replace_noundo (from, from_byte, nchars_del, nbytes_del,
+                                inserted, inserted_byte);
   inserted = Z - prev_Z;
 
   if (!encodep && coding->cmp_data && coding->cmp_data->used)
@@ -5773,22 +5814,35 @@ run_pre_post_conversion_on_str (str, coding, encodep)
      struct coding_system *coding;
      int encodep;
 {
-  int count = specpdl_ptr - specpdl;
+  int count = SPECPDL_INDEX ();
   struct gcpro gcpro1;
   int multibyte = STRING_MULTIBYTE (str);
+  Lisp_Object buffer;
+  struct buffer *buf;
 
   record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
   record_unwind_protect (code_convert_region_unwind, Qnil);
   GCPRO1 (str);
-  temp_output_buffer_setup (" *code-converting-work*");
-  set_buffer_internal (XBUFFER (Vstandard_output));
+
+  buffer = Fget_buffer_create (build_string (" *code-converting-work*"));
+  buf = XBUFFER (buffer);
+
+  buf->directory = current_buffer->directory;
+  buf->read_only = Qnil;
+  buf->filename = Qnil;
+  buf->undo_list = Qt;
+  buf->overlays_before = Qnil;
+  buf->overlays_after = Qnil;
+
+  set_buffer_internal (buf);
   /* We must insert the contents of STR as is without
      unibyte<->multibyte conversion.  For that, we adjust the
      multibyteness of the working buffer to that of STR.  */
   Ferase_buffer ();
-  current_buffer->enable_multibyte_characters = multibyte ? Qt : Qnil;
+  buf->enable_multibyte_characters = multibyte ? Qt : Qnil;
+
   insert_from_string (str, 0, 0,
-                     XSTRING (str)->size, STRING_BYTES (XSTRING (str)), 0);
+                     SCHARS (str), SBYTES (str), 0);
   UNGCPRO;
   inhibit_pre_post_conversion = 1;
   if (encodep)
@@ -5812,7 +5866,6 @@ decode_coding_string (str, coding, nocopy)
   int len;
   struct conversion_buffer buf;
   int from, to_byte;
-  struct gcpro gcpro1;
   Lisp_Object saved_coding_symbol;
   int result;
   int require_decoding;
@@ -5821,7 +5874,7 @@ decode_coding_string (str, coding, nocopy)
   int consumed, consumed_char, produced, produced_char;
 
   from = 0;
-  to_byte = STRING_BYTES (XSTRING (str));
+  to_byte = SBYTES (str);
 
   saved_coding_symbol = coding->symbol;
   coding->src_multibyte = STRING_MULTIBYTE (str);
@@ -5831,7 +5884,7 @@ decode_coding_string (str, coding, nocopy)
       /* See the comments in code_convert_region.  */
       if (coding->type == coding_type_undecided)
        {
-         detect_coding (coding, XSTRING (str)->data, to_byte);
+         detect_coding (coding, SDATA (str), to_byte);
          if (coding->type == coding_type_undecided)
            {
              coding->type = coding_type_emacs_mule;
@@ -5846,7 +5899,7 @@ decode_coding_string (str, coding, nocopy)
          && coding->type != coding_type_ccl)
        {
          saved_coding_symbol = coding->symbol;
-         detect_eol (coding, XSTRING (str)->data, to_byte);
+         detect_eol (coding, SDATA (str), to_byte);
          if (coding->eol_type == CODING_EOL_UNDECIDED)
            coding->eol_type = CODING_EOL_LF;
          /* We had better recover the original eol format if we
@@ -5865,7 +5918,7 @@ decode_coding_string (str, coding, nocopy)
     {
       /* Decoding routines expect the source text to be unibyte.  */
       str = Fstring_as_unibyte (str);
-      to_byte = STRING_BYTES (XSTRING (str));
+      to_byte = SBYTES (str);
       nocopy = 1;
       coding->src_multibyte = 0;
     }
@@ -5873,24 +5926,24 @@ decode_coding_string (str, coding, nocopy)
   /* Try to skip the heading and tailing ASCIIs.  */
   if (require_decoding && coding->type != coding_type_ccl)
     {
-      SHRINK_CONVERSION_REGION (&from, &to_byte, coding, XSTRING (str)->data,
+      SHRINK_CONVERSION_REGION (&from, &to_byte, coding, SDATA (str),
                                0);
       if (from == to_byte)
        require_decoding = 0;
-      shrinked_bytes = from + (STRING_BYTES (XSTRING (str)) - to_byte);
+      shrinked_bytes = from + (SBYTES (str) - to_byte);
     }
 
   if (!require_decoding)
     {
-      coding->consumed = STRING_BYTES (XSTRING (str));
-      coding->consumed_char = XSTRING (str)->size;
+      coding->consumed = SBYTES (str);
+      coding->consumed_char = SCHARS (str);
       if (coding->dst_multibyte)
        {
          str = Fstring_as_multibyte (str);
          nocopy = 1;
        }
-      coding->produced = STRING_BYTES (XSTRING (str));
-      coding->produced_char = XSTRING (str)->size;
+      coding->produced = SBYTES (str);
+      coding->produced_char = SCHARS (str);
       return (nocopy ? str : Fcopy_sequence (str));
     }
 
@@ -5902,7 +5955,7 @@ decode_coding_string (str, coding, nocopy)
   consumed = consumed_char = produced = produced_char = 0;
   while (1)
     {
-      result = decode_coding (coding, XSTRING (str)->data + from + consumed,
+      result = decode_coding (coding, SDATA (str) + from + consumed,
                              buf.data + produced, to_byte - from - consumed,
                              buf.size - produced);
       consumed += coding->consumed;
@@ -5943,7 +5996,7 @@ decode_coding_string (str, coding, nocopy)
                }
              produced += num_eol;
              produced_char += num_eol;
-           } 
+           }
          /* Suppress eol-format conversion in the further conversion.  */
          coding->eol_type = CODING_EOL_LF;
 
@@ -5971,12 +6024,12 @@ decode_coding_string (str, coding, nocopy)
   else
     newstr = make_uninit_string (produced + shrinked_bytes);
   if (from > 0)
-    bcopy (XSTRING (str)->data, XSTRING (newstr)->data, from);
-  bcopy (buf.data, XSTRING (newstr)->data + from, produced);
+    STRING_COPYIN (newstr, 0, SDATA (str), from);
+  STRING_COPYIN (newstr, from, buf.data, produced);
   if (shrinked_bytes > from)
-    bcopy (XSTRING (str)->data + to_byte,
-          XSTRING (newstr)->data + from + produced,
-          shrinked_bytes - from);
+    STRING_COPYIN (newstr, from + produced,
+                  SDATA (str) + to_byte,
+                  shrinked_bytes - from);
   free_conversion_buffer (&buf);
 
   if (coding->cmp_data && coding->cmp_data->used)
@@ -6009,8 +6062,8 @@ encode_coding_string (str, coding, nocopy)
     str = run_pre_post_conversion_on_str (str, coding, 1);
 
   from = 0;
-  to = XSTRING (str)->size;
-  to_byte = STRING_BYTES (XSTRING (str));
+  to = SCHARS (str);
+  to_byte = SBYTES (str);
 
   /* Encoding routines determine the multibyteness of the source text
      by coding->src_multibyte.  */
@@ -6018,15 +6071,15 @@ encode_coding_string (str, coding, nocopy)
   coding->dst_multibyte = 0;
   if (! CODING_REQUIRE_ENCODING (coding))
     {
-      coding->consumed = STRING_BYTES (XSTRING (str));
-      coding->consumed_char = XSTRING (str)->size;
+      coding->consumed = SBYTES (str);
+      coding->consumed_char = SCHARS (str);
       if (STRING_MULTIBYTE (str))
        {
          str = Fstring_as_unibyte (str);
          nocopy = 1;
        }
-      coding->produced = STRING_BYTES (XSTRING (str));
-      coding->produced_char = XSTRING (str)->size;
+      coding->produced = SBYTES (str);
+      coding->produced_char = SCHARS (str);
       return (nocopy ? str : Fcopy_sequence (str));
     }
 
@@ -6036,11 +6089,11 @@ encode_coding_string (str, coding, nocopy)
   /* Try to skip the heading and tailing ASCIIs.  */
   if (coding->type != coding_type_ccl)
     {
-      SHRINK_CONVERSION_REGION (&from, &to_byte, coding, XSTRING (str)->data,
+      SHRINK_CONVERSION_REGION (&from, &to_byte, coding, SDATA (str),
                                1);
       if (from == to_byte)
        return (nocopy ? str : Fcopy_sequence (str));
-      shrinked_bytes = from + (STRING_BYTES (XSTRING (str)) - to_byte);
+      shrinked_bytes = from + (SBYTES (str) - to_byte);
     }
 
   len = encoding_buffer_size (coding, to_byte - from);
@@ -6049,7 +6102,7 @@ encode_coding_string (str, coding, nocopy)
   consumed = consumed_char = produced = produced_char = 0;
   while (1)
     {
-      result = encode_coding (coding, XSTRING (str)->data + from + consumed,
+      result = encode_coding (coding, SDATA (str) + from + consumed,
                              buf.data + produced, to_byte - from - consumed,
                              buf.size - produced);
       consumed += coding->consumed;
@@ -6071,12 +6124,12 @@ encode_coding_string (str, coding, nocopy)
 
   newstr = make_uninit_string (produced + shrinked_bytes);
   if (from > 0)
-    bcopy (XSTRING (str)->data, XSTRING (newstr)->data, from);
-  bcopy (buf.data, XSTRING (newstr)->data + from, produced);
+    STRING_COPYIN (newstr, 0, SDATA (str), from);
+  STRING_COPYIN (newstr, from, buf.data, produced);
   if (shrinked_bytes > from)
-    bcopy (XSTRING (str)->data + to_byte,
-          XSTRING (newstr)->data + from + produced,
-          shrinked_bytes - from);
+    STRING_COPYIN (newstr, from + produced,
+                  SDATA (str) + to_byte,
+                  shrinked_bytes - from);
 
   free_conversion_buffer (&buf);
   coding_free_composition_data (coding);
@@ -6117,7 +6170,7 @@ DEFUN ("read-non-nil-coding-system", Fread_non_nil_coding_system,
       val = Fcompleting_read (prompt, Vcoding_system_alist, Qnil,
                              Qt, Qnil, Qcoding_system_history, Qnil, Qnil);
     }
-  while (XSTRING (val)->size == 0);
+  while (SCHARS (val) == 0);
   return (Fintern (val, Qnil));
 }
 
@@ -6129,11 +6182,11 @@ If the user enters null input, return second argument DEFAULT-CODING-SYSTEM.  */
 {
   Lisp_Object val;
   if (SYMBOLP (default_coding_system))
-    XSETSTRING (default_coding_system, XSYMBOL (default_coding_system)->name);
+    default_coding_system = SYMBOL_NAME (default_coding_system);
   val = Fcompleting_read (prompt, Vcoding_system_alist, Qnil,
                          Qt, Qnil, Qcoding_system_history,
                          default_coding_system, Qnil);
-  return (XSTRING (val)->size == 0 ? Qnil : Fintern (val, Qnil));
+  return (SCHARS (val) == 0 ? Qnil : Fintern (val, Qnil));
 }
 
 DEFUN ("check-coding-system", Fcheck_coding_system, Scheck_coding_system,
@@ -6154,7 +6207,7 @@ The value of property should be a vector of length 5.  */)
 \f
 Lisp_Object
 detect_coding_system (src, src_bytes, highest, multibytep)
-     unsigned char *src;
+     const unsigned char *src;
      int src_bytes, highest;
      int multibytep;
 {
@@ -6213,7 +6266,7 @@ detect_coding_system (src, src_bytes, highest, multibytep)
        }
     }
   return (highest ? XCAR (val) : val);
-}  
+}
 
 DEFUN ("detect-coding-region", Fdetect_coding_region, Sdetect_coding_region,
        2, 3, 0,
@@ -6275,12 +6328,12 @@ highest priority.  */)
 {
   CHECK_STRING (string);
 
-  return detect_coding_system (XSTRING (string)->data,
+  return detect_coding_system (SDATA (string),
                               /* "+ 1" is to include the anchor byte
                                  `\0'.  With this, code detectors can
                                  handle the tailing bytes more
                                  accurately.  */
-                              STRING_BYTES (XSTRING (string)) + 1,
+                              SBYTES (string) + 1,
                               !NILP (highest),
                               STRING_MULTIBYTE (string));
 }
@@ -6291,14 +6344,17 @@ static Lisp_Object
 intersection (l1, l2)
      Lisp_Object l1, l2;
 {
-  Lisp_Object val;
+  Lisp_Object val = Fcons (Qnil, Qnil), tail;
 
-  for (val = Qnil; CONSP (l1); l1 = XCDR (l1))
+  for (tail = val; CONSP (l1); l1 = XCDR (l1))
     {
       if (!NILP (Fmemq (XCAR (l1), l2)))
-       val = Fcons (XCAR (l1), val);
+       {
+         XSETCDR (tail, Fcons (XCAR (l1), Qnil));
+         tail = XCDR (tail);
+       }
     }
-  return val;
+  return XCDR (val);
 }
 
 
@@ -6368,15 +6424,15 @@ DEFUN ("find-coding-systems-region-internal",
   Lisp_Object work_table, safe_codings;
   int non_ascii_p = 0;
   int single_byte_char_found = 0;
-  unsigned char *p1, *p1end, *p2, *p2end, *p;
+  const unsigned char *p1, *p1end, *p2, *p2end, *p;
 
   if (STRINGP (start))
     {
       if (!STRING_MULTIBYTE (start))
        return Qt;
-      p1 = XSTRING (start)->data, p1end = p1 + STRING_BYTES (XSTRING (start));
+      p1 = SDATA (start), p1end = p1 + SBYTES (start);
       p2 = p2end = p1end;
-      if (XSTRING (start)->size != STRING_BYTES (XSTRING (start)))
+      if (SCHARS (start) != SBYTES (start))
        non_ascii_p = 1;
     }
   else
@@ -6409,7 +6465,7 @@ DEFUN ("find-coding-systems-region-internal",
       for (p = p1; p < p1end && ASCII_BYTE_P (*p); p++);
       if (p == p1end)
        {
-         for (p = p2; p < p2end && ASCII_BYTE_P (*p); p++);      
+         for (p = p2; p < p2end && ASCII_BYTE_P (*p); p++);
          if (p == p2end)
            return Qt;
        }
@@ -6462,7 +6518,7 @@ code_convert_region1 (start, end, coding_system, encodep)
     return make_number (to - from);
 
   if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0)
-    error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data);
+    error ("Invalid coding system: %s", SDATA (SYMBOL_NAME (coding_system)));
 
   coding.mode |= CODING_MODE_LAST_BLOCK;
   coding.src_multibyte = coding.dst_multibyte
@@ -6517,7 +6573,7 @@ code_convert_string1 (string, coding_system, nocopy, encodep)
     return (NILP (nocopy) ? Fcopy_sequence (string) : string);
 
   if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0)
-    error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data);
+    error ("Invalid coding system: %s", SDATA (SYMBOL_NAME (coding_system)));
 
   coding.mode |= CODING_MODE_LAST_BLOCK;
   string = (encodep
@@ -6576,7 +6632,7 @@ code_convert_string_norecord (string, coding_system, encodep)
     return string;
 
   if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0)
-    error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data);
+    error ("Invalid coding system: %s", SDATA (SYMBOL_NAME (coding_system)));
 
   coding.composing = COMPOSITION_DISABLED;
   coding.mode |= CODING_MODE_LAST_BLOCK;
@@ -6607,7 +6663,7 @@ Return the corresponding character.  */)
     }
   else
     {
-      if ((s1 < 0x80 || s1 > 0x9F && s1 < 0xE0 || s1 > 0xEF)
+      if ((s1 < 0x80 || (s1 > 0x9F && s1 < 0xE0) || s1 > 0xEF)
          || (s2 < 0x40 || s2 == 0x7F || s2 > 0xFC))
        error ("Invalid Shift JIS code: %x", XFASTINT (code));
       DECODE_SJIS (s1, s2, c1, c2);
@@ -6821,7 +6877,14 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS ...)  */)
     error ("Invalid first argument");
   if (nargs < 1 + XINT (target_idx))
     error ("Too few arguments for operation: %s",
-          XSYMBOL (operation)->name->data);
+          SDATA (SYMBOL_NAME (operation)));
+  /* For write-region, if the 6th argument (i.e. VISIT, the 5th
+     argument to write-region) is string, it must be treated as a
+     target file name.  */
+  if (EQ (operation, Qwrite_region)
+      && nargs > 5
+      && STRINGP (args[5]))
+    target_idx = make_number (4);
   target = args[XINT (target_idx) + 1];
   if (!(STRINGP (target)
        || (EQ (operation, Qopen_network_stream) && INTEGERP (target))))
@@ -6941,7 +7004,7 @@ init_coding_once ()
 {
   int i;
 
-  /* Emacs' internal format specific initialize routine.  */ 
+  /* Emacs' internal format specific initialize routine.  */
   for (i = 0; i <= 0x20; i++)
     emacs_code_class[i] = EMACS_control_code;
   emacs_code_class[0x0A] = EMACS_linefeed_code;
@@ -7108,7 +7171,7 @@ syms_of_coding ()
      But don't staticpro it here--that is done in alloc.c.  */
   Qchar_table_extra_slots = intern ("char-table-extra-slots");
   Fput (Qsafe_chars, Qchar_table_extra_slots, make_number (0));
-  Fput (Qchar_coding_system, Qchar_table_extra_slots, make_number (1));
+  Fput (Qchar_coding_system, Qchar_table_extra_slots, make_number (2));
 
   Qvalid_codes = intern ("valid-codes");
   staticpro (&Qvalid_codes);
@@ -7227,7 +7290,8 @@ the file contents.
 If VAL is a cons of coding systems, the car part is used for decoding,
 and the cdr part is used for encoding.
 If VAL is a function symbol, the function must return a coding system
-or a cons of coding systems which are used as above.
+or a cons of coding systems which are used as above.  The function gets
+the arguments with which `find-operation-coding-system' was called.
 
 See also the function `find-operation-coding-system'
 and the variable `auto-coding-alist'.  */);
@@ -7383,7 +7447,7 @@ emacs_strerror (error_number)
       Lisp_Object dec = code_convert_string_norecord (build_string (str),
                                                      Vlocale_coding_system,
                                                      0);
-      str = (char *) XSTRING (dec)->data;
+      str = (char *) SDATA (dec);
     }
 
   return str;