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