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