1 /* CCL (Code Conversion Language) interpreter.
2 Copyright (C) 2001, 2002, 2003, 2004, 2005,
3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
5 2005, 2006, 2007, 2008, 2009, 2010
6 National Institute of Advanced Industrial Science and Technology (AIST)
7 Registration Number H14PRO021
9 National Institute of Advanced Industrial Science and Technology (AIST)
10 Registration Number H13PRO009
12 This file is part of GNU Emacs.
14 GNU Emacs is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
19 GNU Emacs is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
33 #include "character.h"
38 Lisp_Object Qccl
, Qcclp
;
40 /* This contains all code conversion map available to CCL. */
41 Lisp_Object Vcode_conversion_map_vector
;
43 /* Alist of fontname patterns vs corresponding CCL program. */
44 Lisp_Object Vfont_ccl_encoder_alist
;
46 /* This symbol is a property which associates with ccl program vector.
47 Ex: (get 'ccl-big5-encoder 'ccl-program) returns ccl program vector. */
48 Lisp_Object Qccl_program
;
50 /* These symbols are properties which associate with code conversion
51 map and their ID respectively. */
52 Lisp_Object Qcode_conversion_map
;
53 Lisp_Object Qcode_conversion_map_id
;
55 /* Symbols of ccl program have this property, a value of the property
56 is an index for Vccl_protram_table. */
57 Lisp_Object Qccl_program_idx
;
59 /* Table of registered CCL programs. Each element is a vector of
60 NAME, CCL_PROG, RESOLVEDP, and UPDATEDP, where NAME (symbol) is the
61 name of the program, CCL_PROG (vector) is the compiled code of the
62 program, RESOLVEDP (t or nil) is the flag to tell if symbols in
63 CCL_PROG is already resolved to index numbers or not, UPDATEDP (t
64 or nil) is the flat to tell if the CCL program is updated after it
66 Lisp_Object Vccl_program_table
;
68 /* Vector of registered hash tables for translation. */
69 Lisp_Object Vtranslation_hash_table_vector
;
71 /* Return a hash table of id number ID. */
72 #define GET_HASH_TABLE(id) \
73 (XHASH_TABLE (XCDR(XVECTOR(Vtranslation_hash_table_vector)->contents[(id)])))
75 /* CCL (Code Conversion Language) is a simple language which has
76 operations on one input buffer, one output buffer, and 7 registers.
77 The syntax of CCL is described in `ccl.el'. Emacs Lisp function
78 `ccl-compile' compiles a CCL program and produces a CCL code which
79 is a vector of integers. The structure of this vector is as
80 follows: The 1st element: buffer-magnification, a factor for the
81 size of output buffer compared with the size of input buffer. The
82 2nd element: address of CCL code to be executed when encountered
83 with end of input stream. The 3rd and the remaining elements: CCL
86 /* Header of CCL compiled code */
87 #define CCL_HEADER_BUF_MAG 0
88 #define CCL_HEADER_EOF 1
89 #define CCL_HEADER_MAIN 2
91 /* CCL code is a sequence of 28-bit non-negative integers (i.e. the
92 MSB is always 0), each contains CCL command and/or arguments in the
95 |----------------- integer (28-bit) ------------------|
96 |------- 17-bit ------|- 3-bit --|- 3-bit --|- 5-bit -|
97 |--constant argument--|-register-|-register-|-command-|
98 ccccccccccccccccc RRR rrr XXXXX
100 |------- relative address -------|-register-|-command-|
101 cccccccccccccccccccc rrr XXXXX
103 |------------- constant or other args ----------------|
104 cccccccccccccccccccccccccccc
106 where, `cc...c' is a non-negative integer indicating constant value
107 (the left most `c' is always 0) or an absolute jump address, `RRR'
108 and `rrr' are CCL register number, `XXXXX' is one of the following
113 Each comment fields shows one or more lines for command syntax and
114 the following lines for semantics of the command. In semantics, IC
115 stands for Instruction Counter. */
117 #define CCL_SetRegister 0x00 /* Set register a register value:
118 1:00000000000000000RRRrrrXXXXX
119 ------------------------------
123 #define CCL_SetShortConst 0x01 /* Set register a short constant value:
124 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
125 ------------------------------
126 reg[rrr] = CCCCCCCCCCCCCCCCCCC;
129 #define CCL_SetConst 0x02 /* Set register a constant value:
130 1:00000000000000000000rrrXXXXX
132 ------------------------------
137 #define CCL_SetArray 0x03 /* Set register an element of array:
138 1:CCCCCCCCCCCCCCCCCRRRrrrXXXXX
142 ------------------------------
143 if (0 <= reg[RRR] < CC..C)
144 reg[rrr] = ELEMENT[reg[RRR]];
148 #define CCL_Jump 0x04 /* Jump:
149 1:A--D--D--R--E--S--S-000XXXXX
150 ------------------------------
154 /* Note: If CC..C is greater than 0, the second code is omitted. */
156 #define CCL_JumpCond 0x05 /* Jump conditional:
157 1:A--D--D--R--E--S--S-rrrXXXXX
158 ------------------------------
164 #define CCL_WriteRegisterJump 0x06 /* Write register and jump:
165 1:A--D--D--R--E--S--S-rrrXXXXX
166 ------------------------------
171 #define CCL_WriteRegisterReadJump 0x07 /* Write register, read, and jump:
172 1:A--D--D--R--E--S--S-rrrXXXXX
173 2:A--D--D--R--E--S--S-rrrYYYYY
174 -----------------------------
180 /* Note: If read is suspended, the resumed execution starts from the
181 second code (YYYYY == CCL_ReadJump). */
183 #define CCL_WriteConstJump 0x08 /* Write constant and jump:
184 1:A--D--D--R--E--S--S-000XXXXX
186 ------------------------------
191 #define CCL_WriteConstReadJump 0x09 /* Write constant, read, and jump:
192 1:A--D--D--R--E--S--S-rrrXXXXX
194 3:A--D--D--R--E--S--S-rrrYYYYY
195 -----------------------------
201 /* Note: If read is suspended, the resumed execution starts from the
202 second code (YYYYY == CCL_ReadJump). */
204 #define CCL_WriteStringJump 0x0A /* Write string and jump:
205 1:A--D--D--R--E--S--S-000XXXXX
207 3:000MSTRIN[0]STRIN[1]STRIN[2]
209 ------------------------------
211 write_multibyte_string (STRING, LENGTH);
213 write_string (STRING, LENGTH);
217 #define CCL_WriteArrayReadJump 0x0B /* Write an array element, read, and jump:
218 1:A--D--D--R--E--S--S-rrrXXXXX
223 N:A--D--D--R--E--S--S-rrrYYYYY
224 ------------------------------
225 if (0 <= reg[rrr] < LENGTH)
226 write (ELEMENT[reg[rrr]]);
227 IC += LENGTH + 2; (... pointing at N+1)
231 /* Note: If read is suspended, the resumed execution starts from the
232 Nth code (YYYYY == CCL_ReadJump). */
234 #define CCL_ReadJump 0x0C /* Read and jump:
235 1:A--D--D--R--E--S--S-rrrYYYYY
236 -----------------------------
241 #define CCL_Branch 0x0D /* Jump by branch table:
242 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
243 2:A--D--D--R--E-S-S[0]000XXXXX
244 3:A--D--D--R--E-S-S[1]000XXXXX
246 ------------------------------
247 if (0 <= reg[rrr] < CC..C)
248 IC += ADDRESS[reg[rrr]];
250 IC += ADDRESS[CC..C];
253 #define CCL_ReadRegister 0x0E /* Read bytes into registers:
254 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
255 2:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
257 ------------------------------
262 #define CCL_WriteExprConst 0x0F /* write result of expression:
263 1:00000OPERATION000RRR000XXXXX
265 ------------------------------
266 write (reg[RRR] OPERATION CONSTANT);
270 /* Note: If the Nth read is suspended, the resumed execution starts
271 from the Nth code. */
273 #define CCL_ReadBranch 0x10 /* Read one byte into a register,
274 and jump by branch table:
275 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
276 2:A--D--D--R--E-S-S[0]000XXXXX
277 3:A--D--D--R--E-S-S[1]000XXXXX
279 ------------------------------
281 if (0 <= reg[rrr] < CC..C)
282 IC += ADDRESS[reg[rrr]];
284 IC += ADDRESS[CC..C];
287 #define CCL_WriteRegister 0x11 /* Write registers:
288 1:CCCCCCCCCCCCCCCCCCCrrrXXXXX
289 2:CCCCCCCCCCCCCCCCCCCrrrXXXXX
291 ------------------------------
297 /* Note: If the Nth write is suspended, the resumed execution
298 starts from the Nth code. */
300 #define CCL_WriteExprRegister 0x12 /* Write result of expression
301 1:00000OPERATIONRrrRRR000XXXXX
302 ------------------------------
303 write (reg[RRR] OPERATION reg[Rrr]);
306 #define CCL_Call 0x13 /* Call the CCL program whose ID is
308 1:CCCCCCCCCCCCCCCCCCCCFFFXXXXX
309 [2:00000000cccccccccccccccccccc]
310 ------------------------------
318 #define CCL_WriteConstString 0x14 /* Write a constant or a string:
319 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
320 [2:000MSTRIN[0]STRIN[1]STRIN[2]]
322 -----------------------------
327 write_multibyte_string (STRING, CC..C);
329 write_string (STRING, CC..C);
330 IC += (CC..C + 2) / 3;
333 #define CCL_WriteArray 0x15 /* Write an element of array:
334 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
338 ------------------------------
339 if (0 <= reg[rrr] < CC..C)
340 write (ELEMENT[reg[rrr]]);
344 #define CCL_End 0x16 /* Terminate:
345 1:00000000000000000000000XXXXX
346 ------------------------------
350 /* The following two codes execute an assignment arithmetic/logical
351 operation. The form of the operation is like REG OP= OPERAND. */
353 #define CCL_ExprSelfConst 0x17 /* REG OP= constant:
354 1:00000OPERATION000000rrrXXXXX
356 ------------------------------
357 reg[rrr] OPERATION= CONSTANT;
360 #define CCL_ExprSelfReg 0x18 /* REG1 OP= REG2:
361 1:00000OPERATION000RRRrrrXXXXX
362 ------------------------------
363 reg[rrr] OPERATION= reg[RRR];
366 /* The following codes execute an arithmetic/logical operation. The
367 form of the operation is like REG_X = REG_Y OP OPERAND2. */
369 #define CCL_SetExprConst 0x19 /* REG_X = REG_Y OP constant:
370 1:00000OPERATION000RRRrrrXXXXX
372 ------------------------------
373 reg[rrr] = reg[RRR] OPERATION CONSTANT;
377 #define CCL_SetExprReg 0x1A /* REG1 = REG2 OP REG3:
378 1:00000OPERATIONRrrRRRrrrXXXXX
379 ------------------------------
380 reg[rrr] = reg[RRR] OPERATION reg[Rrr];
383 #define CCL_JumpCondExprConst 0x1B /* Jump conditional according to
384 an operation on constant:
385 1:A--D--D--R--E--S--S-rrrXXXXX
388 -----------------------------
389 reg[7] = reg[rrr] OPERATION CONSTANT;
396 #define CCL_JumpCondExprReg 0x1C /* Jump conditional according to
397 an operation on register:
398 1:A--D--D--R--E--S--S-rrrXXXXX
401 -----------------------------
402 reg[7] = reg[rrr] OPERATION reg[RRR];
409 #define CCL_ReadJumpCondExprConst 0x1D /* Read and jump conditional according
410 to an operation on constant:
411 1:A--D--D--R--E--S--S-rrrXXXXX
414 -----------------------------
416 reg[7] = reg[rrr] OPERATION CONSTANT;
423 #define CCL_ReadJumpCondExprReg 0x1E /* Read and jump conditional according
424 to an operation on register:
425 1:A--D--D--R--E--S--S-rrrXXXXX
428 -----------------------------
430 reg[7] = reg[rrr] OPERATION reg[RRR];
437 #define CCL_Extension 0x1F /* Extended CCL code
438 1:ExtendedCOMMNDRrrRRRrrrXXXXX
441 ------------------------------
442 extended_command (rrr,RRR,Rrr,ARGS)
446 Here after, Extended CCL Instructions.
447 Bit length of extended command is 14.
448 Therefore, the instruction code range is 0..16384(0x3fff).
451 /* Read a multibyte characeter.
452 A code point is stored into reg[rrr]. A charset ID is stored into
455 #define CCL_ReadMultibyteChar2 0x00 /* Read Multibyte Character
456 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
458 /* Write a multibyte character.
459 Write a character whose code point is reg[rrr] and the charset ID
462 #define CCL_WriteMultibyteChar2 0x01 /* Write Multibyte Character
463 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
465 /* Translate a character whose code point is reg[rrr] and the charset
466 ID is reg[RRR] by a translation table whose ID is reg[Rrr].
468 A translated character is set in reg[rrr] (code point) and reg[RRR]
471 #define CCL_TranslateCharacter 0x02 /* Translate a multibyte character
472 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
474 /* Translate a character whose code point is reg[rrr] and the charset
475 ID is reg[RRR] by a translation table whose ID is ARGUMENT.
477 A translated character is set in reg[rrr] (code point) and reg[RRR]
480 #define CCL_TranslateCharacterConstTbl 0x03 /* Translate a multibyte character
481 1:ExtendedCOMMNDRrrRRRrrrXXXXX
482 2:ARGUMENT(Translation Table ID)
485 /* Iterate looking up MAPs for reg[rrr] starting from the Nth (N =
486 reg[RRR]) MAP until some value is found.
488 Each MAP is a Lisp vector whose element is number, nil, t, or
490 If the element is nil, ignore the map and proceed to the next map.
491 If the element is t or lambda, finish without changing reg[rrr].
492 If the element is a number, set reg[rrr] to the number and finish.
494 Detail of the map structure is descibed in the comment for
495 CCL_MapMultiple below. */
497 #define CCL_IterateMultipleMap 0x10 /* Iterate multiple maps
498 1:ExtendedCOMMNDXXXRRRrrrXXXXX
505 /* Map the code in reg[rrr] by MAPs starting from the Nth (N =
508 MAPs are supplied in the succeeding CCL codes as follows:
510 When CCL program gives this nested structure of map to this command:
513 (MAP-ID121 MAP-ID122 MAP-ID123)
516 (MAP-ID211 (MAP-ID2111) MAP-ID212)
518 the compiled CCL codes has this sequence:
519 CCL_MapMultiple (CCL code of this command)
520 16 (total number of MAPs and SEPARATORs)
538 A value of each SEPARATOR follows this rule:
539 MAP-SET := SEPARATOR [(MAP-ID | MAP-SET)]+
540 SEPARATOR := -(number of MAP-IDs and SEPARATORs in the MAP-SET)
542 (*)....Nest level of MAP-SET must not be over than MAX_MAP_SET_LEVEL.
544 When some map fails to map (i.e. it doesn't have a value for
545 reg[rrr]), the mapping is treated as identity.
547 The mapping is iterated for all maps in each map set (set of maps
548 separated by SEPARATOR) except in the case that lambda is
549 encountered. More precisely, the mapping proceeds as below:
551 At first, VAL0 is set to reg[rrr], and it is translated by the
552 first map to VAL1. Then, VAL1 is translated by the next map to
553 VAL2. This mapping is iterated until the last map is used. The
554 result of the mapping is the last value of VAL?. When the mapping
555 process reached to the end of the map set, it moves to the next
556 map set. If the next does not exit, the mapping process terminates,
557 and regard the last value as a result.
559 But, when VALm is mapped to VALn and VALn is not a number, the
560 mapping proceed as below:
562 If VALn is nil, the lastest map is ignored and the mapping of VALm
563 proceed to the next map.
565 In VALn is t, VALm is reverted to reg[rrr] and the mapping of VALm
566 proceed to the next map.
568 If VALn is lambda, move to the next map set like reaching to the
569 end of the current map set.
571 If VALn is a symbol, call the CCL program refered by it.
572 Then, use reg[rrr] as a mapped value except for -1, -2 and -3.
573 Such special values are regarded as nil, t, and lambda respectively.
575 Each map is a Lisp vector of the following format (a) or (b):
576 (a)......[STARTPOINT VAL1 VAL2 ...]
577 (b)......[t VAL STARTPOINT ENDPOINT],
579 STARTPOINT is an offset to be used for indexing a map,
580 ENDPOINT is a maximum index number of a map,
581 VAL and VALn is a number, nil, t, or lambda.
583 Valid index range of a map of type (a) is:
584 STARTPOINT <= index < STARTPOINT + map_size - 1
585 Valid index range of a map of type (b) is:
586 STARTPOINT <= index < ENDPOINT */
588 #define CCL_MapMultiple 0x11 /* Mapping by multiple code conversion maps
589 1:ExtendedCOMMNDXXXRRRrrrXXXXX
601 #define MAX_MAP_SET_LEVEL 30
609 static tr_stack mapping_stack
[MAX_MAP_SET_LEVEL
];
610 static tr_stack
*mapping_stack_pointer
;
612 /* If this variable is non-zero, it indicates the stack_idx
613 of immediately called by CCL_MapMultiple. */
614 static int stack_idx_of_map_multiple
;
616 #define PUSH_MAPPING_STACK(restlen, orig) \
619 mapping_stack_pointer->rest_length = (restlen); \
620 mapping_stack_pointer->orig_val = (orig); \
621 mapping_stack_pointer++; \
625 #define POP_MAPPING_STACK(restlen, orig) \
628 mapping_stack_pointer--; \
629 (restlen) = mapping_stack_pointer->rest_length; \
630 (orig) = mapping_stack_pointer->orig_val; \
634 #define CCL_CALL_FOR_MAP_INSTRUCTION(symbol, ret_ic) \
637 struct ccl_program called_ccl; \
638 if (stack_idx >= 256 \
639 || (setup_ccl_program (&called_ccl, (symbol)) != 0)) \
643 ccl_prog = ccl_prog_stack_struct[0].ccl_prog; \
644 ic = ccl_prog_stack_struct[0].ic; \
645 eof_ic = ccl_prog_stack_struct[0].eof_ic; \
649 ccl_prog_stack_struct[stack_idx].ccl_prog = ccl_prog; \
650 ccl_prog_stack_struct[stack_idx].ic = (ret_ic); \
651 ccl_prog_stack_struct[stack_idx].eof_ic = eof_ic; \
653 ccl_prog = called_ccl.prog; \
654 ic = CCL_HEADER_MAIN; \
655 eof_ic = XFASTINT (ccl_prog[CCL_HEADER_EOF]); \
660 #define CCL_MapSingle 0x12 /* Map by single code conversion map
661 1:ExtendedCOMMNDXXXRRRrrrXXXXX
663 ------------------------------
664 Map reg[rrr] by MAP-ID.
665 If some valid mapping is found,
666 set reg[rrr] to the result,
671 #define CCL_LookupIntConstTbl 0x13 /* Lookup multibyte character by
672 integer key. Afterwards R7 set
673 to 1 if lookup succeeded.
674 1:ExtendedCOMMNDRrrRRRXXXXXXXX
675 2:ARGUMENT(Hash table ID) */
677 #define CCL_LookupCharConstTbl 0x14 /* Lookup integer by multibyte
678 character key. Afterwards R7 set
679 to 1 if lookup succeeded.
680 1:ExtendedCOMMNDRrrRRRrrrXXXXX
681 2:ARGUMENT(Hash table ID) */
683 /* CCL arithmetic/logical operators. */
684 #define CCL_PLUS 0x00 /* X = Y + Z */
685 #define CCL_MINUS 0x01 /* X = Y - Z */
686 #define CCL_MUL 0x02 /* X = Y * Z */
687 #define CCL_DIV 0x03 /* X = Y / Z */
688 #define CCL_MOD 0x04 /* X = Y % Z */
689 #define CCL_AND 0x05 /* X = Y & Z */
690 #define CCL_OR 0x06 /* X = Y | Z */
691 #define CCL_XOR 0x07 /* X = Y ^ Z */
692 #define CCL_LSH 0x08 /* X = Y << Z */
693 #define CCL_RSH 0x09 /* X = Y >> Z */
694 #define CCL_LSH8 0x0A /* X = (Y << 8) | Z */
695 #define CCL_RSH8 0x0B /* X = Y >> 8, r[7] = Y & 0xFF */
696 #define CCL_DIVMOD 0x0C /* X = Y / Z, r[7] = Y % Z */
697 #define CCL_LS 0x10 /* X = (X < Y) */
698 #define CCL_GT 0x11 /* X = (X > Y) */
699 #define CCL_EQ 0x12 /* X = (X == Y) */
700 #define CCL_LE 0x13 /* X = (X <= Y) */
701 #define CCL_GE 0x14 /* X = (X >= Y) */
702 #define CCL_NE 0x15 /* X = (X != Y) */
704 #define CCL_DECODE_SJIS 0x16 /* X = HIGHER_BYTE (DE-SJIS (Y, Z))
705 r[7] = LOWER_BYTE (DE-SJIS (Y, Z)) */
706 #define CCL_ENCODE_SJIS 0x17 /* X = HIGHER_BYTE (SJIS (Y, Z))
707 r[7] = LOWER_BYTE (SJIS (Y, Z) */
709 /* Terminate CCL program successfully. */
710 #define CCL_SUCCESS \
713 ccl->status = CCL_STAT_SUCCESS; \
718 /* Suspend CCL program because of reading from empty input buffer or
719 writing to full output buffer. When this program is resumed, the
720 same I/O command is executed. */
721 #define CCL_SUSPEND(stat) \
725 ccl->status = stat; \
730 /* Terminate CCL program because of invalid command. Should not occur
731 in the normal case. */
734 #define CCL_INVALID_CMD \
737 ccl->status = CCL_STAT_INVALID_CMD; \
738 goto ccl_error_handler; \
744 #define CCL_INVALID_CMD \
747 ccl_debug_hook (this_ic); \
748 ccl->status = CCL_STAT_INVALID_CMD; \
749 goto ccl_error_handler; \
755 /* Encode one character CH to multibyte form and write to the current
756 output buffer. If CH is less than 256, CH is written as is. */
757 #define CCL_WRITE_CHAR(ch) \
761 else if (dst < dst_end) \
764 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
767 /* Write a string at ccl_prog[IC] of length LEN to the current output
769 #define CCL_WRITE_STRING(len) \
774 else if (dst + len <= dst_end) \
776 if (XFASTINT (ccl_prog[ic]) & 0x1000000) \
777 for (i = 0; i < len; i++) \
778 *dst++ = XFASTINT (ccl_prog[ic + i]) & 0xFFFFFF; \
780 for (i = 0; i < len; i++) \
781 *dst++ = ((XFASTINT (ccl_prog[ic + (i / 3)])) \
782 >> ((2 - (i % 3)) * 8)) & 0xFF; \
785 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
788 /* Read one byte from the current input buffer into Rth register. */
789 #define CCL_READ_CHAR(r) \
793 else if (src < src_end) \
795 else if (ccl->last_block) \
802 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); \
805 /* Decode CODE by a charset whose id is ID. If ID is 0, return CODE
806 as is for backward compatibility. Assume that we can use the
807 variable `charset'. */
809 #define CCL_DECODE_CHAR(id, code) \
810 ((id) == 0 ? (code) \
811 : (charset = CHARSET_FROM_ID ((id)), DECODE_CHAR (charset, (code))))
813 /* Encode character C by some of charsets in CHARSET_LIST. Set ID to
814 the id of the used charset, ENCODED to the resulf of encoding.
815 Assume that we can use the variable `charset'. */
817 #define CCL_ENCODE_CHAR(c, charset_list, id, encoded) \
821 charset = char_charset ((c), (charset_list), &code); \
822 if (! charset && ! NILP (charset_list)) \
823 charset = char_charset ((c), Qnil, &code); \
826 (id) = CHARSET_ID (charset); \
831 /* Execute CCL code on characters at SOURCE (length SRC_SIZE). The
832 resulting text goes to a place pointed by DESTINATION, the length
833 of which should not exceed DST_SIZE. As a side effect, how many
834 characters are consumed and produced are recorded in CCL->consumed
835 and CCL->produced, and the contents of CCL registers are updated.
836 If SOURCE or DESTINATION is NULL, only operations on registers are
840 #define CCL_DEBUG_BACKTRACE_LEN 256
841 int ccl_backtrace_table
[CCL_DEBUG_BACKTRACE_LEN
];
842 int ccl_backtrace_idx
;
845 ccl_debug_hook (int ic
)
852 struct ccl_prog_stack
854 Lisp_Object
*ccl_prog
; /* Pointer to an array of CCL code. */
855 int ic
; /* Instruction Counter. */
856 int eof_ic
; /* Instruction Counter to jump on EOF. */
859 /* For the moment, we only support depth 256 of stack. */
860 static struct ccl_prog_stack ccl_prog_stack_struct
[256];
863 ccl_driver (struct ccl_program
*ccl
, int *source
, int *destination
, int src_size
, int dst_size
, Lisp_Object charset_list
)
865 register int *reg
= ccl
->reg
;
866 register int ic
= ccl
->ic
;
867 register int code
= 0, field1
, field2
;
868 register Lisp_Object
*ccl_prog
= ccl
->prog
;
869 int *src
= source
, *src_end
= src
+ src_size
;
870 int *dst
= destination
, *dst_end
= dst
+ dst_size
;
873 int stack_idx
= ccl
->stack_idx
;
874 /* Instruction counter of the current CCL code. */
876 struct charset
*charset
;
877 int eof_ic
= ccl
->eof_ic
;
880 if (ccl
->buf_magnification
== 0) /* We can't read/produce any bytes. */
883 /* Set mapping stack pointer. */
884 mapping_stack_pointer
= mapping_stack
;
887 ccl_backtrace_idx
= 0;
894 ccl_backtrace_table
[ccl_backtrace_idx
++] = ic
;
895 if (ccl_backtrace_idx
>= CCL_DEBUG_BACKTRACE_LEN
)
896 ccl_backtrace_idx
= 0;
897 ccl_backtrace_table
[ccl_backtrace_idx
] = 0;
900 if (!NILP (Vquit_flag
) && NILP (Vinhibit_quit
))
902 /* We can't just signal Qquit, instead break the loop as if
903 the whole data is processed. Don't reset Vquit_flag, it
904 must be handled later at a safer place. */
906 src
= source
+ src_size
;
907 ccl
->status
= CCL_STAT_QUIT
;
912 code
= XINT (ccl_prog
[ic
]); ic
++;
914 field2
= (code
& 0xFF) >> 5;
917 #define RRR (field1 & 7)
918 #define Rrr ((field1 >> 3) & 7)
920 #define EXCMD (field1 >> 6)
924 case CCL_SetRegister
: /* 00000000000000000RRRrrrXXXXX */
928 case CCL_SetShortConst
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
932 case CCL_SetConst
: /* 00000000000000000000rrrXXXXX */
933 reg
[rrr
] = XINT (ccl_prog
[ic
]);
937 case CCL_SetArray
: /* CCCCCCCCCCCCCCCCCCCCRRRrrrXXXXX */
940 if ((unsigned int) i
< j
)
941 reg
[rrr
] = XINT (ccl_prog
[ic
+ i
]);
945 case CCL_Jump
: /* A--D--D--R--E--S--S-000XXXXX */
949 case CCL_JumpCond
: /* A--D--D--R--E--S--S-rrrXXXXX */
954 case CCL_WriteRegisterJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
960 case CCL_WriteRegisterReadJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
964 CCL_READ_CHAR (reg
[rrr
]);
968 case CCL_WriteConstJump
: /* A--D--D--R--E--S--S-000XXXXX */
969 i
= XINT (ccl_prog
[ic
]);
974 case CCL_WriteConstReadJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
975 i
= XINT (ccl_prog
[ic
]);
978 CCL_READ_CHAR (reg
[rrr
]);
982 case CCL_WriteStringJump
: /* A--D--D--R--E--S--S-000XXXXX */
983 j
= XINT (ccl_prog
[ic
]);
985 CCL_WRITE_STRING (j
);
989 case CCL_WriteArrayReadJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
991 j
= XINT (ccl_prog
[ic
]);
992 if ((unsigned int) i
< j
)
994 i
= XINT (ccl_prog
[ic
+ 1 + i
]);
998 CCL_READ_CHAR (reg
[rrr
]);
999 ic
+= ADDR
- (j
+ 2);
1002 case CCL_ReadJump
: /* A--D--D--R--E--S--S-rrrYYYYY */
1003 CCL_READ_CHAR (reg
[rrr
]);
1007 case CCL_ReadBranch
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1008 CCL_READ_CHAR (reg
[rrr
]);
1009 /* fall through ... */
1010 case CCL_Branch
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1011 if ((unsigned int) reg
[rrr
] < field1
)
1012 ic
+= XINT (ccl_prog
[ic
+ reg
[rrr
]]);
1014 ic
+= XINT (ccl_prog
[ic
+ field1
]);
1017 case CCL_ReadRegister
: /* CCCCCCCCCCCCCCCCCCCCrrXXXXX */
1020 CCL_READ_CHAR (reg
[rrr
]);
1022 code
= XINT (ccl_prog
[ic
]); ic
++;
1024 field2
= (code
& 0xFF) >> 5;
1028 case CCL_WriteExprConst
: /* 1:00000OPERATION000RRR000XXXXX */
1031 j
= XINT (ccl_prog
[ic
]);
1033 jump_address
= ic
+ 1;
1036 case CCL_WriteRegister
: /* CCCCCCCCCCCCCCCCCCCrrrXXXXX */
1042 code
= XINT (ccl_prog
[ic
]); ic
++;
1044 field2
= (code
& 0xFF) >> 5;
1048 case CCL_WriteExprRegister
: /* 1:00000OPERATIONRrrRRR000XXXXX */
1056 case CCL_Call
: /* 1:CCCCCCCCCCCCCCCCCCCCFFFXXXXX */
1061 /* If FFF is nonzero, the CCL program ID is in the
1065 prog_id
= XINT (ccl_prog
[ic
]);
1071 if (stack_idx
>= 256
1073 || prog_id
>= ASIZE (Vccl_program_table
)
1074 || (slot
= AREF (Vccl_program_table
, prog_id
), !VECTORP (slot
))
1075 || !VECTORP (AREF (slot
, 1)))
1079 ccl_prog
= ccl_prog_stack_struct
[0].ccl_prog
;
1080 ic
= ccl_prog_stack_struct
[0].ic
;
1081 eof_ic
= ccl_prog_stack_struct
[0].eof_ic
;
1086 ccl_prog_stack_struct
[stack_idx
].ccl_prog
= ccl_prog
;
1087 ccl_prog_stack_struct
[stack_idx
].ic
= ic
;
1088 ccl_prog_stack_struct
[stack_idx
].eof_ic
= eof_ic
;
1090 ccl_prog
= XVECTOR (AREF (slot
, 1))->contents
;
1091 ic
= CCL_HEADER_MAIN
;
1092 eof_ic
= XFASTINT (ccl_prog
[CCL_HEADER_EOF
]);
1096 case CCL_WriteConstString
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1098 CCL_WRITE_CHAR (field1
);
1101 CCL_WRITE_STRING (field1
);
1102 ic
+= (field1
+ 2) / 3;
1106 case CCL_WriteArray
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1108 if ((unsigned int) i
< field1
)
1110 j
= XINT (ccl_prog
[ic
+ i
]);
1116 case CCL_End
: /* 0000000000000000000000XXXXX */
1120 ccl_prog
= ccl_prog_stack_struct
[stack_idx
].ccl_prog
;
1121 ic
= ccl_prog_stack_struct
[stack_idx
].ic
;
1122 eof_ic
= ccl_prog_stack_struct
[stack_idx
].eof_ic
;
1129 /* ccl->ic should points to this command code again to
1130 suppress further processing. */
1134 case CCL_ExprSelfConst
: /* 00000OPERATION000000rrrXXXXX */
1135 i
= XINT (ccl_prog
[ic
]);
1140 case CCL_ExprSelfReg
: /* 00000OPERATION000RRRrrrXXXXX */
1147 case CCL_PLUS
: reg
[rrr
] += i
; break;
1148 case CCL_MINUS
: reg
[rrr
] -= i
; break;
1149 case CCL_MUL
: reg
[rrr
] *= i
; break;
1150 case CCL_DIV
: reg
[rrr
] /= i
; break;
1151 case CCL_MOD
: reg
[rrr
] %= i
; break;
1152 case CCL_AND
: reg
[rrr
] &= i
; break;
1153 case CCL_OR
: reg
[rrr
] |= i
; break;
1154 case CCL_XOR
: reg
[rrr
] ^= i
; break;
1155 case CCL_LSH
: reg
[rrr
] <<= i
; break;
1156 case CCL_RSH
: reg
[rrr
] >>= i
; break;
1157 case CCL_LSH8
: reg
[rrr
] <<= 8; reg
[rrr
] |= i
; break;
1158 case CCL_RSH8
: reg
[7] = reg
[rrr
] & 0xFF; reg
[rrr
] >>= 8; break;
1159 case CCL_DIVMOD
: reg
[7] = reg
[rrr
] % i
; reg
[rrr
] /= i
; break;
1160 case CCL_LS
: reg
[rrr
] = reg
[rrr
] < i
; break;
1161 case CCL_GT
: reg
[rrr
] = reg
[rrr
] > i
; break;
1162 case CCL_EQ
: reg
[rrr
] = reg
[rrr
] == i
; break;
1163 case CCL_LE
: reg
[rrr
] = reg
[rrr
] <= i
; break;
1164 case CCL_GE
: reg
[rrr
] = reg
[rrr
] >= i
; break;
1165 case CCL_NE
: reg
[rrr
] = reg
[rrr
] != i
; break;
1166 default: CCL_INVALID_CMD
;
1170 case CCL_SetExprConst
: /* 00000OPERATION000RRRrrrXXXXX */
1172 j
= XINT (ccl_prog
[ic
]);
1174 jump_address
= ++ic
;
1177 case CCL_SetExprReg
: /* 00000OPERATIONRrrRRRrrrXXXXX */
1184 case CCL_ReadJumpCondExprConst
: /* A--D--D--R--E--S--S-rrrXXXXX */
1185 CCL_READ_CHAR (reg
[rrr
]);
1186 case CCL_JumpCondExprConst
: /* A--D--D--R--E--S--S-rrrXXXXX */
1188 op
= XINT (ccl_prog
[ic
]);
1189 jump_address
= ic
++ + ADDR
;
1190 j
= XINT (ccl_prog
[ic
]);
1195 case CCL_ReadJumpCondExprReg
: /* A--D--D--R--E--S--S-rrrXXXXX */
1196 CCL_READ_CHAR (reg
[rrr
]);
1197 case CCL_JumpCondExprReg
:
1199 op
= XINT (ccl_prog
[ic
]);
1200 jump_address
= ic
++ + ADDR
;
1201 j
= reg
[XINT (ccl_prog
[ic
])];
1208 case CCL_PLUS
: reg
[rrr
] = i
+ j
; break;
1209 case CCL_MINUS
: reg
[rrr
] = i
- j
; break;
1210 case CCL_MUL
: reg
[rrr
] = i
* j
; break;
1211 case CCL_DIV
: reg
[rrr
] = i
/ j
; break;
1212 case CCL_MOD
: reg
[rrr
] = i
% j
; break;
1213 case CCL_AND
: reg
[rrr
] = i
& j
; break;
1214 case CCL_OR
: reg
[rrr
] = i
| j
; break;
1215 case CCL_XOR
: reg
[rrr
] = i
^ j
; break;
1216 case CCL_LSH
: reg
[rrr
] = i
<< j
; break;
1217 case CCL_RSH
: reg
[rrr
] = i
>> j
; break;
1218 case CCL_LSH8
: reg
[rrr
] = (i
<< 8) | j
; break;
1219 case CCL_RSH8
: reg
[rrr
] = i
>> 8; reg
[7] = i
& 0xFF; break;
1220 case CCL_DIVMOD
: reg
[rrr
] = i
/ j
; reg
[7] = i
% j
; break;
1221 case CCL_LS
: reg
[rrr
] = i
< j
; break;
1222 case CCL_GT
: reg
[rrr
] = i
> j
; break;
1223 case CCL_EQ
: reg
[rrr
] = i
== j
; break;
1224 case CCL_LE
: reg
[rrr
] = i
<= j
; break;
1225 case CCL_GE
: reg
[rrr
] = i
>= j
; break;
1226 case CCL_NE
: reg
[rrr
] = i
!= j
; break;
1227 case CCL_DECODE_SJIS
:
1235 case CCL_ENCODE_SJIS
:
1243 default: CCL_INVALID_CMD
;
1246 if (code
== CCL_WriteExprConst
|| code
== CCL_WriteExprRegister
)
1259 case CCL_ReadMultibyteChar2
:
1263 CCL_ENCODE_CHAR (i
, charset_list
, reg
[RRR
], reg
[rrr
]);
1266 case CCL_WriteMultibyteChar2
:
1269 i
= CCL_DECODE_CHAR (reg
[RRR
], reg
[rrr
]);
1273 case CCL_TranslateCharacter
:
1274 i
= CCL_DECODE_CHAR (reg
[RRR
], reg
[rrr
]);
1275 op
= translate_char (GET_TRANSLATION_TABLE (reg
[Rrr
]), i
);
1276 CCL_ENCODE_CHAR (op
, charset_list
, reg
[RRR
], reg
[rrr
]);
1279 case CCL_TranslateCharacterConstTbl
:
1280 op
= XINT (ccl_prog
[ic
]); /* table */
1282 i
= CCL_DECODE_CHAR (reg
[RRR
], reg
[rrr
]);
1283 op
= translate_char (GET_TRANSLATION_TABLE (op
), i
);
1284 CCL_ENCODE_CHAR (op
, charset_list
, reg
[RRR
], reg
[rrr
]);
1287 case CCL_LookupIntConstTbl
:
1288 op
= XINT (ccl_prog
[ic
]); /* table */
1291 struct Lisp_Hash_Table
*h
= GET_HASH_TABLE (op
);
1293 op
= hash_lookup (h
, make_number (reg
[RRR
]), NULL
);
1297 opl
= HASH_VALUE (h
, op
);
1298 if (! CHARACTERP (opl
))
1300 reg
[RRR
] = charset_unicode
;
1302 reg
[7] = 1; /* r7 true for success */
1309 case CCL_LookupCharConstTbl
:
1310 op
= XINT (ccl_prog
[ic
]); /* table */
1312 i
= CCL_DECODE_CHAR (reg
[RRR
], reg
[rrr
]);
1314 struct Lisp_Hash_Table
*h
= GET_HASH_TABLE (op
);
1316 op
= hash_lookup (h
, make_number (i
), NULL
);
1320 opl
= HASH_VALUE (h
, op
);
1321 if (!INTEGERP (opl
))
1323 reg
[RRR
] = XINT (opl
);
1324 reg
[7] = 1; /* r7 true for success */
1331 case CCL_IterateMultipleMap
:
1333 Lisp_Object map
, content
, attrib
, value
;
1334 int point
, size
, fin_ic
;
1336 j
= XINT (ccl_prog
[ic
++]); /* number of maps. */
1339 if ((j
> reg
[RRR
]) && (j
>= 0))
1354 size
= ASIZE (Vcode_conversion_map_vector
);
1355 point
= XINT (ccl_prog
[ic
++]);
1356 if (point
>= size
) continue;
1357 map
= AREF (Vcode_conversion_map_vector
, point
);
1359 /* Check map validity. */
1360 if (!CONSP (map
)) continue;
1362 if (!VECTORP (map
)) continue;
1364 if (size
<= 1) continue;
1366 content
= AREF (map
, 0);
1369 [STARTPOINT VAL1 VAL2 ...] or
1370 [t ELEMENT STARTPOINT ENDPOINT] */
1371 if (NUMBERP (content
))
1373 point
= XUINT (content
);
1374 point
= op
- point
+ 1;
1375 if (!((point
>= 1) && (point
< size
))) continue;
1376 content
= AREF (map
, point
);
1378 else if (EQ (content
, Qt
))
1380 if (size
!= 4) continue;
1381 if ((op
>= XUINT (AREF (map
, 2)))
1382 && (op
< XUINT (AREF (map
, 3))))
1383 content
= AREF (map
, 1);
1392 else if (NUMBERP (content
))
1395 reg
[rrr
] = XINT(content
);
1398 else if (EQ (content
, Qt
) || EQ (content
, Qlambda
))
1403 else if (CONSP (content
))
1405 attrib
= XCAR (content
);
1406 value
= XCDR (content
);
1407 if (!NUMBERP (attrib
) || !NUMBERP (value
))
1410 reg
[rrr
] = XUINT (value
);
1413 else if (SYMBOLP (content
))
1414 CCL_CALL_FOR_MAP_INSTRUCTION (content
, fin_ic
);
1424 case CCL_MapMultiple
:
1426 Lisp_Object map
, content
, attrib
, value
;
1427 int point
, size
, map_vector_size
;
1428 int map_set_rest_length
, fin_ic
;
1429 int current_ic
= this_ic
;
1431 /* inhibit recursive call on MapMultiple. */
1432 if (stack_idx_of_map_multiple
> 0)
1434 if (stack_idx_of_map_multiple
<= stack_idx
)
1436 stack_idx_of_map_multiple
= 0;
1437 mapping_stack_pointer
= mapping_stack
;
1442 mapping_stack_pointer
= mapping_stack
;
1443 stack_idx_of_map_multiple
= 0;
1445 map_set_rest_length
=
1446 XINT (ccl_prog
[ic
++]); /* number of maps and separators. */
1447 fin_ic
= ic
+ map_set_rest_length
;
1450 if ((map_set_rest_length
> reg
[RRR
]) && (reg
[RRR
] >= 0))
1454 map_set_rest_length
-= i
;
1460 mapping_stack_pointer
= mapping_stack
;
1464 if (mapping_stack_pointer
<= (mapping_stack
+ 1))
1466 /* Set up initial state. */
1467 mapping_stack_pointer
= mapping_stack
;
1468 PUSH_MAPPING_STACK (0, op
);
1473 /* Recover after calling other ccl program. */
1476 POP_MAPPING_STACK (map_set_rest_length
, orig_op
);
1477 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1481 /* Regard it as Qnil. */
1485 map_set_rest_length
--;
1488 /* Regard it as Qt. */
1492 map_set_rest_length
--;
1495 /* Regard it as Qlambda. */
1497 i
+= map_set_rest_length
;
1498 ic
+= map_set_rest_length
;
1499 map_set_rest_length
= 0;
1502 /* Regard it as normal mapping. */
1503 i
+= map_set_rest_length
;
1504 ic
+= map_set_rest_length
;
1505 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1509 map_vector_size
= ASIZE (Vcode_conversion_map_vector
);
1512 for (;map_set_rest_length
> 0;i
++, ic
++, map_set_rest_length
--)
1514 point
= XINT(ccl_prog
[ic
]);
1517 /* +1 is for including separator. */
1519 if (mapping_stack_pointer
1520 >= &mapping_stack
[MAX_MAP_SET_LEVEL
])
1522 PUSH_MAPPING_STACK (map_set_rest_length
- point
,
1524 map_set_rest_length
= point
;
1529 if (point
>= map_vector_size
) continue;
1530 map
= AREF (Vcode_conversion_map_vector
, point
);
1532 /* Check map validity. */
1533 if (!CONSP (map
)) continue;
1535 if (!VECTORP (map
)) continue;
1537 if (size
<= 1) continue;
1539 content
= AREF (map
, 0);
1542 [STARTPOINT VAL1 VAL2 ...] or
1543 [t ELEMENT STARTPOINT ENDPOINT] */
1544 if (NUMBERP (content
))
1546 point
= XUINT (content
);
1547 point
= op
- point
+ 1;
1548 if (!((point
>= 1) && (point
< size
))) continue;
1549 content
= AREF (map
, point
);
1551 else if (EQ (content
, Qt
))
1553 if (size
!= 4) continue;
1554 if ((op
>= XUINT (AREF (map
, 2))) &&
1555 (op
< XUINT (AREF (map
, 3))))
1556 content
= AREF (map
, 1);
1567 if (NUMBERP (content
))
1569 op
= XINT (content
);
1570 i
+= map_set_rest_length
- 1;
1571 ic
+= map_set_rest_length
- 1;
1572 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1573 map_set_rest_length
++;
1575 else if (CONSP (content
))
1577 attrib
= XCAR (content
);
1578 value
= XCDR (content
);
1579 if (!NUMBERP (attrib
) || !NUMBERP (value
))
1582 i
+= map_set_rest_length
- 1;
1583 ic
+= map_set_rest_length
- 1;
1584 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1585 map_set_rest_length
++;
1587 else if (EQ (content
, Qt
))
1591 else if (EQ (content
, Qlambda
))
1593 i
+= map_set_rest_length
;
1594 ic
+= map_set_rest_length
;
1597 else if (SYMBOLP (content
))
1599 if (mapping_stack_pointer
1600 >= &mapping_stack
[MAX_MAP_SET_LEVEL
])
1602 PUSH_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1603 PUSH_MAPPING_STACK (map_set_rest_length
, op
);
1604 stack_idx_of_map_multiple
= stack_idx
+ 1;
1605 CCL_CALL_FOR_MAP_INSTRUCTION (content
, current_ic
);
1610 if (mapping_stack_pointer
<= (mapping_stack
+ 1))
1612 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1613 i
+= map_set_rest_length
;
1614 ic
+= map_set_rest_length
;
1615 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1625 Lisp_Object map
, attrib
, value
, content
;
1627 j
= XINT (ccl_prog
[ic
++]); /* map_id */
1629 if (j
>= ASIZE (Vcode_conversion_map_vector
))
1634 map
= AREF (Vcode_conversion_map_vector
, j
);
1647 point
= XUINT (AREF (map
, 0));
1648 point
= op
- point
+ 1;
1651 (!((point
>= 1) && (point
< size
))))
1656 content
= AREF (map
, point
);
1659 else if (NUMBERP (content
))
1660 reg
[rrr
] = XINT (content
);
1661 else if (EQ (content
, Qt
));
1662 else if (CONSP (content
))
1664 attrib
= XCAR (content
);
1665 value
= XCDR (content
);
1666 if (!NUMBERP (attrib
) || !NUMBERP (value
))
1668 reg
[rrr
] = XUINT(value
);
1671 else if (SYMBOLP (content
))
1672 CCL_CALL_FOR_MAP_INSTRUCTION (content
, ic
);
1690 /* The suppress_error member is set when e.g. a CCL-based coding
1691 system is used for terminal output. */
1692 if (!ccl
->suppress_error
&& destination
)
1694 /* We can insert an error message only if DESTINATION is
1695 specified and we still have a room to store the message
1703 switch (ccl
->status
)
1705 case CCL_STAT_INVALID_CMD
:
1706 sprintf(msg
, "\nCCL: Invalid command %x (ccl_code = %x) at %d.",
1707 code
& 0x1F, code
, this_ic
);
1710 int i
= ccl_backtrace_idx
- 1;
1713 msglen
= strlen (msg
);
1714 if (dst
+ msglen
<= (dst_bytes
? dst_end
: src
))
1716 memcpy (dst
, msg
, msglen
);
1720 for (j
= 0; j
< CCL_DEBUG_BACKTRACE_LEN
; j
++, i
--)
1722 if (i
< 0) i
= CCL_DEBUG_BACKTRACE_LEN
- 1;
1723 if (ccl_backtrace_table
[i
] == 0)
1725 sprintf(msg
, " %d", ccl_backtrace_table
[i
]);
1726 msglen
= strlen (msg
);
1727 if (dst
+ msglen
> (dst_bytes
? dst_end
: src
))
1729 memcpy (dst
, msg
, msglen
);
1738 if (! ccl
->quit_silently
)
1739 sprintf(msg
, "\nCCL: Quited.");
1743 sprintf(msg
, "\nCCL: Unknown error type (%d)", ccl
->status
);
1746 msglen
= strlen (msg
);
1747 if (dst
+ msglen
<= dst_end
)
1749 for (i
= 0; i
< msglen
; i
++)
1753 if (ccl
->status
== CCL_STAT_INVALID_CMD
)
1755 #if 0 /* If the remaining bytes contain 0x80..0x9F, copying them
1756 results in an invalid multibyte sequence. */
1758 /* Copy the remaining source data. */
1759 int i
= src_end
- src
;
1760 if (dst_bytes
&& (dst_end
- dst
) < i
)
1762 memcpy (dst
, src
, i
);
1766 /* Signal that we've consumed everything. */
1774 ccl
->stack_idx
= stack_idx
;
1775 ccl
->prog
= ccl_prog
;
1776 ccl
->consumed
= src
- source
;
1778 ccl
->produced
= dst
- destination
;
1783 /* Resolve symbols in the specified CCL code (Lisp vector). This
1784 function converts symbols of code conversion maps and character
1785 translation tables embeded in the CCL code into their ID numbers.
1787 The return value is a vector (CCL itself or a new vector in which
1788 all symbols are resolved), Qt if resolving of some symbol failed,
1789 or nil if CCL contains invalid data. */
1792 resolve_symbol_ccl_program (Lisp_Object ccl
)
1794 int i
, veclen
, unresolved
= 0;
1795 Lisp_Object result
, contents
, val
;
1798 veclen
= ASIZE (result
);
1800 for (i
= 0; i
< veclen
; i
++)
1802 contents
= AREF (result
, i
);
1803 if (INTEGERP (contents
))
1805 else if (CONSP (contents
)
1806 && SYMBOLP (XCAR (contents
))
1807 && SYMBOLP (XCDR (contents
)))
1809 /* This is the new style for embedding symbols. The form is
1810 (SYMBOL . PROPERTY). (get SYMBOL PROPERTY) should give
1813 if (EQ (result
, ccl
))
1814 result
= Fcopy_sequence (ccl
);
1816 val
= Fget (XCAR (contents
), XCDR (contents
));
1818 ASET (result
, i
, val
);
1823 else if (SYMBOLP (contents
))
1825 /* This is the old style for embedding symbols. This style
1826 may lead to a bug if, for instance, a translation table
1827 and a code conversion map have the same name. */
1828 if (EQ (result
, ccl
))
1829 result
= Fcopy_sequence (ccl
);
1831 val
= Fget (contents
, Qtranslation_table_id
);
1833 ASET (result
, i
, val
);
1836 val
= Fget (contents
, Qcode_conversion_map_id
);
1838 ASET (result
, i
, val
);
1841 val
= Fget (contents
, Qccl_program_idx
);
1843 ASET (result
, i
, val
);
1853 return (unresolved
? Qt
: result
);
1856 /* Return the compiled code (vector) of CCL program CCL_PROG.
1857 CCL_PROG is a name (symbol) of the program or already compiled
1858 code. If necessary, resolve symbols in the compiled code to index
1859 numbers. If we failed to get the compiled code or to resolve
1860 symbols, return Qnil. */
1863 ccl_get_compiled_code (Lisp_Object ccl_prog
, int *idx
)
1865 Lisp_Object val
, slot
;
1867 if (VECTORP (ccl_prog
))
1869 val
= resolve_symbol_ccl_program (ccl_prog
);
1871 return (VECTORP (val
) ? val
: Qnil
);
1873 if (!SYMBOLP (ccl_prog
))
1876 val
= Fget (ccl_prog
, Qccl_program_idx
);
1878 || XINT (val
) >= ASIZE (Vccl_program_table
))
1880 slot
= AREF (Vccl_program_table
, XINT (val
));
1881 if (! VECTORP (slot
)
1882 || ASIZE (slot
) != 4
1883 || ! VECTORP (AREF (slot
, 1)))
1886 if (NILP (AREF (slot
, 2)))
1888 val
= resolve_symbol_ccl_program (AREF (slot
, 1));
1889 if (! VECTORP (val
))
1891 ASET (slot
, 1, val
);
1894 return AREF (slot
, 1);
1897 /* Setup fields of the structure pointed by CCL appropriately for the
1898 execution of CCL program CCL_PROG. CCL_PROG is the name (symbol)
1899 of the CCL program or the already compiled code (vector).
1900 Return 0 if we succeed this setup, else return -1.
1902 If CCL_PROG is nil, we just reset the structure pointed by CCL. */
1904 setup_ccl_program (struct ccl_program
*ccl
, Lisp_Object ccl_prog
)
1908 if (! NILP (ccl_prog
))
1910 struct Lisp_Vector
*vp
;
1912 ccl_prog
= ccl_get_compiled_code (ccl_prog
, &ccl
->idx
);
1913 if (! VECTORP (ccl_prog
))
1915 vp
= XVECTOR (ccl_prog
);
1916 ccl
->size
= vp
->size
;
1917 ccl
->prog
= vp
->contents
;
1918 ccl
->eof_ic
= XINT (vp
->contents
[CCL_HEADER_EOF
]);
1919 ccl
->buf_magnification
= XINT (vp
->contents
[CCL_HEADER_BUF_MAG
]);
1924 slot
= AREF (Vccl_program_table
, ccl
->idx
);
1925 ASET (slot
, 3, Qnil
);
1928 ccl
->ic
= CCL_HEADER_MAIN
;
1929 for (i
= 0; i
< 8; i
++)
1931 ccl
->last_block
= 0;
1932 ccl
->private_state
= 0;
1935 ccl
->suppress_error
= 0;
1936 ccl
->eight_bit_control
= 0;
1937 ccl
->quit_silently
= 0;
1942 /* Check if CCL is updated or not. If not, re-setup members of CCL. */
1945 check_ccl_update (struct ccl_program
*ccl
)
1947 Lisp_Object slot
, ccl_prog
;
1951 slot
= AREF (Vccl_program_table
, ccl
->idx
);
1952 if (NILP (AREF (slot
, 3)))
1954 ccl_prog
= ccl_get_compiled_code (AREF (slot
, 0), &ccl
->idx
);
1955 if (! VECTORP (ccl_prog
))
1957 ccl
->size
= ASIZE (ccl_prog
);
1958 ccl
->prog
= XVECTOR (ccl_prog
)->contents
;
1959 ccl
->eof_ic
= XINT (AREF (ccl_prog
, CCL_HEADER_EOF
));
1960 ccl
->buf_magnification
= XINT (AREF (ccl_prog
, CCL_HEADER_BUF_MAG
));
1961 ASET (slot
, 3, Qnil
);
1966 DEFUN ("ccl-program-p", Fccl_program_p
, Sccl_program_p
, 1, 1, 0,
1967 doc
: /* Return t if OBJECT is a CCL program name or a compiled CCL program code.
1968 See the documentation of `define-ccl-program' for the detail of CCL program. */)
1969 (Lisp_Object object
)
1973 if (VECTORP (object
))
1975 val
= resolve_symbol_ccl_program (object
);
1976 return (VECTORP (val
) ? Qt
: Qnil
);
1978 if (!SYMBOLP (object
))
1981 val
= Fget (object
, Qccl_program_idx
);
1982 return ((! NATNUMP (val
)
1983 || XINT (val
) >= ASIZE (Vccl_program_table
))
1987 DEFUN ("ccl-execute", Fccl_execute
, Sccl_execute
, 2, 2, 0,
1988 doc
: /* Execute CCL-PROGRAM with registers initialized by REGISTERS.
1990 CCL-PROGRAM is a CCL program name (symbol)
1991 or compiled code generated by `ccl-compile' (for backward compatibility.
1992 In the latter case, the execution overhead is bigger than in the former).
1993 No I/O commands should appear in CCL-PROGRAM.
1995 REGISTERS is a vector of [R0 R1 ... R7] where RN is an initial value
1996 for the Nth register.
1998 As side effect, each element of REGISTERS holds the value of
1999 the corresponding register after the execution.
2001 See the documentation of `define-ccl-program' for a definition of CCL
2003 (Lisp_Object ccl_prog
, Lisp_Object reg
)
2005 struct ccl_program ccl
;
2008 if (setup_ccl_program (&ccl
, ccl_prog
) < 0)
2009 error ("Invalid CCL program");
2012 if (ASIZE (reg
) != 8)
2013 error ("Length of vector REGISTERS is not 8");
2015 for (i
= 0; i
< 8; i
++)
2016 ccl
.reg
[i
] = (INTEGERP (AREF (reg
, i
))
2017 ? XINT (AREF (reg
, i
))
2020 ccl_driver (&ccl
, NULL
, NULL
, 0, 0, Qnil
);
2022 if (ccl
.status
!= CCL_STAT_SUCCESS
)
2023 error ("Error in CCL program at %dth code", ccl
.ic
);
2025 for (i
= 0; i
< 8; i
++)
2026 ASET (reg
, i
, make_number (ccl
.reg
[i
]));
2030 DEFUN ("ccl-execute-on-string", Fccl_execute_on_string
, Sccl_execute_on_string
,
2032 doc
: /* Execute CCL-PROGRAM with initial STATUS on STRING.
2034 CCL-PROGRAM is a symbol registered by `register-ccl-program',
2035 or a compiled code generated by `ccl-compile' (for backward compatibility,
2036 in this case, the execution is slower).
2038 Read buffer is set to STRING, and write buffer is allocated automatically.
2040 STATUS is a vector of [R0 R1 ... R7 IC], where
2041 R0..R7 are initial values of corresponding registers,
2042 IC is the instruction counter specifying from where to start the program.
2043 If R0..R7 are nil, they are initialized to 0.
2044 If IC is nil, it is initialized to head of the CCL program.
2046 If optional 4th arg CONTINUE is non-nil, keep IC on read operation
2047 when read buffer is exausted, else, IC is always set to the end of
2048 CCL-PROGRAM on exit.
2050 It returns the contents of write buffer as a string,
2051 and as side effect, STATUS is updated.
2052 If the optional 5th arg UNIBYTE-P is non-nil, the returned string
2053 is a unibyte string. By default it is a multibyte string.
2055 See the documentation of `define-ccl-program' for the detail of CCL program.
2056 usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBYTE-P) */)
2057 (Lisp_Object ccl_prog
, Lisp_Object status
, Lisp_Object str
, Lisp_Object contin
, Lisp_Object unibyte_p
)
2060 struct ccl_program ccl
;
2063 unsigned char *outbuf
, *outp
;
2064 EMACS_INT str_chars
, str_bytes
;
2065 #define CCL_EXECUTE_BUF_SIZE 1024
2066 int source
[CCL_EXECUTE_BUF_SIZE
], destination
[CCL_EXECUTE_BUF_SIZE
];
2067 EMACS_INT consumed_chars
, consumed_bytes
, produced_chars
;
2069 if (setup_ccl_program (&ccl
, ccl_prog
) < 0)
2070 error ("Invalid CCL program");
2072 CHECK_VECTOR (status
);
2073 if (ASIZE (status
) != 9)
2074 error ("Length of vector STATUS is not 9");
2077 str_chars
= SCHARS (str
);
2078 str_bytes
= SBYTES (str
);
2080 for (i
= 0; i
< 8; i
++)
2082 if (NILP (AREF (status
, i
)))
2083 ASET (status
, i
, make_number (0));
2084 if (INTEGERP (AREF (status
, i
)))
2085 ccl
.reg
[i
] = XINT (AREF (status
, i
));
2087 if (INTEGERP (AREF (status
, i
)))
2089 i
= XFASTINT (AREF (status
, 8));
2090 if (ccl
.ic
< i
&& i
< ccl
.size
)
2094 outbufsize
= (ccl
.buf_magnification
2095 ? str_bytes
* ccl
.buf_magnification
+ 256
2097 outp
= outbuf
= (unsigned char *) xmalloc (outbufsize
);
2099 consumed_chars
= consumed_bytes
= 0;
2103 const unsigned char *p
= SDATA (str
) + consumed_bytes
;
2104 const unsigned char *endp
= SDATA (str
) + str_bytes
;
2108 if (endp
- p
== str_chars
- consumed_chars
)
2109 while (i
< CCL_EXECUTE_BUF_SIZE
&& p
< endp
)
2112 while (i
< CCL_EXECUTE_BUF_SIZE
&& p
< endp
)
2113 source
[i
++] = STRING_CHAR_ADVANCE (p
);
2114 consumed_chars
+= i
;
2115 consumed_bytes
= p
- SDATA (str
);
2117 if (consumed_bytes
== str_bytes
)
2118 ccl
.last_block
= NILP (contin
);
2123 ccl_driver (&ccl
, src
, destination
, src_size
, CCL_EXECUTE_BUF_SIZE
,
2125 produced_chars
+= ccl
.produced
;
2126 if (NILP (unibyte_p
))
2128 if (outp
- outbuf
+ MAX_MULTIBYTE_LENGTH
* ccl
.produced
2131 EMACS_INT offset
= outp
- outbuf
;
2132 outbufsize
+= MAX_MULTIBYTE_LENGTH
* ccl
.produced
;
2133 outbuf
= (unsigned char *) xrealloc (outbuf
, outbufsize
);
2134 outp
= outbuf
+ offset
;
2136 for (i
= 0; i
< ccl
.produced
; i
++)
2137 CHAR_STRING_ADVANCE (destination
[i
], outp
);
2141 if (outp
- outbuf
+ ccl
.produced
> outbufsize
)
2143 EMACS_INT offset
= outp
- outbuf
;
2144 outbufsize
+= ccl
.produced
;
2145 outbuf
= (unsigned char *) xrealloc (outbuf
, outbufsize
);
2146 outp
= outbuf
+ offset
;
2148 for (i
= 0; i
< ccl
.produced
; i
++)
2149 *outp
++ = destination
[i
];
2151 src
+= ccl
.consumed
;
2152 src_size
-= ccl
.consumed
;
2153 if (ccl
.status
!= CCL_STAT_SUSPEND_BY_DST
)
2157 if (ccl
.status
!= CCL_STAT_SUSPEND_BY_SRC
2158 || str_chars
== consumed_chars
)
2162 if (ccl
.status
== CCL_STAT_INVALID_CMD
)
2163 error ("Error in CCL program at %dth code", ccl
.ic
);
2164 if (ccl
.status
== CCL_STAT_QUIT
)
2165 error ("CCL program interrupted at %dth code", ccl
.ic
);
2167 for (i
= 0; i
< 8; i
++)
2168 ASET (status
, i
, make_number (ccl
.reg
[i
]));
2169 ASET (status
, 8, make_number (ccl
.ic
));
2171 if (NILP (unibyte_p
))
2172 val
= make_multibyte_string ((char *) outbuf
, produced_chars
,
2175 val
= make_unibyte_string ((char *) outbuf
, produced_chars
);
2181 DEFUN ("register-ccl-program", Fregister_ccl_program
, Sregister_ccl_program
,
2183 doc
: /* Register CCL program CCL-PROG as NAME in `ccl-program-table'.
2184 CCL-PROG should be a compiled CCL program (vector), or nil.
2185 If it is nil, just reserve NAME as a CCL program name.
2186 Return index number of the registered CCL program. */)
2187 (Lisp_Object name
, Lisp_Object ccl_prog
)
2189 int len
= ASIZE (Vccl_program_table
);
2191 Lisp_Object resolved
;
2193 CHECK_SYMBOL (name
);
2195 if (!NILP (ccl_prog
))
2197 CHECK_VECTOR (ccl_prog
);
2198 resolved
= resolve_symbol_ccl_program (ccl_prog
);
2199 if (NILP (resolved
))
2200 error ("Error in CCL program");
2201 if (VECTORP (resolved
))
2203 ccl_prog
= resolved
;
2210 for (idx
= 0; idx
< len
; idx
++)
2214 slot
= AREF (Vccl_program_table
, idx
);
2215 if (!VECTORP (slot
))
2216 /* This is the first unused slot. Register NAME here. */
2219 if (EQ (name
, AREF (slot
, 0)))
2221 /* Update this slot. */
2222 ASET (slot
, 1, ccl_prog
);
2223 ASET (slot
, 2, resolved
);
2225 return make_number (idx
);
2230 /* Extend the table. */
2231 Vccl_program_table
= larger_vector (Vccl_program_table
, len
* 2, Qnil
);
2236 elt
= Fmake_vector (make_number (4), Qnil
);
2237 ASET (elt
, 0, name
);
2238 ASET (elt
, 1, ccl_prog
);
2239 ASET (elt
, 2, resolved
);
2241 ASET (Vccl_program_table
, idx
, elt
);
2244 Fput (name
, Qccl_program_idx
, make_number (idx
));
2245 return make_number (idx
);
2248 /* Register code conversion map.
2249 A code conversion map consists of numbers, Qt, Qnil, and Qlambda.
2250 The first element is the start code point.
2251 The other elements are mapped numbers.
2252 Symbol t means to map to an original number before mapping.
2253 Symbol nil means that the corresponding element is empty.
2254 Symbol lambda means to terminate mapping here.
2257 DEFUN ("register-code-conversion-map", Fregister_code_conversion_map
,
2258 Sregister_code_conversion_map
,
2260 doc
: /* Register SYMBOL as code conversion map MAP.
2261 Return index number of the registered map. */)
2262 (Lisp_Object symbol
, Lisp_Object map
)
2264 int len
= ASIZE (Vcode_conversion_map_vector
);
2268 CHECK_SYMBOL (symbol
);
2271 for (i
= 0; i
< len
; i
++)
2273 Lisp_Object slot
= AREF (Vcode_conversion_map_vector
, i
);
2278 if (EQ (symbol
, XCAR (slot
)))
2280 index
= make_number (i
);
2281 XSETCDR (slot
, map
);
2282 Fput (symbol
, Qcode_conversion_map
, map
);
2283 Fput (symbol
, Qcode_conversion_map_id
, index
);
2289 Vcode_conversion_map_vector
= larger_vector (Vcode_conversion_map_vector
,
2292 index
= make_number (i
);
2293 Fput (symbol
, Qcode_conversion_map
, map
);
2294 Fput (symbol
, Qcode_conversion_map_id
, index
);
2295 ASET (Vcode_conversion_map_vector
, i
, Fcons (symbol
, map
));
2303 staticpro (&Vccl_program_table
);
2304 Vccl_program_table
= Fmake_vector (make_number (32), Qnil
);
2306 Qccl
= intern_c_string ("ccl");
2309 Qcclp
= intern_c_string ("cclp");
2312 Qccl_program
= intern_c_string ("ccl-program");
2313 staticpro (&Qccl_program
);
2315 Qccl_program_idx
= intern_c_string ("ccl-program-idx");
2316 staticpro (&Qccl_program_idx
);
2318 Qcode_conversion_map
= intern_c_string ("code-conversion-map");
2319 staticpro (&Qcode_conversion_map
);
2321 Qcode_conversion_map_id
= intern_c_string ("code-conversion-map-id");
2322 staticpro (&Qcode_conversion_map_id
);
2324 DEFVAR_LISP ("code-conversion-map-vector", &Vcode_conversion_map_vector
,
2325 doc
: /* Vector of code conversion maps. */);
2326 Vcode_conversion_map_vector
= Fmake_vector (make_number (16), Qnil
);
2328 DEFVAR_LISP ("font-ccl-encoder-alist", &Vfont_ccl_encoder_alist
,
2329 doc
: /* Alist of fontname patterns vs corresponding CCL program.
2330 Each element looks like (REGEXP . CCL-CODE),
2331 where CCL-CODE is a compiled CCL program.
2332 When a font whose name matches REGEXP is used for displaying a character,
2333 CCL-CODE is executed to calculate the code point in the font
2334 from the charset number and position code(s) of the character which are set
2335 in CCL registers R0, R1, and R2 before the execution.
2336 The code point in the font is set in CCL registers R1 and R2
2337 when the execution terminated.
2338 If the font is single-byte font, the register R2 is not used. */);
2339 Vfont_ccl_encoder_alist
= Qnil
;
2341 DEFVAR_LISP ("translation-hash-table-vector", &Vtranslation_hash_table_vector
,
2342 doc
: /* Vector containing all translation hash tables ever defined.
2343 Comprises pairs (SYMBOL . TABLE) where SYMBOL and TABLE were set up by calls
2344 to `define-translation-hash-table'. The vector is indexed by the table id
2346 Vtranslation_hash_table_vector
= Qnil
;
2348 defsubr (&Sccl_program_p
);
2349 defsubr (&Sccl_execute
);
2350 defsubr (&Sccl_execute_on_string
);
2351 defsubr (&Sregister_ccl_program
);
2352 defsubr (&Sregister_code_conversion_map
);
2355 /* arch-tag: bb9a37be-68ce-4576-8d3d-15d750e4a860
2356 (do not change this comment) */