+ case CCL_Extension:
+ switch (EXCMD)
+ {
+ case CCL_ReadMultibyteChar2:
+ if (!src)
+ CCL_INVALID_CMD;
+
+ if (src >= src_end)
+ {
+ src++;
+ goto ccl_read_multibyte_character_suspend;
+ }
+
+ if (!ccl->multibyte)
+ {
+ int bytes;
+ if (!UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes))
+ {
+ reg[RRR] = CHARSET_8_BIT_CONTROL;
+ reg[rrr] = *src++;
+ break;
+ }
+ }
+ i = *src++;
+ if (i == '\n' && ccl->eol_type != CODING_EOL_LF)
+ {
+ /* We are encoding. */
+ if (ccl->eol_type == CODING_EOL_CRLF)
+ {
+ if (ccl->cr_consumed)
+ ccl->cr_consumed = 0;
+ else
+ {
+ ccl->cr_consumed = 1;
+ i = '\r';
+ src--;
+ }
+ }
+ else
+ i = '\r';
+ reg[rrr] = i;
+ reg[RRR] = CHARSET_ASCII;
+ }
+ else if (i < 0x80)
+ {
+ /* ASCII */
+ reg[rrr] = i;
+ reg[RRR] = CHARSET_ASCII;
+ }
+ else if (i <= MAX_CHARSET_OFFICIAL_DIMENSION2)
+ {
+ int dimension = BYTES_BY_CHAR_HEAD (i) - 1;
+
+ if (dimension == 0)
+ {
+ /* `i' is a leading code for an undefined charset. */
+ reg[RRR] = CHARSET_8_BIT_GRAPHIC;
+ reg[rrr] = i;
+ }
+ else if (src + dimension > src_end)
+ goto ccl_read_multibyte_character_suspend;
+ else
+ {
+ reg[RRR] = i;
+ i = (*src++ & 0x7F);
+ if (dimension == 1)
+ reg[rrr] = i;
+ else
+ reg[rrr] = ((i << 7) | (*src++ & 0x7F));
+ }
+ }
+ 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 if (i == LEADING_CODE_8_BIT_CONTROL)
+ {
+ if (src >= src_end)
+ goto ccl_read_multibyte_character_suspend;
+ reg[RRR] = CHARSET_8_BIT_CONTROL;
+ reg[rrr] = (*src++ - 0x20);
+ }
+ else if (i >= 0xA0)
+ {
+ reg[RRR] = CHARSET_8_BIT_GRAPHIC;
+ reg[rrr] = i;
+ }
+ else
+ {
+ /* INVALID CODE. Return a single byte character. */
+ reg[RRR] = CHARSET_ASCII;
+ reg[rrr] = i;
+ }
+ break;
+
+ ccl_read_multibyte_character_suspend:
+ if (src <= src_end && !ccl->multibyte && ccl->last_block)
+ {
+ reg[RRR] = CHARSET_8_BIT_CONTROL;
+ reg[rrr] = i;
+ break;
+ }
+ src--;
+ if (ccl->last_block)
+ {
+ ic = eof_ic;
+ eof_hit = 1;
+ goto ccl_repeat;
+ }
+ else
+ CCL_SUSPEND (CCL_STAT_SUSPEND_BY_SRC);
+
+ break;
+
+ case CCL_WriteMultibyteChar2:
+ i = reg[RRR]; /* charset */
+ if (i == CHARSET_ASCII
+ || i == CHARSET_8_BIT_CONTROL
+ || i == CHARSET_8_BIT_GRAPHIC)
+ i = reg[rrr] & 0xFF;
+ 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_MULTIBYTE_CHAR (i);
+
+ break;
+
+ case CCL_TranslateCharacter:
+ CCL_MAKE_CHAR (reg[RRR], reg[rrr], i);
+ op = translate_char (GET_TRANSLATION_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_TranslateCharacterConstTbl:
+ op = XINT (ccl_prog[ic]); /* table */
+ ic++;
+ CCL_MAKE_CHAR (reg[RRR], reg[rrr], i);
+ op = translate_char (GET_TRANSLATION_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_LookupIntConstTbl:
+ op = XINT (ccl_prog[ic]); /* table */
+ ic++;
+ {
+ struct Lisp_Hash_Table *h = GET_HASH_TABLE (op);
+
+ op = hash_lookup (h, make_number (reg[RRR]), NULL);
+ if (op >= 0)
+ {
+ Lisp_Object opl;
+ opl = HASH_VALUE (h, op);
+ if (!CHAR_VALID_P (XINT (opl), 0))
+ CCL_INVALID_CMD;
+ SPLIT_CHAR (XINT (opl), reg[RRR], i, j);
+ if (j != -1)
+ i = (i << 7) | j;
+ reg[rrr] = i;
+ reg[7] = 1; /* r7 true for success */
+ }
+ else
+ reg[7] = 0;
+ }
+ break;
+
+ case CCL_LookupCharConstTbl:
+ op = XINT (ccl_prog[ic]); /* table */
+ ic++;
+ CCL_MAKE_CHAR (reg[RRR], reg[rrr], i);
+ {
+ struct Lisp_Hash_Table *h = GET_HASH_TABLE (op);
+
+ op = hash_lookup (h, make_number (i), NULL);
+ if (op >= 0)
+ {
+ Lisp_Object opl;
+ opl = HASH_VALUE (h, op);
+ if (!INTEGERP (opl))
+ CCL_INVALID_CMD;
+ reg[RRR] = XINT (opl);
+ reg[7] = 1; /* r7 true for success */
+ }
+ else
+ reg[7] = 0;
+ }
+ break;
+
+ case CCL_IterateMultipleMap:
+ {
+ Lisp_Object map, content, attrib, value;
+ int point, size, fin_ic;
+
+ j = XINT (ccl_prog[ic++]); /* number of maps. */
+ 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 = ASIZE (Vcode_conversion_map_vector);
+ point = XINT (ccl_prog[ic++]);
+ if (point >= size) continue;
+ map = AREF (Vcode_conversion_map_vector, point);
+
+ /* Check map varidity. */
+ if (!CONSP (map)) continue;
+ map = XCDR (map);
+ if (!VECTORP (map)) continue;
+ size = ASIZE (map);
+ if (size <= 1) continue;
+
+ content = AREF (map, 0);
+
+ /* check map type,
+ [STARTPOINT VAL1 VAL2 ...] or
+ [t ELELMENT STARTPOINT ENDPOINT] */
+ if (NUMBERP (content))
+ {
+ point = XUINT (content);
+ point = op - point + 1;
+ if (!((point >= 1) && (point < size))) continue;
+ content = AREF (map, point);
+ }
+ else if (EQ (content, Qt))
+ {
+ if (size != 4) continue;
+ if ((op >= XUINT (AREF (map, 2)))
+ && (op < XUINT (AREF (map, 3))))
+ content = AREF (map, 1);
+ else
+ continue;
+ }
+ else
+ continue;
+
+ if (NILP (content))
+ continue;
+ else if (NUMBERP (content))
+ {
+ reg[RRR] = i;
+ reg[rrr] = XINT(content);
+ break;
+ }
+ else if (EQ (content, Qt) || EQ (content, Qlambda))
+ {
+ reg[RRR] = i;
+ break;
+ }
+ else if (CONSP (content))
+ {
+ attrib = XCAR (content);
+ value = XCDR (content);
+ if (!NUMBERP (attrib) || !NUMBERP (value))
+ continue;
+ reg[RRR] = i;
+ reg[rrr] = XUINT (value);
+ break;
+ }
+ else if (SYMBOLP (content))
+ CCL_CALL_FOR_MAP_INSTRUCTION (content, fin_ic);
+ else
+ CCL_INVALID_CMD;
+ }
+ if (i == j)
+ reg[RRR] = -1;
+ ic = fin_ic;
+ }
+ break;
+
+ case CCL_MapMultiple:
+ {
+ Lisp_Object map, content, attrib, value;
+ int point, size, map_vector_size;
+ int map_set_rest_length, fin_ic;
+ int current_ic = this_ic;
+
+ /* inhibit recursive call on MapMultiple. */
+ if (stack_idx_of_map_multiple > 0)
+ {
+ if (stack_idx_of_map_multiple <= stack_idx)
+ {
+ stack_idx_of_map_multiple = 0;
+ mapping_stack_pointer = mapping_stack;
+ CCL_INVALID_CMD;
+ }
+ }
+ else
+ mapping_stack_pointer = mapping_stack;
+ stack_idx_of_map_multiple = 0;
+
+ map_set_rest_length =
+ XINT (ccl_prog[ic++]); /* number of maps and separators. */
+ fin_ic = ic + map_set_rest_length;
+ op = reg[rrr];
+
+ if ((map_set_rest_length > reg[RRR]) && (reg[RRR] >= 0))
+ {
+ ic += reg[RRR];
+ i = reg[RRR];
+ map_set_rest_length -= i;
+ }
+ else
+ {
+ ic = fin_ic;
+ reg[RRR] = -1;
+ mapping_stack_pointer = mapping_stack;
+ break;
+ }
+
+ if (mapping_stack_pointer <= (mapping_stack + 1))
+ {
+ /* Set up initial state. */
+ mapping_stack_pointer = mapping_stack;
+ PUSH_MAPPING_STACK (0, op);
+ reg[RRR] = -1;
+ }
+ else
+ {
+ /* Recover after calling other ccl program. */
+ int orig_op;
+
+ POP_MAPPING_STACK (map_set_rest_length, orig_op);
+ POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
+ switch (op)
+ {
+ case -1:
+ /* Regard it as Qnil. */
+ op = orig_op;
+ i++;
+ ic++;
+ map_set_rest_length--;
+ break;
+ case -2:
+ /* Regard it as Qt. */
+ op = reg[rrr];
+ i++;
+ ic++;
+ map_set_rest_length--;
+ break;
+ case -3:
+ /* Regard it as Qlambda. */
+ op = orig_op;
+ i += map_set_rest_length;
+ ic += map_set_rest_length;
+ map_set_rest_length = 0;
+ break;
+ default:
+ /* Regard it as normal mapping. */
+ i += map_set_rest_length;
+ ic += map_set_rest_length;
+ POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
+ break;
+ }
+ }
+ map_vector_size = ASIZE (Vcode_conversion_map_vector);
+
+ do {
+ for (;map_set_rest_length > 0;i++, ic++, map_set_rest_length--)
+ {
+ point = XINT(ccl_prog[ic]);
+ if (point < 0)
+ {
+ /* +1 is for including separator. */
+ point = -point + 1;
+ if (mapping_stack_pointer
+ >= &mapping_stack[MAX_MAP_SET_LEVEL])
+ CCL_INVALID_CMD;
+ PUSH_MAPPING_STACK (map_set_rest_length - point,
+ reg[rrr]);
+ map_set_rest_length = point;
+ reg[rrr] = op;
+ continue;
+ }
+
+ if (point >= map_vector_size) continue;
+ map = AREF (Vcode_conversion_map_vector, point);
+
+ /* Check map varidity. */
+ if (!CONSP (map)) continue;
+ map = XCDR (map);
+ if (!VECTORP (map)) continue;
+ size = ASIZE (map);
+ if (size <= 1) continue;
+
+ content = AREF (map, 0);
+
+ /* check map type,
+ [STARTPOINT VAL1 VAL2 ...] or
+ [t ELEMENT STARTPOINT ENDPOINT] */
+ if (NUMBERP (content))
+ {
+ point = XUINT (content);
+ point = op - point + 1;
+ if (!((point >= 1) && (point < size))) continue;
+ content = AREF (map, point);
+ }
+ else if (EQ (content, Qt))
+ {
+ if (size != 4) continue;
+ if ((op >= XUINT (AREF (map, 2))) &&
+ (op < XUINT (AREF (map, 3))))
+ content = AREF (map, 1);
+ else
+ continue;
+ }
+ else
+ continue;
+
+ if (NILP (content))
+ continue;
+
+ reg[RRR] = i;
+ if (NUMBERP (content))
+ {
+ op = XINT (content);
+ i += map_set_rest_length - 1;
+ ic += map_set_rest_length - 1;
+ POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
+ map_set_rest_length++;
+ }
+ else if (CONSP (content))
+ {
+ attrib = XCAR (content);
+ value = XCDR (content);
+ if (!NUMBERP (attrib) || !NUMBERP (value))
+ continue;
+ op = XUINT (value);
+ i += map_set_rest_length - 1;
+ ic += map_set_rest_length - 1;
+ POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
+ map_set_rest_length++;
+ }
+ else if (EQ (content, Qt))
+ {
+ op = reg[rrr];
+ }
+ else if (EQ (content, Qlambda))
+ {
+ i += map_set_rest_length;
+ ic += map_set_rest_length;
+ break;
+ }
+ else if (SYMBOLP (content))
+ {
+ if (mapping_stack_pointer
+ >= &mapping_stack[MAX_MAP_SET_LEVEL])
+ CCL_INVALID_CMD;
+ PUSH_MAPPING_STACK (map_set_rest_length, reg[rrr]);
+ PUSH_MAPPING_STACK (map_set_rest_length, op);
+ stack_idx_of_map_multiple = stack_idx + 1;
+ CCL_CALL_FOR_MAP_INSTRUCTION (content, current_ic);
+ }
+ else
+ CCL_INVALID_CMD;
+ }
+ if (mapping_stack_pointer <= (mapping_stack + 1))
+ break;
+ POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
+ i += map_set_rest_length;
+ ic += map_set_rest_length;
+ POP_MAPPING_STACK (map_set_rest_length, reg[rrr]);
+ } while (1);
+
+ ic = fin_ic;
+ }
+ reg[rrr] = op;
+ break;
+
+ case CCL_MapSingle:
+ {
+ Lisp_Object map, attrib, value, content;
+ int size, point;
+ j = XINT (ccl_prog[ic++]); /* map_id */
+ op = reg[rrr];
+ if (j >= ASIZE (Vcode_conversion_map_vector))
+ {
+ reg[RRR] = -1;
+ break;
+ }
+ map = AREF (Vcode_conversion_map_vector, j);
+ if (!CONSP (map))
+ {
+ reg[RRR] = -1;
+ break;
+ }
+ map = XCDR (map);
+ if (!VECTORP (map))
+ {
+ reg[RRR] = -1;
+ break;
+ }
+ size = ASIZE (map);
+ point = XUINT (AREF (map, 0));
+ point = op - point + 1;
+ reg[RRR] = 0;
+ if ((size <= 1) ||
+ (!((point >= 1) && (point < size))))
+ reg[RRR] = -1;
+ else
+ {
+ reg[RRR] = 0;
+ content = AREF (map, point);
+ if (NILP (content))
+ reg[RRR] = -1;
+ else if (NUMBERP (content))
+ reg[rrr] = XINT (content);
+ else if (EQ (content, Qt));
+ else if (CONSP (content))
+ {
+ attrib = XCAR (content);
+ value = XCDR (content);
+ if (!NUMBERP (attrib) || !NUMBERP (value))
+ continue;
+ reg[rrr] = XUINT(value);
+ break;
+ }
+ else if (SYMBOLP (content))
+ CCL_CALL_FOR_MAP_INSTRUCTION (content, ic);
+ else
+ reg[RRR] = -1;
+ }
+ }
+ break;
+
+ default:
+ CCL_INVALID_CMD;
+ }
+ break;
+