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