/* 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.
#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 -|
|------------- 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
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
ccl->status = CCL_STAT_INVALID_CMD; \
goto ccl_error_handler; \
} \
-while(0)
+while (0)
#else
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. */
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)
: -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
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)
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);
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))
value = XCDR (content);
if (!INTEGERP (attrib) || !INTEGERP (value))
continue;
- reg[rrr] = XINT(value);
+ reg[rrr] = XINT (value);
break;
}
else if (SYMBOLP (content))
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;
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;
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];
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");
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);
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];
}
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. */);