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