*** empty log message ***
[bpt/emacs.git] / src / coding.c
index d95da9b..bd7e219 100644 (file)
@@ -212,8 +212,8 @@ decode_coding_XXXX (coding)
      when there's no room in CHARBUF for a decoded character.  */
   unsigned char *src_base;
   /* A buffer to produce decoded characters.  */
-  int *charbuf = coding->charbuf;
-  int *charbuf_end = charbuf + coding->charbuf_size;
+  int *charbuf = coding->charbuf + coding->charbuf_used;
+  int *charbuf_end = coding->charbuf + coding->charbuf_size;
   int multibytep = coding->src_multibyte;
 
   while (1)
@@ -411,47 +411,6 @@ Lisp_Object Vtranslation_table_for_input;
 Lisp_Object Vsjis_coding_system;
 Lisp_Object Vbig5_coding_system;
 
-static void record_conversion_result (struct coding_system *coding,
-                                     enum coding_result_code result);
-static int detect_coding_utf_8 P_ ((struct coding_system *,
-                                   struct coding_detection_info *info));
-static void decode_coding_utf_8 P_ ((struct coding_system *));
-static int encode_coding_utf_8 P_ ((struct coding_system *));
-
-static int detect_coding_utf_16 P_ ((struct coding_system *,
-                                    struct coding_detection_info *info));
-static void decode_coding_utf_16 P_ ((struct coding_system *));
-static int encode_coding_utf_16 P_ ((struct coding_system *));
-
-static int detect_coding_iso_2022 P_ ((struct coding_system *,
-                                      struct coding_detection_info *info));
-static void decode_coding_iso_2022 P_ ((struct coding_system *));
-static int encode_coding_iso_2022 P_ ((struct coding_system *));
-
-static int detect_coding_emacs_mule P_ ((struct coding_system *,
-                                        struct coding_detection_info *info));
-static void decode_coding_emacs_mule P_ ((struct coding_system *));
-static int encode_coding_emacs_mule P_ ((struct coding_system *));
-
-static int detect_coding_sjis P_ ((struct coding_system *,
-                                  struct coding_detection_info *info));
-static void decode_coding_sjis P_ ((struct coding_system *));
-static int encode_coding_sjis P_ ((struct coding_system *));
-
-static int detect_coding_big5 P_ ((struct coding_system *,
-                                  struct coding_detection_info *info));
-static void decode_coding_big5 P_ ((struct coding_system *));
-static int encode_coding_big5 P_ ((struct coding_system *));
-
-static int detect_coding_ccl P_ ((struct coding_system *,
-                                 struct coding_detection_info *info));
-static void decode_coding_ccl P_ ((struct coding_system *));
-static int encode_coding_ccl P_ ((struct coding_system *));
-
-static void decode_coding_raw_text P_ ((struct coding_system *));
-static int encode_coding_raw_text P_ ((struct coding_system *));
-
-
 /* ISO2022 section */
 
 #define CODING_ISO_INITIAL(coding, reg)                        \
@@ -858,6 +817,85 @@ static struct coding_system coding_categories[coding_category_max];
   } while (0)
 
 
+/* Prototypes for static functions.  */
+static void record_conversion_result P_ ((struct coding_system *coding,
+                                         enum coding_result_code result));
+static int detect_coding_utf_8 P_ ((struct coding_system *,
+                                   struct coding_detection_info *info));
+static void decode_coding_utf_8 P_ ((struct coding_system *));
+static int encode_coding_utf_8 P_ ((struct coding_system *));
+
+static int detect_coding_utf_16 P_ ((struct coding_system *,
+                                    struct coding_detection_info *info));
+static void decode_coding_utf_16 P_ ((struct coding_system *));
+static int encode_coding_utf_16 P_ ((struct coding_system *));
+
+static int detect_coding_iso_2022 P_ ((struct coding_system *,
+                                      struct coding_detection_info *info));
+static void decode_coding_iso_2022 P_ ((struct coding_system *));
+static int encode_coding_iso_2022 P_ ((struct coding_system *));
+
+static int detect_coding_emacs_mule P_ ((struct coding_system *,
+                                        struct coding_detection_info *info));
+static void decode_coding_emacs_mule P_ ((struct coding_system *));
+static int encode_coding_emacs_mule P_ ((struct coding_system *));
+
+static int detect_coding_sjis P_ ((struct coding_system *,
+                                  struct coding_detection_info *info));
+static void decode_coding_sjis P_ ((struct coding_system *));
+static int encode_coding_sjis P_ ((struct coding_system *));
+
+static int detect_coding_big5 P_ ((struct coding_system *,
+                                  struct coding_detection_info *info));
+static void decode_coding_big5 P_ ((struct coding_system *));
+static int encode_coding_big5 P_ ((struct coding_system *));
+
+static int detect_coding_ccl P_ ((struct coding_system *,
+                                 struct coding_detection_info *info));
+static void decode_coding_ccl P_ ((struct coding_system *));
+static int encode_coding_ccl P_ ((struct coding_system *));
+
+static void decode_coding_raw_text P_ ((struct coding_system *));
+static int encode_coding_raw_text P_ ((struct coding_system *));
+
+static void coding_set_source P_ ((struct coding_system *));
+static void coding_set_destination P_ ((struct coding_system *));
+static void coding_alloc_by_realloc P_ ((struct coding_system *, EMACS_INT));
+static void coding_alloc_by_making_gap P_ ((struct coding_system *,
+                                           EMACS_INT));
+static unsigned char *alloc_destination P_ ((struct coding_system *,
+                                            EMACS_INT, unsigned char *));
+static void setup_iso_safe_charsets P_ ((Lisp_Object));
+static unsigned char *encode_designation_at_bol P_ ((struct coding_system *,
+                                                    int *, int *,
+                                                    unsigned char *));
+static int detect_eol P_ ((const unsigned char *,
+                          EMACS_INT, enum coding_category));
+static Lisp_Object adjust_coding_eol_type P_ ((struct coding_system *, int));
+static void decode_eol P_ ((struct coding_system *));
+static Lisp_Object get_translation_table P_ ((Lisp_Object, int, int *));
+static Lisp_Object get_translation P_ ((Lisp_Object, int *, int *,
+                                       int, int *, int *));
+static int produce_chars P_ ((struct coding_system *, Lisp_Object, int));
+static INLINE void produce_composition P_ ((struct coding_system *, int *,
+                                           EMACS_INT));
+static INLINE void produce_charset P_ ((struct coding_system *, int *,
+                                       EMACS_INT));
+static void produce_annotation P_ ((struct coding_system *, EMACS_INT));
+static int decode_coding P_ ((struct coding_system *));
+static INLINE int *handle_composition_annotation P_ ((EMACS_INT, EMACS_INT,
+                                                     struct coding_system *, 
+                                                     int *, EMACS_INT *));
+static INLINE int *handle_charset_annotation P_ ((EMACS_INT, EMACS_INT,
+                                                 struct coding_system *,
+                                                 int *, EMACS_INT *));
+static void consume_chars P_ ((struct coding_system *, Lisp_Object, int));
+static int encode_coding P_ ((struct coding_system *));
+static Lisp_Object make_conversion_work_buffer P_ ((int));
+static Lisp_Object code_conversion_restore P_ ((Lisp_Object));
+static INLINE int char_encodable_p P_ ((int, Lisp_Object));
+static Lisp_Object make_subsidiaries P_ ((Lisp_Object));
+
 static void
 record_conversion_result (struct coding_system *coding,
                          enum coding_result_code result)
@@ -1025,15 +1063,14 @@ alloc_destination (coding, nbytes, dst)
 
 /* Maximum length of annotation data (sum of annotations for
    composition and charset).  */
-#define MAX_ANNOTATION_LENGTH (5 + (MAX_COMPOSITION_COMPONENTS * 2) - 1 + 5)
+#define MAX_ANNOTATION_LENGTH (4 + (MAX_COMPOSITION_COMPONENTS * 2) - 1 + 4)
 
 /* An annotation data is stored in the array coding->charbuf in this
    format:
-     [ -LENGTH ANNOTATION_MASK FROM TO ... ]
+     [ -LENGTH ANNOTATION_MASK NCHARS ... ]
    LENGTH is the number of elements in the annotation.
    ANNOTATION_MASK is one of CODING_ANNOTATE_XXX_MASK.
-   FROM and TO specify the range of text annotated.  They are relative
-   to coding->src_pos (on encoding) or coding->dst_pos (on decoding).
+   NCHARS is the number of characters in the text annotated.
 
    The format of the following elements depend on ANNOTATION_MASK.
 
@@ -1047,26 +1084,25 @@ alloc_destination (coding, nbytes, dst)
    In the case of CODING_ANNOTATE_CHARSET_MASK, one element CHARSET-ID
    follows.  */
 
-#define ADD_ANNOTATION_DATA(buf, len, mask, from, to)  \
+#define ADD_ANNOTATION_DATA(buf, len, mask, nchars)    \
   do {                                                 \
     *(buf)++ = -(len);                                 \
     *(buf)++ = (mask);                                 \
-    *(buf)++ = (from);                                 \
-    *(buf)++ = (to);                                   \
+    *(buf)++ = (nchars);                               \
     coding->annotated = 1;                             \
   } while (0);
 
-#define ADD_COMPOSITION_DATA(buf, from, to, method)                          \
-  do {                                                                       \
-    ADD_ANNOTATION_DATA (buf, 5, CODING_ANNOTATE_COMPOSITION_MASK, from, to); \
-    *buf++ = method;                                                         \
+#define ADD_COMPOSITION_DATA(buf, nchars, method)                          \
+  do {                                                                     \
+    ADD_ANNOTATION_DATA (buf, 4, CODING_ANNOTATE_COMPOSITION_MASK, nchars); \
+    *buf++ = method;                                                       \
   } while (0)
 
 
-#define ADD_CHARSET_DATA(buf, from, to, id)                              \
-  do {                                                                   \
-    ADD_ANNOTATION_DATA (buf, 5, CODING_ANNOTATE_CHARSET_MASK, from, to); \
-    *buf++ = id;                                                         \
+#define ADD_CHARSET_DATA(buf, nchars, id)                              \
+  do {                                                                 \
+    ADD_ANNOTATION_DATA (buf, 4, CODING_ANNOTATE_CHARSET_MASK, nchars);        \
+    *buf++ = id;                                                       \
   } while (0)
 
 \f
@@ -1166,8 +1202,8 @@ decode_coding_utf_8 (coding)
   const unsigned char *src = coding->source + coding->consumed;
   const unsigned char *src_end = coding->source + coding->src_bytes;
   const unsigned char *src_base;
-  int *charbuf = coding->charbuf;
-  int *charbuf_end = charbuf + coding->charbuf_size;
+  int *charbuf = coding->charbuf + coding->charbuf_used;
+  int *charbuf_end = coding->charbuf + coding->charbuf_size;
   int consumed_chars = 0, consumed_chars_base;
   int multibytep = coding->src_multibyte;
   Lisp_Object attr, charset_list;
@@ -1313,7 +1349,10 @@ encode_coding_utf_8 (coding)
        {
          ASSURE_DESTINATION (safe_room);
          c = *charbuf++;
-         dst += CHAR_STRING (c, dst);
+         if (CHAR_BYTE8_P (c))
+           *dst++ = CHAR_TO_BYTE8 (c);
+         else
+           dst += CHAR_STRING (c, dst);
          produced_chars++;
        }
     }
@@ -1379,26 +1418,6 @@ detect_coding_utf_16 (coding, detect_info)
     }
   else if (c1 >= 0 && c2 >= 0)
     {
-      unsigned char b1[256], b2[256];
-      int b1_variants = 1, b2_variants = 1;
-      int n;
-
-      bzero (b1, 256), bzero (b2, 256);
-      b1[c1]++, b2[c2]++;
-      for (n = 0; n < 256 && src < src_end; n++)
-       {
-         src_base = src;
-         ONE_MORE_BYTE (c1);
-         ONE_MORE_BYTE (c2);
-         if (c1 < 0 || c2 < 0)
-           break;
-         if (! b1[c1++]) b1_variants++;
-         if (! b2[c2++]) b2_variants++;
-       }
-      if (b1_variants < b2_variants)
-       detect_info->found |= CATEGORY_MASK_UTF_16_BE_NOSIG;
-      else
-       detect_info->found |= CATEGORY_MASK_UTF_16_LE_NOSIG;      
       detect_info->rejected
        |= (CATEGORY_MASK_UTF_16_BE | CATEGORY_MASK_UTF_16_LE);
     }
@@ -1413,8 +1432,8 @@ decode_coding_utf_16 (coding)
   const unsigned char *src = coding->source + coding->consumed;
   const unsigned char *src_end = coding->source + coding->src_bytes;
   const unsigned char *src_base;
-  int *charbuf = coding->charbuf;
-  int *charbuf_end = charbuf + coding->charbuf_size;
+  int *charbuf = coding->charbuf + coding->charbuf_used;
+  int *charbuf_end = coding->charbuf + coding->charbuf_size;
   int consumed_chars = 0, consumed_chars_base;
   int multibytep = coding->src_multibyte;
   enum utf_16_bom_type bom = CODING_UTF_16_BOM (coding);
@@ -1678,7 +1697,7 @@ emacs_mule_char (coding, src, nbytes, nchars, id)
          if (! (charset = emacs_mule_charset[c]))
            goto invalid_code;
          ONE_MORE_BYTE (c);
-         if (c < 0)
+         if (c < 0xA0)
            goto invalid_code;
          code = c & 0x7F;
          break;
@@ -1688,10 +1707,10 @@ emacs_mule_char (coding, src, nbytes, nchars, id)
              || c == EMACS_MULE_LEADING_CODE_PRIVATE_12)
            {
              ONE_MORE_BYTE (c);
-             if (c < 0 || ! (charset = emacs_mule_charset[c]))
+             if (c < 0xA0 || ! (charset = emacs_mule_charset[c]))
                goto invalid_code;
              ONE_MORE_BYTE (c);
-             if (c < 0)
+             if (c < 0xA0)
                goto invalid_code;
              code = c & 0x7F;
            }
@@ -1700,11 +1719,11 @@ emacs_mule_char (coding, src, nbytes, nchars, id)
              if (! (charset = emacs_mule_charset[c]))
                goto invalid_code;
              ONE_MORE_BYTE (c);
-             if (c < 0)
+             if (c < 0xA0)
                goto invalid_code;
              code = (c & 0x7F) << 8;
              ONE_MORE_BYTE (c);
-             if (c < 0)
+             if (c < 0xA0)
                goto invalid_code;
              code |= c & 0x7F;
            }
@@ -1715,11 +1734,11 @@ emacs_mule_char (coding, src, nbytes, nchars, id)
          if (c < 0 || ! (charset = emacs_mule_charset[c]))
            goto invalid_code;
          ONE_MORE_BYTE (c);
-         if (c < 0)
+         if (c < 0xA0)
            goto invalid_code;
          code = (c & 0x7F) << 8;
          ONE_MORE_BYTE (c);
-         if (c < 0)
+         if (c < 0xA0)
            goto invalid_code;
          code |= c & 0x7F;
          break;
@@ -1808,14 +1827,19 @@ detect_coding_emacs_mule (coding, detect_info)
        }
       else
        {
-         const unsigned char *src_base = src - 1;
+         int more_bytes = emacs_mule_bytes[*src_base] - 1;
 
-         do
+         while (more_bytes > 0)
            {
              ONE_MORE_BYTE (c);
+             if (c < 0xA0)
+               {
+                 src--;        /* Unread the last byte.  */
+                 break;
+               }
+             more_bytes--;
            }
-         while (c >= 0xA0);
-         if (src - src_base != emacs_mule_bytes[*src_base])
+         if (more_bytes != 0)
            break;
          found = CATEGORY_MASK_EMACS_MULE;
        }
@@ -1916,7 +1940,6 @@ detect_coding_emacs_mule (coding, detect_info)
        number of characters composed by this composition.  */          \
     enum composition_method method = c - 0xF2;                         \
     int *charbuf_base = charbuf;                                       \
-    int from, to;                                                      \
     int consumed_chars_limit;                                          \
     int nbytes, nchars;                                                        \
                                                                        \
@@ -1930,9 +1953,7 @@ detect_coding_emacs_mule (coding, detect_info)
     if (c < 0)                                                         \
       goto invalid_code;                                               \
     nchars = c - 0xA0;                                                 \
-    from = coding->produced + char_offset;                             \
-    to = from + nchars;                                                        \
-    ADD_COMPOSITION_DATA (charbuf, from, to, method);                  \
+    ADD_COMPOSITION_DATA (charbuf, nchars, method);                    \
     consumed_chars_limit = consumed_chars_base + nbytes;               \
     if (method != COMPOSITION_RELATIVE)                                        \
       {                                                                        \
@@ -1960,7 +1981,6 @@ detect_coding_emacs_mule (coding, detect_info)
     int components[MAX_COMPOSITION_COMPONENTS * 2 - 1];                \
     int *buf = components;                                     \
     int i, j;                                                  \
-    int from, to;                                              \
                                                                \
     src = src_base;                                            \
     ONE_MORE_BYTE (c);         /* skip 0x80 */                 \
@@ -1968,9 +1988,7 @@ detect_coding_emacs_mule (coding, detect_info)
       DECODE_EMACS_MULE_COMPOSITION_CHAR (buf);                        \
     if (i < 2)                                                 \
       goto invalid_code;                                       \
-    from = coding->produced_char + char_offset;                        \
-    to = from + i;                                             \
-    ADD_COMPOSITION_DATA (charbuf, from, to, method);          \
+    ADD_COMPOSITION_DATA (charbuf, i, method);                 \
     for (j = 0; j < i; j++)                                    \
       *charbuf++ = components[j];                              \
   } while (0)
@@ -1984,7 +2002,6 @@ detect_coding_emacs_mule (coding, detect_info)
     int components[MAX_COMPOSITION_COMPONENTS * 2 - 1];                \
     int *buf = components;                                     \
     int i, j;                                                  \
-    int from, to;                                              \
                                                                \
     DECODE_EMACS_MULE_COMPOSITION_CHAR (buf);                  \
     for (i = 0; i < MAX_COMPOSITION_COMPONENTS; i++)           \
@@ -1996,9 +2013,7 @@ detect_coding_emacs_mule (coding, detect_info)
       goto invalid_code;                                       \
     if (charbuf + i + (i / 2) + 1 < charbuf_end)               \
       goto no_more_source;                                     \
-    from = coding->produced_char + char_offset;                        \
-    to = from + i;                                             \
-    ADD_COMPOSITION_DATA (buf, from, to, method);              \
+    ADD_COMPOSITION_DATA (buf, i, method);                     \
     for (j = 0; j < i; j++)                                    \
       *charbuf++ = components[j];                              \
     for (j = 0; j < i; j += 2)                                 \
@@ -2013,8 +2028,9 @@ decode_coding_emacs_mule (coding)
   const unsigned char *src = coding->source + coding->consumed;
   const unsigned char *src_end = coding->source + coding->src_bytes;
   const unsigned char *src_base;
-  int *charbuf = coding->charbuf;
-  int *charbuf_end = charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH;
+  int *charbuf = coding->charbuf + coding->charbuf_used;
+  int *charbuf_end
+    = coding->charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH;
   int consumed_chars = 0, consumed_chars_base;
   int multibytep = coding->src_multibyte;
   Lisp_Object attrs, charset_list;
@@ -2077,7 +2093,7 @@ decode_coding_emacs_mule (coding)
          if (last_id != id)
            {
              if (last_id != charset_ascii)
-               ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+               ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
              last_id = id;
              last_offset = char_offset;
            }
@@ -2099,7 +2115,7 @@ decode_coding_emacs_mule (coding)
 
  no_more_source:
   if (last_id != charset_ascii)
-    ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+    ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
   coding->consumed_char += consumed_chars_base;
   coding->consumed = src_base - coding->source;
   coding->charbuf_used = charbuf - coding->charbuf;
@@ -2694,7 +2710,8 @@ detect_coding_iso_2022 (coding, detect_info)
 }
 
 
-/* Set designation state into CODING.  */
+/* Set designation state into CODING.  Set CHARS_96 to -1 if the
+   escape sequence should be kept.  */
 #define DECODE_DESIGNATION(reg, dim, chars_96, final)                  \
   do {                                                                 \
     int id, prev;                                                      \
@@ -2704,7 +2721,8 @@ detect_coding_iso_2022 (coding, detect_info)
        || !SAFE_CHARSET_P (coding, id))                                \
       {                                                                        \
        CODING_ISO_DESIGNATION (coding, reg) = -2;                      \
-       goto invalid_code;                                              \
+       chars_96 = -1;                                                  \
+       break;                                                          \
       }                                                                        \
     prev = CODING_ISO_DESIGNATION (coding, reg);                       \
     if (id == charset_jisx0201_roman)                                  \
@@ -2722,7 +2740,7 @@ detect_coding_iso_2022 (coding, detect_info)
        designation is ASCII to REG, we should keep this designation    \
        sequence.  */                                                   \
     if (prev == -2 && id == charset_ascii)                             \
-      goto invalid_code;                                               \
+      chars_96 = -1;                                                   \
   } while (0)
 
 
@@ -2805,10 +2823,8 @@ detect_coding_iso_2022 (coding, detect_info)
                  : (component_idx + 1) / 2);                           \
     int i;                                                             \
     int *saved_charbuf = charbuf;                                      \
-    int from = char_offset;                                            \
-    int to = from + nchars;                                            \
                                                                        \
-    ADD_COMPOSITION_DATA (charbuf, from, to, method);                  \
+    ADD_COMPOSITION_DATA (charbuf, nchars, method);                    \
     if (method != COMPOSITION_RELATIVE)                                        \
       {                                                                        \
        if (component_len == 0)                                         \
@@ -2864,14 +2880,15 @@ decode_coding_iso_2022 (coding)
   const unsigned char *src = coding->source + coding->consumed;
   const unsigned char *src_end = coding->source + coding->src_bytes;
   const unsigned char *src_base;
-  int *charbuf = coding->charbuf;
+  int *charbuf = coding->charbuf + coding->charbuf_used;
   int *charbuf_end
-    = charbuf + coding->charbuf_size - 4 - MAX_ANNOTATION_LENGTH;
+    = coding->charbuf + coding->charbuf_size - 4 - MAX_ANNOTATION_LENGTH;
   int consumed_chars = 0, consumed_chars_base;
   int multibytep = coding->src_multibyte;
   /* Charsets invoked to graphic plane 0 and 1 respectively.  */
   int charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0);
   int charset_id_1 = CODING_ISO_INVOKED_CHARSET (coding, 1);
+  int charset_id_2, charset_id_3;
   struct charset *charset;
   int c;
   /* For handling composition sequence.  */
@@ -2943,7 +2960,10 @@ decode_coding_iso_2022 (coding)
                  continue;
                }
            }
-         charset = CHARSET_FROM_ID (charset_id_0);
+         if (charset_id_0 < 0)
+           charset = CHARSET_FROM_ID (charset_ascii);
+         else
+           charset = CHARSET_FROM_ID (charset_id_0);
          break;
 
        case ISO_0xA0_or_0xFF:
@@ -3024,27 +3044,36 @@ decode_coding_iso_2022 (coding)
            case '$':           /* designation of 2-byte character set */
              if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_DESIGNATION))
                goto invalid_code;
-             ONE_MORE_BYTE (c1);
-             if (c1 >= '@' && c1 <= 'B')
-               {       /* designation of JISX0208.1978, GB2312.1980,
+             {
+               int reg, chars96;
+
+               ONE_MORE_BYTE (c1);
+               if (c1 >= '@' && c1 <= 'B')
+                 {     /* designation of JISX0208.1978, GB2312.1980,
                           or JISX0208.1980 */
-                 DECODE_DESIGNATION (0, 2, 0, c1);
-               }
-             else if (c1 >= 0x28 && c1 <= 0x2B)
-               {       /* designation of DIMENSION2_CHARS94 character set */
-                 ONE_MORE_BYTE (c2);
-                 DECODE_DESIGNATION (c1 - 0x28, 2, 0, c2);
-               }
-             else if (c1 >= 0x2C && c1 <= 0x2F)
-               {       /* designation of DIMENSION2_CHARS96 character set */
-                 ONE_MORE_BYTE (c2);
-                 DECODE_DESIGNATION (c1 - 0x2C, 2, 1, c2);
-               }
-             else
-               goto invalid_code;
-             /* We must update these variables now.  */
-             charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0);
-             charset_id_1 = CODING_ISO_INVOKED_CHARSET (coding, 1);
+                   reg = 0, chars96 = 0;
+                 }
+               else if (c1 >= 0x28 && c1 <= 0x2B)
+                 { /* designation of DIMENSION2_CHARS94 character set */
+                   reg = c1 - 0x28, chars96 = 0;
+                   ONE_MORE_BYTE (c1);
+                 }
+               else if (c1 >= 0x2C && c1 <= 0x2F)
+                 { /* designation of DIMENSION2_CHARS96 character set */
+                   reg = c1 - 0x2C, chars96 = 1;
+                   ONE_MORE_BYTE (c1);
+                 }
+               else
+                 goto invalid_code;
+               DECODE_DESIGNATION (reg, 2, chars96, c1);
+               /* We must update these variables now.  */
+               if (reg == 0)
+                 charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0);
+               else if (reg == 1)
+                 charset_id_1 = CODING_ISO_INVOKED_CHARSET (coding, 1);
+               if (chars96 < 0)
+                 goto invalid_code;
+             }
              continue;
 
            case 'n':           /* invocation of locking-shift-2 */
@@ -3067,7 +3096,11 @@ decode_coding_iso_2022 (coding)
              if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT)
                  || CODING_ISO_DESIGNATION (coding, 2) < 0)
                goto invalid_code;
-             charset = CHARSET_FROM_ID (CODING_ISO_DESIGNATION (coding, 2));
+             charset_id_2 = CODING_ISO_DESIGNATION (coding, 2);
+             if (charset_id_2 < 0)
+               charset = CHARSET_FROM_ID (charset_ascii);
+             else
+               charset = CHARSET_FROM_ID (charset_id_2);
              ONE_MORE_BYTE (c1);
              if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0))
                goto invalid_code;
@@ -3077,7 +3110,11 @@ decode_coding_iso_2022 (coding)
              if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT)
                  || CODING_ISO_DESIGNATION (coding, 3) < 0)
                goto invalid_code;
-             charset = CHARSET_FROM_ID (CODING_ISO_DESIGNATION (coding, 3));
+             charset_id_3 = CODING_ISO_DESIGNATION (coding, 3);
+             if (charset_id_3 < 0)
+               charset = CHARSET_FROM_ID (charset_ascii);
+             else
+               charset = CHARSET_FROM_ID (charset_id_3);
              ONE_MORE_BYTE (c1);
              if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0))
                goto invalid_code;
@@ -3178,7 +3215,10 @@ decode_coding_iso_2022 (coding)
                          && src + 1 < src_end
                          && src[0] == '%'
                          && src[1] == '@')
-                       break;
+                       {
+                         src += 2;
+                         break;
+                       }
                      *p++ = ASCII_BYTE_P (c1) ? c1 : BYTE8_TO_CHAR (c1);
                    }
                  if (p + 3 > charbuf_end)
@@ -3196,21 +3236,30 @@ decode_coding_iso_2022 (coding)
            default:
              if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_DESIGNATION))
                goto invalid_code;
-             if (c1 >= 0x28 && c1 <= 0x2B)
-               {       /* designation of DIMENSION1_CHARS94 character set */
-                 ONE_MORE_BYTE (c2);
-                 DECODE_DESIGNATION (c1 - 0x28, 1, 0, c2);
-               }
-             else if (c1 >= 0x2C && c1 <= 0x2F)
-               {       /* designation of DIMENSION1_CHARS96 character set */
-                 ONE_MORE_BYTE (c2);
-                 DECODE_DESIGNATION (c1 - 0x2C, 1, 1, c2);
-               }
-             else
-               goto invalid_code;
-             /* We must update these variables now.  */
-             charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0);
-             charset_id_1 = CODING_ISO_INVOKED_CHARSET (coding, 1);
+             {
+               int reg, chars96;
+
+               if (c1 >= 0x28 && c1 <= 0x2B)
+                 { /* designation of DIMENSION1_CHARS94 character set */
+                   reg = c1 - 0x28, chars96 = 0;
+                   ONE_MORE_BYTE (c1);
+                 }
+               else if (c1 >= 0x2C && c1 <= 0x2F)
+                 { /* designation of DIMENSION1_CHARS96 character set */
+                   reg = c1 - 0x2C, chars96 = 1;
+                   ONE_MORE_BYTE (c1);
+                 }
+               else
+                 goto invalid_code;
+               DECODE_DESIGNATION (reg, 1, chars96, c1);
+               /* We must update these variables now.  */
+               if (reg == 0)
+                 charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0);
+               else if (reg == 1)
+                 charset_id_1 = CODING_ISO_INVOKED_CHARSET (coding, 1);
+               if (chars96 < 0)
+                 goto invalid_code;
+             }
              continue;
            }
        }
@@ -3219,7 +3268,7 @@ decode_coding_iso_2022 (coding)
          && last_id != charset->id)
        {
          if (last_id != charset_ascii)
-           ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+           ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
          last_id = charset->id;
          last_offset = char_offset;
        }
@@ -3288,7 +3337,7 @@ decode_coding_iso_2022 (coding)
 
  no_more_source:
   if (last_id != charset_ascii)
-    ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+    ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
   coding->consumed_char += consumed_chars_base;
   coding->consumed = src_base - coding->source;
   coding->charbuf_used = charbuf - coding->charbuf;
@@ -3990,8 +4039,9 @@ decode_coding_sjis (coding)
   const unsigned char *src = coding->source + coding->consumed;
   const unsigned char *src_end = coding->source + coding->src_bytes;
   const unsigned char *src_base;
-  int *charbuf = coding->charbuf;
-  int *charbuf_end = charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH;
+  int *charbuf = coding->charbuf + coding->charbuf_used;
+  int *charbuf_end
+    = coding->charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH;
   int consumed_chars = 0, consumed_chars_base;
   int multibytep = coding->src_multibyte;
   struct charset *charset_roman, *charset_kanji, *charset_kana;
@@ -4059,7 +4109,7 @@ decode_coding_sjis (coding)
          && last_id != charset->id)
        {
          if (last_id != charset_ascii)
-           ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+           ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
          last_id = charset->id;
          last_offset = char_offset;
        }
@@ -4079,7 +4129,7 @@ decode_coding_sjis (coding)
 
  no_more_source:
   if (last_id != charset_ascii)
-    ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+    ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
   coding->consumed_char += consumed_chars_base;
   coding->consumed = src_base - coding->source;
   coding->charbuf_used = charbuf - coding->charbuf;
@@ -4092,8 +4142,9 @@ decode_coding_big5 (coding)
   const unsigned char *src = coding->source + coding->consumed;
   const unsigned char *src_end = coding->source + coding->src_bytes;
   const unsigned char *src_base;
-  int *charbuf = coding->charbuf;
-  int *charbuf_end = charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH;
+  int *charbuf = coding->charbuf + coding->charbuf_used;
+  int *charbuf_end
+    = coding->charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH;
   int consumed_chars = 0, consumed_chars_base;
   int multibytep = coding->src_multibyte;
   struct charset *charset_roman, *charset_big5;
@@ -4139,7 +4190,7 @@ decode_coding_big5 (coding)
          && last_id != charset->id)
        {
          if (last_id != charset_ascii)
-           ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+           ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
          last_id = charset->id;
          last_offset = char_offset;
        }
@@ -4159,7 +4210,7 @@ decode_coding_big5 (coding)
 
  no_more_source:
   if (last_id != charset_ascii)
-    ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+    ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
   coding->consumed_char += consumed_chars_base;
   coding->consumed = src_base - coding->source;
   coding->charbuf_used = charbuf - coding->charbuf;
@@ -4354,13 +4405,14 @@ detect_coding_ccl (coding, detect_info)
   int multibytep = coding->src_multibyte;
   int consumed_chars = 0;
   int found = 0;
-  unsigned char *valids = CODING_CCL_VALIDS (coding);
+  unsigned char *valids;
   int head_ascii = coding->head_ascii;
   Lisp_Object attrs;
 
   detect_info->checked |= CATEGORY_MASK_CCL;
 
   coding = &coding_categories[coding_category_ccl];
+  valids = CODING_CCL_VALIDS (coding);
   attrs = CODING_ID_ATTRS (coding->id);
   if (! NILP (CODING_ATTR_ASCII_COMPAT (attrs)))
     src += head_ascii;
@@ -4390,8 +4442,8 @@ decode_coding_ccl (coding)
 {
   const unsigned char *src = coding->source + coding->consumed;
   const unsigned char *src_end = coding->source + coding->src_bytes;
-  int *charbuf = coding->charbuf;
-  int *charbuf_end = charbuf + coding->charbuf_size;
+  int *charbuf = coding->charbuf + coding->charbuf_used;
+  int *charbuf_end = coding->charbuf + coding->charbuf_size;
   int consumed_chars = 0;
   int multibytep = coding->src_multibyte;
   struct ccl_program ccl;
@@ -4677,8 +4729,9 @@ decode_coding_charset (coding)
   const unsigned char *src = coding->source + coding->consumed;
   const unsigned char *src_end = coding->source + coding->src_bytes;
   const unsigned char *src_base;
-  int *charbuf = coding->charbuf;
-  int *charbuf_end = charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH;
+  int *charbuf = coding->charbuf + coding->charbuf_used;
+  int *charbuf_end
+    = coding->charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH;
   int consumed_chars = 0, consumed_chars_base;
   int multibytep = coding->src_multibyte;
   Lisp_Object attrs, charset_list, valids;
@@ -4753,7 +4806,7 @@ decode_coding_charset (coding)
          && last_id != charset->id)
        {
          if (last_id != charset_ascii)
-           ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+           ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
          last_id = charset->id;
          last_offset = char_offset;
        }
@@ -4773,7 +4826,7 @@ decode_coding_charset (coding)
 
  no_more_source:
   if (last_id != charset_ascii)
-    ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id);
+    ADD_CHARSET_DATA (charbuf, char_offset - last_offset, last_id);
   coding->consumed_char += consumed_chars_base;
   coding->consumed = src_base - coding->source;
   coding->charbuf_used = charbuf - coding->charbuf;
@@ -5020,6 +5073,13 @@ setup_coding_system (coding_system, coding)
       coding->detector = NULL;
       coding->decoder = decode_coding_raw_text;
       coding->encoder = encode_coding_raw_text;
+      if (! EQ (eol_type, Qunix))
+       {
+         coding->common_flags |= CODING_REQUIRE_DECODING_MASK;
+         if (! VECTORP (eol_type))
+           coding->common_flags |= CODING_REQUIRE_ENCODING_MASK;
+       }
+
     }
 
   return;
@@ -5157,7 +5217,7 @@ coding_inherit_eol_type (coding_system, parent)
    o coding-category-utf-8
 
        The category for a coding system which has the same code range
-       as UTF-8 (cf. RFC2279).  Assigned the coding-system (Lisp
+       as UTF-8 (cf. RFC3629).  Assigned the coding-system (Lisp
        symbol) `utf-8' by default.
 
    o coding-category-utf-16-be
@@ -5212,11 +5272,11 @@ coding_inherit_eol_type (coding_system, parent)
 
 static int
 detect_eol (source, src_bytes, category)
-     unsigned char *source;
+     const unsigned char *source;
      EMACS_INT src_bytes;
      enum coding_category category;
 {
-  unsigned char *src = source, *src_end = src + src_bytes;
+  const unsigned char *src = source, *src_end = src + src_bytes;
   unsigned char c;
   int total  = 0;
   int eol_seen = EOL_SEEN_NONE;
@@ -5329,7 +5389,6 @@ detect_coding (coding)
      struct coding_system *coding;
 {
   const unsigned char *src, *src_end;
-  Lisp_Object attrs, coding_type;
 
   coding->consumed = coding->consumed_char = 0;
   coding->produced = coding->produced_char = 0;
@@ -5342,53 +5401,78 @@ detect_coding (coding)
   if (EQ (CODING_ATTR_TYPE (CODING_ID_ATTRS (coding->id)), Qundecided))
     {
       int c, i;
+      struct coding_detection_info detect_info;
 
+      detect_info.checked = detect_info.found = detect_info.rejected = 0;
       for (i = 0, src = coding->source; src < src_end; i++, src++)
        {
          c = *src;
-         if (c & 0x80 || (c < 0x20 && (c == ISO_CODE_ESC
-                                       || c == ISO_CODE_SI
-                                       || c == ISO_CODE_SO)))
+         if (c & 0x80)
            break;
+         if (c < 0x20
+             && (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
+             && ! inhibit_iso_escape_detection
+             && ! detect_info.checked)
+           {
+             coding->head_ascii = src - (coding->source + coding->consumed);
+             if (detect_coding_iso_2022 (coding, &detect_info))
+               {
+                 /* We have scanned the whole data.  */
+                 if (! (detect_info.rejected & CATEGORY_MASK_ISO_7_ELSE))
+                   /* We didn't find an 8-bit code.  */
+                   src = src_end;
+                 break;
+               }
+           }
        }
       coding->head_ascii = src - (coding->source + coding->consumed);
 
-      if (coding->head_ascii < coding->src_bytes)
+      if (coding->head_ascii < coding->src_bytes
+         || detect_info.found)
        {
-         struct coding_detection_info detect_info;
          enum coding_category category;
          struct coding_system *this;
 
-         detect_info.checked = detect_info.found = detect_info.rejected = 0;
-         for (i = 0; i < coding_category_raw_text; i++)
-           {
-             category = coding_priorities[i];
-             this = coding_categories + category;
-             if (this->id < 0)
-               {
-                 /* No coding system of this category is defined.  */
-                 detect_info.rejected |= (1 << category);
-               }
-             else if (category >= coding_category_raw_text)
-               continue;
-             else if (detect_info.checked & (1 << category))
-               {
-                 if (detect_info.found & (1 << category))
-                   break;
-               }
-             else if ((*(this->detector)) (coding, &detect_info)
-                      && detect_info.found & (1 << category))
-               {
-                 if (category == coding_category_utf_16_auto)
-                   {
-                     if (detect_info.found & CATEGORY_MASK_UTF_16_LE)
-                       category = coding_category_utf_16_le;
-                     else
-                       category = coding_category_utf_16_be;
-                   }
+         if (coding->head_ascii == coding->src_bytes)
+           /* As all bytes are 7-bit, we can ignore non-ISO-2022 codings.  */
+           for (i = 0; i < coding_category_raw_text; i++)
+             {
+               category = coding_priorities[i];
+               this = coding_categories + category;
+               if (detect_info.found & (1 << category))
                  break;
-               }
-           }
+             }
+         else
+           for (i = 0; i < coding_category_raw_text; i++)
+             {
+               category = coding_priorities[i];
+               this = coding_categories + category;
+               if (this->id < 0)
+                 {
+                   /* No coding system of this category is defined.  */
+                   detect_info.rejected |= (1 << category);
+                 }
+               else if (category >= coding_category_raw_text)
+                 continue;
+               else if (detect_info.checked & (1 << category))
+                 {
+                   if (detect_info.found & (1 << category))
+                     break;
+                 }
+               else if ((*(this->detector)) (coding, &detect_info)
+                        && detect_info.found & (1 << category))
+                 {
+                   if (category == coding_category_utf_16_auto)
+                     {
+                       if (detect_info.found & CATEGORY_MASK_UTF_16_LE)
+                         category = coding_category_utf_16_le;
+                       else
+                         category = coding_category_utf_16_be;
+                     }
+                   break;
+                 }
+             }
+         
          if (i < coding_category_raw_text)
            setup_coding_system (CODING_ID_NAME (this->id), coding);
          else if (detect_info.rejected == CATEGORY_MASK_ANY)
@@ -5510,10 +5594,13 @@ decode_eol (coding)
    attribute vector ATTRS for encoding (ENCODEP is nonzero) or
    decoding (ENCODEP is zero). */
 
-static INLINE
-get_translation_table (attrs, encodep)
+static Lisp_Object
+get_translation_table (attrs, encodep, max_lookup)
+     Lisp_Object attrs;
+     int encodep, *max_lookup;
 {
   Lisp_Object standard, translation_table;
+  Lisp_Object val;
 
   if (encodep)
     translation_table = CODING_ATTR_ENCODE_TBL (attrs),
@@ -5522,98 +5609,200 @@ get_translation_table (attrs, encodep)
     translation_table = CODING_ATTR_DECODE_TBL (attrs),
       standard = Vstandard_translation_table_for_decode;
   if (NILP (translation_table))
-    return standard;
-  if (SYMBOLP (translation_table))
-    translation_table = Fget (translation_table, Qtranslation_table);
-  else if (CONSP (translation_table))
+    translation_table = standard;
+  else
     {
-      Lisp_Object val;
-
-      translation_table = Fcopy_sequence (translation_table);
-      for (val = translation_table; CONSP (val); val = XCDR (val))
-       if (SYMBOLP (XCAR (val)))
-         XSETCAR (val, Fget (XCAR (val), Qtranslation_table));
+      if (SYMBOLP (translation_table))
+       translation_table = Fget (translation_table, Qtranslation_table);
+      else if (CONSP (translation_table))
+       {
+         translation_table = Fcopy_sequence (translation_table);
+         for (val = translation_table; CONSP (val); val = XCDR (val))
+           if (SYMBOLP (XCAR (val)))
+             XSETCAR (val, Fget (XCAR (val), Qtranslation_table));
+       }
+      if (CHAR_TABLE_P (standard))
+       {
+         if (CONSP (translation_table))
+           translation_table = nconc2 (translation_table,
+                                       Fcons (standard, Qnil));
+         else
+           translation_table = Fcons (translation_table,
+                                      Fcons (standard, Qnil));
+       }
     }
-  if (! NILP (standard))
+
+  if (max_lookup)
     {
-      if (CONSP (translation_table))
-       translation_table = nconc2 (translation_table, Fcons (standard, Qnil));
-      else
-       translation_table = Fcons (translation_table, Fcons (standard, Qnil));
+      *max_lookup = 1;
+      if (CHAR_TABLE_P (translation_table)
+         && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (translation_table)) > 1)
+       {
+         val = XCHAR_TABLE (translation_table)->extras[1];
+         if (NATNUMP (val) && *max_lookup < XFASTINT (val))
+           *max_lookup = XFASTINT (val);
+       }
+      else if (CONSP (translation_table))
+       {
+         Lisp_Object tail, val;
+
+         for (tail = translation_table; CONSP (tail); tail = XCDR (tail))
+           if (CHAR_TABLE_P (XCAR (tail))
+               && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (XCAR (tail))) > 1)
+             {
+               val = XCHAR_TABLE (XCAR (tail))->extras[1];
+               if (NATNUMP (val) && *max_lookup < XFASTINT (val))
+                 *max_lookup = XFASTINT (val);
+             }
+       }
     }
   return translation_table;
 }
 
+#define LOOKUP_TRANSLATION_TABLE(table, c, trans)              \
+  do {                                                         \
+    trans = Qnil;                                              \
+    if (CHAR_TABLE_P (table))                                  \
+      {                                                                \
+       trans = CHAR_TABLE_REF (table, c);                      \
+       if (CHARACTERP (trans))                                 \
+         c = XFASTINT (trans), trans = Qnil;                   \
+      }                                                                \
+    else if (CONSP (table))                                    \
+      {                                                                \
+       Lisp_Object tail;                                       \
+                                                               \
+       for (tail = table; CONSP (tail); tail = XCDR (tail))    \
+         if (CHAR_TABLE_P (XCAR (tail)))                       \
+           {                                                   \
+             trans = CHAR_TABLE_REF (XCAR (tail), c);          \
+             if (CHARACTERP (trans))                           \
+               c = XFASTINT (trans), trans = Qnil;             \
+             else if (! NILP (trans))                          \
+               break;                                          \
+           }                                                   \
+      }                                                                \
+  } while (0)
 
-static void
-translate_chars (coding, table)
-     struct coding_system *coding;
-     Lisp_Object table;
-{
-  int *charbuf = coding->charbuf;
-  int *charbuf_end = charbuf + coding->charbuf_used;
-  int c;
-
-  if (coding->chars_at_source)
-    return;
 
-  while (charbuf < charbuf_end)
+static Lisp_Object
+get_translation (val, buf, buf_end, last_block, from_nchars, to_nchars)
+     Lisp_Object val;
+     int *buf, *buf_end;
+     int last_block;
+     int *from_nchars, *to_nchars;
+{
+  /* VAL is TO or (([FROM-CHAR ...] .  TO) ...) where TO is TO-CHAR or
+     [TO-CHAR ...].  */
+  if (CONSP (val))
     {
-      c = *charbuf;
-      if (c < 0)
-       charbuf += -c;
-      else
-       *charbuf++ = translate_char (table, c);
+      Lisp_Object from, tail;
+      int i, len;
+
+      for (tail = val; CONSP (tail); tail = XCDR (tail))
+       {
+         val = XCAR (tail);
+         from = XCAR (val);
+         len = ASIZE (from);
+         for (i = 0; i < len; i++)
+           {
+             if (buf + i == buf_end)
+               {
+                 if (! last_block)
+                   return Qt;
+                 break;
+               }
+             if (XINT (AREF (from, i)) != buf[i])
+               break;
+           }
+         if (i == len)
+           {
+             val = XCDR (val);
+             *from_nchars = len;
+             break;
+           }
+       }
+      if (! CONSP (tail))
+       return Qnil;
     }
+  if (VECTORP (val))
+    *buf = XINT (AREF (val, 0)), *to_nchars = ASIZE (val);
+  else
+    *buf = XINT (val);
+  return val;
 }
 
+
 static int
-produce_chars (coding)
+produce_chars (coding, translation_table, last_block)
      struct coding_system *coding;
+     Lisp_Object translation_table;
+     int last_block;
 {
   unsigned char *dst = coding->destination + coding->produced;
   unsigned char *dst_end = coding->destination + coding->dst_bytes;
   int produced;
   int produced_chars = 0;
+  int carryover = 0;
 
   if (! coding->chars_at_source)
     {
       /* Characters are in coding->charbuf.  */
       int *buf = coding->charbuf;
       int *buf_end = buf + coding->charbuf_used;
-      unsigned char *adjusted_dst_end;
 
       if (BUFFERP (coding->src_object)
          && EQ (coding->src_object, coding->dst_object))
        dst_end = ((unsigned char *) coding->source) + coding->consumed;
-      adjusted_dst_end = dst_end - MAX_MULTIBYTE_LENGTH;
 
       while (buf < buf_end)
        {
-         int c = *buf++;
+         int c = *buf, i;
 
-         if (dst >= adjusted_dst_end)
-           {
-             dst = alloc_destination (coding,
-                                      buf_end - buf + MAX_MULTIBYTE_LENGTH,
-                                      dst);
-             dst_end = coding->destination + coding->dst_bytes;
-             adjusted_dst_end = dst_end - MAX_MULTIBYTE_LENGTH;
-           }
          if (c >= 0)
            {
-             if (coding->dst_multibyte
-                 || ! CHAR_BYTE8_P (c))
-               CHAR_STRING_ADVANCE (c, dst);
-             else
-               *dst++ = CHAR_TO_BYTE8 (c);
-             produced_chars++;
+             int from_nchars = 1, to_nchars = 1;
+             Lisp_Object trans = Qnil;
+
+             LOOKUP_TRANSLATION_TABLE (translation_table, c, trans);
+             if (! NILP (trans))
+               {
+                 trans = get_translation (trans, buf, buf_end, last_block,
+                                          &from_nchars, &to_nchars);
+                 if (EQ (trans, Qt))
+                   break;
+                 c = *buf;
+               }
+
+             if (dst + MAX_MULTIBYTE_LENGTH * to_nchars > dst_end)
+               {
+                 dst = alloc_destination (coding,
+                                          buf_end - buf
+                                          + MAX_MULTIBYTE_LENGTH * to_nchars,
+                                          dst);
+                 dst_end = coding->destination + coding->dst_bytes;
+               }
+
+             for (i = 0; i < to_nchars; i++)
+               {
+                 if (i > 0)
+                   c = XINT (AREF (trans, i));
+                 if (coding->dst_multibyte
+                     || ! CHAR_BYTE8_P (c))
+                   CHAR_STRING_ADVANCE (c, dst);
+                 else
+                   *dst++ = CHAR_TO_BYTE8 (c);
+               }
+             produced_chars += to_nchars;
+             *buf++ = to_nchars;
+             while (--from_nchars > 0)
+               *buf++ = 0;
            }
          else
-           /* This is an annotation datum.  (-C) is the length of
-              it.  */
-           buf += -c - 1;
+           /* This is an annotation datum.  (-C) is the length.  */
+           buf += -c;
        }
+      carryover = buf_end - buf;
     }
   else
     {
@@ -5755,7 +5944,7 @@ produce_chars (coding)
     insert_from_gap (produced_chars, produced);
   coding->produced += produced;
   coding->produced_char += produced_chars;
-  return produced_chars;
+  return carryover;
 }
 
 /* Compose text in CODING->object according to the annotation data at
@@ -5764,53 +5953,62 @@ produce_chars (coding)
  */
 
 static INLINE void
-produce_composition (coding, charbuf)
+produce_composition (coding, charbuf, pos)
      struct coding_system *coding;
      int *charbuf;
+     EMACS_INT pos;
 {
   int len;
-  EMACS_INT from, to;
+  EMACS_INT to;
   enum composition_method method;
   Lisp_Object components;
 
   len = -charbuf[0];
-  from = coding->dst_pos + charbuf[2];
-  to = coding->dst_pos + charbuf[3];
-  method = (enum composition_method) (charbuf[4]);
+  to = pos + charbuf[2];
+  if (to <= pos)
+    return;
+  method = (enum composition_method) (charbuf[3]);
 
   if (method == COMPOSITION_RELATIVE)
     components = Qnil;
-  else
+  else if (method >= COMPOSITION_WITH_RULE
+          && method <= COMPOSITION_WITH_RULE_ALTCHARS)
     {
       Lisp_Object args[MAX_COMPOSITION_COMPONENTS * 2 - 1];
       int i;
 
-      len -= 5;
-      charbuf += 5;
+      len -= 4;
+      charbuf += 4;
       for (i = 0; i < len; i++)
-       args[i] = make_number (charbuf[i]);
+       {
+         args[i] = make_number (charbuf[i]);
+         if (args[i] < 0)
+           return;
+       }
       components = (method == COMPOSITION_WITH_ALTCHARS
                    ? Fstring (len, args) : Fvector (len, args));
     }
-  compose_text (from, to, components, Qnil, coding->dst_object);
+  else
+    return;
+  compose_text (pos, to, components, Qnil, coding->dst_object);
 }
 
 
 /* Put `charset' property on text in CODING->object according to
    the annotation data at CHARBUF.  CHARBUF is an array:
-     [ -LENGTH ANNOTATION_MASK FROM TO CHARSET-ID ]
+     [ -LENGTH ANNOTATION_MASK NCHARS CHARSET-ID ]
  */
 
 static INLINE void
-produce_charset (coding, charbuf)
+produce_charset (coding, charbuf, pos)
      struct coding_system *coding;
      int *charbuf;
+     EMACS_INT pos;
 {
-  EMACS_INT from = coding->dst_pos + charbuf[2];
-  EMACS_INT to = coding->dst_pos + charbuf[3];
-  struct charset *charset = CHARSET_FROM_ID (charbuf[4]);
+  EMACS_INT from = pos - charbuf[2];
+  struct charset *charset = CHARSET_FROM_ID (charbuf[3]);
 
-  Fput_text_property (make_number (from), make_number (to),
+  Fput_text_property (make_number (from), make_number (pos),
                      Qcharset, CHARSET_NAME (charset),
                      coding->dst_object);
 }
@@ -5840,8 +6038,9 @@ produce_charset (coding, charbuf)
 
 
 static void
-produce_annotation (coding)
+produce_annotation (coding, pos)
      struct coding_system *coding;
+     EMACS_INT pos;
 {
   int *charbuf = coding->charbuf;
   int *charbuf_end = charbuf + coding->charbuf_used;
@@ -5852,17 +6051,17 @@ produce_annotation (coding)
   while (charbuf < charbuf_end)
     {
       if (*charbuf >= 0)
-       charbuf++;
+       pos += *charbuf++;
       else
        {
          int len = -*charbuf;
          switch (charbuf[1])
            {
            case CODING_ANNOTATE_COMPOSITION_MASK:
-             produce_composition (coding, charbuf);
+             produce_composition (coding, charbuf, pos);
              break;
            case CODING_ANNOTATE_CHARSET_MASK:
-             produce_charset (coding, charbuf);
+             produce_charset (coding, charbuf, pos);
              break;
            default:
              abort ();
@@ -5902,6 +6101,8 @@ decode_coding (coding)
   Lisp_Object attrs;
   Lisp_Object undo_list;
   Lisp_Object translation_table;
+  int carryover;
+  int i;
 
   if (BUFFERP (coding->src_object)
       && coding->src_pos > 0
@@ -5929,23 +6130,35 @@ decode_coding (coding)
   ALLOC_CONVERSION_WORK_AREA (coding);
 
   attrs = CODING_ID_ATTRS (coding->id);
-  translation_table = get_translation_table (attrs, 0);
+  translation_table = get_translation_table (attrs, 0, NULL);
 
+  carryover = 0;
   do
     {
+      EMACS_INT pos = coding->dst_pos + coding->produced_char;
+
       coding_set_source (coding);
       coding->annotated = 0;
+      coding->charbuf_used = carryover;
       (*(coding->decoder)) (coding);
-      if (!NILP (translation_table))
-       translate_chars (coding, translation_table);
       coding_set_destination (coding);
-      produce_chars (coding);
+      carryover = produce_chars (coding, translation_table, 0);
       if (coding->annotated)
-       produce_annotation (coding);
+       produce_annotation (coding, pos);
+      for (i = 0; i < carryover; i++)
+       coding->charbuf[i]
+         = coding->charbuf[coding->charbuf_used - carryover + i];
     }
   while (coding->consumed < coding->src_bytes
         && ! coding->result);
 
+  if (carryover > 0)
+    {
+      coding_set_destination (coding);
+      coding->charbuf_used = carryover;
+      produce_chars (coding, translation_table, 1);
+    }
+
   coding->carryover_bytes = 0;
   if (coding->consumed < coding->src_bytes)
     {
@@ -5968,7 +6181,7 @@ decode_coding (coding)
 
              coding->charbuf[coding->charbuf_used++] = (c & 0x80 ? - c : c);
            }
-         produce_chars (coding);
+         produce_chars (coding, Qnil, 1);
        }
       else
        {
@@ -6030,7 +6243,7 @@ handle_composition_annotation (pos, limit, coding, buf, stop)
          enum composition_method method = COMPOSITION_METHOD (prop);
          int nchars = COMPOSITION_LENGTH (prop);
 
-         ADD_COMPOSITION_DATA (buf, 0, nchars, method);
+         ADD_COMPOSITION_DATA (buf, nchars, method);
          if (method != COMPOSITION_RELATIVE)
            {
              Lisp_Object components;
@@ -6105,7 +6318,7 @@ handle_charset_annotation (pos, limit, coding, buf, stop)
     id = XINT (CHARSET_SYMBOL_ID (val));
   else
     id = -1;
-  ADD_CHARSET_DATA (buf, 0, 0, id);
+  ADD_CHARSET_DATA (buf, 0, id);
   next = Fnext_single_property_change (make_number (pos), Qcharset,
                                       coding->src_object,
                                       make_number (limit));
@@ -6115,8 +6328,10 @@ handle_charset_annotation (pos, limit, coding, buf, stop)
 
 
 static void
-consume_chars (coding)
+consume_chars (coding, translation_table, max_lookup)
      struct coding_system *coding;
+     Lisp_Object translation_table;
+     int max_lookup;
 {
   int *buf = coding->charbuf;
   int *buf_end = coding->charbuf + coding->charbuf_size;
@@ -6128,6 +6343,10 @@ consume_chars (coding)
   Lisp_Object eol_type;
   int c;
   EMACS_INT stop, stop_composition, stop_charset;
+  int *lookup_buf = NULL;
+
+  if (! NILP (translation_table))
+    lookup_buf = alloca (sizeof (int) * max_lookup);
 
   eol_type = CODING_ID_EOL_TYPE (coding->id);
   if (VECTORP (eol_type))
@@ -6154,6 +6373,8 @@ consume_chars (coding)
   buf_end -= 1 + MAX_ANNOTATION_LENGTH;
   while (buf < buf_end)
     {
+      Lisp_Object trans;
+
       if (pos == stop)
        {
          if (pos == end_pos)
@@ -6172,11 +6393,12 @@ consume_chars (coding)
        {
          EMACS_INT bytes;
 
-         if (! CODING_FOR_UNIBYTE (coding)
-             && (bytes = MULTIBYTE_LENGTH (src, src_end)) > 0)
+         if (coding->encoder == encode_coding_raw_text)
+           c = *src++, pos++;
+         else if ((bytes = MULTIBYTE_LENGTH (src, src_end)) > 0)
            c = STRING_CHAR_ADVANCE (src), pos += bytes;
          else
-           c = *src++, pos++;
+           c = BYTE8_TO_CHAR (*src), src++, pos++;
        }
       else
        c = STRING_CHAR_ADVANCE (src), pos++;
@@ -6192,7 +6414,33 @@ consume_chars (coding)
                c = '\r';
            }
        }
-      *buf++ = c;
+
+      trans = Qnil;
+      LOOKUP_TRANSLATION_TABLE (translation_table, c, trans);
+      if (NILP (trans))
+       *buf++ = c;
+      else
+       {
+         int from_nchars = 1, to_nchars = 1;
+         int *lookup_buf_end;
+         const unsigned char *p = src;
+         int i;
+
+         lookup_buf[0] = c;
+         for (i = 1; i < max_lookup && p < src_end; i++)
+           lookup_buf[i] = STRING_CHAR_ADVANCE (p);
+         lookup_buf_end = lookup_buf + i;
+         trans = get_translation (trans, lookup_buf, lookup_buf_end, 1,
+                                  &from_nchars, &to_nchars);
+         if (EQ (trans, Qt)
+             || buf + to_nchars > buf_end)
+           break;
+         *buf++ = *lookup_buf;
+         for (i = 1; i < to_nchars; i++)
+           *buf++ = XINT (AREF (trans, i));
+         for (i = 1; i < from_nchars; i++, pos++)
+           src += MULTIBYTE_LENGTH_NO_CHECK (src);
+       }
     }
 
   coding->consumed = src - coding->source;
@@ -6229,9 +6477,13 @@ encode_coding (coding)
 {
   Lisp_Object attrs;
   Lisp_Object translation_table;
+  int max_lookup;
 
   attrs = CODING_ID_ATTRS (coding->id);
-  translation_table = get_translation_table (attrs, 1);
+  if (coding->encoder == encode_coding_raw_text)
+    translation_table = Qnil, max_lookup = 0;
+  else
+    translation_table = get_translation_table (attrs, 1, &max_lookup);
 
   if (BUFFERP (coding->dst_object))
     {
@@ -6249,11 +6501,7 @@ encode_coding (coding)
 
   do {
     coding_set_source (coding);
-    consume_chars (coding);
-
-    if (!NILP (translation_table))
-      translate_chars (coding, translation_table);
-
+    consume_chars (coding, translation_table, max_lookup);
     coding_set_destination (coding);
     (*(coding->encoder)) (coding);
   } while (coding->consumed_char < coding->src_chars);
@@ -6282,8 +6530,9 @@ static int reused_workbuf_in_use;
 /* Return a working buffer of code convesion.  MULTIBYTE specifies the
    multibyteness of returning buffer.  */
 
-Lisp_Object
+static Lisp_Object
 make_conversion_work_buffer (multibyte)
+     int multibyte;
 {
   Lisp_Object name, workbuf;
   struct buffer *current;
@@ -6802,7 +7051,9 @@ If the user enters null input, return second argument DEFAULT-CODING-SYSTEM.  */
 DEFUN ("check-coding-system", Fcheck_coding_system, Scheck_coding_system,
        1, 1, 0,
        doc: /* Check validity of CODING-SYSTEM.
-If valid, return CODING-SYSTEM, else signal a `coding-system-error' error.  */)
+If valid, return CODING-SYSTEM, else signal a `coding-system-error' error.
+It is valid if it is nil or a symbol defined as a coding system by the
+function `define-coding-system'.  */)
   (coding_system)
      Lisp_Object coding_system;
 {
@@ -6874,49 +7125,73 @@ detect_coding_system (src, src_chars, src_bytes, highest, multibytep,
       for (i = 0; src < src_end; i++, src++)
        {
          c = *src;
-         if (c & 0x80 || (c < 0x20 && (c == ISO_CODE_ESC
-                                       || c == ISO_CODE_SI
-                                       || c == ISO_CODE_SO)))
+         if (c & 0x80)
            break;
+         if (c < 0x20
+             && (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
+             && inhibit_iso_escape_detection)
+           {
+             coding.head_ascii = src - coding.source;
+             if (detect_coding_iso_2022 (&coding, &detect_info))
+               {
+                 /* We have scanned the whole data.  */
+                 if (! (detect_info.rejected & CATEGORY_MASK_ISO_7_ELSE))
+                   /* We didn't find an 8-bit code.  */
+                   src = src_end;
+                 break;
+               }
+           }
        }
       coding.head_ascii = src - coding.source;
 
-      if (src < src_end)
-       for (i = 0; i < coding_category_raw_text; i++)
-         {
-           category = coding_priorities[i];
-           this = coding_categories + category;
-
-           if (this->id < 0)
-             {
-               /* No coding system of this category is defined.  */
-               detect_info.rejected |= (1 << category);
-             }
-           else if (category >= coding_category_raw_text)
-             continue;
-           else if (detect_info.checked & (1 << category))
+      if (src < src_end
+         || detect_info.found)
+       {
+         if (src == src_end)
+           /* As all bytes are 7-bit, we can ignore non-ISO-2022 codings.  */
+           for (i = 0; i < coding_category_raw_text; i++)
              {
-               if (highest
-                   && (detect_info.found & (1 << category)))
+               category = coding_priorities[i];
+               if (detect_info.found & (1 << category))
                  break;
              }
-           else
+         else
+           for (i = 0; i < coding_category_raw_text; i++)
              {
-               if ((*(this->detector)) (&coding, &detect_info)
-                   && highest
-                   && (detect_info.found & (1 << category)))
+               category = coding_priorities[i];
+               this = coding_categories + category;
+
+               if (this->id < 0)
                  {
-                   if (category == coding_category_utf_16_auto)
+                   /* No coding system of this category is defined.  */
+                   detect_info.rejected |= (1 << category);
+                 }
+               else if (category >= coding_category_raw_text)
+                 continue;
+               else if (detect_info.checked & (1 << category))
+                 {
+                   if (highest
+                       && (detect_info.found & (1 << category)))
+                     break;
+                 }
+               else
+                 {
+                   if ((*(this->detector)) (&coding, &detect_info)
+                       && highest
+                       && (detect_info.found & (1 << category)))
                      {
-                       if (detect_info.found & CATEGORY_MASK_UTF_16_LE)
-                         category = coding_category_utf_16_le;
-                       else
-                         category = coding_category_utf_16_be;
+                       if (category == coding_category_utf_16_auto)
+                         {
+                           if (detect_info.found & CATEGORY_MASK_UTF_16_LE)
+                             category = coding_category_utf_16_le;
+                           else
+                             category = coding_category_utf_16_be;
+                         }
+                       break;
                      }
-                   break;
                  }
              }
-         }
+       }
 
       if (detect_info.rejected == CATEGORY_MASK_ANY)
        {
@@ -6979,7 +7254,6 @@ detect_coding_system (src, src_chars, src_bytes, highest, multibytep,
     {
       if (detect_coding_utf_16 (&coding, &detect_info))
        {
-         enum coding_category category;
          struct coding_system *this;
 
          if (detect_info.found & CATEGORY_MASK_UTF_16_LE)
@@ -7209,7 +7483,7 @@ DEFUN ("find-coding-systems-region-internal",
            && ! EQ (CODING_ATTR_TYPE (attrs), Qundecided))
          {
            ASET (attrs, coding_attr_trans_tbl,
-                 get_translation_table (attrs, 1));
+                 get_translation_table (attrs, 1, NULL));
            coding_attrs_list = Fcons (attrs, coding_attrs_list);
          }
       }
@@ -7264,7 +7538,7 @@ DEFUN ("find-coding-systems-region-internal",
        }
     }
 
-  safe_codings = Qnil;
+  safe_codings = list2 (Qraw_text, Qno_conversion);
   for (tail = coding_attrs_list; CONSP (tail); tail = XCDR (tail))
     if (! NILP (XCAR (tail)))
       safe_codings = Fcons (CODING_ATTR_BASE_NAME (XCAR (tail)), safe_codings);
@@ -7304,7 +7578,7 @@ to the string.  */)
     return Qnil;
   ascii_compatible = ! NILP (CODING_ATTR_ASCII_COMPAT (attrs));
   charset_list = CODING_ATTR_CHARSET_LIST (attrs);
-  translation_table = get_translation_table (attrs, 1);
+  translation_table = get_translation_table (attrs, 1, NULL);
 
   if (NILP (string))
     {
@@ -7447,7 +7721,8 @@ buffer positions.  END is ignored.  */)
     {
       elt = XCAR (tail);
       attrs = AREF (CODING_SYSTEM_SPEC (elt), 0);
-      ASET (attrs, coding_attr_trans_tbl, get_translation_table (attrs, 1));
+      ASET (attrs, coding_attr_trans_tbl,
+           get_translation_table (attrs, 1, NULL));
       list = Fcons (Fcons (elt, Fcons (attrs, Qnil)), list);
     }
 
@@ -8623,7 +8898,7 @@ DEFUN ("coding-system-put", Fcoding_system_put, Scoding_system_put,
   (coding_system, prop, val)
      Lisp_Object coding_system, prop, val;
 {
-  Lisp_Object spec, attrs, plist;
+  Lisp_Object spec, attrs;
 
   CHECK_CODING_SYSTEM_GET_SPEC (coding_system, spec);
   attrs = AREF (spec, 0);
@@ -8922,7 +9197,7 @@ syms_of_coding ()
   Qchar_table_extra_slots = intern ("char-table-extra-slots");
 
   DEFSYM (Qtranslation_table, "translation-table");
-  Fput (Qtranslation_table, Qchar_table_extra_slots, make_number (1));
+  Fput (Qtranslation_table, Qchar_table_extra_slots, make_number (2));
   DEFSYM (Qtranslation_table_id, "translation-table-id");
   DEFSYM (Qtranslation_table_for_decode, "translation-table-for-decode");
   DEFSYM (Qtranslation_table_for_encode, "translation-table-for-encode");
@@ -9354,3 +9629,6 @@ emacs_strerror (error_number)
 }
 
 #endif /* emacs */
+
+/* arch-tag: 3a3a2b01-5ff6-4071-9afe-f5b808d9229d
+   (do not change this comment) */