1 /* CCL (Code Conversion Language) interpreter.
2 Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN.
3 Copyright (C) 2001 Free Software Foundation, Inc.
4 Licensed to the Free Software Foundation.
5 Copyright (C) 2001, 2002
6 National Institute of Advanced Industrial Science and Technology (AIST)
7 Registration Number H13PRO009
9 This file is part of GNU Emacs.
11 GNU Emacs is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
16 GNU Emacs is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with GNU Emacs; see the file COPYING. If not, write to
23 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA. */
31 #include "character.h"
36 Lisp_Object Qccl
, Qcclp
;
38 /* This contains all code conversion map available to CCL. */
39 Lisp_Object Vcode_conversion_map_vector
;
41 /* Alist of fontname patterns vs corresponding CCL program. */
42 Lisp_Object Vfont_ccl_encoder_alist
;
44 /* This symbol is a property which assocates with ccl program vector.
45 Ex: (get 'ccl-big5-encoder 'ccl-program) returns ccl program vector. */
46 Lisp_Object Qccl_program
;
48 /* These symbols are properties which associate with code conversion
49 map and their ID respectively. */
50 Lisp_Object Qcode_conversion_map
;
51 Lisp_Object Qcode_conversion_map_id
;
53 /* Symbols of ccl program have this property, a value of the property
54 is an index for Vccl_protram_table. */
55 Lisp_Object Qccl_program_idx
;
57 /* Table of registered CCL programs. Each element is a vector of
58 NAME, CCL_PROG, and RESOLVEDP where NAME (symbol) is the name of
59 the program, CCL_PROG (vector) is the compiled code of the program,
60 RESOLVEDP (t or nil) is the flag to tell if symbols in CCL_PROG is
61 already resolved to index numbers or not. */
62 Lisp_Object Vccl_program_table
;
64 /* Vector of registered hash tables for translation. */
65 Lisp_Object Vtranslation_hash_table_vector
;
67 /* Return a hash table of id number ID. */
68 #define GET_HASH_TABLE(id) \
69 (XHASH_TABLE (XCDR(XVECTOR(Vtranslation_hash_table_vector)->contents[(id)])))
70 /* Copied from fns.c. */
71 #define HASH_VALUE(H, IDX) AREF ((H)->key_and_value, 2 * (IDX) + 1)
73 extern int charset_unicode
;
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:0000STRIN[0]STRIN[1]STRIN[2]
209 ------------------------------
210 write_string (STRING, LENGTH);
214 #define CCL_WriteArrayReadJump 0x0B /* Write an array element, read, and jump:
215 1:A--D--D--R--E--S--S-rrrXXXXX
220 N:A--D--D--R--E--S--S-rrrYYYYY
221 ------------------------------
222 if (0 <= reg[rrr] < LENGTH)
223 write (ELEMENT[reg[rrr]]);
224 IC += LENGTH + 2; (... pointing at N+1)
228 /* Note: If read is suspended, the resumed execution starts from the
229 Nth code (YYYYY == CCL_ReadJump). */
231 #define CCL_ReadJump 0x0C /* Read and jump:
232 1:A--D--D--R--E--S--S-rrrYYYYY
233 -----------------------------
238 #define CCL_Branch 0x0D /* Jump by branch table:
239 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
240 2:A--D--D--R--E-S-S[0]000XXXXX
241 3:A--D--D--R--E-S-S[1]000XXXXX
243 ------------------------------
244 if (0 <= reg[rrr] < CC..C)
245 IC += ADDRESS[reg[rrr]];
247 IC += ADDRESS[CC..C];
250 #define CCL_ReadRegister 0x0E /* Read bytes into registers:
251 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
252 2:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
254 ------------------------------
259 #define CCL_WriteExprConst 0x0F /* write result of expression:
260 1:00000OPERATION000RRR000XXXXX
262 ------------------------------
263 write (reg[RRR] OPERATION CONSTANT);
267 /* Note: If the Nth read is suspended, the resumed execution starts
268 from the Nth code. */
270 #define CCL_ReadBranch 0x10 /* Read one byte into a register,
271 and jump by branch table:
272 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
273 2:A--D--D--R--E-S-S[0]000XXXXX
274 3:A--D--D--R--E-S-S[1]000XXXXX
276 ------------------------------
278 if (0 <= reg[rrr] < CC..C)
279 IC += ADDRESS[reg[rrr]];
281 IC += ADDRESS[CC..C];
284 #define CCL_WriteRegister 0x11 /* Write registers:
285 1:CCCCCCCCCCCCCCCCCCCrrrXXXXX
286 2:CCCCCCCCCCCCCCCCCCCrrrXXXXX
288 ------------------------------
294 /* Note: If the Nth write is suspended, the resumed execution
295 starts from the Nth code. */
297 #define CCL_WriteExprRegister 0x12 /* Write result of expression
298 1:00000OPERATIONRrrRRR000XXXXX
299 ------------------------------
300 write (reg[RRR] OPERATION reg[Rrr]);
303 #define CCL_Call 0x13 /* Call the CCL program whose ID is
305 1:CCCCCCCCCCCCCCCCCCCCFFFXXXXX
306 [2:00000000cccccccccccccccccccc]
307 ------------------------------
315 #define CCL_WriteConstString 0x14 /* Write a constant or a string:
316 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
317 [2:0000STRIN[0]STRIN[1]STRIN[2]]
319 -----------------------------
323 write_string (STRING, CC..C);
324 IC += (CC..C + 2) / 3;
327 #define CCL_WriteArray 0x15 /* Write an element of array:
328 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
332 ------------------------------
333 if (0 <= reg[rrr] < CC..C)
334 write (ELEMENT[reg[rrr]]);
338 #define CCL_End 0x16 /* Terminate:
339 1:00000000000000000000000XXXXX
340 ------------------------------
344 /* The following two codes execute an assignment arithmetic/logical
345 operation. The form of the operation is like REG OP= OPERAND. */
347 #define CCL_ExprSelfConst 0x17 /* REG OP= constant:
348 1:00000OPERATION000000rrrXXXXX
350 ------------------------------
351 reg[rrr] OPERATION= CONSTANT;
354 #define CCL_ExprSelfReg 0x18 /* REG1 OP= REG2:
355 1:00000OPERATION000RRRrrrXXXXX
356 ------------------------------
357 reg[rrr] OPERATION= reg[RRR];
360 /* The following codes execute an arithmetic/logical operation. The
361 form of the operation is like REG_X = REG_Y OP OPERAND2. */
363 #define CCL_SetExprConst 0x19 /* REG_X = REG_Y OP constant:
364 1:00000OPERATION000RRRrrrXXXXX
366 ------------------------------
367 reg[rrr] = reg[RRR] OPERATION CONSTANT;
371 #define CCL_SetExprReg 0x1A /* REG1 = REG2 OP REG3:
372 1:00000OPERATIONRrrRRRrrrXXXXX
373 ------------------------------
374 reg[rrr] = reg[RRR] OPERATION reg[Rrr];
377 #define CCL_JumpCondExprConst 0x1B /* Jump conditional according to
378 an operation on constant:
379 1:A--D--D--R--E--S--S-rrrXXXXX
382 -----------------------------
383 reg[7] = reg[rrr] OPERATION CONSTANT;
390 #define CCL_JumpCondExprReg 0x1C /* Jump conditional according to
391 an operation on register:
392 1:A--D--D--R--E--S--S-rrrXXXXX
395 -----------------------------
396 reg[7] = reg[rrr] OPERATION reg[RRR];
403 #define CCL_ReadJumpCondExprConst 0x1D /* Read and jump conditional according
404 to an operation on constant:
405 1:A--D--D--R--E--S--S-rrrXXXXX
408 -----------------------------
410 reg[7] = reg[rrr] OPERATION CONSTANT;
417 #define CCL_ReadJumpCondExprReg 0x1E /* Read and jump conditional according
418 to an operation on register:
419 1:A--D--D--R--E--S--S-rrrXXXXX
422 -----------------------------
424 reg[7] = reg[rrr] OPERATION reg[RRR];
431 #define CCL_Extension 0x1F /* Extended CCL code
432 1:ExtendedCOMMNDRrrRRRrrrXXXXX
435 ------------------------------
436 extended_command (rrr,RRR,Rrr,ARGS)
440 Here after, Extended CCL Instructions.
441 Bit length of extended command is 14.
442 Therefore, the instruction code range is 0..16384(0x3fff).
445 /* Read a multibyte characeter.
446 A code point is stored into reg[rrr]. A charset ID is stored into
449 #define CCL_ReadMultibyteChar2 0x00 /* Read Multibyte Character
450 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
452 /* Write a multibyte character.
453 Write a character whose code point is reg[rrr] and the charset ID
456 #define CCL_WriteMultibyteChar2 0x01 /* Write Multibyte Character
457 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
459 /* Translate a character whose code point is reg[rrr] and the charset
460 ID is reg[RRR] by a translation table whose ID is reg[Rrr].
462 A translated character is set in reg[rrr] (code point) and reg[RRR]
465 #define CCL_TranslateCharacter 0x02 /* Translate a multibyte character
466 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
468 /* Translate a character whose code point is reg[rrr] and the charset
469 ID is reg[RRR] by a translation table whose ID is ARGUMENT.
471 A translated character is set in reg[rrr] (code point) and reg[RRR]
474 #define CCL_TranslateCharacterConstTbl 0x03 /* Translate a multibyte character
475 1:ExtendedCOMMNDRrrRRRrrrXXXXX
476 2:ARGUMENT(Translation Table ID)
479 /* Iterate looking up MAPs for reg[rrr] starting from the Nth (N =
480 reg[RRR]) MAP until some value is found.
482 Each MAP is a Lisp vector whose element is number, nil, t, or
484 If the element is nil, ignore the map and proceed to the next map.
485 If the element is t or lambda, finish without changing reg[rrr].
486 If the element is a number, set reg[rrr] to the number and finish.
488 Detail of the map structure is descibed in the comment for
489 CCL_MapMultiple below. */
491 #define CCL_IterateMultipleMap 0x10 /* Iterate multiple maps
492 1:ExtendedCOMMNDXXXRRRrrrXXXXX
499 /* Map the code in reg[rrr] by MAPs starting from the Nth (N =
502 MAPs are supplied in the succeeding CCL codes as follows:
504 When CCL program gives this nested structure of map to this command:
507 (MAP-ID121 MAP-ID122 MAP-ID123)
510 (MAP-ID211 (MAP-ID2111) MAP-ID212)
512 the compiled CCL codes has this sequence:
513 CCL_MapMultiple (CCL code of this command)
514 16 (total number of MAPs and SEPARATORs)
532 A value of each SEPARATOR follows this rule:
533 MAP-SET := SEPARATOR [(MAP-ID | MAP-SET)]+
534 SEPARATOR := -(number of MAP-IDs and SEPARATORs in the MAP-SET)
536 (*)....Nest level of MAP-SET must not be over than MAX_MAP_SET_LEVEL.
538 When some map fails to map (i.e. it doesn't have a value for
539 reg[rrr]), the mapping is treated as identity.
541 The mapping is iterated for all maps in each map set (set of maps
542 separated by SEPARATOR) except in the case that lambda is
543 encountered. More precisely, the mapping proceeds as below:
545 At first, VAL0 is set to reg[rrr], and it is translated by the
546 first map to VAL1. Then, VAL1 is translated by the next map to
547 VAL2. This mapping is iterated until the last map is used. The
548 result of the mapping is the last value of VAL?. When the mapping
549 process reached to the end of the map set, it moves to the next
550 map set. If the next does not exit, the mapping process terminates,
551 and regard the last value as a result.
553 But, when VALm is mapped to VALn and VALn is not a number, the
554 mapping proceed as below:
556 If VALn is nil, the lastest map is ignored and the mapping of VALm
557 proceed to the next map.
559 In VALn is t, VALm is reverted to reg[rrr] and the mapping of VALm
560 proceed to the next map.
562 If VALn is lambda, move to the next map set like reaching to the
563 end of the current map set.
565 If VALn is a symbol, call the CCL program refered by it.
566 Then, use reg[rrr] as a mapped value except for -1, -2 and -3.
567 Such special values are regarded as nil, t, and lambda respectively.
569 Each map is a Lisp vector of the following format (a) or (b):
570 (a)......[STARTPOINT VAL1 VAL2 ...]
571 (b)......[t VAL STARTPOINT ENDPOINT],
573 STARTPOINT is an offset to be used for indexing a map,
574 ENDPOINT is a maximum index number of a map,
575 VAL and VALn is a number, nil, t, or lambda.
577 Valid index range of a map of type (a) is:
578 STARTPOINT <= index < STARTPOINT + map_size - 1
579 Valid index range of a map of type (b) is:
580 STARTPOINT <= index < ENDPOINT */
582 #define CCL_MapMultiple 0x11 /* Mapping by multiple code conversion maps
583 1:ExtendedCOMMNDXXXRRRrrrXXXXX
595 #define MAX_MAP_SET_LEVEL 30
603 static tr_stack mapping_stack
[MAX_MAP_SET_LEVEL
];
604 static tr_stack
*mapping_stack_pointer
;
606 /* If this variable is non-zero, it indicates the stack_idx
607 of immediately called by CCL_MapMultiple. */
608 static int stack_idx_of_map_multiple
;
610 #define PUSH_MAPPING_STACK(restlen, orig) \
613 mapping_stack_pointer->rest_length = (restlen); \
614 mapping_stack_pointer->orig_val = (orig); \
615 mapping_stack_pointer++; \
619 #define POP_MAPPING_STACK(restlen, orig) \
622 mapping_stack_pointer--; \
623 (restlen) = mapping_stack_pointer->rest_length; \
624 (orig) = mapping_stack_pointer->orig_val; \
628 #define CCL_CALL_FOR_MAP_INSTRUCTION(symbol, ret_ic) \
631 struct ccl_program called_ccl; \
632 if (stack_idx >= 256 \
633 || (setup_ccl_program (&called_ccl, (symbol)) != 0)) \
637 ccl_prog = ccl_prog_stack_struct[0].ccl_prog; \
638 ic = ccl_prog_stack_struct[0].ic; \
642 ccl_prog_stack_struct[stack_idx].ccl_prog = ccl_prog; \
643 ccl_prog_stack_struct[stack_idx].ic = (ret_ic); \
645 ccl_prog = called_ccl.prog; \
646 ic = CCL_HEADER_MAIN; \
651 #define CCL_MapSingle 0x12 /* Map by single code conversion map
652 1:ExtendedCOMMNDXXXRRRrrrXXXXX
654 ------------------------------
655 Map reg[rrr] by MAP-ID.
656 If some valid mapping is found,
657 set reg[rrr] to the result,
662 #define CCL_LookupIntConstTbl 0x13 /* Lookup multibyte character by
663 integer key. Afterwards R7 set
664 to 1 iff lookup succeeded.
665 1:ExtendedCOMMNDRrrRRRXXXXXXXX
666 2:ARGUMENT(Hash table ID) */
668 #define CCL_LookupCharConstTbl 0x14 /* Lookup integer by multibyte
669 character key. Afterwards R7 set
670 to 1 iff lookup succeeded.
671 1:ExtendedCOMMNDRrrRRRrrrXXXXX
672 2:ARGUMENT(Hash table ID) */
674 /* CCL arithmetic/logical operators. */
675 #define CCL_PLUS 0x00 /* X = Y + Z */
676 #define CCL_MINUS 0x01 /* X = Y - Z */
677 #define CCL_MUL 0x02 /* X = Y * Z */
678 #define CCL_DIV 0x03 /* X = Y / Z */
679 #define CCL_MOD 0x04 /* X = Y % Z */
680 #define CCL_AND 0x05 /* X = Y & Z */
681 #define CCL_OR 0x06 /* X = Y | Z */
682 #define CCL_XOR 0x07 /* X = Y ^ Z */
683 #define CCL_LSH 0x08 /* X = Y << Z */
684 #define CCL_RSH 0x09 /* X = Y >> Z */
685 #define CCL_LSH8 0x0A /* X = (Y << 8) | Z */
686 #define CCL_RSH8 0x0B /* X = Y >> 8, r[7] = Y & 0xFF */
687 #define CCL_DIVMOD 0x0C /* X = Y / Z, r[7] = Y % Z */
688 #define CCL_LS 0x10 /* X = (X < Y) */
689 #define CCL_GT 0x11 /* X = (X > Y) */
690 #define CCL_EQ 0x12 /* X = (X == Y) */
691 #define CCL_LE 0x13 /* X = (X <= Y) */
692 #define CCL_GE 0x14 /* X = (X >= Y) */
693 #define CCL_NE 0x15 /* X = (X != Y) */
695 #define CCL_DECODE_SJIS 0x16 /* X = HIGHER_BYTE (DE-SJIS (Y, Z))
696 r[7] = LOWER_BYTE (DE-SJIS (Y, Z)) */
697 #define CCL_ENCODE_SJIS 0x17 /* X = HIGHER_BYTE (SJIS (Y, Z))
698 r[7] = LOWER_BYTE (SJIS (Y, Z) */
700 /* Terminate CCL program successfully. */
701 #define CCL_SUCCESS \
704 ccl->status = CCL_STAT_SUCCESS; \
709 /* Suspend CCL program because of reading from empty input buffer or
710 writing to full output buffer. When this program is resumed, the
711 same I/O command is executed. */
712 #define CCL_SUSPEND(stat) \
716 ccl->status = stat; \
721 /* Terminate CCL program because of invalid command. Should not occur
722 in the normal case. */
723 #define CCL_INVALID_CMD \
726 ccl->status = CCL_STAT_INVALID_CMD; \
727 goto ccl_error_handler; \
731 /* Encode one character CH to multibyte form and write to the current
732 output buffer. If CH is less than 256, CH is written as is. */
733 #define CCL_WRITE_CHAR(ch) \
737 else if (dst < dst_end) \
740 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
743 /* Write a string at ccl_prog[IC] of length LEN to the current output
745 #define CCL_WRITE_STRING(len) \
750 else if (dst + len <= dst_end) \
751 for (i = 0; i < len; i++) \
752 *dst++ = ((XFASTINT (ccl_prog[ic + (i / 3)])) \
753 >> ((2 - (i % 3)) * 8)) & 0xFF; \
755 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
758 /* Read one byte from the current input buffer into Rth register. */
759 #define CCL_READ_CHAR(r) \
763 else if (src < src_end) \
765 else if (ccl->last_block) \
771 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); \
775 /* Execute CCL code on characters at SOURCE (length SRC_SIZE). The
776 resulting text goes to a place pointed by DESTINATION, the length
777 of which should not exceed DST_SIZE. As a side effect, how many
778 characters are consumed and produced are recorded in CCL->consumed
779 and CCL->produced, and the contents of CCL registers are updated.
780 If SOURCE or DESTINATION is NULL, only operations on registers are
784 #define CCL_DEBUG_BACKTRACE_LEN 256
785 int ccl_backtrace_table
[CCL_BACKTRACE_TABLE
];
786 int ccl_backtrace_idx
;
789 struct ccl_prog_stack
791 Lisp_Object
*ccl_prog
; /* Pointer to an array of CCL code. */
792 int ic
; /* Instruction Counter. */
795 /* For the moment, we only support depth 256 of stack. */
796 static struct ccl_prog_stack ccl_prog_stack_struct
[256];
799 ccl_driver (ccl
, source
, destination
, src_size
, dst_size
)
800 struct ccl_program
*ccl
;
801 int *source
, *destination
;
802 int src_size
, dst_size
;
804 register int *reg
= ccl
->reg
;
805 register int ic
= ccl
->ic
;
806 register int code
= 0, field1
, field2
;
807 register Lisp_Object
*ccl_prog
= ccl
->prog
;
808 int *src
= source
, *src_end
= src
+ src_size
;
809 int *dst
= destination
, *dst_end
= dst
+ dst_size
;
812 int stack_idx
= ccl
->stack_idx
;
813 /* Instruction counter of the current CCL code. */
815 struct charset
*charset
;
817 if (ic
>= ccl
->eof_ic
)
818 ic
= CCL_HEADER_MAIN
;
820 if (ccl
->buf_magnification
== 0) /* We can't read/produce any bytes. */
823 /* Set mapping stack pointer. */
824 mapping_stack_pointer
= mapping_stack
;
827 ccl_backtrace_idx
= 0;
834 ccl_backtrace_table
[ccl_backtrace_idx
++] = ic
;
835 if (ccl_backtrace_idx
>= CCL_DEBUG_BACKTRACE_LEN
)
836 ccl_backtrace_idx
= 0;
837 ccl_backtrace_table
[ccl_backtrace_idx
] = 0;
840 if (!NILP (Vquit_flag
) && NILP (Vinhibit_quit
))
842 /* We can't just signal Qquit, instead break the loop as if
843 the whole data is processed. Don't reset Vquit_flag, it
844 must be handled later at a safer place. */
846 src
= source
+ src_size
;
847 ccl
->status
= CCL_STAT_QUIT
;
852 code
= XINT (ccl_prog
[ic
]); ic
++;
854 field2
= (code
& 0xFF) >> 5;
857 #define RRR (field1 & 7)
858 #define Rrr ((field1 >> 3) & 7)
860 #define EXCMD (field1 >> 6)
864 case CCL_SetRegister
: /* 00000000000000000RRRrrrXXXXX */
868 case CCL_SetShortConst
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
872 case CCL_SetConst
: /* 00000000000000000000rrrXXXXX */
873 reg
[rrr
] = XINT (ccl_prog
[ic
]);
877 case CCL_SetArray
: /* CCCCCCCCCCCCCCCCCCCCRRRrrrXXXXX */
880 if ((unsigned int) i
< j
)
881 reg
[rrr
] = XINT (ccl_prog
[ic
+ i
]);
885 case CCL_Jump
: /* A--D--D--R--E--S--S-000XXXXX */
889 case CCL_JumpCond
: /* A--D--D--R--E--S--S-rrrXXXXX */
894 case CCL_WriteRegisterJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
900 case CCL_WriteRegisterReadJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
904 CCL_READ_CHAR (reg
[rrr
]);
908 case CCL_WriteConstJump
: /* A--D--D--R--E--S--S-000XXXXX */
909 i
= XINT (ccl_prog
[ic
]);
914 case CCL_WriteConstReadJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
915 i
= XINT (ccl_prog
[ic
]);
918 CCL_READ_CHAR (reg
[rrr
]);
922 case CCL_WriteStringJump
: /* A--D--D--R--E--S--S-000XXXXX */
923 j
= XINT (ccl_prog
[ic
]);
925 CCL_WRITE_STRING (j
);
929 case CCL_WriteArrayReadJump
: /* A--D--D--R--E--S--S-rrrXXXXX */
931 j
= XINT (ccl_prog
[ic
]);
932 if ((unsigned int) i
< j
)
934 i
= XINT (ccl_prog
[ic
+ 1 + i
]);
938 CCL_READ_CHAR (reg
[rrr
]);
939 ic
+= ADDR
- (j
+ 2);
942 case CCL_ReadJump
: /* A--D--D--R--E--S--S-rrrYYYYY */
943 CCL_READ_CHAR (reg
[rrr
]);
947 case CCL_ReadBranch
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
948 CCL_READ_CHAR (reg
[rrr
]);
949 /* fall through ... */
950 case CCL_Branch
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
951 if ((unsigned int) reg
[rrr
] < field1
)
952 ic
+= XINT (ccl_prog
[ic
+ reg
[rrr
]]);
954 ic
+= XINT (ccl_prog
[ic
+ field1
]);
957 case CCL_ReadRegister
: /* CCCCCCCCCCCCCCCCCCCCrrXXXXX */
960 CCL_READ_CHAR (reg
[rrr
]);
962 code
= XINT (ccl_prog
[ic
]); ic
++;
964 field2
= (code
& 0xFF) >> 5;
968 case CCL_WriteExprConst
: /* 1:00000OPERATION000RRR000XXXXX */
971 j
= XINT (ccl_prog
[ic
]);
973 jump_address
= ic
+ 1;
976 case CCL_WriteRegister
: /* CCCCCCCCCCCCCCCCCCCrrrXXXXX */
982 code
= XINT (ccl_prog
[ic
]); ic
++;
984 field2
= (code
& 0xFF) >> 5;
988 case CCL_WriteExprRegister
: /* 1:00000OPERATIONRrrRRR000XXXXX */
996 case CCL_Call
: /* 1:CCCCCCCCCCCCCCCCCCCCFFFXXXXX */
1001 /* If FFF is nonzero, the CCL program ID is in the
1005 prog_id
= XINT (ccl_prog
[ic
]);
1011 if (stack_idx
>= 256
1013 || prog_id
>= ASIZE (Vccl_program_table
)
1014 || (slot
= AREF (Vccl_program_table
, prog_id
), !VECTORP (slot
))
1015 || !VECTORP (AREF (slot
, 1)))
1019 ccl_prog
= ccl_prog_stack_struct
[0].ccl_prog
;
1020 ic
= ccl_prog_stack_struct
[0].ic
;
1025 ccl_prog_stack_struct
[stack_idx
].ccl_prog
= ccl_prog
;
1026 ccl_prog_stack_struct
[stack_idx
].ic
= ic
;
1028 ccl_prog
= XVECTOR (AREF (slot
, 1))->contents
;
1029 ic
= CCL_HEADER_MAIN
;
1033 case CCL_WriteConstString
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1035 CCL_WRITE_CHAR (field1
);
1038 CCL_WRITE_STRING (field1
);
1039 ic
+= (field1
+ 2) / 3;
1043 case CCL_WriteArray
: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1045 if ((unsigned int) i
< field1
)
1047 j
= XINT (ccl_prog
[ic
+ i
]);
1053 case CCL_End
: /* 0000000000000000000000XXXXX */
1057 ccl_prog
= ccl_prog_stack_struct
[stack_idx
].ccl_prog
;
1058 ic
= ccl_prog_stack_struct
[stack_idx
].ic
;
1063 /* ccl->ic should points to this command code again to
1064 suppress further processing. */
1068 case CCL_ExprSelfConst
: /* 00000OPERATION000000rrrXXXXX */
1069 i
= XINT (ccl_prog
[ic
]);
1074 case CCL_ExprSelfReg
: /* 00000OPERATION000RRRrrrXXXXX */
1081 case CCL_PLUS
: reg
[rrr
] += i
; break;
1082 case CCL_MINUS
: reg
[rrr
] -= i
; break;
1083 case CCL_MUL
: reg
[rrr
] *= i
; break;
1084 case CCL_DIV
: reg
[rrr
] /= i
; break;
1085 case CCL_MOD
: reg
[rrr
] %= i
; break;
1086 case CCL_AND
: reg
[rrr
] &= i
; break;
1087 case CCL_OR
: reg
[rrr
] |= i
; break;
1088 case CCL_XOR
: reg
[rrr
] ^= i
; break;
1089 case CCL_LSH
: reg
[rrr
] <<= i
; break;
1090 case CCL_RSH
: reg
[rrr
] >>= i
; break;
1091 case CCL_LSH8
: reg
[rrr
] <<= 8; reg
[rrr
] |= i
; break;
1092 case CCL_RSH8
: reg
[7] = reg
[rrr
] & 0xFF; reg
[rrr
] >>= 8; break;
1093 case CCL_DIVMOD
: reg
[7] = reg
[rrr
] % i
; reg
[rrr
] /= i
; break;
1094 case CCL_LS
: reg
[rrr
] = reg
[rrr
] < i
; break;
1095 case CCL_GT
: reg
[rrr
] = reg
[rrr
] > i
; break;
1096 case CCL_EQ
: reg
[rrr
] = reg
[rrr
] == i
; break;
1097 case CCL_LE
: reg
[rrr
] = reg
[rrr
] <= i
; break;
1098 case CCL_GE
: reg
[rrr
] = reg
[rrr
] >= i
; break;
1099 case CCL_NE
: reg
[rrr
] = reg
[rrr
] != i
; break;
1100 default: CCL_INVALID_CMD
;
1104 case CCL_SetExprConst
: /* 00000OPERATION000RRRrrrXXXXX */
1106 j
= XINT (ccl_prog
[ic
]);
1108 jump_address
= ++ic
;
1111 case CCL_SetExprReg
: /* 00000OPERATIONRrrRRRrrrXXXXX */
1118 case CCL_ReadJumpCondExprConst
: /* A--D--D--R--E--S--S-rrrXXXXX */
1119 CCL_READ_CHAR (reg
[rrr
]);
1120 case CCL_JumpCondExprConst
: /* A--D--D--R--E--S--S-rrrXXXXX */
1122 op
= XINT (ccl_prog
[ic
]);
1123 jump_address
= ic
++ + ADDR
;
1124 j
= XINT (ccl_prog
[ic
]);
1129 case CCL_ReadJumpCondExprReg
: /* A--D--D--R--E--S--S-rrrXXXXX */
1130 CCL_READ_CHAR (reg
[rrr
]);
1131 case CCL_JumpCondExprReg
:
1133 op
= XINT (ccl_prog
[ic
]);
1134 jump_address
= ic
++ + ADDR
;
1135 j
= reg
[XINT (ccl_prog
[ic
])];
1142 case CCL_PLUS
: reg
[rrr
] = i
+ j
; break;
1143 case CCL_MINUS
: reg
[rrr
] = i
- j
; break;
1144 case CCL_MUL
: reg
[rrr
] = i
* j
; break;
1145 case CCL_DIV
: reg
[rrr
] = i
/ j
; break;
1146 case CCL_MOD
: reg
[rrr
] = i
% j
; break;
1147 case CCL_AND
: reg
[rrr
] = i
& j
; break;
1148 case CCL_OR
: reg
[rrr
] = i
| j
; break;
1149 case CCL_XOR
: reg
[rrr
] = i
^ j
;; break;
1150 case CCL_LSH
: reg
[rrr
] = i
<< j
; break;
1151 case CCL_RSH
: reg
[rrr
] = i
>> j
; break;
1152 case CCL_LSH8
: reg
[rrr
] = (i
<< 8) | j
; break;
1153 case CCL_RSH8
: reg
[rrr
] = i
>> 8; reg
[7] = i
& 0xFF; break;
1154 case CCL_DIVMOD
: reg
[rrr
] = i
/ j
; reg
[7] = i
% j
; break;
1155 case CCL_LS
: reg
[rrr
] = i
< j
; break;
1156 case CCL_GT
: reg
[rrr
] = i
> j
; break;
1157 case CCL_EQ
: reg
[rrr
] = i
== j
; break;
1158 case CCL_LE
: reg
[rrr
] = i
<= j
; break;
1159 case CCL_GE
: reg
[rrr
] = i
>= j
; break;
1160 case CCL_NE
: reg
[rrr
] = i
!= j
; break;
1161 case CCL_DECODE_SJIS
:
1169 case CCL_ENCODE_SJIS
:
1177 default: CCL_INVALID_CMD
;
1180 if (code
== CCL_WriteExprConst
|| code
== CCL_WriteExprRegister
)
1193 case CCL_ReadMultibyteChar2
:
1197 charset
= CHAR_CHARSET (i
);
1198 reg
[rrr
] = CHARSET_ID (charset
);
1199 reg
[RRR
] = ENCODE_CHAR (charset
, i
);
1202 case CCL_WriteMultibyteChar2
:
1205 charset
= CHARSET_FROM_ID (reg
[RRR
]);
1206 i
= DECODE_CHAR (charset
, reg
[rrr
]);
1210 case CCL_TranslateCharacter
:
1211 charset
= CHARSET_FROM_ID (reg
[RRR
]);
1212 i
= DECODE_CHAR (charset
, reg
[rrr
]);
1213 op
= translate_char (GET_TRANSLATION_TABLE (reg
[Rrr
]), i
);
1214 charset
= CHAR_CHARSET (op
);
1215 reg
[RRR
] = CHARSET_ID (charset
);
1216 reg
[rrr
] = ENCODE_CHAR (charset
, op
);
1219 case CCL_TranslateCharacterConstTbl
:
1220 op
= XINT (ccl_prog
[ic
]); /* table */
1222 charset
= CHARSET_FROM_ID (reg
[RRR
]);
1223 i
= DECODE_CHAR (charset
, reg
[rrr
]);
1224 op
= translate_char (GET_TRANSLATION_TABLE (op
), i
);
1225 charset
= CHAR_CHARSET (op
);
1226 reg
[RRR
] = CHARSET_ID (charset
);
1227 reg
[rrr
] = ENCODE_CHAR (charset
, op
);
1230 case CCL_LookupIntConstTbl
:
1231 op
= XINT (ccl_prog
[ic
]); /* table */
1234 struct Lisp_Hash_Table
*h
= GET_HASH_TABLE (op
);
1236 op
= hash_lookup (h
, make_number (reg
[RRR
]), NULL
);
1240 opl
= HASH_VALUE (h
, op
);
1241 if (!CHARACTERP (opl
))
1243 reg
[rrr
] = ENCODE_CHAR (CHAR_CHARSET (charset_unicode
),
1245 reg
[7] = 1; /* r7 true for success */
1252 case CCL_LookupCharConstTbl
:
1253 op
= XINT (ccl_prog
[ic
]); /* table */
1255 charset
= CHARSET_FROM_ID (reg
[RRR
]);
1256 i
= DECODE_CHAR (charset
, reg
[rrr
]);
1258 struct Lisp_Hash_Table
*h
= GET_HASH_TABLE (op
);
1260 op
= hash_lookup (h
, make_number (i
), NULL
);
1264 opl
= HASH_VALUE (h
, op
);
1265 if (!INTEGERP (opl
))
1267 reg
[RRR
] = XINT (opl
);
1268 reg
[7] = 1; /* r7 true for success */
1275 case CCL_IterateMultipleMap
:
1277 Lisp_Object map
, content
, attrib
, value
;
1278 int point
, size
, fin_ic
;
1280 j
= XINT (ccl_prog
[ic
++]); /* number of maps. */
1283 if ((j
> reg
[RRR
]) && (j
>= 0))
1298 size
= ASIZE (Vcode_conversion_map_vector
);
1299 point
= XINT (ccl_prog
[ic
++]);
1300 if (point
>= size
) continue;
1301 map
= AREF (Vcode_conversion_map_vector
, point
);
1303 /* Check map varidity. */
1304 if (!CONSP (map
)) continue;
1306 if (!VECTORP (map
)) continue;
1308 if (size
<= 1) continue;
1310 content
= AREF (map
, 0);
1313 [STARTPOINT VAL1 VAL2 ...] or
1314 [t ELELMENT STARTPOINT ENDPOINT] */
1315 if (NUMBERP (content
))
1317 point
= XUINT (content
);
1318 point
= op
- point
+ 1;
1319 if (!((point
>= 1) && (point
< size
))) continue;
1320 content
= AREF (map
, point
);
1322 else if (EQ (content
, Qt
))
1324 if (size
!= 4) continue;
1325 if ((op
>= XUINT (AREF (map
, 2)))
1326 && (op
< XUINT (AREF (map
, 3))))
1327 content
= AREF (map
, 1);
1336 else if (NUMBERP (content
))
1339 reg
[rrr
] = XINT(content
);
1342 else if (EQ (content
, Qt
) || EQ (content
, Qlambda
))
1347 else if (CONSP (content
))
1349 attrib
= XCAR (content
);
1350 value
= XCDR (content
);
1351 if (!NUMBERP (attrib
) || !NUMBERP (value
))
1354 reg
[rrr
] = XUINT (value
);
1357 else if (SYMBOLP (content
))
1358 CCL_CALL_FOR_MAP_INSTRUCTION (content
, fin_ic
);
1368 case CCL_MapMultiple
:
1370 Lisp_Object map
, content
, attrib
, value
;
1371 int point
, size
, map_vector_size
;
1372 int map_set_rest_length
, fin_ic
;
1373 int current_ic
= this_ic
;
1375 /* inhibit recursive call on MapMultiple. */
1376 if (stack_idx_of_map_multiple
> 0)
1378 if (stack_idx_of_map_multiple
<= stack_idx
)
1380 stack_idx_of_map_multiple
= 0;
1381 mapping_stack_pointer
= mapping_stack
;
1386 mapping_stack_pointer
= mapping_stack
;
1387 stack_idx_of_map_multiple
= 0;
1389 map_set_rest_length
=
1390 XINT (ccl_prog
[ic
++]); /* number of maps and separators. */
1391 fin_ic
= ic
+ map_set_rest_length
;
1394 if ((map_set_rest_length
> reg
[RRR
]) && (reg
[RRR
] >= 0))
1398 map_set_rest_length
-= i
;
1404 mapping_stack_pointer
= mapping_stack
;
1408 if (mapping_stack_pointer
<= (mapping_stack
+ 1))
1410 /* Set up initial state. */
1411 mapping_stack_pointer
= mapping_stack
;
1412 PUSH_MAPPING_STACK (0, op
);
1417 /* Recover after calling other ccl program. */
1420 POP_MAPPING_STACK (map_set_rest_length
, orig_op
);
1421 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1425 /* Regard it as Qnil. */
1429 map_set_rest_length
--;
1432 /* Regard it as Qt. */
1436 map_set_rest_length
--;
1439 /* Regard it as Qlambda. */
1441 i
+= map_set_rest_length
;
1442 ic
+= map_set_rest_length
;
1443 map_set_rest_length
= 0;
1446 /* Regard it as normal mapping. */
1447 i
+= map_set_rest_length
;
1448 ic
+= map_set_rest_length
;
1449 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1453 map_vector_size
= ASIZE (Vcode_conversion_map_vector
);
1456 for (;map_set_rest_length
> 0;i
++, ic
++, map_set_rest_length
--)
1458 point
= XINT(ccl_prog
[ic
]);
1461 /* +1 is for including separator. */
1463 if (mapping_stack_pointer
1464 >= &mapping_stack
[MAX_MAP_SET_LEVEL
])
1466 PUSH_MAPPING_STACK (map_set_rest_length
- point
,
1468 map_set_rest_length
= point
;
1473 if (point
>= map_vector_size
) continue;
1474 map
= AREF (Vcode_conversion_map_vector
, point
);
1476 /* Check map varidity. */
1477 if (!CONSP (map
)) continue;
1479 if (!VECTORP (map
)) continue;
1481 if (size
<= 1) continue;
1483 content
= AREF (map
, 0);
1486 [STARTPOINT VAL1 VAL2 ...] or
1487 [t ELEMENT STARTPOINT ENDPOINT] */
1488 if (NUMBERP (content
))
1490 point
= XUINT (content
);
1491 point
= op
- point
+ 1;
1492 if (!((point
>= 1) && (point
< size
))) continue;
1493 content
= AREF (map
, point
);
1495 else if (EQ (content
, Qt
))
1497 if (size
!= 4) continue;
1498 if ((op
>= XUINT (AREF (map
, 2))) &&
1499 (op
< XUINT (AREF (map
, 3))))
1500 content
= AREF (map
, 1);
1511 if (NUMBERP (content
))
1513 op
= XINT (content
);
1514 i
+= map_set_rest_length
- 1;
1515 ic
+= map_set_rest_length
- 1;
1516 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1517 map_set_rest_length
++;
1519 else if (CONSP (content
))
1521 attrib
= XCAR (content
);
1522 value
= XCDR (content
);
1523 if (!NUMBERP (attrib
) || !NUMBERP (value
))
1526 i
+= map_set_rest_length
- 1;
1527 ic
+= map_set_rest_length
- 1;
1528 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1529 map_set_rest_length
++;
1531 else if (EQ (content
, Qt
))
1535 else if (EQ (content
, Qlambda
))
1537 i
+= map_set_rest_length
;
1538 ic
+= map_set_rest_length
;
1541 else if (SYMBOLP (content
))
1543 if (mapping_stack_pointer
1544 >= &mapping_stack
[MAX_MAP_SET_LEVEL
])
1546 PUSH_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1547 PUSH_MAPPING_STACK (map_set_rest_length
, op
);
1548 stack_idx_of_map_multiple
= stack_idx
+ 1;
1549 CCL_CALL_FOR_MAP_INSTRUCTION (content
, current_ic
);
1554 if (mapping_stack_pointer
<= (mapping_stack
+ 1))
1556 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1557 i
+= map_set_rest_length
;
1558 ic
+= map_set_rest_length
;
1559 POP_MAPPING_STACK (map_set_rest_length
, reg
[rrr
]);
1569 Lisp_Object map
, attrib
, value
, content
;
1571 j
= XINT (ccl_prog
[ic
++]); /* map_id */
1573 if (j
>= ASIZE (Vcode_conversion_map_vector
))
1578 map
= AREF (Vcode_conversion_map_vector
, j
);
1591 point
= XUINT (AREF (map
, 0));
1592 point
= op
- point
+ 1;
1595 (!((point
>= 1) && (point
< size
))))
1600 content
= AREF (map
, point
);
1603 else if (NUMBERP (content
))
1604 reg
[rrr
] = XINT (content
);
1605 else if (EQ (content
, Qt
));
1606 else if (CONSP (content
))
1608 attrib
= XCAR (content
);
1609 value
= XCDR (content
);
1610 if (!NUMBERP (attrib
) || !NUMBERP (value
))
1612 reg
[rrr
] = XUINT(value
);
1615 else if (SYMBOLP (content
))
1616 CCL_CALL_FOR_MAP_INSTRUCTION (content
, ic
);
1634 /* The suppress_error member is set when e.g. a CCL-based coding
1635 system is used for terminal output. */
1636 if (!ccl
->suppress_error
&& destination
)
1638 /* We can insert an error message only if DESTINATION is
1639 specified and we still have a room to store the message
1647 switch (ccl
->status
)
1649 case CCL_STAT_INVALID_CMD
:
1650 sprintf(msg
, "\nCCL: Invalid command %x (ccl_code = %x) at %d.",
1651 code
& 0x1F, code
, this_ic
);
1654 int i
= ccl_backtrace_idx
- 1;
1657 msglen
= strlen (msg
);
1658 if (dst
+ msglen
<= (dst_bytes
? dst_end
: src
))
1660 bcopy (msg
, dst
, msglen
);
1664 for (j
= 0; j
< CCL_DEBUG_BACKTRACE_LEN
; j
++, i
--)
1666 if (i
< 0) i
= CCL_DEBUG_BACKTRACE_LEN
- 1;
1667 if (ccl_backtrace_table
[i
] == 0)
1669 sprintf(msg
, " %d", ccl_backtrace_table
[i
]);
1670 msglen
= strlen (msg
);
1671 if (dst
+ msglen
> (dst_bytes
? dst_end
: src
))
1673 bcopy (msg
, dst
, msglen
);
1682 sprintf(msg
, "\nCCL: Quited.");
1686 sprintf(msg
, "\nCCL: Unknown error type (%d).", ccl
->status
);
1689 msglen
= strlen (msg
);
1690 if (dst
+ msglen
<= dst_end
)
1692 for (i
= 0; i
< msglen
; i
++)
1699 ccl
->stack_idx
= stack_idx
;
1700 ccl
->prog
= ccl_prog
;
1701 ccl
->consumed
= src
- source
;
1702 ccl
->produced
= dst
- destination
;
1705 /* Resolve symbols in the specified CCL code (Lisp vector). This
1706 function converts symbols of code conversion maps and character
1707 translation tables embeded in the CCL code into their ID numbers.
1709 The return value is a vector (CCL itself or a new vector in which
1710 all symbols are resolved), Qt if resolving of some symbol failed,
1711 or nil if CCL contains invalid data. */
1714 resolve_symbol_ccl_program (ccl
)
1717 int i
, veclen
, unresolved
= 0;
1718 Lisp_Object result
, contents
, val
;
1721 veclen
= ASIZE (result
);
1723 for (i
= 0; i
< veclen
; i
++)
1725 contents
= AREF (result
, i
);
1726 if (INTEGERP (contents
))
1728 else if (CONSP (contents
)
1729 && SYMBOLP (XCAR (contents
))
1730 && SYMBOLP (XCDR (contents
)))
1732 /* This is the new style for embedding symbols. The form is
1733 (SYMBOL . PROPERTY). (get SYMBOL PROPERTY) should give
1736 if (EQ (result
, ccl
))
1737 result
= Fcopy_sequence (ccl
);
1739 val
= Fget (XCAR (contents
), XCDR (contents
));
1741 AREF (result
, i
) = val
;
1746 else if (SYMBOLP (contents
))
1748 /* This is the old style for embedding symbols. This style
1749 may lead to a bug if, for instance, a translation table
1750 and a code conversion map have the same name. */
1751 if (EQ (result
, ccl
))
1752 result
= Fcopy_sequence (ccl
);
1754 val
= Fget (contents
, Qtranslation_table_id
);
1756 AREF (result
, i
) = val
;
1759 val
= Fget (contents
, Qcode_conversion_map_id
);
1761 AREF (result
, i
) = val
;
1764 val
= Fget (contents
, Qccl_program_idx
);
1766 AREF (result
, i
) = val
;
1776 return (unresolved
? Qt
: result
);
1779 /* Return the compiled code (vector) of CCL program CCL_PROG.
1780 CCL_PROG is a name (symbol) of the program or already compiled
1781 code. If necessary, resolve symbols in the compiled code to index
1782 numbers. If we failed to get the compiled code or to resolve
1783 symbols, return Qnil. */
1786 ccl_get_compiled_code (ccl_prog
)
1787 Lisp_Object ccl_prog
;
1789 Lisp_Object val
, slot
;
1791 if (VECTORP (ccl_prog
))
1793 val
= resolve_symbol_ccl_program (ccl_prog
);
1794 return (VECTORP (val
) ? val
: Qnil
);
1796 if (!SYMBOLP (ccl_prog
))
1799 val
= Fget (ccl_prog
, Qccl_program_idx
);
1801 || XINT (val
) >= ASIZE (Vccl_program_table
))
1803 slot
= AREF (Vccl_program_table
, XINT (val
));
1804 if (! VECTORP (slot
)
1805 || ASIZE (slot
) != 3
1806 || ! VECTORP (AREF (slot
, 1)))
1808 if (NILP (AREF (slot
, 2)))
1810 val
= resolve_symbol_ccl_program (AREF (slot
, 1));
1811 if (! VECTORP (val
))
1813 AREF (slot
, 1) = val
;
1814 AREF (slot
, 2) = Qt
;
1816 return AREF (slot
, 1);
1819 /* Setup fields of the structure pointed by CCL appropriately for the
1820 execution of CCL program CCL_PROG. CCL_PROG is the name (symbol)
1821 of the CCL program or the already compiled code (vector).
1822 Return 0 if we succeed this setup, else return -1.
1824 If CCL_PROG is nil, we just reset the structure pointed by CCL. */
1826 setup_ccl_program (ccl
, ccl_prog
)
1827 struct ccl_program
*ccl
;
1828 Lisp_Object ccl_prog
;
1832 if (! NILP (ccl_prog
))
1834 struct Lisp_Vector
*vp
;
1836 ccl_prog
= ccl_get_compiled_code (ccl_prog
);
1837 if (! VECTORP (ccl_prog
))
1839 vp
= XVECTOR (ccl_prog
);
1840 ccl
->size
= vp
->size
;
1841 ccl
->prog
= vp
->contents
;
1842 ccl
->eof_ic
= XINT (vp
->contents
[CCL_HEADER_EOF
]);
1843 ccl
->buf_magnification
= XINT (vp
->contents
[CCL_HEADER_BUF_MAG
]);
1845 ccl
->ic
= CCL_HEADER_MAIN
;
1846 for (i
= 0; i
< 8; i
++)
1848 ccl
->last_block
= 0;
1849 ccl
->private_state
= 0;
1852 ccl
->suppress_error
= 0;
1856 DEFUN ("ccl-program-p", Fccl_program_p
, Sccl_program_p
, 1, 1, 0,
1857 doc
: /* Return t if OBJECT is a CCL program name or a compiled CCL program code.
1858 See the documentation of `define-ccl-program' for the detail of CCL program. */)
1864 if (VECTORP (object
))
1866 val
= resolve_symbol_ccl_program (object
);
1867 return (VECTORP (val
) ? Qt
: Qnil
);
1869 if (!SYMBOLP (object
))
1872 val
= Fget (object
, Qccl_program_idx
);
1873 return ((! NATNUMP (val
)
1874 || XINT (val
) >= ASIZE (Vccl_program_table
))
1878 DEFUN ("ccl-execute", Fccl_execute
, Sccl_execute
, 2, 2, 0,
1879 doc
: /* Execute CCL-PROGRAM with registers initialized by REGISTERS.
1881 CCL-PROGRAM is a CCL program name (symbol)
1882 or compiled code generated by `ccl-compile' (for backward compatibility.
1883 In the latter case, the execution overhead is bigger than in the former).
1884 No I/O commands should appear in CCL-PROGRAM.
1886 REGISTERS is a vector of [R0 R1 ... R7] where RN is an initial value
1887 for the Nth register.
1889 As side effect, each element of REGISTERS holds the value of
1890 the corresponding register after the execution.
1892 See the documentation of `define-ccl-program' for a definition of CCL
1895 Lisp_Object ccl_prog
, reg
;
1897 struct ccl_program ccl
;
1900 if (setup_ccl_program (&ccl
, ccl_prog
) < 0)
1901 error ("Invalid CCL program");
1904 if (ASIZE (reg
) != 8)
1905 error ("Length of vector REGISTERS is not 8");
1907 for (i
= 0; i
< 8; i
++)
1908 ccl
.reg
[i
] = (INTEGERP (AREF (reg
, i
))
1909 ? XINT (AREF (reg
, i
))
1912 ccl_driver (&ccl
, NULL
, NULL
, 0, 0);
1914 if (ccl
.status
!= CCL_STAT_SUCCESS
)
1915 error ("Error in CCL program at %dth code", ccl
.ic
);
1917 for (i
= 0; i
< 8; i
++)
1918 XSETINT (AREF (reg
, i
), ccl
.reg
[i
]);
1922 DEFUN ("ccl-execute-on-string", Fccl_execute_on_string
, Sccl_execute_on_string
,
1924 doc
: /* Execute CCL-PROGRAM with initial STATUS on STRING.
1926 CCL-PROGRAM is a symbol registered by register-ccl-program,
1927 or a compiled code generated by `ccl-compile' (for backward compatibility,
1928 in this case, the execution is slower).
1930 Read buffer is set to STRING, and write buffer is allocated automatically.
1932 STATUS is a vector of [R0 R1 ... R7 IC], where
1933 R0..R7 are initial values of corresponding registers,
1934 IC is the instruction counter specifying from where to start the program.
1935 If R0..R7 are nil, they are initialized to 0.
1936 If IC is nil, it is initialized to head of the CCL program.
1938 If optional 4th arg CONTINUE is non-nil, keep IC on read operation
1939 when read buffer is exausted, else, IC is always set to the end of
1940 CCL-PROGRAM on exit.
1942 It returns the contents of write buffer as a string,
1943 and as side effect, STATUS is updated.
1944 If the optional 5th arg UNIBYTE-P is non-nil, the returned string
1945 is a unibyte string. By default it is a multibyte string.
1947 See the documentation of `define-ccl-program' for the detail of CCL program. */)
1948 (ccl_prog
, status
, str
, contin
, unibyte_p
)
1949 Lisp_Object ccl_prog
, status
, str
, contin
, unibyte_p
;
1952 struct ccl_program ccl
;
1955 unsigned char *outbuf
, *outp
;
1956 int str_chars
, str_bytes
;
1957 #define CCL_EXECUTE_BUF_SIZE 1024
1958 int source
[CCL_EXECUTE_BUF_SIZE
], destination
[CCL_EXECUTE_BUF_SIZE
];
1959 int consumed_chars
, consumed_bytes
, produced_chars
;
1961 if (setup_ccl_program (&ccl
, ccl_prog
) < 0)
1962 error ("Invalid CCL program");
1964 CHECK_VECTOR (status
);
1965 if (ASIZE (status
) != 9)
1966 error ("Length of vector STATUS is not 9");
1968 str_chars
= XSTRING (str
)->size
;
1969 str_bytes
= STRING_BYTES (XSTRING (str
));
1971 for (i
= 0; i
< 8; i
++)
1973 if (NILP (AREF (status
, i
)))
1974 XSETINT (AREF (status
, i
), 0);
1975 if (INTEGERP (AREF (status
, i
)))
1976 ccl
.reg
[i
] = XINT (AREF (status
, i
));
1978 if (INTEGERP (AREF (status
, i
)))
1980 i
= XFASTINT (AREF (status
, 8));
1981 if (ccl
.ic
< i
&& i
< ccl
.size
)
1985 outbufsize
= (ccl
.buf_magnification
1986 ? str_bytes
* ccl
.buf_magnification
+ 256
1988 outp
= outbuf
= (unsigned char *) xmalloc (outbufsize
);
1990 consumed_chars
= consumed_bytes
= 0;
1992 while (consumed_bytes
< str_bytes
)
1994 const unsigned char *p
= XSTRING (str
)->data
+ consumed_bytes
;
1995 const unsigned char *endp
= XSTRING (str
)->data
+ str_bytes
;
1999 if (endp
- p
== str_chars
- consumed_chars
)
2000 while (i
< CCL_EXECUTE_BUF_SIZE
&& p
< endp
)
2003 while (i
< CCL_EXECUTE_BUF_SIZE
&& p
< endp
)
2004 source
[i
++] = STRING_CHAR_ADVANCE (p
);
2005 consumed_chars
+= i
;
2006 consumed_bytes
= p
- XSTRING (str
)->data
;
2008 if (consumed_bytes
== str_bytes
)
2009 ccl
.last_block
= NILP (contin
);
2014 ccl_driver (&ccl
, src
, destination
, src_size
, CCL_EXECUTE_BUF_SIZE
);
2015 if (ccl
.status
!= CCL_STAT_SUSPEND_BY_DST
)
2017 produced_chars
+= ccl
.produced
;
2018 if (NILP (unibyte_p
))
2020 if (outp
- outbuf
+ MAX_MULTIBYTE_LENGTH
* ccl
.produced
2023 int offset
= outp
- outbuf
;
2024 outbufsize
+= MAX_MULTIBYTE_LENGTH
* ccl
.produced
;
2025 outbuf
= (unsigned char *) xrealloc (outbuf
, outbufsize
);
2026 outp
= outbuf
+ offset
;
2028 for (i
= 0; i
< ccl
.produced
; i
++)
2029 CHAR_STRING_ADVANCE (destination
[i
], outp
);
2033 if (outp
- outbuf
+ ccl
.produced
> outbufsize
)
2035 int offset
= outp
- outbuf
;
2036 outbufsize
+= ccl
.produced
;
2037 outbuf
= (unsigned char *) xrealloc (outbuf
, outbufsize
);
2038 outp
= outbuf
+ offset
;
2040 for (i
= 0; i
< ccl
.produced
; i
++)
2041 *outp
++ = destination
[i
];
2043 src
+= ccl
.consumed
;
2044 src_size
-= ccl
.consumed
;
2047 if (ccl
.status
!= CCL_STAT_SUSPEND_BY_SRC
)
2051 if (ccl
.status
!= CCL_STAT_SUCCESS
2052 && ccl
.status
!= CCL_STAT_SUSPEND_BY_SRC
)
2053 error ("Error in CCL program at %dth code", ccl
.ic
);
2055 for (i
= 0; i
< 8; i
++)
2056 XSET (XVECTOR (status
)->contents
[i
], Lisp_Int
, ccl
.reg
[i
]);
2057 XSETINT (XVECTOR (status
)->contents
[8], ccl
.ic
);
2059 if (NILP (unibyte_p
))
2060 val
= make_multibyte_string ((char *) outbuf
, produced_chars
,
2063 val
= make_unibyte_string ((char *) outbuf
, produced_chars
);
2069 DEFUN ("register-ccl-program", Fregister_ccl_program
, Sregister_ccl_program
,
2071 doc
: /* Register CCL program CCL_PROG as NAME in `ccl-program-table'.
2072 CCL_PROG should be a compiled CCL program (vector), or nil.
2073 If it is nil, just reserve NAME as a CCL program name.
2074 Return index number of the registered CCL program. */)
2076 Lisp_Object name
, ccl_prog
;
2078 int len
= ASIZE (Vccl_program_table
);
2080 Lisp_Object resolved
;
2082 CHECK_SYMBOL (name
);
2084 if (!NILP (ccl_prog
))
2086 CHECK_VECTOR (ccl_prog
);
2087 resolved
= resolve_symbol_ccl_program (ccl_prog
);
2088 if (NILP (resolved
))
2089 error ("Error in CCL program");
2090 if (VECTORP (resolved
))
2092 ccl_prog
= resolved
;
2099 for (idx
= 0; idx
< len
; idx
++)
2103 slot
= AREF (Vccl_program_table
, idx
);
2104 if (!VECTORP (slot
))
2105 /* This is the first unsed slot. Register NAME here. */
2108 if (EQ (name
, AREF (slot
, 0)))
2110 /* Update this slot. */
2111 AREF (slot
, 1) = ccl_prog
;
2112 AREF (slot
, 2) = resolved
;
2113 return make_number (idx
);
2119 /* Extend the table. */
2120 Lisp_Object new_table
;
2123 new_table
= Fmake_vector (make_number (len
* 2), Qnil
);
2124 for (j
= 0; j
< len
; j
++)
2126 = AREF (Vccl_program_table
, j
);
2127 Vccl_program_table
= new_table
;
2133 elt
= Fmake_vector (make_number (3), Qnil
);
2134 AREF (elt
, 0) = name
;
2135 AREF (elt
, 1) = ccl_prog
;
2136 AREF (elt
, 2) = resolved
;
2137 AREF (Vccl_program_table
, idx
) = elt
;
2140 Fput (name
, Qccl_program_idx
, make_number (idx
));
2141 return make_number (idx
);
2144 /* Register code conversion map.
2145 A code conversion map consists of numbers, Qt, Qnil, and Qlambda.
2146 The first element is the start code point.
2147 The other elements are mapped numbers.
2148 Symbol t means to map to an original number before mapping.
2149 Symbol nil means that the corresponding element is empty.
2150 Symbol lambda means to terminate mapping here.
2153 DEFUN ("register-code-conversion-map", Fregister_code_conversion_map
,
2154 Sregister_code_conversion_map
,
2156 doc
: /* Register SYMBOL as code conversion map MAP.
2157 Return index number of the registered map. */)
2159 Lisp_Object symbol
, map
;
2161 int len
= ASIZE (Vcode_conversion_map_vector
);
2165 CHECK_SYMBOL (symbol
);
2168 for (i
= 0; i
< len
; i
++)
2170 Lisp_Object slot
= AREF (Vcode_conversion_map_vector
, i
);
2175 if (EQ (symbol
, XCAR (slot
)))
2177 index
= make_number (i
);
2178 XSETCDR (slot
, map
);
2179 Fput (symbol
, Qcode_conversion_map
, map
);
2180 Fput (symbol
, Qcode_conversion_map_id
, index
);
2187 Lisp_Object new_vector
= Fmake_vector (make_number (len
* 2), Qnil
);
2190 for (j
= 0; j
< len
; j
++)
2191 AREF (new_vector
, j
)
2192 = AREF (Vcode_conversion_map_vector
, j
);
2193 Vcode_conversion_map_vector
= new_vector
;
2196 index
= make_number (i
);
2197 Fput (symbol
, Qcode_conversion_map
, map
);
2198 Fput (symbol
, Qcode_conversion_map_id
, index
);
2199 AREF (Vcode_conversion_map_vector
, i
) = Fcons (symbol
, map
);
2207 staticpro (&Vccl_program_table
);
2208 Vccl_program_table
= Fmake_vector (make_number (32), Qnil
);
2210 Qccl
= intern ("ccl");
2213 Qcclp
= intern ("cclp");
2216 Qccl_program
= intern ("ccl-program");
2217 staticpro (&Qccl_program
);
2219 Qccl_program_idx
= intern ("ccl-program-idx");
2220 staticpro (&Qccl_program_idx
);
2222 Qcode_conversion_map
= intern ("code-conversion-map");
2223 staticpro (&Qcode_conversion_map
);
2225 Qcode_conversion_map_id
= intern ("code-conversion-map-id");
2226 staticpro (&Qcode_conversion_map_id
);
2228 DEFVAR_LISP ("code-conversion-map-vector", &Vcode_conversion_map_vector
,
2229 doc
: /* Vector of code conversion maps. */);
2230 Vcode_conversion_map_vector
= Fmake_vector (make_number (16), Qnil
);
2232 DEFVAR_LISP ("font-ccl-encoder-alist", &Vfont_ccl_encoder_alist
,
2233 doc
: /* Alist of fontname patterns vs corresponding CCL program.
2234 Each element looks like (REGEXP . CCL-CODE),
2235 where CCL-CODE is a compiled CCL program.
2236 When a font whose name matches REGEXP is used for displaying a character,
2237 CCL-CODE is executed to calculate the code point in the font
2238 from the charset number and position code(s) of the character which are set
2239 in CCL registers R0, R1, and R2 before the execution.
2240 The code point in the font is set in CCL registers R1 and R2
2241 when the execution terminated.
2242 If the font is single-byte font, the register R2 is not used. */);
2243 Vfont_ccl_encoder_alist
= Qnil
;
2245 DEFVAR_LISP ("translation-hash-table-vector", &Vtranslation_hash_table_vector
,
2246 doc
: /* Vector containing all translation hash tables ever defined.
2247 Comprises pairs (SYMBOL . TABLE) where SYMBOL and TABLE were set up by calls
2248 to `define-translation-hash-table'. The vector is indexed by the table id
2250 Vtranslation_hash_table_vector
= Qnil
;
2252 defsubr (&Sccl_program_p
);
2253 defsubr (&Sccl_execute
);
2254 defsubr (&Sccl_execute_on_string
);
2255 defsubr (&Sregister_ccl_program
);
2256 defsubr (&Sregister_code_conversion_map
);