1 |
/* CCL (Code Conversion Language) interpreter. |
/* CCL (Code Conversion Language) interpreter. |
2 |
Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN. |
Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN. |
3 |
|
Licensed to the Free Software Foundation. |
4 |
Copyright (C) 2001, 2002 Free Software Foundation, Inc. |
Copyright (C) 2001, 2002 Free Software Foundation, Inc. |
5 |
Licensed to the Free Software Foundation. |
Copyright (C) 2003 |
6 |
|
National Institute of Advanced Industrial Science and Technology (AIST) |
7 |
|
Registration Number H13PRO009 |
8 |
|
|
9 |
This file is part of GNU Emacs. |
This file is part of GNU Emacs. |
10 |
|
|
28 |
#include <stdio.h> |
#include <stdio.h> |
29 |
|
|
30 |
#include "lisp.h" |
#include "lisp.h" |
31 |
|
#include "character.h" |
32 |
#include "charset.h" |
#include "charset.h" |
33 |
#include "ccl.h" |
#include "ccl.h" |
34 |
#include "coding.h" |
#include "coding.h" |
35 |
|
|
36 |
|
Lisp_Object Qccl, Qcclp; |
37 |
|
|
38 |
/* This contains all code conversion map available to CCL. */ |
/* This contains all code conversion map available to CCL. */ |
39 |
Lisp_Object Vcode_conversion_map_vector; |
Lisp_Object Vcode_conversion_map_vector; |
40 |
|
|
68 |
#define GET_HASH_TABLE(id) \ |
#define GET_HASH_TABLE(id) \ |
69 |
(XHASH_TABLE (XCDR(XVECTOR(Vtranslation_hash_table_vector)->contents[(id)]))) |
(XHASH_TABLE (XCDR(XVECTOR(Vtranslation_hash_table_vector)->contents[(id)]))) |
70 |
|
|
71 |
|
extern int charset_unicode; |
72 |
|
|
73 |
/* CCL (Code Conversion Language) is a simple language which has |
/* CCL (Code Conversion Language) is a simple language which has |
74 |
operations on one input buffer, one output buffer, and 7 registers. |
operations on one input buffer, one output buffer, and 7 registers. |
75 |
The syntax of CCL is described in `ccl.el'. Emacs Lisp function |
The syntax of CCL is described in `ccl.el'. Emacs Lisp function |
728 |
|
|
729 |
/* Encode one character CH to multibyte form and write to the current |
/* Encode one character CH to multibyte form and write to the current |
730 |
output buffer. If CH is less than 256, CH is written as is. */ |
output buffer. If CH is less than 256, CH is written as is. */ |
731 |
#define CCL_WRITE_CHAR(ch) \ |
#define CCL_WRITE_CHAR(ch) \ |
732 |
do { \ |
do { \ |
733 |
int bytes = SINGLE_BYTE_CHAR_P (ch) ? 1: CHAR_BYTES (ch); \ |
if (! dst) \ |
734 |
if (!dst) \ |
CCL_INVALID_CMD; \ |
735 |
CCL_INVALID_CMD; \ |
else if (dst < dst_end) \ |
736 |
else if (dst + bytes + extra_bytes < (dst_bytes ? dst_end : src)) \ |
*dst++ = (ch); \ |
737 |
{ \ |
else \ |
738 |
if (bytes == 1) \ |
CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \ |
|
{ \ |
|
|
*dst++ = (ch); \ |
|
|
if (extra_bytes && (ch) >= 0x80 && (ch) < 0xA0) \ |
|
|
/* We may have to convert this eight-bit char to \ |
|
|
multibyte form later. */ \ |
|
|
extra_bytes++; \ |
|
|
} \ |
|
|
else if (CHAR_VALID_P (ch, 0)) \ |
|
|
dst += CHAR_STRING (ch, dst); \ |
|
|
else \ |
|
|
CCL_INVALID_CMD; \ |
|
|
} \ |
|
|
else \ |
|
|
CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \ |
|
|
} while (0) |
|
|
|
|
|
/* Encode one character CH to multibyte form and write to the current |
|
|
output buffer. The output bytes always forms a valid multibyte |
|
|
sequence. */ |
|
|
#define CCL_WRITE_MULTIBYTE_CHAR(ch) \ |
|
|
do { \ |
|
|
int bytes = CHAR_BYTES (ch); \ |
|
|
if (!dst) \ |
|
|
CCL_INVALID_CMD; \ |
|
|
else if (dst + bytes + extra_bytes < (dst_bytes ? dst_end : src)) \ |
|
|
{ \ |
|
|
if (CHAR_VALID_P ((ch), 0)) \ |
|
|
dst += CHAR_STRING ((ch), dst); \ |
|
|
else \ |
|
|
CCL_INVALID_CMD; \ |
|
|
} \ |
|
|
else \ |
|
|
CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \ |
|
739 |
} while (0) |
} while (0) |
740 |
|
|
741 |
/* Write a string at ccl_prog[IC] of length LEN to the current output |
/* Write a string at ccl_prog[IC] of length LEN to the current output |
742 |
buffer. */ |
buffer. */ |
743 |
#define CCL_WRITE_STRING(len) \ |
#define CCL_WRITE_STRING(len) \ |
744 |
do { \ |
do { \ |
745 |
|
int i; \ |
746 |
if (!dst) \ |
if (!dst) \ |
747 |
CCL_INVALID_CMD; \ |
CCL_INVALID_CMD; \ |
748 |
else if (dst + len <= (dst_bytes ? dst_end : src)) \ |
else if (dst + len <= dst_end) \ |
749 |
for (i = 0; i < len; i++) \ |
for (i = 0; i < len; i++) \ |
750 |
*dst++ = ((XFASTINT (ccl_prog[ic + (i / 3)])) \ |
*dst++ = ((XFASTINT (ccl_prog[ic + (i / 3)])) \ |
751 |
>> ((2 - (i % 3)) * 8)) & 0xFF; \ |
>> ((2 - (i % 3)) * 8)) & 0xFF; \ |
753 |
CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \ |
CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \ |
754 |
} while (0) |
} while (0) |
755 |
|
|
756 |
/* Read one byte from the current input buffer into REGth register. */ |
/* Read one byte from the current input buffer into Rth register. */ |
757 |
#define CCL_READ_CHAR(REG) \ |
#define CCL_READ_CHAR(r) \ |
758 |
do { \ |
do { \ |
759 |
if (!src) \ |
if (! src) \ |
760 |
CCL_INVALID_CMD; \ |
CCL_INVALID_CMD; \ |
761 |
else if (src < src_end) \ |
else if (src < src_end) \ |
762 |
{ \ |
r = *src++; \ |
763 |
REG = *src++; \ |
else if (ccl->last_block) \ |
764 |
if (REG == '\n' \ |
{ \ |
765 |
&& ccl->eol_type != CODING_EOL_LF) \ |
ic = ccl->eof_ic; \ |
766 |
{ \ |
goto ccl_repeat; \ |
767 |
/* We are encoding. */ \ |
} \ |
768 |
if (ccl->eol_type == CODING_EOL_CRLF) \ |
else \ |
769 |
{ \ |
CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); \ |
770 |
if (ccl->cr_consumed) \ |
} while (0) |
771 |
ccl->cr_consumed = 0; \ |
|
772 |
else \ |
/* Decode CODE by a charset whose id is ID. If ID is 0, return CODE |
773 |
{ \ |
as is for backward compatibility. Assume that we can use the |
774 |
ccl->cr_consumed = 1; \ |
variable `charset'. */ |
775 |
REG = '\r'; \ |
|
776 |
src--; \ |
#define CCL_DECODE_CHAR(id, code) \ |
777 |
} \ |
((id) == 0 ? (code) \ |
778 |
} \ |
: (charset = CHARSET_FROM_ID ((id)), DECODE_CHAR (charset, (code)))) |
779 |
else \ |
|
780 |
REG = '\r'; \ |
/* Encode character C by some of charsets in CHARSET_LIST. Set ID to |
781 |
} \ |
the id of the used charset, ENCODED to the resulf of encoding. |
782 |
if (REG == LEADING_CODE_8_BIT_CONTROL \ |
Assume that we can use the variable `charset'. */ |
|
&& ccl->multibyte) \ |
|
|
REG = *src++ - 0x20; \ |
|
|
} \ |
|
|
else if (ccl->last_block) \ |
|
|
{ \ |
|
|
ic = ccl->eof_ic; \ |
|
|
goto ccl_repeat; \ |
|
|
} \ |
|
|
else \ |
|
|
CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); \ |
|
|
} while (0) |
|
|
|
|
|
|
|
|
/* Set C to the character code made from CHARSET and CODE. This is |
|
|
like MAKE_CHAR but check the validity of CHARSET and CODE. If they |
|
|
are not valid, set C to (CODE & 0xFF) because that is usually the |
|
|
case that CCL_ReadMultibyteChar2 read an invalid code and it set |
|
|
CODE to that invalid byte. */ |
|
783 |
|
|
784 |
#define CCL_MAKE_CHAR(charset, code, c) \ |
#define CCL_ENCODE_CHAR(c, charset_list, id, encoded) \ |
785 |
do { \ |
do { \ |
786 |
if (charset == CHARSET_ASCII) \ |
unsigned code; \ |
|
c = code & 0xFF; \ |
|
|
else if (CHARSET_DEFINED_P (charset) \ |
|
|
&& (code & 0x7F) >= 32 \ |
|
|
&& (code < 256 || ((code >> 7) & 0x7F) >= 32)) \ |
|
|
{ \ |
|
|
int c1 = code & 0x7F, c2 = 0; \ |
|
787 |
\ |
\ |
788 |
if (code >= 256) \ |
charset = char_charset ((c), (charset_list), &code); \ |
789 |
c2 = c1, c1 = (code >> 7) & 0x7F; \ |
if (! charset && ! NILP (charset_list)) \ |
790 |
c = MAKE_CHAR (charset, c1, c2); \ |
charset = char_charset ((c), Qnil, &code); \ |
791 |
|
if (charset) \ |
792 |
|
{ \ |
793 |
|
(id) = CHARSET_ID (charset); \ |
794 |
|
(encoded) = code; \ |
795 |
} \ |
} \ |
796 |
else \ |
} while (0) |
|
c = code & 0xFF; \ |
|
|
} while (0) |
|
797 |
|
|
798 |
|
/* Execute CCL code on characters at SOURCE (length SRC_SIZE). The |
799 |
/* Execute CCL code on SRC_BYTES length text at SOURCE. The resulting |
resulting text goes to a place pointed by DESTINATION, the length |
800 |
text goes to a place pointed by DESTINATION, the length of which |
of which should not exceed DST_SIZE. As a side effect, how many |
801 |
should not exceed DST_BYTES. The bytes actually processed is |
characters are consumed and produced are recorded in CCL->consumed |
802 |
returned as *CONSUMED. The return value is the length of the |
and CCL->produced, and the contents of CCL registers are updated. |
803 |
resulting text. As a side effect, the contents of CCL registers |
If SOURCE or DESTINATION is NULL, only operations on registers are |
804 |
are updated. If SOURCE or DESTINATION is NULL, only operations on |
permitted. */ |
|
registers are permitted. */ |
|
805 |
|
|
806 |
#ifdef CCL_DEBUG |
#ifdef CCL_DEBUG |
807 |
#define CCL_DEBUG_BACKTRACE_LEN 256 |
#define CCL_DEBUG_BACKTRACE_LEN 256 |
818 |
/* For the moment, we only support depth 256 of stack. */ |
/* For the moment, we only support depth 256 of stack. */ |
819 |
static struct ccl_prog_stack ccl_prog_stack_struct[256]; |
static struct ccl_prog_stack ccl_prog_stack_struct[256]; |
820 |
|
|
821 |
int |
void |
822 |
ccl_driver (ccl, source, destination, src_bytes, dst_bytes, consumed) |
ccl_driver (ccl, source, destination, src_size, dst_size, charset_list) |
823 |
struct ccl_program *ccl; |
struct ccl_program *ccl; |
824 |
unsigned char *source, *destination; |
int *source, *destination; |
825 |
int src_bytes, dst_bytes; |
int src_size, dst_size; |
826 |
int *consumed; |
Lisp_Object charset_list; |
827 |
{ |
{ |
828 |
register int *reg = ccl->reg; |
register int *reg = ccl->reg; |
829 |
register int ic = ccl->ic; |
register int ic = ccl->ic; |
830 |
register int code = 0, field1, field2; |
register int code = 0, field1, field2; |
831 |
register Lisp_Object *ccl_prog = ccl->prog; |
register Lisp_Object *ccl_prog = ccl->prog; |
832 |
unsigned char *src = source, *src_end = src + src_bytes; |
int *src = source, *src_end = src + src_size; |
833 |
unsigned char *dst = destination, *dst_end = dst + dst_bytes; |
int *dst = destination, *dst_end = dst + dst_size; |
834 |
int jump_address; |
int jump_address; |
835 |
int i = 0, j, op; |
int i = 0, j, op; |
836 |
int stack_idx = ccl->stack_idx; |
int stack_idx = ccl->stack_idx; |
837 |
/* Instruction counter of the current CCL code. */ |
/* Instruction counter of the current CCL code. */ |
838 |
int this_ic = 0; |
int this_ic = 0; |
839 |
/* CCL_WRITE_CHAR will produce 8-bit code of range 0x80..0x9F. But, |
struct charset *charset; |
|
each of them will be converted to multibyte form of 2-byte |
|
|
sequence. For that conversion, we remember how many more bytes |
|
|
we must keep in DESTINATION in this variable. */ |
|
|
int extra_bytes = ccl->eight_bit_control; |
|
840 |
|
|
841 |
if (ic >= ccl->eof_ic) |
if (ic >= ccl->eof_ic) |
842 |
ic = CCL_HEADER_MAIN; |
ic = CCL_HEADER_MAIN; |
843 |
|
|
844 |
if (ccl->buf_magnification == 0) /* We can't produce any bytes. */ |
if (ccl->buf_magnification == 0) /* We can't read/produce any bytes. */ |
845 |
dst = NULL; |
dst = NULL; |
846 |
|
|
847 |
/* Set mapping stack pointer. */ |
/* Set mapping stack pointer. */ |
866 |
/* We can't just signal Qquit, instead break the loop as if |
/* We can't just signal Qquit, instead break the loop as if |
867 |
the whole data is processed. Don't reset Vquit_flag, it |
the whole data is processed. Don't reset Vquit_flag, it |
868 |
must be handled later at a safer place. */ |
must be handled later at a safer place. */ |
869 |
if (consumed) |
if (src) |
870 |
src = source + src_bytes; |
src = source + src_size; |
871 |
ccl->status = CCL_STAT_QUIT; |
ccl->status = CCL_STAT_QUIT; |
872 |
break; |
break; |
873 |
} |
} |
1182 |
case CCL_LE: reg[rrr] = i <= j; break; |
case CCL_LE: reg[rrr] = i <= j; break; |
1183 |
case CCL_GE: reg[rrr] = i >= j; break; |
case CCL_GE: reg[rrr] = i >= j; break; |
1184 |
case CCL_NE: reg[rrr] = i != j; break; |
case CCL_NE: reg[rrr] = i != j; break; |
1185 |
case CCL_DECODE_SJIS: DECODE_SJIS (i, j, reg[rrr], reg[7]); break; |
case CCL_DECODE_SJIS: |
1186 |
case CCL_ENCODE_SJIS: ENCODE_SJIS (i, j, reg[rrr], reg[7]); break; |
{ |
1187 |
|
i = (i << 8) | j; |
1188 |
|
SJIS_TO_JIS (i); |
1189 |
|
reg[rrr] = i >> 8; |
1190 |
|
reg[7] = i & 0xFF; |
1191 |
|
break; |
1192 |
|
} |
1193 |
|
case CCL_ENCODE_SJIS: |
1194 |
|
{ |
1195 |
|
i = (i << 8) | j; |
1196 |
|
JIS_TO_SJIS (i); |
1197 |
|
reg[rrr] = i >> 8; |
1198 |
|
reg[7] = i & 0xFF; |
1199 |
|
break; |
1200 |
|
} |
1201 |
default: CCL_INVALID_CMD; |
default: CCL_INVALID_CMD; |
1202 |
} |
} |
1203 |
code &= 0x1F; |
code &= 0x1F; |
1217 |
case CCL_ReadMultibyteChar2: |
case CCL_ReadMultibyteChar2: |
1218 |
if (!src) |
if (!src) |
1219 |
CCL_INVALID_CMD; |
CCL_INVALID_CMD; |
1220 |
|
CCL_READ_CHAR (i); |
1221 |
if (src >= src_end) |
CCL_ENCODE_CHAR (i, charset_list, reg[RRR], reg[rrr]); |
|
{ |
|
|
src++; |
|
|
goto ccl_read_multibyte_character_suspend; |
|
|
} |
|
|
|
|
|
if (!ccl->multibyte) |
|
|
{ |
|
|
int bytes; |
|
|
if (!UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes)) |
|
|
{ |
|
|
reg[RRR] = CHARSET_8_BIT_CONTROL; |
|
|
reg[rrr] = *src++; |
|
|
break; |
|
|
} |
|
|
} |
|
|
i = *src++; |
|
|
if (i == '\n' && ccl->eol_type != CODING_EOL_LF) |
|
|
{ |
|
|
/* We are encoding. */ |
|
|
if (ccl->eol_type == CODING_EOL_CRLF) |
|
|
{ |
|
|
if (ccl->cr_consumed) |
|
|
ccl->cr_consumed = 0; |
|
|
else |
|
|
{ |
|
|
ccl->cr_consumed = 1; |
|
|
i = '\r'; |
|
|
src--; |
|
|
} |
|
|
} |
|
|
else |
|
|
i = '\r'; |
|
|
reg[rrr] = i; |
|
|
reg[RRR] = CHARSET_ASCII; |
|
|
} |
|
|
else if (i < 0x80) |
|
|
{ |
|
|
/* ASCII */ |
|
|
reg[rrr] = i; |
|
|
reg[RRR] = CHARSET_ASCII; |
|
|
} |
|
|
else if (i <= MAX_CHARSET_OFFICIAL_DIMENSION2) |
|
|
{ |
|
|
int dimension = BYTES_BY_CHAR_HEAD (i) - 1; |
|
|
|
|
|
if (dimension == 0) |
|
|
{ |
|
|
/* `i' is a leading code for an undefined charset. */ |
|
|
reg[RRR] = CHARSET_8_BIT_GRAPHIC; |
|
|
reg[rrr] = i; |
|
|
} |
|
|
else if (src + dimension > src_end) |
|
|
goto ccl_read_multibyte_character_suspend; |
|
|
else |
|
|
{ |
|
|
reg[RRR] = i; |
|
|
i = (*src++ & 0x7F); |
|
|
if (dimension == 1) |
|
|
reg[rrr] = i; |
|
|
else |
|
|
reg[rrr] = ((i << 7) | (*src++ & 0x7F)); |
|
|
} |
|
|
} |
|
|
else if ((i == LEADING_CODE_PRIVATE_11) |
|
|
|| (i == LEADING_CODE_PRIVATE_12)) |
|
|
{ |
|
|
if ((src + 1) >= src_end) |
|
|
goto ccl_read_multibyte_character_suspend; |
|
|
reg[RRR] = *src++; |
|
|
reg[rrr] = (*src++ & 0x7F); |
|
|
} |
|
|
else if ((i == LEADING_CODE_PRIVATE_21) |
|
|
|| (i == LEADING_CODE_PRIVATE_22)) |
|
|
{ |
|
|
if ((src + 2) >= src_end) |
|
|
goto ccl_read_multibyte_character_suspend; |
|
|
reg[RRR] = *src++; |
|
|
i = (*src++ & 0x7F); |
|
|
reg[rrr] = ((i << 7) | (*src & 0x7F)); |
|
|
src++; |
|
|
} |
|
|
else if (i == LEADING_CODE_8_BIT_CONTROL) |
|
|
{ |
|
|
if (src >= src_end) |
|
|
goto ccl_read_multibyte_character_suspend; |
|
|
reg[RRR] = CHARSET_8_BIT_CONTROL; |
|
|
reg[rrr] = (*src++ - 0x20); |
|
|
} |
|
|
else if (i >= 0xA0) |
|
|
{ |
|
|
reg[RRR] = CHARSET_8_BIT_GRAPHIC; |
|
|
reg[rrr] = i; |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* INVALID CODE. Return a single byte character. */ |
|
|
reg[RRR] = CHARSET_ASCII; |
|
|
reg[rrr] = i; |
|
|
} |
|
|
break; |
|
|
|
|
|
ccl_read_multibyte_character_suspend: |
|
|
if (src <= src_end && !ccl->multibyte && ccl->last_block) |
|
|
{ |
|
|
reg[RRR] = CHARSET_8_BIT_CONTROL; |
|
|
reg[rrr] = i; |
|
|
break; |
|
|
} |
|
|
src--; |
|
|
if (ccl->last_block) |
|
|
{ |
|
|
ic = ccl->eof_ic; |
|
|
goto ccl_repeat; |
|
|
} |
|
|
else |
|
|
CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); |
|
|
|
|
1222 |
break; |
break; |
1223 |
|
|
1224 |
case CCL_WriteMultibyteChar2: |
case CCL_WriteMultibyteChar2: |
1225 |
i = reg[RRR]; /* charset */ |
if (! dst) |
1226 |
if (i == CHARSET_ASCII |
CCL_INVALID_CMD; |
1227 |
|| i == CHARSET_8_BIT_CONTROL |
i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]); |
1228 |
|| i == CHARSET_8_BIT_GRAPHIC) |
CCL_WRITE_CHAR (i); |
|
i = reg[rrr] & 0xFF; |
|
|
else if (CHARSET_DIMENSION (i) == 1) |
|
|
i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F); |
|
|
else if (i < MIN_CHARSET_PRIVATE_DIMENSION2) |
|
|
i = ((i - 0x8F) << 14) | reg[rrr]; |
|
|
else |
|
|
i = ((i - 0xE0) << 14) | reg[rrr]; |
|
|
|
|
|
CCL_WRITE_MULTIBYTE_CHAR (i); |
|
|
|
|
1229 |
break; |
break; |
1230 |
|
|
1231 |
case CCL_TranslateCharacter: |
case CCL_TranslateCharacter: |
1232 |
CCL_MAKE_CHAR (reg[RRR], reg[rrr], i); |
i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]); |
1233 |
op = translate_char (GET_TRANSLATION_TABLE (reg[Rrr]), |
op = translate_char (GET_TRANSLATION_TABLE (reg[Rrr]), i); |
1234 |
i, -1, 0, 0); |
CCL_ENCODE_CHAR (op, charset_list, reg[RRR], reg[rrr]); |
|
SPLIT_CHAR (op, reg[RRR], i, j); |
|
|
if (j != -1) |
|
|
i = (i << 7) | j; |
|
|
|
|
|
reg[rrr] = i; |
|
1235 |
break; |
break; |
1236 |
|
|
1237 |
case CCL_TranslateCharacterConstTbl: |
case CCL_TranslateCharacterConstTbl: |
1238 |
op = XINT (ccl_prog[ic]); /* table */ |
op = XINT (ccl_prog[ic]); /* table */ |
1239 |
ic++; |
ic++; |
1240 |
CCL_MAKE_CHAR (reg[RRR], reg[rrr], i); |
i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]); |
1241 |
op = translate_char (GET_TRANSLATION_TABLE (op), i, -1, 0, 0); |
op = translate_char (GET_TRANSLATION_TABLE (op), i); |
1242 |
SPLIT_CHAR (op, reg[RRR], i, j); |
CCL_ENCODE_CHAR (op, charset_list, reg[RRR], reg[rrr]); |
|
if (j != -1) |
|
|
i = (i << 7) | j; |
|
|
|
|
|
reg[rrr] = i; |
|
1243 |
break; |
break; |
1244 |
|
|
1245 |
case CCL_LookupIntConstTbl: |
case CCL_LookupIntConstTbl: |
1253 |
{ |
{ |
1254 |
Lisp_Object opl; |
Lisp_Object opl; |
1255 |
opl = HASH_VALUE (h, op); |
opl = HASH_VALUE (h, op); |
1256 |
if (!CHAR_VALID_P (XINT (opl), 0)) |
if (! CHARACTERP (XINT (opl))) |
1257 |
CCL_INVALID_CMD; |
CCL_INVALID_CMD; |
1258 |
SPLIT_CHAR (XINT (opl), reg[RRR], i, j); |
reg[RRR] = charset_unicode; |
1259 |
if (j != -1) |
reg[rrr] = op; |
|
i = (i << 7) | j; |
|
|
reg[rrr] = i; |
|
1260 |
reg[7] = 1; /* r7 true for success */ |
reg[7] = 1; /* r7 true for success */ |
1261 |
} |
} |
1262 |
else |
else |
1267 |
case CCL_LookupCharConstTbl: |
case CCL_LookupCharConstTbl: |
1268 |
op = XINT (ccl_prog[ic]); /* table */ |
op = XINT (ccl_prog[ic]); /* table */ |
1269 |
ic++; |
ic++; |
1270 |
CCL_MAKE_CHAR (reg[RRR], reg[rrr], i); |
i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]); |
1271 |
{ |
{ |
1272 |
struct Lisp_Hash_Table *h = GET_HASH_TABLE (op); |
struct Lisp_Hash_Table *h = GET_HASH_TABLE (op); |
1273 |
|
|
1701 |
} |
} |
1702 |
|
|
1703 |
msglen = strlen (msg); |
msglen = strlen (msg); |
1704 |
if (dst + msglen <= (dst_bytes ? dst_end : src)) |
if (dst + msglen <= dst_end) |
1705 |
{ |
{ |
1706 |
bcopy (msg, dst, msglen); |
for (i = 0; i < msglen; i++) |
1707 |
dst += msglen; |
*dst++ = msg[i]; |
1708 |
} |
} |
1709 |
|
|
1710 |
if (ccl->status == CCL_STAT_INVALID_CMD) |
if (ccl->status == CCL_STAT_INVALID_CMD) |
1730 |
ccl->ic = ic; |
ccl->ic = ic; |
1731 |
ccl->stack_idx = stack_idx; |
ccl->stack_idx = stack_idx; |
1732 |
ccl->prog = ccl_prog; |
ccl->prog = ccl_prog; |
1733 |
ccl->eight_bit_control = (extra_bytes > 1); |
ccl->consumed = src - source; |
1734 |
if (consumed) |
ccl->produced = dst - destination; |
|
*consumed = src - source; |
|
|
return (dst ? dst - destination : 0); |
|
1735 |
} |
} |
1736 |
|
|
1737 |
/* Resolve symbols in the specified CCL code (Lisp vector). This |
/* Resolve symbols in the specified CCL code (Lisp vector). This |
1881 |
ccl->private_state = 0; |
ccl->private_state = 0; |
1882 |
ccl->status = 0; |
ccl->status = 0; |
1883 |
ccl->stack_idx = 0; |
ccl->stack_idx = 0; |
|
ccl->eol_type = CODING_EOL_LF; |
|
1884 |
ccl->suppress_error = 0; |
ccl->suppress_error = 0; |
1885 |
ccl->eight_bit_control = 0; |
ccl->eight_bit_control = 0; |
1886 |
return 0; |
return 0; |
1942 |
? XINT (AREF (reg, i)) |
? XINT (AREF (reg, i)) |
1943 |
: 0); |
: 0); |
1944 |
|
|
1945 |
ccl_driver (&ccl, (unsigned char *)0, (unsigned char *)0, 0, 0, (int *)0); |
ccl_driver (&ccl, NULL, NULL, 0, 0, Qnil); |
1946 |
QUIT; |
QUIT; |
1947 |
if (ccl.status != CCL_STAT_SUCCESS) |
if (ccl.status != CCL_STAT_SUCCESS) |
1948 |
error ("Error in CCL program at %dth code", ccl.ic); |
error ("Error in CCL program at %dth code", ccl.ic); |
1983 |
{ |
{ |
1984 |
Lisp_Object val; |
Lisp_Object val; |
1985 |
struct ccl_program ccl; |
struct ccl_program ccl; |
1986 |
int i, produced; |
int i; |
1987 |
int outbufsize; |
int outbufsize; |
1988 |
char *outbuf; |
unsigned char *outbuf, *outp; |
1989 |
struct gcpro gcpro1, gcpro2; |
int str_chars, str_bytes; |
1990 |
|
#define CCL_EXECUTE_BUF_SIZE 1024 |
1991 |
|
int source[CCL_EXECUTE_BUF_SIZE], destination[CCL_EXECUTE_BUF_SIZE]; |
1992 |
|
int consumed_chars, consumed_bytes, produced_chars; |
1993 |
|
|
1994 |
if (setup_ccl_program (&ccl, ccl_prog) < 0) |
if (setup_ccl_program (&ccl, ccl_prog) < 0) |
1995 |
error ("Invalid CCL program"); |
error ("Invalid CCL program"); |
1999 |
error ("Length of vector STATUS is not 9"); |
error ("Length of vector STATUS is not 9"); |
2000 |
CHECK_STRING (str); |
CHECK_STRING (str); |
2001 |
|
|
2002 |
GCPRO2 (status, str); |
str_chars = SCHARS (str); |
2003 |
|
str_bytes = SBYTES (str); |
2004 |
|
|
2005 |
for (i = 0; i < 8; i++) |
for (i = 0; i < 8; i++) |
2006 |
{ |
{ |
2015 |
if (ccl.ic < i && i < ccl.size) |
if (ccl.ic < i && i < ccl.size) |
2016 |
ccl.ic = i; |
ccl.ic = i; |
2017 |
} |
} |
|
outbufsize = SBYTES (str) * ccl.buf_magnification + 256; |
|
|
outbuf = (char *) xmalloc (outbufsize); |
|
|
ccl.last_block = NILP (contin); |
|
|
ccl.multibyte = STRING_MULTIBYTE (str); |
|
|
produced = ccl_driver (&ccl, SDATA (str), outbuf, |
|
|
SBYTES (str), outbufsize, (int *) 0); |
|
|
for (i = 0; i < 8; i++) |
|
|
XSET (AREF (status, i), Lisp_Int, ccl.reg[i]); |
|
|
XSETINT (AREF (status, 8), ccl.ic); |
|
|
UNGCPRO; |
|
2018 |
|
|
2019 |
if (NILP (unibyte_p)) |
outbufsize = (ccl.buf_magnification |
2020 |
|
? str_bytes * ccl.buf_magnification + 256 |
2021 |
|
: str_bytes + 256); |
2022 |
|
outp = outbuf = (unsigned char *) xmalloc (outbufsize); |
2023 |
|
|
2024 |
|
consumed_chars = consumed_bytes = 0; |
2025 |
|
produced_chars = 0; |
2026 |
|
while (consumed_bytes < str_bytes) |
2027 |
{ |
{ |
2028 |
int nchars; |
const unsigned char *p = SDATA (str) + consumed_bytes; |
2029 |
|
const unsigned char *endp = SDATA (str) + str_bytes; |
2030 |
|
int i = 0; |
2031 |
|
int *src, src_size; |
2032 |
|
|
2033 |
|
if (endp - p == str_chars - consumed_chars) |
2034 |
|
while (i < CCL_EXECUTE_BUF_SIZE && p < endp) |
2035 |
|
source[i++] = *p++; |
2036 |
|
else |
2037 |
|
while (i < CCL_EXECUTE_BUF_SIZE && p < endp) |
2038 |
|
source[i++] = STRING_CHAR_ADVANCE (p); |
2039 |
|
consumed_chars += i; |
2040 |
|
consumed_bytes = p - SDATA (str); |
2041 |
|
|
2042 |
|
if (consumed_bytes == str_bytes) |
2043 |
|
ccl.last_block = NILP (contin); |
2044 |
|
src = source; |
2045 |
|
src_size = i; |
2046 |
|
while (1) |
2047 |
|
{ |
2048 |
|
ccl_driver (&ccl, src, destination, src_size, CCL_EXECUTE_BUF_SIZE, |
2049 |
|
Qnil); |
2050 |
|
if (ccl.status != CCL_STAT_SUSPEND_BY_DST) |
2051 |
|
break; |
2052 |
|
produced_chars += ccl.produced; |
2053 |
|
if (NILP (unibyte_p)) |
2054 |
|
{ |
2055 |
|
if (outp - outbuf + MAX_MULTIBYTE_LENGTH * ccl.produced |
2056 |
|
> outbufsize) |
2057 |
|
{ |
2058 |
|
int offset = outp - outbuf; |
2059 |
|
outbufsize += MAX_MULTIBYTE_LENGTH * ccl.produced; |
2060 |
|
outbuf = (unsigned char *) xrealloc (outbuf, outbufsize); |
2061 |
|
outp = outbuf + offset; |
2062 |
|
} |
2063 |
|
for (i = 0; i < ccl.produced; i++) |
2064 |
|
CHAR_STRING_ADVANCE (destination[i], outp); |
2065 |
|
} |
2066 |
|
else |
2067 |
|
{ |
2068 |
|
if (outp - outbuf + ccl.produced > outbufsize) |
2069 |
|
{ |
2070 |
|
int offset = outp - outbuf; |
2071 |
|
outbufsize += ccl.produced; |
2072 |
|
outbuf = (unsigned char *) xrealloc (outbuf, outbufsize); |
2073 |
|
outp = outbuf + offset; |
2074 |
|
} |
2075 |
|
for (i = 0; i < ccl.produced; i++) |
2076 |
|
*outp++ = destination[i]; |
2077 |
|
} |
2078 |
|
src += ccl.consumed; |
2079 |
|
src_size -= ccl.consumed; |
2080 |
|
} |
2081 |
|
|
2082 |
produced = str_as_multibyte (outbuf, outbufsize, produced, &nchars); |
if (ccl.status != CCL_STAT_SUSPEND_BY_SRC) |
2083 |
val = make_multibyte_string (outbuf, nchars, produced); |
break; |
2084 |
} |
} |
2085 |
else |
|
|
val = make_unibyte_string (outbuf, produced); |
|
|
xfree (outbuf); |
|
|
QUIT; |
|
|
if (ccl.status == CCL_STAT_SUSPEND_BY_DST) |
|
|
error ("Output buffer for the CCL programs overflow"); |
|
2086 |
if (ccl.status != CCL_STAT_SUCCESS |
if (ccl.status != CCL_STAT_SUCCESS |
2087 |
&& ccl.status != CCL_STAT_SUSPEND_BY_SRC) |
&& ccl.status != CCL_STAT_SUSPEND_BY_SRC) |
2088 |
error ("Error in CCL program at %dth code", ccl.ic); |
error ("Error in CCL program at %dth code", ccl.ic); |
2089 |
|
|
2090 |
|
for (i = 0; i < 8; i++) |
2091 |
|
XSET (XVECTOR (status)->contents[i], Lisp_Int, ccl.reg[i]); |
2092 |
|
XSETINT (XVECTOR (status)->contents[8], ccl.ic); |
2093 |
|
|
2094 |
|
if (NILP (unibyte_p)) |
2095 |
|
val = make_multibyte_string ((char *) outbuf, produced_chars, |
2096 |
|
outp - outbuf); |
2097 |
|
else |
2098 |
|
val = make_unibyte_string ((char *) outbuf, produced_chars); |
2099 |
|
xfree (outbuf); |
2100 |
|
|
2101 |
return val; |
return val; |
2102 |
} |
} |
2103 |
|
|
2242 |
staticpro (&Vccl_program_table); |
staticpro (&Vccl_program_table); |
2243 |
Vccl_program_table = Fmake_vector (make_number (32), Qnil); |
Vccl_program_table = Fmake_vector (make_number (32), Qnil); |
2244 |
|
|
2245 |
|
Qccl = intern ("ccl"); |
2246 |
|
staticpro (&Qccl); |
2247 |
|
|
2248 |
|
Qcclp = intern ("cclp"); |
2249 |
|
staticpro (&Qcclp); |
2250 |
|
|
2251 |
Qccl_program = intern ("ccl-program"); |
Qccl_program = intern ("ccl-program"); |
2252 |
staticpro (&Qccl_program); |
staticpro (&Qccl_program); |
2253 |
|
|