]> code.delx.au - gnu-emacs/blobdiff - src/ccl.c
* lisp/window.el (display-buffer--action-function-custom-type):
[gnu-emacs] / src / ccl.c
index 630c6b3de9eefdd5bd532159494dec1b42c76e1b..cb96eece5eec1edbb208eaa35c42f11f8a61d04a 100644 (file)
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -61,7 +61,7 @@ static Lisp_Object Vccl_program_table;
 
 /* Return a hash table of id number ID.  */
 #define GET_HASH_TABLE(id) \
-  (XHASH_TABLE (XCDR(XVECTOR(Vtranslation_hash_table_vector)->contents[(id)])))
+  (XHASH_TABLE (XCDR (XVECTOR (Vtranslation_hash_table_vector)->contents[(id)])))
 
 /* CCL (Code Conversion Language) is a simple language which has
    operations on one input buffer, one output buffer, and 7 registers.
@@ -79,9 +79,8 @@ static Lisp_Object Vccl_program_table;
 #define CCL_HEADER_EOF         1
 #define CCL_HEADER_MAIN                2
 
-/* CCL code is a sequence of 28-bit non-negative integers (i.e. the
-   MSB is always 0), each contains CCL command and/or arguments in the
-   following format:
+/* CCL code is a sequence of 28-bit integers.  Each contains a CCL
+   command and/or arguments in the following format:
 
        |----------------- integer (28-bit) ------------------|
        |------- 17-bit ------|- 3-bit --|- 3-bit --|- 5-bit -|
@@ -94,12 +93,13 @@ static Lisp_Object Vccl_program_table;
        |------------- constant or other args ----------------|
                      cccccccccccccccccccccccccccc
 
-   where, `cc...c' is a non-negative integer indicating constant value
-   (the left most `c' is always 0) or an absolute jump address, `RRR'
+   where `cc...c' is a 17-bit, 20-bit, or 28-bit integer indicating a
+   constant value or a relative/absolute jump address, `RRR'
    and `rrr' are CCL register number, `XXXXX' is one of the following
    CCL commands.  */
 
 #define CCL_CODE_MAX ((1 << (28 - 1)) - 1)
+#define CCL_CODE_MIN (-1 - CCL_CODE_MAX)
 
 /* CCL commands
 
@@ -706,7 +706,7 @@ do                                  \
     ccl->status = CCL_STAT_SUCCESS;    \
     goto ccl_finish;                   \
   }                                    \
-while(0)
+while (0)
 
 /* Suspend CCL program because of reading from empty input buffer or
    writing to full output buffer.  When this program is resumed, the
@@ -730,7 +730,7 @@ do                                  \
     ccl->status = CCL_STAT_INVALID_CMD;        \
     goto ccl_error_handler;            \
   }                                    \
-while(0)
+while (0)
 
 #else
 
@@ -741,27 +741,31 @@ do                                        \
     ccl->status = CCL_STAT_INVALID_CMD;        \
     goto ccl_error_handler;            \
   }                                    \
-while(0)
+while (0)
 
 #endif
 
+/* Use "&" rather than "&&" to suppress a bogus GCC warning; see
+   <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43772>.  */
+#define ASCENDING_ORDER(lo, med, hi) (((lo) <= (med)) & ((med) <= (hi)))
+
 #define GET_CCL_RANGE(var, ccl_prog, ic, lo, hi)               \
   do                                                           \
     {                                                          \
       EMACS_INT prog_word = XINT ((ccl_prog)[ic]);             \
-      if (! ((lo) <= prog_word && prog_word <= (hi)))          \
+      if (! ASCENDING_ORDER (lo, prog_word, hi))               \
        CCL_INVALID_CMD;                                        \
       (var) = prog_word;                                       \
     }                                                          \
   while (0)
 
 #define GET_CCL_CODE(code, ccl_prog, ic)                       \
-  GET_CCL_RANGE (code, ccl_prog, ic, 0, CCL_CODE_MAX)
+  GET_CCL_RANGE (code, ccl_prog, ic, CCL_CODE_MIN, CCL_CODE_MAX)
 
 #define GET_CCL_INT(var, ccl_prog, ic)                         \
   GET_CCL_RANGE (var, ccl_prog, ic, INT_MIN, INT_MAX)
 
-#define IN_INT_RANGE(val) (INT_MIN <= (val) && (val) <= INT_MAX)
+#define IN_INT_RANGE(val) ASCENDING_ORDER (INT_MIN, val, INT_MAX)
 
 /* Encode one character CH to multibyte form and write to the current
    output buffer.  If CH is less than 256, CH is written as is.  */
@@ -1299,7 +1303,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
 
            case CCL_LookupIntConstTbl:
              {
-               EMACS_INT eop;
+               ptrdiff_t eop;
                struct Lisp_Hash_Table *h;
                GET_CCL_RANGE (eop, ccl_prog, ic++, 0,
                               (VECTORP (Vtranslation_hash_table_vector)
@@ -1307,15 +1311,15 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
                                : -1));
                h = GET_HASH_TABLE (eop);
 
-               op = hash_lookup (h, make_number (reg[RRR]), NULL);
-               if (op >= 0)
+               eop = hash_lookup (h, make_number (reg[RRR]), NULL);
+               if (eop >= 0)
                  {
                    Lisp_Object opl;
-                   opl = HASH_VALUE (h, op);
-                   if (! CHARACTERP (opl))
+                   opl = HASH_VALUE (h, eop);
+                   if (! (IN_INT_RANGE (eop) && CHARACTERP (opl)))
                      CCL_INVALID_CMD;
                    reg[RRR] = charset_unicode;
-                   reg[rrr] = op;
+                   reg[rrr] = eop;
                    reg[7] = 1; /* r7 true for success */
                  }
                else
@@ -1325,7 +1329,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
 
            case CCL_LookupCharConstTbl:
              {
-               EMACS_INT eop;
+               ptrdiff_t eop;
                struct Lisp_Hash_Table *h;
                GET_CCL_RANGE (eop, ccl_prog, ic++, 0,
                               (VECTORP (Vtranslation_hash_table_vector)
@@ -1334,11 +1338,11 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
                i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
                h = GET_HASH_TABLE (eop);
 
-               op = hash_lookup (h, make_number (i), NULL);
-               if (op >= 0)
+               eop = hash_lookup (h, make_number (i), NULL);
+               if (eop >= 0)
                  {
                    Lisp_Object opl;
-                   opl = HASH_VALUE (h, op);
+                   opl = HASH_VALUE (h, eop);
                    if (! (INTEGERP (opl) && IN_INT_RANGE (XINT (opl))))
                      CCL_INVALID_CMD;
                    reg[RRR] = XINT (opl);
@@ -1415,7 +1419,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
                    else if (INTEGERP (content) && IN_INT_RANGE (XINT (content)))
                      {
                        reg[RRR] = i;
-                       reg[rrr] = XINT(content);
+                       reg[rrr] = XINT (content);
                        break;
                      }
                    else if (EQ (content, Qt) || EQ (content, Qlambda))
@@ -1688,7 +1692,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
                    value = XCDR (content);
                    if (!INTEGERP (attrib) || !INTEGERP (value))
                      continue;
-                   reg[rrr] = XINT(value);
+                   reg[rrr] = XINT (value);
                    break;
                  }
                else if (SYMBOLP (content))
@@ -1725,8 +1729,8 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
       switch (ccl->status)
        {
        case CCL_STAT_INVALID_CMD:
-         sprintf(msg, "\nCCL: Invalid command %x (ccl_code = %x) at %d.",
-                 code & 0x1F, code, this_ic);
+         sprintf (msg, "\nCCL: Invalid command %x (ccl_code = %x) at %d.",
+                   code & 0x1F, code, this_ic);
 #ifdef CCL_DEBUG
          {
            int i = ccl_backtrace_idx - 1;
@@ -1744,7 +1748,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
                if (i < 0) i = CCL_DEBUG_BACKTRACE_LEN - 1;
                if (ccl_backtrace_table[i] == 0)
                  break;
-               sprintf(msg, " %d", ccl_backtrace_table[i]);
+               sprintf (msg, " %d", ccl_backtrace_table[i]);
                msglen = strlen (msg);
                if (dst + msglen > (dst_bytes ? dst_end : src))
                  break;
@@ -1758,15 +1762,15 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
 
        case CCL_STAT_QUIT:
          if (! ccl->quit_silently)
-           sprintf(msg, "\nCCL: Quited.");
+           sprintf (msg, "\nCCL: Quited.");
          break;
 
        default:
-         sprintf(msg, "\nCCL: Unknown error type (%d)", ccl->status);
+         sprintf (msg, "\nCCL: Unknown error type (%d)", ccl->status);
        }
 
       msglen = strlen (msg);
-      if (dst + msglen <= dst_end)
+      if (msglen <= dst_end - dst)
        {
          for (i = 0; i < msglen; i++)
            *dst++ = msg[i];
@@ -2057,12 +2061,13 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY
   Lisp_Object val;
   struct ccl_program ccl;
   int i;
-  EMACS_INT outbufsize;
+  ptrdiff_t outbufsize;
   unsigned char *outbuf, *outp;
-  EMACS_INT str_chars, str_bytes;
+  ptrdiff_t str_chars, str_bytes;
 #define CCL_EXECUTE_BUF_SIZE 1024
   int source[CCL_EXECUTE_BUF_SIZE], destination[CCL_EXECUTE_BUF_SIZE];
-  EMACS_INT consumed_chars, consumed_bytes, produced_chars;
+  ptrdiff_t consumed_chars, consumed_bytes, produced_chars;
+  int buf_magnification;
 
   if (setup_ccl_program (&ccl, ccl_prog) < 0)
     error ("Invalid CCL program");
@@ -2089,6 +2094,10 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY
        ccl.ic = i;
     }
 
+  buf_magnification = ccl.buf_magnification ? ccl.buf_magnification : 1;
+
+  if ((min (PTRDIFF_MAX, SIZE_MAX) - 256) / buf_magnification < str_bytes)
+    memory_full (SIZE_MAX);
   outbufsize = (ccl.buf_magnification
                ? str_bytes * ccl.buf_magnification + 256
                : str_bytes + 256);
@@ -2118,31 +2127,25 @@ usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBY
       src_size = j;
       while (1)
        {
+         int max_expansion = NILP (unibyte_p) ? MAX_MULTIBYTE_LENGTH : 1;
+         ptrdiff_t offset, shortfall;
          ccl_driver (&ccl, src, destination, src_size, CCL_EXECUTE_BUF_SIZE,
                      Qnil);
          produced_chars += ccl.produced;
+         offset = outp - outbuf;
+         shortfall = ccl.produced * max_expansion - (outbufsize - offset);
+         if (0 < shortfall)
+           {
+             outbuf = xpalloc (outbuf, &outbufsize, shortfall, -1, 1);
+             outp = outbuf + offset;
+           }
          if (NILP (unibyte_p))
            {
-             if (outp - outbuf + MAX_MULTIBYTE_LENGTH * ccl.produced
-                 > outbufsize)
-               {
-                 EMACS_INT offset = outp - outbuf;
-                 outbufsize += MAX_MULTIBYTE_LENGTH * ccl.produced;
-                 outbuf = (unsigned char *) xrealloc (outbuf, outbufsize);
-                 outp = outbuf + offset;
-               }
              for (j = 0; j < ccl.produced; j++)
                CHAR_STRING_ADVANCE (destination[j], outp);
            }
          else
            {
-             if (outp - outbuf + ccl.produced > outbufsize)
-               {
-                 EMACS_INT offset = outp - outbuf;
-                 outbufsize += ccl.produced;
-                 outbuf = (unsigned char *) xrealloc (outbuf, outbufsize);
-                 outp = outbuf + offset;
-               }
              for (j = 0; j < ccl.produced; j++)
                *outp++ = destination[j];
            }
@@ -2301,23 +2304,12 @@ syms_of_ccl (void)
   staticpro (&Vccl_program_table);
   Vccl_program_table = Fmake_vector (make_number (32), Qnil);
 
-  Qccl = intern_c_string ("ccl");
-  staticpro (&Qccl);
-
-  Qcclp = intern_c_string ("cclp");
-  staticpro (&Qcclp);
-
-  Qccl_program = intern_c_string ("ccl-program");
-  staticpro (&Qccl_program);
-
-  Qccl_program_idx = intern_c_string ("ccl-program-idx");
-  staticpro (&Qccl_program_idx);
-
-  Qcode_conversion_map = intern_c_string ("code-conversion-map");
-  staticpro (&Qcode_conversion_map);
-
-  Qcode_conversion_map_id = intern_c_string ("code-conversion-map-id");
-  staticpro (&Qcode_conversion_map_id);
+  DEFSYM (Qccl, "ccl");
+  DEFSYM (Qcclp, "cclp");
+  DEFSYM (Qccl_program, "ccl-program");
+  DEFSYM (Qccl_program_idx, "ccl-program-idx");
+  DEFSYM (Qcode_conversion_map, "code-conversion-map");
+  DEFSYM (Qcode_conversion_map_id, "code-conversion-map-id");
 
   DEFVAR_LISP ("code-conversion-map-vector", Vcode_conversion_map_vector,
               doc: /* Vector of code conversion maps.  */);