This source file includes following definitions.
- ccl_debug_hook
- GET_TRANSLATION_TABLE
- ccl_driver
- resolve_symbol_ccl_program
- ccl_get_compiled_code
- setup_ccl_program
- DEFUN
- syms_of_ccl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include <config.h>
27
28 #include <stdio.h>
29 #include <limits.h>
30
31 #include "lisp.h"
32 #include "character.h"
33 #include "charset.h"
34 #include "ccl.h"
35 #include "coding.h"
36 #include "keyboard.h"
37
38
39 #if GNUC_PREREQ (12, 0, 0)
40 # pragma GCC diagnostic ignored "-Wanalyzer-use-of-uninitialized-value"
41 #endif
42
43
44
45
46
47
48
49
50 static Lisp_Object Vccl_program_table;
51
52
53 #define GET_HASH_TABLE(id) \
54 (XHASH_TABLE (XCDR (AREF (Vtranslation_hash_table_vector, (id)))))
55
56
57
58
59
60
61
62
63
64
65
66
67
68 #define CCL_HEADER_BUF_MAG 0
69 #define CCL_HEADER_EOF 1
70 #define CCL_HEADER_MAIN 2
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 #define CCL_CODE_MAX ((1 << (28 - 1)) - 1)
92 #define CCL_CODE_MIN (-1 - CCL_CODE_MAX)
93
94
95
96
97
98
99
100 #define CCL_SetRegister 0x00
101
102
103
104
105
106 #define CCL_SetShortConst 0x01
107
108
109
110
111
112 #define CCL_SetConst 0x02
113
114
115
116
117
118
119
120 #define CCL_SetArray 0x03
121
122
123
124
125
126
127
128
129
130
131 #define CCL_Jump 0x04
132
133
134
135
136
137
138
139 #define CCL_JumpCond 0x05
140
141
142
143
144
145
146
147 #define CCL_WriteRegisterJump 0x06
148
149
150
151
152
153
154 #define CCL_WriteRegisterReadJump 0x07
155
156
157
158
159
160
161
162
163
164
165
166 #define CCL_WriteConstJump 0x08
167
168
169
170
171
172
173
174 #define CCL_WriteConstReadJump 0x09
175
176
177
178
179
180
181
182
183
184
185
186
187 #define CCL_WriteStringJump 0x0A
188
189
190
191
192
193
194
195
196
197
198
199
200 #define CCL_WriteArrayReadJump 0x0B
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 #define CCL_ReadJump 0x0C
218
219
220
221
222
223
224 #define CCL_Branch 0x0D
225
226
227
228
229
230
231
232
233
234
235
236 #define CCL_ReadRegister 0x0E
237
238
239
240
241
242
243
244
245 #define CCL_WriteExprConst 0x0F
246
247
248
249
250
251
252
253
254
255
256 #define CCL_ReadBranch 0x10
257
258
259
260
261
262
263
264
265
266
267
268
269
270 #define CCL_WriteRegister 0x11
271
272
273
274
275
276
277
278
279
280
281
282
283 #define CCL_WriteExprRegister 0x12
284
285
286
287
288
289 #define CCL_Call 0x13
290
291
292
293
294
295
296
297
298
299
300
301 #define CCL_WriteConstString 0x14
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316 #define CCL_WriteArray 0x15
317
318
319
320
321
322
323
324
325
326
327 #define CCL_End 0x16
328
329
330
331
332
333
334
335
336 #define CCL_ExprSelfConst 0x17
337
338
339
340
341
342
343 #define CCL_ExprSelfReg 0x18
344
345
346
347
348
349
350
351
352 #define CCL_SetExprConst 0x19
353
354
355
356
357
358
359
360 #define CCL_SetExprReg 0x1A
361
362
363
364
365
366 #define CCL_JumpCondExprConst 0x1B
367
368
369
370
371
372
373
374
375
376
377
378
379 #define CCL_JumpCondExprReg 0x1C
380
381
382
383
384
385
386
387
388
389
390
391
392 #define CCL_ReadJumpCondExprConst 0x1D
393
394
395
396
397
398
399
400
401
402
403
404
405
406 #define CCL_ReadJumpCondExprReg 0x1E
407
408
409
410
411
412
413
414
415
416
417
418
419
420 #define CCL_Extension 0x1F
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438 #define CCL_ReadMultibyteChar2 0x00
439
440
441
442
443
444
445 #define CCL_WriteMultibyteChar2 0x01
446
447
448
449
450
451
452
453
454 #define CCL_TranslateCharacter 0x02
455
456
457
458
459
460
461
462
463 #define CCL_TranslateCharacterConstTbl 0x03
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480 #define CCL_IterateMultipleMap 0x10
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571 #define CCL_MapMultiple 0x11
572
573
574
575
576
577
578
579
580
581
582
583
584 #define MAX_MAP_SET_LEVEL 30
585
586 typedef struct
587 {
588 int rest_length;
589 int orig_val;
590 } tr_stack;
591
592 static tr_stack mapping_stack[MAX_MAP_SET_LEVEL];
593 static tr_stack *mapping_stack_pointer;
594
595
596
597 static int stack_idx_of_map_multiple;
598
599 #define PUSH_MAPPING_STACK(restlen, orig) \
600 do \
601 { \
602 mapping_stack_pointer->rest_length = (restlen); \
603 mapping_stack_pointer->orig_val = (orig); \
604 mapping_stack_pointer++; \
605 } \
606 while (0)
607
608 #define POP_MAPPING_STACK(restlen, orig) \
609 do \
610 { \
611 mapping_stack_pointer--; \
612 (restlen) = mapping_stack_pointer->rest_length; \
613 (orig) = mapping_stack_pointer->orig_val; \
614 } \
615 while (0)
616
617 #define CCL_CALL_FOR_MAP_INSTRUCTION(symbol, ret_ic) \
618 do \
619 { \
620 struct ccl_program called_ccl; \
621 if (stack_idx >= 256 \
622 || ! setup_ccl_program (&called_ccl, (symbol))) \
623 { \
624 if (stack_idx > 0) \
625 { \
626 ccl_prog = ccl_prog_stack_struct[0].ccl_prog; \
627 ic = ccl_prog_stack_struct[0].ic; \
628 eof_ic = ccl_prog_stack_struct[0].eof_ic; \
629 } \
630 CCL_INVALID_CMD; \
631 } \
632 ccl_prog_stack_struct[stack_idx].ccl_prog = ccl_prog; \
633 ccl_prog_stack_struct[stack_idx].ic = (ret_ic); \
634 ccl_prog_stack_struct[stack_idx].eof_ic = eof_ic; \
635 stack_idx++; \
636 ccl_prog = called_ccl.prog; \
637 ic = CCL_HEADER_MAIN; \
638 eof_ic = XFIXNAT (ccl_prog[CCL_HEADER_EOF]); \
639 goto ccl_repeat; \
640 } \
641 while (0)
642
643 #define CCL_MapSingle 0x12
644
645
646
647
648
649
650
651
652
653
654 #define CCL_LookupIntConstTbl 0x13
655
656
657
658
659
660 #define CCL_LookupCharConstTbl 0x14
661
662
663
664
665
666
667 #define CCL_PLUS 0x00
668 #define CCL_MINUS 0x01
669 #define CCL_MUL 0x02
670 #define CCL_DIV 0x03
671 #define CCL_MOD 0x04
672 #define CCL_AND 0x05
673 #define CCL_OR 0x06
674 #define CCL_XOR 0x07
675 #define CCL_LSH 0x08
676 #define CCL_RSH 0x09
677 #define CCL_LSH8 0x0A
678 #define CCL_RSH8 0x0B
679 #define CCL_DIVMOD 0x0C
680 #define CCL_LS 0x10
681 #define CCL_GT 0x11
682 #define CCL_EQ 0x12
683 #define CCL_LE 0x13
684 #define CCL_GE 0x14
685 #define CCL_NE 0x15
686
687 #define CCL_DECODE_SJIS 0x16
688
689 #define CCL_ENCODE_SJIS 0x17
690
691
692
693 #define CCL_SUCCESS \
694 do \
695 { \
696 ccl->status = CCL_STAT_SUCCESS; \
697 goto ccl_finish; \
698 } \
699 while (0)
700
701
702
703
704 #define CCL_SUSPEND(stat) \
705 do \
706 { \
707 ic--; \
708 ccl->status = stat; \
709 goto ccl_finish; \
710 } \
711 while (0)
712
713
714
715 #ifndef CCL_DEBUG
716
717 #define CCL_INVALID_CMD \
718 do \
719 { \
720 ccl->status = CCL_STAT_INVALID_CMD; \
721 goto ccl_error_handler; \
722 } \
723 while (0)
724
725 #else
726
727 #define CCL_INVALID_CMD \
728 do \
729 { \
730 ccl_debug_hook (this_ic); \
731 ccl->status = CCL_STAT_INVALID_CMD; \
732 goto ccl_error_handler; \
733 } \
734 while (0)
735
736 #endif
737
738
739
740 #define ASCENDING_ORDER(lo, med, hi) (((lo) <= (med)) & ((med) <= (hi)))
741
742 #define GET_CCL_RANGE(var, ccl_prog, ic, lo, hi) \
743 do \
744 { \
745 EMACS_INT prog_word = XFIXNUM ((ccl_prog)[ic]); \
746 if (! ASCENDING_ORDER (lo, prog_word, hi)) \
747 CCL_INVALID_CMD; \
748 (var) = prog_word; \
749 } \
750 while (0)
751
752 #define GET_CCL_CODE(code, ccl_prog, ic) \
753 GET_CCL_RANGE (code, ccl_prog, ic, CCL_CODE_MIN, CCL_CODE_MAX)
754
755 #define IN_INT_RANGE(val) ASCENDING_ORDER (INT_MIN, val, INT_MAX)
756
757
758
759 #define CCL_WRITE_CHAR(ch) \
760 do { \
761 if (! dst) \
762 CCL_INVALID_CMD; \
763 else if (dst < dst_end) \
764 *dst++ = (ch); \
765 else \
766 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
767 } while (0)
768
769
770
771 #define CCL_WRITE_STRING(len) \
772 do { \
773 int ccli; \
774 if (!dst) \
775 CCL_INVALID_CMD; \
776 else if (dst + len <= dst_end) \
777 { \
778 if (XFIXNAT (ccl_prog[ic]) & 0x1000000) \
779 for (ccli = 0; ccli < len; ccli++) \
780 *dst++ = XFIXNAT (ccl_prog[ic + ccli]) & 0xFFFFFF; \
781 else \
782 for (ccli = 0; ccli < len; ccli++) \
783 *dst++ = ((XFIXNAT (ccl_prog[ic + (ccli / 3)])) \
784 >> ((2 - (ccli % 3)) * 8)) & 0xFF; \
785 } \
786 else \
787 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \
788 } while (0)
789
790
791 #define CCL_READ_CHAR(r) \
792 do { \
793 if (! src) \
794 CCL_INVALID_CMD; \
795 else if (src < src_end) \
796 r = *src++; \
797 else if (ccl->last_block) \
798 { \
799 r = -1; \
800 ic = ccl->eof_ic; \
801 goto ccl_repeat; \
802 } \
803 else \
804 CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); \
805 } while (0)
806
807
808
809
810
811 #define CCL_DECODE_CHAR(id, code) \
812 ((id) == 0 ? (code) \
813 : (charset = CHARSET_FROM_ID ((id)), DECODE_CHAR (charset, (code))))
814
815
816
817
818
819 #define CCL_ENCODE_CHAR(c, charset_list, id, encoded) \
820 do { \
821 unsigned ncode; \
822 \
823 charset = char_charset ((c), (charset_list), &ncode); \
824 if (! charset && ! NILP (charset_list)) \
825 charset = char_charset ((c), Qnil, &ncode); \
826 if (charset) \
827 { \
828 (id) = CHARSET_ID (charset); \
829 (encoded) = ncode; \
830 } \
831 } while (0)
832
833
834
835
836
837
838
839
840
841 #ifdef CCL_DEBUG
842 #define CCL_DEBUG_BACKTRACE_LEN 256
843 int ccl_backtrace_table[CCL_DEBUG_BACKTRACE_LEN];
844 int ccl_backtrace_idx;
845
846 int
847 ccl_debug_hook (int ic)
848 {
849 return ic;
850 }
851
852 #endif
853
854 struct ccl_prog_stack
855 {
856 Lisp_Object *ccl_prog;
857 int ic;
858 int eof_ic;
859 };
860
861
862 static struct ccl_prog_stack ccl_prog_stack_struct[256];
863
864
865 static inline Lisp_Object
866 GET_TRANSLATION_TABLE (int id)
867 {
868 return XCDR (XVECTOR (Vtranslation_table_vector)->contents[id]);
869 }
870
871 void
872 ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size, int dst_size, Lisp_Object charset_list)
873 {
874 register int *reg = ccl->reg;
875 register int ic = ccl->ic;
876 register int code = 0, field1, field2;
877 register Lisp_Object *ccl_prog = ccl->prog;
878 int *src = source, *src_end = src + src_size;
879 int *dst = destination, *dst_end = dst + dst_size;
880 int jump_address;
881 int i = 0, j, op;
882 int stack_idx = ccl->stack_idx;
883
884 int this_ic = 0;
885 struct charset *charset;
886 int eof_ic = ccl->eof_ic;
887 int eof_hit = 0;
888
889 if (ccl->buf_magnification == 0)
890 dst = NULL;
891
892
893 mapping_stack_pointer = mapping_stack;
894
895 #ifdef CCL_DEBUG
896 ccl_backtrace_idx = 0;
897 #endif
898
899 for (;;)
900 {
901 ccl_repeat:
902 #ifdef CCL_DEBUG
903 ccl_backtrace_table[ccl_backtrace_idx++] = ic;
904 if (ccl_backtrace_idx >= CCL_DEBUG_BACKTRACE_LEN)
905 ccl_backtrace_idx = 0;
906 ccl_backtrace_table[ccl_backtrace_idx] = 0;
907 #endif
908
909 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
910 {
911
912
913
914 if (src)
915 src = source + src_size;
916 ccl->status = CCL_STAT_QUIT;
917 break;
918 }
919
920 this_ic = ic;
921 GET_CCL_CODE (code, ccl_prog, ic++);
922 field1 = code >> 8;
923 field2 = (code & 0xFF) >> 5;
924
925 #define rrr field2
926 #define RRR (field1 & 7)
927 #define Rrr ((field1 >> 3) & 7)
928 #define ADDR field1
929 #define EXCMD (field1 >> 6)
930
931 switch (code & 0x1F)
932 {
933 case CCL_SetRegister:
934 reg[rrr] = reg[RRR];
935 break;
936
937 case CCL_SetShortConst:
938 reg[rrr] = field1;
939 break;
940
941 case CCL_SetConst:
942 reg[rrr] = XFIXNUM (ccl_prog[ic++]);
943 break;
944
945 case CCL_SetArray:
946 i = reg[RRR];
947 j = field1 >> 3;
948 if (0 <= i && i < j)
949 reg[rrr] = XFIXNUM (ccl_prog[ic + i]);
950 ic += j;
951 break;
952
953 case CCL_Jump:
954 ic += ADDR;
955 break;
956
957 case CCL_JumpCond:
958 if (!reg[rrr])
959 ic += ADDR;
960 break;
961
962 case CCL_WriteRegisterJump:
963 i = reg[rrr];
964 CCL_WRITE_CHAR (i);
965 ic += ADDR;
966 break;
967
968 case CCL_WriteRegisterReadJump:
969 i = reg[rrr];
970 CCL_WRITE_CHAR (i);
971 ic++;
972 CCL_READ_CHAR (reg[rrr]);
973 ic += ADDR - 1;
974 break;
975
976 case CCL_WriteConstJump:
977 i = XFIXNUM (ccl_prog[ic]);
978 CCL_WRITE_CHAR (i);
979 ic += ADDR;
980 break;
981
982 case CCL_WriteConstReadJump:
983 i = XFIXNUM (ccl_prog[ic]);
984 CCL_WRITE_CHAR (i);
985 ic++;
986 CCL_READ_CHAR (reg[rrr]);
987 ic += ADDR - 1;
988 break;
989
990 case CCL_WriteStringJump:
991 j = XFIXNUM (ccl_prog[ic++]);
992 CCL_WRITE_STRING (j);
993 ic += ADDR - 1;
994 break;
995
996 case CCL_WriteArrayReadJump:
997 i = reg[rrr];
998 j = XFIXNUM (ccl_prog[ic]);
999 if (0 <= i && i < j)
1000 {
1001 i = XFIXNUM (ccl_prog[ic + 1 + i]);
1002 CCL_WRITE_CHAR (i);
1003 }
1004 ic += j + 2;
1005 CCL_READ_CHAR (reg[rrr]);
1006 ic += ADDR - (j + 2);
1007 break;
1008
1009 case CCL_ReadJump:
1010 CCL_READ_CHAR (reg[rrr]);
1011 ic += ADDR;
1012 break;
1013
1014 case CCL_ReadBranch:
1015 CCL_READ_CHAR (reg[rrr]);
1016 FALLTHROUGH;
1017 case CCL_Branch:
1018 {
1019 int ioff = 0 <= reg[rrr] && reg[rrr] < field1 ? reg[rrr] : field1;
1020 int incr = XFIXNUM (ccl_prog[ic + ioff]);
1021 ic += incr;
1022 }
1023 break;
1024
1025 case CCL_ReadRegister:
1026 while (1)
1027 {
1028 CCL_READ_CHAR (reg[rrr]);
1029 if (!field1) break;
1030 GET_CCL_CODE (code, ccl_prog, ic++);
1031 field1 = code >> 8;
1032 field2 = (code & 0xFF) >> 5;
1033 }
1034 break;
1035
1036 case CCL_WriteExprConst:
1037 rrr = 7;
1038 i = reg[RRR];
1039 j = XFIXNUM (ccl_prog[ic]);
1040 op = field1 >> 6;
1041 jump_address = ic + 1;
1042 goto ccl_set_expr;
1043
1044 case CCL_WriteRegister:
1045 while (1)
1046 {
1047 i = reg[rrr];
1048 CCL_WRITE_CHAR (i);
1049 if (!field1) break;
1050 GET_CCL_CODE (code, ccl_prog, ic++);
1051 field1 = code >> 8;
1052 field2 = (code & 0xFF) >> 5;
1053 }
1054 break;
1055
1056 case CCL_WriteExprRegister:
1057 rrr = 7;
1058 i = reg[RRR];
1059 j = reg[Rrr];
1060 op = field1 >> 6;
1061 jump_address = ic;
1062 goto ccl_set_expr;
1063
1064 case CCL_Call:
1065 {
1066 Lisp_Object slot;
1067 int prog_id;
1068
1069
1070
1071 if (rrr)
1072 prog_id = XFIXNUM (ccl_prog[ic++]);
1073 else
1074 prog_id = field1;
1075
1076 if (stack_idx >= 256
1077 || prog_id < 0
1078 || prog_id >= ASIZE (Vccl_program_table)
1079 || (slot = AREF (Vccl_program_table, prog_id), !VECTORP (slot))
1080 || !VECTORP (AREF (slot, 1)))
1081 {
1082 if (stack_idx > 0)
1083 {
1084 ccl_prog = ccl_prog_stack_struct[0].ccl_prog;
1085 ic = ccl_prog_stack_struct[0].ic;
1086 eof_ic = ccl_prog_stack_struct[0].eof_ic;
1087 }
1088 CCL_INVALID_CMD;
1089 }
1090
1091 ccl_prog_stack_struct[stack_idx].ccl_prog = ccl_prog;
1092 ccl_prog_stack_struct[stack_idx].ic = ic;
1093 ccl_prog_stack_struct[stack_idx].eof_ic = eof_ic;
1094 stack_idx++;
1095 ccl_prog = XVECTOR (AREF (slot, 1))->contents;
1096 ic = CCL_HEADER_MAIN;
1097 eof_ic = XFIXNAT (ccl_prog[CCL_HEADER_EOF]);
1098 }
1099 break;
1100
1101 case CCL_WriteConstString:
1102 if (!rrr)
1103 CCL_WRITE_CHAR (field1);
1104 else
1105 {
1106 CCL_WRITE_STRING (field1);
1107 ic += (field1 + 2) / 3;
1108 }
1109 break;
1110
1111 case CCL_WriteArray:
1112 i = reg[rrr];
1113 if (0 <= i && i < field1)
1114 {
1115 j = XFIXNUM (ccl_prog[ic + i]);
1116 CCL_WRITE_CHAR (j);
1117 }
1118 ic += field1;
1119 break;
1120
1121 case CCL_End:
1122 if (stack_idx > 0)
1123 {
1124 stack_idx--;
1125 ccl_prog = ccl_prog_stack_struct[stack_idx].ccl_prog;
1126 ic = ccl_prog_stack_struct[stack_idx].ic;
1127 eof_ic = ccl_prog_stack_struct[stack_idx].eof_ic;
1128 if (eof_hit)
1129 ic = eof_ic;
1130 break;
1131 }
1132 if (src)
1133 src = src_end;
1134
1135
1136 ic--;
1137 CCL_SUCCESS;
1138
1139 case CCL_ExprSelfConst:
1140 i = XFIXNUM (ccl_prog[ic++]);
1141 op = field1 >> 6;
1142 goto ccl_expr_self;
1143
1144 case CCL_ExprSelfReg:
1145 i = reg[RRR];
1146 op = field1 >> 6;
1147
1148 ccl_expr_self:
1149 switch (op)
1150 {
1151 case CCL_PLUS: INT_ADD_WRAPV (reg[rrr], i, ®[rrr]); break;
1152 case CCL_MINUS: INT_SUBTRACT_WRAPV (reg[rrr], i, ®[rrr]); break;
1153 case CCL_MUL: INT_MULTIPLY_WRAPV (reg[rrr], i, ®[rrr]); break;
1154 case CCL_DIV:
1155 if (!i)
1156 CCL_INVALID_CMD;
1157 if (!INT_DIVIDE_OVERFLOW (reg[rrr], i))
1158 reg[rrr] /= i;
1159 break;
1160 case CCL_MOD:
1161 if (!i)
1162 CCL_INVALID_CMD;
1163 reg[rrr] = i == -1 ? 0 : reg[rrr] % i;
1164 break;
1165 case CCL_AND: reg[rrr] &= i; break;
1166 case CCL_OR: reg[rrr] |= i; break;
1167 case CCL_XOR: reg[rrr] ^= i; break;
1168 case CCL_LSH:
1169 if (i < 0)
1170 CCL_INVALID_CMD;
1171 reg[rrr] = i < UINT_WIDTH ? (unsigned) reg[rrr] << i : 0;
1172 break;
1173 case CCL_RSH:
1174 if (i < 0)
1175 CCL_INVALID_CMD;
1176 reg[rrr] = reg[rrr] >> min (i, INT_WIDTH - 1);
1177 break;
1178 case CCL_LSH8:
1179 reg[rrr] = (unsigned) reg[rrr] << 8;
1180 reg[rrr] |= i;
1181 break;
1182 case CCL_RSH8: reg[7] = reg[rrr] & 0xFF; reg[rrr] >>= 8; break;
1183 case CCL_DIVMOD:
1184 if (!i)
1185 CCL_INVALID_CMD;
1186 if (i == -1)
1187 {
1188 reg[7] = 0;
1189 INT_SUBTRACT_WRAPV (0, reg[rrr], ®[rrr]);
1190 }
1191 else
1192 {
1193 reg[7] = reg[rrr] % i;
1194 reg[rrr] /= i;
1195 }
1196 break;
1197 case CCL_LS: reg[rrr] = reg[rrr] < i; break;
1198 case CCL_GT: reg[rrr] = reg[rrr] > i; break;
1199 case CCL_EQ: reg[rrr] = reg[rrr] == i; break;
1200 case CCL_LE: reg[rrr] = reg[rrr] <= i; break;
1201 case CCL_GE: reg[rrr] = reg[rrr] >= i; break;
1202 case CCL_NE: reg[rrr] = reg[rrr] != i; break;
1203 default: CCL_INVALID_CMD;
1204 }
1205 break;
1206
1207 case CCL_SetExprConst:
1208 i = reg[RRR];
1209 j = XFIXNUM (ccl_prog[ic++]);
1210 op = field1 >> 6;
1211 jump_address = ic;
1212 goto ccl_set_expr;
1213
1214 case CCL_SetExprReg:
1215 i = reg[RRR];
1216 j = reg[Rrr];
1217 op = field1 >> 6;
1218 jump_address = ic;
1219 goto ccl_set_expr;
1220
1221 case CCL_ReadJumpCondExprConst:
1222 CCL_READ_CHAR (reg[rrr]);
1223 FALLTHROUGH;
1224 case CCL_JumpCondExprConst:
1225 i = reg[rrr];
1226 jump_address = ic + ADDR;
1227 op = XFIXNUM (ccl_prog[ic++]);
1228 j = XFIXNUM (ccl_prog[ic++]);
1229 rrr = 7;
1230 goto ccl_set_expr;
1231
1232 case CCL_ReadJumpCondExprReg:
1233 CCL_READ_CHAR (reg[rrr]);
1234 FALLTHROUGH;
1235 case CCL_JumpCondExprReg:
1236 i = reg[rrr];
1237 jump_address = ic + ADDR;
1238 op = XFIXNUM (ccl_prog[ic++]);
1239 GET_CCL_RANGE (j, ccl_prog, ic++, 0, 7);
1240 j = reg[j];
1241 rrr = 7;
1242
1243 ccl_set_expr:
1244 switch (op)
1245 {
1246 case CCL_PLUS: INT_ADD_WRAPV (i, j, ®[rrr]); break;
1247 case CCL_MINUS: INT_SUBTRACT_WRAPV (i, j, ®[rrr]); break;
1248 case CCL_MUL: INT_MULTIPLY_WRAPV (i, j, ®[rrr]); break;
1249 case CCL_DIV:
1250 if (!j)
1251 CCL_INVALID_CMD;
1252 if (!INT_DIVIDE_OVERFLOW (i, j))
1253 i /= j;
1254 reg[rrr] = i;
1255 break;
1256 case CCL_MOD:
1257 if (!j)
1258 CCL_INVALID_CMD;
1259 reg[rrr] = j == -1 ? 0 : i % j;
1260 break;
1261 case CCL_AND: reg[rrr] = i & j; break;
1262 case CCL_OR: reg[rrr] = i | j; break;
1263 case CCL_XOR: reg[rrr] = i ^ j; break;
1264 case CCL_LSH:
1265 if (j < 0)
1266 CCL_INVALID_CMD;
1267 reg[rrr] = j < UINT_WIDTH ? (unsigned) i << j : 0;
1268 break;
1269 case CCL_RSH:
1270 if (j < 0)
1271 CCL_INVALID_CMD;
1272 reg[rrr] = i >> min (j, INT_WIDTH - 1);
1273 break;
1274 case CCL_LSH8:
1275 reg[rrr] = ((unsigned) i << 8) | j;
1276 break;
1277 case CCL_RSH8: reg[rrr] = i >> 8; reg[7] = i & 0xFF; break;
1278 case CCL_DIVMOD:
1279 if (!j)
1280 CCL_INVALID_CMD;
1281 if (j == -1)
1282 {
1283 INT_SUBTRACT_WRAPV (0, reg[rrr], ®[rrr]);
1284 reg[7] = 0;
1285 }
1286 else
1287 {
1288 reg[rrr] = i / j;
1289 reg[7] = i % j;
1290 }
1291 break;
1292 case CCL_LS: reg[rrr] = i < j; break;
1293 case CCL_GT: reg[rrr] = i > j; break;
1294 case CCL_EQ: reg[rrr] = i == j; break;
1295 case CCL_LE: reg[rrr] = i <= j; break;
1296 case CCL_GE: reg[rrr] = i >= j; break;
1297 case CCL_NE: reg[rrr] = i != j; break;
1298 case CCL_DECODE_SJIS:
1299 {
1300 i = ((unsigned) i << 8) | j;
1301 SJIS_TO_JIS (i);
1302 reg[rrr] = i >> 8;
1303 reg[7] = i & 0xFF;
1304 break;
1305 }
1306 case CCL_ENCODE_SJIS:
1307 {
1308 i = ((unsigned) i << 8) | j;
1309 JIS_TO_SJIS (i);
1310 reg[rrr] = i >> 8;
1311 reg[7] = i & 0xFF;
1312 break;
1313 }
1314 default: CCL_INVALID_CMD;
1315 }
1316 code &= 0x1F;
1317 if (code == CCL_WriteExprConst || code == CCL_WriteExprRegister)
1318 {
1319 i = reg[rrr];
1320 CCL_WRITE_CHAR (i);
1321 ic = jump_address;
1322 }
1323 else if (!reg[rrr])
1324 ic = jump_address;
1325 break;
1326
1327 case CCL_Extension:
1328 switch (EXCMD)
1329 {
1330 case CCL_ReadMultibyteChar2:
1331 if (!src)
1332 CCL_INVALID_CMD;
1333 CCL_READ_CHAR (i);
1334 CCL_ENCODE_CHAR (i, charset_list, reg[RRR], reg[rrr]);
1335 break;
1336
1337 case CCL_WriteMultibyteChar2:
1338 if (! dst)
1339 CCL_INVALID_CMD;
1340 i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
1341 CCL_WRITE_CHAR (i);
1342 break;
1343
1344 case CCL_TranslateCharacter:
1345 i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
1346 op = translate_char (GET_TRANSLATION_TABLE (reg[Rrr]), i);
1347 CCL_ENCODE_CHAR (op, charset_list, reg[RRR], reg[rrr]);
1348 break;
1349
1350 case CCL_TranslateCharacterConstTbl:
1351 {
1352 ptrdiff_t eop;
1353 GET_CCL_RANGE (eop, ccl_prog, ic++, 0,
1354 (VECTORP (Vtranslation_table_vector)
1355 ? ASIZE (Vtranslation_table_vector)
1356 : -1));
1357 i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
1358 op = translate_char (GET_TRANSLATION_TABLE (eop), i);
1359 CCL_ENCODE_CHAR (op, charset_list, reg[RRR], reg[rrr]);
1360 }
1361 break;
1362
1363 case CCL_LookupIntConstTbl:
1364 {
1365 ptrdiff_t eop;
1366 struct Lisp_Hash_Table *h;
1367 GET_CCL_RANGE (eop, ccl_prog, ic++, 0,
1368 (VECTORP (Vtranslation_hash_table_vector)
1369 ? ASIZE (Vtranslation_hash_table_vector)
1370 : -1));
1371 h = GET_HASH_TABLE (eop);
1372
1373 eop = (FIXNUM_OVERFLOW_P (reg[RRR])
1374 ? -1
1375 : hash_lookup (h, make_fixnum (reg[RRR]), NULL));
1376 if (eop >= 0)
1377 {
1378 Lisp_Object opl;
1379 opl = HASH_VALUE (h, eop);
1380 if (! (IN_INT_RANGE (eop) && CHARACTERP (opl)))
1381 CCL_INVALID_CMD;
1382 reg[RRR] = charset_unicode;
1383 reg[rrr] = XFIXNUM (opl);
1384 reg[7] = 1;
1385 }
1386 else
1387 reg[7] = 0;
1388 }
1389 break;
1390
1391 case CCL_LookupCharConstTbl:
1392 {
1393 ptrdiff_t eop;
1394 struct Lisp_Hash_Table *h;
1395 GET_CCL_RANGE (eop, ccl_prog, ic++, 0,
1396 (VECTORP (Vtranslation_hash_table_vector)
1397 ? ASIZE (Vtranslation_hash_table_vector)
1398 : -1));
1399 i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
1400 h = GET_HASH_TABLE (eop);
1401
1402 eop = (FIXNUM_OVERFLOW_P (i)
1403 ? -1
1404 : hash_lookup (h, make_fixnum (i), NULL));
1405 if (eop >= 0)
1406 {
1407 Lisp_Object opl;
1408 opl = HASH_VALUE (h, eop);
1409 if (! (FIXNUMP (opl) && IN_INT_RANGE (XFIXNUM (opl))))
1410 CCL_INVALID_CMD;
1411 reg[RRR] = XFIXNUM (opl);
1412 reg[7] = 1;
1413 }
1414 else
1415 reg[7] = 0;
1416 }
1417 break;
1418
1419 case CCL_IterateMultipleMap:
1420 {
1421 Lisp_Object map, content, attrib, value;
1422 EMACS_INT point;
1423 ptrdiff_t size;
1424 int fin_ic;
1425
1426 j = XFIXNUM (ccl_prog[ic++]);
1427 fin_ic = ic + j;
1428 op = reg[rrr];
1429 if ((j > reg[RRR]) && (j >= 0))
1430 {
1431 ic += reg[RRR];
1432 i = reg[RRR];
1433 }
1434 else
1435 {
1436 reg[RRR] = -1;
1437 ic = fin_ic;
1438 break;
1439 }
1440
1441 for (;i < j;i++)
1442 {
1443 if (!VECTORP (Vcode_conversion_map_vector)) continue;
1444 size = ASIZE (Vcode_conversion_map_vector);
1445 point = XFIXNUM (ccl_prog[ic++]);
1446 if (! (0 <= point && point < size)) continue;
1447 map = AREF (Vcode_conversion_map_vector, point);
1448
1449
1450 if (!CONSP (map)) continue;
1451 map = XCDR (map);
1452 if (!VECTORP (map)) continue;
1453 size = ASIZE (map);
1454 if (size <= 1) continue;
1455
1456 content = AREF (map, 0);
1457
1458
1459
1460
1461 if (FIXNUMP (content))
1462 {
1463 point = XFIXNUM (content);
1464 if (!(point <= op && op - point + 1 < size)) continue;
1465 content = AREF (map, op - point + 1);
1466 }
1467 else if (EQ (content, Qt))
1468 {
1469 if (size != 4) continue;
1470 if (FIXNUMP (AREF (map, 2))
1471 && XFIXNUM (AREF (map, 2)) <= op
1472 && FIXNUMP (AREF (map, 3))
1473 && op < XFIXNUM (AREF (map, 3)))
1474 content = AREF (map, 1);
1475 else
1476 continue;
1477 }
1478 else
1479 continue;
1480
1481 if (NILP (content))
1482 continue;
1483 else if (FIXNUMP (content) && IN_INT_RANGE (XFIXNUM (content)))
1484 {
1485 reg[RRR] = i;
1486 reg[rrr] = XFIXNUM (content);
1487 break;
1488 }
1489 else if (EQ (content, Qt) || EQ (content, Qlambda))
1490 {
1491 reg[RRR] = i;
1492 break;
1493 }
1494 else if (CONSP (content))
1495 {
1496 attrib = XCAR (content);
1497 value = XCDR (content);
1498 if (! (FIXNUMP (attrib) && FIXNUMP (value)
1499 && IN_INT_RANGE (XFIXNUM (value))))
1500 continue;
1501 reg[RRR] = i;
1502 reg[rrr] = XFIXNUM (value);
1503 break;
1504 }
1505 else if (SYMBOLP (content))
1506 CCL_CALL_FOR_MAP_INSTRUCTION (content, fin_ic);
1507 else
1508 CCL_INVALID_CMD;
1509 }
1510 if (i == j)
1511 reg[RRR] = -1;
1512 ic = fin_ic;
1513 }
1514 break;
1515
1516 case CCL_MapMultiple:
1517 {
1518 Lisp_Object map, content, attrib, value;
1519 EMACS_INT point;
1520 ptrdiff_t size, map_vector_size;
1521 int map_set_rest_length, fin_ic;
1522 int current_ic = this_ic;
1523
1524
1525 if (stack_idx_of_map_multiple > 0)
1526 {
1527 if (stack_idx_of_map_multiple <= stack_idx)
1528 {
1529 stack_idx_of_map_multiple = 0;
1530 mapping_stack_pointer = mapping_stack;
1531 CCL_INVALID_CMD;
1532 }
1533 }
1534 else
1535 mapping_stack_pointer = mapping_stack;
1536 stack_idx_of_map_multiple = 0;
1537
1538
1539 map_set_rest_length = XFIXNUM (ccl_prog[ic++]);
1540
1541 fin_ic = ic + map_set_rest_length;
1542 op = reg[rrr];
1543
1544 if ((map_set_rest_length > reg[RRR]) && (reg[RRR] >= 0))
1545 {
1546 ic += reg[RRR];
1547 i = reg[RRR];
1548 map_set_rest_length -= i;
1549 }
1550 else
1551 {
1552 ic = fin_ic;
1553 reg[RRR] = -1;
1554 mapping_stack_pointer = mapping_stack;
1555 break;
1556 }
1557
1558 if (mapping_stack_pointer <= (mapping_stack + 1))
1559 {
1560
1561 mapping_stack_pointer = mapping_stack;
1562 PUSH_MAPPING_STACK (0, op);
1563 reg[RRR] = -1;
1564 }
1565 else
1566 {
1567
1568 int orig_op;
1569
1570 POP_MAPPING_STACK (map_set_rest_length, orig_op);
1571 POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1572 switch (op)
1573 {
1574 case -1:
1575
1576 op = orig_op;
1577 i++;
1578 ic++;
1579 map_set_rest_length--;
1580 break;
1581 case -2:
1582
1583 op = reg[rrr];
1584 i++;
1585 ic++;
1586 map_set_rest_length--;
1587 break;
1588 case -3:
1589
1590 op = orig_op;
1591 i += map_set_rest_length;
1592 ic += map_set_rest_length;
1593 map_set_rest_length = 0;
1594 break;
1595 default:
1596
1597 i += map_set_rest_length;
1598 ic += map_set_rest_length;
1599 POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1600 break;
1601 }
1602 }
1603 if (!VECTORP (Vcode_conversion_map_vector))
1604 CCL_INVALID_CMD;
1605 map_vector_size = ASIZE (Vcode_conversion_map_vector);
1606
1607 do {
1608 for (;map_set_rest_length > 0;i++, ic++, map_set_rest_length--)
1609 {
1610 point = XFIXNUM (ccl_prog[ic]);
1611 if (point < 0)
1612 {
1613
1614 point = -point + 1;
1615 if (mapping_stack_pointer
1616 >= &mapping_stack[MAX_MAP_SET_LEVEL])
1617 CCL_INVALID_CMD;
1618 PUSH_MAPPING_STACK (map_set_rest_length - point,
1619 reg[rrr]);
1620 map_set_rest_length = point;
1621 reg[rrr] = op;
1622 continue;
1623 }
1624
1625 if (point >= map_vector_size) continue;
1626 map = AREF (Vcode_conversion_map_vector, point);
1627
1628
1629 if (!CONSP (map)) continue;
1630 map = XCDR (map);
1631 if (!VECTORP (map)) continue;
1632 size = ASIZE (map);
1633 if (size <= 1) continue;
1634
1635 content = AREF (map, 0);
1636
1637
1638
1639
1640 if (FIXNUMP (content))
1641 {
1642 point = XFIXNUM (content);
1643 if (!(point <= op && op - point + 1 < size)) continue;
1644 content = AREF (map, op - point + 1);
1645 }
1646 else if (EQ (content, Qt))
1647 {
1648 if (size != 4) continue;
1649 if (FIXNUMP (AREF (map, 2))
1650 && XFIXNUM (AREF (map, 2)) <= op
1651 && FIXNUMP (AREF (map, 3))
1652 && op < XFIXNUM (AREF (map, 3)))
1653 content = AREF (map, 1);
1654 else
1655 continue;
1656 }
1657 else
1658 continue;
1659
1660 if (NILP (content))
1661 continue;
1662
1663 reg[RRR] = i;
1664 if (FIXNUMP (content) && IN_INT_RANGE (XFIXNUM (content)))
1665 {
1666 op = XFIXNUM (content);
1667 i += map_set_rest_length - 1;
1668 ic += map_set_rest_length - 1;
1669 POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1670 map_set_rest_length++;
1671 }
1672 else if (CONSP (content))
1673 {
1674 attrib = XCAR (content);
1675 value = XCDR (content);
1676 if (! (FIXNUMP (attrib) && FIXNUMP (value)
1677 && IN_INT_RANGE (XFIXNUM (value))))
1678 continue;
1679 op = XFIXNUM (value);
1680 i += map_set_rest_length - 1;
1681 ic += map_set_rest_length - 1;
1682 POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1683 map_set_rest_length++;
1684 }
1685 else if (EQ (content, Qt))
1686 {
1687 op = reg[rrr];
1688 }
1689 else if (EQ (content, Qlambda))
1690 {
1691 i += map_set_rest_length;
1692 ic += map_set_rest_length;
1693 break;
1694 }
1695 else if (SYMBOLP (content))
1696 {
1697 if (mapping_stack_pointer
1698 >= &mapping_stack[MAX_MAP_SET_LEVEL])
1699 CCL_INVALID_CMD;
1700 PUSH_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1701 PUSH_MAPPING_STACK (map_set_rest_length, op);
1702 stack_idx_of_map_multiple = stack_idx + 1;
1703 CCL_CALL_FOR_MAP_INSTRUCTION (content, current_ic);
1704 }
1705 else
1706 CCL_INVALID_CMD;
1707 }
1708 if (mapping_stack_pointer <= (mapping_stack + 1))
1709 break;
1710 POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1711 i += map_set_rest_length;
1712 ic += map_set_rest_length;
1713 POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
1714 } while (1);
1715
1716 ic = fin_ic;
1717 }
1718 reg[rrr] = op;
1719 break;
1720
1721 case CCL_MapSingle:
1722 {
1723 Lisp_Object map, attrib, value, content;
1724 int point;
1725 j = XFIXNUM (ccl_prog[ic++]);
1726 op = reg[rrr];
1727 if (! (VECTORP (Vcode_conversion_map_vector)
1728 && j < ASIZE (Vcode_conversion_map_vector)))
1729 {
1730 reg[RRR] = -1;
1731 break;
1732 }
1733 map = AREF (Vcode_conversion_map_vector, j);
1734 if (!CONSP (map))
1735 {
1736 reg[RRR] = -1;
1737 break;
1738 }
1739 map = XCDR (map);
1740 if (! (VECTORP (map)
1741 && 0 < ASIZE (map)
1742 && FIXNUMP (AREF (map, 0))
1743 && XFIXNUM (AREF (map, 0)) <= op
1744 && op - XFIXNUM (AREF (map, 0)) + 1 < ASIZE (map)))
1745 {
1746 reg[RRR] = -1;
1747 break;
1748 }
1749 point = op - XFIXNUM (AREF (map, 0)) + 1;
1750 reg[RRR] = 0;
1751 content = AREF (map, point);
1752 if (NILP (content))
1753 reg[RRR] = -1;
1754 else if (TYPE_RANGED_FIXNUMP (int, content))
1755 reg[rrr] = XFIXNUM (content);
1756 else if (EQ (content, Qt));
1757 else if (CONSP (content))
1758 {
1759 attrib = XCAR (content);
1760 value = XCDR (content);
1761 if (!FIXNUMP (attrib)
1762 || !TYPE_RANGED_FIXNUMP (int, value))
1763 continue;
1764 reg[rrr] = XFIXNUM (value);
1765 break;
1766 }
1767 else if (SYMBOLP (content))
1768 CCL_CALL_FOR_MAP_INSTRUCTION (content, ic);
1769 else
1770 reg[RRR] = -1;
1771 }
1772 break;
1773
1774 default:
1775 CCL_INVALID_CMD;
1776 }
1777 break;
1778
1779 default:
1780 CCL_INVALID_CMD;
1781 }
1782 }
1783
1784 ccl_error_handler:
1785 if (destination)
1786 {
1787
1788
1789
1790 char msg[256];
1791 int msglen;
1792
1793 if (!dst)
1794 dst = destination;
1795
1796 switch (ccl->status)
1797 {
1798 case CCL_STAT_INVALID_CMD:
1799 msglen = sprintf (msg,
1800 "\nCCL: Invalid command %x (ccl_code = %x) at %d.",
1801 code & 0x1Fu, code + 0u, this_ic);
1802 #ifdef CCL_DEBUG
1803 {
1804 int i = ccl_backtrace_idx - 1;
1805 int j;
1806
1807 if (dst + msglen <= (dst_bytes ? dst_end : src))
1808 {
1809 memcpy (dst, msg, msglen);
1810 dst += msglen;
1811 }
1812
1813 for (j = 0; j < CCL_DEBUG_BACKTRACE_LEN; j++, i--)
1814 {
1815 if (i < 0) i = CCL_DEBUG_BACKTRACE_LEN - 1;
1816 if (ccl_backtrace_table[i] == 0)
1817 break;
1818 msglen = sprintf (msg, " %d", ccl_backtrace_table[i]);
1819 if (dst + msglen > (dst_bytes ? dst_end : src))
1820 break;
1821 memcpy (dst, msg, msglen);
1822 dst += msglen;
1823 }
1824 goto ccl_finish;
1825 }
1826 #endif
1827 break;
1828
1829 case CCL_STAT_QUIT:
1830 msglen = ccl->quit_silently ? 0 : sprintf (msg, "\nCCL: Quitted.");
1831 break;
1832
1833 default:
1834 msglen = sprintf (msg, "\nCCL: Unknown error type (%d)", ccl->status);
1835 }
1836
1837 if (msglen <= dst_end - dst)
1838 {
1839 for (i = 0; i < msglen; i++)
1840 *dst++ = msg[i];
1841 }
1842
1843 if (ccl->status == CCL_STAT_INVALID_CMD)
1844 {
1845 #if 0
1846
1847
1848
1849 int i = src_end - src;
1850 if (dst_bytes && (dst_end - dst) < i)
1851 i = dst_end - dst;
1852 memcpy (dst, src, i);
1853 src += i;
1854 dst += i;
1855 #else
1856
1857 src = src_end;
1858 #endif
1859 }
1860 }
1861
1862 ccl_finish:
1863 ccl->ic = ic;
1864 ccl->stack_idx = stack_idx;
1865 ccl->prog = ccl_prog;
1866 ccl->consumed = src - source;
1867 if (dst != NULL)
1868 ccl->produced = dst - destination;
1869 else
1870 ccl->produced = 0;
1871 }
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881 static Lisp_Object
1882 resolve_symbol_ccl_program (Lisp_Object ccl)
1883 {
1884 int i, veclen, unresolved = 0;
1885 Lisp_Object result, contents, val;
1886
1887 if (! (CCL_HEADER_MAIN < ASIZE (ccl) && ASIZE (ccl) <= INT_MAX))
1888 return Qnil;
1889 result = Fcopy_sequence (ccl);
1890 veclen = ASIZE (result);
1891
1892 for (i = 0; i < veclen; i++)
1893 {
1894 contents = AREF (result, i);
1895 if (TYPE_RANGED_FIXNUMP (int, contents))
1896 continue;
1897 else if (CONSP (contents)
1898 && SYMBOLP (XCAR (contents))
1899 && SYMBOLP (XCDR (contents)))
1900 {
1901
1902
1903
1904 val = Fget (XCAR (contents), XCDR (contents));
1905 if (RANGED_FIXNUMP (0, val, INT_MAX))
1906 ASET (result, i, val);
1907 else
1908 unresolved = 1;
1909 continue;
1910 }
1911 else if (SYMBOLP (contents))
1912 {
1913
1914
1915
1916 val = Fget (contents, Qtranslation_table_id);
1917 if (RANGED_FIXNUMP (0, val, INT_MAX))
1918 ASET (result, i, val);
1919 else
1920 {
1921 val = Fget (contents, Qcode_conversion_map_id);
1922 if (RANGED_FIXNUMP (0, val, INT_MAX))
1923 ASET (result, i, val);
1924 else
1925 {
1926 val = Fget (contents, Qccl_program_idx);
1927 if (RANGED_FIXNUMP (0, val, INT_MAX))
1928 ASET (result, i, val);
1929 else
1930 unresolved = 1;
1931 }
1932 }
1933 continue;
1934 }
1935 return Qnil;
1936 }
1937
1938 if (! (0 <= XFIXNUM (AREF (result, CCL_HEADER_BUF_MAG))
1939 && ASCENDING_ORDER (0, XFIXNUM (AREF (result, CCL_HEADER_EOF)),
1940 ASIZE (ccl))))
1941 return Qnil;
1942
1943 return (unresolved ? Qt : result);
1944 }
1945
1946
1947
1948
1949
1950
1951
1952 static Lisp_Object
1953 ccl_get_compiled_code (Lisp_Object ccl_prog, ptrdiff_t *idx)
1954 {
1955 Lisp_Object val, slot;
1956
1957 if (VECTORP (ccl_prog))
1958 {
1959 val = resolve_symbol_ccl_program (ccl_prog);
1960 *idx = -1;
1961 return (VECTORP (val) ? val : Qnil);
1962 }
1963 if (!SYMBOLP (ccl_prog))
1964 return Qnil;
1965
1966 val = Fget (ccl_prog, Qccl_program_idx);
1967 if (! FIXNATP (val)
1968 || XFIXNUM (val) >= ASIZE (Vccl_program_table))
1969 return Qnil;
1970 slot = AREF (Vccl_program_table, XFIXNUM (val));
1971 if (! VECTORP (slot)
1972 || ASIZE (slot) != 4
1973 || ! VECTORP (AREF (slot, 1)))
1974 return Qnil;
1975 *idx = XFIXNUM (val);
1976 if (NILP (AREF (slot, 2)))
1977 {
1978 val = resolve_symbol_ccl_program (AREF (slot, 1));
1979 if (! VECTORP (val))
1980 return Qnil;
1981 ASET (slot, 1, val);
1982 ASET (slot, 2, Qt);
1983 }
1984 return AREF (slot, 1);
1985 }
1986
1987
1988
1989
1990
1991
1992
1993 bool
1994 setup_ccl_program (struct ccl_program *ccl, Lisp_Object ccl_prog)
1995 {
1996 if (! NILP (ccl_prog))
1997 {
1998 struct Lisp_Vector *vp;
1999
2000 ccl_prog = ccl_get_compiled_code (ccl_prog, &ccl->idx);
2001 if (! VECTORP (ccl_prog))
2002 return false;
2003 vp = XVECTOR (ccl_prog);
2004 ccl->size = vp->header.size;
2005 ccl->prog = vp->contents;
2006 ccl->eof_ic = XFIXNUM (vp->contents[CCL_HEADER_EOF]);
2007 ccl->buf_magnification = XFIXNUM (vp->contents[CCL_HEADER_BUF_MAG]);
2008 if (ccl->idx >= 0)
2009 {
2010 Lisp_Object slot;
2011
2012 slot = AREF (Vccl_program_table, ccl->idx);
2013 ASET (slot, 3, Qnil);
2014 }
2015 }
2016 ccl->ic = CCL_HEADER_MAIN;
2017 memset (ccl->reg, 0, sizeof ccl->reg);
2018 ccl->last_block = false;
2019 ccl->status = 0;
2020 ccl->stack_idx = 0;
2021 ccl->quit_silently = false;
2022 return true;
2023 }
2024
2025
2026 DEFUN ("ccl-program-p", Fccl_program_p, Sccl_program_p, 1, 1, 0,
2027 doc:
2028 )
2029 (Lisp_Object object)
2030 {
2031 Lisp_Object val;
2032
2033 if (VECTORP (object))
2034 {
2035 val = resolve_symbol_ccl_program (object);
2036 return (VECTORP (val) ? Qt : Qnil);
2037 }
2038 if (!SYMBOLP (object))
2039 return Qnil;
2040
2041 val = Fget (object, Qccl_program_idx);
2042 return ((! FIXNATP (val)
2043 || XFIXNUM (val) >= ASIZE (Vccl_program_table))
2044 ? Qnil : Qt);
2045 }
2046
2047 DEFUN ("ccl-execute", Fccl_execute, Sccl_execute, 2, 2, 0,
2048 doc:
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062 )
2063 (Lisp_Object ccl_prog, Lisp_Object reg)
2064 {
2065 struct ccl_program ccl;
2066 int i;
2067
2068 if (! setup_ccl_program (&ccl, ccl_prog))
2069 error ("Invalid CCL program");
2070
2071 CHECK_VECTOR (reg);
2072 if (ASIZE (reg) != 8)
2073 error ("Length of vector REGISTERS is not 8");
2074
2075 for (i = 0; i < 8; i++)
2076 {
2077 intmax_t n;
2078 ccl.reg[i] = ((INTEGERP (AREF (reg, i))
2079 && integer_to_intmax (AREF (reg, i), &n)
2080 && INT_MIN <= n && n <= INT_MAX)
2081 ? n : 0);
2082 }
2083
2084 ccl_driver (&ccl, NULL, NULL, 0, 0, Qnil);
2085 maybe_quit ();
2086 if (ccl.status != CCL_STAT_SUCCESS)
2087 error ("Error in CCL program at %dth code", ccl.ic);
2088
2089 for (i = 0; i < 8; i++)
2090 ASET (reg, i, make_int (ccl.reg[i]));
2091 return Qnil;
2092 }
2093
2094 DEFUN ("ccl-execute-on-string", Fccl_execute_on_string, Sccl_execute_on_string,
2095 3, 5, 0,
2096 doc:
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120 )
2121 (Lisp_Object ccl_prog, Lisp_Object status, Lisp_Object str, Lisp_Object contin, Lisp_Object unibyte_p)
2122 {
2123 Lisp_Object val;
2124 struct ccl_program ccl;
2125 int i;
2126 ptrdiff_t outbufsize;
2127 unsigned char *outbuf, *outp;
2128 ptrdiff_t str_chars, str_bytes;
2129 #define CCL_EXECUTE_BUF_SIZE 1024
2130 int source[CCL_EXECUTE_BUF_SIZE], destination[CCL_EXECUTE_BUF_SIZE];
2131 ptrdiff_t consumed_chars, consumed_bytes, produced_chars;
2132 int buf_magnification;
2133
2134 if (! setup_ccl_program (&ccl, ccl_prog))
2135 error ("Invalid CCL program");
2136
2137 CHECK_VECTOR (status);
2138 if (ASIZE (status) != 9)
2139 error ("Length of vector STATUS is not 9");
2140 CHECK_STRING (str);
2141
2142 str_chars = SCHARS (str);
2143 str_bytes = SBYTES (str);
2144
2145 for (i = 0; i < 8; i++)
2146 {
2147 if (NILP (AREF (status, i)))
2148 ASET (status, i, make_fixnum (0));
2149 intmax_t n;
2150 if (INTEGERP (AREF (status, i))
2151 && integer_to_intmax (AREF (status, i), &n)
2152 && INT_MIN <= n && n <= INT_MAX)
2153 ccl.reg[i] = n;
2154 }
2155 intmax_t ic;
2156 if (INTEGERP (AREF (status, 8)) && integer_to_intmax (AREF (status, 8), &ic))
2157 {
2158 if (ccl.ic < ic && ic < ccl.size)
2159 ccl.ic = ic;
2160 }
2161
2162 buf_magnification = ccl.buf_magnification ? ccl.buf_magnification : 1;
2163 outbufsize = str_bytes;
2164 if (INT_MULTIPLY_WRAPV (buf_magnification, outbufsize, &outbufsize)
2165 || INT_ADD_WRAPV (256, outbufsize, &outbufsize))
2166 memory_full (SIZE_MAX);
2167 outp = outbuf = xmalloc (outbufsize);
2168
2169 consumed_chars = consumed_bytes = 0;
2170 produced_chars = 0;
2171 while (1)
2172 {
2173 const unsigned char *p = SDATA (str) + consumed_bytes;
2174 const unsigned char *endp = SDATA (str) + str_bytes;
2175 int j = 0;
2176 int *src, src_size;
2177
2178 if (endp - p == str_chars - consumed_chars)
2179 while (j < CCL_EXECUTE_BUF_SIZE && p < endp)
2180 source[j++] = *p++;
2181 else
2182 while (j < CCL_EXECUTE_BUF_SIZE && p < endp)
2183 source[j++] = string_char_advance (&p);
2184 consumed_chars += j;
2185 consumed_bytes = p - SDATA (str);
2186
2187 if (consumed_bytes == str_bytes)
2188 ccl.last_block = NILP (contin);
2189 src = source;
2190 src_size = j;
2191 while (1)
2192 {
2193 int max_expansion = NILP (unibyte_p) ? MAX_MULTIBYTE_LENGTH : 1;
2194 ptrdiff_t offset, shortfall;
2195 ccl_driver (&ccl, src, destination, src_size, CCL_EXECUTE_BUF_SIZE,
2196 Qnil);
2197 produced_chars += ccl.produced;
2198 offset = outp - outbuf;
2199 shortfall = ccl.produced * max_expansion - (outbufsize - offset);
2200 if (shortfall > 0)
2201 {
2202 outbuf = xpalloc (outbuf, &outbufsize, shortfall, -1, 1);
2203 outp = outbuf + offset;
2204 }
2205 if (NILP (unibyte_p))
2206 {
2207 for (j = 0; j < ccl.produced; j++)
2208 outp += CHAR_STRING (destination[j], outp);
2209 }
2210 else
2211 {
2212 for (j = 0; j < ccl.produced; j++)
2213 *outp++ = destination[j];
2214 }
2215 src += ccl.consumed;
2216 src_size -= ccl.consumed;
2217 if (ccl.status != CCL_STAT_SUSPEND_BY_DST)
2218 break;
2219 }
2220
2221 if (ccl.status != CCL_STAT_SUSPEND_BY_SRC
2222 || str_chars == consumed_chars)
2223 break;
2224 }
2225
2226 if (ccl.status == CCL_STAT_INVALID_CMD)
2227 error ("Error in CCL program at %dth code", ccl.ic);
2228 if (ccl.status == CCL_STAT_QUIT)
2229 error ("CCL program interrupted at %dth code", ccl.ic);
2230
2231 for (i = 0; i < 8; i++)
2232 ASET (status, i, make_int (ccl.reg[i]));
2233 ASET (status, 8, make_int (ccl.ic));
2234
2235 val = make_specified_string ((const char *) outbuf, produced_chars,
2236 outp - outbuf, NILP (unibyte_p));
2237 xfree (outbuf);
2238
2239 return val;
2240 }
2241
2242 DEFUN ("register-ccl-program", Fregister_ccl_program, Sregister_ccl_program,
2243 2, 2, 0,
2244 doc:
2245
2246
2247 )
2248 (Lisp_Object name, Lisp_Object ccl_prog)
2249 {
2250 ptrdiff_t len = ASIZE (Vccl_program_table);
2251 ptrdiff_t idx;
2252 Lisp_Object resolved;
2253
2254 CHECK_SYMBOL (name);
2255 resolved = Qnil;
2256 if (!NILP (ccl_prog))
2257 {
2258 CHECK_VECTOR (ccl_prog);
2259 resolved = resolve_symbol_ccl_program (ccl_prog);
2260 if (NILP (resolved))
2261 error ("Error in CCL program");
2262 if (VECTORP (resolved))
2263 {
2264 ccl_prog = resolved;
2265 resolved = Qt;
2266 }
2267 else
2268 resolved = Qnil;
2269 }
2270
2271 for (idx = 0; idx < len; idx++)
2272 {
2273 Lisp_Object slot;
2274
2275 slot = AREF (Vccl_program_table, idx);
2276 if (!VECTORP (slot))
2277
2278 break;
2279
2280 if (EQ (name, AREF (slot, 0)))
2281 {
2282
2283 ASET (slot, 1, ccl_prog);
2284 ASET (slot, 2, resolved);
2285 ASET (slot, 3, Qt);
2286 return make_fixnum (idx);
2287 }
2288 }
2289
2290 if (idx == len)
2291
2292 Vccl_program_table = larger_vector (Vccl_program_table, 1, -1);
2293
2294 ASET (Vccl_program_table, idx,
2295 CALLN (Fvector, name, ccl_prog, resolved, Qt));
2296
2297 Fput (name, Qccl_program_idx, make_fixnum (idx));
2298 return make_fixnum (idx);
2299 }
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310 DEFUN ("register-code-conversion-map", Fregister_code_conversion_map,
2311 Sregister_code_conversion_map,
2312 2, 2, 0,
2313 doc:
2314 )
2315 (Lisp_Object symbol, Lisp_Object map)
2316 {
2317 ptrdiff_t len;
2318 ptrdiff_t i;
2319 Lisp_Object idx;
2320
2321 CHECK_SYMBOL (symbol);
2322 CHECK_VECTOR (map);
2323 if (! VECTORP (Vcode_conversion_map_vector))
2324 error ("Invalid code-conversion-map-vector");
2325
2326 len = ASIZE (Vcode_conversion_map_vector);
2327
2328 for (i = 0; i < len; i++)
2329 {
2330 Lisp_Object slot = AREF (Vcode_conversion_map_vector, i);
2331
2332 if (!CONSP (slot))
2333 break;
2334
2335 if (EQ (symbol, XCAR (slot)))
2336 {
2337 idx = make_fixnum (i);
2338 XSETCDR (slot, map);
2339 Fput (symbol, Qcode_conversion_map, map);
2340 Fput (symbol, Qcode_conversion_map_id, idx);
2341 return idx;
2342 }
2343 }
2344
2345 if (i == len)
2346 Vcode_conversion_map_vector = larger_vector (Vcode_conversion_map_vector,
2347 1, -1);
2348
2349 idx = make_fixnum (i);
2350 Fput (symbol, Qcode_conversion_map, map);
2351 Fput (symbol, Qcode_conversion_map_id, idx);
2352 ASET (Vcode_conversion_map_vector, i, Fcons (symbol, map));
2353 return idx;
2354 }
2355
2356
2357 void
2358 syms_of_ccl (void)
2359 {
2360 staticpro (&Vccl_program_table);
2361 Vccl_program_table = make_nil_vector (32);
2362
2363 DEFSYM (Qccl, "ccl");
2364 DEFSYM (Qcclp, "cclp");
2365
2366
2367
2368 DEFSYM (Qccl_program_idx, "ccl-program-idx");
2369
2370
2371
2372 DEFSYM (Qcode_conversion_map, "code-conversion-map");
2373 DEFSYM (Qcode_conversion_map_id, "code-conversion-map-id");
2374
2375 DEFVAR_LISP ("code-conversion-map-vector", Vcode_conversion_map_vector,
2376 doc: );
2377 Vcode_conversion_map_vector = make_nil_vector (16);
2378
2379 DEFVAR_LISP ("font-ccl-encoder-alist", Vfont_ccl_encoder_alist,
2380 doc:
2381
2382
2383
2384
2385
2386
2387
2388
2389 );
2390 Vfont_ccl_encoder_alist = Qnil;
2391
2392 DEFVAR_LISP ("translation-hash-table-vector", Vtranslation_hash_table_vector,
2393 doc:
2394
2395
2396 );
2397 Vtranslation_hash_table_vector = Qnil;
2398
2399 defsubr (&Sccl_program_p);
2400 defsubr (&Sccl_execute);
2401 defsubr (&Sccl_execute_on_string);
2402 defsubr (&Sregister_ccl_program);
2403 defsubr (&Sregister_code_conversion_map);
2404 }