Mercurial > freewnn
view Xwnmo/romkan_m/rk_main.c @ 8:76281fa7934f
fix version string.
author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
---|---|
date | Fri, 21 Dec 2007 16:41:48 +0900 |
parents | bbc77ca4def5 |
children |
line wrap: on
line source
/* * $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 /******************************************************************************/