diff Xwnmo/romkan_m/rk_main.c @ 0:bbc77ca4def5

initial import
author Yoshiki Yazawa <yaz@cc.rim.or.jp>
date Thu, 13 Dec 2007 04:30:14 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Xwnmo/romkan_m/rk_main.c	Thu Dec 13 04:30:14 2007 +0900
@@ -0,0 +1,2124 @@
+/*
+ * $Id: rk_main.c,v 1.2 2001/06/14 18:16:09 ura Exp $
+ */
+
+/*
+ * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
+ * This file is part of FreeWnn.
+ * 
+ * Copyright Kyoto University Research Institute for Mathematical Sciences
+ *                 1987, 1988, 1989, 1990, 1991, 1992
+ * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
+ * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992
+ *
+ * Author: OMRON SOFTWARE Co., Ltd. <freewnn@rd.kyoto.omronsoft.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Emacs; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Commentary:
+ *
+ * Change log:
+ *
+ * Last modified date: 8,Feb.1999
+ *
+ * Code:
+ *
+ */
+/***********************************************************************
+                        rk_main.c
+                                                87.12. 3  改 正
+
+        ローマ字かな変換・その他、入力コードを変換するプログラム。
+        ASCIIコード使用を、前提としている。
+        このファイルは、変換のメインルーチン。
+***********************************************************************/
+/*      Version 3.1     88/06/14        H.HASHIMOTO
+ */
+#ifndef OMRON_LIB
+#include "rk_header.h"
+#include "rk_extvars.h"
+#ifdef  MULTI
+#include "rk_multi.h"
+#endif /*MULTI*/
+#endif
+#include "rext.h"
+#ifdef  MULTI
+#define DISOUT ((cur_rk->flags & RK_NONISE) ? cur_rk->rk_output : cur_rk->disout)
+  /* フラグの値はromkan_init3()の中で設定され、そのRK_NONISEのビットの値の
+     標準は0。従ってDISOUTの標準値はdisout。これをrk_outputに変えると、偽コード
+     (除:LTREOF)を一切出さない(但し、キー入力があれば必ず何かを返すように
+     してある時に限り、EOLTTRをも返す)。 */
+#else /* !MULTI */
+#ifdef KDSP
+#       ifdef MVUX
+  letter displine[DSPLIN];      /* デバッグ用  表示の一行分を記憶 */
+#       endif
+#endif
+
+/* 88/06/02 V3.1 */
+static letter nil[1] = { EOLTTR };
+static letter *curdis;
+static int codein_len;
+static letter *codeout, *remainkbf;
+static letter ungetc_buf = EOLTTR;      /* romkan_ungetcが一文字退避しておくバッファ */
+static letter unnext_buf = EOLTTR;      /* romkan_unnextが            〃             */
+
+static letter (*keyin_method) ();       /* キーイン関数のアドレス */
+static int (*bytcnt_method) (); /* バイトカウント関数のアドレス */
+static int (*kbytcnt_method) ();        /* キー入力解釈用バイトカウント関数のアドレス */
+
+/* モード表名(又はそのパス名)を保存 *//* 初期設定がいい加減! */
+static char prv_modfnm[REALFN] = "\0";
+
+#define DISOUT ((flags & RK_NONISE) ? rk_output : disout)
+ /* フラグの値はromkan_init3()の中で設定され、そのRK_NONISEのビットの値の
+    標準は0。従ってDISOUTの標準値はdisout。これをrk_outputに変えると、偽コード
+    (除:LTREOF)を一切出さない(但し、キー入力があれば必ず何かを返すように
+    してある時に限り、EOLTTRをも返す)。 */
+
+static                          /* V3.1 */
+char eofflg;                    /* romkan_next()からLTREOFが来たときに、romkan_henkan()内で1
+                                   にする。これの値が非0なら変換対応表の(error)を無視して、
+                                   本処理バッファ内の未確定コードも、強制的に変換させる。更に
+                                   LTREOFが来た時に特別にある出力を出すように指定されていれば
+                                   その処理も行う(但し、その処理は急ごしらえで不完全)。その
+                                   処理中はeofflgは2。 */
+
+static letter evalbuf[2][2][OUTSIZ];
+static letter delchr, delchr2 = EOLTTR, nisedl; /* DELのキャラクタは二個まで持てる */
+
+/* 88/05/31 V3.1 */
+static letter rk_input;         /* 入力。3バイトまでは変更なしに対応可 */
+static letter disout[OUTSIZ];   /* 本処理からの出力のバッファ */
+static letter rk_output[OUTSIZ];        /* 後処理からの出力(最終出力)のバッファ */
+static letter keybuf[KBFSIZ], urabuf[KBFSIZ];   /* 本処理バッファとその退避領域 */
+static int lastoutlen, lastkbflen;
+static int hyonum;
+#endif /* MULTI */
+
+static void romkan_delete (), mchevl (), add_at_eof (), free_for_all_area (), ltrevlcpy (), set_rubout (), maeato_henkan (), codeout_chg ();
+
+/* letterを返す関数の定義及び宣言(一部にはcharのものも混じっている) */
+
+static int head_bytecount (), p_eq (), hen_ikisrc (), match (), henkan_ok (), romkan_restart ();
+static letter mchedsrc ();
+letter romkan_next (), romkan_unnext ();
+letter romkan_getc (), romkan_ungetc (), *romkan_henkan ();
+letter to_zenalpha (), to_zenhira (), to_zenkata ();
+ /* to_zenhira;kata は濁点を持つ文字を一まとめにしない。 */
+
+static letter *
+ltrcpy (lp1, lp2)
+     fast letter *lp1, *lp2;    /* V3.1 */
+{
+  fast letter *org;             /* V3.1 */
+
+  org = lp1;
+  while ((*lp1++ = *lp2++) != EOLTTR);
+  return (org);
+}
+
+#ifdef nodef
+static letter *
+ltrncpy (lp1, lp2, n)           /* 末尾に'EOLTTR'をセット */
+     letter *lp1, *lp2;
+     int n;
+{
+  fast letter *org;
+
+  org = lp1;
+  for (; n; --n)
+    if (EOLTTR == (*lp1++ = *lp2++))
+      return (org);
+  *lp1 = EOLTTR;
+  return (org);
+}
+#endif
+
+ /** letterの列の末尾に一文字つなげる */
+static                          /* V3.1 */
+letter *
+ltr1cat (lp, l)
+     fast letter *lp, l;        /* V3.1 */
+{
+  fast letter *org;             /* V3.1 */
+
+  org = lp;
+  totail (lp);
+  *lp++ = l;
+  *lp = EOLTTR;
+  return (org);
+}
+
+ /** 文字列の末尾に一文字つなげる。ltr1catのchar版 */
+#ifdef OMRON_LIB
+static
+#endif
+char *
+chrcat (s, c)
+     fast char *s, c;           /* V3.1 */
+{
+  fast char *org;               /* V3.1 */
+
+  org = s;
+  strtail (s);
+  *s++ = c;
+  *s = '\0';
+  return (org);
+}
+
+static letter *
+ltrcat (lp1, lp2)
+     fast letter *lp1, *lp2;    /* V3.1 */
+{
+  fast letter *org;             /* V3.1 */
+
+  org = lp1;
+  totail (lp1);
+  ltrcpy (lp1, lp2);
+  return (org);
+}
+
+ /** letterの列lp2の各要素の最上位ビットを立ててから、lp1の後ろにつなげる。*/
+static                          /* V3.1 */
+letter *
+bitup_ltrcat (lp1, lp2)
+     fast letter *lp1, *lp2;    /* V3.1 */
+{
+  fast letter *org;             /* V3.1 */
+
+  org = lp1;
+  totail (lp1);
+
+  while ((*lp1 = *lp2++) != EOLTTR)
+    *lp1++ |= HG1BIT;
+         /** lp2 の要素全ての最上位ビットを立てる。*lp2がNISEBP(rk_spclval.h
+             でdefine)などのときは最初から最上位が立ってるからよい */
+
+  return (org);
+}
+
+ /** ltrcatしたあと、結果の文字列の末尾にポインタをもっていく。*/
+#ifdef OMRON_LIB
+static
+#endif
+letter *
+ltrgrow (lp1, lp2)
+     fast letter *lp1, *lp2;    /* V3.1 */
+{
+  totail (lp1);
+  while ((*lp1 = *lp2++) != EOLTTR)
+    lp1++;
+  return (lp1);
+}
+
+int
+ltrlen (lp)
+     fast letter *lp;           /* V3.1 */
+{
+  fast letter *org;             /* V3.1 */
+
+  for (org = lp; *lp != EOLTTR; lp++);
+  return (lp - org);
+}
+
+ /**    letterの列の最後の文字へのポインタを返す。但し空文字列に対しては
+        そのまま返す。*/
+static letter *
+ltrend (lp)
+     fast letter *lp;           /* V3.1 */
+{
+  return ((*lp != EOLTTR) ? (lp + ltrlen (lp) - 1) : lp);
+}
+
+ /**    文字列の最後の文字へのポインタを返す。ltrend()のchar版。ltrend()と
+        同様、空文字列のときは特例がある。*/
+#ifdef OMRON_LIB
+static
+#endif
+char *
+strend (s)
+     fast char *s;              /* V3.1 */
+{
+  return (*s ? (s + strlen (s) - 1) : s);
+}
+
+int
+ltrcmp (lp1, lp2)
+     fast letter *lp1, *lp2;    /* V3.1 */
+{
+  for (; *lp1 == *lp2; lp1++, lp2++)
+    if (*lp1 == EOLTTR)
+      return (0);
+  return (*lp1 > *lp2 ? 1 : -1);
+}
+
+#ifdef nodef
+int
+ltrncmp (lp1, lp2, n)
+     letter *lp1, *lp2;
+     int n;
+{
+  for (; n && *lp1 == *lp2; n--, lp1++, lp2++)
+    if (*lp1 == EOLTTR)
+      return (0);
+  return (n == 0 ? 0 : (*lp1 > *lp2 ? 1 : -1));
+}
+
+/* 88/06/14 V3.1 */
+/******************************************************************************/
+#ifndef OMRON
+letter *
+ltr_index (lp, l)
+     letter l, *lp;
+{
+  for (; *lp != EOLTTR; lp++)
+    if (*lp == l)
+      return (lp);
+  return (NULL);
+}
+#endif
+/******************************************************************************/
+#endif
+
+static                          /* V3.1 */
+letter *
+ltr_rindex (lp, l)
+     fast letter l, *lp;        /* V3.1 */
+{
+  fast letter *lp2;             /* V3.1 */
+
+  for (lp += ltrlen (lp2 = lp); lp2 != lp;)
+    if (*--lp == l)
+      return (lp);
+  return (NULL);
+}
+
+ /** 文字列の末尾一文字をカットする。*/
+/*static V3.1 */
+letter *
+ltr1cut (lp)
+     fast letter *lp;           /* V3.1 */
+{
+  fast int l;                   /* V3.1 */
+
+  if (0 == (l = ltrlen (lp)))
+    BUGreport (0);              /* Illegal POP */
+  *(lp + --l) = EOLTTR;
+  return (lp);
+}
+
+ /** letterの一文字を長さ1の文字列に変換する */
+static                          /* V3.1 */
+letter *
+ltr_to_ltrseq (lp, l)
+     letter *lp, l;
+{
+  *lp++ = l;
+  *lp-- = EOLTTR;
+  return (lp);
+}
+
+ /** charの列からletterを一つ取り出す。但し'\0'はEOLTTRに変える */
+#ifdef OMRON_LIB
+static
+#endif
+  letter
+letterpick (lbfpptr)
+     fast uns_chr **lbfpptr;
+{
+  fast letter l = 0;
+  fast int i;                   /* V3.1 */
+
+  for (i = (*(cur_rk_table->bytcnt_method)) (*lbfpptr); i; i--)
+    l = (l << 8) + *(*lbfpptr)++;
+  return (l == 0 ? EOLTTR : l);
+}
+
+ /**    入力されたコードを文字単位にまとめる。但しEOFはLTREOF(rk_spclval.h
+        にて定義)に変える。*/
+/* *INDENT-OFF* */
+letter
+romkan_next ()
+/* *INDENT-ON* */
+{
+  letter in;
+  int i, n;
+  uns_chr c;
+
+  /* unnextされている場合は、それを取り出す。 */
+  if (cur_rk->unnext_buf != EOLTTR)
+    return (in = cur_rk->unnext_buf, cur_rk->unnext_buf = EOLTTR, in);
+
+  if ((letter) EOF == (in = (*(cur_rk_table->keyin_method)) ()))
+    return (LTREOF);
+  c = (in &= 0xff);
+  n = (*(cur_rk_table->kbytcnt_method)) (&c);
+  for (i = 1; i < n; i++)
+    in = (in << 8) + ((*(cur_rk_table->keyin_method)) () & 0xff);
+  return (in);
+}
+
+ /*     letterの文字 l とcharの文字 c の比較。エンドマーク同士(letter列の
+    エンドマークはEOLTTR、char列のは'\0')も一致とみなす。 */
+#define ltrchreq(l, c) ((l) == (c) && (c) != 0 || (l) == EOLTTR && (c) == 0)
+
+ /** letterの文字列とcharの文字列の比較 但し大小比較は符号なしとしてやる */
+#ifdef OMRON_LIB
+static
+#endif
+  int
+ltrstrcmp (l, s)
+     fast letter *l;            /* V3.1 */
+     fast char *s;              /* V3.1 */
+{
+  for (; ltrchreq (*l, *s); l++, s++)
+    if (*s == 0)
+      return (0);
+  return (1);
+/*
+        return((*l < (uns_chr)*s || *l == EOLTTR)? -1 : 1);
+*/
+}
+
+ /** 最後にマッチした文字 つまりurabufの最後。urabufが空だとEOLTTRを返す */
+static                          /* V3.1 */
+  letter
+lastmch ()
+{
+  return (*(ltrend (cur_rk->urabuf)));
+}
+
+/* end of 'letter' functions */
+
+
+ /** 変換バッファのクリア */
+ /* 注意! romkan_clear()を呼ぶ時は、必ずその前に、cur_rkをセットすること */
+void
+romkan_clear ()
+{
+#ifdef KDSP
+#       ifdef MVUX
+  *displine = EOLTTR;
+#       endif
+#endif
+  cur_rk->ungetc_buf = *(cur_rk->keybuf) = *(cur_rk->urabuf) = *(cur_rk->disout) = *(cur_rk->rk_output) = EOLTTR;
+  cur_rk->curdis = DISOUT;
+  cur_rk->lastoutlen = cur_rk->lastkbflen = 0;
+}
+
+ /**    WnnV4.0マルチクライアント用のRomkan構造体を初期化する **/
+Romkan *
+rk_buf_init ()
+{
+  register Romkan *p;
+  register int i;
+
+  if ((p = (Romkan *) malloc (sizeof (Romkan))) == NULL)
+    {
+      return (NULL);
+    }
+  malloc_for_henmatch (&(p->rk_henmatch), cur_rk_table->rk_hensuudef.count);
+  malloc_for_modesw (&(p->rk_modesw), cur_rk_table->rk_modesw.max);
+  p->rk_modesw.max = cur_rk_table->rk_modesw.max;
+  p->rk_modesw.count = cur_rk_table->rk_modesw.count;
+  for (i = 0; i < cur_rk_table->rk_modesw.max; i++)
+    {
+      p->rk_modesw.point[i] = cur_rk_table->rk_modesw.point[i];
+    }
+  malloc_for_usehyo (&(p->rk_usehyo), cur_rk_table->rk_usehyo.size);
+  p->rk_usehyo.size = cur_rk_table->rk_usehyo.size;
+  for (i = 0; i < (cur_rk_table->rk_usehyo.size + 1); i++)
+    {
+      p->rk_usehyo.usemaehyo[i] = cur_rk_table->rk_usehyo.usemaehyo[i];
+      p->rk_usehyo.usehyo[i] = cur_rk_table->rk_usehyo.usehyo[i];
+      p->rk_usehyo.useatohyo[i] = cur_rk_table->rk_usehyo.useatohyo[i];
+    }
+  p->rk_errstat = NULL;
+  p->flags = 0;
+  p->nil[0] = EOLTTR;
+  p->ungetc_buf = EOLTTR;
+  p->unnext_buf = EOLTTR;
+  p->delchr2 = EOLTTR;
+  p->ebf_sw = NULL;
+  p->oneletter[0] = p->oneletter[1] = EOLTTR;
+  p->keybuf[0] = p->urabuf[0] = p->disout[0] = p->rk_output[0] = EOLTTR;
+  p->rk_table = (RomkanTable *) NULL;
+  return (p);
+}
+
+RomkanTable *
+rk_table_buf_init ()
+{
+  RomkanTable *p;
+  if ((p = (RomkanTable *) malloc (sizeof (RomkanTable))) == NULL)
+    {
+      return (NULL);
+    }
+  p->flags = 0;
+  p->rk_usehyo.size = -1;
+  p->prv_modfnm[0] = NULL;
+  return (p);
+}
+
+
+void
+rk_close (p)
+     Romkan *p;
+{
+/*free_for_all_area(); *//* V3.1 */
+  free_for_modesw (&(p->rk_modesw));
+  free_for_henmatch (&(p->rk_henmatch));
+  free_for_usehyo (&(p->rk_usehyo));
+  free (p);
+}
+
+ /**    表を読み込んで変換の初期設定をする。(part 3)*/
+ /* WnnV4.0マルチクライアントの場合
+    romkan_init3は、Romkan構造体へのポインタを返します。
+    その後、romkanをする場合は、グローバル変数cur_rkに
+    そのポインタを入れなければならない。 
+    但し、romkan_init3()は、内部で一時的にcur_rkをセットし、
+    returnする時に元の値に戻します。 */
+
+#ifdef nodef
+/* 88/06/13 V3.1 */
+ /** 変換表のクリア */
+static                          /* V3.1 */
+  void
+romkan_reset ()
+{
+  if (cur_rk_table->rk_modenaibu.org != NULL)
+    {
+      cur_rk_table->rk_modenaibu.org[0] = 0;    /* Terminator */
+    }
+  choosehyo ();
+  romkan_clear ();
+}
+#endif
+
+
+RomkanTable *
+romkan_table_init (p, modhyo, keyinfn, bytcntfn, kbytcntfn, flags_)
+     RomkanTable *p;
+     fast char *modhyo;         /* モード定義表の名又はそのパス名 */
+letter (*keyinfn) ();
+     fast int (*bytcntfn) ();
+     fast int (*kbytcntfn) ();
+     fast int flags_;
+{
+  int errcod;                   /* 今の所1のみ */
+  fast RomkanTable *tmp_cur_rk_table;
+  fast RomkanTable *rk_table_buf;
+
+  tmp_cur_rk_table = cur_rk_table;
+  if (p == NULL)
+    {
+      if ((rk_table_buf = (RomkanTable *) rk_table_buf_init ()) == NULL)
+        {
+          return (NULL);
+        }
+    }
+  else
+    {
+      rk_table_buf = p;
+    }
+  cur_rk_table = rk_table_buf;
+  cur_rk_table->keyin_method = keyinfn;
+  cur_rk_table->bytcnt_method = (bytcntfn == NULL ? head_bytecount : bytcntfn);
+  cur_rk_table->kbytcnt_method = (kbytcntfn == NULL ? cur_rk_table->bytcnt_method : kbytcntfn);
+  /* 88/05/30/ V3.1 */
+  if (modhyo == NULL)
+    modhyo = "";
+  strcpy (cur_rk_table->prv_modfnm, modhyo);    /* V3.1 */
+  if ((errcod = setjmp (cur_rk_table->env0)) != 0)
+    {
+      /* 88/06/13 V3.1 */
+      free_for_all_area ();     /* V3.1 */
+      fprintf (stderr, "romkan_init failed.");
+    }
+  else
+    {
+      readdata (modhyo);        /* 88/06/08 V3.1 */
+    }
+  cur_rk_table = tmp_cur_rk_table;
+  if (!errcod)
+    {
+      return (rk_table_buf);
+    }
+  else
+    {
+      free (rk_table_buf);
+      return (NULL);
+    }
+}
+
+
+ /**    表を読み込んで変換の初期設定をする。(part 3)*/
+
+Romkan *
+romkan_init3 (delchr_, nisedl_, delchr2_, flags_)
+     letter delchr_;            /* DELとして使うコード */
+     letter nisedl_;            /* 偽DELとして使うコード */
+     letter delchr2_;           /* DELとして使うコードが二つある場合そのもう一方 */
+     int flags_;
+ /* 以下のフラグが利用可。これらはrk_spclval.hにて定義。
+    RK_CHMOUT:モードチェンジを知らせるコードを返すか?
+    RK_KEYACK:キーインに対し必ず何かを返すか
+    RK_NONISE:偽コードを出さないようにするか
+    RK_REDRAW:Wnn用特殊フラグ(redraw用のフラグを出すかどうか)
+    RK_SIMPLD:deleteの動作を単純にするか
+  */
+{
+  Romkan *tmp_cur_rk;
+  Romkan *rk_buf;
+
+  tmp_cur_rk = cur_rk;
+
+  if (setjmp (cur_rk_table->env0) != 0)
+    {
+      return (NULL);
+    }
+
+  if ((rk_buf = (Romkan *) rk_buf_init ()) == NULL)
+    {
+      return (NULL);
+    }
+  cur_rk = rk_buf;
+  /* 偽コードを出すかの設定はromkan_clearで使うので、フラグの設定を
+     先にやっておかないといけない。 */
+  cur_rk->flags = flags_;
+  cur_rk->curdis = DISOUT;
+  cur_rk->delchr = delchr_;
+  cur_rk->nisedl = nisedl_;
+  cur_rk->delchr2 = delchr2_;
+ /**    実はDELのキャラクタを二個まで持てる。二個目:delchr2は、未設定の
+        とき(値がEOLTTR)は無視される。それ以外は、delchr2が入力されると
+        delchrが入力されたのと同じ振る舞いをする。*/
+
+  choosehyo ();
+  cur_rk = tmp_cur_rk;
+  return (rk_buf);
+}
+
+#define ifflg(a, b) ((a) ? (b) : 0)
+
+ /**    表を読み込んで変換の初期設定をする。(part 2: キー入力に対し必ず何か
+        返すようにするか、キーバッファをクリアするかどうかなども指定可)*/
+
+Romkan *
+romkan_init2 (delchr_, chmoutf, keyinfn, bytcntfn, keyackf, restartf, nonisecodf)
+     char chmoutf, keyackf, restartf, nonisecodf;
+     letter delchr_;
+letter (*keyinfn) ();
+     int (*bytcntfn) ();        /* 引数の詳細はromkan_init3を参照 */
+{
+  return (romkan_init3 (delchr_, toNISE (delchr_), EOLTTR, keyinfn, bytcntfn, (int (*)()) NULL, ifflg (chmoutf, RK_CHMOUT) | ifflg (keyackf, RK_KEYACK) | ifflg (nonisecodf, RK_NONISE)));
+}
+
+ /**    表を読み込んで変換の初期設定をする。(part 1)*/
+Romkan *
+romkan_init (delchr_, chmoutf, keyinfn, bytcntfn)
+     char chmoutf;
+     letter delchr_;
+letter (*keyinfn) ();
+     int (*bytcntfn) ();        /* 引数の詳細はromkan_init3を参照 */
+{
+  return (romkan_init2 (delchr_, chmoutf, keyinfn, bytcntfn, 0, 0, 0));
+}
+
+
+ /**    バイトカウント関数のデフォルト。sの指している所に入っているのが
+        何バイトコードかを返す。
+        romkan_nextに注意。そちらでは、バイトカウント関数の値は
+        引数の一文字目にのみ依存すると仮定している。*/
+static                          /* V3.1 */
+  int
+head_bytecount (s)
+     fast uns_chr *s;
+{
+  fast uns_chr c = *s;
+#ifdef IKIS
+  return ((c <= 0xa0 || c == 0xff) ? 1 : 2);
+#else
+  if (c == SS2)
+    return (2);
+  if (c == SS3)
+    return (3);
+  if (c <= 0xa0)
+    return (1);
+  else
+    return (2);
+#endif
+}
+
+ /** 変換された文字を順次返す */
+/* *INDENT-OFF* */
+letter
+romkan_getc ()
+/* *INDENT-ON* */
+{
+  fast letter l;                /* V3.1 */
+
+  /* ungetcされている場合は、それを取り出す。 */
+  if (cur_rk->ungetc_buf != EOLTTR)
+    return (l = cur_rk->ungetc_buf, cur_rk->ungetc_buf = EOLTTR, l);
+
+  while (*(cur_rk->curdis) == EOLTTR)
+    {
+      /* romkan_next()の値がLTREOFの時も、そのまま送れば良い。 */
+      cur_rk->curdis = romkan_henkan (romkan_next ());
+
+      /* keyackflgが非0なら、キーインがあれば必ず何か返す。その
+         ため、返すべきものがない時はEOLTTRを返すことにする。 */
+      if (cur_rk->flags & RK_KEYACK)
+        break;
+    }
+
+  if (EOLTTR != (l = *(cur_rk->curdis)))
+    cur_rk->curdis++;
+  return (l);
+  /* 偽物の文字なら、HG1BITが立っている。 */
+  /* 特別なコード(例えば偽のBEEPとしてNISEBP)を返すときがある。それらは
+     rk_spclval.hに定義されている。 */
+}
+
+ /**    romkan_getcの下位関数として、入力を一文字受け取って
+        変換結果の文字列を出力する。*/
+letter *
+romkan_henkan (mae_in)
+     letter mae_in;
+{
+  letter mae_out[2], *p;
+
+  /* if(*(cur_rk->curdis) != EOLTTR){p = cur_rk->curdis; cur_rk->curdis = cur_rk->nil; return(p);} */
+  /* ↑これではmae_inが無視される */
+  cur_rk->curdis = cur_rk->nil;
+
+  /* 前・後処理への入力は常にただ一文字 */
+  mae_out[0] = mae_out[1] = EOLTTR;
+
+  cur_rk->eofflg = cur_rk->rk_errstat = 0;
+  *(cur_rk->rk_output) = *(cur_rk->disout) = EOLTTR;
+
+  maeato_henkan (mae_in, mae_out, cur_rk->rk_usehyo.usemaehyo);
+  cur_rk->rk_input = *mae_out;
+
+  if (cur_rk->rk_input == LTREOF)
+    {
+      /* LTREOFが来た場合、(error)を無視し、本処理バッファの末尾迄
+         強制変換する。そのためにeofflgを1にする。その後、結果の
+         末尾に、LTREOFが来た時の特別コード(指定されていれば)と、
+         LTREOFをつなぐ。 */
+      cur_rk->eofflg = 1;
+      match ();
+
+      cur_rk->eofflg = 2;
+      add_at_eof ();            /* codeoutに、LTREOFが来た時出すコードが入る。 */
+      ltr1cat (cur_rk->codeout, LTREOF);
+
+      ltrcat (cur_rk->disout, cur_rk->codeout);
+      ltrcat (cur_rk->rk_output, cur_rk->codeout);
+    }
+  else if (cur_rk->rk_input == EOLTTR)
+    {
+      /* EOLTTRが来た場合も、上と同様の処理を行うが、LTREOFは
+         つながない。なお、これはromkan_getc()を呼んでいる時は
+         起こらない(romkan_next()がEOLTTRを返さないから)。 */
+      cur_rk->eofflg = 1;
+      match ();
+    }
+  else if (cur_rk->rk_input == cur_rk->delchr || cur_rk->rk_input == cur_rk->delchr2)
+    {
+      /* delchr2が未設定ならその値はEOLTTRなのでrk_inputと等しくない。 */
+      romkan_delete (cur_rk->rk_input); /* V3.1 */
+    }
+  else
+    {
+      ltr1cat (cur_rk->keybuf, cur_rk->rk_input);
+      ltr1cat (cur_rk->disout, toNISE (cur_rk->rk_input));
+      match ();
+    }
+
+  if (!(cur_rk->flags & RK_CHMOUT))
+    {
+      /* chmoutflgが0の時は、CHMSIGを出さない。 */
+      for (p = DISOUT;; p++)
+        {
+          while (*p == CHMSIG)
+            ltrcpy (p, p + 1);
+          if (*p == EOLTTR)
+            break;
+        }
+    }
+
+  if ((cur_rk->flags & RK_REDRAW) && NULL != (p = ltr_rindex (cur_rk->disout, cur_rk->nisedl)))
+    {
+      for (p++; *p != EOLTTR || (ltr1cat (cur_rk->disout, REDRAW), 0); p++)
+        if (!isSPCL (*p))
+          break;
+    }
+  /* wnnのredrawのフラグが立っていて、disoutがnisedl以後特殊コードのみ
+     で終わっていたら、REDRAWを出して、Wnnに変換行のredrawをさせる。 */
+
+  return (DISOUT);
+}
+
+
+/******************************************************************************/
+ /* デバッグ用関数 */
+#ifdef  KDSP
+#       ifdef   MVUX
+
+pridbg2 (a, b, c)
+     char *a, *c;
+     letter *b;
+{
+  printf ("%s", a);
+  dump_fordbg (b);
+  printf ("%s", c);
+}
+
+ltr_displen (l)
+     letter l;
+{
+  while (l >= 256)
+    l >>= 8;
+
+  if (l == 0)
+    return (0);
+  if (l < ' ')
+    return (0);
+  if (168 <= l && l <= 170)
+    return (1);
+  return (l > 160 ? 2 : 1);
+}
+
+dump_fordbg (lp)
+     letter *lp;
+{
+  while (*lp != EOLTTR)
+    printf ("%x/", *lp++);
+}
+
+print_fordbg (lp)
+     letter *lp;
+{
+  while (*lp != EOLTTR)
+    putletter (*lp++ & ~HG1BIT);
+}
+
+print_ltrseq (lp)
+     letter *lp;
+{
+  while (*lp != EOLTTR)
+    print_ltr (*lp++ & ~HG1BIT);
+}
+
+print_ltr (l)
+     letter l;
+{
+  letter *disptail;
+  int i;
+
+  if (!isSPCL (l))
+    l &= ~HG1BIT;
+
+  if (l == CHMSIG)
+#ifdef CHMDSP
+    printf ("...mode=%s\n", romkan_dispmode ())
+#endif
+      ;
+  else
+#define BEEPCH  '\007'
+#define NEWLIN  '\n'
+  if (l == BEEPCH || l == NISEBP)
+    putchar (BEEPCH);
+  else if (l == NEWLIN)
+    {
+      *(cur_rk->displine) = *(cur_rk->keybuf) = *(cur_rk->urabuf) = EOLTTR;
+      cur_rk->lastoutlen = cur_rk->lastkbflen = 0;
+      putchar (l);
+    }
+  else if (l == cur_rk->delchr || l == cur_rk->nisedl)
+    {
+      if (*(cur_rk->displine) == EOLTTR)
+        putchar (BEEPCH);
+      else
+        {
+          disptail = ltrend (cur_rk->displine);
+          for (i = ltr_displen (*disptail); i; i--)
+            printf ("\031 \031");
+          *disptail = EOLTTR;
+        }
+    }
+  else
+    {
+      ltr1cat (cur_rk->displine, l);
+      putletter (l);
+    }
+}
+
+#       endif /* of #ifdef MVUX */
+#endif
+/* デバッグ用関数終わり */
+
+
+/* 88/06/10 V3.1 */
+ /** DELが入力されたときの処理をする */
+static                          /* V3.1 */
+  void
+romkan_delete (input_del)
+     letter input_del;
+{
+  if (ltrlen (cur_rk->keybuf) > ((cur_rk->flags & RK_SIMPLD) ? 0 : cur_rk->lastkbflen))
+    {
+      ltr1cut (cur_rk->keybuf);
+      set_rubout (cur_rk->disout, 1, cur_rk->nisedl);
+    }
+  else
+    {
+      if (*(cur_rk->urabuf) != EOLTTR && !(cur_rk->flags & RK_SIMPLD))
+        {
+          ltr1cut (ltrcpy (cur_rk->keybuf, cur_rk->urabuf));
+          *(cur_rk->urabuf) = EOLTTR;
+
+          set_rubout (cur_rk->rk_output, cur_rk->lastoutlen, input_del);
+
+          set_rubout (cur_rk->disout, cur_rk->lastkbflen, cur_rk->nisedl);
+          bitup_ltrcat (ltrcat (cur_rk->disout, cur_rk->rk_output), cur_rk->keybuf);
+
+          cur_rk->lastkbflen = cur_rk->lastoutlen = 0;
+        }
+      else
+        {
+          set_rubout (cur_rk->disout, 1, input_del);
+          set_rubout (cur_rk->rk_output, 1, input_del);
+        }
+    }
+}
+
+ /**    letterの列 lp1 と lp2 のマッチを試みる。返値は、lp1がlp2の頭部と
+        一致の時 -1、lp1またはその頭部とlp2が一致のときは一致長(lp2が
+        空文字列の時を含む。この場合返値は0)、それ以外は -2。
+        lp2側に式が含まれていたら評価をする。lp1側には式を含んではだめ */
+static                          /* V3.1 */
+  int
+prefixp (lp1, lp2)
+     letter *lp1, *lp2;
+{
+  /* 1行マッチさせるごとに、まずmatch情報をクリアしてから。
+     つまり、rk_henmatch.point[0].ltrmch = EOLTTR; としておく。 */
+
+  fast int mch_len = 0, d_len;  /* V3.1 */
+
+  for (;;)
+    {
+      if (*lp2 == EOLTTR)
+        return (mch_len);
+      if (*lp1 == EOLTTR)
+        return (-1);
+      if ((d_len = p_eq (&lp2, &lp1)) < 0)
+        return (d_len);
+      mch_len += d_len;
+    }
+}
+
+ /** num番目の変数が既にある文字とマッチしていると仮定して、その文字を返す */
+static                          /* V3.1 */
+  letter
+mchedsrc (num)
+     fast int num;              /* V3.1 */
+{
+  fast matchpair *pairptr;      /* V3.1 */
+
+  if (cur_rk->rk_henmatch.size <= 0)
+    return (0);
+  for (pairptr = cur_rk->rk_henmatch.point; pairptr->ltrmch != EOLTTR; pairptr++)
+    {
+      if (num == pairptr->hennum)
+        return (pairptr->ltrmch);
+    }
+  return (BUGreport (8), 0);
+}
+
+ /**    num番目の変数が文字 l とマッチするか調べる。その変数がunboundだった
+        場合は l にbindする。マッチしたら(bindの時を含む)1、しないと0を返す */
+static                          /* V3.1 */
+  int
+mchsrc (num, l)
+     fast int num;              /* V3.1 */
+     fast letter l;             /* V3.1 */
+{
+  fast matchpair *pairptr;      /* V3.1 */
+
+  if (hen_ikisrc (num, l) == 0)
+    return (0);
+  if (cur_rk->rk_henmatch.size <= 0)
+    return (0);
+  for (pairptr = cur_rk->rk_henmatch.point; pairptr->ltrmch != EOLTTR; pairptr++)
+    {
+      if (num == pairptr->hennum)
+        return (pairptr->ltrmch == l);
+    }
+
+  pairptr->ltrmch = l;
+  pairptr->hennum = num;
+  (++pairptr)->ltrmch = EOLTTR;
+  return (1);
+}
+
+ /**    l1pから一単位を取って評価し、文字l2と一致するかどうかを返す。評価した
+        結果が一文字にならなかったら、当然一致しない。*/
+static                          /* V3.1 */
+  int
+l_eq (l1p, l2)
+     letter *l1p, l2;
+{
+  letter evlrsl[RSLMAX];
+
+  switch (SHUBET (*l1p))
+    {
+    case 0:
+      return (*l1p == l2);
+    case 1:
+      return (mchsrc ((int) LWRMSK (*l1p), l2));
+    case 2:
+      mchevl (&l1p, evlrsl);
+      return (evlrsl[0] == l2 && evlrsl[1] == EOLTTR);
+    default:
+      return (BUGreport (1), 0);
+    }
+}
+
+ /**    prefixp内で使用  但し引数の順序は逆、すなわち式が含まれうるのはl1pp側
+        のみ。l1ppから一単位ぶん取って評価したものとl2ppのマッチを試みる。それ
+        がl2ppまたはその頭部とマッチすれば一致長を返し(l1ppの評価結果が空文字
+        列の時を含む。この場合返値は0)、逆にl1ppの評価結果の頭部とl2ppがマッ
+        チした時は -1を返す。マッチが失敗したら返値は -2。*/
+static                          /* V3.1 */
+  int
+p_eq (l1pp, l2pp)
+     fast letter **l1pp, **l2pp;        /* V3.1 */
+{
+  int num;
+  letter evlrsl[RSLMAX], *rslptr;
+  fast int retval = -2;         /* V3.1 */
+
+  /*  l2pp側には式を含まない筈 */
+  if (!is_HON (**l2pp))
+    {
+      /*  if(is_HON(**l1pp)) retval = p_eq(l2pp, l1pp); else  */
+      BUGreport (9);
+    }
+  else
+    {
+      switch (SHUBET (**l1pp))
+        {
+        case 0:         /* 文字同士 */
+          retval = (*(*l1pp)++ == *(*l2pp)++ ? 1 : -2);
+          break;
+        case 1:         /* 変数と文字 */
+          num = LWRMSK (*(*l1pp)++);
+          retval = (mchsrc (num, *(*l2pp)++) ? 1 : -2);
+          break;
+        case 2:         /* 式と文字 */
+          mchevl (l1pp, rslptr = evlrsl);
+          for (retval = 0; *rslptr != EOLTTR; retval++)
+            {
+              if (**l2pp == EOLTTR)
+                {
+                  retval = -1;
+                  break;
+                }
+              else if (*rslptr++ != *(*l2pp)++)
+                {
+                  retval = -2;
+                  break;
+                }
+            }
+          break;
+        default:
+          BUGreport (2);
+        }
+    }
+
+  return (retval);
+}
+
+ /** l1pから一単位評価してl2pに入れる */
+#ifdef  MULTI
+
+
+#define XY2INT(X, Y) (((X) << 24) | (Y))        /* これが1回しかYを評価しないことに
+                                                   依存して書いてある箇所がある  注意! */
+
+ /** l1pから一単位評価してl2pに入れる */
+static void
+mchevl (l1pp, l2p)
+     letter **l1pp, *l2p;
+{
+  letter *l1p, tmpevl[RSLMAX];
+
+  l1p = *l1pp;
+
+  switch (SHUBET (*l1p))
+    {
+    case 0:
+      *l2p++ = *l1p++;
+      break;
+    case 1:
+      *l2p++ = mchedsrc ((int) LWRMSK (*l1p++));
+      break;
+    case 2:                     /* toupper, tolower, error, … */
+      switch (LWRMSK (*l1p++))
+        {
+        case 2:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_upper (*tmpevl);
+          break;
+        case 3:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_lower (*tmpevl);
+          break;
+        case 4:
+          *l2p++ = CHMSIG;
+          *l2p++ = *l1p++;
+          *l2p++ = 0;
+          break;                /* EOLではない */
+        case 5:
+          *l2p++ = CHMSIG;
+          *l2p++ = *l1p++;
+          *l2p++ = 1;
+          break;
+        case 6:
+          *l2p++ = CHMSIG;
+          *l2p++ = *l1p++;
+          *l2p++ = 2;
+          break;
+        case 7:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_updown (*tmpevl);
+          break;
+        case 8:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_zenalpha (*tmpevl);
+          break;
+        case 9:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_hira (*tmpevl);
+          break;
+        case 10:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_kata (*tmpevl);
+          break;
+        case 11:
+          mchevl (&l1p, tmpevl);
+          to_hankata (*tmpevl, &l2p);
+          break;                /* 特殊 */
+        case 12:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_zenhira (*tmpevl);
+          break;
+        case 13:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_zenkata (*tmpevl);
+          break;
+        case 14:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p += *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 15:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p -= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 16:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p *= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 17:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          if (!*tmpevl)
+            *l2p = LTRHUG;
+          else
+            *l2p /= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 18:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          if (!*tmpevl)
+            *l2p = LTRHUG;
+          else
+            *l2p %= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+          /* 19〜21・30は、条件を満たすと空文字列、
+             そうでないとUNUSDCを文字列として返す。 */
+        case 19:
+          mchevl (&l1p, tmpevl);
+          if (lastmch () != *tmpevl)
+            *l2p++ = UNUSDC;
+          break;
+        case 20:
+          if (!(cur_rk->rk_modesw.point)[LWRMSK (*l1p++)])
+            *l2p++ = UNUSDC;
+          break;
+        case 21:
+          if (cur_rk->rk_modesw.point[LWRMSK (*l1p++)])
+            *l2p++ = UNUSDC;
+          break;
+        case 22:
+          *l2p++ = REASIG;
+          break;
+        case 23:
+          *l2p++ = cur_rk->delchr;
+          break;
+        case 24:
+          *l2p++ = CHMSIG;
+          *l2p++ = 0;           /* これで「all」を表す */
+          *l2p++ = 0;
+          break;
+        case 25:
+          *l2p++ = CHMSIG;
+          *l2p++ = 0;
+          *l2p++ = 1;
+          break;
+        case 26:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p &= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 27:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p |= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 28:
+          mchevl (&l1p, tmpevl);
+          *l2p = ~(*tmpevl);
+          LWRCUT (*l2p++);
+          break;
+        case 29:
+          *l2p++ = URBFCL;
+          break;
+        case 30:
+          if (cur_rk->eofflg != 2 || *(cur_rk->keybuf) != EOLTTR)
+            *l2p++ = UNUSDC;
+          break;
+        case 31:
+          {
+            letter code, basenum;
+
+            mchevl (&l1p, tmpevl);
+            code = *tmpevl;
+            mchevl (&l1p, tmpevl);
+            if ((basenum = *tmpevl) <= 1 || BASEMX < basenum)
+              basenum = 10;
+            to_digit (code, basenum, &l2p);
+          }
+          break;
+        case 32:
+          mchevl (&l1p, tmpevl);
+          dakuadd (*tmpevl, &l2p);
+          break;                /* 特殊 */
+        case 33:
+          mchevl (&l1p, tmpevl);
+          handakuadd (*tmpevl, &l2p);
+          break;                /* 特殊 */
+        case 34:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = ltov (*tmpevl);
+          break;
+        case 35:
+          *l2p++ = ERRCOD;
+          break;
+          /* case 36: omitted */
+        case 37:
+          *l2p++ = CHMSIG;
+/*
+                                        *l2p++ = LWRMSK(*l1p++);
+*/
+          *l2p++ = *l1p++;
+          *l2p++ = *l1p++;
+          break;
+        case 38:
+          *l2p++ = CHMSIG;
+          *l2p++ = XY2INT (2, LWRMSK (*l1p++));
+          *l2p++ = *l1p++;
+          break;
+        case 39:
+          *l2p++ = CHMSIG;
+          *l2p++ = XY2INT (3, LWRMSK (*l1p++));
+          *l2p++ = *l1p++;
+          break;
+        case 40:
+          {
+            letter modnum;
+
+            modnum = LWRMSK (*l1p++);
+            if (cur_rk->rk_modesw.point[modnum] != *l1p++)
+              *l2p++ = UNUSDC;
+            break;
+          }
+        case 41:
+          {
+            letter modnum;
+
+            modnum = LWRMSK (*l1p++);
+            if (cur_rk->rk_modesw.point[modnum] == *l1p++)
+              *l2p++ = UNUSDC;
+            break;
+          }
+        case 42:
+          {
+            letter modnum;
+
+            modnum = LWRMSK (*l1p++);
+            if (cur_rk->rk_modesw.point[modnum] >= *l1p++)
+              *l2p++ = UNUSDC;
+            break;
+          }
+        case 43:
+          {
+            letter modnum;
+
+            modnum = LWRMSK (*l1p++);
+            if (cur_rk->rk_modesw.point[modnum] <= *l1p++)
+              *l2p++ = UNUSDC;
+            break;
+          }
+        case 44:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = SENDCH;
+          *l2p++ = *tmpevl;
+          break;
+        default:                /* case 0及び上記以外 */ ;
+          BUGreport (7);
+        }
+    }
+
+  *l2p = EOLTTR;
+  *l1pp = l1p;
+}
+#else /*!MULTI */
+static                          /* V3.1 */
+mchevl (l1pp, l2p)
+     letter **l1pp, *l2p;
+{
+  letter *l1p, tmpevl[RSLMAX];
+
+  l1p = *l1pp;
+
+  switch (SHUBET (*l1p))
+    {
+    case 0:
+      *l2p++ = *l1p++;
+      break;
+    case 1:
+      *l2p++ = mchedsrc ((int) LWRMSK (*l1p++));
+      break;
+    case 2:                     /* toupper, tolower, error, … */
+      switch (LWRMSK (*l1p++))
+        {
+        case 1:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_upper (*tmpevl);
+          break;
+        case 2:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_lower (*tmpevl);
+          break;
+        case 3:
+          *l2p++ = ERRCOD;
+          break;
+        case 4:
+          *l2p++ = CHMSIG;
+          *l2p++ = *l1p++;
+          *l2p++ = 0;
+          break;                /* EOLではない */
+        case 5:
+          *l2p++ = CHMSIG;
+          *l2p++ = *l1p++;
+          *l2p++ = 1;
+          break;
+        case 6:
+          *l2p++ = CHMSIG;
+          *l2p++ = *l1p++;
+          *l2p++ = 2;
+          break;
+        case 7:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_updown (*tmpevl);
+          break;
+        case 8:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_zenalpha (*tmpevl);
+          break;
+        case 9:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_hira (*tmpevl);
+          break;
+        case 10:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_kata (*tmpevl);
+          break;
+        case 11:
+          mchevl (&l1p, tmpevl);
+          to_hankata (*tmpevl, &l2p);
+          break;                /* 特殊 */
+        case 12:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_zenhira (*tmpevl);
+          break;
+        case 13:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = to_zenkata (*tmpevl);
+          break;
+        case 14:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p += *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 15:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p -= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 16:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p *= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 17:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          if (!*tmpevl)
+            *l2p = LTRHUG;
+          else
+            *l2p /= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 18:
+          mchevl (&l1p, tmpevl);
+          *l2p++ = ltov (*tmpevl);
+          break;
+          /* 19〜21・30は、条件を満たすと空文字列、
+             そうでないとUNUSDCを文字列として返す。 */
+        case 19:
+          mchevl (&l1p, tmpevl);
+          if (lastmch () != *tmpevl)
+            *l2p++ = UNUSDC;
+          break;
+        case 20:
+          if (!(cur_rk->rk_modesw.point)[LWRMSK (*l1p++)])
+            *l2p++ = UNUSDC;
+          break;
+        case 21:
+          if (cur_rk->rk_modesw.point[LWRMSK (*l1p++)])
+            *l2p++ = UNUSDC;
+          break;
+        case 22:
+          *l2p++ = REASIG;
+          break;
+        case 23:
+          *l2p++ = cur_rk->delchr;
+          break;
+        case 24:
+          *l2p++ = CHMSIG;
+          *l2p++ = 0;           /* これで「all」を表す */
+          *l2p++ = 0;
+          break;
+        case 25:
+          *l2p++ = CHMSIG;
+          *l2p++ = 0;
+          *l2p++ = 1;
+          break;
+        case 26:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p &= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 27:
+          mchevl (&l1p, tmpevl);
+          *l2p = *tmpevl;
+          mchevl (&l1p, tmpevl);
+          *l2p |= *tmpevl;
+          LWRCUT (*l2p++);
+          break;
+        case 28:
+          mchevl (&l1p, tmpevl);
+          *l2p = ~(*tmpevl);
+          LWRCUT (*l2p++);
+          break;
+        case 29:
+          *l2p++ = URBFCL;
+          break;
+        case 30:
+          if (cur_rk->eofflg != 2 || *(cur_rk->keybuf) != EOLTTR)
+            *l2p++ = UNUSDC;
+          break;
+        case 31:
+          {
+            letter code, basenum;
+
+            mchevl (&l1p, tmpevl);
+            code = *tmpevl;
+            mchevl (&l1p, tmpevl);
+            if ((basenum = *tmpevl) <= 1 || BASEMX < basenum)
+              basenum = 10;
+            to_digit (code, basenum, &l2p);
+          }
+          break;
+        case 32:
+          mchevl (&l1p, tmpevl);
+          dakuadd (*tmpevl, &l2p);
+          break;                /* 特殊 */
+        case 33:
+          mchevl (&l1p, tmpevl);
+          handakuadd (*tmpevl, &l2p);
+          break;                /* 特殊 */
+        default:                /* case 0及び上記以降 */ ;
+          BUGreport (7);
+        }
+    }
+
+  *l2p = EOLTTR;
+  *l1pp = l1p;
+}
+#endif /*!MULTI */
+
+ /** num番目の変数の変域が文字 l を含むかどうかを返す */
+static                          /* V3.1 */
+  int
+hen_ikisrc (num, l)
+     int num;
+     letter l;
+{
+  fast letter *defptr;          /* V3.1 */
+
+  defptr = cur_rk_table->rk_hyo.point[cur_rk->hyonum].hensudef[num];    /* V3.1 */
+  if (*defptr == VARRNG)
+    {
+      for (defptr++; *defptr != EOLTTR;)
+        if (*defptr++ <= l && l <= *defptr++)
+          return (1);
+      return (0);
+    }
+
+  for (; *defptr != EOLTTR; defptr++)
+    {
+      if (l == *defptr)
+        return (1);
+    }
+  return (0);
+}
+
+ /**    変換のメインルーチン。本処理を行うが、ついでに後処理もやっている。
+        ちなみに前処理は、romkan_getcの下位関数romkan_henkanの中で、
+        この関数を呼ぶ前にやっている。
+        この関数は、romkan_nextから一文字来る度に呼ばれる。呼び出された直後は
+        outputは空文字列、disoutには入力コード一文字が入っている。
+        この関数で得られる文字の列が、romkan_henkanに渡り、
+        romkan_getcは、それを文字ごとに分解して返す。
+        (error)でエラーが引き起こされた場合は0を返し、正常終了時は1を返す */
+static                          /* V3.1 */
+  int
+match ()
+{
+  int henkanflg = 0, okcode = 0, chm_exist;
+  letter *q;                    /* V3.1 */
+  letter urabufcreate[KBFSIZ], orgkeybuf[KBFSIZ];
+  letter *urabufjunbi, *outcutptr, *dis_end;
+  /* 88/03/01/ V3.1 */
+  letter nokoribuf[KBFSIZ];
+
+  if (*(cur_rk->keybuf) == EOLTTR)
+    {
+      *(cur_rk->urabuf) = EOLTTR;
+      return (1);
+    }
+
+  ltrcpy (urabufjunbi = orgkeybuf, cur_rk->keybuf);
+  outcutptr = cur_rk->rk_output;
+
+  while ((okcode = henkan_ok ()) > 0)
+    {
+      henkanflg = 1;
+
+      codeout_chg ();
+      ltrcat (cur_rk->rk_output, cur_rk->codeout);
+      /* 88/03/01/ V3.1 */
+      /*
+         p = keybuf + codein_len;
+
+         ltrcat(ltrcpy(keybuf, remainkbf), p);
+       */
+      ltrcpy (nokoribuf, cur_rk->keybuf + cur_rk->codein_len);
+      ltrcat (ltrcpy (cur_rk->keybuf, cur_rk->remainkbf), nokoribuf);
+
+      if (okcode == 2)
+        {
+          ltrcpy (urabufjunbi = urabufcreate, cur_rk->keybuf);
+          totail (outcutptr);
+        }
+    }
+
+  if (okcode == 0)
+    {
+      ltr1cut (ltrcpy (cur_rk->keybuf, orgkeybuf));
+      ltr_to_ltrseq (cur_rk->disout, NISEBP);
+      *(cur_rk->rk_output) = EOLTTR;
+      return (0);
+    }
+  if (henkanflg)
+    {
+      ltrcpy (cur_rk->urabuf, urabufjunbi);
+
+      set_rubout (cur_rk->disout, ltrlen (orgkeybuf) - 1, cur_rk->nisedl);
+
+      dis_end = cur_rk->disout;
+      totail (dis_end);
+      ltrcpy (dis_end, cur_rk->rk_output);
+
+      /* モードチェンジを直ちに知らせるため CHMSIGを出力
+         (romkan_chmack(1)をやってないと、あとで一文字ずつに
+         分解する時点で、CHMSIGをカット)。
+         但し、rk_outputからは、CHMSIGを抜く。
+         また、CHMSIGは末尾に1回しか出力しない
+         (2回以上あっても、1回にまとめて、末尾に置く)。 */
+      for (chm_exist = 0, q = cur_rk->rk_output;; q++)
+        {
+          while (*q == CHMSIG)
+            {
+              chm_exist = 1;
+              if (ltrcpy (q, q + 1) < outcutptr)
+                outcutptr--;
+            }
+          if (*q == EOLTTR)
+            break;
+        }
+      if (chm_exist)
+        {
+          /* CHMSIGを1つにまとめたものをdis_endにつなげ直す。
+             このif文をカットすれば、CHMSIGのとりまとめはやらない */
+          ltr1cat (ltrcpy (dis_end, cur_rk->rk_output), CHMSIG);
+        }
+
+      bitup_ltrcat (cur_rk->disout, cur_rk->keybuf);
+      cur_rk->lastoutlen = ltrlen (outcutptr);
+      cur_rk->lastkbflen = ltrlen (cur_rk->keybuf);
+    }
+  return (1);
+}
+
+ /**    LTREOFが入ったときに、何か出すように指定されているか調べて、
+        codeoutをその結果の文字列(指定がなかったら当然空)にポイントする。
+        超急ごしらえで、特殊コード等は一切無視する。*/
+static                          /* V3.1 */
+  void
+add_at_eof ()
+{
+  fast dat *datptr;             /* V3.1 */
+  fast int i;                   /* V3.1 */
+  fast int hyoseq;              /* V3.1 */
+  letter *p;
+  letter evlrsl[RSLMAX];
+
+  /* 88/06/14 V3.1 */
+  for (hyoseq = 0; cur_rk_table->rk_hyo.point != NULL && (cur_rk->hyonum = cur_rk->rk_usehyo.usehyo[hyoseq]) != -1; hyoseq++)
+    {
+      for (i = 0, datptr = cur_rk_table->rk_hyo.point[cur_rk->hyonum].data; (p = datptr[i].code[0]) != NULL; i++)
+        {
+          if (cur_rk->rk_henmatch.size > 0)
+            {
+              cur_rk->rk_henmatch.point[0].ltrmch = EOLTTR;
+            }
+          while (*p != EOLTTR)
+            {
+              switch (SHUBET (*p))
+                {
+                case 0: /* 文字 */
+                case 1: /* 変数 */
+                  /* これらがある場合は、NULLとは
+                     マッチし得ない。 */
+                  goto Pass;
+                case 2: /* 式 */
+                  mchevl (&p, evlrsl);
+                  if (*evlrsl != EOLTTR)
+                    goto Pass;
+                  /* 入力コード部に、評価すると
+                     空文字列になるものが、他にはない
+                     ことが前提。 */
+                }
+            }
+
+          ltrevlcpy (cur_rk->codeout = p = cur_rk->evalbuf[0][0], datptr[i].code[1]);
+          while (*p != EOLTTR)
+            {
+              if (isSPCL (*p))
+                ltrcpy (p, p + 1);
+              else
+                p++;
+            }
+          codeout_chg ();
+          return;
+
+        Pass:;
+        }
+    }
+  cur_rk->codeout = cur_rk->nil;
+}
+
+/* 88/06/02 V3.1 */
+ /**    num番目のモードをチェンジし、変換表を選択し直す。引数 mod の値が0なら
+        モードをoff、1ならon、2なら切り替える。旧modの値(0か1)を返す。*/
+static int
+chgmod (num, mod)
+     int num, mod;
+{
+  fast int oldmod;              /* V3.1 */
+
+  oldmod = cur_rk->rk_modesw.point[num];
+  cur_rk->rk_modesw.point[num] = (mod != 2 ? mod : !oldmod);
+  choosehyo ();
+  return (oldmod);
+}
+
+ /** 全モードを、modが1ならon、0ならoffに切り換える。2ならswitchする。*/
+static void
+allchgmod (mod)
+     int mod;
+{
+  fast int i;                   /* V3.1 */
+
+  /* 88/06/07 V3.1 */
+  for (i = 0; i < cur_rk->rk_modesw.count; i++)
+    cur_rk->rk_modesw.point[i] = (mod != 2 ? mod : !(cur_rk->rk_modesw.point[i]));
+  choosehyo ();
+}
+
+ /**    一回マッチを試みる。返値は、マッチして確定した場合1(モードチェンジが
+        混じっている場合は2)、マッチしたが未確定の時-1、マッチしなかったら0。
+        実行中は、変数 l に、それまでに一致した長さの最高記録を入れており、
+        より長く一致するものが見つかるごとに、これを更新する。lの値は、マッチ
+        していても0になることもある。p_eq() 及び prefixp() の注釈文を参照。*/
+static                          /* V3.1 */
+  int
+henkan_ok ()
+{
+  fast dat *datptr;             /* V3.1 */
+  fast int i, k;                /* V3.1 */
+  fast int l, j, hyoseq;        /* V3.1 */
+  char urabuf_clrf;             /* モードチェンジなどで、urabufをクリアする必要が
+                                   生じた場合はこれが立ち、その結果、henkan_ok()
+                                   が1を返すべきところで2を返す。それを見て、
+                                   match()がurabufなどの調整をする。 */
+  fast letter *p;               /* V3.1 */
+#ifndef MULTI
+  static char ebf_sw = 0;       /* V3.1 */
+  static letter oneletter[2] = { EOLTTR, EOLTTR };      /* V3.1 */
+#endif /*!MULTI */
+
+  if (*(cur_rk->keybuf) == EOLTTR)
+    return (-1);
+
+  /* 88/06/14 V3.1 */
+  for (l = -1, hyoseq = 0; cur_rk_table->rk_hyo.point != NULL && cur_rk->rk_usehyo.usehyo != NULL && (cur_rk->hyonum = cur_rk->rk_usehyo.usehyo[hyoseq]) != -1; hyoseq++)
+    {
+      for (i = 0, datptr = cur_rk_table->rk_hyo.point[cur_rk->hyonum].data; (p = datptr[i].code[0]) != NULL; i++)
+        {
+          if (cur_rk->rk_henmatch.size > 0)
+            {
+              cur_rk->rk_henmatch.point[0].ltrmch = EOLTTR;
+            }
+          switch (k = prefixp (cur_rk->keybuf, p))
+            {
+            case -2:
+              break;
+            case -1:
+              if (cur_rk->eofflg != 0)
+                break;
+              /* eofflgが立っていたら、未確定の可能性は
+                 捨てる。 */
+
+              return (-1);
+            default:
+              if (k > l)
+                {
+                  cur_rk->ebf_sw = !cur_rk->ebf_sw;
+                  for (j = 1; j <= 2; j++)
+                    {
+                      ltrevlcpy (cur_rk->evalbuf[cur_rk->ebf_sw][j - 1], datptr[i].code[j]);
+                    }
+
+                  l = k;
+                }
+            }
+        }
+    }
+
+  if (l >= 0)
+    {
+      cur_rk->codein_len = l;
+      cur_rk->codeout = cur_rk->evalbuf[cur_rk->ebf_sw][0];
+      cur_rk->remainkbf = cur_rk->evalbuf[cur_rk->ebf_sw][1];
+
+      for (urabuf_clrf = 0, p = cur_rk->codeout; *p != EOLTTR; p++)
+        {
+          switch (*p)
+            {
+            case CHMSIG:
+              /* codeoutの1,2バイト目に
+                 モード番号とスイッチが入ってる */
+              if (*(p + 1) == 0)
+                allchgmod ((int) *(p + 2));
+              else
+                chgmod ((int) LWRMSK (*(p + 1)), (int) *(p + 2));
+              ltrcpy (p + 1, p + 3);
+              /* CHMSIGだけ残して1,2バイト目cut */
+
+              urabuf_clrf = 1;
+              break;
+            case URBFCL:
+              /* urabufのクリアを明示的に指定する */
+              urabuf_clrf = 1;
+              ltrcpy (p, p + 1);
+              p--;              /* 一文字前にずれるため、
+                                   for文の p++ を相殺して、
+                                   同じ地点をもう一度見る。 */
+              break;
+            }
+        }
+
+      if (*(cur_rk->codeout) == ERRCOD)
+        {
+          if (cur_rk->eofflg == 0)
+            {
+              cur_rk->rk_errstat = 1;
+              return (0);
+            }
+
+          /* (error)であって、しかもeofflgが立ってたら、keybuf
+             の末尾まで、そのまま出す。 */
+          cur_rk->codein_len = ltrlen (cur_rk->keybuf);
+          cur_rk->codeout = ltrcpy (cur_rk->evalbuf[cur_rk->ebf_sw][0], cur_rk->keybuf);
+          cur_rk->remainkbf = cur_rk->nil;
+          cur_rk->rk_errstat = 2;
+
+          return (1);
+        }
+      /* (error)は単独でしか書けないので、エラー検出はこれで十分。 */
+
+      if (*(cur_rk->codeout) == REASIG)
+        {
+          *(cur_rk->codeout) = (romkan_restart () != 0 ? EOLTTR : CHMSIG);
+          /* 再readでエラったらモードチェンジの通知はしない */
+
+          urabuf_clrf = 1;
+        }
+      /* 表の再read。但し、これが起こったことを外に知らせるのはCHMSIGで
+         このコードそのものは外へ出ない。(restart)は、(error)同様、
+         単独でしか書けないので、検出はこれで十分。 */
+
+      return (urabuf_clrf ? 2 : 1);
+    }
+
+  /* 表に現れていないコードはそのまま返す */
+
+  cur_rk->codein_len = 1;
+  *(cur_rk->codeout = cur_rk->oneletter) = *(cur_rk->keybuf);
+  cur_rk->remainkbf = cur_rk->nil;
+  return (1);
+}
+
+static void
+free_for_all_area ()
+{
+  fast int i;
+
+  free_for_modetable_struct (&(cur_rk_table->rk_defmode));
+  free_for_modetable_struct (&(cur_rk_table->rk_taiouhyo));
+  free_for_modetable_struct (&(cur_rk_table->rk_path));
+  free_for_modebuf (&(cur_rk_table->rk_modebuf));
+  free_for_hyobuf (&(cur_rk_table->rk_hyobuf));
+  free_for_heniki (&(cur_rk_table->rk_heniki));
+  free_for_hensuu (&(cur_rk_table->rk_hensuu));
+
+  free_for_modetable_struct (&(cur_rk_table->rk_dspmode));
+  /* free_for_modesw(&(cur_rk_table->rk_modesw)); */
+  free_for_modenaibu (&(cur_rk_table->rk_modenaibu));
+  for (i = 0; i < cur_rk_table->rk_hyo.size; i++)
+    {
+      free_for_hyo_area (&(cur_rk_table->rk_hyo), i);
+    }
+  free_for_hyo (&(cur_rk_table->rk_hyo));
+  /* free_for_usehyo(&(cur_rk_table->rk_usehyo)); */
+  free_for_hensuudef (&(cur_rk_table->rk_hensuudef));
+  /* free_for_henmatch(&(cur_rk_table->rk_henmatch)); */
+}
+
+/* 88/06/10 V3.1 */
+ /* romkan_restart内で使うマクロ */
+#define taihi(X, Y) {(X) = (Y);}
+#define clear(X, N) {memset((char *)(&(X)), 0, (N));}
+#define recov(X, Y) taihi((Y), (X))
+
+ /**    表の動的再読み込みをする。現在の内部表現を全て退避し、前と同じ
+        ディレクトリ(に、現在のところ限定)から表を読み込む。もし、
+        読み込み中にエラーを検出すれば、もとの内部データを復活し非0を返す。*/
+static                          /* V3.1 */
+  int
+romkan_restart ()
+{
+  fast int i /*, j */ ;         /* V3.1 */
+  RomkanTable *rk_t = cur_rk_table;
+
+  modenaibutable rk_modenaibu_sv;
+  modeswtable rk_modesw_sv;
+  modetable rk_dspmode_sv;
+  hyotable rk_hyo_sv;
+  /* usehyotable  rk_usehyo_sv; */
+  hensuudeftable rk_hensuudef_sv;
+  /* matchtable   rk_henmatch_sv; */
+
+  /* char *dspmod_sv[2][2]; */
+
+  /* 待避 */
+  taihi (rk_modenaibu_sv, rk_t->rk_modenaibu);
+  taihi (rk_modesw_sv, rk_t->rk_modesw);
+  taihi (rk_dspmode_sv, rk_t->rk_dspmode);
+  taihi (rk_hyo_sv, rk_t->rk_hyo);
+  /* taihi(rk_usehyo_sv,          rk_t->rk_usehyo); */
+  taihi (rk_hensuudef_sv, rk_t->rk_hensuudef);
+  /* taihi(rk_henmatch_sv,                rk_t->rk_henmatch);
+
+     for(i = 0; i < 2; i++)
+     for(j = 0; j < 2; j++)  dspmod_sv[i][j] = rk_t->dspmod[i][j];
+   */
+
+  /* 消去 */
+  clear (rk_t->rk_modenaibu, sizeof (modenaibutable));
+  clear (rk_t->rk_modesw, sizeof (modeswtable));
+  clear (rk_t->rk_dspmode, sizeof (modetable));
+  clear (rk_t->rk_hyo, sizeof (hyotable));
+  /* clear(rk_t->rk_usehyo,               sizeof(usehyotable)); */
+  clear (rk_t->rk_hensuudef, sizeof (hensuudeftable));
+  /* clear(rk_t->rk_henmatch,             sizeof(matchtable)); */
+
+  if (NULL != romkan_table_init (rk_t, rk_t->prv_modfnm, rk_t->keyin_method, rk_t->bytcnt_method, rk_t->kbytcnt_method, rk_t->flags))
+    {
+      /* 正常終了 */
+      /* 88/06/10 V3.1 */
+      /* 不要領域の削除 */
+      free_for_modenaibu (&rk_modenaibu_sv);
+      free_for_modesw (&rk_modesw_sv);
+      free_for_modetable_struct (&rk_dspmode_sv);
+      for (i = 0; i < rk_hyo_sv.size; i++)
+        {
+          free_for_hyo_area (&rk_hyo_sv, i);
+        }
+      free_for_hyo (&rk_hyo_sv);
+      /* free_for_usehyo(&rk_usehyo_sv); */
+      free_for_hensuudef (&rk_hensuudef_sv);
+      /* free_for_henmatch(&rk_henmatch_sv); */
+
+      return (0);
+    }
+
+  /* 異常終了 */
+  /* 88/06/10 V3.1 */
+  /* 不要領域の削除 */
+  free_for_modenaibu (&(rk_t->rk_modenaibu));
+  free_for_modesw (&(rk_t->rk_modesw));
+  free_for_modetable_struct (&(rk_t->rk_dspmode));
+  for (i = 0; i < rk_t->rk_hyo.size; i++)
+    {
+      free_for_hyo_area (&(rk_t->rk_hyo), i);
+    }
+  free_for_hyo (&(rk_t->rk_hyo));
+  /* free_for_usehyo(&(rk_t->rk_usehyo)); */
+  free_for_hensuudef (&(rk_t->rk_hensuudef));
+  /* free_for_henmatch(&(rk_t->rk_henmatch)); */
+
+  /* 復帰 */
+  recov (rk_modenaibu_sv, rk_t->rk_modenaibu);
+  recov (rk_modesw_sv, rk_t->rk_modesw);
+  recov (rk_dspmode_sv, rk_t->rk_dspmode);
+  recov (rk_hyo_sv, rk_t->rk_hyo);
+  /* recov(rk_usehyo_sv,          rk_t->rk_usehyo); */
+  recov (rk_hensuudef_sv, rk_t->rk_hensuudef);
+  /* recov(rk_henmatch_sv,                rk_t->rk_henmatch);
+
+     for(i = 0; i < 2; i++)
+     for(j = 0; j < 2; j++)  rk_t->dspmod[i][j] = dspmod_sv[i][j];
+   */
+  return (1);
+}
+
+ /** lp2から評価して得た文字列をlp1にコピー */
+static                          /* V3.1 */
+  void
+ltrevlcpy (lp1, lp2)
+     letter *lp1, *lp2;
+{
+  while (*lp2 != EOLTTR)
+    {
+      mchevl (&lp2, lp1);
+      totail (lp1);
+    }
+  *lp1 = EOLTTR;
+}
+
+static                          /* V3.1 */
+  void
+set_rubout (lp, n, del)
+ /** lpに 「del」n個の列をセットする。ここに del は 'delchr'か'nisedl' */
+     fast letter *lp, del;      /* V3.1 */
+     fast int n;                /* V3.1 */
+{
+  for (; n; n--)
+    *lp++ = del;
+  *lp = EOLTTR;
+}
+
+ /** これが実行されたらバグ。但し実行はそのまま続く */
+#ifdef OMRON_LIB
+static
+#endif
+  void
+BUGreport (n)
+     int n;
+{
+  fprintf (stderr, "\r\nromkan-Bug%d!!\r\n", n);
+}
+
+ /** 前処理(mae_in→mae_out)又は後処理(ato_in→ato_out)を行う。*/
+static                          /* V3.1 */
+  void
+maeato_henkan (in, outp, m_a_hyo)
+     letter in;                 /* 入力の一文字 */
+     letter *outp;              /* 出力はここに入る */
+     int *m_a_hyo;              /* どの前・後処理表が選択されているかの情報 */
+{
+  fast dat *datptr;             /* V3.1 */
+  fast int i, hyoseq;           /* V3.1 */
+  fast letter *curdat;          /* V3.1 */
+
+  if (isSPCL (in))
+    {
+      /* LTREOFやCHMSIGが来うるので、特殊コードはそのまま返すように
+         細工しておかないといけない。 */
+      ltr_to_ltrseq (outp, in);
+      return;
+    }
+
+  /* 88/06/14 V3.1 */
+  for (hyoseq = 0; m_a_hyo != NULL && (cur_rk->hyonum = m_a_hyo[hyoseq]) != -1; hyoseq++)
+    {
+      for (i = 0, datptr = cur_rk_table->rk_hyo.point[cur_rk->hyonum].data; NULL != (curdat = datptr[i].code[0]); i++)
+        {
+          if (cur_rk->rk_henmatch.size > 0)
+            {
+              cur_rk->rk_henmatch.point[0].ltrmch = EOLTTR;
+            }
+          if (!l_eq (curdat, in))
+            continue;
+
+          ltrevlcpy (outp, datptr[i].code[1]);
+          return;
+        }
+    }
+  ltr_to_ltrseq (outp, in);
+}
+
+ /** 後処理 */
+static                          /* V3.1 */
+  void
+codeout_chg ()
+{
+  fast letter *saishu_outp;     /* V3.1 */
+  letter saishu_out[OUTSIZ];    /* V3.1 */
+
+  *(saishu_outp = saishu_out) = EOLTTR;
+
+  for (; *(cur_rk->codeout) != EOLTTR; cur_rk->codeout++)
+    {
+      maeato_henkan (*(cur_rk->codeout), saishu_outp, cur_rk->rk_usehyo.useatohyo);
+      totail (saishu_outp);
+    }
+
+  cur_rk->codeout = saishu_out;
+}
+
+ /** 一文字プッシュ・バック */
+/* *INDENT-OFF* */
+letter
+romkan_ungetc (l)
+     letter l;
+/* *INDENT-ON* */
+{
+  return (cur_rk->ungetc_buf = l);
+}
+
+ /** romkan_nextに対し一文字プッシュ・バック */
+/* *INDENT-OFF* */
+letter
+romkan_unnext (l)
+     letter l;
+/* *INDENT-ON* */
+{
+  return (cur_rk->unnext_buf = l);
+}
+
+/* 88/06/02 V3.1 */
+/******************************************************************************/
+#ifndef OMRON
+ /**    deleteとして使うキャラクタの設定(偽deleteも)。これを実行後は
+        romkan_clearを実行しておかないと混乱のもとになります。(廃止予定)*/
+void
+romkan_setdel (delchr_, nisedl_)
+     letter delchr_, nisedl_;
+{
+  cur_rk->delchr = delchr_;
+  cur_rk->nisedl = nisedl_;
+}
+#endif
+/******************************************************************************/