Add 2012 to FSF copyright years for Emacs files
[bpt/emacs.git] / src / coding.c
index d914e0d..5c3048f 100644 (file)
@@ -1,5 +1,5 @@
 /* Coding system handler (conversion, detection, etc).
-   Copyright (C) 2001-2011 Free Software Foundation, Inc.
+   Copyright (C) 2001-2012 Free Software Foundation, Inc.
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
      2005, 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
@@ -847,16 +847,16 @@ static int encode_coding_ccl (struct coding_system *);
 static void decode_coding_raw_text (struct coding_system *);
 static int encode_coding_raw_text (struct coding_system *);
 
-static void coding_set_source (struct coding_system *);
-static void coding_set_destination (struct coding_system *);
+static EMACS_INT coding_set_source (struct coding_system *);
+static EMACS_INT coding_set_destination (struct coding_system *);
 static void coding_alloc_by_realloc (struct coding_system *, EMACS_INT);
 static void coding_alloc_by_making_gap (struct coding_system *,
                                         EMACS_INT, EMACS_INT);
 static unsigned char *alloc_destination (struct coding_system *,
                                          EMACS_INT, unsigned char *);
 static void setup_iso_safe_charsets (Lisp_Object);
-static unsigned char *encode_designation_at_bol (struct coding_system *,
-                                                 int *, unsigned char *);
+static int encode_designation_at_bol (struct coding_system *,
+                                     int *, int *, unsigned char *);
 static int detect_eol (const unsigned char *,
                        EMACS_INT, enum coding_category);
 static Lisp_Object adjust_coding_eol_type (struct coding_system *, int);
@@ -915,27 +915,68 @@ record_conversion_result (struct coding_system *coding,
     }
 }
 
-/* This wrapper macro is used to preserve validity of pointers into
-   buffer text across calls to decode_char, which could cause
-   relocation of buffers if it loads a charset map, because loading a
-   charset map allocates large structures.  */
+/* These wrapper macros are used to preserve validity of pointers into
+   buffer text across calls to decode_char, encode_char, etc, which
+   could cause relocation of buffers if it loads a charset map,
+   because loading a charset map allocates large structures.  */
+
 #define CODING_DECODE_CHAR(coding, src, src_base, src_end, charset, code, c) \
   do {                                                                      \
+    EMACS_INT offset;                                                       \
+                                                                            \
     charset_map_loaded = 0;                                                 \
     c = DECODE_CHAR (charset, code);                                        \
-    if (charset_map_loaded)                                                 \
+    if (charset_map_loaded                                                  \
+       && (offset = coding_set_source (coding)))                            \
       {                                                                             \
-       const unsigned char *orig = coding->source;                          \
-       EMACS_INT offset;                                                    \
-                                                                            \
-       coding_set_source (coding);                                          \
-       offset = coding->source - orig;                                      \
        src += offset;                                                       \
        src_base += offset;                                                  \
        src_end += offset;                                                   \
       }                                                                             \
   } while (0)
 
+#define CODING_ENCODE_CHAR(coding, dst, dst_end, charset, c, code)     \
+  do {                                                                 \
+    EMACS_INT offset;                                                  \
+                                                                       \
+    charset_map_loaded = 0;                                            \
+    code = ENCODE_CHAR (charset, c);                                   \
+    if (charset_map_loaded                                             \
+       && (offset = coding_set_destination (coding)))                  \
+      {                                                                        \
+       dst += offset;                                                  \
+       dst_end += offset;                                              \
+      }                                                                        \
+  } while (0)
+
+#define CODING_CHAR_CHARSET(coding, dst, dst_end, c, charset_list, code_return, charset) \
+  do {                                                                 \
+    EMACS_INT offset;                                                  \
+                                                                       \
+    charset_map_loaded = 0;                                            \
+    charset = char_charset (c, charset_list, code_return);             \
+    if (charset_map_loaded                                             \
+       && (offset = coding_set_destination (coding)))                  \
+      {                                                                        \
+       dst += offset;                                                  \
+       dst_end += offset;                                              \
+      }                                                                        \
+  } while (0)
+
+#define CODING_CHAR_CHARSET_P(coding, dst, dst_end, c, charset, result)        \
+  do {                                                                 \
+    EMACS_INT offset;                                                  \
+                                                                       \
+    charset_map_loaded = 0;                                            \
+    result = CHAR_CHARSET_P (c, charset);                              \
+    if (charset_map_loaded                                             \
+       && (offset = coding_set_destination (coding)))                  \
+      {                                                                        \
+       dst += offset;                                                  \
+       dst_end += offset;                                              \
+      }                                                                        \
+  } while (0)
+
 
 /* If there are at least BYTES length of room at dst, allocate memory
    for coding->destination and update dst and dst_end.  We don't have
@@ -1015,9 +1056,14 @@ record_conversion_result (struct coding_system *coding,
        | ((p)[-1] & 0x3F))))
 
 
-static void
+/* Update coding->source from coding->src_object, and return how many
+   bytes coding->source was changed.  */
+
+static EMACS_INT
 coding_set_source (struct coding_system *coding)
 {
+  const unsigned char *orig = coding->source;
+
   if (BUFFERP (coding->src_object))
     {
       struct buffer *buf = XBUFFER (coding->src_object);
@@ -1036,14 +1082,21 @@ coding_set_source (struct coding_system *coding)
       /* Otherwise, the source is C string and is never relocated
         automatically.  Thus we don't have to update anything.  */
     }
+  return coding->source - orig;
 }
 
-static void
+
+/* Update coding->destination from coding->dst_object, and return how
+   many bytes coding->destination was changed.  */
+
+static EMACS_INT
 coding_set_destination (struct coding_system *coding)
 {
+  const unsigned char *orig = coding->destination;
+
   if (BUFFERP (coding->dst_object))
     {
-      if (coding->src_pos < 0)
+      if (BUFFERP (coding->src_object) && coding->src_pos < 0)
        {
          coding->destination = BEG_ADDR + coding->dst_pos_byte - BEG_BYTE;
          coding->dst_bytes = (GAP_END_ADDR
@@ -1065,6 +1118,7 @@ coding_set_destination (struct coding_system *coding)
       /* Otherwise, the destination is C string and is never relocated
         automatically.  Thus we don't have to update anything.  */
     }
+  return coding->destination - orig;
 }
 
 
@@ -2650,14 +2704,19 @@ encode_coding_emacs_mule (struct coding_system *coding)
 
          if (preferred_charset_id >= 0)
            {
+             int result;
+
              charset = CHARSET_FROM_ID (preferred_charset_id);
-             if (CHAR_CHARSET_P (c, charset))
+             CODING_CHAR_CHARSET_P (coding, dst, dst_end, c, charset, result);
+             if (result)
                code = ENCODE_CHAR (charset, c);
              else
-               charset = char_charset (c, charset_list, &code);
+               CODING_CHAR_CHARSET (coding, dst, dst_end, c, charset_list,
+                                    &code, charset);
            }
          else
-           charset = char_charset (c, charset_list, &code);
+           CODING_CHAR_CHARSET (coding, dst, dst_end, c, charset_list,
+                                &code, charset);
          if (! charset)
            {
              c = coding->default_char;
@@ -2666,7 +2725,8 @@ encode_coding_emacs_mule (struct coding_system *coding)
                  EMIT_ONE_ASCII_BYTE (c);
                  continue;
                }
-             charset = char_charset (c, charset_list, &code);
+             CODING_CHAR_CHARSET (coding, dst, dst_end, c, charset_list,
+                                  &code, charset);
            }
          dimension = CHARSET_DIMENSION (charset);
          emacs_mule_id = CHARSET_EMACS_MULE_ID (charset);
@@ -4185,7 +4245,8 @@ decode_coding_iso_2022 (struct coding_system *coding)
 
 #define ENCODE_ISO_CHARACTER(charset, c)                                  \
   do {                                                                    \
-    int code = ENCODE_CHAR ((charset), (c));                              \
+    int code;                                                             \
+    CODING_ENCODE_CHAR (coding, dst, dst_end, (charset), (c), code);      \
                                                                           \
     if (CHARSET_DIMENSION (charset) == 1)                                 \
       ENCODE_ISO_CHARACTER_DIMENSION1 ((charset), code);                  \
@@ -4283,15 +4344,19 @@ encode_invocation_designation (struct charset *charset,
 
 
 /* Produce designation sequences of charsets in the line started from
-   SRC to a place pointed by DST, and return updated DST.
+   CHARBUF to a place pointed by DST, and return the number of
+   produced bytes.  DST should not directly point a buffer text area
+   which may be relocated by char_charset call.
 
    If the current block ends before any end-of-line, we may fail to
    find all the necessary designations.  */
 
-static unsigned char *
-encode_designation_at_bol (struct coding_system *coding, int *charbuf,
+static int
+encode_designation_at_bol (struct coding_system *coding,
+                          int *charbuf, int *charbuf_end,
                           unsigned char *dst)
 {
+  unsigned char *orig = dst;
   struct charset *charset;
   /* Table of charsets to be designated to each graphic register.  */
   int r[4];
@@ -4309,7 +4374,7 @@ encode_designation_at_bol (struct coding_system *coding, int *charbuf,
   for (reg = 0; reg < 4; reg++)
     r[reg] = -1;
 
-  while (found < 4)
+  while (charbuf < charbuf_end && found < 4)
     {
       int id;
 
@@ -4334,7 +4399,7 @@ encode_designation_at_bol (struct coding_system *coding, int *charbuf,
          ENCODE_DESIGNATION (CHARSET_FROM_ID (r[reg]), reg, coding);
     }
 
-  return dst;
+  return dst - orig;
 }
 
 /* See the above "GENERAL NOTES on `encode_coding_XXX ()' functions".  */
@@ -4378,13 +4443,26 @@ encode_coding_iso_2022 (struct coding_system *coding)
 
       if (bol_designation)
        {
-         unsigned char *dst_prev = dst;
-
          /* We have to produce designation sequences if any now.  */
-         dst = encode_designation_at_bol (coding, charbuf, dst);
-         bol_designation = 0;
+         unsigned char desig_buf[16];
+         int nbytes;
+         EMACS_INT offset;
+
+         charset_map_loaded = 0;
+         nbytes = encode_designation_at_bol (coding, charbuf, charbuf_end,
+                                             desig_buf);
+         if (charset_map_loaded
+             && (offset = coding_set_destination (coding)))
+           {
+             dst += offset;
+             dst_end += offset;
+           }
+         memcpy (dst, desig_buf, nbytes);
+         dst += nbytes;
          /* We are sure that designation sequences are all ASCII bytes.  */
-         produced_chars += dst - dst_prev;
+         produced_chars += nbytes;
+         bol_designation = 0;
+         ASSURE_DESTINATION (safe_room);
        }
 
       c = *charbuf++;
@@ -4455,12 +4533,17 @@ encode_coding_iso_2022 (struct coding_system *coding)
 
          if (preferred_charset_id >= 0)
            {
+             int result;
+
              charset = CHARSET_FROM_ID (preferred_charset_id);
-             if (! CHAR_CHARSET_P (c, charset))
-               charset = char_charset (c, charset_list, NULL);
+             CODING_CHAR_CHARSET_P (coding, dst, dst_end, c, charset, result);
+             if (! result)
+               CODING_CHAR_CHARSET (coding, dst, dst_end, c, charset_list,
+                                    NULL, charset);
            }
          else
-           charset = char_charset (c, charset_list, NULL);
+           CODING_CHAR_CHARSET (coding, dst, dst_end, c, charset_list,
+                                NULL, charset);
          if (!charset)
            {
              if (coding->mode & CODING_MODE_SAFE_ENCODING)
@@ -4471,7 +4554,8 @@ encode_coding_iso_2022 (struct coding_system *coding)
              else
                {
                  c = coding->default_char;
-                 charset = char_charset (c, charset_list, NULL);
+                 CODING_CHAR_CHARSET (coding, dst, dst_end, c,
+                                      charset_list, NULL, charset);
                }
            }
          ENCODE_ISO_CHARACTER (charset, c);
@@ -4897,7 +4981,9 @@ encode_coding_sjis (struct coding_system *coding)
       else
        {
          unsigned code;
-         struct charset *charset = char_charset (c, charset_list, &code);
+         struct charset *charset;
+         CODING_CHAR_CHARSET (coding, dst, dst_end, c, charset_list,
+                              &code, charset);
 
          if (!charset)
            {
@@ -4909,7 +4995,8 @@ encode_coding_sjis (struct coding_system *coding)
              else
                {
                  c = coding->default_char;
-                 charset = char_charset (c, charset_list, &code);
+                 CODING_CHAR_CHARSET (coding, dst, dst_end, c,
+                                      charset_list, &code, charset);
                }
            }
          if (code == CHARSET_INVALID_CODE (charset))
@@ -4984,7 +5071,9 @@ encode_coding_big5 (struct coding_system *coding)
       else
        {
          unsigned code;
-         struct charset *charset = char_charset (c, charset_list, &code);
+         struct charset *charset;
+         CODING_CHAR_CHARSET (coding, dst, dst_end, c, charset_list,
+                              &code, charset);
 
          if (! charset)
            {
@@ -4996,7 +5085,8 @@ encode_coding_big5 (struct coding_system *coding)
              else
                {
                  c = coding->default_char;
-                 charset = char_charset (c, charset_list, &code);
+                 CODING_CHAR_CHARSET (coding, dst, dst_end, c,
+                                      charset_list, &code, charset);
                }
            }
          if (code == CHARSET_INVALID_CODE (charset))
@@ -5154,7 +5244,7 @@ encode_coding_ccl (struct coding_system *coding)
       && coding->mode & CODING_MODE_LAST_BLOCK)
     ccl->last_block = 1;
 
-  while (charbuf < charbuf_end)
+  do
     {
       ccl_driver (ccl, charbuf, destination_charbuf,
                  charbuf_end - charbuf, 1024, charset_list);
@@ -5176,6 +5266,7 @@ encode_coding_ccl (struct coding_system *coding)
          || ccl->status == CCL_STAT_INVALID_CMD)
        break;
     }
+  while (charbuf < charbuf_end);
 
   switch (ccl->status)
     {
@@ -5572,7 +5663,9 @@ encode_coding_charset (struct coding_system *coding)
        }
       else
        {
-         charset = char_charset (c, charset_list, &code);
+         CODING_CHAR_CHARSET (coding, dst, dst_end, c, charset_list,
+                              &code, charset);
+
          if (charset)
            {
              if (CHARSET_DIMENSION (charset) == 1)
@@ -5838,7 +5931,7 @@ coding_charset_list (struct coding_system *coding)
 Lisp_Object
 coding_system_charset_list (Lisp_Object coding_system)
 {
-  int id;
+  ptrdiff_t id;
   Lisp_Object attrs, charset_list;
 
   CHECK_CODING_SYSTEM_GET_ID (coding_system, id);
@@ -6683,8 +6776,12 @@ produce_chars (struct coding_system *coding, Lisp_Object translation_table,
                    break;
                }
 
-             if (dst + MAX_MULTIBYTE_LENGTH * to_nchars > dst_end)
+             if ((dst_end - dst) / MAX_MULTIBYTE_LENGTH < to_nchars)
                {
+                 if (((min (PTRDIFF_MAX, SIZE_MAX) - (buf_end - buf))
+                      / MAX_MULTIBYTE_LENGTH)
+                     < to_nchars)
+                   memory_full (SIZE_MAX);
                  dst = alloc_destination (coding,
                                           buf_end - buf
                                           + MAX_MULTIBYTE_LENGTH * to_nchars,
@@ -7888,11 +7985,10 @@ encode_coding_object (struct coding_system *coding,
     }
   else if (EQ (dst_object, Qt))
     {
+      ptrdiff_t dst_bytes = max (1, coding->src_chars);
       coding->dst_object = Qnil;
-      coding->dst_bytes = coding->src_chars;
-      if (coding->dst_bytes == 0)
-       coding->dst_bytes = 1;
-      coding->destination = (unsigned char *) xmalloc (coding->dst_bytes);
+      coding->destination = (unsigned char *) xmalloc (dst_bytes);
+      coding->dst_bytes = dst_bytes;
       coding->dst_multibyte = 0;
     }
   else
@@ -8076,7 +8172,7 @@ detect_coding_system (const unsigned char *src,
   Lisp_Object attrs, eol_type;
   Lisp_Object val = Qnil;
   struct coding_system coding;
-  int id;
+  ptrdiff_t id;
   struct coding_detection_info detect_info;
   enum coding_category base_category;
   int null_byte_found = 0, eight_bit_found = 0;
@@ -8660,6 +8756,7 @@ to the string.  */)
     }
 
   positions = Qnil;
+  charset_map_loaded = 0;
   while (1)
     {
       int c;
@@ -8687,6 +8784,16 @@ to the string.  */)
        }
 
       from++;
+      if (charset_map_loaded && NILP (string))
+       {
+         p = CHAR_POS_ADDR (from);
+         pend = CHAR_POS_ADDR (to);
+         if (from < GPT && to >= GPT)
+           stop = GPT_ADDR;
+         else
+           stop = pend;
+         charset_map_loaded = 0;
+       }
     }
 
   return (NILP (count) ? Fcar (positions) : Fnreverse (positions));
@@ -9000,7 +9107,7 @@ not fully specified.)  */)
   (Lisp_Object string, Lisp_Object coding_system, Lisp_Object nocopy, Lisp_Object buffer)
 {
   return code_convert_string (string, coding_system, buffer,
-                             1, ! NILP (nocopy), 1);
+                             1, ! NILP (nocopy), 0);
 }
 
 \f
@@ -9205,7 +9312,7 @@ frame's terminal device.  */)
     = TERMINAL_TERMINAL_CODING (get_terminal (terminal, 1));
   Lisp_Object coding_system = CODING_ID_NAME (terminal_coding->id);
 
-  /* For backward compatibility, return nil if it is `undecided'. */
+  /* For backward compatibility, return nil if it is `undecided'.  */
   return (! EQ (coding_system, Qundecided) ? coding_system : Qnil);
 }
 
@@ -9278,7 +9385,7 @@ function to call for FILENAME, that function should examine the
 contents of BUFFER instead of reading the file.
 
 usage: (find-operation-coding-system OPERATION ARGUMENTS...)  */)
-  (size_t nargs, Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   Lisp_Object operation, target_idx, target, val;
   register Lisp_Object chain;
@@ -9355,9 +9462,9 @@ If multiple coding systems belong to the same category,
 all but the first one are ignored.
 
 usage: (set-coding-system-priority &rest coding-systems)  */)
-  (size_t nargs, Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
-  size_t i, j;
+  ptrdiff_t i, j;
   int changed[coding_category_max];
   enum coding_category priorities[coding_category_max];
 
@@ -9442,7 +9549,7 @@ static Lisp_Object
 make_subsidiaries (Lisp_Object base)
 {
   Lisp_Object subsidiaries;
-  int base_name_len = SBYTES (SYMBOL_NAME (base));
+  ptrdiff_t base_name_len = SBYTES (SYMBOL_NAME (base));
   char *buf = (char *) alloca (base_name_len + 6);
   int i;
 
@@ -9450,7 +9557,7 @@ make_subsidiaries (Lisp_Object base)
   subsidiaries = Fmake_vector (make_number (3), Qnil);
   for (i = 0; i < 3; i++)
     {
-      memcpy (buf + base_name_len, suffixes[i], strlen (suffixes[i]) + 1);
+      strcpy (buf + base_name_len, suffixes[i]);
       ASET (subsidiaries, i, intern (buf));
     }
   return subsidiaries;
@@ -9461,7 +9568,7 @@ DEFUN ("define-coding-system-internal", Fdefine_coding_system_internal,
        Sdefine_coding_system_internal, coding_arg_max, MANY, 0,
        doc: /* For internal use only.
 usage: (define-coding-system-internal ...)  */)
-  (size_t nargs, Lisp_Object *args)
+  (ptrdiff_t nargs, Lisp_Object *args)
 {
   Lisp_Object name;
   Lisp_Object spec_vec;                /* [ ATTRS ALIASE EOL_TYPE ] */
@@ -9892,8 +9999,6 @@ usage: (define-coding-system-internal ...)  */)
     {
       Lisp_Object bom;
 
-      CODING_ATTR_ASCII_COMPAT (attrs) = Qt;
-
       if (nargs < coding_arg_utf8_max)
        goto short_args;
 
@@ -9907,6 +10012,8 @@ usage: (define-coding-system-internal ...)  */)
          CHECK_CODING_SYSTEM (val);
        }
       ASET (attrs, coding_attr_utf_bom, bom);
+      if (NILP (bom))
+       CODING_ATTR_ASCII_COMPAT (attrs) = Qt;
 
       category = (CONSP (bom) ? coding_category_utf_8_auto
                  : NILP (bom) ? coding_category_utf_8_nosig