]> code.delx.au - gnu-emacs/blobdiff - src/coding.c
(code_convert_string): Add record_unwind_protect to
[gnu-emacs] / src / coding.c
index cf6bab223bb5ad7bac0fa3a61829fd99f905800f..4bf0b2aea81bb73bbb66cad588ebc1f4720ddefd 100644 (file)
@@ -224,10 +224,10 @@ encode_coding_XXX (coding, source, destination, src_bytes, dst_bytes)
       }                                                \
     else                                       \
       {                                                \
-       *dst++ = (c);                           \
+       /* If ASCII charset is invoked to GR,   \
+          we must reset MSB now.  */           \
+       *dst++ = (c) & 0x7F;                    \
        coding->produced_char++;                \
-       if ((c) >= 0x80)                        \
-         coding->fake_multibyte = 1;           \
       }                                                \
   } while (0)
 
@@ -411,6 +411,12 @@ Lisp_Object Vcharset_revision_alist;
 /* Default coding systems used for process I/O.  */
 Lisp_Object Vdefault_process_coding_system;
 
+/* Global flag to tell that we can't call post-read-conversion and
+   pre-write-conversion functions.  Usually the value is zero, but it
+   is set to 1 temporarily while such functions are running.  This is
+   to avoid infinite recursive call.  */
+static int inhibit_pre_post_conversion;
+
 \f
 /*** 2. Emacs internal format (emacs-mule) handlers ***/
 
@@ -1610,32 +1616,52 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
       dst = encode_invocation_designation (charset, coding, dst);      \
   } while (1)
 
-#define ENCODE_ISO_CHARACTER(charset, c1, c2)                  \
-  do {                                                         \
-    int c_alt, charset_alt;                                    \
-    if (!NILP (translation_table)                              \
-       && ((c_alt = translate_char (translation_table, -1,     \
-                                    charset, c1, c2))          \
-           >= 0))                                              \
-      SPLIT_CHAR (c_alt, charset_alt, c1, c2);                 \
-    else                                                       \
-      charset_alt = charset;                                   \
-    if (CHARSET_DIMENSION (charset_alt) == 1)                  \
-      {                                                                \
-       if (charset == CHARSET_ASCII                            \
-           && coding->flags & CODING_FLAG_ISO_USE_ROMAN)       \
-         charset_alt = charset_latin_jisx0201;                 \
-       ENCODE_ISO_CHARACTER_DIMENSION1 (charset_alt, c1);      \
-      }                                                                \
-    else                                                       \
-      {                                                                \
-       if (charset == charset_jisx0208                         \
-           && coding->flags & CODING_FLAG_ISO_USE_OLDJIS)      \
-         charset_alt = charset_jisx0208_1978;                  \
-       ENCODE_ISO_CHARACTER_DIMENSION2 (charset_alt, c1, c2);  \
-      }                                                                \
-    if (! COMPOSING_P (coding->composing))                     \
-      coding->consumed_char++;                                 \
+#define ENCODE_ISO_CHARACTER(charset, c1, c2)                          \
+  do {                                                                 \
+    int c_alt, charset_alt;                                            \
+    if (!NILP (translation_table)                                      \
+       && ((c_alt = translate_char (translation_table, -1,             \
+                                    charset, c1, c2))                  \
+           >= 0))                                                      \
+      SPLIT_CHAR (c_alt, charset_alt, c1, c2);                         \
+    else                                                               \
+      charset_alt = charset;                                           \
+    if (CHARSET_DEFINED_P (charset_alt))                               \
+      {                                                                        \
+       if (CHARSET_DIMENSION (charset_alt) == 1)                       \
+         {                                                             \
+           if (charset == CHARSET_ASCII                                \
+               && coding->flags & CODING_FLAG_ISO_USE_ROMAN)           \
+             charset_alt = charset_latin_jisx0201;                     \
+           ENCODE_ISO_CHARACTER_DIMENSION1 (charset_alt, c1);          \
+         }                                                             \
+       else                                                            \
+         {                                                             \
+           if (charset == charset_jisx0208                             \
+               && coding->flags & CODING_FLAG_ISO_USE_OLDJIS)          \
+             charset_alt = charset_jisx0208_1978;                      \
+           ENCODE_ISO_CHARACTER_DIMENSION2 (charset_alt, c1, c2);      \
+         }                                                             \
+      }                                                                        \
+    else                                                               \
+      {                                                                        \
+       if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS)                 \
+         {                                                             \
+           *dst++ = charset & 0x7f;                                    \
+           *dst++ = c1 & 0x7f;                                         \
+           if (c2)                                                     \
+             *dst++ = c2 & 0x7f;                                       \
+         }                                                             \
+       else                                                            \
+         {                                                             \
+           *dst++ = charset;                                           \
+           *dst++ = c1;                                                \
+           if (c2)                                                     \
+             *dst++ = c2;                                              \
+         }                                                             \
+      }                                                                        \
+    if (! COMPOSING_P (coding->composing))                             \
+      coding->consumed_char++;                                         \
   } while (0)
 
 /* Produce designation and invocation codes at a place pointed by DST
@@ -1882,6 +1908,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
       switch (emacs_code_class[c1])
        {
        case EMACS_ascii_code:
+         c2 = 0;
          ENCODE_ISO_CHARACTER (CHARSET_ASCII, c1, /* dummy */ c2);
          break;
 
@@ -1923,6 +1950,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
 
        case EMACS_leading_code_2:
          ONE_MORE_BYTE (c2);
+         c3 = 0;
          if (c2 < 0xA0)
            {
              /* invalid sequence */
@@ -1936,6 +1964,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
 
        case EMACS_leading_code_3:
          TWO_MORE_BYTES (c2, c3);
+         c4 = 0;
          if (c2 < 0xA0 || c3 < 0xA0)
            {
              /* invalid sequence */
@@ -2132,6 +2161,8 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
       {                                                                \
        if (sjis_p && charset_alt == charset_katakana_jisx0201) \
          *dst++ = c1;                                          \
+       else if (sjis_p && charset_alt == charset_latin_jisx0201) \
+         *dst++ = c1 & 0x7F;                                   \
        else                                                    \
          {                                                     \
            *dst++ = charset_alt, *dst++ = c1;                  \
@@ -2141,7 +2172,8 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
     else                                                       \
       {                                                                \
        c1 &= 0x7F, c2 &= 0x7F;                                 \
-       if (sjis_p && charset_alt == charset_jisx0208)          \
+       if (sjis_p && (charset_alt == charset_jisx0208          \
+                      || charset_alt == charset_jisx0208_1978))\
          {                                                     \
            unsigned char s1, s2;                               \
                                                                \
@@ -2289,7 +2321,10 @@ decode_coding_sjis_big5 (coding, source, destination,
          coding->produced_char++;
        }
       else if (c1 < 0x80)
-       DECODE_SJIS_BIG5_CHARACTER (charset_ascii, c1, /* dummy */ c2);
+        {
+          c2 = 0;               /* avoid warning */
+          DECODE_SJIS_BIG5_CHARACTER (charset_ascii, c1, /* dummy */ c2);
+        }
       else
        {
          if (sjis_p)
@@ -2308,8 +2343,11 @@ decode_coding_sjis_big5 (coding, source, destination,
                }
              else if (c1 < 0xE0)
                /* SJIS -> JISX0201-Kana */
-               DECODE_SJIS_BIG5_CHARACTER (charset_katakana_jisx0201, c1,
-                                           /* dummy */ c2);
+               {
+                 c2 = 0;       /* avoid warning */
+                 DECODE_SJIS_BIG5_CHARACTER (charset_katakana_jisx0201, c1,
+                                             /* dummy */ c2);
+               }
              else
                goto label_invalid_code_1;
            }
@@ -2554,7 +2592,11 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
   coding->fake_multibyte = 0;
 
   if (src_bytes <= 0)
-    return result;
+    {
+      coding->produced = coding->produced_char = 0;
+      coding->consumed = coding->consumed_char = 0;
+      return result;
+    }
 
   switch (coding->eol_type)
     {
@@ -2905,8 +2947,14 @@ setup_coding_system (coding_system, coding)
      `post-read-conversion', `pre-write-conversion',
      `translation-table-for-decode', `translation-table-for-encode'.  */
   plist = XVECTOR (coding_spec)->contents[3];
-  coding->post_read_conversion = Fplist_get (plist, Qpost_read_conversion);
-  coding->pre_write_conversion = Fplist_get (plist, Qpre_write_conversion);
+  /* Pre & post conversion functions should be disabled if
+     inhibit_eol_conversion is nozero.  This is the case that a code
+     conversion function is called while those functions are running.  */
+  if (! inhibit_pre_post_conversion)
+    {
+      coding->post_read_conversion = Fplist_get (plist, Qpost_read_conversion);
+      coding->pre_write_conversion = Fplist_get (plist, Qpre_write_conversion);
+    }
   val = Fplist_get (plist, Qtranslation_table_for_decode);
   if (SYMBOLP (val))
     val = Fget (val, Qtranslation_table_for_decode);
@@ -2938,9 +2986,9 @@ setup_coding_system (coding_system, coding)
       bzero (coding->safe_charsets, MAX_CHARSET + 1);
       while (CONSP (val))
        {
-         if ((i = get_charset_id (XCONS (val)->car)) >= 0)
+         if ((i = get_charset_id (XCAR (val))) >= 0)
            coding->safe_charsets[i] = 1;
-         val = XCONS (val)->cdr;
+         val = XCDR (val);
        }
     }
 
@@ -3006,12 +3054,12 @@ setup_coding_system (coding_system, coding)
        val = Vcharset_revision_alist;
        while (CONSP (val))
          {
-           charset = get_charset_id (Fcar_safe (XCONS (val)->car));
+           charset = get_charset_id (Fcar_safe (XCAR (val)));
            if (charset >= 0
-               && (temp = Fcdr_safe (XCONS (val)->car), INTEGERP (temp))
+               && (temp = Fcdr_safe (XCAR (val)), INTEGERP (temp))
                && (i = XINT (temp), (i >= 0 && (i + '@') < 128)))
              CODING_SPEC_ISO_REVISION_NUMBER (coding, charset) = i;
-           val = XCONS (val)->cdr;
+           val = XCDR (val);
          }
 
        /* Checks FLAGS[REG] (REG = 0, 1, 2 3) and decide designations.
@@ -3048,28 +3096,28 @@ setup_coding_system (coding_system, coding)
                tail = flags[i];
 
                coding->flags |= CODING_FLAG_ISO_DESIGNATION;
-               if (INTEGERP (XCONS (tail)->car)
-                   && (charset = XINT (XCONS (tail)->car),
+               if (INTEGERP (XCAR (tail))
+                   && (charset = XINT (XCAR (tail)),
                        CHARSET_VALID_P (charset))
-                   || (charset = get_charset_id (XCONS (tail)->car)) >= 0)
+                   || (charset = get_charset_id (XCAR (tail))) >= 0)
                  {
                    CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = charset;
                    CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) =i;
                  }
                else
                  CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = -1;
-               tail = XCONS (tail)->cdr;
+               tail = XCDR (tail);
                while (CONSP (tail))
                  {
-                   if (INTEGERP (XCONS (tail)->car)
-                       && (charset = XINT (XCONS (tail)->car),
+                   if (INTEGERP (XCAR (tail))
+                       && (charset = XINT (XCAR (tail)),
                            CHARSET_VALID_P (charset))
-                       || (charset = get_charset_id (XCONS (tail)->car)) >= 0)
+                       || (charset = get_charset_id (XCAR (tail))) >= 0)
                      CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset)
                        = i;
-                   else if (EQ (XCONS (tail)->car, Qt))
+                   else if (EQ (XCAR (tail), Qt))
                      reg_bits |= 1 << i;
-                   tail = XCONS (tail)->cdr;
+                   tail = XCDR (tail);
                  }
              }
            else
@@ -3129,22 +3177,12 @@ setup_coding_system (coding_system, coding)
       coding->common_flags
        |= CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK;
       {
-       Lisp_Object val;
-       Lisp_Object decoder, encoder;
-
        val = XVECTOR (coding_spec)->contents[4];
-       if (CONSP  (val)
-           && SYMBOLP (XCONS (val)->car)
-           && !NILP (decoder = Fget (XCONS (val)->car, Qccl_program_idx))
-           && !NILP (decoder = Fcdr (Faref (Vccl_program_table, decoder)))
-           && SYMBOLP (XCONS (val)->cdr)
-           && !NILP (encoder = Fget (XCONS (val)->cdr, Qccl_program_idx))
-           && !NILP (encoder = Fcdr (Faref (Vccl_program_table, encoder))))
-         {
-           setup_ccl_program (&(coding->spec.ccl.decoder), decoder);
-           setup_ccl_program (&(coding->spec.ccl.encoder), encoder);
-         }
-       else
+       if (! CONSP (val)
+           || setup_ccl_program (&(coding->spec.ccl.decoder),
+                                 XCAR (val)) < 0
+           || setup_ccl_program (&(coding->spec.ccl.encoder),
+                                 XCDR (val)) < 0)
          goto label_invalid_coding_system;
 
        bzero (coding->spec.ccl.valid_codes, 256);
@@ -3153,18 +3191,18 @@ setup_coding_system (coding_system, coding)
          {
            Lisp_Object this;
 
-           for (; CONSP (val); val = XCONS (val)->cdr)
+           for (; CONSP (val); val = XCDR (val))
              {
-               this = XCONS (val)->car;
+               this = XCAR (val);
                if (INTEGERP (this)
                    && XINT (this) >= 0 && XINT (this) < 256)
                  coding->spec.ccl.valid_codes[XINT (this)] = 1;
                else if (CONSP (this)
-                        && INTEGERP (XCONS (this)->car)
-                        && INTEGERP (XCONS (this)->cdr))
+                        && INTEGERP (XCAR (this))
+                        && INTEGERP (XCDR (this)))
                  {
-                   int start = XINT (XCONS (this)->car);
-                   int end = XINT (XCONS (this)->cdr);
+                   int start = XINT (XCAR (this));
+                   int end = XINT (XCDR (this));
 
                    if (start >= 0 && start <= end && end < 256)
                      while (start <= end)
@@ -3217,6 +3255,7 @@ setup_raw_text_coding_system (coding)
            coding->symbol
              = XVECTOR (subsidiaries)->contents[coding->eol_type];
        }
+      setup_coding_system (coding->symbol, coding);
     }
   return;
 }
@@ -3706,7 +3745,17 @@ ccl_coding_driver (coding, source, destination, src_bytes, dst_bytes, encodep)
 
 /* See "GENERAL NOTES about `decode_coding_XXX ()' functions".  Before
    decoding, it may detect coding system and format of end-of-line if
-   those are not yet decided.  */
+   those are not yet decided.
+
+   This function does not make full use of DESTINATION buffer.  For
+   instance, if coding->type is coding_type_iso2022, it uses only
+   (DST_BYTES - 7) bytes of DESTINATION buffer.  In the case that
+   DST_BYTES is decided by the function decoding_buffer_size, it
+   contains extra 256 bytes (defined by CONVERSION_BUFFER_EXTRA_ROOM).
+   So, this function can decode the full SOURCE.  But, in the other
+   case, if you want to avoid carry over, you must supply at least 7
+   bytes more area in DESTINATION buffer than expected maximum bytes
+   that will be produced by this function.  */
 
 int
 decode_coding (coding, source, destination, src_bytes, dst_bytes)
@@ -3789,7 +3838,17 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
   return result;
 }
 
-/* See "GENERAL NOTES about `encode_coding_XXX ()' functions".  */
+/* See "GENERAL NOTES about `encode_coding_XXX ()' functions".
+
+   This function does not make full use of DESTINATION buffer.  For
+   instance, if coding->type is coding_type_iso2022, it uses only
+   (DST_BYTES - 20) bytes of DESTINATION buffer.  In the case that
+   DST_BYTES is decided by the function encoding_buffer_size, it
+   contains extra 256 bytes (defined by CONVERSION_BUFFER_EXTRA_ROOM).
+   So, this function can encode the full SOURCE.  But, in the other
+   case, if you want to avoid carry over, you must supply at least 20
+   bytes more area in DESTINATION buffer than expected maximum bytes
+   that will be produced by this function.  */
 
 int
 encode_coding (coding, source, destination, src_bytes, dst_bytes)
@@ -4174,6 +4233,14 @@ static int shrink_conversion_region_threshhold = 1024;
       }                                                                        \
   } while (0)
 
+static Lisp_Object
+code_convert_region_unwind (dummy)
+     Lisp_Object dummy;
+{
+  inhibit_pre_post_conversion = 0;
+  return Qnil;
+}
+
 /* Decode (if ENCODEP is zero) or encode (if ENCODEP is nonzero) the
    text from FROM to TO (byte positions are FROM_BYTE and TO_BYTE) by
    coding system CODING, and return the status code of code conversion
@@ -4298,9 +4365,18 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
          new buffer.  */
       struct buffer *prev = current_buffer;
       Lisp_Object new;
+      int count = specpdl_ptr - specpdl;
 
+      record_unwind_protect (code_convert_region_unwind, Qnil);
+      /* We should not call any more pre-write/post-read-conversion
+         functions while this pre-write-conversion is running.  */
+      inhibit_pre_post_conversion = 1;
       call2 (coding->pre_write_conversion,
             make_number (from), make_number (to));
+      inhibit_pre_post_conversion = 0;
+      /* Discard the unwind protect.  */
+      specpdl_ptr--;
+
       if (current_buffer != prev)
        {
          len = ZV - BEGV;
@@ -4385,10 +4461,10 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
   ZV_BYTE -= len_byte;
   Z_BYTE -= len_byte;
 
-  if (GPT - BEG < beg_unchanged)
-    beg_unchanged = GPT - BEG;
-  if (Z - GPT < end_unchanged)
-    end_unchanged = Z - GPT;
+  if (GPT - BEG < BEG_UNCHANGED)
+    BEG_UNCHANGED = GPT - BEG;
+  if (Z - GPT < END_UNCHANGED)
+    END_UNCHANGED = Z - GPT;
 
   for (;;)
     {
@@ -4425,6 +4501,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
       if (! encodep && result == CODING_FINISH_INCONSISTENT_EOL)
        {
          unsigned char *pend = dst, *p = pend - inserted_byte;
+         Lisp_Object eol_type;
 
          /* Encode LFs back to the original eol format (CR or CRLF).  */
          if (coding->eol_type == CODING_EOL_CR)
@@ -4438,7 +4515,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
              while (p < pend) if (*p++ == '\n') count++;
              if (src - dst < count)
                {
-                 /* We don't have sufficient room for putting LFs
+                 /* We don't have sufficient room for encoding LFs
                     back to CRLF.  We must record converted and
                     not-yet-converted text back to the buffer
                     content, enlarge the gap, then record them out of
@@ -4471,8 +4548,14 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
          /* Suppress eol-format conversion in the further conversion.  */
          coding->eol_type = CODING_EOL_LF;
 
-         /* Restore the original symbol.  */
-         coding->symbol = saved_coding_symbol;
+         /* Set the coding system symbol to that for Unix-like EOL.  */
+         eol_type = Fget (saved_coding_symbol, Qeol_type);
+         if (VECTORP (eol_type)
+             && XVECTOR (eol_type)->size == 3
+             && SYMBOLP (XVECTOR (eol_type)->contents[CODING_EOL_LF]))
+           coding->symbol = XVECTOR (eol_type)->contents[CODING_EOL_LF];
+         else
+           coding->symbol = saved_coding_symbol;
          
          continue;
        }
@@ -4572,11 +4655,19 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
   if (! encodep && ! NILP (coding->post_read_conversion))
     {
       Lisp_Object val;
+      int count = specpdl_ptr - specpdl;
 
       if (from != PT)
        TEMP_SET_PT_BOTH (from, from_byte);
       prev_Z = Z;
+      record_unwind_protect (code_convert_region_unwind, Qnil);
+      /* We should not call any more pre-write/post-read-conversion
+         functions while this post-read-conversion is running.  */
+      inhibit_pre_post_conversion = 1;
       val = call1 (coding->post_read_conversion, make_number (inserted));
+      inhibit_pre_post_conversion = 0;
+      /* Discard the unwind protect.  */
+      specpdl_ptr--;
       CHECK_NUMBER (val, 0);
       inserted += Z - prev_Z;
     }
@@ -4617,34 +4708,34 @@ code_convert_string (str, coding, encodep, nocopy)
   int result;
 
   saved_coding_symbol = Qnil;
-  if (encodep && !NILP (coding->pre_write_conversion)
-      || !encodep && !NILP (coding->post_read_conversion))
+  if ((encodep && !NILP (coding->pre_write_conversion)
+       || !encodep && !NILP (coding->post_read_conversion)))
     {
       /* Since we have to call Lisp functions which assume target text
-         is in a buffer, after setting a temporary buffer, call
-         code_convert_region.  */
+        is in a buffer, after setting a temporary buffer, call
+        code_convert_region.  */
       int count = specpdl_ptr - specpdl;
       struct buffer *prev = current_buffer;
+      int multibyte = STRING_MULTIBYTE (str);
 
       record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+      record_unwind_protect (code_convert_region_unwind, Qnil);
+      inhibit_pre_post_conversion = 1;
+      GCPRO1 (str);
       temp_output_buffer_setup (" *code-converting-work*");
       set_buffer_internal (XBUFFER (Vstandard_output));
-      if (encodep)
-       insert_from_string (str, 0, 0, to, to_byte, 0);
-      else
-       {
-         /* We must insert the contents of STR as is without
-             unibyte<->multibyte conversion.  */
-         current_buffer->enable_multibyte_characters = Qnil;
-         insert_from_string (str, 0, 0, to_byte, to_byte, 0);
-         current_buffer->enable_multibyte_characters = Qt;
-       }
+      /* 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 ();                /* for safety */
+      current_buffer->enable_multibyte_characters = multibyte ? Qt : Qnil;
+      insert_from_string (str, 0, 0, to, to_byte, 0);
+      UNGCPRO;
       code_convert_region (BEGV, BEGV_BYTE, ZV, ZV_BYTE, coding, encodep, 1);
-      if (encodep)
-       /* We must return the buffer contents as unibyte string.  */
-       current_buffer->enable_multibyte_characters = Qnil;
+      /* Make a unibyte string if we are encoding, otherwise make a
+         multibyte string.  */
+      Fset_buffer_multibyte (encodep ? Qnil : Qt);
       str = make_buffer_string (BEGV, ZV, 0);
-      set_buffer_internal (prev);
       return unbind_to (count, str);
     }
 
@@ -4822,13 +4913,13 @@ detect_coding_system (src, src_bytes, highest)
 
   /* At first, gather possible coding systems in VAL.  */
   val = Qnil;
-  for (tmp = Vcoding_category_list; !NILP (tmp); tmp = XCONS (tmp)->cdr)
+  for (tmp = Vcoding_category_list; !NILP (tmp); tmp = XCDR (tmp))
     {
       int idx
-       = XFASTINT (Fget (XCONS (tmp)->car, Qcoding_category_index));
+       = XFASTINT (Fget (XCAR (tmp), Qcoding_category_index));
       if (coding_mask & (1 << idx))
        {
-         val = Fcons (Fsymbol_value (XCONS (tmp)->car), val);
+         val = Fcons (Fsymbol_value (XCAR (tmp)), val);
          if (highest)
            break;
        }
@@ -4837,18 +4928,18 @@ detect_coding_system (src, src_bytes, highest)
     val = Fnreverse (val);
 
   /* Then, replace the elements with subsidiary coding systems.  */
-  for (tmp = val; !NILP (tmp); tmp = XCONS (tmp)->cdr)
+  for (tmp = val; !NILP (tmp); tmp = XCDR (tmp))
     {
       if (eol_type != CODING_EOL_UNDECIDED
          && eol_type != CODING_EOL_INCONSISTENT)
        {
          Lisp_Object eol;
-         eol = Fget (XCONS (tmp)->car, Qeol_type);
+         eol = Fget (XCAR (tmp), Qeol_type);
          if (VECTORP (eol))
-           XCONS (tmp)->car = XVECTOR (eol)->contents[eol_type];
+           XCAR (tmp) = XVECTOR (eol)->contents[eol_type];
        }
     }
-  return (highest ? XCONS (val)->car : val);
+  return (highest ? XCAR (val) : val);
 }  
 
 DEFUN ("detect-coding-region", Fdetect_coding_region, Sdetect_coding_region,
@@ -5270,18 +5361,18 @@ which is a list of all the arguments given to this function.")
   if (NILP (chain))
     return Qnil;
 
-  for (; CONSP (chain); chain = XCONS (chain)->cdr)
+  for (; CONSP (chain); chain = XCDR (chain))
     {
       Lisp_Object elt;
-      elt = XCONS (chain)->car;
+      elt = XCAR (chain);
 
       if (CONSP (elt)
          && ((STRINGP (target)
-              && STRINGP (XCONS (elt)->car)
-              && fast_string_match (XCONS (elt)->car, target) >= 0)
-             || (INTEGERP (target) && EQ (target, XCONS (elt)->car))))
+              && STRINGP (XCAR (elt))
+              && fast_string_match (XCAR (elt), target) >= 0)
+             || (INTEGERP (target) && EQ (target, XCAR (elt)))))
        {
-         val = XCONS (elt)->cdr;
+         val = XCDR (elt);
          /* Here, if VAL is both a valid coding system and a valid
              function symbol, we return VAL as a coding system.  */
          if (CONSP (val))
@@ -5352,13 +5443,13 @@ This function is internal use only.")
 
   while (CONSP (val) && i < CODING_CATEGORY_IDX_MAX)
     {
-      if (! SYMBOLP (XCONS (val)->car))
+      if (! SYMBOLP (XCAR (val)))
        break;
-      idx = XFASTINT (Fget (XCONS (val)->car, Qcoding_category_index));
+      idx = XFASTINT (Fget (XCAR (val), Qcoding_category_index));
       if (idx >= CODING_CATEGORY_IDX_MAX)
        break;
       coding_priorities[i++] = (1 << idx);
-      val = XCONS (val)->cdr;
+      val = XCDR (val);
     }
   /* If coding-category-list is valid and contains all coding
      categories, `i' should be CODING_CATEGORY_IDX_MAX now.  If not,
@@ -5439,6 +5530,8 @@ init_coding_once ()
 #else
   system_eol_type = CODING_EOL_LF;
 #endif
+
+  inhibit_pre_post_conversion = 0;
 }
 
 #ifdef emacs
@@ -5618,11 +5711,16 @@ There are three such tables, `file-coding-system-alist',\n\
 
   DEFVAR_LISP ("coding-system-for-write", &Vcoding_system_for_write,
     "Specify the coding system for write operations.\n\
-It is useful to bind this variable with `let', but do not set it globally.\n\
-If the value is a coding system, it is used for encoding on write operation.\n\
-If not, an appropriate element is used from one of the coding system alists:\n\
+Programs bind this variable with `let', but you should not set it globally.\n\
+If the value is a coding system, it is used for encoding of output,\n\
+when writing it to a file and when sending it to a file or subprocess.\n\
+\n\
+If this does not specify a coding system, an appropriate element\n\
+is used from one of the coding system alists:\n\
 There are three such tables, `file-coding-system-alist',\n\
-`process-coding-system-alist', and `network-coding-system-alist'.");
+`process-coding-system-alist', and `network-coding-system-alist'.\n\
+For output to files, if the above procedure does not specify a coding system,\n\
+the value of `buffer-file-coding-system' is used.");
   Vcoding_system_for_write = Qnil;
 
   DEFVAR_LISP ("last-coding-system-used", &Vlast_coding_system_used,