comparison src/mule-ccl.c @ 213:78f53ef88e17 r20-4b5

Import from CVS: tag r20-4b5
author cvs
date Mon, 13 Aug 2007 10:06:47 +0200
parents 3d6bfa290dbd
children f955c73f5258
comparison
equal deleted inserted replaced
212:d8688acf4c5b 213:78f53ef88e17
1 /* CCL -- Code Conversion Language Interpreter 1 /* CCL (Code Conversion Language) interpreter.
2 Copyright (C) 1992, 1995 Free Software Foundation, Inc. 2 Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN.
3 Copyright (C) 1995 Sun Microsystems, Inc. 3 Licensed to the Free Software Foundation.
4 4
5 This file is part of XEmacs. 5 This file is part of XEmacs.
6 6
7 XEmacs is free software; you can redistribute it and/or modify it 7 GNU Emacs is free software; you can redistribute it and/or modify
8 under the terms of the GNU General Public License as published by the 8 it under the terms of the GNU General Public License as published by
9 Free Software Foundation; either version 2, or (at your option) any 9 the Free Software Foundation; either version 2, or (at your option)
10 later version. 10 any later version.
11 11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT 12 GNU Emacs is distributed in the hope that it will be useful,
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 for more details. 15 GNU General Public License for more details.
16 16
17 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to 18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */ 20 Boston, MA 02111-1307, USA. */
21 21
22 /* Synched up with: Mule 2.3. Not in FSF. */ 22 /* Synched up with : FSF Emacs 20.2 */
23
24 #include <stdio.h>
25
26 #ifdef emacs
23 27
24 #include <config.h> 28 #include <config.h>
25 #include "lisp.h" 29 #include "lisp.h"
26
27 #include "buffer.h" 30 #include "buffer.h"
31 #include "mule-charset.h"
32 #include "mule-ccl.h"
28 #include "mule-coding.h" 33 #include "mule-coding.h"
29 34
30 /* CCL operators */ 35 #else /* not emacs */
31 #define CCL_SetCS 0x00 36
32 #define CCL_SetCL 0x01 37 #include "mulelib.h"
33 #define CCL_SetR 0x02 38
34 #define CCL_SetA 0x03 39 #endif /* not emacs */
35 #define CCL_Jump 0x04 40
36 #define CCL_JumpCond 0x05 41 /* Alist of fontname patterns vs corresponding CCL program. */
37 #define CCL_WriteJump 0x06 42 Lisp_Object Vfont_ccl_encoder_alist;
38 #define CCL_WriteReadJump 0x07 43
39 #define CCL_WriteCJump 0x08 44 /* Vector of CCL program names vs corresponding program data. */
40 #define CCL_WriteCReadJump 0x09 45 Lisp_Object Vccl_program_table;
41 #define CCL_WriteSJump 0x0A 46
42 #define CCL_WriteSReadJump 0x0B 47 /* CCL (Code Conversion Language) is a simple language which has
43 #define CCL_WriteAReadJump 0x0C 48 operations on one input buffer, one output buffer, and 7 registers.
44 #define CCL_Branch 0x0D 49 The syntax of CCL is described in `ccl.el'. Emacs Lisp function
45 #define CCL_Read1 0x0E 50 `ccl-compile' compiles a CCL program and produces a CCL code which
46 #define CCL_Read2 0x0F 51 is a vector of integers. The structure of this vector is as
47 #define CCL_ReadBranch 0x10 52 follows: The 1st element: buffer-magnification, a factor for the
48 #define CCL_Write1 0x11 53 size of output buffer compared with the size of input buffer. The
49 #define CCL_Write2 0x12 54 2nd element: address of CCL code to be executed when encountered
50 #define CCL_WriteC 0x13 55 with end of input stream. The 3rd and the remaining elements: CCL
51 #define CCL_WriteS 0x14 56 codes. */
52 #define CCL_WriteA 0x15
53 #define CCL_End 0x16
54 #define CCL_SetSelfCS 0x17
55 #define CCL_SetSelfCL 0x18
56 #define CCL_SetSelfR 0x19
57 #define CCL_SetExprCL 0x1A
58 #define CCL_SetExprR 0x1B
59 #define CCL_JumpCondC 0x1C
60 #define CCL_JumpCondR 0x1D
61 #define CCL_ReadJumpCondC 0x1E
62 #define CCL_ReadJumpCondR 0x1F
63
64 #define CCL_PLUS 0x00
65 #define CCL_MINUS 0x01
66 #define CCL_MUL 0x02
67 #define CCL_DIV 0x03
68 #define CCL_MOD 0x04
69 #define CCL_AND 0x05
70 #define CCL_OR 0x06
71 #define CCL_XOR 0x07
72 #define CCL_LSH 0x08
73 #define CCL_RSH 0x09
74 #define CCL_LSH8 0x0A
75 #define CCL_RSH8 0x0B
76 #define CCL_DIVMOD 0x0C
77 #define CCL_LS 0x10
78 #define CCL_GT 0x11
79 #define CCL_EQ 0x12
80 #define CCL_LE 0x13
81 #define CCL_GE 0x14
82 #define CCL_NE 0x15
83 57
84 /* Header of CCL compiled code */ 58 /* Header of CCL compiled code */
85 #define CCL_HEADER_EOF 0 59 #define CCL_HEADER_BUF_MAG 0
86 #define CCL_HEADER_MAIN 1 60 #define CCL_HEADER_EOF 1
87 61 #define CCL_HEADER_MAIN 2
88 #define CCL_STAT_SUCCESS 0 62
89 #define CCL_STAT_SUSPEND 1 63 /* CCL code is a sequence of 28-bit non-negative integers (i.e. the
90 #define CCL_STAT_INVALID_CMD 2 64 MSB is always 0), each contains CCL command and/or arguments in the
91 65 following format:
92 #define CCL_SUCCESS \ 66
93 ccl->status = CCL_STAT_SUCCESS; \ 67 |----------------- integer (28-bit) ------------------|
94 goto ccl_finish 68 |------- 17-bit ------|- 3-bit --|- 3-bit --|- 5-bit -|
95 #define CCL_SUSPEND \ 69 |--constant argument--|-register-|-register-|-command-|
96 ccl->ic = --ic; \ 70 ccccccccccccccccc RRR rrr XXXXX
97 ccl->status = CCL_STAT_SUSPEND; \ 71 or
98 goto ccl_finish 72 |------- relative address -------|-register-|-command-|
99 #define CCL_INVALID_CMD \ 73 cccccccccccccccccccc rrr XXXXX
100 ccl->status = CCL_STAT_INVALID_CMD; \ 74 or
101 goto ccl_error_handler 75 |------------- constant or other args ----------------|
102 76 cccccccccccccccccccccccccccc
103 #define CCL_WRITE_CHAR(ch) do \ 77
104 { \ 78 where, `cc...c' is a non-negative integer indicating constant value
105 if (!src) \ 79 (the left most `c' is always 0) or an absolute jump address, `RRR'
106 { \ 80 and `rrr' are CCL register number, `XXXXX' is one of the following
81 CCL commands. */
82
83 /* CCL commands
84
85 Each comment fields shows one or more lines for command syntax and
86 the following lines for semantics of the command. In semantics, IC
87 stands for Instruction Counter. */
88
89 #define CCL_SetRegister 0x00 /* Set register a register value:
90 1:00000000000000000RRRrrrXXXXX
91 ------------------------------
92 reg[rrr] = reg[RRR];
93 */
94
95 #define CCL_SetShortConst 0x01 /* Set register a short constant value:
96 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
97 ------------------------------
98 reg[rrr] = CCCCCCCCCCCCCCCCCCC;
99 */
100
101 #define CCL_SetConst 0x02 /* Set register a constant value:
102 1:00000000000000000000rrrXXXXX
103 2:CONSTANT
104 ------------------------------
105 reg[rrr] = CONSTANT;
106 IC++;
107 */
108
109 #define CCL_SetArray 0x03 /* Set register an element of array:
110 1:CCCCCCCCCCCCCCCCCRRRrrrXXXXX
111 2:ELEMENT[0]
112 3:ELEMENT[1]
113 ...
114 ------------------------------
115 if (0 <= reg[RRR] < CC..C)
116 reg[rrr] = ELEMENT[reg[RRR]];
117 IC += CC..C;
118 */
119
120 #define CCL_Jump 0x04 /* Jump:
121 1:A--D--D--R--E--S--S-000XXXXX
122 ------------------------------
123 IC += ADDRESS;
124 */
125
126 /* Note: If CC..C is greater than 0, the second code is omitted. */
127
128 #define CCL_JumpCond 0x05 /* Jump conditional:
129 1:A--D--D--R--E--S--S-rrrXXXXX
130 ------------------------------
131 if (!reg[rrr])
132 IC += ADDRESS;
133 */
134
135
136 #define CCL_WriteRegisterJump 0x06 /* Write register and jump:
137 1:A--D--D--R--E--S--S-rrrXXXXX
138 ------------------------------
139 write (reg[rrr]);
140 IC += ADDRESS;
141 */
142
143 #define CCL_WriteRegisterReadJump 0x07 /* Write register, read, and jump:
144 1:A--D--D--R--E--S--S-rrrXXXXX
145 2:A--D--D--R--E--S--S-rrrYYYYY
146 -----------------------------
147 write (reg[rrr]);
148 IC++;
149 read (reg[rrr]);
150 IC += ADDRESS;
151 */
152 /* Note: If read is suspended, the resumed execution starts from the
153 second code (YYYYY == CCL_ReadJump). */
154
155 #define CCL_WriteConstJump 0x08 /* Write constant and jump:
156 1:A--D--D--R--E--S--S-000XXXXX
157 2:CONST
158 ------------------------------
159 write (CONST);
160 IC += ADDRESS;
161 */
162
163 #define CCL_WriteConstReadJump 0x09 /* Write constant, read, and jump:
164 1:A--D--D--R--E--S--S-rrrXXXXX
165 2:CONST
166 3:A--D--D--R--E--S--S-rrrYYYYY
167 -----------------------------
168 write (CONST);
169 IC += 2;
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_WriteStringJump 0x0A /* Write string and jump:
177 1:A--D--D--R--E--S--S-000XXXXX
178 2:LENGTH
179 3:0000STRIN[0]STRIN[1]STRIN[2]
180 ...
181 ------------------------------
182 write_string (STRING, LENGTH);
183 IC += ADDRESS;
184 */
185
186 #define CCL_WriteArrayReadJump 0x0B /* Write an array element, read, and jump:
187 1:A--D--D--R--E--S--S-rrrXXXXX
188 2:LENGTH
189 3:ELEMENET[0]
190 4:ELEMENET[1]
191 ...
192 N:A--D--D--R--E--S--S-rrrYYYYY
193 ------------------------------
194 if (0 <= reg[rrr] < LENGTH)
195 write (ELEMENT[reg[rrr]]);
196 IC += LENGTH + 2; (... pointing at N+1)
197 read (reg[rrr]);
198 IC += ADDRESS;
199 */
200 /* Note: If read is suspended, the resumed execution starts from the
201 Nth code (YYYYY == CCL_ReadJump). */
202
203 #define CCL_ReadJump 0x0C /* Read and jump:
204 1:A--D--D--R--E--S--S-rrrYYYYY
205 -----------------------------
206 read (reg[rrr]);
207 IC += ADDRESS;
208 */
209
210 #define CCL_Branch 0x0D /* Jump by branch table:
211 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
212 2:A--D--D--R--E-S-S[0]000XXXXX
213 3:A--D--D--R--E-S-S[1]000XXXXX
214 ...
215 ------------------------------
216 if (0 <= reg[rrr] < CC..C)
217 IC += ADDRESS[reg[rrr]];
218 else
219 IC += ADDRESS[CC..C];
220 */
221
222 #define CCL_ReadRegister 0x0E /* Read bytes into registers:
223 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
224 2:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
225 ...
226 ------------------------------
227 while (CCC--)
228 read (reg[rrr]);
229 */
230
231 #define CCL_WriteExprConst 0x0F /* write result of expression:
232 1:00000OPERATION000RRR000XXXXX
233 2:CONSTANT
234 ------------------------------
235 write (reg[RRR] OPERATION CONSTANT);
236 IC++;
237 */
238
239 /* Note: If the Nth read is suspended, the resumed execution starts
240 from the Nth code. */
241
242 #define CCL_ReadBranch 0x10 /* Read one byte into a register,
243 and jump by branch table:
244 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
245 2:A--D--D--R--E-S-S[0]000XXXXX
246 3:A--D--D--R--E-S-S[1]000XXXXX
247 ...
248 ------------------------------
249 read (read[rrr]);
250 if (0 <= reg[rrr] < CC..C)
251 IC += ADDRESS[reg[rrr]];
252 else
253 IC += ADDRESS[CC..C];
254 */
255
256 #define CCL_WriteRegister 0x11 /* Write registers:
257 1:CCCCCCCCCCCCCCCCCCCrrrXXXXX
258 2:CCCCCCCCCCCCCCCCCCCrrrXXXXX
259 ...
260 ------------------------------
261 while (CCC--)
262 write (reg[rrr]);
263 ...
264 */
265
266 /* Note: If the Nth write is suspended, the resumed execution
267 starts from the Nth code. */
268
269 #define CCL_WriteExprRegister 0x12 /* Write result of expression
270 1:00000OPERATIONRrrRRR000XXXXX
271 ------------------------------
272 write (reg[RRR] OPERATION reg[Rrr]);
273 */
274
275 #define CCL_Call 0x13 /* Write a constant:
276 1:CCCCCCCCCCCCCCCCCCCC000XXXXX
277 ------------------------------
278 call (CC..C)
279 */
280
281 #define CCL_WriteConstString 0x14 /* Write a constant or a string:
282 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
283 [2:0000STRIN[0]STRIN[1]STRIN[2]]
284 [...]
285 -----------------------------
286 if (!rrr)
287 write (CC..C)
288 else
289 write_string (STRING, CC..C);
290 IC += (CC..C + 2) / 3;
291 */
292
293 #define CCL_WriteArray 0x15 /* Write an element of array:
294 1:CCCCCCCCCCCCCCCCCCCCrrrXXXXX
295 2:ELEMENT[0]
296 3:ELEMENT[1]
297 ...
298 ------------------------------
299 if (0 <= reg[rrr] < CC..C)
300 write (ELEMENT[reg[rrr]]);
301 IC += CC..C;
302 */
303
304 #define CCL_End 0x16 /* Terminate:
305 1:00000000000000000000000XXXXX
306 ------------------------------
307 terminate ();
308 */
309
310 /* The following two codes execute an assignment arithmetic/logical
311 operation. The form of the operation is like REG OP= OPERAND. */
312
313 #define CCL_ExprSelfConst 0x17 /* REG OP= constant:
314 1:00000OPERATION000000rrrXXXXX
315 2:CONSTANT
316 ------------------------------
317 reg[rrr] OPERATION= CONSTANT;
318 */
319
320 #define CCL_ExprSelfReg 0x18 /* REG1 OP= REG2:
321 1:00000OPERATION000RRRrrrXXXXX
322 ------------------------------
323 reg[rrr] OPERATION= reg[RRR];
324 */
325
326 /* The following codes execute an arithmetic/logical operation. The
327 form of the operation is like REG_X = REG_Y OP OPERAND2. */
328
329 #define CCL_SetExprConst 0x19 /* REG_X = REG_Y OP constant:
330 1:00000OPERATION000RRRrrrXXXXX
331 2:CONSTANT
332 ------------------------------
333 reg[rrr] = reg[RRR] OPERATION CONSTANT;
334 IC++;
335 */
336
337 #define CCL_SetExprReg 0x1A /* REG1 = REG2 OP REG3:
338 1:00000OPERATIONRrrRRRrrrXXXXX
339 ------------------------------
340 reg[rrr] = reg[RRR] OPERATION reg[Rrr];
341 */
342
343 #define CCL_JumpCondExprConst 0x1B /* Jump conditional according to
344 an operation on constant:
345 1:A--D--D--R--E--S--S-rrrXXXXX
346 2:OPERATION
347 3:CONSTANT
348 -----------------------------
349 reg[7] = reg[rrr] OPERATION CONSTANT;
350 if (!(reg[7]))
351 IC += ADDRESS;
352 else
353 IC += 2
354 */
355
356 #define CCL_JumpCondExprReg 0x1C /* Jump conditional according to
357 an operation on register:
358 1:A--D--D--R--E--S--S-rrrXXXXX
359 2:OPERATION
360 3:RRR
361 -----------------------------
362 reg[7] = reg[rrr] OPERATION reg[RRR];
363 if (!reg[7])
364 IC += ADDRESS;
365 else
366 IC += 2;
367 */
368
369 #define CCL_ReadJumpCondExprConst 0x1D /* Read and jump conditional according
370 to an operation on constant:
371 1:A--D--D--R--E--S--S-rrrXXXXX
372 2:OPERATION
373 3:CONSTANT
374 -----------------------------
375 read (reg[rrr]);
376 reg[7] = reg[rrr] OPERATION CONSTANT;
377 if (!reg[7])
378 IC += ADDRESS;
379 else
380 IC += 2;
381 */
382
383 #define CCL_ReadJumpCondExprReg 0x1E /* Read and jump conditional according
384 to an operation on register:
385 1:A--D--D--R--E--S--S-rrrXXXXX
386 2:OPERATION
387 3:RRR
388 -----------------------------
389 read (reg[rrr]);
390 reg[7] = reg[rrr] OPERATION reg[RRR];
391 if (!reg[7])
392 IC += ADDRESS;
393 else
394 IC += 2;
395 */
396
397 #define CCL_Extention 0x1F /* Extended CCL code
398 1:ExtendedCOMMNDRrrRRRrrrXXXXX
399 2:ARGUEMENT
400 3:...
401 ------------------------------
402 extended_command (rrr,RRR,Rrr,ARGS)
403 */
404
405
406 /* CCL arithmetic/logical operators. */
407 #define CCL_PLUS 0x00 /* X = Y + Z */
408 #define CCL_MINUS 0x01 /* X = Y - Z */
409 #define CCL_MUL 0x02 /* X = Y * Z */
410 #define CCL_DIV 0x03 /* X = Y / Z */
411 #define CCL_MOD 0x04 /* X = Y % Z */
412 #define CCL_AND 0x05 /* X = Y & Z */
413 #define CCL_OR 0x06 /* X = Y | Z */
414 #define CCL_XOR 0x07 /* X = Y ^ Z */
415 #define CCL_LSH 0x08 /* X = Y << Z */
416 #define CCL_RSH 0x09 /* X = Y >> Z */
417 #define CCL_LSH8 0x0A /* X = (Y << 8) | Z */
418 #define CCL_RSH8 0x0B /* X = Y >> 8, r[7] = Y & 0xFF */
419 #define CCL_DIVMOD 0x0C /* X = Y / Z, r[7] = Y % Z */
420 #define CCL_LS 0x10 /* X = (X < Y) */
421 #define CCL_GT 0x11 /* X = (X > Y) */
422 #define CCL_EQ 0x12 /* X = (X == Y) */
423 #define CCL_LE 0x13 /* X = (X <= Y) */
424 #define CCL_GE 0x14 /* X = (X >= Y) */
425 #define CCL_NE 0x15 /* X = (X != Y) */
426
427 #define CCL_ENCODE_SJIS 0x16 /* X = HIGHER_BYTE (SJIS (Y, Z))
428 r[7] = LOWER_BYTE (SJIS (Y, Z) */
429 #define CCL_DECODE_SJIS 0x17 /* X = HIGHER_BYTE (DE-SJIS (Y, Z))
430 r[7] = LOWER_BYTE (DE-SJIS (Y, Z)) */
431
432 /* Macros for exit status of CCL program. */
433 #define CCL_STAT_SUCCESS 0 /* Terminated successfully. */
434 #define CCL_STAT_SUSPEND 1 /* Terminated because of empty input
435 buffer or full output buffer. */
436 #define CCL_STAT_INVALID_CMD 2 /* Terminated because of invalid
437 command. */
438 #define CCL_STAT_QUIT 3 /* Terminated because of quit. */
439
440 /* Terminate CCL program successfully. */
441 #define CCL_SUCCESS \
442 do { \
443 ccl->status = CCL_STAT_SUCCESS; \
444 ccl->ic = CCL_HEADER_MAIN; \
445 goto ccl_finish; \
446 } while (0)
447
448 /* Suspend CCL program because of reading from empty input buffer or
449 writing to full output buffer. When this program is resumed, the
450 same I/O command is executed. */
451 #define CCL_SUSPEND \
452 do { \
453 ic--; \
454 ccl->status = CCL_STAT_SUSPEND; \
455 goto ccl_finish; \
456 } while (0)
457
458 /* Terminate CCL program because of invalid command. Should not occur
459 in the normal case. */
460 #define CCL_INVALID_CMD \
461 do { \
462 ccl->status = CCL_STAT_INVALID_CMD; \
463 goto ccl_error_handler; \
464 } while (0)
465
466 /* Encode one character CH to multibyte form and write to the current
467 output buffer. If CH is less than 256, CH is written as is. */
468 #define CCL_WRITE_CHAR(ch) \
469 do { \
470 if (!destination) \
471 CCL_INVALID_CMD; \
472 else \
473 { \
474 Bufbyte work[MAX_EMCHAR_LEN]; \
475 int len = set_charptr_emchar (work, ch); \
476 Dynarr_add_many (destination, work, len); \
477 } \
478 } while (0)
479
480 /* Write a string at ccl_prog[IC] of length LEN to the current output
481 buffer. */
482 #define CCL_WRITE_STRING(len) \
483 do { \
484 if (!destination) \
107 CCL_INVALID_CMD; \ 485 CCL_INVALID_CMD; \
108 } \ 486 else \
109 else \ 487 for (i = 0; i < len; i++) \
110 { \ 488 Dynarr_add(destination, (XINT (ccl_prog[ic + (i / 3)]) \
111 /* !!#### is this correct for both directions????? */ \ 489 >> ((2 - (i % 3)) * 8)) & 0xFF); \
112 Bufbyte __buf__[MAX_EMCHAR_LEN]; \ 490 } while (0)
113 int __len__; \ 491
114 __len__ = set_charptr_emchar (__buf__, ch); \ 492 /* Read one byte from the current input buffer into Rth register. */
115 Dynarr_add_many (dst, __buf__, __len__); \ 493 #define CCL_READ_CHAR(r) \
116 } \ 494 do { \
117 } while (0) 495 if (!src) \
118 496 CCL_INVALID_CMD; \
119 #define CCL_WRITE_STRING(len) do \ 497 else if (src < src_end) \
120 { \ 498 r = *src++; \
121 if (!src) \ 499 else if (ccl->last_block) \
122 { \ 500 { \
123 CCL_INVALID_CMD; \ 501 ic = ccl->eof_ic; \
124 } \ 502 goto ccl_finish; \
125 else \ 503 } \
126 { \ 504 else \
127 for (j = 0; j < len; j++) \ 505 CCL_SUSPEND; \
128 Dynarr_add (dst, XINT (prog[ic + 1 + j])); \ 506 } while (0)
129 } \ 507
130 } while (0) 508
131 509 /* Execute CCL code on SRC_BYTES length text at SOURCE. The resulting
132 #define CCL_READ_CHAR(r) do \ 510 text goes to a place pointed by DESTINATION. The bytes actually
133 { \ 511 processed is returned as *CONSUMED. The return value is the length
134 if (!src) \ 512 of the resulting text. As a side effect, the contents of CCL registers
135 { \ 513 are updated. If SOURCE or DESTINATION is NULL, only operations on
136 CCL_INVALID_CMD; \ 514 registers are permitted. */
137 } \ 515
138 else if (s < s_end) \ 516 #ifdef CCL_DEBUG
139 r = *s++; \ 517 #define CCL_DEBUG_BACKTRACE_LEN 256
140 else if (end_flag) \ 518 int ccl_backtrace_table[CCL_BACKTRACE_TABLE];
141 { \ 519 int ccl_backtrace_idx;
142 ic = XINT (prog[CCL_HEADER_EOF]); \ 520 #endif
143 continue; \ 521
144 } \ 522 struct ccl_prog_stack
145 else \ 523 {
146 { \ 524 Lisp_Object *ccl_prog; /* Pointer to an array of CCL code. */
147 CCL_SUSPEND; \ 525 int ic; /* Instruction Counter. */
148 } \ 526 };
149 } while (0)
150
151
152 /* Run a CCL program. The initial state and program are contained in
153 CCL. SRC, if non-zero, specifies a source string (of size N)
154 to read bytes from, and DST, of non-zero, specifies a destination
155 Dynarr to write bytes to. If END_FLAG is set, it means that
156 the end section of the CCL program should be run rather than
157 the normal section.
158
159 For CCL programs that do not involve code conversion (e.g.
160 converting a single character into a font index), all parameters
161 but the first will usually be 0. */
162 527
163 int 528 int
164 ccl_driver (struct ccl_program *ccl, CONST unsigned char *src, 529 ccl_driver (struct ccl_program *ccl, CONST unsigned char *source, unsigned_char_dynarr *destination, int src_bytes, int *consumed)
165 unsigned_char_dynarr *dst, int n, int end_flag)
166 { 530 {
167 int code, op, rrr, cc, i, j;
168 CONST unsigned char *s = NULL, *s_end = NULL;
169 int ic = ccl->ic;
170 int *reg = ccl->reg; 531 int *reg = ccl->reg;
171 Lisp_Object *prog = ccl->prog; 532 int ic = ccl->ic;
172 533 int code, field1, field2;
173 if (!ic) 534 Lisp_Object *ccl_prog = ccl->prog;
535 unsigned char *src = source, *src_end = src + src_bytes;
536 int jump_address;
537 int i, j, op;
538 int stack_idx = 0;
539 /* For the moment, we only support depth 256 of stack. */
540 struct ccl_prog_stack ccl_prog_stack_struct[256];
541
542 if (ic >= ccl->eof_ic)
174 ic = CCL_HEADER_MAIN; 543 ic = CCL_HEADER_MAIN;
175 544
176 if (src) 545 #ifdef CCL_DEBUG
546 ccl_backtrace_idx = 0;
547 #endif
548
549 for (;;)
177 { 550 {
178 s = src; 551 #ifdef CCL_DEBUG
179 s_end = s + n; 552 ccl_backtrace_table[ccl_backtrace_idx++] = ic;
180 } 553 if (ccl_backtrace_idx >= CCL_DEBUG_BACKTRACE_LEN)
181 554 ccl_backtrace_idx = 0;
182 while (1) 555 ccl_backtrace_table[ccl_backtrace_idx] = 0;
183 { 556 #endif
184 code = XINT (prog[ic++]); 557
185 op = code & 0x1F; 558 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
186 rrr = (code >> 5) & 0x7;
187 cc = code >> 8;
188
189 switch (op)
190 { 559 {
191 case CCL_SetCS: 560 /* We can't just signal Qquit, instead break the loop as if
192 reg[rrr] = cc; continue; 561 the whole data is processed. Don't reset Vquit_flag, it
193 case CCL_SetCL: 562 must be handled later at a safer place. */
194 reg[rrr] = XINT (prog[ic++]); continue; 563 if (consumed)
195 case CCL_SetR: 564 src = source + src_bytes;
196 reg[rrr] = reg[cc]; continue; 565 ccl->status = CCL_STAT_QUIT;
197 case CCL_SetA: 566 break;
198 cc = reg[cc]; 567 }
199 i = XINT (prog[ic++]); 568
200 if (cc >= 0 && cc < i) 569 code = XINT (ccl_prog[ic]); ic++;
201 reg[rrr] = XINT (prog[ic + cc]); 570 field1 = code >> 8;
202 ic += i; 571 field2 = (code & 0xFF) >> 5;
203 continue; 572
204 case CCL_Jump: 573 #define rrr field2
205 ic = cc; continue; 574 #define RRR (field1 & 7)
206 case CCL_JumpCond: 575 #define Rrr ((field1 >> 3) & 7)
576 #define ADDR field1
577
578 switch (code & 0x1F)
579 {
580 case CCL_SetRegister: /* 00000000000000000RRRrrrXXXXX */
581 reg[rrr] = reg[RRR];
582 break;
583
584 case CCL_SetShortConst: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
585 reg[rrr] = field1;
586 break;
587
588 case CCL_SetConst: /* 00000000000000000000rrrXXXXX */
589 reg[rrr] = XINT (ccl_prog[ic]);
590 ic++;
591 break;
592
593 case CCL_SetArray: /* CCCCCCCCCCCCCCCCCCCCRRRrrrXXXXX */
594 i = reg[RRR];
595 j = field1 >> 3;
596 if ((unsigned int) i < j)
597 reg[rrr] = XINT (ccl_prog[ic + i]);
598 ic += j;
599 break;
600
601 case CCL_Jump: /* A--D--D--R--E--S--S-000XXXXX */
602 ic += ADDR;
603 break;
604
605 case CCL_JumpCond: /* A--D--D--R--E--S--S-rrrXXXXX */
207 if (!reg[rrr]) 606 if (!reg[rrr])
208 ic = cc; 607 ic += ADDR;
209 continue; 608 break;
210 case CCL_WriteJump: 609
211 CCL_WRITE_CHAR (reg[rrr]); 610 case CCL_WriteRegisterJump: /* A--D--D--R--E--S--S-rrrXXXXX */
212 ic = cc; 611 i = reg[rrr];
213 continue; 612 CCL_WRITE_CHAR (i);
214 case CCL_WriteReadJump: 613 ic += ADDR;
215 if (ccl->status != CCL_STAT_SUSPEND) 614 break;
615
616 case CCL_WriteRegisterReadJump: /* A--D--D--R--E--S--S-rrrXXXXX */
617 i = reg[rrr];
618 CCL_WRITE_CHAR (i);
619 ic++;
620 CCL_READ_CHAR (reg[rrr]);
621 ic += ADDR - 1;
622 break;
623
624 case CCL_WriteConstJump: /* A--D--D--R--E--S--S-000XXXXX */
625 i = XINT (ccl_prog[ic]);
626 CCL_WRITE_CHAR (i);
627 ic += ADDR;
628 break;
629
630 case CCL_WriteConstReadJump: /* A--D--D--R--E--S--S-rrrXXXXX */
631 i = XINT (ccl_prog[ic]);
632 CCL_WRITE_CHAR (i);
633 ic++;
634 CCL_READ_CHAR (reg[rrr]);
635 ic += ADDR - 1;
636 break;
637
638 case CCL_WriteStringJump: /* A--D--D--R--E--S--S-000XXXXX */
639 j = XINT (ccl_prog[ic]);
640 ic++;
641 CCL_WRITE_STRING (j);
642 ic += ADDR - 1;
643 break;
644
645 case CCL_WriteArrayReadJump: /* A--D--D--R--E--S--S-rrrXXXXX */
646 i = reg[rrr];
647 j = XINT (ccl_prog[ic]);
648 if ((unsigned int) i < j)
216 { 649 {
217 CCL_WRITE_CHAR (reg[rrr]); 650 i = XINT (ccl_prog[ic + 1 + i]);
651 CCL_WRITE_CHAR (i);
218 } 652 }
653 ic += j + 2;
654 CCL_READ_CHAR (reg[rrr]);
655 ic += ADDR - (j + 2);
656 break;
657
658 case CCL_ReadJump: /* A--D--D--R--E--S--S-rrrYYYYY */
659 CCL_READ_CHAR (reg[rrr]);
660 ic += ADDR;
661 break;
662
663 case CCL_ReadBranch: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
664 CCL_READ_CHAR (reg[rrr]);
665 /* fall through ... */
666 case CCL_Branch: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
667 if ((unsigned int) reg[rrr] < field1)
668 ic += XINT (ccl_prog[ic + reg[rrr]]);
219 else 669 else
220 ccl->status = CCL_STAT_SUCCESS; 670 ic += XINT (ccl_prog[ic + field1]);
221 CCL_READ_CHAR (reg[rrr]); 671 break;
222 ic = cc; 672
223 continue; 673 case CCL_ReadRegister: /* CCCCCCCCCCCCCCCCCCCCrrXXXXX */
224 case CCL_WriteCJump: 674 while (1)
225 CCL_WRITE_CHAR (XINT (prog[ic]));
226 ic = cc;
227 continue;
228 case CCL_WriteCReadJump:
229 if (ccl->status != CCL_STAT_SUSPEND)
230 { 675 {
231 CCL_WRITE_CHAR (XINT (prog[ic])); 676 CCL_READ_CHAR (reg[rrr]);
677 if (!field1) break;
678 code = XINT (ccl_prog[ic]); ic++;
679 field1 = code >> 8;
680 field2 = (code & 0xFF) >> 5;
232 } 681 }
682 break;
683
684 case CCL_WriteExprConst: /* 1:00000OPERATION000RRR000XXXXX */
685 rrr = 7;
686 i = reg[RRR];
687 j = XINT (ccl_prog[ic]);
688 op = field1 >> 6;
689 ic++;
690 goto ccl_set_expr;
691
692 case CCL_WriteRegister: /* CCCCCCCCCCCCCCCCCCCrrrXXXXX */
693 while (1)
694 {
695 i = reg[rrr];
696 CCL_WRITE_CHAR (i);
697 if (!field1) break;
698 code = XINT (ccl_prog[ic]); ic++;
699 field1 = code >> 8;
700 field2 = (code & 0xFF) >> 5;
701 }
702 break;
703
704 case CCL_WriteExprRegister: /* 1:00000OPERATIONRrrRRR000XXXXX */
705 rrr = 7;
706 i = reg[RRR];
707 j = reg[Rrr];
708 op = field1 >> 6;
709 goto ccl_set_expr;
710
711 case CCL_Call: /* CCCCCCCCCCCCCCCCCCCC000XXXXX */
712 {
713 Lisp_Object slot;
714
715 if (stack_idx >= 256
716 || field1 < 0
717 || field1 >= XVECTOR_LENGTH (Vccl_program_table)
718 || (slot = XVECTOR_DATA (Vccl_program_table)[field1],
719 !CONSP (slot))
720 || !VECTORP (XCDR (slot)))
721 {
722 if (stack_idx > 0)
723 {
724 ccl_prog = ccl_prog_stack_struct[0].ccl_prog;
725 ic = ccl_prog_stack_struct[0].ic;
726 }
727 CCL_INVALID_CMD;
728 }
729
730 ccl_prog_stack_struct[stack_idx].ccl_prog = ccl_prog;
731 ccl_prog_stack_struct[stack_idx].ic = ic;
732 stack_idx++;
733 ccl_prog = XVECTOR_DATA (XCDR (slot));
734 ic = CCL_HEADER_MAIN;
735 }
736 break;
737
738 case CCL_WriteConstString: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
739 if (!rrr)
740 CCL_WRITE_CHAR (field1);
233 else 741 else
234 ccl->status = CCL_STAT_SUCCESS;
235 CCL_READ_CHAR (reg[rrr]);
236 ic = cc;
237 continue;
238 case CCL_WriteSJump:
239 i = XINT (prog[ic]);
240 CCL_WRITE_STRING (i);
241 ic = cc;
242 continue;
243 case CCL_WriteSReadJump:
244 if (ccl->status != CCL_STAT_SUSPEND)
245 { 742 {
246 i = XINT (prog[ic]); 743 CCL_WRITE_STRING (field1);
247 CCL_WRITE_STRING (i); 744 ic += (field1 + 2) / 3;
248 } 745 }
249 else 746 break;
250 ccl->status = CCL_STAT_SUCCESS; 747
251 CCL_READ_CHAR (reg[rrr]); 748 case CCL_WriteArray: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
252 ic = cc; 749 i = reg[rrr];
253 continue; 750 if ((unsigned int) i < field1)
254 case CCL_WriteAReadJump:
255 if (ccl->status != CCL_STAT_SUSPEND)
256 { 751 {
257 i = XINT (prog[ic]); 752 j = XINT (ccl_prog[ic + i]);
258 if (reg[rrr] >= 0 && reg[rrr] < i) 753 CCL_WRITE_CHAR (j);
259 CCL_WRITE_CHAR (XINT (prog[ic + 1 + reg[rrr]]));
260 } 754 }
261 else 755 ic += field1;
262 ccl->status = CCL_STAT_SUCCESS; 756 break;
263 CCL_READ_CHAR (reg[rrr]); 757
264 ic = cc; 758 case CCL_End: /* 0000000000000000000000XXXXX */
265 continue; 759 if (stack_idx-- > 0)
266 case CCL_ReadBranch: 760 {
267 CCL_READ_CHAR (reg[rrr]); 761 ccl_prog = ccl_prog_stack_struct[stack_idx].ccl_prog;
268 case CCL_Branch: 762 ic = ccl_prog_stack_struct[stack_idx].ic;
269 ic = XINT (prog[ic + (((unsigned int) reg[rrr] < cc) 763 break;
270 ? reg[rrr] : cc)]); 764 }
271 continue;
272 case CCL_Read1:
273 CCL_READ_CHAR (reg[rrr]);
274 continue;
275 case CCL_Read2:
276 CCL_READ_CHAR (reg[rrr]);
277 CCL_READ_CHAR (reg[cc]);
278 continue;
279 case CCL_Write1:
280 CCL_WRITE_CHAR (reg[rrr]);
281 continue;
282 case CCL_Write2:
283 CCL_WRITE_CHAR (reg[rrr]);
284 CCL_WRITE_CHAR (reg[cc]);
285 continue;
286 case CCL_WriteC:
287 i = XINT (prog[ic++]);
288 CCL_WRITE_CHAR (i);
289 continue;
290 case CCL_WriteS:
291 cc = XINT (prog[ic]);
292 CCL_WRITE_STRING (cc);
293 ic += cc + 1;
294 continue;
295 case CCL_WriteA:
296 i = XINT (prog[ic++]);
297 cc = reg[rrr];
298 if (cc >= 0 && cc < i)
299 CCL_WRITE_CHAR (XINT (prog[ic + cc]));
300 ic += i;
301 continue;
302 case CCL_End:
303 CCL_SUCCESS; 765 CCL_SUCCESS;
304 case CCL_SetSelfCS: 766
305 i = cc; 767 case CCL_ExprSelfConst: /* 00000OPERATION000000rrrXXXXX */
306 op = XINT (prog[ic++]); 768 i = XINT (ccl_prog[ic]);
307 goto ccl_set_self; 769 ic++;
308 case CCL_SetSelfCL: 770 op = field1 >> 6;
309 i = XINT (prog[ic++]); 771 goto ccl_expr_self;
310 op = XINT (prog[ic++]); 772
311 goto ccl_set_self; 773 case CCL_ExprSelfReg: /* 00000OPERATION000RRRrrrXXXXX */
312 case CCL_SetSelfR: 774 i = reg[RRR];
313 i = reg[cc]; 775 op = field1 >> 6;
314 op = XINT (prog[ic++]); 776
315 ccl_set_self: 777 ccl_expr_self:
316 switch (op) 778 switch (op)
317 { 779 {
318 case CCL_PLUS: reg[rrr] += i; break; 780 case CCL_PLUS: reg[rrr] += i; break;
319 case CCL_MINUS: reg[rrr] -= i; break; 781 case CCL_MINUS: reg[rrr] -= i; break;
320 case CCL_MUL: reg[rrr] *= i; break; 782 case CCL_MUL: reg[rrr] *= i; break;
321 case CCL_DIV: reg[rrr] /= i; break; 783 case CCL_DIV: reg[rrr] /= i; break;
322 case CCL_MOD: reg[rrr] %= i; break; 784 case CCL_MOD: reg[rrr] %= i; break;
323 case CCL_AND: reg[rrr] &= i; break; 785 case CCL_AND: reg[rrr] &= i; break;
324 case CCL_OR: reg[rrr] |= i; break; 786 case CCL_OR: reg[rrr] |= i; break;
325 case CCL_XOR: reg[rrr] ^= i; break; 787 case CCL_XOR: reg[rrr] ^= i; break;
326 case CCL_LSH: reg[rrr] <<= i; break; 788 case CCL_LSH: reg[rrr] <<= i; break;
327 case CCL_RSH: reg[rrr] >>= i; break; 789 case CCL_RSH: reg[rrr] >>= i; break;
328 case CCL_LSH8: reg[rrr] <<= 8; reg[rrr] |= i; break; 790 case CCL_LSH8: reg[rrr] <<= 8; reg[rrr] |= i; break;
329 case CCL_RSH8: reg[7] = reg[rrr] & 0xFF; reg[rrr] >>= 8; break; 791 case CCL_RSH8: reg[7] = reg[rrr] & 0xFF; reg[rrr] >>= 8; break;
330 case CCL_DIVMOD: reg[7] = reg[rrr] % i; reg[rrr] /= i; break; 792 case CCL_DIVMOD: reg[7] = reg[rrr] % i; reg[rrr] /= i; break;
331 case CCL_LS: reg[rrr] = reg[rrr] < i; break; 793 case CCL_LS: reg[rrr] = reg[rrr] < i; break;
332 case CCL_GT: reg[rrr] = reg[rrr] > i; break; 794 case CCL_GT: reg[rrr] = reg[rrr] > i; break;
333 case CCL_EQ: reg[rrr] = reg[rrr] == i; break; 795 case CCL_EQ: reg[rrr] = reg[rrr] == i; break;
334 case CCL_LE: reg[rrr] = reg[rrr] <= i; break; 796 case CCL_LE: reg[rrr] = reg[rrr] <= i; break;
335 case CCL_GE: reg[rrr] = reg[rrr] >= i; break; 797 case CCL_GE: reg[rrr] = reg[rrr] >= i; break;
336 case CCL_NE: reg[rrr] = reg[rrr] != i; break; 798 case CCL_NE: reg[rrr] = reg[rrr] != i; break;
337 default: CCL_INVALID_CMD; 799 default: CCL_INVALID_CMD;
338 } 800 }
339 continue; 801 break;
340 case CCL_SetExprCL: 802
341 i = reg[cc]; 803 case CCL_SetExprConst: /* 00000OPERATION000RRRrrrXXXXX */
342 j = XINT (prog[ic++]); 804 i = reg[RRR];
343 op = XINT (prog[ic++]); 805 j = XINT (ccl_prog[ic]);
344 cc = 0; 806 op = field1 >> 6;
807 jump_address = ++ic;
345 goto ccl_set_expr; 808 goto ccl_set_expr;
346 case CCL_SetExprR: 809
347 i = reg[cc]; 810 case CCL_SetExprReg: /* 00000OPERATIONRrrRRRrrrXXXXX */
348 j = reg[XINT (prog[ic++])]; 811 i = reg[RRR];
349 op = XINT (prog[ic++]); 812 j = reg[Rrr];
350 cc = 0; 813 op = field1 >> 6;
814 jump_address = ic;
351 goto ccl_set_expr; 815 goto ccl_set_expr;
352 case CCL_ReadJumpCondC: 816
817 case CCL_ReadJumpCondExprConst: /* A--D--D--R--E--S--S-rrrXXXXX */
353 CCL_READ_CHAR (reg[rrr]); 818 CCL_READ_CHAR (reg[rrr]);
354 case CCL_JumpCondC: 819 case CCL_JumpCondExprConst: /* A--D--D--R--E--S--S-rrrXXXXX */
355 i = reg[rrr]; 820 i = reg[rrr];
356 j = XINT (prog[ic++]); 821 op = XINT (ccl_prog[ic]);
822 jump_address = ic++ + ADDR;
823 j = XINT (ccl_prog[ic]);
824 ic++;
357 rrr = 7; 825 rrr = 7;
358 op = XINT (prog[ic++]);
359 goto ccl_set_expr; 826 goto ccl_set_expr;
360 case CCL_ReadJumpCondR: 827
828 case CCL_ReadJumpCondExprReg: /* A--D--D--R--E--S--S-rrrXXXXX */
361 CCL_READ_CHAR (reg[rrr]); 829 CCL_READ_CHAR (reg[rrr]);
362 case CCL_JumpCondR: 830 case CCL_JumpCondExprReg:
363 i = reg[rrr]; 831 i = reg[rrr];
364 j = reg[XINT (prog[ic++])]; 832 op = XINT (ccl_prog[ic]);
833 jump_address = ic++ + ADDR;
834 j = reg[XINT (ccl_prog[ic])];
835 ic++;
365 rrr = 7; 836 rrr = 7;
366 op = XINT (prog[ic++]); 837
367 ccl_set_expr: 838 ccl_set_expr:
368 switch (op) 839 switch (op)
369 { 840 {
370 case CCL_PLUS: reg[rrr] = i + j; break; 841 case CCL_PLUS: reg[rrr] = i + j; break;
371 case CCL_MINUS: reg[rrr] = i - j; break; 842 case CCL_MINUS: reg[rrr] = i - j; break;
372 case CCL_MUL: reg[rrr] = i * j; break; 843 case CCL_MUL: reg[rrr] = i * j; break;
373 case CCL_DIV: reg[rrr] = i / j; break; 844 case CCL_DIV: reg[rrr] = i / j; break;
374 case CCL_MOD: reg[rrr] = i % j; break; 845 case CCL_MOD: reg[rrr] = i % j; break;
375 case CCL_AND: reg[rrr] = i & j; break; 846 case CCL_AND: reg[rrr] = i & j; break;
376 case CCL_OR: reg[rrr] = i | j; break; 847 case CCL_OR: reg[rrr] = i | j; break;
377 case CCL_XOR: reg[rrr] = i ^ j;; break; 848 case CCL_XOR: reg[rrr] = i ^ j;; break;
378 case CCL_LSH: reg[rrr] = i << j; break; 849 case CCL_LSH: reg[rrr] = i << j; break;
379 case CCL_RSH: reg[rrr] = i >> j; break; 850 case CCL_RSH: reg[rrr] = i >> j; break;
380 case CCL_LSH8: reg[rrr] = (i << 8) | j; break; 851 case CCL_LSH8: reg[rrr] = (i << 8) | j; break;
381 case CCL_RSH8: reg[rrr] = i >> 8; reg[7] = i & 0xFF; break; 852 case CCL_RSH8: reg[rrr] = i >> 8; reg[7] = i & 0xFF; break;
382 case CCL_DIVMOD: reg[rrr] = i / j; reg[7] = i % j; break; 853 case CCL_DIVMOD: reg[rrr] = i / j; reg[7] = i % j; break;
383 case CCL_LS: reg[rrr] = i < j; break; 854 case CCL_LS: reg[rrr] = i < j; break;
384 case CCL_GT: reg[rrr] = i > j; break; 855 case CCL_GT: reg[rrr] = i > j; break;
385 case CCL_EQ: reg[rrr] = i == j; break; 856 case CCL_EQ: reg[rrr] = i == j; break;
386 case CCL_LE: reg[rrr] = i <= j; break; 857 case CCL_LE: reg[rrr] = i <= j; break;
387 case CCL_GE: reg[rrr] = i >= j; break; 858 case CCL_GE: reg[rrr] = i >= j; break;
388 case CCL_NE: reg[rrr] = i != j; break; 859 case CCL_NE: reg[rrr] = i != j; break;
860 case CCL_ENCODE_SJIS: ENCODE_SJIS (i, j, reg[rrr], reg[7]); break;
861 case CCL_DECODE_SJIS: DECODE_SJIS (i, j, reg[rrr], reg[7]); break;
389 default: CCL_INVALID_CMD; 862 default: CCL_INVALID_CMD;
390 } 863 }
391 if (cc && !reg[rrr]) 864 code &= 0x1F;
392 ic = cc; 865 if (code == CCL_WriteExprConst || code == CCL_WriteExprRegister)
393 continue; 866 {
867 i = reg[rrr];
868 CCL_WRITE_CHAR (i);
869 }
870 else if (!reg[rrr])
871 ic = jump_address;
872 break;
873
394 default: 874 default:
395 CCL_INVALID_CMD; 875 CCL_INVALID_CMD;
396 } 876 }
397 } 877 }
398 878
399 ccl_error_handler: 879 ccl_error_handler:
400 if (dst) 880 if (destination)
401 { 881 {
402 char buf[200]; 882 /* We can insert an error message only if DESTINATION is
883 specified and we still have a room to store the message
884 there. */
885 char msg[256];
886
403 switch (ccl->status) 887 switch (ccl->status)
404 { 888 {
405 case CCL_STAT_INVALID_CMD: 889 case CCL_STAT_INVALID_CMD:
406 sprintf (buf, "CCL: Invalid command (%x).\n", op); 890 sprintf(msg, "\nCCL: Invalid command %x (ccl_code = %x) at %d.",
407 break; 891 code & 0x1F, code, ic);
892 #ifdef CCL_DEBUG
893 {
894 int i = ccl_backtrace_idx - 1;
895 int j;
896
897 Dynarr_add_many (destination, (unsigned char *) msg, strlen (msg));
898
899 for (j = 0; j < CCL_DEBUG_BACKTRACE_LEN; j++, i--)
900 {
901 if (i < 0) i = CCL_DEBUG_BACKTRACE_LEN - 1;
902 if (ccl_backtrace_table[i] == 0)
903 break;
904 sprintf(msg, " %d", ccl_backtrace_table[i]);
905 Dynarr_add_many (destination, (unsigned char *) msg, strlen (msg));
906 }
907 }
908 #endif
909 goto ccl_finish;
910
911 case CCL_STAT_QUIT:
912 sprintf(msg, "\nCCL: Quited.");
913 break;
914
408 default: 915 default:
409 sprintf (buf, "CCL: Unknown error type (%d).\n", ccl->status); 916 sprintf(msg, "\nCCL: Unknown error type (%d).", ccl->status);
410 } 917 }
411 Dynarr_add_many (dst, (unsigned char *) buf, strlen (buf)); 918
919 Dynarr_add_many (destination, (unsigned char *) msg, strlen (msg));
412 } 920 }
413 921
414 ccl_finish: 922 ccl_finish:
415 ccl->ic = ic; 923 ccl->ic = ic;
416 if (dst) 924 if (consumed) *consumed = src - source;
417 return Dynarr_length (dst); 925 if (destination)
926 return Dynarr_length (destination);
418 else 927 else
419 return 0; 928 return 0;
420 } 929 }
421 930
422 /* Set up CCL to execute CCL program VAL, with initial register values 931 /* Setup fields of the structure pointed by CCL appropriately for the
423 coming from REGS (NUMREGS of them are specified) and initial 932 execution of compiled CCL code in VEC (vector of integer). */
424 instruction counter coming from INITIAL_IC (a value of 0 means
425 start at the beginning of the program, wherever that is).
426 */
427
428 void 933 void
429 set_ccl_program (struct ccl_program *ccl, Lisp_Object val, int *regs, 934 setup_ccl_program (ccl, vec)
430 int numregs, int initial_ic) 935 struct ccl_program *ccl;
936 Lisp_Object vec;
431 { 937 {
432 int i; 938 int i;
433 939
434 ccl->saved_vector = val; 940 ccl->size = XVECTOR_LENGTH (vec);
435 ccl->prog = XVECTOR_DATA (val); 941 ccl->prog = XVECTOR_DATA (vec);
436 ccl->size = XVECTOR_LENGTH (val); 942 ccl->ic = CCL_HEADER_MAIN;
437 if (initial_ic == 0) 943 ccl->eof_ic = XINT (XVECTOR_DATA (vec)[CCL_HEADER_EOF]);
438 ccl->ic = CCL_HEADER_MAIN; 944 ccl->buf_magnification = XINT (XVECTOR_DATA (vec)[CCL_HEADER_BUF_MAG]);
439 else 945 for (i = 0; i < 8; i++)
440 ccl->ic = initial_ic;
441 for (i = 0; i < numregs; i++)
442 ccl->reg[i] = regs[i];
443 for (; i < 8; i++)
444 ccl->reg[i] = 0; 946 ccl->reg[i] = 0;
445 ccl->end_flag = 0; 947 ccl->last_block = 0;
446 ccl->status = 0; 948 ccl->status = 0;
447 } 949 }
448 950
449 #ifdef emacs 951 #ifdef emacs
450 952
451 static void 953 DEFUN ("ccl-execute", Fccl_execute, 2, 2, 0, /*
452 set_ccl_program_from_lisp_values (struct ccl_program *ccl, 954 Execute CCL-PROGRAM with registers initialized by REGISTERS.
453 Lisp_Object prog, 955 CCL-PROGRAM is a compiled code generated by `ccl-compile',
454 Lisp_Object status) 956 no I/O commands should appear in the CCL program.
957 REGISTERS is a vector of [R0 R1 ... R7] where RN is an initial value
958 of Nth register.
959 As side effect, each element of REGISTER holds the value of
960 corresponding register after the execution.
961 */
962 (ccl_prog, reg))
455 { 963 {
964 struct ccl_program ccl;
456 int i; 965 int i;
457 int intregs[8]; 966
458 int ic; 967 CHECK_VECTOR (ccl_prog);
459 968 CHECK_VECTOR (reg);
460 CHECK_VECTOR (prog); 969 if (XVECTOR_LENGTH (reg) != 8)
970 error ("Invalid length of vector REGISTERS");
971
972 setup_ccl_program (&ccl, ccl_prog);
973 for (i = 0; i < 8; i++)
974 ccl.reg[i] = (INTP (XVECTOR_DATA (reg)[i])
975 ? XINT (XVECTOR_DATA (reg)[i])
976 : 0);
977
978 ccl_driver (&ccl, (CONST unsigned char *)0, (unsigned_char_dynarr *)0,
979 0, (int *)0);
980 QUIT;
981 if (ccl.status != CCL_STAT_SUCCESS)
982 error ("Error in CCL program at %dth code", ccl.ic);
983
984 for (i = 0; i < 8; i++)
985 XSETINT (XVECTOR_DATA (reg)[i], ccl.reg[i]);
986 return Qnil;
987 }
988
989 DEFUN ("ccl-execute-on-string", Fccl_execute_on_string, 3, 4, 0, /*
990 Execute CCL-PROGRAM with initial STATUS on STRING.
991 CCL-PROGRAM is a compiled code generated by `ccl-compile'.
992 Read buffer is set to STRING, and write buffer is allocated automatically.
993 STATUS is a vector of [R0 R1 ... R7 IC], where
994 R0..R7 are initial values of corresponding registers,
995 IC is the instruction counter specifying from where to start the program.
996 If R0..R7 are nil, they are initialized to 0.
997 If IC is nil, it is initialized to head of the CCL program.
998 Returns the contents of write buffer as a string,
999 and as side effect, STATUS is updated.
1000 If optional 4th arg CONTINUE is non-nil, keep IC on read operation
1001 when read buffer is exausted, else, IC is always set to the end of
1002 CCL-PROGRAM on exit.
1003 */
1004 (ccl_prog, status, str, contin))
1005 {
1006 Lisp_Object val;
1007 struct ccl_program ccl;
1008 int i, produced;
1009 unsigned_char_dynarr *outbuf;
1010 struct gcpro gcpro1, gcpro2, gcpro3;
1011
1012 CHECK_VECTOR (ccl_prog);
461 CHECK_VECTOR (status); 1013 CHECK_VECTOR (status);
462
463 if (XVECTOR_LENGTH (status) != 9) 1014 if (XVECTOR_LENGTH (status) != 9)
464 signal_simple_error ("Must specify values for the eight registers and IC", 1015 error ("Invalid length of vector STATUS");
465 status); 1016 CHECK_STRING (str);
1017 GCPRO3 (ccl_prog, status, str);
1018
1019 setup_ccl_program (&ccl, ccl_prog);
466 for (i = 0; i < 8; i++) 1020 for (i = 0; i < 8; i++)
467 { 1021 {
468 Lisp_Object regval = XVECTOR_DATA (status)[i]; 1022 if (NILP (XVECTOR_DATA (status)[i]))
469 if (NILP (regval)) 1023 XSETINT (XVECTOR_DATA (status)[i], 0);
470 intregs[i] = 0; 1024 if (INTP (XVECTOR_DATA (status)[i]))
471 else 1025 ccl.reg[i] = XINT (XVECTOR_DATA (status)[i]);
1026 }
1027 if (INTP (XVECTOR_DATA (status)[8]))
1028 {
1029 i = XINT (XVECTOR_DATA (status)[8]);
1030 if (ccl.ic < i && i < ccl.size)
1031 ccl.ic = i;
1032 }
1033 outbuf = Dynarr_new (unsigned_char);
1034 ccl.last_block = NILP (contin);
1035 produced = ccl_driver (&ccl, XSTRING_DATA (str), outbuf,
1036 XSTRING_LENGTH (str), (int *)0);
1037 for (i = 0; i < 8; i++)
1038 XVECTOR_DATA (status)[i] = make_int(ccl.reg[i]);
1039 XSETINT (XVECTOR_DATA (status)[8], ccl.ic);
1040 UNGCPRO;
1041
1042 val = make_string (Dynarr_atp (outbuf, 0), produced);
1043 free (outbuf);
1044 QUIT;
1045 if (ccl.status != CCL_STAT_SUCCESS
1046 && ccl.status != CCL_STAT_SUSPEND)
1047 error ("Error in CCL program at %dth code", ccl.ic);
1048
1049 return val;
1050 }
1051
1052 DEFUN ("register-ccl-program", Fregister_ccl_program, 2, 2, 0, /*
1053 Register CCL program PROGRAM of NAME in `ccl-program-table'.
1054 PROGRAM should be a compiled code of CCL program, or nil.
1055 Return index number of the registered CCL program.
1056 */
1057 (name, ccl_prog))
1058 {
1059 int len = XVECTOR_LENGTH (Vccl_program_table);
1060 int i;
1061
1062 CHECK_SYMBOL (name);
1063 if (!NILP (ccl_prog))
1064 CHECK_VECTOR (ccl_prog);
1065
1066 for (i = 0; i < len; i++)
1067 {
1068 Lisp_Object slot = XVECTOR_DATA (Vccl_program_table)[i];
1069
1070 if (!CONSP (slot))
1071 break;
1072
1073 if (EQ (name, XCAR (slot)))
472 { 1074 {
473 CHECK_INT (regval); 1075 XCDR (slot) = ccl_prog;
474 intregs[i] = XINT (regval); 1076 return make_int (i);
475 } 1077 }
476 } 1078 }
477 1079
478 { 1080 if (i == len)
479 Lisp_Object lic = XVECTOR_DATA (status)[8]; 1081 {
480 if (NILP (lic)) 1082 Lisp_Object new_table = Fmake_vector (make_int (len * 2), Qnil);
481 ic = 0; 1083 int j;
482 else 1084
483 { 1085 for (j = 0; j < len; j++)
484 CHECK_NATNUM (lic); 1086 XVECTOR_DATA (new_table)[j]
485 ic = XINT (lic); 1087 = XVECTOR_DATA (Vccl_program_table)[j];
486 } 1088 Vccl_program_table = new_table;
487 } 1089 }
488 1090
489 set_ccl_program (ccl, prog, intregs, 8, ic); 1091 XVECTOR_DATA (Vccl_program_table)[i] = Fcons (name, ccl_prog);
490 } 1092 return make_int (i);
491
492 static void
493 set_lisp_status_from_ccl_program (Lisp_Object status,
494 struct ccl_program *ccl)
495 {
496 int i;
497
498 for (i = 0; i < 8; i++)
499 XVECTOR_DATA (status)[i] = make_int (ccl->reg[i]);
500 XVECTOR_DATA (status)[8] = make_int (ccl->ic);
501 }
502
503
504 DEFUN ("execute-ccl-program", Fexecute_ccl_program, 2, 2, 0, /*
505 Execute CCL-PROGRAM with registers initialized by STATUS.
506 CCL-PROGRAM is a vector of compiled CCL code created by `ccl-compile'.
507 STATUS must be a vector of nine values, specifying the initial value
508 for the R0, R1 .. R7 registers and for the instruction counter IC.
509 A nil value for a register initializer causes the register to be set
510 to 0. A nil value for the IC initializer causes execution to start
511 at the beginning of the program.
512 When the program is done, STATUS is modified (by side-effect) to contain
513 the ending values for the corresponding registers and IC.
514 */
515 (ccl_program, status))
516 {
517 struct ccl_program ccl;
518
519 set_ccl_program_from_lisp_values (&ccl, ccl_program, status);
520 ccl_driver (&ccl, 0, 0, 0, 0);
521 set_lisp_status_from_ccl_program (status, &ccl);
522 return Qnil;
523 }
524
525 DEFUN ("execute-ccl-program-string", Fexecute_ccl_program_string, 3, 3, 0, /*
526 Execute CCL-PROGRAM with initial STATUS on STRING.
527 CCL-PROGRAM is a vector of compiled CCL code created by `ccl-compile'.
528 STATUS must be a vector of nine values, specifying the initial value
529 for the R0, R1 .. R7 registers and for the instruction counter IC.
530 A nil value for a register initializer causes the register to be set
531 to 0. A nil value for the IC initializer causes execution to start
532 at the beginning of the program.
533 When the program is done, STATUS is modified (by side-effect) to contain
534 the ending values for the corresponding registers and IC.
535 Returns the resulting string.
536 */
537 (ccl_program, status, str))
538 {
539 struct ccl_program ccl;
540 Lisp_Object val;
541 int len;
542 unsigned_char_dynarr *outbuf;
543
544 set_ccl_program_from_lisp_values (&ccl, ccl_program, status);
545 CHECK_STRING (str);
546
547 outbuf = Dynarr_new (unsigned_char);
548 len = ccl_driver (&ccl, XSTRING_DATA (str), outbuf, XSTRING_LENGTH (str), 0);
549 ccl_driver (&ccl, (unsigned char *) "", outbuf, 0, 1);
550 set_lisp_status_from_ccl_program (status, &ccl);
551
552 val = make_string (Dynarr_atp (outbuf, 0), len);
553 Dynarr_free (outbuf);
554 return val;
555 }
556
557 DEFUN ("ccl-reset-elapsed-time", Fccl_reset_elapsed_time, 0, 0, 0, /*
558 Reset the internal value which holds the time elapsed by CCL interpreter.
559 */
560 ())
561 {
562 error ("Not yet implemented; use `current-process-time'");
563 return Qnil;
564 }
565
566 DEFUN ("ccl-elapsed-time", Fccl_elapsed_time, 0, 0, 0, /*
567 Return the time elapsed by CCL interpreter as cons of user and system time.
568 This measures processor time, not real time. Both values are floating point
569 numbers measured in seconds. If only one overall value can be determined,
570 the return value will be a cons of that value and 0.
571 */
572 ())
573 {
574 error ("Not yet implemented; use `current-process-time'");
575 return Qnil;
576 } 1093 }
577 1094
578 void 1095 void
579 syms_of_mule_ccl (void) 1096 syms_of_mule_ccl (void)
580 { 1097 {
581 DEFSUBR (Fexecute_ccl_program); 1098 staticpro (&Vccl_program_table);
582 DEFSUBR (Fexecute_ccl_program_string); 1099 Vccl_program_table = Fmake_vector (make_int (32), Qnil);
583 DEFSUBR (Fccl_reset_elapsed_time); 1100
584 DEFSUBR (Fccl_elapsed_time); 1101 DEFVAR_LISP ("font-ccl-encoder-alist", &Vfont_ccl_encoder_alist /*
1102 Alist of fontname patterns vs corresponding CCL program.
1103 Each element looks like (REGEXP . CCL-CODE),
1104 where CCL-CODE is a compiled CCL program.
1105 When a font whose name matches REGEXP is used for displaying a character,
1106 CCL-CODE is executed to calculate the code point in the font
1107 from the charset number and position code(s) of the character which are set
1108 in CCL registers R0, R1, and R2 before the execution.
1109 The code point in the font is set in CCL registers R1 and R2
1110 when the execution terminated.
1111 If the font is single-byte font, the register R2 is not used.
1112 */ );
1113 Vfont_ccl_encoder_alist = Qnil;
1114
1115 DEFSUBR (Fccl_execute);
1116 DEFSUBR (Fccl_execute_on_string);
1117 DEFSUBR (Fregister_ccl_program);
585 } 1118 }
586 1119
587 #else /* not emacs */ 1120 #endif /* emacs */
588 #ifdef standalone
589
590 #define INBUF_SIZE 1024
591 #define MAX_CCL_CODE_SIZE 4096
592
593 void
594 main (int argc, char **argv)
595 {
596 FILE *progf;
597 char inbuf[INBUF_SIZE];
598 unsigned_char_dynarr *outbuf;
599 struct ccl_program ccl;
600 int i;
601 Lisp_Object ccl_prog = make_vector (MAX_CCL_CODE_SIZE);
602
603 if (argc < 2)
604 {
605 fprintf (stderr,
606 "Usage: %s ccl_program_file_name <infile >outfile\n",
607 argv[0]);
608 exit (1);
609 }
610
611 if ((progf = fopen (argv[1], "r")) == NULL)
612 {
613 fprintf (stderr, "%s: Can't read file %s", argv[0], argv[1]);
614 exit (1);
615 }
616
617 XVECTOR_LENGTH (ccl_prog) = 0;
618 while (fscanf (progf, "%x", &i) == 1)
619 XVECTOR_DATA (ccl_prog)[XVECTOR_LENGTH (ccl_prog)++] = make_int (i);
620 set_ccl_program (&ccl, ccl_prog, 0, 0, 0);
621
622 outbuf = Dynarr_new (unsigned char);
623
624 while ((i = fread (inbuf, 1, INBUF_SIZE, stdin)) == INBUF_SIZE)
625 {
626 i = ccl_driver (&ccl, inbuf, outbuf, INBUF_SIZE, 0);
627 fwrite (Dynarr_atp (outbuf, 0), 1, i, stdout);
628 }
629 if (i)
630 {
631 i = ccl_driver (&ccl, inbuf, outbuf, i, 1);
632 fwrite (Dynarr_atp (outbuf, 0), 1, i, stdout);
633 }
634
635 fclose (progf);
636 exit (0);
637 }
638 #endif /* standalone */
639 #endif /* not emacs */