Change terms unify/unification to
[bpt/emacs.git] / src / ccl.c
CommitLineData
4ed46869 1/* CCL (Code Conversion Language) interpreter.
75c8c592
RS
2 Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN.
3 Licensed to the Free Software Foundation.
4ed46869 4
369314dc
KH
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
4ed46869 11
369314dc
KH
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
4ed46869 16
369314dc
KH
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
4ed46869
KH
21
22#include <stdio.h>
23
24#ifdef emacs
25
26#include <config.h>
dfcf069d
AS
27
28#ifdef STDC_HEADERS
29#include <stdlib.h>
30#endif
31
4ed46869
KH
32#include "lisp.h"
33#include "charset.h"
34#include "ccl.h"
35#include "coding.h"
36
37#else /* not emacs */
38
39#include "mulelib.h"
40
41#endif /* not emacs */
42
e34b1164
KH
43/* Where is stored translation tables for CCL program. */
44Lisp_Object Vccl_translation_table_vector;
45
4ed46869
KH
46/* Alist of fontname patterns vs corresponding CCL program. */
47Lisp_Object Vfont_ccl_encoder_alist;
48
6ae21908
KH
49/* This symbol is a property which assocates with ccl program vector.
50 Ex: (get 'ccl-big5-encoder 'ccl-program) returns ccl program vector. */
e34b1164
KH
51Lisp_Object Qccl_program;
52
6ae21908
KH
53/* These symbols are properties which associate with ccl translation
54 tables and their ID respectively. */
e34b1164
KH
55Lisp_Object Qccl_translation_table;
56Lisp_Object Qccl_translation_table_id;
57
6ae21908
KH
58/* Symbols of ccl program have this property, a value of the property
59 is an index for Vccl_protram_table. */
60Lisp_Object Qccl_program_idx;
61
62/* These symbols are properties which associate with character
63 unification tables and their ID respectively. */
64Lisp_Object Qunification_table;
65Lisp_Object Qunification_table_id;
66
4ed46869
KH
67/* Vector of CCL program names vs corresponding program data. */
68Lisp_Object Vccl_program_table;
69
70/* CCL (Code Conversion Language) is a simple language which has
71 operations on one input buffer, one output buffer, and 7 registers.
72 The syntax of CCL is described in `ccl.el'. Emacs Lisp function
73 `ccl-compile' compiles a CCL program and produces a CCL code which
74 is a vector of integers. The structure of this vector is as
75 follows: The 1st element: buffer-magnification, a factor for the
76 size of output buffer compared with the size of input buffer. The
77 2nd element: address of CCL code to be executed when encountered
78 with end of input stream. The 3rd and the remaining elements: CCL
79 codes. */
80
81/* Header of CCL compiled code */
82#define CCL_HEADER_BUF_MAG 0
83#define CCL_HEADER_EOF 1
84#define CCL_HEADER_MAIN 2
85
86/* CCL code is a sequence of 28-bit non-negative integers (i.e. the
87 MSB is always 0), each contains CCL command and/or arguments in the
88 following format:
89
90 |----------------- integer (28-bit) ------------------|
91 |------- 17-bit ------|- 3-bit --|- 3-bit --|- 5-bit -|
92 |--constant argument--|-register-|-register-|-command-|
93 ccccccccccccccccc RRR rrr XXXXX
94 or
95 |------- relative address -------|-register-|-command-|
96 cccccccccccccccccccc rrr XXXXX
97 or
98 |------------- constant or other args ----------------|
99 cccccccccccccccccccccccccccc
100
101 where, `cc...c' is a non-negative integer indicating constant value
102 (the left most `c' is always 0) or an absolute jump address, `RRR'
103 and `rrr' are CCL register number, `XXXXX' is one of the following
104 CCL commands. */
105
106/* CCL commands
107
108 Each comment fields shows one or more lines for command syntax and
109 the following lines for semantics of the command. In semantics, IC
110 stands for Instruction Counter. */
111
112#define CCL_SetRegister 0x00 /* Set register a register value:
113 1:00000000000000000RRRrrrXXXXX
114 ------------------------------
115 reg[rrr] = reg[RRR];
116 */
117
118#define CCL_SetShortConst 0x01 /* Set register a short constant value:
119 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
120 ------------------------------
121 reg[rrr] = CCCCCCCCCCCCCCCCCCC;
122 */
123
124#define CCL_SetConst 0x02 /* Set register a constant value:
125 1:00000000000000000000rrrXXXXX
126 2:CONSTANT
127 ------------------------------
128 reg[rrr] = CONSTANT;
129 IC++;
130 */
131
132#define CCL_SetArray 0x03 /* Set register an element of array:
133 1:CCCCCCCCCCCCCCCCCRRRrrrXXXXX
134 2:ELEMENT[0]
135 3:ELEMENT[1]
136 ...
137 ------------------------------
138 if (0 <= reg[RRR] < CC..C)
139 reg[rrr] = ELEMENT[reg[RRR]];
140 IC += CC..C;
141 */
142
143#define CCL_Jump 0x04 /* Jump:
144 1:A--D--D--R--E--S--S-000XXXXX
145 ------------------------------
146 IC += ADDRESS;
147 */
148
149/* Note: If CC..C is greater than 0, the second code is omitted. */
150
151#define CCL_JumpCond 0x05 /* Jump conditional:
152 1:A--D--D--R--E--S--S-rrrXXXXX
153 ------------------------------
154 if (!reg[rrr])
155 IC += ADDRESS;
156 */
157
158
159#define CCL_WriteRegisterJump 0x06 /* Write register and jump:
160 1:A--D--D--R--E--S--S-rrrXXXXX
161 ------------------------------
162 write (reg[rrr]);
163 IC += ADDRESS;
164 */
165
166#define CCL_WriteRegisterReadJump 0x07 /* Write register, read, and jump:
167 1:A--D--D--R--E--S--S-rrrXXXXX
168 2:A--D--D--R--E--S--S-rrrYYYYY
169 -----------------------------
170 write (reg[rrr]);
171 IC++;
172 read (reg[rrr]);
173 IC += ADDRESS;
174 */
175/* Note: If read is suspended, the resumed execution starts from the
176 second code (YYYYY == CCL_ReadJump). */
177
178#define CCL_WriteConstJump 0x08 /* Write constant and jump:
179 1:A--D--D--R--E--S--S-000XXXXX
180 2:CONST
181 ------------------------------
182 write (CONST);
183 IC += ADDRESS;
184 */
185
186#define CCL_WriteConstReadJump 0x09 /* Write constant, read, and jump:
187 1:A--D--D--R--E--S--S-rrrXXXXX
188 2:CONST
189 3:A--D--D--R--E--S--S-rrrYYYYY
190 -----------------------------
191 write (CONST);
192 IC += 2;
193 read (reg[rrr]);
194 IC += ADDRESS;
195 */
196/* Note: If read is suspended, the resumed execution starts from the
197 second code (YYYYY == CCL_ReadJump). */
198
199#define CCL_WriteStringJump 0x0A /* Write string and jump:
200 1:A--D--D--R--E--S--S-000XXXXX
201 2:LENGTH
202 3:0000STRIN[0]STRIN[1]STRIN[2]
203 ...
204 ------------------------------
205 write_string (STRING, LENGTH);
206 IC += ADDRESS;
207 */
208
209#define CCL_WriteArrayReadJump 0x0B /* Write an array element, read, and jump:
210 1:A--D--D--R--E--S--S-rrrXXXXX
211 2:LENGTH
212 3:ELEMENET[0]
213 4:ELEMENET[1]
214 ...
215 N:A--D--D--R--E--S--S-rrrYYYYY
216 ------------------------------
217 if (0 <= reg[rrr] < LENGTH)
218 write (ELEMENT[reg[rrr]]);
219 IC += LENGTH + 2; (... pointing at N+1)
220 read (reg[rrr]);
221 IC += ADDRESS;
222 */
223/* Note: If read is suspended, the resumed execution starts from the
887bfbd7 224 Nth code (YYYYY == CCL_ReadJump). */
4ed46869
KH
225
226#define CCL_ReadJump 0x0C /* Read and jump:
227 1:A--D--D--R--E--S--S-rrrYYYYY
228 -----------------------------
229 read (reg[rrr]);
230 IC += ADDRESS;
231 */
232
233#define CCL_Branch 0x0D /* Jump by branch table:
234 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
235 2:A--D--D--R--E-S-S[0]000XXXXX
236 3:A--D--D--R--E-S-S[1]000XXXXX
237 ...
238 ------------------------------
239 if (0 <= reg[rrr] < CC..C)
240 IC += ADDRESS[reg[rrr]];
241 else
242 IC += ADDRESS[CC..C];
243 */
244
245#define CCL_ReadRegister 0x0E /* Read bytes into registers:
246 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
247 2:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
248 ...
249 ------------------------------
250 while (CCC--)
251 read (reg[rrr]);
252 */
253
254#define CCL_WriteExprConst 0x0F /* write result of expression:
255 1:00000OPERATION000RRR000XXXXX
256 2:CONSTANT
257 ------------------------------
258 write (reg[RRR] OPERATION CONSTANT);
259 IC++;
260 */
261
262/* Note: If the Nth read is suspended, the resumed execution starts
263 from the Nth code. */
264
265#define CCL_ReadBranch 0x10 /* Read one byte into a register,
266 and jump by branch table:
267 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
268 2:A--D--D--R--E-S-S[0]000XXXXX
269 3:A--D--D--R--E-S-S[1]000XXXXX
270 ...
271 ------------------------------
272 read (read[rrr]);
273 if (0 <= reg[rrr] < CC..C)
274 IC += ADDRESS[reg[rrr]];
275 else
276 IC += ADDRESS[CC..C];
277 */
278
279#define CCL_WriteRegister 0x11 /* Write registers:
280 1:CCCCCCCCCCCCCCCCCCCrrrXXXXX
281 2:CCCCCCCCCCCCCCCCCCCrrrXXXXX
282 ...
283 ------------------------------
284 while (CCC--)
285 write (reg[rrr]);
286 ...
287 */
288
289/* Note: If the Nth write is suspended, the resumed execution
290 starts from the Nth code. */
291
292#define CCL_WriteExprRegister 0x12 /* Write result of expression
293 1:00000OPERATIONRrrRRR000XXXXX
294 ------------------------------
295 write (reg[RRR] OPERATION reg[Rrr]);
296 */
297
e34b1164
KH
298#define CCL_Call 0x13 /* Call the CCL program whose ID is
299 (CC..C).
4ed46869
KH
300 1:CCCCCCCCCCCCCCCCCCCC000XXXXX
301 ------------------------------
302 call (CC..C)
303 */
304
305#define CCL_WriteConstString 0x14 /* Write a constant or a string:
306 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
307 [2:0000STRIN[0]STRIN[1]STRIN[2]]
308 [...]
309 -----------------------------
310 if (!rrr)
311 write (CC..C)
312 else
313 write_string (STRING, CC..C);
314 IC += (CC..C + 2) / 3;
315 */
316
317#define CCL_WriteArray 0x15 /* Write an element of array:
318 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
319 2:ELEMENT[0]
320 3:ELEMENT[1]
321 ...
322 ------------------------------
323 if (0 <= reg[rrr] < CC..C)
324 write (ELEMENT[reg[rrr]]);
325 IC += CC..C;
326 */
327
328#define CCL_End 0x16 /* Terminate:
329 1:00000000000000000000000XXXXX
330 ------------------------------
331 terminate ();
332 */
333
334/* The following two codes execute an assignment arithmetic/logical
335 operation. The form of the operation is like REG OP= OPERAND. */
336
337#define CCL_ExprSelfConst 0x17 /* REG OP= constant:
338 1:00000OPERATION000000rrrXXXXX
339 2:CONSTANT
340 ------------------------------
341 reg[rrr] OPERATION= CONSTANT;
342 */
343
344#define CCL_ExprSelfReg 0x18 /* REG1 OP= REG2:
345 1:00000OPERATION000RRRrrrXXXXX
346 ------------------------------
347 reg[rrr] OPERATION= reg[RRR];
348 */
349
350/* The following codes execute an arithmetic/logical operation. The
351 form of the operation is like REG_X = REG_Y OP OPERAND2. */
352
353#define CCL_SetExprConst 0x19 /* REG_X = REG_Y OP constant:
354 1:00000OPERATION000RRRrrrXXXXX
355 2:CONSTANT
356 ------------------------------
357 reg[rrr] = reg[RRR] OPERATION CONSTANT;
358 IC++;
359 */
360
361#define CCL_SetExprReg 0x1A /* REG1 = REG2 OP REG3:
362 1:00000OPERATIONRrrRRRrrrXXXXX
363 ------------------------------
364 reg[rrr] = reg[RRR] OPERATION reg[Rrr];
365 */
366
367#define CCL_JumpCondExprConst 0x1B /* Jump conditional according to
368 an operation on constant:
369 1:A--D--D--R--E--S--S-rrrXXXXX
370 2:OPERATION
371 3:CONSTANT
372 -----------------------------
373 reg[7] = reg[rrr] OPERATION CONSTANT;
374 if (!(reg[7]))
375 IC += ADDRESS;
376 else
377 IC += 2
378 */
379
380#define CCL_JumpCondExprReg 0x1C /* Jump conditional according to
381 an operation on register:
382 1:A--D--D--R--E--S--S-rrrXXXXX
383 2:OPERATION
384 3:RRR
385 -----------------------------
386 reg[7] = reg[rrr] OPERATION reg[RRR];
387 if (!reg[7])
388 IC += ADDRESS;
389 else
390 IC += 2;
391 */
392
393#define CCL_ReadJumpCondExprConst 0x1D /* Read and jump conditional according
394 to an operation on constant:
395 1:A--D--D--R--E--S--S-rrrXXXXX
396 2:OPERATION
397 3:CONSTANT
398 -----------------------------
399 read (reg[rrr]);
400 reg[7] = reg[rrr] OPERATION CONSTANT;
401 if (!reg[7])
402 IC += ADDRESS;
403 else
404 IC += 2;
405 */
406
407#define CCL_ReadJumpCondExprReg 0x1E /* Read and jump conditional according
408 to an operation on register:
409 1:A--D--D--R--E--S--S-rrrXXXXX
410 2:OPERATION
411 3:RRR
412 -----------------------------
413 read (reg[rrr]);
414 reg[7] = reg[rrr] OPERATION reg[RRR];
415 if (!reg[7])
416 IC += ADDRESS;
417 else
418 IC += 2;
419 */
420
421#define CCL_Extention 0x1F /* Extended CCL code
422 1:ExtendedCOMMNDRrrRRRrrrXXXXX
423 2:ARGUEMENT
424 3:...
425 ------------------------------
426 extended_command (rrr,RRR,Rrr,ARGS)
427 */
428
e34b1164 429/*
6ae21908 430 Here after, Extended CCL Instructions.
e34b1164 431 Bit length of extended command is 14.
6ae21908 432 Therefore, the instruction code range is 0..16384(0x3fff).
e34b1164
KH
433 */
434
6ae21908
KH
435/* Read a multibyte characeter.
436 A code point is stored into reg[rrr]. A charset ID is stored into
437 reg[RRR]. */
438
439#define CCL_ReadMultibyteChar2 0x00 /* Read Multibyte Character
440 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
441
442/* Write a multibyte character.
443 Write a character whose code point is reg[rrr] and the charset ID
444 is reg[RRR]. */
445
446#define CCL_WriteMultibyteChar2 0x01 /* Write Multibyte Character
447 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
448
449/* Unify a character whose code point is reg[rrr] the charset ID is
450 reg[RRR] with a unification table whose ID is reg[Rrr].
451
452 A unified character is set in reg[rrr] (code point) and reg[RRR]
453 (charset ID). */
454
455#define CCL_UnifyCharacter 0x02 /* Unify Multibyte Character
456 1:ExtendedCOMMNDRrrRRRrrrXXXXX */
457
458/* Unify a character whose code point is reg[rrr] and the charset ID
459 is reg[RRR] with a unification table whose ID is ARGUMENT.
460
461 A unified character is set in reg[rrr] (code point) and reg[RRR]
462 (charset ID). */
463
464#define CCL_UnifyCharacterConstTbl 0x03 /* Unify Multibyte Character
465 1:ExtendedCOMMNDRrrRRRrrrXXXXX
466 2:ARGUMENT(Unification Table ID)
467 */
468
469/* Iterate looking up TABLEs for reg[rrr] starting from the Nth (N =
470 reg[RRR]) TABLE until some value is found.
471
472 Each TABLE is a Lisp vector whose element is number, nil, t, or
473 lambda.
474 If the element is nil, ignore the table and proceed to the next table.
475 If the element is t or lambda, finish without changing reg[rrr].
476 If the element is a number, set reg[rrr] to the number and finish.
477
478 Detail of the table structure is descibed in the comment for
479 CCL_TranslateMultipleMap below. */
480
481#define CCL_IterateMultipleMap 0x10 /* Iterate Multiple Map
482 1:ExtendedCOMMNDXXXRRRrrrXXXXX
483 2:NUMBER of TABLEs
484 3:TABLE-ID1
485 4:TABLE-ID2
486 ...
487 */
488
489/* Translate code point reg[rrr] by TABLEs starting from the Nth (N =
490 reg[RRR]) table.
491
492 TABLEs are suppried in the succeeding CCL codes as follows:
493
494 When CCL program gives this nested structure of table to this command:
495 ((TABLE-ID11
496 TABLE-ID12
497 (TABLE-ID121 TABLE-ID122 TABLE-ID123)
498 TABLE-ID13)
499 (TABLE-ID21
500 (TABLE-ID211 (TABLE-ID2111) TABLE-ID212)
501 TABLE-ID22)),
502 the compiled CCL codes has this sequence:
503 CCL_TranslateMultipleMap (CCL code of this command)
504 16 (total number of TABLEs and SEPARATERs)
505 -7 (1st SEPARATER)
506 TABLE-ID11
507 TABLE-ID12
508 -3 (2nd SEPARATER)
509 TABLE-ID121
510 TABLE-ID122
511 TABLE-ID123
512 TABLE-ID13
513 -7 (3rd SEPARATER)
514 TABLE-ID21
515 -4 (4th SEPARATER)
516 TABLE-ID211
517 -1 (5th SEPARATER)
518 TABLE_ID2111
519 TABLE-ID212
520 TABLE-ID22
521
522 A value of each SEPARATER follows this rule:
523 TABLE-SET := SEPARATOR [(TABLE-ID | TABLE-SET)]+
524 SEPARATOR := -(number of TABLE-IDs and SEPARATORs in the TABLE-SET)
525
526 (*)....Nest level of TABLE-SET must not be over than MAX_TABLE_SET_LEVEL.
527
528 When some table fails to translate (i.e. it doesn't have a value
529 for reg[rrr]), the translation is treated as identity.
530
531 The translation is iterated for all tables in each table set (set
532 of tables separators by a SEPARATOR) except the case that lambda is
533 encountered (see below).
534
535 Each table is a Lisp vector of the following format (a) or (b):
536 (a)......[STARTPOINT VAL1 VAL2 ...]
537 (b)......[t VAL STARTPOINT ENDPOINT],
538 where
539 STARTPOINT is an offset to be used for indexing a table,
540 ENDPOINT is a maxmum index number of a table,
541 VAL and VALn is a number, nil, t, or lambda.
542
543 Valid index range of a table of type (a) is:
544 STARTPOINT <= index < STARTPOINT + table_size - 1
545 Valid index range of a table of type (b) is:
546 STARTPOINT <= index < ENDPOINT
547
548 If VALn is nil, the table is ignored and translation proceed to the
549 next table.
550 In VALn is t, reg[rrr] is reverted to the original value and
551 translation proceed to the next table.
552 If VALn is lambda, translation in the current TABLE-SET finishes
553 and proceed to the upper level TABLE-SET. */
554
555#define CCL_TranslateMultipleMap 0x11 /* Translate Multiple Map
556 1:ExtendedCOMMNDXXXRRRrrrXXXXX
557 2:N-2
558 3:SEPARATOR_1 (< 0)
559 4:TABLE-ID_1
560 5:TABLE-ID_2
561 ...
562 M:SEPARATOR_x (< 0)
563 M+1:TABLE-ID_y
564 ...
565 N:SEPARATOR_z (< 0)
566 */
567
568#define MAX_TABLE_SET_LEVEL 20
569
570typedef struct
571{
572 int rest_length;
573 int orig_val;
574} tr_stack;
575
576static tr_stack translate_stack[MAX_TABLE_SET_LEVEL];
577static tr_stack *translate_stack_pointer;
578
579#define PUSH_TRANSLATE_STACK(restlen, orig) \
580{ \
581 translate_stack_pointer->rest_length = (restlen); \
582 translate_stack_pointer->orig_val = (orig); \
583 translate_stack_pointer++; \
584}
585
586#define POP_TRANSLATE_STACK(restlen, orig) \
587{ \
588 translate_stack_pointer--; \
589 (restlen) = translate_stack_pointer->rest_length; \
590 (orig) = translate_stack_pointer->orig_val; \
591} \
592
593#define CCL_TranslateSingleMap 0x12 /* Translate Single Map
594 1:ExtendedCOMMNDXXXRRRrrrXXXXX
595 2:TABLE-ID
596 ------------------------------
597 Translate reg[rrr] by TABLE-ID.
598 If some valid translation is found,
599 set reg[rrr] to the result,
600 else
601 set reg[RRR] to -1.
602 */
4ed46869
KH
603
604/* CCL arithmetic/logical operators. */
605#define CCL_PLUS 0x00 /* X = Y + Z */
606#define CCL_MINUS 0x01 /* X = Y - Z */
607#define CCL_MUL 0x02 /* X = Y * Z */
608#define CCL_DIV 0x03 /* X = Y / Z */
609#define CCL_MOD 0x04 /* X = Y % Z */
610#define CCL_AND 0x05 /* X = Y & Z */
611#define CCL_OR 0x06 /* X = Y | Z */
612#define CCL_XOR 0x07 /* X = Y ^ Z */
613#define CCL_LSH 0x08 /* X = Y << Z */
614#define CCL_RSH 0x09 /* X = Y >> Z */
615#define CCL_LSH8 0x0A /* X = (Y << 8) | Z */
616#define CCL_RSH8 0x0B /* X = Y >> 8, r[7] = Y & 0xFF */
617#define CCL_DIVMOD 0x0C /* X = Y / Z, r[7] = Y % Z */
618#define CCL_LS 0x10 /* X = (X < Y) */
619#define CCL_GT 0x11 /* X = (X > Y) */
620#define CCL_EQ 0x12 /* X = (X == Y) */
621#define CCL_LE 0x13 /* X = (X <= Y) */
622#define CCL_GE 0x14 /* X = (X >= Y) */
623#define CCL_NE 0x15 /* X = (X != Y) */
624
625#define CCL_ENCODE_SJIS 0x16 /* X = HIGHER_BYTE (SJIS (Y, Z))
626 r[7] = LOWER_BYTE (SJIS (Y, Z) */
627#define CCL_DECODE_SJIS 0x17 /* X = HIGHER_BYTE (DE-SJIS (Y, Z))
628 r[7] = LOWER_BYTE (DE-SJIS (Y, Z)) */
629
4ed46869
KH
630/* Terminate CCL program successfully. */
631#define CCL_SUCCESS \
632 do { \
633 ccl->status = CCL_STAT_SUCCESS; \
634 ccl->ic = CCL_HEADER_MAIN; \
635 goto ccl_finish; \
636 } while (0)
637
638/* Suspend CCL program because of reading from empty input buffer or
639 writing to full output buffer. When this program is resumed, the
640 same I/O command is executed. */
e34b1164
KH
641#define CCL_SUSPEND(stat) \
642 do { \
643 ic--; \
644 ccl->status = stat; \
645 goto ccl_finish; \
4ed46869
KH
646 } while (0)
647
648/* Terminate CCL program because of invalid command. Should not occur
649 in the normal case. */
650#define CCL_INVALID_CMD \
651 do { \
652 ccl->status = CCL_STAT_INVALID_CMD; \
653 goto ccl_error_handler; \
654 } while (0)
655
656/* Encode one character CH to multibyte form and write to the current
887bfbd7 657 output buffer. If CH is less than 256, CH is written as is. */
e34b1164
KH
658#define CCL_WRITE_CHAR(ch) \
659 do { \
660 if (!dst) \
661 CCL_INVALID_CMD; \
662 else \
663 { \
664 unsigned char work[4], *str; \
665 int len = CHAR_STRING (ch, work, str); \
666 if (dst + len <= (dst_bytes ? dst_end : src)) \
667 { \
668 bcopy (str, dst, len); \
669 dst += len; \
670 } \
671 else \
672 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
673 } \
4ed46869
KH
674 } while (0)
675
676/* Write a string at ccl_prog[IC] of length LEN to the current output
677 buffer. */
678#define CCL_WRITE_STRING(len) \
679 do { \
680 if (!dst) \
681 CCL_INVALID_CMD; \
e34b1164 682 else if (dst + len <= (dst_bytes ? dst_end : src)) \
4ed46869
KH
683 for (i = 0; i < len; i++) \
684 *dst++ = ((XFASTINT (ccl_prog[ic + (i / 3)])) \
685 >> ((2 - (i % 3)) * 8)) & 0xFF; \
686 else \
e34b1164 687 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
4ed46869
KH
688 } while (0)
689
690/* Read one byte from the current input buffer into Rth register. */
e34b1164
KH
691#define CCL_READ_CHAR(r) \
692 do { \
693 if (!src) \
694 CCL_INVALID_CMD; \
695 else if (src < src_end) \
696 r = *src++; \
697 else if (ccl->last_block) \
698 { \
699 ic = ccl->eof_ic; \
700 goto ccl_finish; \
701 } \
702 else \
703 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); \
4ed46869
KH
704 } while (0)
705
706
707/* Execute CCL code on SRC_BYTES length text at SOURCE. The resulting
708 text goes to a place pointed by DESTINATION, the length of which
709 should not exceed DST_BYTES. The bytes actually processed is
710 returned as *CONSUMED. The return value is the length of the
711 resulting text. As a side effect, the contents of CCL registers
712 are updated. If SOURCE or DESTINATION is NULL, only operations on
713 registers are permitted. */
714
715#ifdef CCL_DEBUG
716#define CCL_DEBUG_BACKTRACE_LEN 256
717int ccl_backtrace_table[CCL_BACKTRACE_TABLE];
718int ccl_backtrace_idx;
719#endif
720
721struct ccl_prog_stack
722 {
a9f1cc19 723 Lisp_Object *ccl_prog; /* Pointer to an array of CCL code. */
4ed46869
KH
724 int ic; /* Instruction Counter. */
725 };
726
dfcf069d 727int
4ed46869
KH
728ccl_driver (ccl, source, destination, src_bytes, dst_bytes, consumed)
729 struct ccl_program *ccl;
730 unsigned char *source, *destination;
731 int src_bytes, dst_bytes;
732 int *consumed;
733{
734 register int *reg = ccl->reg;
735 register int ic = ccl->ic;
736 register int code, field1, field2;
e995085f 737 register Lisp_Object *ccl_prog = ccl->prog;
4ed46869
KH
738 unsigned char *src = source, *src_end = src + src_bytes;
739 unsigned char *dst = destination, *dst_end = dst + dst_bytes;
740 int jump_address;
741 int i, j, op;
742 int stack_idx = 0;
743 /* For the moment, we only support depth 256 of stack. */
744 struct ccl_prog_stack ccl_prog_stack_struct[256];
745
746 if (ic >= ccl->eof_ic)
747 ic = CCL_HEADER_MAIN;
748
749#ifdef CCL_DEBUG
750 ccl_backtrace_idx = 0;
751#endif
752
753 for (;;)
754 {
755#ifdef CCL_DEBUG
756 ccl_backtrace_table[ccl_backtrace_idx++] = ic;
757 if (ccl_backtrace_idx >= CCL_DEBUG_BACKTRACE_LEN)
758 ccl_backtrace_idx = 0;
759 ccl_backtrace_table[ccl_backtrace_idx] = 0;
760#endif
761
762 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
763 {
764 /* We can't just signal Qquit, instead break the loop as if
765 the whole data is processed. Don't reset Vquit_flag, it
766 must be handled later at a safer place. */
767 if (consumed)
768 src = source + src_bytes;
769 ccl->status = CCL_STAT_QUIT;
770 break;
771 }
772
773 code = XINT (ccl_prog[ic]); ic++;
774 field1 = code >> 8;
775 field2 = (code & 0xFF) >> 5;
776
777#define rrr field2
778#define RRR (field1 & 7)
779#define Rrr ((field1 >> 3) & 7)
780#define ADDR field1
e34b1164 781#define EXCMD (field1 >> 6)
4ed46869
KH
782
783 switch (code & 0x1F)
784 {
785 case CCL_SetRegister: /* 00000000000000000RRRrrrXXXXX */
786 reg[rrr] = reg[RRR];
787 break;
788
789 case CCL_SetShortConst: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
790 reg[rrr] = field1;
791 break;
792
793 case CCL_SetConst: /* 00000000000000000000rrrXXXXX */
794 reg[rrr] = XINT (ccl_prog[ic]);
795 ic++;
796 break;
797
798 case CCL_SetArray: /* CCCCCCCCCCCCCCCCCCCCRRRrrrXXXXX */
799 i = reg[RRR];
800 j = field1 >> 3;
801 if ((unsigned int) i < j)
802 reg[rrr] = XINT (ccl_prog[ic + i]);
803 ic += j;
804 break;
805
806 case CCL_Jump: /* A--D--D--R--E--S--S-000XXXXX */
807 ic += ADDR;
808 break;
809
810 case CCL_JumpCond: /* A--D--D--R--E--S--S-rrrXXXXX */
811 if (!reg[rrr])
812 ic += ADDR;
813 break;
814
815 case CCL_WriteRegisterJump: /* A--D--D--R--E--S--S-rrrXXXXX */
816 i = reg[rrr];
817 CCL_WRITE_CHAR (i);
818 ic += ADDR;
819 break;
820
821 case CCL_WriteRegisterReadJump: /* A--D--D--R--E--S--S-rrrXXXXX */
822 i = reg[rrr];
823 CCL_WRITE_CHAR (i);
824 ic++;
825 CCL_READ_CHAR (reg[rrr]);
826 ic += ADDR - 1;
827 break;
828
829 case CCL_WriteConstJump: /* A--D--D--R--E--S--S-000XXXXX */
830 i = XINT (ccl_prog[ic]);
831 CCL_WRITE_CHAR (i);
832 ic += ADDR;
833 break;
834
835 case CCL_WriteConstReadJump: /* A--D--D--R--E--S--S-rrrXXXXX */
836 i = XINT (ccl_prog[ic]);
837 CCL_WRITE_CHAR (i);
838 ic++;
839 CCL_READ_CHAR (reg[rrr]);
840 ic += ADDR - 1;
841 break;
842
843 case CCL_WriteStringJump: /* A--D--D--R--E--S--S-000XXXXX */
844 j = XINT (ccl_prog[ic]);
845 ic++;
846 CCL_WRITE_STRING (j);
847 ic += ADDR - 1;
848 break;
849
850 case CCL_WriteArrayReadJump: /* A--D--D--R--E--S--S-rrrXXXXX */
851 i = reg[rrr];
2e34157c 852 j = XINT (ccl_prog[ic]);
4ed46869
KH
853 if ((unsigned int) i < j)
854 {
887bfbd7 855 i = XINT (ccl_prog[ic + 1 + i]);
4ed46869
KH
856 CCL_WRITE_CHAR (i);
857 }
887bfbd7 858 ic += j + 2;
4ed46869
KH
859 CCL_READ_CHAR (reg[rrr]);
860 ic += ADDR - (j + 2);
861 break;
862
863 case CCL_ReadJump: /* A--D--D--R--E--S--S-rrrYYYYY */
864 CCL_READ_CHAR (reg[rrr]);
865 ic += ADDR;
866 break;
867
868 case CCL_ReadBranch: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
869 CCL_READ_CHAR (reg[rrr]);
870 /* fall through ... */
871 case CCL_Branch: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
872 if ((unsigned int) reg[rrr] < field1)
873 ic += XINT (ccl_prog[ic + reg[rrr]]);
874 else
875 ic += XINT (ccl_prog[ic + field1]);
876 break;
877
878 case CCL_ReadRegister: /* CCCCCCCCCCCCCCCCCCCCrrXXXXX */
879 while (1)
880 {
881 CCL_READ_CHAR (reg[rrr]);
882 if (!field1) break;
883 code = XINT (ccl_prog[ic]); ic++;
884 field1 = code >> 8;
885 field2 = (code & 0xFF) >> 5;
886 }
887 break;
888
889 case CCL_WriteExprConst: /* 1:00000OPERATION000RRR000XXXXX */
890 rrr = 7;
891 i = reg[RRR];
892 j = XINT (ccl_prog[ic]);
893 op = field1 >> 6;
894 ic++;
895 goto ccl_set_expr;
896
897 case CCL_WriteRegister: /* CCCCCCCCCCCCCCCCCCCrrrXXXXX */
898 while (1)
899 {
900 i = reg[rrr];
901 CCL_WRITE_CHAR (i);
902 if (!field1) break;
903 code = XINT (ccl_prog[ic]); ic++;
904 field1 = code >> 8;
905 field2 = (code & 0xFF) >> 5;
906 }
907 break;
908
909 case CCL_WriteExprRegister: /* 1:00000OPERATIONRrrRRR000XXXXX */
910 rrr = 7;
911 i = reg[RRR];
912 j = reg[Rrr];
913 op = field1 >> 6;
914 goto ccl_set_expr;
915
916 case CCL_Call: /* CCCCCCCCCCCCCCCCCCCC000XXXXX */
917 {
918 Lisp_Object slot;
919
920 if (stack_idx >= 256
921 || field1 < 0
922 || field1 >= XVECTOR (Vccl_program_table)->size
923 || (slot = XVECTOR (Vccl_program_table)->contents[field1],
924 !CONSP (slot))
925 || !VECTORP (XCONS (slot)->cdr))
926 {
927 if (stack_idx > 0)
928 {
929 ccl_prog = ccl_prog_stack_struct[0].ccl_prog;
930 ic = ccl_prog_stack_struct[0].ic;
931 }
932 CCL_INVALID_CMD;
933 }
934
935 ccl_prog_stack_struct[stack_idx].ccl_prog = ccl_prog;
936 ccl_prog_stack_struct[stack_idx].ic = ic;
937 stack_idx++;
938 ccl_prog = XVECTOR (XCONS (slot)->cdr)->contents;
939 ic = CCL_HEADER_MAIN;
940 }
941 break;
942
943 case CCL_WriteConstString: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
944 if (!rrr)
945 CCL_WRITE_CHAR (field1);
946 else
947 {
948 CCL_WRITE_STRING (field1);
949 ic += (field1 + 2) / 3;
950 }
951 break;
952
953 case CCL_WriteArray: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
954 i = reg[rrr];
955 if ((unsigned int) i < field1)
956 {
957 j = XINT (ccl_prog[ic + i]);
958 CCL_WRITE_CHAR (j);
959 }
960 ic += field1;
961 break;
962
963 case CCL_End: /* 0000000000000000000000XXXXX */
964 if (stack_idx-- > 0)
965 {
966 ccl_prog = ccl_prog_stack_struct[stack_idx].ccl_prog;
967 ic = ccl_prog_stack_struct[stack_idx].ic;
968 break;
969 }
970 CCL_SUCCESS;
971
972 case CCL_ExprSelfConst: /* 00000OPERATION000000rrrXXXXX */
973 i = XINT (ccl_prog[ic]);
974 ic++;
975 op = field1 >> 6;
976 goto ccl_expr_self;
977
978 case CCL_ExprSelfReg: /* 00000OPERATION000RRRrrrXXXXX */
979 i = reg[RRR];
980 op = field1 >> 6;
981
982 ccl_expr_self:
983 switch (op)
984 {
985 case CCL_PLUS: reg[rrr] += i; break;
986 case CCL_MINUS: reg[rrr] -= i; break;
987 case CCL_MUL: reg[rrr] *= i; break;
988 case CCL_DIV: reg[rrr] /= i; break;
989 case CCL_MOD: reg[rrr] %= i; break;
990 case CCL_AND: reg[rrr] &= i; break;
991 case CCL_OR: reg[rrr] |= i; break;
992 case CCL_XOR: reg[rrr] ^= i; break;
993 case CCL_LSH: reg[rrr] <<= i; break;
994 case CCL_RSH: reg[rrr] >>= i; break;
995 case CCL_LSH8: reg[rrr] <<= 8; reg[rrr] |= i; break;
996 case CCL_RSH8: reg[7] = reg[rrr] & 0xFF; reg[rrr] >>= 8; break;
997 case CCL_DIVMOD: reg[7] = reg[rrr] % i; reg[rrr] /= i; break;
998 case CCL_LS: reg[rrr] = reg[rrr] < i; break;
999 case CCL_GT: reg[rrr] = reg[rrr] > i; break;
1000 case CCL_EQ: reg[rrr] = reg[rrr] == i; break;
1001 case CCL_LE: reg[rrr] = reg[rrr] <= i; break;
1002 case CCL_GE: reg[rrr] = reg[rrr] >= i; break;
1003 case CCL_NE: reg[rrr] = reg[rrr] != i; break;
1004 default: CCL_INVALID_CMD;
1005 }
1006 break;
1007
1008 case CCL_SetExprConst: /* 00000OPERATION000RRRrrrXXXXX */
1009 i = reg[RRR];
1010 j = XINT (ccl_prog[ic]);
1011 op = field1 >> 6;
1012 jump_address = ++ic;
1013 goto ccl_set_expr;
1014
1015 case CCL_SetExprReg: /* 00000OPERATIONRrrRRRrrrXXXXX */
1016 i = reg[RRR];
1017 j = reg[Rrr];
1018 op = field1 >> 6;
1019 jump_address = ic;
1020 goto ccl_set_expr;
1021
1022 case CCL_ReadJumpCondExprConst: /* A--D--D--R--E--S--S-rrrXXXXX */
1023 CCL_READ_CHAR (reg[rrr]);
1024 case CCL_JumpCondExprConst: /* A--D--D--R--E--S--S-rrrXXXXX */
1025 i = reg[rrr];
1026 op = XINT (ccl_prog[ic]);
1027 jump_address = ic++ + ADDR;
1028 j = XINT (ccl_prog[ic]);
1029 ic++;
1030 rrr = 7;
1031 goto ccl_set_expr;
1032
1033 case CCL_ReadJumpCondExprReg: /* A--D--D--R--E--S--S-rrrXXXXX */
1034 CCL_READ_CHAR (reg[rrr]);
1035 case CCL_JumpCondExprReg:
1036 i = reg[rrr];
1037 op = XINT (ccl_prog[ic]);
1038 jump_address = ic++ + ADDR;
1039 j = reg[XINT (ccl_prog[ic])];
1040 ic++;
1041 rrr = 7;
1042
1043 ccl_set_expr:
1044 switch (op)
1045 {
1046 case CCL_PLUS: reg[rrr] = i + j; break;
1047 case CCL_MINUS: reg[rrr] = i - j; break;
1048 case CCL_MUL: reg[rrr] = i * j; break;
1049 case CCL_DIV: reg[rrr] = i / j; break;
1050 case CCL_MOD: reg[rrr] = i % j; break;
1051 case CCL_AND: reg[rrr] = i & j; break;
1052 case CCL_OR: reg[rrr] = i | j; break;
1053 case CCL_XOR: reg[rrr] = i ^ j;; break;
1054 case CCL_LSH: reg[rrr] = i << j; break;
1055 case CCL_RSH: reg[rrr] = i >> j; break;
1056 case CCL_LSH8: reg[rrr] = (i << 8) | j; break;
1057 case CCL_RSH8: reg[rrr] = i >> 8; reg[7] = i & 0xFF; break;
1058 case CCL_DIVMOD: reg[rrr] = i / j; reg[7] = i % j; break;
1059 case CCL_LS: reg[rrr] = i < j; break;
1060 case CCL_GT: reg[rrr] = i > j; break;
1061 case CCL_EQ: reg[rrr] = i == j; break;
1062 case CCL_LE: reg[rrr] = i <= j; break;
1063 case CCL_GE: reg[rrr] = i >= j; break;
1064 case CCL_NE: reg[rrr] = i != j; break;
1065 case CCL_ENCODE_SJIS: ENCODE_SJIS (i, j, reg[rrr], reg[7]); break;
1066 case CCL_DECODE_SJIS: DECODE_SJIS (i, j, reg[rrr], reg[7]); break;
1067 default: CCL_INVALID_CMD;
1068 }
1069 code &= 0x1F;
1070 if (code == CCL_WriteExprConst || code == CCL_WriteExprRegister)
1071 {
1072 i = reg[rrr];
1073 CCL_WRITE_CHAR (i);
1074 }
1075 else if (!reg[rrr])
1076 ic = jump_address;
1077 break;
1078
e34b1164
KH
1079 case CCL_Extention:
1080 switch (EXCMD)
1081 {
6ae21908 1082 case CCL_ReadMultibyteChar2:
e34b1164
KH
1083 if (!src)
1084 CCL_INVALID_CMD;
1085 do {
1086 if (src >= src_end)
6ae21908
KH
1087 {
1088 src++;
1089 goto ccl_read_multibyte_character_suspend;
1090 }
e34b1164
KH
1091
1092 i = *src++;
1093 if (i == LEADING_CODE_COMPOSITION)
1094 {
1095 if (src >= src_end)
1096 goto ccl_read_multibyte_character_suspend;
1097 if (*src == 0xFF)
1098 {
1099 ccl->private_state = COMPOSING_WITH_RULE_HEAD;
1100 src++;
1101 }
1102 else
1103 ccl->private_state = COMPOSING_NO_RULE_HEAD;
1104 }
1105 if (ccl->private_state != 0)
1106 {
1107 /* composite character */
1108 if (*src < 0xA0)
1109 ccl->private_state = 0;
1110 else
1111 {
1112 if (i == 0xA0)
1113 {
1114 if (src >= src_end)
1115 goto ccl_read_multibyte_character_suspend;
1116 i = *src++ & 0x7F;
1117 }
1118 else
1119 i -= 0x20;
1120
1121 if (COMPOSING_WITH_RULE_RULE == ccl->private_state)
1122 {
1123 ccl->private_state = COMPOSING_WITH_RULE_HEAD;
1124 continue;
1125 }
1126 else if (COMPOSING_WITH_RULE_HEAD == ccl->private_state)
1127 ccl->private_state = COMPOSING_WITH_RULE_RULE;
1128 }
1129 }
1130 if (i < 0x80)
1131 {
1132 /* ASCII */
1133 reg[rrr] = i;
1134 reg[RRR] = CHARSET_ASCII;
1135 }
1136 else if (i <= MAX_CHARSET_OFFICIAL_DIMENSION1)
1137 {
1138 if (src >= src_end)
1139 goto ccl_read_multibyte_character_suspend;
1140 reg[RRR] = i;
1141 reg[rrr] = (*src++ & 0x7F);
1142 }
1143 else if (i <= MAX_CHARSET_OFFICIAL_DIMENSION2)
1144 {
1145 if ((src + 1) >= src_end)
1146 goto ccl_read_multibyte_character_suspend;
1147 reg[RRR] = i;
1148 i = (*src++ & 0x7F);
1149 reg[rrr] = ((i << 7) | (*src & 0x7F));
1150 src++;
1151 }
6ae21908
KH
1152 else if ((i == LEADING_CODE_PRIVATE_11)
1153 || (i == LEADING_CODE_PRIVATE_12))
e34b1164
KH
1154 {
1155 if ((src + 1) >= src_end)
1156 goto ccl_read_multibyte_character_suspend;
1157 reg[RRR] = *src++;
1158 reg[rrr] = (*src++ & 0x7F);
1159 }
6ae21908
KH
1160 else if ((i == LEADING_CODE_PRIVATE_21)
1161 || (i == LEADING_CODE_PRIVATE_22))
e34b1164
KH
1162 {
1163 if ((src + 2) >= src_end)
1164 goto ccl_read_multibyte_character_suspend;
1165 reg[RRR] = *src++;
1166 i = (*src++ & 0x7F);
1167 reg[rrr] = ((i << 7) | (*src & 0x7F));
1168 src++;
1169 }
1170 else
1171 {
6ae21908
KH
1172 /* INVALID CODE
1173 Returned charset is -1. */
e34b1164
KH
1174 reg[RRR] = -1;
1175 }
1176 } while (0);
1177 break;
1178
1179 ccl_read_multibyte_character_suspend:
1180 src--;
1181 if (ccl->last_block)
1182 {
1183 ic = ccl->eof_ic;
1184 goto ccl_finish;
1185 }
1186 else
1187 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC);
1188
1189 break;
1190
6ae21908 1191 case CCL_WriteMultibyteChar2:
e34b1164
KH
1192 i = reg[RRR]; /* charset */
1193 if (i == CHARSET_ASCII)
1194 i = reg[rrr] & 0x7F;
1195 else if (i == CHARSET_COMPOSITION)
1196 i = MAKE_COMPOSITE_CHAR (reg[rrr]);
1197 else if (CHARSET_DIMENSION (i) == 1)
1198 i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F);
1199 else if (i < MIN_CHARSET_PRIVATE_DIMENSION2)
1200 i = ((i - 0x8F) << 14) | reg[rrr];
1201 else
1202 i = ((i - 0xE0) << 14) | reg[rrr];
1203
1204 CCL_WRITE_CHAR (i);
1205
1206 break;
1207
1208 case CCL_UnifyCharacter:
1209 i = reg[RRR]; /* charset */
1210 if (i == CHARSET_ASCII)
1211 i = reg[rrr] & 0x7F;
1212 else if (i == CHARSET_COMPOSITION)
1213 {
1214 reg[RRR] = -1;
1215 break;
1216 }
1217 else if (CHARSET_DIMENSION (i) == 1)
1218 i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F);
1219 else if (i < MIN_CHARSET_PRIVATE_DIMENSION2)
1220 i = ((i - 0x8F) << 14) | (reg[rrr] & 0x3FFF);
1221 else
1222 i = ((i - 0xE0) << 14) | (reg[rrr] & 0x3FFF);
1223
1224 op = unify_char (UNIFICATION_ID_TABLE (reg[Rrr]), i, -1, 0, 0);
1225 SPLIT_CHAR (op, reg[RRR], i, j);
1226 if (j != -1)
1227 i = (i << 7) | j;
1228
1229 reg[rrr] = i;
1230 break;
1231
1232 case CCL_UnifyCharacterConstTbl:
1233 op = XINT (ccl_prog[ic]); /* table */
1234 ic++;
1235 i = reg[RRR]; /* charset */
1236 if (i == CHARSET_ASCII)
1237 i = reg[rrr] & 0x7F;
1238 else if (i == CHARSET_COMPOSITION)
1239 {
1240 reg[RRR] = -1;
1241 break;
1242 }
1243 else if (CHARSET_DIMENSION (i) == 1)
1244 i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F);
1245 else if (i < MIN_CHARSET_PRIVATE_DIMENSION2)
1246 i = ((i - 0x8F) << 14) | (reg[rrr] & 0x3FFF);
1247 else
1248 i = ((i - 0xE0) << 14) | (reg[rrr] & 0x3FFF);
1249
1250 op = unify_char (UNIFICATION_ID_TABLE (op), i, -1, 0, 0);
1251 SPLIT_CHAR (op, reg[RRR], i, j);
1252 if (j != -1)
1253 i = (i << 7) | j;
1254
1255 reg[rrr] = i;
1256 break;
1257
1258 case CCL_IterateMultipleMap:
1259 {
1260 Lisp_Object table, content, attrib, value;
1261 int point, size, fin_ic;
1262
1263 j = XINT (ccl_prog[ic++]); /* number of tables. */
1264 fin_ic = ic + j;
1265 op = reg[rrr];
1266 if ((j > reg[RRR]) && (j >= 0))
1267 {
1268 ic += reg[RRR];
1269 i = reg[RRR];
1270 }
1271 else
1272 {
1273 reg[RRR] = -1;
1274 ic = fin_ic;
1275 break;
1276 }
1277
1278 for (;i < j;i++)
1279 {
1280
1281 size = XVECTOR (Vccl_translation_table_vector)->size;
d387866a 1282 point = XINT (ccl_prog[ic++]);
e34b1164 1283 if (point >= size) continue;
6ae21908
KH
1284 table =
1285 XVECTOR (Vccl_translation_table_vector)->contents[point];
1286
1287 /* Check table varidity. */
e34b1164
KH
1288 if (!CONSP (table)) continue;
1289 table = XCONS(table)->cdr;
1290 if (!VECTORP (table)) continue;
1291 size = XVECTOR (table)->size;
1292 if (size <= 1) continue;
6ae21908
KH
1293
1294 content = XVECTOR (table)->contents[0];
1295
1296 /* check table type,
1297 [STARTPOINT VAL1 VAL2 ...] or
1298 [t ELELMENT STARTPOINT ENDPOINT] */
1299 if (NUMBERP (content))
1300 {
1301 point = XUINT (content);
1302 point = op - point + 1;
1303 if (!((point >= 1) && (point < size))) continue;
1304 content = XVECTOR (table)->contents[point];
1305 }
1306 else if (EQ (content, Qt))
1307 {
1308 if (size != 4) continue;
1309 if ((op >= XUINT (XVECTOR (table)->contents[2]))
1310 && (op < XUINT (XVECTOR (table)->contents[3])))
1311 content = XVECTOR (table)->contents[1];
1312 else
1313 continue;
1314 }
1315 else
1316 continue;
e34b1164
KH
1317
1318 if (NILP (content))
1319 continue;
1320 else if (NUMBERP (content))
1321 {
1322 reg[RRR] = i;
6ae21908 1323 reg[rrr] = XINT(content);
e34b1164
KH
1324 break;
1325 }
1326 else if (EQ (content, Qt) || EQ (content, Qlambda))
1327 {
1328 reg[RRR] = i;
1329 break;
1330 }
1331 else if (CONSP (content))
1332 {
1333 attrib = XCONS (content)->car;
1334 value = XCONS (content)->cdr;
1335 if (!NUMBERP (attrib) || !NUMBERP (value))
1336 continue;
1337 reg[RRR] = i;
6ae21908 1338 reg[rrr] = XUINT (value);
e34b1164
KH
1339 break;
1340 }
1341 }
1342 if (i == j)
1343 reg[RRR] = -1;
1344 ic = fin_ic;
1345 }
1346 break;
1347
1348 case CCL_TranslateMultipleMap:
1349 {
1350 Lisp_Object table, content, attrib, value;
1351 int point, size, table_vector_size;
6ae21908 1352 int table_set_rest_length, fin_ic;
e34b1164 1353
6ae21908
KH
1354 table_set_rest_length =
1355 XINT (ccl_prog[ic++]); /* number of tables and separators. */
1356 fin_ic = ic + table_set_rest_length;
1357 if ((table_set_rest_length > reg[RRR]) && (reg[RRR] >= 0))
e34b1164
KH
1358 {
1359 ic += reg[RRR];
1360 i = reg[RRR];
6ae21908 1361 table_set_rest_length -= i;
e34b1164
KH
1362 }
1363 else
1364 {
1365 ic = fin_ic;
1366 reg[RRR] = -1;
1367 break;
1368 }
6ae21908 1369 translate_stack_pointer = translate_stack;
e34b1164 1370 op = reg[rrr];
6ae21908 1371 PUSH_TRANSLATE_STACK (0, op);
e34b1164 1372 reg[RRR] = -1;
6ae21908
KH
1373 table_vector_size
1374 = XVECTOR (Vccl_translation_table_vector)->size;
1375 for (;table_set_rest_length > 0;i++, table_set_rest_length--)
e34b1164 1376 {
6ae21908
KH
1377 point = XINT(ccl_prog[ic++]);
1378 if (point < 0)
e34b1164 1379 {
6ae21908
KH
1380 point = -point;
1381 if (translate_stack_pointer
1382 >= &translate_stack[MAX_TABLE_SET_LEVEL])
1383 {
1384 CCL_INVALID_CMD;
1385 }
1386 PUSH_TRANSLATE_STACK (table_set_rest_length - point,
1387 reg[rrr]);
1388 table_set_rest_length = point + 1;
1389 reg[rrr] = op;
e34b1164
KH
1390 continue;
1391 }
6ae21908 1392
e34b1164 1393 if (point >= table_vector_size) continue;
6ae21908
KH
1394 table =
1395 XVECTOR (Vccl_translation_table_vector)->contents[point];
1396
1397 /* Check table varidity. */
e34b1164
KH
1398 if (!CONSP (table)) continue;
1399 table = XCONS (table)->cdr;
1400 if (!VECTORP (table)) continue;
1401 size = XVECTOR (table)->size;
1402 if (size <= 1) continue;
6ae21908
KH
1403
1404 content = XVECTOR (table)->contents[0];
1405
1406 /* check table type,
1407 [STARTPOINT VAL1 VAL2 ...] or
1408 [t ELEMENT STARTPOINT ENDPOINT] */
1409 if (NUMBERP (content))
1410 {
1411 point = XUINT (content);
1412 point = op - point + 1;
1413 if (!((point >= 1) && (point < size))) continue;
1414 content = XVECTOR (table)->contents[point];
1415 }
1416 else if (EQ (content, Qt))
1417 {
1418 if (size != 4) continue;
1419 if ((op >= XUINT (XVECTOR (table)->contents[2])) &&
1420 (op < XUINT (XVECTOR (table)->contents[3])))
1421 content = XVECTOR (table)->contents[1];
1422 else
1423 continue;
1424 }
1425 else
1426 continue;
e34b1164
KH
1427
1428 if (NILP (content))
1429 continue;
1430 else if (NUMBERP (content))
1431 {
6ae21908 1432 op = XINT (content);
e34b1164 1433 reg[RRR] = i;
6ae21908
KH
1434 i += table_set_rest_length;
1435 POP_TRANSLATE_STACK (table_set_rest_length, reg[rrr]);
e34b1164
KH
1436 }
1437 else if (CONSP (content))
1438 {
1439 attrib = XCONS (content)->car;
1440 value = XCONS (content)->cdr;
1441 if (!NUMBERP (attrib) || !NUMBERP (value))
1442 continue;
1443 reg[RRR] = i;
1444 op = XUINT (value);
6ae21908
KH
1445 i += table_set_rest_length;
1446 POP_TRANSLATE_STACK (table_set_rest_length, reg[rrr]);
e34b1164
KH
1447 }
1448 else if (EQ (content, Qt))
1449 {
1450 reg[RRR] = i;
1451 op = reg[rrr];
6ae21908
KH
1452 i += table_set_rest_length;
1453 POP_TRANSLATE_STACK (table_set_rest_length, reg[rrr]);
e34b1164
KH
1454 }
1455 else if (EQ (content, Qlambda))
6ae21908
KH
1456 {
1457 break;
1458 }
1459 else
1460 CCL_INVALID_CMD;
e34b1164
KH
1461 }
1462 ic = fin_ic;
1463 }
1464 reg[rrr] = op;
1465 break;
1466
1467 case CCL_TranslateSingleMap:
1468 {
1469 Lisp_Object table, attrib, value, content;
1470 int size, point;
1471 j = XINT (ccl_prog[ic++]); /* table_id */
1472 op = reg[rrr];
1473 if (j >= XVECTOR (Vccl_translation_table_vector)->size)
1474 {
1475 reg[RRR] = -1;
1476 break;
1477 }
6ae21908 1478 table = XVECTOR (Vccl_translation_table_vector)->contents[j];
e34b1164
KH
1479 if (!CONSP (table))
1480 {
1481 reg[RRR] = -1;
1482 break;
1483 }
1484 table = XCONS(table)->cdr;
1485 if (!VECTORP (table))
1486 {
1487 reg[RRR] = -1;
1488 break;
1489 }
1490 size = XVECTOR (table)->size;
1491 point = XUINT (XVECTOR (table)->contents[0]);
1492 point = op - point + 1;
1493 reg[RRR] = 0;
1494 if ((size <= 1) ||
1495 (!((point >= 1) && (point < size))))
1496 reg[RRR] = -1;
1497 else
1498 {
1499 content = XVECTOR (table)->contents[point];
1500 if (NILP (content))
1501 reg[RRR] = -1;
1502 else if (NUMBERP (content))
6ae21908 1503 reg[rrr] = XINT (content);
e34b1164
KH
1504 else if (EQ (content, Qt))
1505 reg[RRR] = i;
1506 else if (CONSP (content))
1507 {
1508 attrib = XCONS (content)->car;
1509 value = XCONS (content)->cdr;
1510 if (!NUMBERP (attrib) || !NUMBERP (value))
1511 continue;
1512 reg[rrr] = XUINT(value);
1513 break;
1514 }
1515 else
1516 reg[RRR] = -1;
1517 }
1518 }
1519 break;
1520
1521 default:
1522 CCL_INVALID_CMD;
1523 }
1524 break;
1525
4ed46869
KH
1526 default:
1527 CCL_INVALID_CMD;
1528 }
1529 }
1530
1531 ccl_error_handler:
1532 if (destination)
1533 {
1534 /* We can insert an error message only if DESTINATION is
1535 specified and we still have a room to store the message
1536 there. */
1537 char msg[256];
1538 int msglen;
1539
1540 switch (ccl->status)
1541 {
1542 case CCL_STAT_INVALID_CMD:
1543 sprintf(msg, "\nCCL: Invalid command %x (ccl_code = %x) at %d.",
1544 code & 0x1F, code, ic);
1545#ifdef CCL_DEBUG
1546 {
1547 int i = ccl_backtrace_idx - 1;
1548 int j;
1549
1550 msglen = strlen (msg);
6ae21908 1551 if (dst + msglen <= dst_end)
4ed46869
KH
1552 {
1553 bcopy (msg, dst, msglen);
1554 dst += msglen;
1555 }
1556
1557 for (j = 0; j < CCL_DEBUG_BACKTRACE_LEN; j++, i--)
1558 {
1559 if (i < 0) i = CCL_DEBUG_BACKTRACE_LEN - 1;
1560 if (ccl_backtrace_table[i] == 0)
1561 break;
1562 sprintf(msg, " %d", ccl_backtrace_table[i]);
1563 msglen = strlen (msg);
6ae21908 1564 if (dst + msglen > dst_end)
4ed46869
KH
1565 break;
1566 bcopy (msg, dst, msglen);
1567 dst += msglen;
1568 }
1569 }
4ed46869 1570#endif
887bfbd7 1571 goto ccl_finish;
4ed46869
KH
1572
1573 case CCL_STAT_QUIT:
1574 sprintf(msg, "\nCCL: Quited.");
1575 break;
1576
1577 default:
1578 sprintf(msg, "\nCCL: Unknown error type (%d).", ccl->status);
1579 }
1580
1581 msglen = strlen (msg);
6ae21908 1582 if (dst + msglen <= dst_end)
4ed46869
KH
1583 {
1584 bcopy (msg, dst, msglen);
1585 dst += msglen;
1586 }
1587 }
1588
1589 ccl_finish:
1590 ccl->ic = ic;
1591 if (consumed) *consumed = src - source;
1592 return dst - destination;
1593}
1594
1595/* Setup fields of the structure pointed by CCL appropriately for the
1596 execution of compiled CCL code in VEC (vector of integer). */
07478155 1597void
4ed46869
KH
1598setup_ccl_program (ccl, vec)
1599 struct ccl_program *ccl;
1600 Lisp_Object vec;
1601{
1602 int i;
1603
1604 ccl->size = XVECTOR (vec)->size;
1605 ccl->prog = XVECTOR (vec)->contents;
1606 ccl->ic = CCL_HEADER_MAIN;
1607 ccl->eof_ic = XINT (XVECTOR (vec)->contents[CCL_HEADER_EOF]);
1608 ccl->buf_magnification = XINT (XVECTOR (vec)->contents[CCL_HEADER_BUF_MAG]);
1609 for (i = 0; i < 8; i++)
1610 ccl->reg[i] = 0;
1611 ccl->last_block = 0;
e34b1164 1612 ccl->private_state = 0;
4ed46869
KH
1613 ccl->status = 0;
1614}
1615
6ae21908
KH
1616/* Resolve symbols in the specified CCL code (Lisp vector). This
1617 function converts translation-table and unification-table symbols
1618 embeded in the CCL code into their ID numbers. */
1619
1620Lisp_Object
1621resolve_symbol_ccl_program (ccl)
1622 Lisp_Object ccl;
1623{
1624 int i, veclen;
1625 Lisp_Object result, contents, prop;
1626
1627 result = ccl;
1628 veclen = XVECTOR (result)->size;
1629
1630 /* Set CCL program's table ID */
1631 for (i = 0; i < veclen; i++)
1632 {
1633 contents = XVECTOR (result)->contents[i];
1634 if (SYMBOLP (contents))
1635 {
1636 if (EQ(result, ccl))
1637 result = Fcopy_sequence (ccl);
1638
1639 prop = Fget (contents, Qunification_table_id);
1640 if (NUMBERP (prop))
1641 {
1642 XVECTOR (result)->contents[i] = prop;
1643 continue;
1644 }
1645 prop = Fget (contents, Qccl_translation_table_id);
1646 if (NUMBERP (prop))
1647 {
1648 XVECTOR (result)->contents[i] = prop;
1649 continue;
1650 }
1651 prop = Fget (contents, Qccl_program_idx);
1652 if (NUMBERP (prop))
1653 {
1654 XVECTOR (result)->contents[i] = prop;
1655 continue;
1656 }
1657 }
1658 }
1659
1660 return result;
1661}
1662
1663
4ed46869
KH
1664#ifdef emacs
1665
1666DEFUN ("ccl-execute", Fccl_execute, Sccl_execute, 2, 2, 0,
1667 "Execute CCL-PROGRAM with registers initialized by REGISTERS.\n\
6ae21908
KH
1668\n\
1669CCL-PROGRAM is a symbol registered by register-ccl-program,\n\
1670or a compiled code generated by `ccl-compile' (for backward compatibility,\n\
1671in this case, the execution is slower).\n\
1672No I/O commands should appear in CCL-PROGRAM.\n\
1673\n\
4ed46869
KH
1674REGISTERS is a vector of [R0 R1 ... R7] where RN is an initial value\n\
1675 of Nth register.\n\
6ae21908
KH
1676\n\
1677As side effect, each element of REGISTERS holds the value of\n\
4ed46869
KH
1678 corresponding register after the execution.")
1679 (ccl_prog, reg)
1680 Lisp_Object ccl_prog, reg;
1681{
1682 struct ccl_program ccl;
1683 int i;
6ae21908 1684 Lisp_Object ccl_id;
4ed46869 1685
6ae21908
KH
1686 if ((SYMBOLP (ccl_prog)) &&
1687 (!NILP (ccl_id = Fget (ccl_prog, Qccl_program_idx))))
1688 {
1689 ccl_prog = XVECTOR (Vccl_program_table)->contents[XUINT (ccl_id)];
1690 CHECK_LIST (ccl_prog, 0);
1691 ccl_prog = XCONS (ccl_prog)->cdr;
1692 CHECK_VECTOR (ccl_prog, 1);
1693 }
1694 else
1695 {
1696 CHECK_VECTOR (ccl_prog, 1);
1697 ccl_prog = resolve_symbol_ccl_program (ccl_prog);
1698 }
1699
1700 CHECK_VECTOR (reg, 2);
4ed46869
KH
1701 if (XVECTOR (reg)->size != 8)
1702 error ("Invalid length of vector REGISTERS");
1703
1704 setup_ccl_program (&ccl, ccl_prog);
1705 for (i = 0; i < 8; i++)
1706 ccl.reg[i] = (INTEGERP (XVECTOR (reg)->contents[i])
1707 ? XINT (XVECTOR (reg)->contents[i])
1708 : 0);
1709
1710 ccl_driver (&ccl, (char *)0, (char *)0, 0, 0, (int *)0);
1711 QUIT;
1712 if (ccl.status != CCL_STAT_SUCCESS)
1713 error ("Error in CCL program at %dth code", ccl.ic);
1714
1715 for (i = 0; i < 8; i++)
1716 XSETINT (XVECTOR (reg)->contents[i], ccl.reg[i]);
1717 return Qnil;
1718}
1719
1720DEFUN ("ccl-execute-on-string", Fccl_execute_on_string, Sccl_execute_on_string,
39a68837 1721 3, 5, 0,
4ed46869 1722 "Execute CCL-PROGRAM with initial STATUS on STRING.\n\
6ae21908
KH
1723\n\
1724CCL-PROGRAM is a symbol registered by register-ccl-program,\n\
1725or a compiled code generated by `ccl-compile' (for backward compatibility,\n\
1726in this case, the execution is slower).\n\
1727\n\
4ed46869 1728Read buffer is set to STRING, and write buffer is allocated automatically.\n\
6ae21908 1729\n\
4ed46869
KH
1730STATUS is a vector of [R0 R1 ... R7 IC], where\n\
1731 R0..R7 are initial values of corresponding registers,\n\
1732 IC is the instruction counter specifying from where to start the program.\n\
1733If R0..R7 are nil, they are initialized to 0.\n\
1734If IC is nil, it is initialized to head of the CCL program.\n\
39a68837 1735\n\
6ae21908 1736If optional 4th arg CONTINUE is non-nil, keep IC on read operation\n\
cb5373dd 1737when read buffer is exausted, else, IC is always set to the end of\n\
db6089c5 1738CCL-PROGRAM on exit.\n\
39a68837
KH
1739\n\
1740It returns the contents of write buffer as a string,\n\
6ae21908 1741 and as side effect, STATUS is updated.\n\
39a68837
KH
1742If the optional 5th arg UNIBYTE-P is non-nil, the returned string\n\
1743is a unibyte string. By default it is a multibyte string.")
1744 (ccl_prog, status, str, contin, unibyte_p)
1745 Lisp_Object ccl_prog, status, str, contin, unibyte_p;
4ed46869
KH
1746{
1747 Lisp_Object val;
1748 struct ccl_program ccl;
1749 int i, produced;
1750 int outbufsize;
1751 char *outbuf;
1752 struct gcpro gcpro1, gcpro2, gcpro3;
6ae21908
KH
1753 Lisp_Object ccl_id;
1754
1755 if ((SYMBOLP (ccl_prog)) &&
1756 (!NILP (ccl_id = Fget (ccl_prog, Qccl_program_idx))))
1757 {
1758 ccl_prog = XVECTOR (Vccl_program_table)->contents[XUINT (ccl_id)];
1759 CHECK_LIST (ccl_prog, 0);
1760 ccl_prog = XCONS (ccl_prog)->cdr;
1761 CHECK_VECTOR (ccl_prog, 1);
1762 }
1763 else
1764 {
1765 CHECK_VECTOR (ccl_prog, 1);
1766 ccl_prog = resolve_symbol_ccl_program (ccl_prog);
1767 }
4ed46869 1768
4ed46869
KH
1769 CHECK_VECTOR (status, 1);
1770 if (XVECTOR (status)->size != 9)
1771 error ("Invalid length of vector STATUS");
1772 CHECK_STRING (str, 2);
1773 GCPRO3 (ccl_prog, status, str);
1774
1775 setup_ccl_program (&ccl, ccl_prog);
1776 for (i = 0; i < 8; i++)
1777 {
1778 if (NILP (XVECTOR (status)->contents[i]))
1779 XSETINT (XVECTOR (status)->contents[i], 0);
1780 if (INTEGERP (XVECTOR (status)->contents[i]))
1781 ccl.reg[i] = XINT (XVECTOR (status)->contents[i]);
1782 }
1783 if (INTEGERP (XVECTOR (status)->contents[i]))
1784 {
1785 i = XFASTINT (XVECTOR (status)->contents[8]);
1786 if (ccl.ic < i && i < ccl.size)
1787 ccl.ic = i;
1788 }
fc932ac6 1789 outbufsize = STRING_BYTES (XSTRING (str)) * ccl.buf_magnification + 256;
4ed46869
KH
1790 outbuf = (char *) xmalloc (outbufsize);
1791 if (!outbuf)
1792 error ("Not enough memory");
cb5373dd 1793 ccl.last_block = NILP (contin);
4ed46869 1794 produced = ccl_driver (&ccl, XSTRING (str)->data, outbuf,
fc932ac6 1795 STRING_BYTES (XSTRING (str)), outbufsize, (int *)0);
4ed46869
KH
1796 for (i = 0; i < 8; i++)
1797 XSET (XVECTOR (status)->contents[i], Lisp_Int, ccl.reg[i]);
1798 XSETINT (XVECTOR (status)->contents[8], ccl.ic);
1799 UNGCPRO;
1800
39a68837
KH
1801 if (NILP (unibyte_p))
1802 val = make_string (outbuf, produced);
1803 else
1804 val = make_unibyte_string (outbuf, produced);
4ed46869
KH
1805 free (outbuf);
1806 QUIT;
1807 if (ccl.status != CCL_STAT_SUCCESS
e34b1164
KH
1808 && ccl.status != CCL_STAT_SUSPEND_BY_SRC
1809 && ccl.status != CCL_STAT_SUSPEND_BY_DST)
4ed46869
KH
1810 error ("Error in CCL program at %dth code", ccl.ic);
1811
1812 return val;
1813}
1814
1815DEFUN ("register-ccl-program", Fregister_ccl_program, Sregister_ccl_program,
1816 2, 2, 0,
7bce92a6
KH
1817 "Register CCL program PROGRAM of NAME in `ccl-program-table'.\n\
1818PROGRAM should be a compiled code of CCL program, or nil.\n\
4ed46869
KH
1819Return index number of the registered CCL program.")
1820 (name, ccl_prog)
1821 Lisp_Object name, ccl_prog;
1822{
1823 int len = XVECTOR (Vccl_program_table)->size;
e34b1164 1824 int i;
4ed46869
KH
1825
1826 CHECK_SYMBOL (name, 0);
1827 if (!NILP (ccl_prog))
6ae21908
KH
1828 {
1829 CHECK_VECTOR (ccl_prog, 1);
1830 ccl_prog = resolve_symbol_ccl_program (ccl_prog);
1831 }
4ed46869
KH
1832
1833 for (i = 0; i < len; i++)
1834 {
1835 Lisp_Object slot = XVECTOR (Vccl_program_table)->contents[i];
1836
1837 if (!CONSP (slot))
1838 break;
1839
1840 if (EQ (name, XCONS (slot)->car))
1841 {
1842 XCONS (slot)->cdr = ccl_prog;
1843 return make_number (i);
1844 }
1845 }
1846
1847 if (i == len)
1848 {
6703ac4f 1849 Lisp_Object new_table = Fmake_vector (make_number (len * 2), Qnil);
4ed46869
KH
1850 int j;
1851
1852 for (j = 0; j < len; j++)
1853 XVECTOR (new_table)->contents[j]
1854 = XVECTOR (Vccl_program_table)->contents[j];
1855 Vccl_program_table = new_table;
1856 }
1857
1858 XVECTOR (Vccl_program_table)->contents[i] = Fcons (name, ccl_prog);
b23c2440 1859 Fput (name, Qccl_program_idx, make_number (i));
4ed46869
KH
1860 return make_number (i);
1861}
1862
e34b1164
KH
1863/* register CCL translation table.
1864 CCL translation table consists of numbers and Qt and Qnil and Qlambda.
1865 The first element is start code point.
1866 The rest elements are translated numbers.
1867 Qt shows that an original number before translation.
1868 Qnil shows that an empty element.
1869 Qlambda makes translation stopped.
1870*/
1871
1872DEFUN ("register-ccl-translation-table", Fregister_ccl_translation_table,
1873 Sregister_ccl_translation_table,
1874 2, 2, 0,
1875 "Register CCL translation table.\n\
1876TABLE should be a vector. SYMBOL is used for pointing the translation table out.\n\
1877Return index number of the registered translation table.")
1878 (symbol, table)
1879 Lisp_Object symbol, table;
1880{
1881 int len = XVECTOR (Vccl_translation_table_vector)->size;
1882 int i;
1883 Lisp_Object index;
1884
1885 CHECK_SYMBOL (symbol, 0);
1886 CHECK_VECTOR (table, 1);
1887
1888 for (i = 0; i < len; i++)
1889 {
1890 Lisp_Object slot = XVECTOR (Vccl_translation_table_vector)->contents[i];
1891
1892 if (!CONSP (slot))
1893 break;
1894
1895 if (EQ (symbol, XCONS (slot)->car))
1896 {
1897 index = make_number (i);
1898 XCONS (slot)->cdr = table;
1899 Fput (symbol, Qccl_translation_table, table);
1900 Fput (symbol, Qccl_translation_table_id, index);
1901 return index;
1902 }
1903 }
1904
1905 if (i == len)
1906 {
1907 Lisp_Object new_vector = Fmake_vector (make_number (len * 2), Qnil);
1908 int j;
1909
1910 for (j = 0; j < len; j++)
1911 XVECTOR (new_vector)->contents[j]
1912 = XVECTOR (Vccl_translation_table_vector)->contents[j];
1913 Vccl_translation_table_vector = new_vector;
1914 }
1915
1916 index = make_number (i);
1917 Fput (symbol, Qccl_translation_table, table);
1918 Fput (symbol, Qccl_translation_table_id, index);
1919 XVECTOR (Vccl_translation_table_vector)->contents[i] = Fcons (symbol, table);
1920 return index;
1921}
1922
1923
dfcf069d 1924void
4ed46869
KH
1925syms_of_ccl ()
1926{
1927 staticpro (&Vccl_program_table);
6703ac4f 1928 Vccl_program_table = Fmake_vector (make_number (32), Qnil);
4ed46869 1929
6ae21908
KH
1930 Qccl_program = intern ("ccl-program");
1931 staticpro (&Qccl_program);
1932
1933 Qccl_program_idx = intern ("ccl-program-idx");
1934 staticpro (&Qccl_program_idx);
e34b1164
KH
1935
1936 Qccl_translation_table = intern ("ccl-translation-table");
1937 staticpro (&Qccl_translation_table);
1938
1939 Qccl_translation_table_id = intern ("ccl-translation-table-id");
1940 staticpro (&Qccl_translation_table_id);
1941
6ae21908
KH
1942 Qunification_table = intern ("unification-table");
1943 staticpro (&Qunification_table);
1944
1945 Qunification_table_id = intern ("unification-table-id");
1946 staticpro (&Qunification_table_id);
1947
e34b1164
KH
1948 DEFVAR_LISP ("ccl-translation-table-vector", &Vccl_translation_table_vector,
1949 "Where is stored translation tables for CCL program.\n\
1950Because CCL program can't access these tables except by the index of the vector.");
d387866a 1951 Vccl_translation_table_vector = Fmake_vector (make_number (16), Qnil);
e34b1164 1952
4ed46869
KH
1953 DEFVAR_LISP ("font-ccl-encoder-alist", &Vfont_ccl_encoder_alist,
1954 "Alist of fontname patterns vs corresponding CCL program.\n\
1955Each element looks like (REGEXP . CCL-CODE),\n\
1956 where CCL-CODE is a compiled CCL program.\n\
1957When a font whose name matches REGEXP is used for displaying a character,\n\
1958 CCL-CODE is executed to calculate the code point in the font\n\
1959 from the charset number and position code(s) of the character which are set\n\
1960 in CCL registers R0, R1, and R2 before the execution.\n\
1961The code point in the font is set in CCL registers R1 and R2\n\
1962 when the execution terminated.\n\
1963If the font is single-byte font, the register R2 is not used.");
1964 Vfont_ccl_encoder_alist = Qnil;
1965
1966 defsubr (&Sccl_execute);
1967 defsubr (&Sccl_execute_on_string);
1968 defsubr (&Sregister_ccl_program);
e34b1164 1969 defsubr (&Sregister_ccl_translation_table);
4ed46869
KH
1970}
1971
1972#endif /* emacs */