Mercurial > emacs
changeset 20722:cce3ef478c64
(Vccl_translation_table_vector, Qccl_program,
Qccl_translation_table, Qccl_translation_table_id): New variables.
append new symbols. Qccl_translation_table and
Qccl_translation_table_id.
(CCL_Call): Fix the comment.
(CCL_ReadMultibyteCharacter, CCL_WriteMultibyteCharacter,
CCL_UnifyCharacter, CCL_UnifyCharacterConstTbl,
CCL_IterateMultipleMap, CCL_TranslateMultipleMap): New macros for
CCL Commands.
(EXCMD): New macro.
(ccl_driver): New case lable `CCL_Extention'.
(setup_ccl_program): Initialize the member `private_state' of CCL.
(Fregister_ccl_program): Delete unused variable IDX.
(Fregister_ccl_translation_table): New function.
(syms_of_ccl): Intern and staticpro Qccl_program,
Qccl_translation_table, and Qccl_translation_table_id. Declare
`ccl-translation-table-vector' as a Lisp variable. Declare
register-ccl-translation-table as a Lisp function.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Thu, 22 Jan 1998 01:26:45 +0000 |
parents | b5b97880b7d0 |
children | a0df1e68fc76 |
files | src/ccl.c |
diffstat | 1 files changed, 638 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ccl.c Thu Jan 22 01:26:45 1998 +0000 +++ b/src/ccl.c Thu Jan 22 01:26:45 1998 +0000 @@ -35,9 +35,21 @@ #endif /* not emacs */ +/* Where is stored translation tables for CCL program. */ +Lisp_Object Vccl_translation_table_vector; + /* Alist of fontname patterns vs corresponding CCL program. */ Lisp_Object Vfont_ccl_encoder_alist; +/* This symbol is property which assocate with ccl program vector. e.g. + (get 'ccl-big5-encoder 'ccl-program) returns ccl program vector */ +Lisp_Object Qccl_program; + +/* These symbol is properties whish associate with ccl translation table and its id + respectively. */ +Lisp_Object Qccl_translation_table; +Lisp_Object Qccl_translation_table_id; + /* Vector of CCL program names vs corresponding program data. */ Lisp_Object Vccl_program_table; @@ -269,7 +281,8 @@ write (reg[RRR] OPERATION reg[Rrr]); */ -#define CCL_Call 0x13 /* Write a constant: +#define CCL_Call 0x13 /* Call the CCL program whose ID is + (CC..C). 1:CCCCCCCCCCCCCCCCCCCC000XXXXX ------------------------------ call (CC..C) @@ -399,6 +412,129 @@ extended_command (rrr,RRR,Rrr,ARGS) */ +/* + From here, Extended CCL Instruction. + Bit length of extended command is 14. + Therefore the instruction code begins from 0 to 16384(0x3fff). + */ + +#define CCL_ReadMultibyteCharacter 0x00 /* Read Multibyte Character + 1:ExtendedCOMMNDRrrRRRrrrXXXXX + + Read a multibyte characeter. + A code point is stored + into rrr register. + A charset ID is stored + into RRR register. + */ +#define CCL_WriteMultibyteCharacter 0x01 /* Write Multibyte Character + 1:ExtendedCOMMNDRrrRRRrrrXXXXX + + Write a multibyte character. + Write a character whose code point + is in rrr register, and its charset ID + is in RRR charset. + */ +#define CCL_UnifyCharacter 0x02 /* Unify Multibyte Character + 1:ExtendedCOMMNDRrrRRRrrrXXXXX + + Unify a character where its code point + is in rrr register, and its charset ID + is in RRR register with the table of + the unification table ID + in Rrr register. + + Return a unified character where its + code point is in rrr register, and its + charset ID is in RRR register. + */ +#define CCL_UnifyCharacterConstTbl 0x03 /* Unify Multibyte Character + 1:ExtendedCOMMNDRrrRRRrrrXXXXX + 2:ARGUMENT(Unification Table ID) + + Unify a character where its code point + is in rrr register, and its charset ID + is in RRR register with the table of + the unification table ID + in 2nd argument. + + Return a unified character where its + code point is in rrr register, and its + charset ID is in RRR register. + */ +#define CCL_IterateMultipleMap 0x10 /* Iterate Multiple Map + 1:ExtendedCOMMNDXXXRRRrrrXXXXX + 2:NUMBER of TABLES + 3:TABLE-ID1 + 4:TABLE-ID2 + ... + + iterate to lookup tables from a number + until finding a value. + + Each table consists of a vector + whose element is number or + nil or t or lambda. + If the element is nil, + its table is neglected. + In the case of t or lambda, + return the original value. + + */ +#define CCL_TranslateMultipleMap 0x11 /* Translate Multiple Map + 1:ExtendedCOMMNDXXXRRRrrrXXXXX + 2:NUMBER of TABLE-IDs and SEPARATERs + (i.e. m1+m2+m3+...mk+k-1) + 3:TABLE-ID 1,1 + 4:TABLE-ID 1,2 + ... + m1+2:TABLE-ID 1,m1 + m1+3: -1 (SEPARATOR) + m1+4:TABLE-ID 2,1 + ... + m1+m2+4:TABLE-ID 2,m2 + m1+m2+5: -1 + ... + m1+m2+...+mk+k+1:TABLE-ID k,mk + + Translate the code point in + rrr register by tables. + Translation starts from the table + where RRR register points out. + + We translate the given value + from the tables which are separated + by -1. + When each translation is failed to find + any values, we regard the traslation + as identity. + + We iterate to traslate by using each + table set(tables separated by -1) + until lookup the last table except + lookup lambda. + + Each table consists of a vector + whose element is number + or nil or t or lambda. + If the element is nil, + it is neglected and use the next table. + In the case of t, + it is translated to the original value. + In the case of lambda, + it cease the translation and return the + current value. + + */ +#define CCL_TranslateSingleMap 0x12 /* Translate Single Map + 1:ExtendedCOMMNDXXXRRRrrrXXXXX + 2:TABLE-ID + + Translate a number in rrr register. + If it is not found any translation, + set RRR register -1 but rrr register + is not changed. + */ /* CCL arithmetic/logical operators. */ #define CCL_PLUS 0x00 /* X = Y + Z */ @@ -426,14 +562,6 @@ #define CCL_DECODE_SJIS 0x17 /* X = HIGHER_BYTE (DE-SJIS (Y, Z)) r[7] = LOWER_BYTE (DE-SJIS (Y, Z)) */ -/* Macros for exit status of CCL program. */ -#define CCL_STAT_SUCCESS 0 /* Terminated successfully. */ -#define CCL_STAT_SUSPEND 1 /* Terminated because of empty input - buffer or full output buffer. */ -#define CCL_STAT_INVALID_CMD 2 /* Terminated because of invalid - command. */ -#define CCL_STAT_QUIT 3 /* Terminated because of quit. */ - /* Terminate CCL program successfully. */ #define CCL_SUCCESS \ do { \ @@ -445,11 +573,11 @@ /* Suspend CCL program because of reading from empty input buffer or writing to full output buffer. When this program is resumed, the same I/O command is executed. */ -#define CCL_SUSPEND \ - do { \ - ic--; \ - ccl->status = CCL_STAT_SUSPEND; \ - goto ccl_finish; \ +#define CCL_SUSPEND(stat) \ + do { \ + ic--; \ + ccl->status = stat; \ + goto ccl_finish; \ } while (0) /* Terminate CCL program because of invalid command. Should not occur @@ -462,22 +590,22 @@ /* Encode one character CH to multibyte form and write to the current output buffer. If CH is less than 256, CH is written as is. */ -#define CCL_WRITE_CHAR(ch) \ - do { \ - if (!dst) \ - CCL_INVALID_CMD; \ - else \ - { \ - unsigned char work[4], *str; \ - int len = CHAR_STRING (ch, work, str); \ - if (dst + len <= dst_end) \ - { \ - bcopy (str, dst, len); \ - dst += len; \ - } \ - else \ - CCL_SUSPEND; \ - } \ +#define CCL_WRITE_CHAR(ch) \ + do { \ + if (!dst) \ + CCL_INVALID_CMD; \ + else \ + { \ + unsigned char work[4], *str; \ + int len = CHAR_STRING (ch, work, str); \ + if (dst + len <= (dst_bytes ? dst_end : src)) \ + { \ + bcopy (str, dst, len); \ + dst += len; \ + } \ + else \ + CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \ + } \ } while (0) /* Write a string at ccl_prog[IC] of length LEN to the current output @@ -486,28 +614,28 @@ do { \ if (!dst) \ CCL_INVALID_CMD; \ - else if (dst + len <= dst_end) \ + else if (dst + len <= (dst_bytes ? dst_end : src)) \ for (i = 0; i < len; i++) \ *dst++ = ((XFASTINT (ccl_prog[ic + (i / 3)])) \ >> ((2 - (i % 3)) * 8)) & 0xFF; \ else \ - CCL_SUSPEND; \ + CCL_SUSPEND (CCL_STAT_SUSPEND_BY_DST); \ } while (0) /* Read one byte from the current input buffer into Rth register. */ -#define CCL_READ_CHAR(r) \ - do { \ - if (!src) \ - CCL_INVALID_CMD; \ - else if (src < src_end) \ - r = *src++; \ - else if (ccl->last_block) \ - { \ - ic = ccl->eof_ic; \ - goto ccl_finish; \ - } \ - else \ - CCL_SUSPEND; \ +#define CCL_READ_CHAR(r) \ + do { \ + if (!src) \ + CCL_INVALID_CMD; \ + else if (src < src_end) \ + r = *src++; \ + else if (ccl->last_block) \ + { \ + ic = ccl->eof_ic; \ + goto ccl_finish; \ + } \ + else \ + CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); \ } while (0) @@ -584,6 +712,7 @@ #define RRR (field1 & 7) #define Rrr ((field1 >> 3) & 7) #define ADDR field1 +#define EXCMD (field1 >> 6) switch (code & 0x1F) { @@ -881,6 +1010,387 @@ ic = jump_address; break; + case CCL_Extention: + switch (EXCMD) + { + case CCL_ReadMultibyteCharacter: + if (!src) + CCL_INVALID_CMD; + do { + if (src >= src_end) + goto ccl_read_multibyte_character_suspend; + + i = *src++; + if (i == LEADING_CODE_COMPOSITION) + { + if (src >= src_end) + goto ccl_read_multibyte_character_suspend; + if (*src == 0xFF) + { + ccl->private_state = COMPOSING_WITH_RULE_HEAD; + src++; + } + else + ccl->private_state = COMPOSING_NO_RULE_HEAD; + } + if (ccl->private_state != 0) + { + /* composite character */ + if (*src < 0xA0) + ccl->private_state = 0; + else + { + if (i == 0xA0) + { + if (src >= src_end) + goto ccl_read_multibyte_character_suspend; + i = *src++ & 0x7F; + } + else + i -= 0x20; + + if (COMPOSING_WITH_RULE_RULE == ccl->private_state) + { + ccl->private_state = COMPOSING_WITH_RULE_HEAD; + continue; + } + else if (COMPOSING_WITH_RULE_HEAD == ccl->private_state) + ccl->private_state = COMPOSING_WITH_RULE_RULE; + } + } + if (i < 0x80) + { + /* ASCII */ + reg[rrr] = i; + reg[RRR] = CHARSET_ASCII; + } + else if (i <= MAX_CHARSET_OFFICIAL_DIMENSION1) + { + if (src >= src_end) + goto ccl_read_multibyte_character_suspend; + reg[RRR] = i; + reg[rrr] = (*src++ & 0x7F); + } + else if (i <= MAX_CHARSET_OFFICIAL_DIMENSION2) + { + if ((src + 1) >= src_end) + goto ccl_read_multibyte_character_suspend; + reg[RRR] = i; + i = (*src++ & 0x7F); + reg[rrr] = ((i << 7) | (*src & 0x7F)); + src++; + } + else if ((i == LEADING_CODE_PRIVATE_11) || + (i == LEADING_CODE_PRIVATE_12)) + { + if ((src + 1) >= src_end) + goto ccl_read_multibyte_character_suspend; + reg[RRR] = *src++; + reg[rrr] = (*src++ & 0x7F); + } + else if ((i == LEADING_CODE_PRIVATE_21) || + (i == LEADING_CODE_PRIVATE_22)) + { + if ((src + 2) >= src_end) + goto ccl_read_multibyte_character_suspend; + reg[RRR] = *src++; + i = (*src++ & 0x7F); + reg[rrr] = ((i << 7) | (*src & 0x7F)); + src++; + } + else + { + /* INVALID CODE + Returned charset is -1.*/ + reg[RRR] = -1; + } + } while (0); + break; + + ccl_read_multibyte_character_suspend: + src--; + if (ccl->last_block) + { + ic = ccl->eof_ic; + goto ccl_finish; + } + else + CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC); + + break; + + case CCL_WriteMultibyteCharacter: + i = reg[RRR]; /* charset */ + if (i == CHARSET_ASCII) + i = reg[rrr] & 0x7F; + else if (i == CHARSET_COMPOSITION) + i = MAKE_COMPOSITE_CHAR (reg[rrr]); + else if (CHARSET_DIMENSION (i) == 1) + i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F); + else if (i < MIN_CHARSET_PRIVATE_DIMENSION2) + i = ((i - 0x8F) << 14) | reg[rrr]; + else + i = ((i - 0xE0) << 14) | reg[rrr]; + + CCL_WRITE_CHAR (i); + + break; + + case CCL_UnifyCharacter: + i = reg[RRR]; /* charset */ + if (i == CHARSET_ASCII) + i = reg[rrr] & 0x7F; + else if (i == CHARSET_COMPOSITION) + { + reg[RRR] = -1; + break; + } + else if (CHARSET_DIMENSION (i) == 1) + i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F); + else if (i < MIN_CHARSET_PRIVATE_DIMENSION2) + i = ((i - 0x8F) << 14) | (reg[rrr] & 0x3FFF); + else + i = ((i - 0xE0) << 14) | (reg[rrr] & 0x3FFF); + + op = unify_char (UNIFICATION_ID_TABLE (reg[Rrr]), i, -1, 0, 0); + SPLIT_CHAR (op, reg[RRR], i, j); + if (j != -1) + i = (i << 7) | j; + + reg[rrr] = i; + break; + + case CCL_UnifyCharacterConstTbl: + op = XINT (ccl_prog[ic]); /* table */ + ic++; + i = reg[RRR]; /* charset */ + if (i == CHARSET_ASCII) + i = reg[rrr] & 0x7F; + else if (i == CHARSET_COMPOSITION) + { + reg[RRR] = -1; + break; + } + else if (CHARSET_DIMENSION (i) == 1) + i = ((i - 0x70) << 7) | (reg[rrr] & 0x7F); + else if (i < MIN_CHARSET_PRIVATE_DIMENSION2) + i = ((i - 0x8F) << 14) | (reg[rrr] & 0x3FFF); + else + i = ((i - 0xE0) << 14) | (reg[rrr] & 0x3FFF); + + op = unify_char (UNIFICATION_ID_TABLE (op), i, -1, 0, 0); + SPLIT_CHAR (op, reg[RRR], i, j); + if (j != -1) + i = (i << 7) | j; + + reg[rrr] = i; + break; + + case CCL_IterateMultipleMap: + { + Lisp_Object table, content, attrib, value; + int point, size, fin_ic; + + j = XINT (ccl_prog[ic++]); /* number of tables. */ + fin_ic = ic + j; + op = reg[rrr]; + if ((j > reg[RRR]) && (j >= 0)) + { + ic += reg[RRR]; + i = reg[RRR]; + } + else + { + reg[RRR] = -1; + ic = fin_ic; + break; + } + + for (;i < j;i++) + { + + size = XVECTOR (Vccl_translation_table_vector)->size; + point = ccl_prog[ic++]; + if (point >= size) continue; + table = XVECTOR (Vccl_translation_table_vector)-> + contents[point]; + if (!CONSP (table)) continue; + table = XCONS(table)->cdr; + if (!VECTORP (table)) continue; + size = XVECTOR (table)->size; + if (size <= 1) continue; + point = XUINT (XVECTOR (table)->contents[0]); + point = op - point + 1; + if (!((point >= 1) && (point < size))) continue; + content = XVECTOR (table)->contents[point]; + + if (NILP (content)) + continue; + else if (NUMBERP (content)) + { + reg[RRR] = i; + reg[rrr] = XUINT(content); + break; + } + else if (EQ (content, Qt) || EQ (content, Qlambda)) + { + reg[RRR] = i; + break; + } + else if (CONSP (content)) + { + attrib = XCONS (content)->car; + value = XCONS (content)->cdr; + if (!NUMBERP (attrib) || !NUMBERP (value)) + continue; + reg[RRR] = i; + reg[rrr] = XUINT(value); + break; + } + } + if (i == j) + reg[RRR] = -1; + ic = fin_ic; + } + break; + + case CCL_TranslateMultipleMap: + { + Lisp_Object table, content, attrib, value; + int point, size, table_vector_size; + int skip_to_next, fin_ic; + + j = XINT (ccl_prog[ic++]); /* number of tables and separators. */ + fin_ic = ic + j; + if ((j > reg[RRR]) && (j >= 0)) + { + ic += reg[RRR]; + i = reg[RRR]; + } + else + { + ic = fin_ic; + reg[RRR] = -1; + break; + } + op = reg[rrr]; + reg[RRR] = -1; + skip_to_next = 0; + table_vector_size = XVECTOR (Vccl_translation_table_vector)->size; + for (;i < j;i++) + { + point = ccl_prog[ic++]; + if (XINT(point) == -1) + { + skip_to_next = 0; + continue; + } + if (skip_to_next) continue; + if (point >= table_vector_size) continue; + table = XVECTOR (Vccl_translation_table_vector)-> + contents[point]; + if (!CONSP (table)) continue; + table = XCONS (table)->cdr; + if (!VECTORP (table)) continue; + size = XVECTOR (table)->size; + if (size <= 1) continue; + point = XUINT (XVECTOR (table)->contents[0]); + point = op - point + 1; + if (!((point >= 1) && (point < size))) continue; + content = XVECTOR (table)->contents[point]; + + if (NILP (content)) + continue; + else if (NUMBERP (content)) + { + op = XUINT (content); + reg[RRR] = i; + skip_to_next = 1; + } + else if (CONSP (content)) + { + attrib = XCONS (content)->car; + value = XCONS (content)->cdr; + if (!NUMBERP (attrib) || !NUMBERP (value)) + continue; + reg[RRR] = i; + op = XUINT (value); + + } + else if (EQ (content, Qt)) + { + reg[RRR] = i; + op = reg[rrr]; + skip_to_next = 1; + } + else if (EQ (content, Qlambda)) + break; + } + ic = fin_ic; + } + reg[rrr] = op; + break; + + case CCL_TranslateSingleMap: + { + Lisp_Object table, attrib, value, content; + int size, point; + j = XINT (ccl_prog[ic++]); /* table_id */ + op = reg[rrr]; + if (j >= XVECTOR (Vccl_translation_table_vector)->size) + { + reg[RRR] = -1; + break; + } + table = XVECTOR (Vccl_translation_table_vector)-> + contents[j]; + if (!CONSP (table)) + { + reg[RRR] = -1; + break; + } + table = XCONS(table)->cdr; + if (!VECTORP (table)) + { + reg[RRR] = -1; + break; + } + size = XVECTOR (table)->size; + point = XUINT (XVECTOR (table)->contents[0]); + point = op - point + 1; + reg[RRR] = 0; + if ((size <= 1) || + (!((point >= 1) && (point < size)))) + reg[RRR] = -1; + else + { + content = XVECTOR (table)->contents[point]; + if (NILP (content)) + reg[RRR] = -1; + else if (NUMBERP (content)) + reg[rrr] = XUINT (content); + else if (EQ (content, Qt)) + reg[RRR] = i; + else if (CONSP (content)) + { + attrib = XCONS (content)->car; + value = XCONS (content)->cdr; + if (!NUMBERP (attrib) || !NUMBERP (value)) + continue; + reg[rrr] = XUINT(value); + break; + } + else + reg[RRR] = -1; + } + } + break; + + default: + CCL_INVALID_CMD; + } + break; + default: CCL_INVALID_CMD; } @@ -906,7 +1416,7 @@ int j; msglen = strlen (msg); - if (dst + msglen <= dst_end) + if (dst + msglen <= (dst_bytes ? dst_end : src)) { bcopy (msg, dst, msglen); dst += msglen; @@ -919,7 +1429,7 @@ break; sprintf(msg, " %d", ccl_backtrace_table[i]); msglen = strlen (msg); - if (dst + msglen > dst_end) + if (dst + msglen > (dst_bytes ? dst_end : src)) break; bcopy (msg, dst, msglen); dst += msglen; @@ -937,7 +1447,7 @@ } msglen = strlen (msg); - if (dst + msglen <= dst_end) + if (dst + msglen <= (dst_bytes ? dst_end : src)) { bcopy (msg, dst, msglen); dst += msglen; @@ -967,6 +1477,7 @@ for (i = 0; i < 8; i++) ccl->reg[i] = 0; ccl->last_block = 0; + ccl->private_state = 0; ccl->status = 0; } @@ -1069,7 +1580,8 @@ free (outbuf); QUIT; if (ccl.status != CCL_STAT_SUCCESS - && ccl.status != CCL_STAT_SUSPEND) + && ccl.status != CCL_STAT_SUSPEND_BY_SRC + && ccl.status != CCL_STAT_SUSPEND_BY_DST) error ("Error in CCL program at %dth code", ccl.ic); return val; @@ -1084,7 +1596,7 @@ Lisp_Object name, ccl_prog; { int len = XVECTOR (Vccl_program_table)->size; - int i, idx; + int i; CHECK_SYMBOL (name, 0); if (!NILP (ccl_prog)) @@ -1119,11 +1631,86 @@ return make_number (i); } +/* register CCL translation table. + CCL translation table consists of numbers and Qt and Qnil and Qlambda. + The first element is start code point. + The rest elements are translated numbers. + Qt shows that an original number before translation. + Qnil shows that an empty element. + Qlambda makes translation stopped. +*/ + +DEFUN ("register-ccl-translation-table", Fregister_ccl_translation_table, + Sregister_ccl_translation_table, + 2, 2, 0, + "Register CCL translation table.\n\ +TABLE should be a vector. SYMBOL is used for pointing the translation table out.\n\ +Return index number of the registered translation table.") + (symbol, table) + Lisp_Object symbol, table; +{ + int len = XVECTOR (Vccl_translation_table_vector)->size; + int i; + Lisp_Object index; + + CHECK_SYMBOL (symbol, 0); + CHECK_VECTOR (table, 1); + + for (i = 0; i < len; i++) + { + Lisp_Object slot = XVECTOR (Vccl_translation_table_vector)->contents[i]; + + if (!CONSP (slot)) + break; + + if (EQ (symbol, XCONS (slot)->car)) + { + index = make_number (i); + XCONS (slot)->cdr = table; + Fput (symbol, Qccl_translation_table, table); + Fput (symbol, Qccl_translation_table_id, index); + return index; + } + } + + if (i == len) + { + Lisp_Object new_vector = Fmake_vector (make_number (len * 2), Qnil); + int j; + + for (j = 0; j < len; j++) + XVECTOR (new_vector)->contents[j] + = XVECTOR (Vccl_translation_table_vector)->contents[j]; + Vccl_translation_table_vector = new_vector; + } + + index = make_number (i); + Fput (symbol, Qccl_translation_table, table); + Fput (symbol, Qccl_translation_table_id, index); + XVECTOR (Vccl_translation_table_vector)->contents[i] = Fcons (symbol, table); + return index; +} + + syms_of_ccl () { staticpro (&Vccl_program_table); Vccl_program_table = Fmake_vector (make_number (32), Qnil); + Qccl_program = intern("ccl-program"); + staticpro(&Qccl_program); + + Qccl_translation_table = intern ("ccl-translation-table"); + staticpro (&Qccl_translation_table); + + Qccl_translation_table_id = intern ("ccl-translation-table-id"); + staticpro (&Qccl_translation_table_id); + + DEFVAR_LISP ("ccl-translation-table-vector", &Vccl_translation_table_vector, + "Where is stored translation tables for CCL program.\n\ +Because CCL program can't access these tables except by the index of the vector."); + Vccl_translation_table_vector = Fmake_vector (XFASTINT (16), Qnil); + DEFVAR_LISP ("font-ccl-encoder-alist", &Vfont_ccl_encoder_alist, "Alist of fontname patterns vs corresponding CCL program.\n\ Each element looks like (REGEXP . CCL-CODE),\n\ @@ -1140,6 +1727,7 @@ defsubr (&Sccl_execute); defsubr (&Sccl_execute_on_string); defsubr (&Sregister_ccl_program); + defsubr (&Sregister_ccl_translation_table); } #endif /* emacs */