Mercurial > freewnn
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 +/******************************************************************************/