(ccl_driver): Don't define `CCL_ReadMultibyteChar2' in UTF-2000
[chise/xemacs-chise.git] / 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 "character.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;
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 #ifndef UTF2000
1121             case CCL_ReadMultibyteChar2:
1122               if (!src)
1123                 CCL_INVALID_CMD;
1124
1125               do {
1126                 if (src >= src_end)
1127                   {
1128                     src++;
1129                     goto ccl_read_multibyte_character_suspend;
1130                   }
1131               
1132                 i = *src++;
1133 #if 0
1134                 if (i == LEADING_CODE_COMPOSITION)
1135                   {
1136                     if (src >= src_end)
1137                       goto ccl_read_multibyte_character_suspend;
1138                     if (*src == 0xFF)
1139                       {
1140                         ccl->private_state = COMPOSING_WITH_RULE_HEAD;
1141                         src++;
1142                       }
1143                     else
1144                       ccl->private_state = COMPOSING_NO_RULE_HEAD;
1145
1146                     continue;
1147                   }
1148                 if (ccl->private_state != COMPOSING_NO)
1149                   {
1150                     /* composite character */
1151                     if (i < 0xA0)
1152                       ccl->private_state = COMPOSING_NO;
1153                     else
1154                       {
1155                         if (COMPOSING_WITH_RULE_RULE == ccl->private_state)
1156                           {
1157                             ccl->private_state = COMPOSING_WITH_RULE_HEAD;
1158                             continue;
1159                           }
1160                         else if (COMPOSING_WITH_RULE_HEAD == ccl->private_state)
1161                           ccl->private_state = COMPOSING_WITH_RULE_RULE;
1162
1163                         if (i == 0xA0)
1164                           {
1165                             if (src >= src_end)
1166                               goto ccl_read_multibyte_character_suspend;
1167                             i = *src++ & 0x7F;
1168                           }
1169                         else
1170                           i -= 0x20;
1171                       }
1172                   }
1173 #endif
1174
1175                 if (i < 0x80)
1176                   {
1177                     /* ASCII */
1178                     reg[rrr] = i;
1179                     reg[RRR] = LEADING_BYTE_ASCII;
1180                   }
1181                 else if (i <= MAX_LEADING_BYTE_OFFICIAL_1)
1182                   {
1183                     if (src >= src_end)
1184                       goto ccl_read_multibyte_character_suspend;
1185                     reg[RRR] = i;
1186                     reg[rrr] = (*src++ & 0x7F);
1187                   }
1188                 else if (i <= MAX_LEADING_BYTE_OFFICIAL_2)
1189                   {
1190                     if ((src + 1) >= src_end)
1191                       goto ccl_read_multibyte_character_suspend;
1192                     reg[RRR] = i;
1193                     i = (*src++ & 0x7F);
1194                     reg[rrr] = ((i << 7) | (*src & 0x7F));
1195                     src++;
1196                   }
1197                 else if (i == PRE_LEADING_BYTE_PRIVATE_1)
1198                   {
1199                     if ((src + 1) >= src_end)
1200                       goto ccl_read_multibyte_character_suspend;
1201                     reg[RRR] = *src++;
1202                     reg[rrr] = (*src++ & 0x7F);
1203                   }
1204                 else if (i == PRE_LEADING_BYTE_PRIVATE_2)
1205                   {
1206                     if ((src + 2) >= src_end)
1207                       goto ccl_read_multibyte_character_suspend;
1208                     reg[RRR] = *src++;
1209                     i = (*src++ & 0x7F);
1210                     reg[rrr] = ((i << 7) | (*src & 0x7F));
1211                     src++;
1212                   }
1213                 else
1214                   {
1215                     /* INVALID CODE.  Return a single byte character.  */
1216                     reg[RRR] = LEADING_BYTE_ASCII;
1217                     reg[rrr] = i;
1218                   }
1219                 break;
1220               } while (1);
1221               break;
1222
1223             ccl_read_multibyte_character_suspend:
1224               src--;
1225               if (ccl->last_block)
1226                 {
1227                   ic = ccl->eof_ic;
1228                   goto ccl_repeat;
1229                 }
1230               else
1231                 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC);
1232
1233               break;
1234 #endif
1235
1236             case CCL_WriteMultibyteChar2:
1237               i = reg[RRR]; /* charset */
1238               if (i == LEADING_BYTE_ASCII)
1239                 i = reg[rrr] & 0xFF;
1240 #if 0
1241               else if (i == CHARSET_COMPOSITION)
1242                 i = MAKE_COMPOSITE_CHAR (reg[rrr]);
1243 #endif
1244               else if (XCHARSET_DIMENSION (CHARSET_BY_LEADING_BYTE (i)) == 1)
1245                 i = ((i - FIELD2_TO_OFFICIAL_LEADING_BYTE) << 7)
1246                   | (reg[rrr] & 0x7F);
1247               else if (i < MIN_LEADING_BYTE_OFFICIAL_2)
1248                 i = ((i - FIELD1_TO_OFFICIAL_LEADING_BYTE) << 14) | reg[rrr];
1249               else
1250                 i = ((i - FIELD1_TO_PRIVATE_LEADING_BYTE) << 14) | reg[rrr];
1251
1252               CCL_WRITE_CHAR (i);
1253
1254               break;
1255
1256 #if 0
1257             case CCL_TranslateCharacter:
1258               i = reg[RRR]; /* charset */
1259               if (i == LEADING_BYTE_ASCII)
1260                 i = reg[rrr];
1261               else if (i == CHARSET_COMPOSITION)
1262                 {
1263                   reg[RRR] = -1;
1264                   break;
1265                 }
1266               else if (CHARSET_DIMENSION (i) == 1)
1267                 i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F);
1268               else if (i < MIN_LEADING_BYTE_OFFICIAL_2)
1269                 i = ((i - 0x8F) << 14) | (reg[rrr] & 0x3FFF);
1270               else
1271                 i = ((i - 0xE0) << 14) | (reg[rrr] & 0x3FFF);
1272
1273               op = translate_char (GET_TRANSLATION_TABLE (reg[Rrr]),
1274                                    i, -1, 0, 0);
1275               SPLIT_CHAR (op, reg[RRR], i, j);
1276               if (j != -1)
1277                 i = (i << 7) | j;
1278               
1279               reg[rrr] = i;
1280               break;
1281
1282             case CCL_TranslateCharacterConstTbl:
1283               op = XINT (ccl_prog[ic]); /* table */
1284               ic++;
1285               i = reg[RRR]; /* charset */
1286               if (i == LEADING_BYTE_ASCII)
1287                 i = reg[rrr];
1288               else if (i == CHARSET_COMPOSITION)
1289                 {
1290                   reg[RRR] = -1;
1291                   break;
1292                 }
1293               else if (CHARSET_DIMENSION (i) == 1)
1294                 i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F);
1295               else if (i < MIN_LEADING_BYTE_OFFICIAL_2)
1296                 i = ((i - 0x8F) << 14) | (reg[rrr] & 0x3FFF);
1297               else
1298                 i = ((i - 0xE0) << 14) | (reg[rrr] & 0x3FFF);
1299
1300               op = translate_char (GET_TRANSLATION_TABLE (op), i, -1, 0, 0);
1301               SPLIT_CHAR (op, reg[RRR], i, j);
1302               if (j != -1)
1303                 i = (i << 7) | j;
1304               
1305               reg[rrr] = i;
1306               break;
1307
1308             case CCL_IterateMultipleMap:
1309               {
1310                 Lisp_Object map, content, attrib, value;
1311                 int point, size, fin_ic;
1312
1313                 j = XINT (ccl_prog[ic++]); /* number of maps. */
1314                 fin_ic = ic + j;
1315                 op = reg[rrr];
1316                 if ((j > reg[RRR]) && (j >= 0))
1317                   {
1318                     ic += reg[RRR];
1319                     i = reg[RRR];
1320                   }
1321                 else
1322                   {
1323                     reg[RRR] = -1;
1324                     ic = fin_ic;
1325                     break;
1326                   }
1327
1328                 for (;i < j;i++)
1329                   {
1330
1331                     size = XVECTOR (Vcode_conversion_map_vector)->size;
1332                     point = XINT (ccl_prog[ic++]);
1333                     if (point >= size) continue;
1334                     map =
1335                       XVECTOR (Vcode_conversion_map_vector)->contents[point];
1336
1337                     /* Check map varidity.  */
1338                     if (!CONSP (map)) continue;
1339                     map = XCONS(map)->cdr;
1340                     if (!VECTORP (map)) continue;
1341                     size = XVECTOR (map)->size;
1342                     if (size <= 1) continue;
1343
1344                     content = XVECTOR (map)->contents[0];
1345
1346                     /* check map type,
1347                        [STARTPOINT VAL1 VAL2 ...] or
1348                        [t ELELMENT STARTPOINT ENDPOINT]  */
1349                     if (NUMBERP (content))
1350                       {
1351                         point = XUINT (content);
1352                         point = op - point + 1;
1353                         if (!((point >= 1) && (point < size))) continue;
1354                         content = XVECTOR (map)->contents[point];
1355                       }
1356                     else if (EQ (content, Qt))
1357                       {
1358                         if (size != 4) continue;
1359                         if ((op >= XUINT (XVECTOR (map)->contents[2]))
1360                             && (op < XUINT (XVECTOR (map)->contents[3])))
1361                           content = XVECTOR (map)->contents[1];
1362                         else
1363                           continue;
1364                       }
1365                     else 
1366                       continue;
1367
1368                     if (NILP (content))
1369                       continue;
1370                     else if (NUMBERP (content))
1371                       {
1372                         reg[RRR] = i;
1373                         reg[rrr] = XINT(content);
1374                         break;
1375                       }
1376                     else if (EQ (content, Qt) || EQ (content, Qlambda))
1377                       {
1378                         reg[RRR] = i;
1379                         break;
1380                       }
1381                     else if (CONSP (content))
1382                       {
1383                         attrib = XCONS (content)->car;
1384                         value = XCONS (content)->cdr;
1385                         if (!NUMBERP (attrib) || !NUMBERP (value))
1386                           continue;
1387                         reg[RRR] = i;
1388                         reg[rrr] = XUINT (value);
1389                         break;
1390                       }
1391                   }
1392                 if (i == j)
1393                   reg[RRR] = -1;
1394                 ic = fin_ic;
1395               }
1396               break;
1397               
1398             case CCL_MapMultiple:
1399               {
1400                 Lisp_Object map, content, attrib, value;
1401                 int point, size, map_vector_size;
1402                 int map_set_rest_length, fin_ic;
1403
1404                 map_set_rest_length =
1405                   XINT (ccl_prog[ic++]); /* number of maps and separators. */
1406                 fin_ic = ic + map_set_rest_length;
1407                 if ((map_set_rest_length > reg[RRR]) && (reg[RRR] >= 0))
1408                   {
1409                     ic += reg[RRR];
1410                     i = reg[RRR];
1411                     map_set_rest_length -= i;
1412                   }
1413                 else
1414                   {
1415                     ic = fin_ic;
1416                     reg[RRR] = -1;
1417                     break;
1418                   }
1419                 mapping_stack_pointer = mapping_stack;
1420                 op = reg[rrr];
1421                 PUSH_MAPPING_STACK (0, op);
1422                 reg[RRR] = -1;
1423                 map_vector_size = XVECTOR (Vcode_conversion_map_vector)->size;
1424                 for (;map_set_rest_length > 0;i++, map_set_rest_length--)
1425                   {
1426                     point = XINT(ccl_prog[ic++]);
1427                     if (point < 0)
1428                       {
1429                         point = -point;
1430                         if (mapping_stack_pointer
1431                             >= &mapping_stack[MAX_MAP_SET_LEVEL])
1432                           {
1433                             CCL_INVALID_CMD;
1434                           }
1435                         PUSH_MAPPING_STACK (map_set_rest_length - point,
1436                                             reg[rrr]);
1437                         map_set_rest_length = point + 1;
1438                         reg[rrr] = op;
1439                         continue;
1440                       }
1441
1442                     if (point >= map_vector_size) continue;
1443                     map = (XVECTOR (Vcode_conversion_map_vector)
1444                            ->contents[point]);
1445
1446                     /* Check map varidity.  */
1447                     if (!CONSP (map)) continue;
1448                     map = XCONS (map)->cdr;
1449                     if (!VECTORP (map)) continue;
1450                     size = XVECTOR (map)->size;
1451                     if (size <= 1) continue;
1452
1453                     content = XVECTOR (map)->contents[0];
1454
1455                     /* check map type,
1456                        [STARTPOINT VAL1 VAL2 ...] or
1457                        [t ELEMENT STARTPOINT ENDPOINT]  */
1458                     if (NUMBERP (content))
1459                       {
1460                         point = XUINT (content);
1461                         point = op - point + 1;
1462                         if (!((point >= 1) && (point < size))) continue;
1463                         content = XVECTOR (map)->contents[point];
1464                       }
1465                     else if (EQ (content, Qt))
1466                       {
1467                         if (size != 4) continue;
1468                         if ((op >= XUINT (XVECTOR (map)->contents[2])) &&
1469                             (op < XUINT (XVECTOR (map)->contents[3])))
1470                           content = XVECTOR (map)->contents[1];
1471                         else
1472                           continue;
1473                       }
1474                     else 
1475                       continue;
1476
1477                     if (NILP (content))
1478                       continue;
1479                     else if (NUMBERP (content))
1480                       {
1481                         op = XINT (content);
1482                         reg[RRR] = i;
1483                         i += map_set_rest_length;
1484                         POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1485                       }
1486                     else if (CONSP (content))
1487                       {
1488                         attrib = XCONS (content)->car;
1489                         value = XCONS (content)->cdr;
1490                         if (!NUMBERP (attrib) || !NUMBERP (value))
1491                           continue;
1492                         reg[RRR] = i;
1493                         op = XUINT (value);
1494                         i += map_set_rest_length;
1495                         POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1496                       }
1497                     else if (EQ (content, Qt))
1498                       {
1499                         reg[RRR] = i;
1500                         op = reg[rrr];
1501                         i += map_set_rest_length;
1502                         POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1503                       }
1504                     else if (EQ (content, Qlambda))
1505                       {
1506                         break;
1507                       }
1508                     else
1509                       CCL_INVALID_CMD;
1510                   }
1511                 ic = fin_ic;
1512               }
1513               reg[rrr] = op;
1514               break;
1515
1516             case CCL_MapSingle:
1517               {
1518                 Lisp_Object map, attrib, value, content;
1519                 int size, point;
1520                 j = XINT (ccl_prog[ic++]); /* map_id */
1521                 op = reg[rrr];
1522                 if (j >= XVECTOR (Vcode_conversion_map_vector)->size)
1523                   {
1524                     reg[RRR] = -1;
1525                     break;
1526                   }
1527                 map = XVECTOR (Vcode_conversion_map_vector)->contents[j];
1528                 if (!CONSP (map))
1529                   {
1530                     reg[RRR] = -1;
1531                     break;
1532                   }
1533                 map = XCONS(map)->cdr;
1534                 if (!VECTORP (map))
1535                   {
1536                     reg[RRR] = -1;
1537                     break;
1538                   }
1539                 size = XVECTOR (map)->size;
1540                 point = XUINT (XVECTOR (map)->contents[0]);
1541                 point = op - point + 1;
1542                 reg[RRR] = 0;
1543                 if ((size <= 1) ||
1544                     (!((point >= 1) && (point < size))))
1545                   reg[RRR] = -1;
1546                 else
1547                   {
1548                     content = XVECTOR (map)->contents[point];
1549                     if (NILP (content))
1550                       reg[RRR] = -1;
1551                     else if (NUMBERP (content))
1552                       reg[rrr] = XINT (content);
1553                     else if (EQ (content, Qt))
1554                       reg[RRR] = i;
1555                     else if (CONSP (content))
1556                       {
1557                         attrib = XCONS (content)->car;
1558                         value = XCONS (content)->cdr;
1559                         if (!NUMBERP (attrib) || !NUMBERP (value))
1560                           continue;
1561                         reg[rrr] = XUINT(value);
1562                         break;
1563                       }
1564                     else
1565                       reg[RRR] = -1;
1566                   }
1567               }
1568               break;
1569 #endif
1570               
1571             default:
1572               CCL_INVALID_CMD;
1573             }
1574           break;
1575
1576         default:
1577           ccl->status = CCL_STAT_INVALID_CMD;
1578           goto ccl_error_handler;
1579         }
1580     }
1581
1582  ccl_error_handler:
1583   if (destination)
1584     {
1585       /* We can insert an error message only if DESTINATION is
1586          specified and we still have a room to store the message
1587          there.  */
1588       char msg[256];
1589
1590 #if 0 /* not for XEmacs ? */
1591       if (!dst)
1592         dst = destination;
1593 #endif
1594
1595       switch (ccl->status)
1596         {
1597           /* Terminate CCL program because of invalid command.
1598              Should not occur in the normal case.  */
1599         case CCL_STAT_INVALID_CMD:
1600           sprintf(msg, "\nCCL: Invalid command %x (ccl_code = %x) at %d.",
1601                   code & 0x1F, code, this_ic);
1602 #ifdef CCL_DEBUG
1603           {
1604             int i = ccl_backtrace_idx - 1;
1605             int j;
1606
1607             Dynarr_add_many (destination, (unsigned char *) msg, strlen (msg));
1608
1609             for (j = 0; j < CCL_DEBUG_BACKTRACE_LEN; j++, i--)
1610               {
1611                 if (i < 0) i = CCL_DEBUG_BACKTRACE_LEN - 1;
1612                 if (ccl_backtrace_table[i] == 0)
1613                   break;
1614                 sprintf(msg, " %d", ccl_backtrace_table[i]);
1615                 Dynarr_add_many (destination, (unsigned char *) msg, strlen (msg));
1616               }
1617             goto ccl_finish;
1618           }
1619 #endif
1620           break;
1621
1622         case CCL_STAT_QUIT:
1623           sprintf(msg, "\nCCL: Quited.");
1624           break;
1625
1626         default:
1627           sprintf(msg, "\nCCL: Unknown error type (%d).", ccl->status);
1628         }
1629
1630       Dynarr_add_many (destination, (unsigned char *) msg, strlen (msg));
1631     }
1632
1633  ccl_finish:
1634   ccl->ic = ic;
1635   ccl->stack_idx = stack_idx;
1636   ccl->prog = ccl_prog;
1637   if (consumed) *consumed = src - source;
1638   if (destination)
1639     return Dynarr_length (destination);
1640   else
1641     return 0;
1642 }
1643
1644 /* Setup fields of the structure pointed by CCL appropriately for the
1645    execution of compiled CCL code in VEC (vector of integer).
1646    If VEC is nil, we skip setting ups based on VEC.  */
1647 void
1648 setup_ccl_program (struct ccl_program *ccl, Lisp_Object vec)
1649 {
1650   int i;
1651
1652   if (VECTORP (vec))
1653     {
1654       ccl->size = XVECTOR_LENGTH (vec);
1655       ccl->prog = XVECTOR_DATA (vec);
1656       ccl->eof_ic = XINT (XVECTOR_DATA (vec)[CCL_HEADER_EOF]);
1657       ccl->buf_magnification = XINT (XVECTOR_DATA (vec)[CCL_HEADER_BUF_MAG]);
1658     }
1659   ccl->ic = CCL_HEADER_MAIN;
1660   for (i = 0; i < 8; i++)
1661     ccl->reg[i] = 0;
1662   ccl->last_block = 0;
1663   ccl->private_state = 0;
1664   ccl->status = 0;
1665   ccl->stack_idx = 0;
1666 }
1667
1668 /* Resolve symbols in the specified CCL code (Lisp vector).  This
1669    function converts symbols of code conversion maps and character
1670    translation tables embeded in the CCL code into their ID numbers.  */
1671
1672 Lisp_Object
1673 resolve_symbol_ccl_program (Lisp_Object ccl)
1674 {
1675   int i, veclen;
1676   Lisp_Object result, contents /*, prop */;
1677
1678   result = ccl;
1679   veclen = XVECTOR_LENGTH (result);
1680
1681   /* Set CCL program's table ID */
1682   for (i = 0; i < veclen; i++)
1683     {
1684       contents = XVECTOR_DATA (result)[i];
1685       if (SYMBOLP (contents))
1686         {
1687           if (EQ(result, ccl))
1688             result = Fcopy_sequence (ccl);
1689
1690 #if 0
1691           prop = Fget (contents, Qtranslation_table_id);
1692           if (NUMBERP (prop))
1693             {
1694               XVECTOR_DATA (result)[i] = prop;
1695               continue;
1696             }
1697           prop = Fget (contents, Qcode_conversion_map_id);
1698           if (NUMBERP (prop))
1699             {
1700               XVECTOR_DATA (result)[i] = prop;
1701               continue;
1702             }
1703           prop = Fget (contents, Qccl_program_idx);
1704           if (NUMBERP (prop))
1705             {
1706               XVECTOR_DATA (result)[i] = prop;
1707               continue;
1708             }
1709 #endif
1710         }
1711     }
1712
1713   return result;
1714 }
1715
1716
1717 #ifdef emacs
1718
1719 DEFUN ("ccl-execute", Fccl_execute, 2, 2, 0, /*
1720 Execute CCL-PROGRAM with registers initialized by REGISTERS.
1721
1722 CCL-PROGRAM is a symbol registered by register-ccl-program,
1723 or a compiled code generated by `ccl-compile' (for backward compatibility,
1724 in this case, the execution is slower).
1725 No I/O commands should appear in CCL-PROGRAM.
1726
1727 REGISTERS is a vector of [R0 R1 ... R7] where RN is an initial value
1728  of Nth register.
1729
1730 As side effect, each element of REGISTER holds the value of
1731  corresponding register after the execution.
1732 */
1733   (ccl_prog, reg))
1734 {
1735   struct ccl_program ccl;
1736   int i;
1737   Lisp_Object ccl_id;
1738
1739   if ((SYMBOLP (ccl_prog)) &&
1740       (!NILP (ccl_id = Fget (ccl_prog, Qccl_program_idx, Qnil))))
1741     {
1742       ccl_prog = XVECTOR_DATA (Vccl_program_table)[XUINT (ccl_id)];
1743       CHECK_LIST (ccl_prog);
1744       ccl_prog = XCDR (ccl_prog);
1745       CHECK_VECTOR (ccl_prog);
1746     }
1747   else
1748     {
1749       CHECK_VECTOR (ccl_prog);
1750       ccl_prog = resolve_symbol_ccl_program (ccl_prog);
1751     }
1752
1753   CHECK_VECTOR (reg);
1754   if (XVECTOR_LENGTH (reg) != 8)
1755     error ("Invalid length of vector REGISTERS");
1756
1757   setup_ccl_program (&ccl, ccl_prog);
1758   for (i = 0; i < 8; i++)
1759     ccl.reg[i] = (INTP (XVECTOR_DATA (reg)[i])
1760                   ? XINT (XVECTOR_DATA (reg)[i])
1761                   : 0);
1762
1763   ccl_driver (&ccl, (CONST unsigned char *)0, (unsigned_char_dynarr *)0,
1764               0, (int *)0, CCL_MODE_ENCODING);
1765   QUIT;
1766   if (ccl.status != CCL_STAT_SUCCESS)
1767     error ("Error in CCL program at %dth code", ccl.ic);
1768
1769   for (i = 0; i < 8; i++)
1770     XSETINT (XVECTOR_DATA (reg)[i], ccl.reg[i]);
1771   return Qnil;
1772 }
1773
1774 DEFUN ("ccl-execute-on-string", Fccl_execute_on_string, 3, 4, 0, /*
1775 Execute CCL-PROGRAM with initial STATUS on STRING.
1776
1777 CCL-PROGRAM is a symbol registered by register-ccl-program,
1778 or a compiled code generated by `ccl-compile' (for backward compatibility,
1779 in this case, the execution is slower).
1780
1781 Read buffer is set to STRING, and write buffer is allocated automatically.
1782
1783 If IC is nil, it is initialized to head of the CCL program.\n\
1784 STATUS is a vector of [R0 R1 ... R7 IC], where
1785  R0..R7 are initial values of corresponding registers,
1786  IC is the instruction counter specifying from where to start the program.
1787 If R0..R7 are nil, they are initialized to 0.
1788 If IC is nil, it is initialized to head of the CCL program.
1789
1790 If optional 4th arg CONTINUE is non-nil, keep IC on read operation
1791 when read buffer is exausted, else, IC is always set to the end of
1792 CCL-PROGRAM on exit.
1793
1794 It returns the contents of write buffer as a string,
1795  and as side effect, STATUS is updated.
1796 */
1797   (ccl_prog, status, str, contin))
1798 {
1799   Lisp_Object val;
1800   struct ccl_program ccl;
1801   int i, produced;
1802   unsigned_char_dynarr *outbuf;
1803   struct gcpro gcpro1, gcpro2, gcpro3;
1804   Lisp_Object ccl_id;
1805
1806   if ((SYMBOLP (ccl_prog)) &&
1807       (!NILP (ccl_id = Fget (ccl_prog, Qccl_program_idx, Qnil))))
1808     {
1809       ccl_prog = XVECTOR (Vccl_program_table)->contents[XUINT (ccl_id)];
1810       CHECK_LIST (ccl_prog);
1811       ccl_prog = XCDR (ccl_prog);
1812       CHECK_VECTOR (ccl_prog);
1813     }
1814   else
1815     {
1816       CHECK_VECTOR (ccl_prog);
1817       ccl_prog = resolve_symbol_ccl_program (ccl_prog);
1818     }
1819
1820   CHECK_VECTOR (status);
1821   if (XVECTOR_LENGTH (status) != 9)
1822     signal_simple_error ("Vector should be of length 9", status);
1823   CHECK_STRING (str);
1824   GCPRO3 (ccl_prog, status, str);
1825
1826   setup_ccl_program (&ccl, ccl_prog);
1827   for (i = 0; i < 8; i++)
1828     {
1829       if (NILP (XVECTOR_DATA (status)[i]))
1830         XSETINT (XVECTOR_DATA (status)[i], 0);
1831       if (INTP (XVECTOR_DATA (status)[i]))
1832         ccl.reg[i] = XINT (XVECTOR_DATA (status)[i]);
1833     }
1834   if (INTP (XVECTOR_DATA (status)[8]))
1835     {
1836       i = XINT (XVECTOR_DATA (status)[8]);
1837       if (ccl.ic < i && i < ccl.size)
1838         ccl.ic = i;
1839     }
1840   outbuf = Dynarr_new (unsigned_char);
1841   ccl.last_block = NILP (contin);
1842   produced = ccl_driver (&ccl, XSTRING_DATA (str), outbuf,
1843                          XSTRING_LENGTH (str), (int *)0, CCL_MODE_ENCODING);
1844   for (i = 0; i < 8; i++)
1845     XVECTOR_DATA (status)[i] = make_int(ccl.reg[i]);
1846   XSETINT (XVECTOR_DATA (status)[8], ccl.ic);
1847   UNGCPRO;
1848
1849   val = make_string (Dynarr_atp (outbuf, 0), produced);
1850   Dynarr_free (outbuf);
1851   QUIT;
1852   if (ccl.status != CCL_STAT_SUCCESS
1853       && ccl.status != CCL_STAT_SUSPEND_BY_SRC
1854       && ccl.status != CCL_STAT_SUSPEND_BY_DST)
1855     error ("Error in CCL program at %dth code", ccl.ic);
1856
1857   return val;
1858 }
1859
1860 DEFUN ("register-ccl-program", Fregister_ccl_program, 2, 2, 0, /*
1861 Register CCL program PROGRAM of NAME in `ccl-program-table'.
1862 PROGRAM should be a compiled code of CCL program, or nil.
1863 Return index number of the registered CCL program.
1864 */
1865   (name, ccl_prog))
1866 {
1867   int len = XVECTOR_LENGTH (Vccl_program_table);
1868   int i;
1869
1870   CHECK_SYMBOL (name);
1871   if (!NILP (ccl_prog))
1872     {
1873       CHECK_VECTOR (ccl_prog);
1874       ccl_prog = resolve_symbol_ccl_program (ccl_prog);
1875     }
1876
1877   for (i = 0; i < len; i++)
1878     {
1879       Lisp_Object slot = XVECTOR_DATA (Vccl_program_table)[i];
1880
1881       if (!CONSP (slot))
1882         break;
1883
1884       if (EQ (name, XCAR (slot)))
1885         {
1886           XCDR (slot) = ccl_prog;
1887           return make_int (i);
1888         }
1889     }
1890
1891   if (i == len)
1892     {
1893       Lisp_Object new_table = Fmake_vector (make_int (len * 2), Qnil);
1894       int j;
1895
1896       for (j = 0; j < len; j++)
1897         XVECTOR_DATA (new_table)[j]
1898           = XVECTOR_DATA (Vccl_program_table)[j];
1899       Vccl_program_table = new_table;
1900     }
1901
1902   XVECTOR_DATA (Vccl_program_table)[i] = Fcons (name, ccl_prog);
1903   Fput (name, Qccl_program_idx, make_int (i));
1904   return make_int (i);
1905 }
1906
1907 #if 0
1908 /* Register code conversion map.
1909    A code conversion map consists of numbers, Qt, Qnil, and Qlambda.
1910    The first element is start code point.
1911    The rest elements are mapped numbers.
1912    Symbol t means to map to an original number before mapping.
1913    Symbol nil means that the corresponding element is empty.
1914    Symbol lambda menas to terminate mapping here.
1915 */
1916
1917 DEFUN ("register-code-conversion-map", Fregister_code_conversion_map,
1918        Sregister_code_conversion_map,
1919        2, 2, 0,
1920   "Register SYMBOL as code conversion map MAP.\n\
1921 Return index number of the registered map.")
1922   (symbol, map)
1923      Lisp_Object symbol, map;
1924 {
1925   int len = XVECTOR (Vcode_conversion_map_vector)->size;
1926   int i;
1927   Lisp_Object index;
1928
1929   CHECK_SYMBOL (symbol, 0);
1930   CHECK_VECTOR (map, 1);
1931   
1932   for (i = 0; i < len; i++)
1933     {
1934       Lisp_Object slot = XVECTOR (Vcode_conversion_map_vector)->contents[i];
1935
1936       if (!CONSP (slot))
1937         break;
1938
1939       if (EQ (symbol, XCONS (slot)->car))
1940         {
1941           index = make_int (i);
1942           XCONS (slot)->cdr = map;
1943           Fput (symbol, Qcode_conversion_map, map);
1944           Fput (symbol, Qcode_conversion_map_id, index);
1945           return index;
1946         }
1947     }
1948
1949   if (i == len)
1950     {
1951       Lisp_Object new_vector = Fmake_vector (make_int (len * 2), Qnil);
1952       int j;
1953
1954       for (j = 0; j < len; j++)
1955         XVECTOR (new_vector)->contents[j]
1956           = XVECTOR (Vcode_conversion_map_vector)->contents[j];
1957       Vcode_conversion_map_vector = new_vector;
1958     }
1959
1960   index = make_int (i);
1961   Fput (symbol, Qcode_conversion_map, map);
1962   Fput (symbol, Qcode_conversion_map_id, index);
1963   XVECTOR (Vcode_conversion_map_vector)->contents[i] = Fcons (symbol, map);
1964   return index;
1965 }
1966 #endif
1967
1968
1969 void
1970 syms_of_mule_ccl (void)
1971 {
1972   DEFSUBR (Fccl_execute);
1973   DEFSUBR (Fccl_execute_on_string);
1974   DEFSUBR (Fregister_ccl_program);
1975 #if 0
1976   DEFSUBR (&Fregister_code_conversion_map);
1977 #endif
1978 }
1979
1980 void
1981 vars_of_mule_ccl (void)
1982 {
1983   staticpro (&Vccl_program_table);
1984   Vccl_program_table = Fmake_vector (make_int (32), Qnil);
1985
1986   Qccl_program = intern ("ccl-program");
1987   staticpro (&Qccl_program);
1988
1989   Qccl_program_idx = intern ("ccl-program-idx");
1990   staticpro (&Qccl_program_idx);
1991
1992 #if 0
1993   Qcode_conversion_map = intern ("code-conversion-map");
1994   staticpro (&Qcode_conversion_map);
1995
1996   Qcode_conversion_map_id = intern ("code-conversion-map-id");
1997   staticpro (&Qcode_conversion_map_id);
1998
1999   DEFVAR_LISP ("code-conversion-map-vector", &Vcode_conversion_map_vector /*
2000 Vector of code conversion maps.*/ );
2001   Vcode_conversion_map_vector = Fmake_vector (make_int (16), Qnil);
2002 #endif
2003
2004   DEFVAR_LISP ("font-ccl-encoder-alist", &Vfont_ccl_encoder_alist /*
2005 Alist of fontname patterns vs corresponding CCL program.
2006 Each element looks like (REGEXP . CCL-CODE),
2007  where CCL-CODE is a compiled CCL program.
2008 When a font whose name matches REGEXP is used for displaying a character,
2009  CCL-CODE is executed to calculate the code point in the font
2010  from the charset number and position code(s) of the character which are set
2011  in CCL registers R0, R1, and R2 before the execution.
2012 The code point in the font is set in CCL registers R1 and R2
2013  when the execution terminated.
2014 If the font is single-byte font, the register R2 is not used.
2015 */ );
2016   Vfont_ccl_encoder_alist = Qnil;
2017 }
2018
2019 #endif  /* emacs */