1 /* CCL (Code Conversion Language) interpreter.
2 Copyright (C) 2001-2011 Free Software Foundation, Inc.
3 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 2005, 2006, 2007, 2008, 2009, 2010, 2011
5 National Institute of Advanced Industrial Science and Technology (AIST)
6 Registration Number H14PRO021
8 National Institute of Advanced Industrial Science and Technology (AIST)
9 Registration Number H13PRO009
11 This file is part of GNU Emacs.
13 GNU Emacs is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
18 GNU Emacs is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
32 #include "character.h"
37 Lisp_Object Qccl
, Qcclp
;
39 /* This symbol is a property which associates with ccl program vector.
40 Ex: (get 'ccl-big5-encoder 'ccl-program) returns ccl program vector. */
41 static Lisp_Object Qccl_program
;
43 /* These symbols are properties which associate with code conversion
44 map and their ID respectively. */
45 static Lisp_Object Qcode_conversion_map
;
46 static Lisp_Object Qcode_conversion_map_id
;
48 /* Symbols of ccl program have this property, a value of the property
49 is an index for Vccl_protram_table. */
50 static Lisp_Object Qccl_program_idx
;
52 /* Table of registered CCL programs. Each element is a vector of
53 NAME, CCL_PROG, RESOLVEDP, and UPDATEDP, where NAME (symbol) is the
54 name of the program, CCL_PROG (vector) is the compiled code of the
55 program, RESOLVEDP (t or nil) is the flag to tell if symbols in
56 CCL_PROG is already resolved to index numbers or not, UPDATEDP (t
57 or nil) is the flat to tell if the CCL program is updated after it
59 static Lisp_Object Vccl_program_table
;
61 /* Return a hash table of id number ID. */
62 #define GET_HASH_TABLE(id) \
63 (XHASH_TABLE (XCDR(XVECTOR(Vtranslation_hash_table_vector)->contents[(id)])))
65 /* CCL (Code Conversion Language) is a simple language which has
66 operations on one input buffer, one output buffer, and 7 registers.
67 The syntax of CCL is described in `ccl.el'. Emacs Lisp function
68 `ccl-compile' compiles a CCL program and produces a CCL code which
69 is a vector of integers. The structure of this vector is as
70 follows: The 1st element: buffer-magnification, a factor for the
71 size of output buffer compared with the size of input buffer. The
72 2nd element: address of CCL code to be executed when encountered
73 with end of input stream. The 3rd and the remaining elements: CCL
76 /* Header of CCL compiled code */
77 #define CCL_HEADER_BUF_MAG 0
78 #define CCL_HEADER_EOF 1
79 #define CCL_HEADER_MAIN 2
81 /* CCL code is a sequence of 28-bit non-negative integers (i.e. the
82 MSB is always 0), each contains CCL command and/or arguments in the
85 |----------------- integer (28-bit) ------------------|
86 |------- 17-bit ------|- 3-bit --|- 3-bit --|- 5-bit -|
87 |--constant argument--|-register-|-register-|-command-|
88 ccccccccccccccccc RRR rrr XXXXX
90 |------- relative address -------|-register-|-command-|
91 cccccccccccccccccccc rrr XXXXX
93 |------------- constant or other args ----------------|
94 cccccccccccccccccccccccccccc
96 where, `cc...c' is a non-negative integer indicating constant value
97 (the left most `c' is always 0) or an absolute jump address, `RRR'
98 and `rrr' are CCL register number, `XXXXX' is one of the following
103 Each comment fields shows one or more lines for command syntax and
104 the following lines for semantics of the command. In semantics, IC
105 stands for Instruction Counter. */
107 #define CCL_SetRegister 0x00 /* Set register a register value:
108 1:00000000000000000RRRrrrXXXXX
109 ------------------------------
113 #define CCL_SetShortConst 0x01 /* Set register a short constant value:
114 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
115 ------------------------------
116 reg[rrr] = CCCCCCCCCCCCCCCCCCC;
119 #define CCL_SetConst 0x02 /* Set register a constant value:
120 1:00000000000000000000rrrXXXXX
122 ------------------------------
127 #define CCL_SetArray 0x03 /* Set register an element of array:
128 1:CCCCCCCCCCCCCCCCCRRRrrrXXXXX
132 ------------------------------
133 if (0 <= reg[RRR] < CC..C)
134 reg[rrr] = ELEMENT[reg[RRR]];
138 #define CCL_Jump 0x04 /* Jump:
139 1:A--D--D--R--E--S--S-000XXXXX
140 ------------------------------
144 /* Note: If CC..C is greater than 0, the second code is omitted. */
146 #define CCL_JumpCond 0x05 /* Jump conditional:
147 1:A--D--D--R--E--S--S-rrrXXXXX
148 ------------------------------
154 #define CCL_WriteRegisterJump 0x06 /* Write register and jump:
155 1:A--D--D--R--E--S--S-rrrXXXXX
156 ------------------------------
161 #define CCL_WriteRegisterReadJump 0x07 /* Write register, read, and jump:
162 1:A--D--D--R--E--S--S-rrrXXXXX
163 2:A--D--D--R--E--S--S-rrrYYYYY
164 -----------------------------
170 /* Note: If read is suspended, the resumed execution starts from the
171 second code (YYYYY == CCL_ReadJump). */
173 #define CCL_WriteConstJump 0x08 /* Write constant and jump:
174 1:A--D--D--R--E--S--S-000XXXXX
176 ------------------------------
181 #define CCL_WriteConstReadJump 0x09 /* Write constant, read, and jump:
182 1:A--D--D--R--E--S--S-rrrXXXXX
184 3:A--D--D--R--E--S--S-rrrYYYYY
185 -----------------------------
191 /* Note: If read is suspended, the resumed execution starts from the
192 second code (YYYYY == CCL_ReadJump). */
194 #define CCL_WriteStringJump 0x0A /* Write string and jump:
195 1:A--D--D--R--E--S--S-000XXXXX
197 3:000MSTRIN[0]STRIN[1]STRIN[2]
199 ------------------------------
201 write_multibyte_string (STRING, LENGTH);
203 write_string (STRING, LENGTH);
207 #define CCL_WriteArrayReadJump 0x0B /* Write an array element, read, and jump:
208 1:A--D--D--R--E--S--S-rrrXXXXX
213 N:A--D--D--R--E--S--S-rrrYYYYY
214 ------------------------------
215 if (0 <= reg[rrr] < LENGTH)
216 write (ELEMENT[reg[rrr]]);
217 IC += LENGTH + 2; (... pointing at N+1)
221 /* Note: If read is suspended, the resumed execution starts from the
222 Nth code (YYYYY == CCL_ReadJump). */
224 #define CCL_ReadJump 0x0C /* Read and jump:
225 1:A--D--D--R--E--S--S-rrrYYYYY
226 -----------------------------
231 #define CCL_Branch 0x0D /* Jump by branch table:
232 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
233 2:A--D--D--R--E-S-S[0]000XXXXX
234 3:A--D--D--R--E-S-S[1]000XXXXX
236 ------------------------------
237 if (0 <= reg[rrr] < CC..C)
238 IC += ADDRESS[reg[rrr]];
240 IC += ADDRESS[CC..C];
243 #define CCL_ReadRegister 0x0E /* Read bytes into registers:
244 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
245 2:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
247 ------------------------------
252 #define CCL_WriteExprConst 0x0F /* write result of expression:
253 1:00000OPERATION000RRR000XXXXX
255 ------------------------------
256 write (reg[RRR] OPERATION CONSTANT);
260 /* Note: If the Nth read is suspended, the resumed execution starts
261 from the Nth code. */
263 #define CCL_ReadBranch 0x10 /* Read one byte into a register,
264 and jump by branch table:
265 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
266 2:A--D--D--R--E-S-S[0]000XXXXX
267 3:A--D--D--R--E-S-S[1]000XXXXX
269 ------------------------------
271 if (0 <= reg[rrr] < CC..C)
272 IC += ADDRESS[reg[rrr]];
274 IC += ADDRESS[CC..C];
277 #define CCL_WriteRegister 0x11 /* Write registers:
278 1:CCCCCCCCCCCCCCCCCCCrrrXXXXX
279 2:CCCCCCCCCCCCCCCCCCCrrrXXXXX
281 ------------------------------
287 /* Note: If the Nth write is suspended, the resumed execution
288 starts from the Nth code. */
290 #define CCL_WriteExprRegister 0x12 /* Write result of expression
291 1:00000OPERATIONRrrRRR000XXXXX
292 ------------------------------
293 write (reg[RRR] OPERATION reg[Rrr]);
296 #define CCL_Call 0x13 /* Call the CCL program whose ID is
298 1:CCCCCCCCCCCCCCCCCCCCFFFXXXXX
299 [2:00000000cccccccccccccccccccc]
300 ------------------------------
308 #define CCL_WriteConstString 0x14 /* Write a constant or a string:
309 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
310 [2:000MSTRIN[0]STRIN[1]STRIN[2]]
312 -----------------------------
317 write_multibyte_string (STRING, CC..C);
319 write_string (STRING, CC..C);
320 IC += (CC..C + 2) / 3;
323 #define CCL_WriteArray 0x15 /* Write an element of array:
324 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
328 ------------------------------
329 if (0 <= reg[rrr] < CC..C)
330 write (ELEMENT[reg[rrr]]);
334 #define CCL_End 0x16 /* Terminate:
335 1:00000000000000000000000XXXXX
336 ------------------------------
340 /* The following two codes execute an assignment arithmetic/logical
341 operation. The form of the operation is like REG OP= OPERAND. */
343 #define CCL_ExprSelfConst 0x17 /* REG OP= constant:
344 1:00000OPERATION000000rrrXXXXX
346 ------------------------------
347 reg[rrr] OPERATION= CONSTANT;
350 #define CCL_ExprSelfReg 0x18 /* REG1 OP= REG2:
351 1:00000OPERATION000RRRrrrXXXXX
352 ------------------------------
353 reg[rrr] OPERATION= reg[RRR];
356 /* The following codes execute an arithmetic/logical operation. The
357 form of the operation is like REG_X = REG_Y OP OPERAND2. */
359 #define CCL_SetExprConst 0x19 /* REG_X = REG_Y OP constant:
360 1:00000OPERATION000RRRrrrXXXXX
362 ------------------------------
363 reg[rrr] = reg[RRR] OPERATION CONSTANT;
367 #define CCL_SetExprReg 0x1A /* REG1 = REG2 OP REG3:
368 1:00000OPERATIONRrrRRRrrrXXXXX
369 ------------------------------
370 reg[rrr] = reg[RRR] OPERATION reg[Rrr];
373 #define CCL_JumpCondExprConst 0x1B /* Jump conditional according to
374 an operation on constant:
375 1:A--D--D--R--E--S--S-rrrXXXXX
378 -----------------------------
379 reg[7] = reg[rrr] OPERATION CONSTANT;
386 #define CCL_JumpCondExprReg 0x1C /* Jump conditional according to
387 an operation on register:
388 1:A--D--D--R--E--S--S-rrrXXXXX
391 -----------------------------
392 reg[7] = reg[rrr] OPERATION reg[RRR];
399 #define CCL_ReadJumpCondExprConst 0x1D /* Read and jump conditional according
400 to an operation on constant:
401 1:A--D--D--R--E--S--S-rrrXXXXX
404 -----------------------------
406 reg[7] = reg[rrr] OPERATION CONSTANT;
413 #define CCL_ReadJumpCondExprReg 0x1E /* Read and jump conditional according
414 to an operation on register:
415 1:A--D--D--R--E--S--S-rrrXXXXX
418 -----------------------------
420 reg[7] = reg[rrr] OPERATION reg[RRR];
427 #define CCL_Extension 0x1F /* Extended CCL code
428 1:ExtendedCOMMNDRrrRRRrrrXXXXX
431 ------------------------------
432 extended_command (rrr,RRR,Rrr,ARGS)
436 Here after, Extended CCL Instructions.
437 Bit length of extended command is 14.
438 Therefore, the instruction code range is 0..16384(0x3fff).
441 /* Read a multibyte character.
442 A code point is stored into reg[rrr]. A charset ID is stored into
445 #define CCL_ReadMultibyteChar2 0x00 /* Read Multibyte Character
446 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
448 /* Write a multibyte character.
449 Write a character whose code point is reg[rrr] and the charset ID
452 #define CCL_WriteMultibyteChar2 0x01 /* Write Multibyte Character
453 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
455 /* Translate a character whose code point is reg[rrr] and the charset
456 ID is reg[RRR] by a translation table whose ID is reg[Rrr].
458 A translated character is set in reg[rrr] (code point) and reg[RRR]
461 #define CCL_TranslateCharacter 0x02 /* Translate a multibyte character
462 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
464 /* Translate a character whose code point is reg[rrr] and the charset
465 ID is reg[RRR] by a translation table whose ID is ARGUMENT.
467 A translated character is set in reg[rrr] (code point) and reg[RRR]
470 #define CCL_TranslateCharacterConstTbl 0x03 /* Translate a multibyte character
471 1:ExtendedCOMMNDRrrRRRrrrXXXXX
472 2:ARGUMENT(Translation Table ID)
475 /* Iterate looking up MAPs for reg[rrr] starting from the Nth (N =
476 reg[RRR]) MAP until some value is found.
478 Each MAP is a Lisp vector whose element is number, nil, t, or
480 If the element is nil, ignore the map and proceed to the next map.
481 If the element is t or lambda, finish without changing reg[rrr].
482 If the element is a number, set reg[rrr] to the number and finish.
484 Detail of the map structure is descibed in the comment for
485 CCL_MapMultiple below. */
487 #define CCL_IterateMultipleMap 0x10 /* Iterate multiple maps
488 1:ExtendedCOMMNDXXXRRRrrrXXXXX
495 /* Map the code in reg[rrr] by MAPs starting from the Nth (N =
498 MAPs are supplied in the succeeding CCL codes as follows:
500 When CCL program gives this nested structure of map to this command:
503 (MAP-ID121 MAP-ID122 MAP-ID123)
506 (MAP-ID211 (MAP-ID2111) MAP-ID212)
508 the compiled CCL codes has this sequence:
509 CCL_MapMultiple (CCL code of this command)
510 16 (total number of MAPs and SEPARATORs)
528 A value of each SEPARATOR follows this rule:
529 MAP-SET := SEPARATOR [(MAP-ID | MAP-SET)]+
530 SEPARATOR := -(number of MAP-IDs and SEPARATORs in the MAP-SET)
532 (*)....Nest level of MAP-SET must not be over than MAX_MAP_SET_LEVEL.
534 When some map fails to map (i.e. it doesn't have a value for
535 reg[rrr]), the mapping is treated as identity.
537 The mapping is iterated for all maps in each map set (set of maps
538 separated by SEPARATOR) except in the case that lambda is
539 encountered. More precisely, the mapping proceeds as below:
541 At first, VAL0 is set to reg[rrr], and it is translated by the
542 first map to VAL1. Then, VAL1 is translated by the next map to
543 VAL2. This mapping is iterated until the last map is used. The
544 result of the mapping is the last value of VAL?. When the mapping
545 process reached to the end of the map set, it moves to the next
546 map set. If the next does not exit, the mapping process terminates,
547 and regard the last value as a result.
549 But, when VALm is mapped to VALn and VALn is not a number, the
550 mapping proceed as below:
552 If VALn is nil, the lastest map is ignored and the mapping of VALm
553 proceed to the next map.
555 In VALn is t, VALm is reverted to reg[rrr] and the mapping of VALm
556 proceed to the next map.
558 If VALn is lambda, move to the next map set like reaching to the
559 end of the current map set.
561 If VALn is a symbol, call the CCL program refered by it.
562 Then, use reg[rrr] as a mapped value except for -1, -2 and -3.
563 Such special values are regarded as nil, t, and lambda respectively.
565 Each map is a Lisp vector of the following format (a) or (b):
566 (a)......[STARTPOINT VAL1 VAL2 ...]
567 (b)......[t VAL STARTPOINT ENDPOINT],
569 STARTPOINT is an offset to be used for indexing a map,
570 ENDPOINT is a maximum index number of a map,
571 VAL and VALn is a number, nil, t, or lambda.
573 Valid index range of a map of type (a) is:
574 STARTPOINT <= index < STARTPOINT + map_size - 1
575 Valid index range of a map of type (b) is:
576 STARTPOINT <= index < ENDPOINT */
578 #define CCL_MapMultiple 0x11 /* Mapping by multiple code conversion maps
579 1:ExtendedCOMMNDXXXRRRrrrXXXXX
591 #define MAX_MAP_SET_LEVEL 30
599 static tr_stack mapping_stack
[MAX_MAP_SET_LEVEL
];
600 static tr_stack
*mapping_stack_pointer
;
602 /* If this variable is non-zero, it indicates the stack_idx
603 of immediately called by CCL_MapMultiple. */
604 static int stack_idx_of_map_multiple
;
606 #define PUSH_MAPPING_STACK(restlen, orig) \
609 mapping_stack_pointer->rest_length = (restlen); \
610 mapping_stack_pointer->orig_val = (orig); \
611 mapping_stack_pointer++; \
615 #define POP_MAPPING_STACK(restlen, orig) \
618 mapping_stack_pointer--; \
619 (restlen) = mapping_stack_pointer->rest_length; \
620 (orig) = mapping_stack_pointer->orig_val; \
624 #define CCL_CALL_FOR_MAP_INSTRUCTION(symbol, ret_ic) \
627 struct ccl_program called_ccl; \
628 if (stack_idx >= 256 \
629 || (setup_ccl_program (&called_ccl, (symbol)) != 0)) \
633 ccl_prog = ccl_prog_stack_struct[0].ccl_prog; \
634 ic = ccl_prog_stack_struct[0].ic; \
635 eof_ic = ccl_prog_stack_struct[0].eof_ic; \
639 ccl_prog_stack_struct[stack_idx].ccl_prog = ccl_prog; \
640 ccl_prog_stack_struct[stack_idx].ic = (ret_ic); \
641 ccl_prog_stack_struct[stack_idx].eof_ic = eof_ic; \
643 ccl_prog = called_ccl.prog; \
644 ic = CCL_HEADER_MAIN; \
645 eof_ic = XFASTINT (ccl_prog[CCL_HEADER_EOF]); \
650 #define CCL_MapSingle 0x12 /* Map by single code conversion map
651 1:ExtendedCOMMNDXXXRRRrrrXXXXX
653 ------------------------------
654 Map reg[rrr] by MAP-ID.
655 If some valid mapping is found,
656 set reg[rrr] to the result,
661 #define CCL_LookupIntConstTbl 0x13 /* Lookup multibyte character by
662 integer key. Afterwards R7 set
663 to 1 if lookup succeeded.
664 1:ExtendedCOMMNDRrrRRRXXXXXXXX
665 2:ARGUMENT(Hash table ID) */
667 #define CCL_LookupCharConstTbl 0x14 /* Lookup integer by multibyte
668 character key. Afterwards R7 set
669 to 1 if lookup succeeded.
670 1:ExtendedCOMMNDRrrRRRrrrXXXXX
671 2:ARGUMENT(Hash table ID) */
673 /* CCL arithmetic/logical operators. */
674 #define CCL_PLUS 0x00 /* X = Y + Z */
675 #define CCL_MINUS 0x01 /* X = Y - Z */
676 #define CCL_MUL 0x02 /* X = Y * Z */
677 #define CCL_DIV 0x03 /* X = Y / Z */
678 #define CCL_MOD 0x04 /* X = Y % Z */
679 #define CCL_AND 0x05 /* X = Y & Z */
680 #define CCL_OR 0x06 /* X = Y | Z */
681 #define CCL_XOR 0x07 /* X = Y ^ Z */
682 #define CCL_LSH 0x08 /* X = Y << Z */
683 #define CCL_RSH 0x09 /* X = Y >> Z */
684 #define CCL_LSH8 0x0A /* X = (Y << 8) | Z */
685 #define CCL_RSH8 0x0B /* X = Y >> 8, r[7] = Y & 0xFF */
686 #define CCL_DIVMOD 0x0C /* X = Y / Z, r[7] = Y % Z */
687 #define CCL_LS 0x10 /* X = (X < Y) */
688 #define CCL_GT 0x11 /* X = (X > Y) */
689 #define CCL_EQ 0x12 /* X = (X == Y) */
690 #define CCL_LE 0x13 /* X = (X <= Y) */
691 #define CCL_GE 0x14 /* X = (X >= Y) */
692 #define CCL_NE 0x15 /* X = (X != Y) */
694 #define CCL_DECODE_SJIS 0x16 /* X = HIGHER_BYTE (DE-SJIS (Y, Z))
695 r[7] = LOWER_BYTE (DE-SJIS (Y, Z)) */
696 #define CCL_ENCODE_SJIS 0x17 /* X = HIGHER_BYTE (SJIS (Y, Z))
697 r[7] = LOWER_BYTE (SJIS (Y, Z) */
699 /* Terminate CCL program successfully. */
700 #define CCL_SUCCESS \
703 ccl->status = CCL_STAT_SUCCESS; \
708 /* Suspend CCL program because of reading from empty input buffer or
709 writing to full output buffer. When this program is resumed, the
710 same I/O command is executed. */
711 #define CCL_SUSPEND(stat) \
715 ccl->status = stat; \
720 /* Terminate CCL program because of invalid command. Should not occur
721 in the normal case. */
724 #define CCL_INVALID_CMD \
727 ccl->status = CCL_STAT_INVALID_CMD; \
728 goto ccl_error_handler; \
734 #define CCL_INVALID_CMD \
737 ccl_debug_hook (this_ic); \
738 ccl->status = CCL_STAT_INVALID_CMD; \
739 goto ccl_error_handler; \
745 /* Encode one character CH to multibyte form and write to the current
746 output buffer. If CH is less than 256, CH is written as is. */
747 #define CCL_WRITE_CHAR(ch) \
751 else if (dst < dst_end) \
754 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
757 /* Write a string at ccl_prog[IC] of length LEN to the current output
759 #define CCL_WRITE_STRING(len) \
764 else if (dst + len <= dst_end) \
766 if (XFASTINT (ccl_prog[ic]) & 0x1000000) \
767 for (ccli = 0; ccli < len; ccli++) \
768 *dst++ = XFASTINT (ccl_prog[ic + ccli]) & 0xFFFFFF; \
770 for (ccli = 0; ccli < len; ccli++) \
771 *dst++ = ((XFASTINT (ccl_prog[ic + (ccli / 3)])) \
772 >> ((2 - (ccli % 3)) * 8)) & 0xFF; \
775 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
778 /* Read one byte from the current input buffer into Rth register. */
779 #define CCL_READ_CHAR(r) \
783 else if (src < src_end) \
785 else if (ccl->last_block) \
792 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); \
795 /* Decode CODE by a charset whose id is ID. If ID is 0, return CODE
796 as is for backward compatibility. Assume that we can use the
797 variable `charset'. */
799 #define CCL_DECODE_CHAR(id, code) \
800 ((id) == 0 ? (code) \
801 : (charset = CHARSET_FROM_ID ((id)), DECODE_CHAR (charset, (code))))
803 /* Encode character C by some of charsets in CHARSET_LIST. Set ID to
804 the id of the used charset, ENCODED to the resulf of encoding.
805 Assume that we can use the variable `charset'. */
807 #define CCL_ENCODE_CHAR(c, charset_list, id, encoded) \
811 charset = char_charset ((c), (charset_list), &ncode); \
812 if (! charset && ! NILP (charset_list)) \
813 charset = char_charset ((c), Qnil, &ncode); \
816 (id) = CHARSET_ID (charset); \
821 /* Execute CCL code on characters at SOURCE (length SRC_SIZE). The
822 resulting text goes to a place pointed by DESTINATION, the length
823 of which should not exceed DST_SIZE. As a side effect, how many
824 characters are consumed and produced are recorded in CCL->consumed
825 and CCL->produced, and the contents of CCL registers are updated.
826 If SOURCE or DESTINATION is NULL, only operations on registers are
830 #define CCL_DEBUG_BACKTRACE_LEN 256
831 int ccl_backtrace_table
[CCL_DEBUG_BACKTRACE_LEN
];
832 int ccl_backtrace_idx
;
835 ccl_debug_hook (int ic
)
842 struct ccl_prog_stack
844 Lisp_Object
*ccl_prog
; /* Pointer to an array of CCL code. */
845 int ic
; /* Instruction Counter. */
846 int eof_ic
; /* Instruction Counter to jump on EOF. */
849 /* For the moment, we only support depth 256 of stack. */
850 static struct ccl_prog_stack ccl_prog_stack_struct
[256];
853 ccl_driver (struct ccl_program
*ccl
, int *source
, int *destination
, int src_size
, int dst_size
, Lisp_Object charset_list
)
855 register int *reg
= ccl
->reg
;
856 register int ic
= ccl
->ic
;
857 register int code
= 0, field1
, field2
;
858 register Lisp_Object
*ccl_prog
= ccl
->prog
;
859 int *src
= source
, *src_end
= src
+ src_size
;
860 int *dst
= destination
, *dst_end
= dst
+ dst_size
;
863 int stack_idx
= ccl
->stack_idx
;
864 /* Instruction counter of the current CCL code. */
866 struct charset
*charset
;
867 int eof_ic
= ccl
->eof_ic
;
870 if (ccl
->buf_magnification
== 0) /* We can't read/produce any bytes. */
873 /* Set mapping stack pointer. */
874 mapping_stack_pointer
= mapping_stack
;
877 ccl_backtrace_idx
= 0;
884 ccl_backtrace_table
[ccl_backtrace_idx
++] = ic
;
885 if (ccl_backtrace_idx
>= CCL_DEBUG_BACKTRACE_LEN
)
886 ccl_backtrace_idx
= 0;
887 ccl_backtrace_table
[ccl_backtrace_idx
] = 0;
890 if (!NILP (Vquit_flag
) && NILP (Vinhibit_quit
))
892 /* We can't just signal Qquit, instead break the loop as if
893 the whole data is processed. Don't reset Vquit_flag, it
894 must be handled later at a safer place. */
896 src
= source
+ src_size
;
897 ccl
->status
= CCL_STAT_QUIT
;
902 code
= XINT (ccl_prog
[ic
]); ic
++;
904 field2
= (code
& 0xFF) >> 5;
907 #define RRR (field1 & 7)
908 #define Rrr ((field1 >> 3) & 7)
910 #define EXCMD (field1 >> 6)
914 case CCL_SetRegister
: /* 00000000000000000RRRrrrXXXXX */
918 case CCL_SetShortConst
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
922 case CCL_SetConst
: /* 00000000000000000000rrrXXXXX */
923 reg
[rrr
] = XINT (ccl_prog
[ic
]);
927 case CCL_SetArray
: /* CCCCCCCCCCCCCCCCCCCCRRRrrrXXXXX */
930 if ((unsigned int) i
< j
)
931 reg
[rrr
] = XINT (ccl_prog
[ic
+ i
]);
935 case CCL_Jump
: /* A--D--D--R--E--S--S-000XXXXX */
939 case CCL_JumpCond
: /* A--D--D--R--E--S--S-rrrXXXXX */
944 case CCL_WriteRegisterJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
950 case CCL_WriteRegisterReadJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
954 CCL_READ_CHAR (reg
[rrr
]);
958 case CCL_WriteConstJump
: /* A--D--D--R--E--S--S-000XXXXX */
959 i
= XINT (ccl_prog
[ic
]);
964 case CCL_WriteConstReadJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
965 i
= XINT (ccl_prog
[ic
]);
968 CCL_READ_CHAR (reg
[rrr
]);
972 case CCL_WriteStringJump
: /* A--D--D--R--E--S--S-000XXXXX */
973 j
= XINT (ccl_prog
[ic
]);
975 CCL_WRITE_STRING (j
);
979 case CCL_WriteArrayReadJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
981 j
= XINT (ccl_prog
[ic
]);
982 if ((unsigned int) i
< j
)
984 i
= XINT (ccl_prog
[ic
+ 1 + i
]);
988 CCL_READ_CHAR (reg
[rrr
]);
989 ic
+= ADDR
- (j
+ 2);
992 case CCL_ReadJump
: /* A--D--D--R--E--S--S-rrrYYYYY */
993 CCL_READ_CHAR (reg
[rrr
]);
997 case CCL_ReadBranch
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
998 CCL_READ_CHAR (reg
[rrr
]);
999 /* fall through ... */
1000 case CCL_Branch
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1001 if ((unsigned int) reg
[rrr
] < field1
)
1002 ic
+= XINT (ccl_prog
[ic
+ reg
[rrr
]]);
1004 ic
+= XINT (ccl_prog
[ic
+ field1
]);
1007 case CCL_ReadRegister
: /* CCCCCCCCCCCCCCCCCCCCrrXXXXX */
1010 CCL_READ_CHAR (reg
[rrr
]);
1012 code
= XINT (ccl_prog
[ic
]); ic
++;
1014 field2
= (code
& 0xFF) >> 5;
1018 case CCL_WriteExprConst
: /* 1:00000OPERATION000RRR000XXXXX */
1021 j
= XINT (ccl_prog
[ic
]);
1023 jump_address
= ic
+ 1;
1026 case CCL_WriteRegister
: /* CCCCCCCCCCCCCCCCCCCrrrXXXXX */
1032 code
= XINT (ccl_prog
[ic
]); ic
++;
1034 field2
= (code
& 0xFF) >> 5;
1038 case CCL_WriteExprRegister
: /* 1:00000OPERATIONRrrRRR000XXXXX */
1046 case CCL_Call
: /* 1:CCCCCCCCCCCCCCCCCCCCFFFXXXXX */
1051 /* If FFF is nonzero, the CCL program ID is in the
1055 prog_id
= XINT (ccl_prog
[ic
]);
1061 if (stack_idx
>= 256
1063 || prog_id
>= ASIZE (Vccl_program_table
)
1064 || (slot
= AREF (Vccl_program_table
, prog_id
), !VECTORP (slot
))
1065 || !VECTORP (AREF (slot
, 1)))
1069 ccl_prog
= ccl_prog_stack_struct
[0].ccl_prog
;
1070 ic
= ccl_prog_stack_struct
[0].ic
;
1071 eof_ic
= ccl_prog_stack_struct
[0].eof_ic
;
1076 ccl_prog_stack_struct
[stack_idx
].ccl_prog
= ccl_prog
;
1077 ccl_prog_stack_struct
[stack_idx
].ic
= ic
;
1078 ccl_prog_stack_struct
[stack_idx
].eof_ic
= eof_ic
;
1080 ccl_prog
= XVECTOR (AREF (slot
, 1))->contents
;
1081 ic
= CCL_HEADER_MAIN
;
1082 eof_ic
= XFASTINT (ccl_prog
[CCL_HEADER_EOF
]);
1086 case CCL_WriteConstString
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1088 CCL_WRITE_CHAR (field1
);
1091 CCL_WRITE_STRING (field1
);
1092 ic
+= (field1
+ 2) / 3;
1096 case CCL_WriteArray
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1098 if ((unsigned int) i
< field1
)
1100 j
= XINT (ccl_prog
[ic
+ i
]);
1106 case CCL_End
: /* 0000000000000000000000XXXXX */
1110 ccl_prog
= ccl_prog_stack_struct
[stack_idx
].ccl_prog
;
1111 ic
= ccl_prog_stack_struct
[stack_idx
].ic
;
1112 eof_ic
= ccl_prog_stack_struct
[stack_idx
].eof_ic
;
1119 /* ccl->ic should points to this command code again to
1120 suppress further processing. */
1124 case CCL_ExprSelfConst
: /* 00000OPERATION000000rrrXXXXX */
1125 i
= XINT (ccl_prog
[ic
]);
1130 case CCL_ExprSelfReg
: /* 00000OPERATION000RRRrrrXXXXX */
1137 case CCL_PLUS
: reg
[rrr
] += i
; break;
1138 case CCL_MINUS
: reg
[rrr
] -= i
; break;
1139 case CCL_MUL
: reg
[rrr
] *= i
; break;
1140 case CCL_DIV
: reg
[rrr
] /= i
; break;
1141 case CCL_MOD
: reg
[rrr
] %= i
; break;
1142 case CCL_AND
: reg
[rrr
] &= i
; break;
1143 case CCL_OR
: reg
[rrr
] |= i
; break;
1144 case CCL_XOR
: reg
[rrr
] ^= i
; break;
1145 case CCL_LSH
: reg
[rrr
] <<= i
; break;
1146 case CCL_RSH
: reg
[rrr
] >>= i
; break;
1147 case CCL_LSH8
: reg
[rrr
] <<= 8; reg
[rrr
] |= i
; break;
1148 case CCL_RSH8
: reg
[7] = reg
[rrr
] & 0xFF; reg
[rrr
] >>= 8; break;
1149 case CCL_DIVMOD
: reg
[7] = reg
[rrr
] % i
; reg
[rrr
] /= i
; break;
1150 case CCL_LS
: reg
[rrr
] = reg
[rrr
] < i
; break;
1151 case CCL_GT
: reg
[rrr
] = reg
[rrr
] > i
; break;
1152 case CCL_EQ
: reg
[rrr
] = reg
[rrr
] == i
; break;
1153 case CCL_LE
: reg
[rrr
] = reg
[rrr
] <= i
; break;
1154 case CCL_GE
: reg
[rrr
] = reg
[rrr
] >= i
; break;
1155 case CCL_NE
: reg
[rrr
] = reg
[rrr
] != i
; break;
1156 default: CCL_INVALID_CMD
;
1160 case CCL_SetExprConst
: /* 00000OPERATION000RRRrrrXXXXX */
1162 j
= XINT (ccl_prog
[ic
]);
1164 jump_address
= ++ic
;
1167 case CCL_SetExprReg
: /* 00000OPERATIONRrrRRRrrrXXXXX */
1174 case CCL_ReadJumpCondExprConst
: /* A--D--D--R--E--S--S-rrrXXXXX */
1175 CCL_READ_CHAR (reg
[rrr
]);
1176 case CCL_JumpCondExprConst
: /* A--D--D--R--E--S--S-rrrXXXXX */
1178 op
= XINT (ccl_prog
[ic
]);
1179 jump_address
= ic
++ + ADDR
;
1180 j
= XINT (ccl_prog
[ic
]);
1185 case CCL_ReadJumpCondExprReg
: /* A--D--D--R--E--S--S-rrrXXXXX */
1186 CCL_READ_CHAR (reg
[rrr
]);
1187 case CCL_JumpCondExprReg
:
1189 op
= XINT (ccl_prog
[ic
]);
1190 jump_address
= ic
++ + ADDR
;
1191 j
= reg
[XINT (ccl_prog
[ic
])];
1198 case CCL_PLUS
: reg
[rrr
] = i
+ j
; break;
1199 case CCL_MINUS
: reg
[rrr
] = i
- j
; break;
1200 case CCL_MUL
: reg
[rrr
] = i
* j
; break;
1201 case CCL_DIV
: reg
[rrr
] = i
/ j
; break;
1202 case CCL_MOD
: reg
[rrr
] = i
% j
; break;
1203 case CCL_AND
: reg
[rrr
] = i
& j
; break;
1204 case CCL_OR
: reg
[rrr
] = i
| j
; break;
1205 case CCL_XOR
: reg
[rrr
] = i
^ j
; break;
1206 case CCL_LSH
: reg
[rrr
] = i
<< j
; break;
1207 case CCL_RSH
: reg
[rrr
] = i
>> j
; break;
1208 case CCL_LSH8
: reg
[rrr
] = (i
<< 8) | j
; break;
1209 case CCL_RSH8
: reg
[rrr
] = i
>> 8; reg
[7] = i
& 0xFF; break;
1210 case CCL_DIVMOD
: reg
[rrr
] = i
/ j
; reg
[7] = i
% j
; break;
1211 case CCL_LS
: reg
[rrr
] = i
< j
; break;
1212 case CCL_GT
: reg
[rrr
] = i
> j
; break;
1213 case CCL_EQ
: reg
[rrr
] = i
== j
; break;
1214 case CCL_LE
: reg
[rrr
] = i
<= j
; break;
1215 case CCL_GE
: reg
[rrr
] = i
>= j
; break;
1216 case CCL_NE
: reg
[rrr
] = i
!= j
; break;
1217 case CCL_DECODE_SJIS
:
1225 case CCL_ENCODE_SJIS
:
1233 default: CCL_INVALID_CMD
;
1236 if (code
== CCL_WriteExprConst
|| code
== CCL_WriteExprRegister
)
1249 case CCL_ReadMultibyteChar2
:
1253 CCL_ENCODE_CHAR (i
, charset_list
, reg
[RRR
], reg
[rrr
]);
1256 case CCL_WriteMultibyteChar2
:
1259 i
= CCL_DECODE_CHAR (reg
[RRR
], reg
[rrr
]);
1263 case CCL_TranslateCharacter
:
1264 i
= CCL_DECODE_CHAR (reg
[RRR
], reg
[rrr
]);
1265 op
= translate_char (GET_TRANSLATION_TABLE (reg
[Rrr
]), i
);
1266 CCL_ENCODE_CHAR (op
, charset_list
, reg
[RRR
], reg
[rrr
]);
1269 case CCL_TranslateCharacterConstTbl
:
1270 op
= XINT (ccl_prog
[ic
]); /* table */
1272 i
= CCL_DECODE_CHAR (reg
[RRR
], reg
[rrr
]);
1273 op
= translate_char (GET_TRANSLATION_TABLE (op
), i
);
1274 CCL_ENCODE_CHAR (op
, charset_list
, reg
[RRR
], reg
[rrr
]);
1277 case CCL_LookupIntConstTbl
:
1278 op
= XINT (ccl_prog
[ic
]); /* table */
1281 struct Lisp_Hash_Table
*h
= GET_HASH_TABLE (op
);
1283 op
= hash_lookup (h
, make_number (reg
[RRR
]), NULL
);
1287 opl
= HASH_VALUE (h
, op
);
1288 if (! CHARACTERP (opl
))
1290 reg
[RRR
] = charset_unicode
;
1292 reg
[7] = 1; /* r7 true for success */
1299 case CCL_LookupCharConstTbl
:
1300 op
= XINT (ccl_prog
[ic
]); /* table */
1302 i
= CCL_DECODE_CHAR (reg
[RRR
], reg
[rrr
]);
1304 struct Lisp_Hash_Table
*h
= GET_HASH_TABLE (op
);
1306 op
= hash_lookup (h
, make_number (i
), NULL
);
1310 opl
= HASH_VALUE (h
, op
);
1311 if (!INTEGERP (opl
))
1313 reg
[RRR
] = XINT (opl
);
1314 reg
[7] = 1; /* r7 true for success */
1321 case CCL_IterateMultipleMap
:
1323 Lisp_Object map
, content
, attrib
, value
;
1324 int point
, size
, fin_ic
;
1326 j
= XINT (ccl_prog
[ic
++]); /* number of maps. */
1329 if ((j
> reg
[RRR
]) && (j
>= 0))
1344 size
= ASIZE (Vcode_conversion_map_vector
);
1345 point
= XINT (ccl_prog
[ic
++]);
1346 if (point
>= size
) continue;
1347 map
= AREF (Vcode_conversion_map_vector
, point
);
1349 /* Check map validity. */
1350 if (!CONSP (map
)) continue;
1352 if (!VECTORP (map
)) continue;
1354 if (size
<= 1) continue;
1356 content
= AREF (map
, 0);
1359 [STARTPOINT VAL1 VAL2 ...] or
1360 [t ELEMENT STARTPOINT ENDPOINT] */
1361 if (NUMBERP (content
))
1363 point
= XUINT (content
);
1364 point
= op
- point
+ 1;
1365 if (!((point
>= 1) && (point
< size
))) continue;
1366 content
= AREF (map
, point
);
1368 else if (EQ (content
, Qt
))
1370 if (size
!= 4) continue;
1371 if ((op
>= XUINT (AREF (map
, 2)))
1372 && (op
< XUINT (AREF (map
, 3))))
1373 content
= AREF (map
, 1);
1382 else if (NUMBERP (content
))
1385 reg
[rrr
] = XINT(content
);
1388 else if (EQ (content
, Qt
) || EQ (content
, Qlambda
))
1393 else if (CONSP (content
))
1395 attrib
= XCAR (content
);
1396 value
= XCDR (content
);
1397 if (!NUMBERP (attrib
) || !NUMBERP (value
))
1400 reg
[rrr
] = XUINT (value
);
1403 else if (SYMBOLP (content
))
1404 CCL_CALL_FOR_MAP_INSTRUCTION (content
, fin_ic
);
1414 case CCL_MapMultiple
:
1416 Lisp_Object map
, content
, attrib
, value
;
1417 int point
, size
, map_vector_size
;
1418 int map_set_rest_length
, fin_ic
;
1419 int current_ic
= this_ic
;
1421 /* inhibit recursive call on MapMultiple. */
1422 if (stack_idx_of_map_multiple
> 0)
1424 if (stack_idx_of_map_multiple
<= stack_idx
)
1426 stack_idx_of_map_multiple
= 0;
1427 mapping_stack_pointer
= mapping_stack
;
1432 mapping_stack_pointer
= mapping_stack
;
1433 stack_idx_of_map_multiple
= 0;
1435 map_set_rest_length
=
1436 XINT (ccl_prog
[ic
++]); /* number of maps and separators. */
1437 fin_ic
= ic
+ map_set_rest_length
;
1440 if ((map_set_rest_length
> reg
[RRR
]) && (reg
[RRR
] >= 0))
1444 map_set_rest_length
-= i
;
1450 mapping_stack_pointer
= mapping_stack
;
1454 if (mapping_stack_pointer
<= (mapping_stack
+ 1))
1456 /* Set up initial state. */
1457 mapping_stack_pointer
= mapping_stack
;
1458 PUSH_MAPPING_STACK (0, op
);
1463 /* Recover after calling other ccl program. */
1466 POP_MAPPING_STACK (map_set_rest_length
, orig_op
);
1467 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1471 /* Regard it as Qnil. */
1475 map_set_rest_length
--;
1478 /* Regard it as Qt. */
1482 map_set_rest_length
--;
1485 /* Regard it as Qlambda. */
1487 i
+= map_set_rest_length
;
1488 ic
+= map_set_rest_length
;
1489 map_set_rest_length
= 0;
1492 /* Regard it as normal mapping. */
1493 i
+= map_set_rest_length
;
1494 ic
+= map_set_rest_length
;
1495 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1499 map_vector_size
= ASIZE (Vcode_conversion_map_vector
);
1502 for (;map_set_rest_length
> 0;i
++, ic
++, map_set_rest_length
--)
1504 point
= XINT(ccl_prog
[ic
]);
1507 /* +1 is for including separator. */
1509 if (mapping_stack_pointer
1510 >= &mapping_stack
[MAX_MAP_SET_LEVEL
])
1512 PUSH_MAPPING_STACK (map_set_rest_length
- point
,
1514 map_set_rest_length
= point
;
1519 if (point
>= map_vector_size
) continue;
1520 map
= AREF (Vcode_conversion_map_vector
, point
);
1522 /* Check map validity. */
1523 if (!CONSP (map
)) continue;
1525 if (!VECTORP (map
)) continue;
1527 if (size
<= 1) continue;
1529 content
= AREF (map
, 0);
1532 [STARTPOINT VAL1 VAL2 ...] or
1533 [t ELEMENT STARTPOINT ENDPOINT] */
1534 if (NUMBERP (content
))
1536 point
= XUINT (content
);
1537 point
= op
- point
+ 1;
1538 if (!((point
>= 1) && (point
< size
))) continue;
1539 content
= AREF (map
, point
);
1541 else if (EQ (content
, Qt
))
1543 if (size
!= 4) continue;
1544 if ((op
>= XUINT (AREF (map
, 2))) &&
1545 (op
< XUINT (AREF (map
, 3))))
1546 content
= AREF (map
, 1);
1557 if (NUMBERP (content
))
1559 op
= XINT (content
);
1560 i
+= map_set_rest_length
- 1;
1561 ic
+= map_set_rest_length
- 1;
1562 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1563 map_set_rest_length
++;
1565 else if (CONSP (content
))
1567 attrib
= XCAR (content
);
1568 value
= XCDR (content
);
1569 if (!NUMBERP (attrib
) || !NUMBERP (value
))
1572 i
+= map_set_rest_length
- 1;
1573 ic
+= map_set_rest_length
- 1;
1574 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1575 map_set_rest_length
++;
1577 else if (EQ (content
, Qt
))
1581 else if (EQ (content
, Qlambda
))
1583 i
+= map_set_rest_length
;
1584 ic
+= map_set_rest_length
;
1587 else if (SYMBOLP (content
))
1589 if (mapping_stack_pointer
1590 >= &mapping_stack
[MAX_MAP_SET_LEVEL
])
1592 PUSH_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1593 PUSH_MAPPING_STACK (map_set_rest_length
, op
);
1594 stack_idx_of_map_multiple
= stack_idx
+ 1;
1595 CCL_CALL_FOR_MAP_INSTRUCTION (content
, current_ic
);
1600 if (mapping_stack_pointer
<= (mapping_stack
+ 1))
1602 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1603 i
+= map_set_rest_length
;
1604 ic
+= map_set_rest_length
;
1605 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1615 Lisp_Object map
, attrib
, value
, content
;
1617 j
= XINT (ccl_prog
[ic
++]); /* map_id */
1619 if (j
>= ASIZE (Vcode_conversion_map_vector
))
1624 map
= AREF (Vcode_conversion_map_vector
, j
);
1637 point
= XUINT (AREF (map
, 0));
1638 point
= op
- point
+ 1;
1641 (!((point
>= 1) && (point
< size
))))
1646 content
= AREF (map
, point
);
1649 else if (NUMBERP (content
))
1650 reg
[rrr
] = XINT (content
);
1651 else if (EQ (content
, Qt
));
1652 else if (CONSP (content
))
1654 attrib
= XCAR (content
);
1655 value
= XCDR (content
);
1656 if (!NUMBERP (attrib
) || !NUMBERP (value
))
1658 reg
[rrr
] = XUINT(value
);
1661 else if (SYMBOLP (content
))
1662 CCL_CALL_FOR_MAP_INSTRUCTION (content
, ic
);
1680 /* The suppress_error member is set when e.g. a CCL-based coding
1681 system is used for terminal output. */
1682 if (!ccl
->suppress_error
&& destination
)
1684 /* We can insert an error message only if DESTINATION is
1685 specified and we still have a room to store the message
1693 switch (ccl
->status
)
1695 case CCL_STAT_INVALID_CMD
:
1696 sprintf(msg
, "\nCCL: Invalid command %x (ccl_code = %x) at %d.",
1697 code
& 0x1F, code
, this_ic
);
1700 int i
= ccl_backtrace_idx
- 1;
1703 msglen
= strlen (msg
);
1704 if (dst
+ msglen
<= (dst_bytes
? dst_end
: src
))
1706 memcpy (dst
, msg
, msglen
);
1710 for (j
= 0; j
< CCL_DEBUG_BACKTRACE_LEN
; j
++, i
--)
1712 if (i
< 0) i
= CCL_DEBUG_BACKTRACE_LEN
- 1;
1713 if (ccl_backtrace_table
[i
] == 0)
1715 sprintf(msg
, " %d", ccl_backtrace_table
[i
]);
1716 msglen
= strlen (msg
);
1717 if (dst
+ msglen
> (dst_bytes
? dst_end
: src
))
1719 memcpy (dst
, msg
, msglen
);
1728 if (! ccl
->quit_silently
)
1729 sprintf(msg
, "\nCCL: Quited.");
1733 sprintf(msg
, "\nCCL: Unknown error type (%d)", ccl
->status
);
1736 msglen
= strlen (msg
);
1737 if (dst
+ msglen
<= dst_end
)
1739 for (i
= 0; i
< msglen
; i
++)
1743 if (ccl
->status
== CCL_STAT_INVALID_CMD
)
1745 #if 0 /* If the remaining bytes contain 0x80..0x9F, copying them
1746 results in an invalid multibyte sequence. */
1748 /* Copy the remaining source data. */
1749 int i
= src_end
- src
;
1750 if (dst_bytes
&& (dst_end
- dst
) < i
)
1752 memcpy (dst
, src
, i
);
1756 /* Signal that we've consumed everything. */
1764 ccl
->stack_idx
= stack_idx
;
1765 ccl
->prog
= ccl_prog
;
1766 ccl
->consumed
= src
- source
;
1768 ccl
->produced
= dst
- destination
;
1773 /* Resolve symbols in the specified CCL code (Lisp vector). This
1774 function converts symbols of code conversion maps and character
1775 translation tables embeded in the CCL code into their ID numbers.
1777 The return value is a vector (CCL itself or a new vector in which
1778 all symbols are resolved), Qt if resolving of some symbol failed,
1779 or nil if CCL contains invalid data. */
1782 resolve_symbol_ccl_program (Lisp_Object ccl
)
1784 int i
, veclen
, unresolved
= 0;
1785 Lisp_Object result
, contents
, val
;
1788 veclen
= ASIZE (result
);
1790 for (i
= 0; i
< veclen
; i
++)
1792 contents
= AREF (result
, i
);
1793 if (INTEGERP (contents
))
1795 else if (CONSP (contents
)
1796 && SYMBOLP (XCAR (contents
))
1797 && SYMBOLP (XCDR (contents
)))
1799 /* This is the new style for embedding symbols. The form is
1800 (SYMBOL . PROPERTY). (get SYMBOL PROPERTY) should give
1803 if (EQ (result
, ccl
))
1804 result
= Fcopy_sequence (ccl
);
1806 val
= Fget (XCAR (contents
), XCDR (contents
));
1808 ASET (result
, i
, val
);
1813 else if (SYMBOLP (contents
))
1815 /* This is the old style for embedding symbols. This style
1816 may lead to a bug if, for instance, a translation table
1817 and a code conversion map have the same name. */
1818 if (EQ (result
, ccl
))
1819 result
= Fcopy_sequence (ccl
);
1821 val
= Fget (contents
, Qtranslation_table_id
);
1823 ASET (result
, i
, val
);
1826 val
= Fget (contents
, Qcode_conversion_map_id
);
1828 ASET (result
, i
, val
);
1831 val
= Fget (contents
, Qccl_program_idx
);
1833 ASET (result
, i
, val
);
1843 return (unresolved
? Qt
: result
);
1846 /* Return the compiled code (vector) of CCL program CCL_PROG.
1847 CCL_PROG is a name (symbol) of the program or already compiled
1848 code. If necessary, resolve symbols in the compiled code to index
1849 numbers. If we failed to get the compiled code or to resolve
1850 symbols, return Qnil. */
1853 ccl_get_compiled_code (Lisp_Object ccl_prog
, int *idx
)
1855 Lisp_Object val
, slot
;
1857 if (VECTORP (ccl_prog
))
1859 val
= resolve_symbol_ccl_program (ccl_prog
);
1861 return (VECTORP (val
) ? val
: Qnil
);
1863 if (!SYMBOLP (ccl_prog
))
1866 val
= Fget (ccl_prog
, Qccl_program_idx
);
1868 || XINT (val
) >= ASIZE (Vccl_program_table
))
1870 slot
= AREF (Vccl_program_table
, XINT (val
));
1871 if (! VECTORP (slot
)
1872 || ASIZE (slot
) != 4
1873 || ! VECTORP (AREF (slot
, 1)))
1876 if (NILP (AREF (slot
, 2)))
1878 val
= resolve_symbol_ccl_program (AREF (slot
, 1));
1879 if (! VECTORP (val
))
1881 ASET (slot
, 1, val
);
1884 return AREF (slot
, 1);
1887 /* Setup fields of the structure pointed by CCL appropriately for the
1888 execution of CCL program CCL_PROG. CCL_PROG is the name (symbol)
1889 of the CCL program or the already compiled code (vector).
1890 Return 0 if we succeed this setup, else return -1.
1892 If CCL_PROG is nil, we just reset the structure pointed by CCL. */
1894 setup_ccl_program (struct ccl_program
*ccl
, Lisp_Object ccl_prog
)
1898 if (! NILP (ccl_prog
))
1900 struct Lisp_Vector
*vp
;
1902 ccl_prog
= ccl_get_compiled_code (ccl_prog
, &ccl
->idx
);
1903 if (! VECTORP (ccl_prog
))
1905 vp
= XVECTOR (ccl_prog
);
1906 ccl
->size
= vp
->header
.size
;
1907 ccl
->prog
= vp
->contents
;
1908 ccl
->eof_ic
= XINT (vp
->contents
[CCL_HEADER_EOF
]);
1909 ccl
->buf_magnification
= XINT (vp
->contents
[CCL_HEADER_BUF_MAG
]);
1914 slot
= AREF (Vccl_program_table
, ccl
->idx
);
1915 ASET (slot
, 3, Qnil
);
1918 ccl
->ic
= CCL_HEADER_MAIN
;
1919 for (i
= 0; i
< 8; i
++)
1921 ccl
->last_block
= 0;
1922 ccl
->private_state
= 0;
1925 ccl
->suppress_error
= 0;
1926 ccl
->eight_bit_control
= 0;
1927 ccl
->quit_silently
= 0;
1932 DEFUN ("ccl-program-p", Fccl_program_p
, Sccl_program_p
, 1, 1, 0,
1933 doc
: /* Return t if OBJECT is a CCL program name or a compiled CCL program code.
1934 See the documentation of `define-ccl-program' for the detail of CCL program. */)
1935 (Lisp_Object object
)
1939 if (VECTORP (object
))
1941 val
= resolve_symbol_ccl_program (object
);
1942 return (VECTORP (val
) ? Qt
: Qnil
);
1944 if (!SYMBOLP (object
))
1947 val
= Fget (object
, Qccl_program_idx
);
1948 return ((! NATNUMP (val
)
1949 || XINT (val
) >= ASIZE (Vccl_program_table
))
1953 DEFUN ("ccl-execute", Fccl_execute
, Sccl_execute
, 2, 2, 0,
1954 doc
: /* Execute CCL-PROGRAM with registers initialized by REGISTERS.
1956 CCL-PROGRAM is a CCL program name (symbol)
1957 or compiled code generated by `ccl-compile' (for backward compatibility.
1958 In the latter case, the execution overhead is bigger than in the former).
1959 No I/O commands should appear in CCL-PROGRAM.
1961 REGISTERS is a vector of [R0 R1 ... R7] where RN is an initial value
1962 for the Nth register.
1964 As side effect, each element of REGISTERS holds the value of
1965 the corresponding register after the execution.
1967 See the documentation of `define-ccl-program' for a definition of CCL
1969 (Lisp_Object ccl_prog
, Lisp_Object reg
)
1971 struct ccl_program ccl
;
1974 if (setup_ccl_program (&ccl
, ccl_prog
) < 0)
1975 error ("Invalid CCL program");
1978 if (ASIZE (reg
) != 8)
1979 error ("Length of vector REGISTERS is not 8");
1981 for (i
= 0; i
< 8; i
++)
1982 ccl
.reg
[i
] = (INTEGERP (AREF (reg
, i
))
1983 ? XINT (AREF (reg
, i
))
1986 ccl_driver (&ccl
, NULL
, NULL
, 0, 0, Qnil
);
1988 if (ccl
.status
!= CCL_STAT_SUCCESS
)
1989 error ("Error in CCL program at %dth code", ccl
.ic
);
1991 for (i
= 0; i
< 8; i
++)
1992 ASET (reg
, i
, make_number (ccl
.reg
[i
]));
1996 DEFUN ("ccl-execute-on-string", Fccl_execute_on_string
, Sccl_execute_on_string
,
1998 doc
: /* Execute CCL-PROGRAM with initial STATUS on STRING.
2000 CCL-PROGRAM is a symbol registered by `register-ccl-program',
2001 or a compiled code generated by `ccl-compile' (for backward compatibility,
2002 in this case, the execution is slower).
2004 Read buffer is set to STRING, and write buffer is allocated automatically.
2006 STATUS is a vector of [R0 R1 ... R7 IC], where
2007 R0..R7 are initial values of corresponding registers,
2008 IC is the instruction counter specifying from where to start the program.
2009 If R0..R7 are nil, they are initialized to 0.
2010 If IC is nil, it is initialized to head of the CCL program.
2012 If optional 4th arg CONTINUE is non-nil, keep IC on read operation
2013 when read buffer is exhausted, else, IC is always set to the end of
2014 CCL-PROGRAM on exit.
2016 It returns the contents of write buffer as a string,
2017 and as side effect, STATUS is updated.
2018 If the optional 5th arg UNIBYTE-P is non-nil, the returned string
2019 is a unibyte string. By default it is a multibyte string.
2021 See the documentation of `define-ccl-program' for the detail of CCL program.
2022 usage: (ccl-execute-on-string CCL-PROGRAM STATUS STRING &optional CONTINUE UNIBYTE-P) */)
2023 (Lisp_Object ccl_prog
, Lisp_Object status
, Lisp_Object str
, Lisp_Object contin
, Lisp_Object unibyte_p
)
2026 struct ccl_program ccl
;
2028 EMACS_INT outbufsize
;
2029 unsigned char *outbuf
, *outp
;
2030 EMACS_INT str_chars
, str_bytes
;
2031 #define CCL_EXECUTE_BUF_SIZE 1024
2032 int source
[CCL_EXECUTE_BUF_SIZE
], destination
[CCL_EXECUTE_BUF_SIZE
];
2033 EMACS_INT consumed_chars
, consumed_bytes
, produced_chars
;
2035 if (setup_ccl_program (&ccl
, ccl_prog
) < 0)
2036 error ("Invalid CCL program");
2038 CHECK_VECTOR (status
);
2039 if (ASIZE (status
) != 9)
2040 error ("Length of vector STATUS is not 9");
2043 str_chars
= SCHARS (str
);
2044 str_bytes
= SBYTES (str
);
2046 for (i
= 0; i
< 8; i
++)
2048 if (NILP (AREF (status
, i
)))
2049 ASET (status
, i
, make_number (0));
2050 if (INTEGERP (AREF (status
, i
)))
2051 ccl
.reg
[i
] = XINT (AREF (status
, i
));
2053 if (INTEGERP (AREF (status
, i
)))
2055 i
= XFASTINT (AREF (status
, 8));
2056 if (ccl
.ic
< i
&& i
< ccl
.size
)
2060 outbufsize
= (ccl
.buf_magnification
2061 ? str_bytes
* ccl
.buf_magnification
+ 256
2063 outp
= outbuf
= (unsigned char *) xmalloc (outbufsize
);
2065 consumed_chars
= consumed_bytes
= 0;
2069 const unsigned char *p
= SDATA (str
) + consumed_bytes
;
2070 const unsigned char *endp
= SDATA (str
) + str_bytes
;
2074 if (endp
- p
== str_chars
- consumed_chars
)
2075 while (j
< CCL_EXECUTE_BUF_SIZE
&& p
< endp
)
2078 while (j
< CCL_EXECUTE_BUF_SIZE
&& p
< endp
)
2079 source
[j
++] = STRING_CHAR_ADVANCE (p
);
2080 consumed_chars
+= j
;
2081 consumed_bytes
= p
- SDATA (str
);
2083 if (consumed_bytes
== str_bytes
)
2084 ccl
.last_block
= NILP (contin
);
2089 ccl_driver (&ccl
, src
, destination
, src_size
, CCL_EXECUTE_BUF_SIZE
,
2091 produced_chars
+= ccl
.produced
;
2092 if (NILP (unibyte_p
))
2094 if (outp
- outbuf
+ MAX_MULTIBYTE_LENGTH
* ccl
.produced
2097 EMACS_INT offset
= outp
- outbuf
;
2098 outbufsize
+= MAX_MULTIBYTE_LENGTH
* ccl
.produced
;
2099 outbuf
= (unsigned char *) xrealloc (outbuf
, outbufsize
);
2100 outp
= outbuf
+ offset
;
2102 for (j
= 0; j
< ccl
.produced
; j
++)
2103 CHAR_STRING_ADVANCE (destination
[j
], outp
);
2107 if (outp
- outbuf
+ ccl
.produced
> outbufsize
)
2109 EMACS_INT offset
= outp
- outbuf
;
2110 outbufsize
+= ccl
.produced
;
2111 outbuf
= (unsigned char *) xrealloc (outbuf
, outbufsize
);
2112 outp
= outbuf
+ offset
;
2114 for (j
= 0; j
< ccl
.produced
; j
++)
2115 *outp
++ = destination
[j
];
2117 src
+= ccl
.consumed
;
2118 src_size
-= ccl
.consumed
;
2119 if (ccl
.status
!= CCL_STAT_SUSPEND_BY_DST
)
2123 if (ccl
.status
!= CCL_STAT_SUSPEND_BY_SRC
2124 || str_chars
== consumed_chars
)
2128 if (ccl
.status
== CCL_STAT_INVALID_CMD
)
2129 error ("Error in CCL program at %dth code", ccl
.ic
);
2130 if (ccl
.status
== CCL_STAT_QUIT
)
2131 error ("CCL program interrupted at %dth code", ccl
.ic
);
2133 for (i
= 0; i
< 8; i
++)
2134 ASET (status
, i
, make_number (ccl
.reg
[i
]));
2135 ASET (status
, 8, make_number (ccl
.ic
));
2137 if (NILP (unibyte_p
))
2138 val
= make_multibyte_string ((char *) outbuf
, produced_chars
,
2141 val
= make_unibyte_string ((char *) outbuf
, produced_chars
);
2147 DEFUN ("register-ccl-program", Fregister_ccl_program
, Sregister_ccl_program
,
2149 doc
: /* Register CCL program CCL-PROG as NAME in `ccl-program-table'.
2150 CCL-PROG should be a compiled CCL program (vector), or nil.
2151 If it is nil, just reserve NAME as a CCL program name.
2152 Return index number of the registered CCL program. */)
2153 (Lisp_Object name
, Lisp_Object ccl_prog
)
2155 int len
= ASIZE (Vccl_program_table
);
2157 Lisp_Object resolved
;
2159 CHECK_SYMBOL (name
);
2161 if (!NILP (ccl_prog
))
2163 CHECK_VECTOR (ccl_prog
);
2164 resolved
= resolve_symbol_ccl_program (ccl_prog
);
2165 if (NILP (resolved
))
2166 error ("Error in CCL program");
2167 if (VECTORP (resolved
))
2169 ccl_prog
= resolved
;
2176 for (idx
= 0; idx
< len
; idx
++)
2180 slot
= AREF (Vccl_program_table
, idx
);
2181 if (!VECTORP (slot
))
2182 /* This is the first unused slot. Register NAME here. */
2185 if (EQ (name
, AREF (slot
, 0)))
2187 /* Update this slot. */
2188 ASET (slot
, 1, ccl_prog
);
2189 ASET (slot
, 2, resolved
);
2191 return make_number (idx
);
2196 /* Extend the table. */
2197 Vccl_program_table
= larger_vector (Vccl_program_table
, len
* 2, Qnil
);
2202 elt
= Fmake_vector (make_number (4), Qnil
);
2203 ASET (elt
, 0, name
);
2204 ASET (elt
, 1, ccl_prog
);
2205 ASET (elt
, 2, resolved
);
2207 ASET (Vccl_program_table
, idx
, elt
);
2210 Fput (name
, Qccl_program_idx
, make_number (idx
));
2211 return make_number (idx
);
2214 /* Register code conversion map.
2215 A code conversion map consists of numbers, Qt, Qnil, and Qlambda.
2216 The first element is the start code point.
2217 The other elements are mapped numbers.
2218 Symbol t means to map to an original number before mapping.
2219 Symbol nil means that the corresponding element is empty.
2220 Symbol lambda means to terminate mapping here.
2223 DEFUN ("register-code-conversion-map", Fregister_code_conversion_map
,
2224 Sregister_code_conversion_map
,
2226 doc
: /* Register SYMBOL as code conversion map MAP.
2227 Return index number of the registered map. */)
2228 (Lisp_Object symbol
, Lisp_Object map
)
2230 int len
= ASIZE (Vcode_conversion_map_vector
);
2234 CHECK_SYMBOL (symbol
);
2237 for (i
= 0; i
< len
; i
++)
2239 Lisp_Object slot
= AREF (Vcode_conversion_map_vector
, i
);
2244 if (EQ (symbol
, XCAR (slot
)))
2246 idx
= make_number (i
);
2247 XSETCDR (slot
, map
);
2248 Fput (symbol
, Qcode_conversion_map
, map
);
2249 Fput (symbol
, Qcode_conversion_map_id
, idx
);
2255 Vcode_conversion_map_vector
= larger_vector (Vcode_conversion_map_vector
,
2258 idx
= make_number (i
);
2259 Fput (symbol
, Qcode_conversion_map
, map
);
2260 Fput (symbol
, Qcode_conversion_map_id
, idx
);
2261 ASET (Vcode_conversion_map_vector
, i
, Fcons (symbol
, map
));
2269 staticpro (&Vccl_program_table
);
2270 Vccl_program_table
= Fmake_vector (make_number (32), Qnil
);
2272 Qccl
= intern_c_string ("ccl");
2275 Qcclp
= intern_c_string ("cclp");
2278 Qccl_program
= intern_c_string ("ccl-program");
2279 staticpro (&Qccl_program
);
2281 Qccl_program_idx
= intern_c_string ("ccl-program-idx");
2282 staticpro (&Qccl_program_idx
);
2284 Qcode_conversion_map
= intern_c_string ("code-conversion-map");
2285 staticpro (&Qcode_conversion_map
);
2287 Qcode_conversion_map_id
= intern_c_string ("code-conversion-map-id");
2288 staticpro (&Qcode_conversion_map_id
);
2290 DEFVAR_LISP ("code-conversion-map-vector", Vcode_conversion_map_vector
,
2291 doc
: /* Vector of code conversion maps. */);
2292 Vcode_conversion_map_vector
= Fmake_vector (make_number (16), Qnil
);
2294 DEFVAR_LISP ("font-ccl-encoder-alist", Vfont_ccl_encoder_alist
,
2295 doc
: /* Alist of fontname patterns vs corresponding CCL program.
2296 Each element looks like (REGEXP . CCL-CODE),
2297 where CCL-CODE is a compiled CCL program.
2298 When a font whose name matches REGEXP is used for displaying a character,
2299 CCL-CODE is executed to calculate the code point in the font
2300 from the charset number and position code(s) of the character which are set
2301 in CCL registers R0, R1, and R2 before the execution.
2302 The code point in the font is set in CCL registers R1 and R2
2303 when the execution terminated.
2304 If the font is single-byte font, the register R2 is not used. */);
2305 Vfont_ccl_encoder_alist
= Qnil
;
2307 DEFVAR_LISP ("translation-hash-table-vector", Vtranslation_hash_table_vector
,
2308 doc
: /* Vector containing all translation hash tables ever defined.
2309 Comprises pairs (SYMBOL . TABLE) where SYMBOL and TABLE were set up by calls
2310 to `define-translation-hash-table'. The vector is indexed by the table id
2312 Vtranslation_hash_table_vector
= Qnil
;
2314 defsubr (&Sccl_program_p
);
2315 defsubr (&Sccl_execute
);
2316 defsubr (&Sccl_execute_on_string
);
2317 defsubr (&Sregister_ccl_program
);
2318 defsubr (&Sregister_code_conversion_map
);