Mercurial > freewnn
diff Wnn/romkan/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 | a7ccf412ba02 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Wnn/romkan/rk_main.c Thu Dec 13 04:30:14 2007 +0900 @@ -0,0 +1,1688 @@ +/* + * $Id: rk_main.c,v 1.4 2005/04/10 15:26:38 aonoto 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 + * Copyright FreeWnn Project 1999, 2000 + * + * Maintainer: FreeWnn Project <freewnn@tomo.gr.jp> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/*********************************************************************** + rk_main.c + 88. 6.10 改 正 + + ローマ字かな変換・その他、入力コードを変換するプログラム。 + ASCIIコード使用を、前提としている。 + このファイルは、変換のメインルーチン。 +***********************************************************************/ + +#include "rk_header.h" +#include "rk_extvars.h" +#include "rk_fundecl.h" + +struct matchpair /* 現在マッチされている変数の番号と、マッチした文字の + 組を保持。 */ +{ + int hennum; + letter ltrmch; +}; + +letter memory[SIZALL]; /* 変換対応表や、変数の変域などを入れる領域 */ +struct dat data[LINALL]; /* 対応表の一行ごとのデータへのポインタ */ +letter *hensudefhyo[VARTOT]; /* 変数ごとの変域データへのポインタ */ +struct matchpair henmatch[VARTOT]; /* 変数のマッチ状況をためておく */ + +#ifdef KDSP +# ifdef MVUX +letter displine[DSPLIN]; /* デバッグ用 表示の一行分を記憶 */ +# endif +#endif + +letter *curdis; +int codein_len; +letter *codeout, *remainkbf; +letter ungetc_buf = EOLTTR; /* romkan_ungetcが一文字退避しておくバッファ */ +letter unnext_buf = EOLTTR; /* romkan_unnextが 〃 */ + +letter (*keyin_method) (); /* キーイン関数のアドレス */ +int (*bytcnt_method) (); /* バイトカウント関数のアドレス */ +int (*kbytcnt_method) (); /* キー入力解釈用バイトカウント関数のアドレス */ +char prv_modfnm[REALFN] = "\0"; /* モード表名(又はそのパス名)を保存 */ + /* 初期設定がいい加減! */ + +#define DISOUT ((flags & RK_NONISE) ? rk_output : disout) + /* フラグの値はromkan_init3()の中で設定され、そのRK_NONISEのビットの値の + 標準は0。従ってDISOUTの標準値はdisout。これをrk_outputに変えると、偽コード + (除:LTREOF)を一切出さない(但し、キー入力があれば必ず何かを返すように + してある時に限り、EOLTTRをも返す)。 */ + +char eofflg; /* romkan_next()からLTREOFが来たときに、romkan_henkan()内で1 + にする。これの値が非0なら変換対応表の(error)を無視して、 + 本処理バッファ内の未確定コードも、強制的に変換させる。更に + LTREOFが来た時に特別にある出力を出すように指定されていれば + その処理も行う(但し、その処理は急ごしらえで不完全)。その + 処理中はeofflgは2。 */ + +letter evalbuf[2][2][OUTSIZ]; +char ebf_sw = 0; +letter saishu_out[OUTSIZ]; +letter delchr, delchr2 = EOLTTR, nisedl; /* DELのキャラクタは二個まで持てる */ + +modetyp chgmod (), incmod (), decmod (); + + +/* letterを返す関数の定義及び宣言(一部にはcharのものも混じっている) */ + +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 は濁点を持つ文字を一まとめにしない。 */ + +void BUGreport (); +static void maeato_henkan (), add_at_eof (), rk_delete (), set_rubout (), mchevl (), codeout_chg (), ltrevlcpy (); +int match (); +static int p_eq (), hen_ikisrc (), henkan_ok (), rk_rst (), head_bytecount (); +extern void readdata (), romkan_reset (), hank_setup (), to_hankata (), to_digit (), dakuadd (), handakuadd (), allchgmod (); +extern int ltov (); + +static letter * +ltrcpy (lp1, lp2) + letter *lp1, *lp2; +{ + letter *org; + + org = lp1; + while ((*lp1++ = *lp2++) != EOLTTR); + return (org); +} + +#ifdef notuse +letter * +ltrncpy (lp1, lp2, n) /* 末尾に'EOLTTR'をセット */ + letter *lp1, *lp2; + int n; +{ + letter *org; + + org = lp1; + for (; n; --n) + if (EOLTTR == (*lp1++ = *lp2++)) + return (org); + *lp1 = EOLTTR; + return (org); +} +#endif + + /** letterの列の末尾に一文字つなげる */ +static letter * +ltr1cat (lp, l) + letter *lp, l; +{ + letter *org; + + org = lp; + totail (lp); + *lp++ = l; + *lp = EOLTTR; + return (org); +} + + /** 文字列の末尾に一文字つなげる。ltr1catのchar版 */ +char * +chrcat (s, c) + char *s, c; +{ + char *org; + + org = s; + strtail (s); + *s++ = c; + *s = '\0'; + return (org); +} + +static letter * +ltrcat (lp1, lp2) + letter *lp1, *lp2; +{ + letter *org; + + org = lp1; + totail (lp1); + ltrcpy (lp1, lp2); + return (org); +} + + /** letterの列lp2の各要素の最上位ビットを立ててから、lp1の後ろにつなげる。*/ +static letter * +bitup_ltrcat (lp1, lp2) + letter *lp1, *lp2; +{ + letter *org; + + org = lp1; + totail (lp1); + + while ((*lp1 = *lp2++) != EOLTTR) + *lp1++ |= HG1BIT; + /** lp2 の要素全ての最上位ビットを立てる。*lp2がNISEBP(rk_spclval.h + でdefine)などのときは最初から最上位が立ってるからよい */ + + return (org); +} + + /** ltrcatしたあと、結果の文字列の末尾にポインタをもっていく。*/ +letter * +ltrgrow (lp1, lp2) + letter *lp1, *lp2; +{ + totail (lp1); + while ((*lp1 = *lp2++) != EOLTTR) + lp1++; + return (lp1); +} + +static int +ltrlen (lp) + letter *lp; +{ + letter *org; + + for (org = lp; *lp != EOLTTR; lp++); + return (lp - org); +} + + /** letterの列の最後の文字へのポインタを返す。但し空文字列に対しては + そのまま返す。*/ +letter * +ltrend (lp) + letter *lp; +{ + return ((*lp != EOLTTR) ? (lp + ltrlen (lp) - 1) : lp); +} + + /** 文字列の最後の文字へのポインタを返す。ltrend()のchar版。ltrend()と + 同様、空文字列のときは特例がある。*/ +char * +strend (s) + char *s; +{ + return (*s ? (s + strlen (s) - 1) : s); +} + +int +ltrcmp (lp1, lp2) + letter *lp1, *lp2; +{ + for (; *lp1 == *lp2; lp1++, lp2++) + if (*lp1 == EOLTTR) + return (0); + return (*lp1 > *lp2 ? 1 : -1); +} + +#ifdef notuse +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)); +} + +letter * +ltr_index (lp, l) + letter l, *lp; +{ + for (; *lp != EOLTTR; lp++) + if (*lp == l) + return (lp); + return (NULL); +} +#endif + +static letter * +ltr_rindex (lp, l) + letter l, *lp; +{ + letter *lp2; + + for (lp += ltrlen (lp2 = lp); lp2 != lp;) + if (*--lp == l) + return (lp); + return (NULL); +} + + /** 文字列の末尾一文字をカットする。*/ +letter * +ltr1cut (lp) + letter *lp; +{ + int l; + + if (0 == (l = ltrlen (lp))) + BUGreport (0); /* Illegal POP */ + *(lp + --l) = EOLTTR; + return (lp); +} + + /** letterの一文字を長さ1の文字列に変換する */ +static letter * +ltr_to_ltrseq (lp, l) + letter *lp, l; +{ + *lp++ = l; + *lp-- = EOLTTR; + return (lp); +} + + /** charの列からletterを一つ取り出す。但し'\0'はEOLTTRに変える */ +/* *INDENT-OFF* */ +letter +letterpick (lbfpptr) + uns_chr **lbfpptr; +/* *INDENT-ON* */ +{ + letter l = 0; + register int i; + + for (i = (*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 (unnext_buf != EOLTTR) + return (in = unnext_buf, unnext_buf = EOLTTR, in); + + if ((letter) EOF == (in = (*keyin_method) ())) + return (LTREOF); + c = (in &= 0xff); + n = (*kbytcnt_method) (&c); + for (i = 1; i < n; i++) + in = (in << 8) + ((*keyin_method) () & 0xff); + return (in); +} + + /* letterの文字 l とcharの文字 c の比較。エンドマーク同士(letter列の + エンドマークはEOLTTR、char列のは'\0')も一致とみなす。 */ +#define ltrchreq(l, c) ((l) == ((c) != 0 ? (c) : EOLTTR)) + + /** letterの文字列とcharの文字列の比較 但し大小比較は符号なしとしてやる */ +int +ltrstrcmp (l, s) + register letter *l; + register char *s; +{ + for (; ltrchreq (*l, *s); l++, s++) + if (*s == 0) + return (0); + return ((*l < (uns_chr) * s || *l == EOLTTR) ? -1 : 1); +} + + /** 最後にマッチした文字 つまりurabufの最後。urabufが空だとEOLTTRを返す */ +static letter +lastmch () +{ + return (*(ltrend (urabuf))); +} + +/* end of 'letter' functions */ + + +#ifdef OMAKE + /** お ま け + TVアニメのご案内(一部特撮を含む)。引数が非負整数の時はどれか一つ、 + -1なら全てを出力し、それ以外なら何も出力しない。いずれの場合も、データ + の個数を返す。*/ +takeoka (i) + int i; +{ +#define OPIMAX (numberof(opinion)) + + static char *opinion[] = { + "「魔法のアイドル パステルユーミ」は良い番組だ。by竹岡", + "「機動戦士ガンダムΖΖ」の地球編は良い番組だ。by服部", + "「魔法のスター マジカルエミ」は良い番組だ。by竹岡", + "(参考意見)「マジカルエミ〔蝉時雨〕」は良いアニメだ。by森島", + "「魔法の天使 クリィミーマミ」は良い番組だ。by竹岡", + "「サザエさん」は良い番組だ。by鈴木", + "「ムーミン」は良い番組だ。by鈴木", + "「マンガ大作戦」のロードランナーシリーズは良い番組だ。by新出", + "「スプーンおばさん」は良い番組だ。by鴨", + "「はじめ人間ギャートルズ」は良い番組だ。by富永", + "「宇宙の騎士テッカマン」は良い番組だ。by駒嵐", + "「妖怪人間ベム」は良い番組だ。by鴨", + "「アルプスの少女ハイジ」は良い番組だ。by富永", + "「ときめきトゥナイト」は良い番組だ。by駒嵐", + "「あしたのジョー」は良い番組だったね。by立木(ついき)", + "「きまぐれオレンジ・ロード」は良い番組だ。by三好・服部", + "「ゲッターロボ」(「ゲッターロボG」を含む)は良い番組だ。by新出", + "「テッちゃん」(「じゃりン子チエ」のこと)は良い番組だ。by松田", + "「チキチキマシン猛レース」は良い番組だ。by服部", + "「小公女セーラ」は良い番組だ。by森島", + "「秘密戦隊ゴレンジャー」は良い番組だ。by新出", + "(白黒時代の)「鉄人28号」は良い番組だ。by桜川" + }; + + if (i >= 0) + printf ("%s\n", opinion[i % OPIMAX]); + else if (i == -1) + for (i = 0; i < OPIMAX; i++) + printf ("%s\n", opinion[i]); + return (OPIMAX); +} +#endif /* OMAKE */ + + + /** 変換バッファのクリア */ +void +romkan_clear () +{ +#ifdef KDSP +# ifdef MVUX + *displine = EOLTTR; +# endif +#endif + ungetc_buf = *keybuf = *urabuf = *disout = *rk_output = EOLTTR; + curdis = DISOUT; + lastoutlen = lastkbflen = 0; +} + + /** 表を読み込んで変換の初期設定をする。(part 1)*/ +int +romkan_init (modhyo, delchr_, chmoutf, keyinfn, bytcntfn) + char *modhyo, chmoutf; + letter delchr_; +letter (*keyinfn) (); + int (*bytcntfn) (); /* 引数の詳細はromkan_init3を参照 */ +{ + return (romkan_init2 (modhyo, delchr_, chmoutf, keyinfn, bytcntfn, 0, 0, 0)); +} + +#define ifflg(a, b) ((a) ? (b) : 0) + + /** 表を読み込んで変換の初期設定をする。(part 2: キー入力に対し必ず何か + 返すようにするか、キーバッファをクリアするかどうかなども指定可)*/ +int +romkan_init2 (modhyo, delchr_, chmoutf, keyinfn, bytcntfn, keyackf, restartf, nonisecodf) + char *modhyo, chmoutf, keyackf, restartf, nonisecodf; + letter delchr_; +letter (*keyinfn) (); + int (*bytcntfn) (); /* 引数の詳細はromkan_init3を参照 */ +{ + return (romkan_init3 (modhyo, delchr_, toNISE (delchr_), EOLTTR, + keyinfn, bytcntfn, (int (*)()) NULL, restartf, ifflg (chmoutf, RK_CHMOUT) | ifflg (keyackf, RK_KEYACK) | ifflg (nonisecodf, RK_NONISE) | RK_DSPNIL)); +} + + /** 表を読み込んで変換の初期設定をする。(part 3)*/ +int +romkan_init3 (modhyo, delchr_, nisedl_, delchr2_, keyinfn, bytcntfn, kbytcntfn, restartf, flags_) + char *modhyo; /* モード定義表の名又はそのパス名 */ + letter delchr_; /* DELとして使うコード */ + letter nisedl_; /* 偽DELとして使うコード */ + letter delchr2_; /* DELとして使うコードが二つある場合そのもう一方 */ +letter (*keyinfn) (); /* キーイン関数 */ + int (*bytcntfn) (); /* バイトカウント関数 */ + int (*kbytcntfn) (); /* キーインの解釈用バイトカウント関数。NULL指定の時は + bytcntfnと同じものが使われる */ + char restartf; + /* rk_rst()内から呼ばれた時に立つフラグ。これが立つと、バッファをクリア + せずに済ます。この時はエラー検出時のメッセージも少し異なる */ + int flags_; + /* 以下のフラグが利用可。これらはrk_spclval.hにて定義。 + RK_CHMOUT:モードチェンジを知らせるコードを返すか? + RK_KEYACK:キーインに対し必ず何かを返すか + RK_DSPNIL:romkan_disp(off)modeのデフォルトを空文字列にするか + RK_NONISE:偽コードを出さないようにするか + RK_REDRAW:Wnn用特殊フラグ(redraw用のフラグを出すかどうか) + RK_SIMPLD:deleteの動作を単純にするか + RK_VERBOS:verboseモードで起こすか + */ +{ + int errcod; /* 今の所1のみ */ + + /* 偽コードを出すかの設定はromkan_clearで使うので、フラグの設定を + 先にやっておかないといけない。 */ + if ((flags = flags_) & RK_VERBOS) + { + fprintf (stderr, "romkan_init invoked.\r\n"); + fflush (stderr); + } + +#ifdef OMAKE + if (modhyo == NULL) + takeoka (-1); /* おまけ;通常は実行されない */ +#endif /* OMAKE */ + + keyin_method = keyinfn; + bytcnt_method = (bytcntfn == NULL ? head_bytecount : bytcntfn); + kbytcnt_method = (kbytcntfn == NULL ? bytcnt_method : kbytcntfn); + strcpy (prv_modfnm, modhyo); + + delchr = delchr_; + nisedl = nisedl_; + delchr2 = delchr2_; + /** 実はDELのキャラクタを二個まで持てる。二個目:delchr2は、未設定の + とき(値がEOLTTR)は無視される。それ以外は、delchr2が入力されると + delchrが入力されたのと同じ振る舞いをする。*/ + + if ((errcod = setjmp (env0)) != 0) + { + fprintf (stderr, "romkan_init failed."); + if (!restartf) + { + romkan_reset (); + /* fprintf(stderr, + "No conversion is currently performed."); */ + fprintf (stderr, "\r\n"); + } + else + { + fprintf (stderr, "Conversion method was unchanged.\r\n"); + } + } + else + { + readdata (memory, data, hensudefhyo, modhyo); + if (!restartf) + { + romkan_clear (); + hank_setup (); + } + } + + if (!errcod && (flags & RK_VERBOS)) + { + fprintf (stderr, "romkan_init finished.\r\n"); + fflush (stderr); + } + return (errcod); /* 正常終了なら0 */ +} + + /** バイトカウント関数のデフォルト。sの指している所に入っているのが + 何バイトコードかを返す。 + romkan_nextに注意。そちらでは、バイトカウント関数の値は + 引数の一文字目にのみ依存すると仮定している。*/ +static int +head_bytecount (s) + uns_chr *s; +{ +#ifdef IKIS + return ((*s <= 0xa0 || *s == 0xff) ? 1 : 2); +#else + return (((*s <= 0xa0 && *s != HNKAK1) || *s == 0xff) ? 1 : 2); +#endif +} + + /** 変換された文字を順次返す */ +/* *INDENT-OFF* */ +letter +romkan_getc () +/* *INDENT-ON* */ +{ + letter l; + + /* ungetcされている場合は、それを取り出す。 */ + if (ungetc_buf != EOLTTR) + return (l = ungetc_buf, ungetc_buf = EOLTTR, l); + + while (*curdis == EOLTTR) + { + /* romkan_next()の値がLTREOFの時も、そのまま送れば良い。 */ + curdis = romkan_henkan (romkan_next ()); + + /* keyackflgが非0なら、キーインがあれば必ず何か返す。その + ため、返すべきものがない時はEOLTTRを返すことにする。 */ + if (flags & RK_KEYACK) + break; + } + + if (EOLTTR != (l = *curdis)) + 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(*curdis != EOLTTR){p = curdis; curdis = nil; return(p);} */ + /* ↑これではmae_inが無視される */ + curdis = nil; + + /* 前・後処理への入力は常にただ一文字 */ + mae_out[0] = mae_out[1] = EOLTTR; + + eofflg = rk_errstat = 0; + *rk_output = *disout = EOLTTR; + + maeato_henkan (mae_in, mae_out, usemaehyo); + rk_input = *mae_out; + + if (rk_input == LTREOF) + { + /* LTREOFが来た場合、(error)を無視し、本処理バッファの末尾迄 + 強制変換する。そのためにeofflgを1にする。その後、結果の + 末尾に、LTREOFが来た時の特別コード(指定されていれば)と、 + LTREOFをつなぐ。 */ + eofflg = 1; + match (); + + eofflg = 2; + add_at_eof (); /* codeoutに、LTREOFが来た時出すコードが入る。 */ + ltr1cat (codeout, LTREOF); + + ltrcat (disout, codeout); + ltrcat (rk_output, codeout); + } + else if (rk_input == EOLTTR) + { + /* EOLTTRが来た場合も、上と同様の処理を行うが、LTREOFは + つながない。なお、これはromkan_getc()を呼んでいる時は + 起こらない(romkan_next()がEOLTTRを返さないから)。 */ + eofflg = 1; + match (); + } + else if (rk_input == delchr || rk_input == delchr2) + { + /* delchr2が未設定ならその値はEOLTTRなのでrk_inputと等しくない。 */ + rk_delete (rk_input); + } + else + { + ltr1cat (keybuf, rk_input); + ltr1cat (disout, toNISE (rk_input)); + match (); + } + + if (!(flags & RK_CHMOUT)) + { + /* chmoutflgが0の時は、CHMSIGを出さない。 */ + for (p = DISOUT;; p++) + { + while (*p == CHMSIG) + ltrcpy (p, p + 1); + if (*p == EOLTTR) + break; + } + } + + if ((flags & RK_REDRAW) && NULL != (p = ltr_rindex (disout, nisedl))) + { + for (p++; *p != EOLTTR || (ltr1cat (disout, REDRAW), 0); p++) + if (!isSPCL (*p)) + break; + } + /* wnnのredrawのフラグが立っていて、disoutがnisedl以後特殊コードのみ + で終わっていたら、REDRAWを出して、Wnnに変換行のredrawをさせる。 */ + + return (DISOUT); +} + + + /* デバッグ用関数 */ +#ifdef KDSP +# ifdef MVUX + +void +pridbg2 (a, b, c) + char *a, *c; + letter *b; +{ + printf ("%s", a); + dump_fordbg (b); + printf ("%s", c); +} + +int +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); +} + +void +dump_fordbg (lp) + letter *lp; +{ + while (*lp != EOLTTR) + printf ("%x/", *lp++); +} + +void +print_fordbg (lp) + letter *lp; +{ + while (*lp != EOLTTR) + putletter (*lp++ & ~HG1BIT); +} + +void +print_ltrseq (lp) + letter *lp; +{ + while (*lp != EOLTTR) + print_ltr (*lp++ & ~HG1BIT); +} + +void +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) + { + *displine = *keybuf = *urabuf = EOLTTR; + lastoutlen = lastkbflen = 0; + putchar (l); + } + else if (l == delchr || l == nisedl) + { + if (*displine == EOLTTR) + putchar (BEEPCH); + else + { + disptail = ltrend (displine); + for (i = ltr_displen (*disptail); i; i--) + printf ("\031 \031"); + *disptail = EOLTTR; + } + } + else + { + ltr1cat (displine, l); + putletter (l); + } +} + +# endif /* of #ifdef MVUX */ +#endif +/* デバッグ用関数終わり */ + + + /** DELが入力されたときの処理をする */ +static void +rk_delete (input_del) + letter input_del; +{ + if (ltrlen (keybuf) > ((flags & RK_SIMPLD) ? 0 : lastkbflen)) + { + ltr1cut (keybuf); + set_rubout (disout, 1, nisedl); + } + else + { + if (*urabuf != EOLTTR && !(flags & RK_SIMPLD)) + { + ltr1cut (ltrcpy (keybuf, urabuf)); + *urabuf = EOLTTR; + + set_rubout (rk_output, lastoutlen, input_del); + + set_rubout (disout, lastkbflen, nisedl); + bitup_ltrcat (ltrcat (disout, rk_output), keybuf); + + lastkbflen = lastoutlen = 0; + } + else + { + set_rubout (disout, 1, input_del); + set_rubout (rk_output, 1, input_del); + } + } +} + + /** letterの列 lp1 と lp2 のマッチを試みる。返値は、lp1がlp2の頭部と + 一致の時 -1、lp1またはその頭部とlp2が一致のときは一致長(lp2が + 空文字列の時を含む。この場合返値は0)、それ以外は -2。 + lp2側に式が含まれていたら評価をする。lp1側には式を含んではだめ */ +static int +prefixp (lp1, lp2) + letter *lp1, *lp2; +{ + /* 1行マッチさせるごとに、まずmatch情報をクリアしてから。 + つまり、henmatch[0] . ltrmch = EOLTTR; としておく。 */ + + register int mch_len = 0, d_len; + + 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 letter +mchedsrc (num) + int num; +{ + struct matchpair *pairptr; + + for (pairptr = henmatch; pairptr->ltrmch != EOLTTR; pairptr++) + { + if (num == pairptr->hennum) + return (pairptr->ltrmch); + } + return (BUGreport (8), 0); +} + + /** num番目の変数が文字 l とマッチするか調べる。その変数がunboundだった + 場合は l にbindする。マッチしたら(bindの時を含む)1、しないと0を返す */ +static int +mchsrc (num, l) + int num; + letter l; +{ + struct matchpair *pairptr; + + if (hen_ikisrc (num, l) == 0) + return (0); + for (pairptr = henmatch; 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 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 int +p_eq (l1pp, l2pp) + register letter **l1pp, **l2pp; +{ + int num; + letter evlrsl[RSLMAX], *rslptr; + register int retval = -2; + + /* 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に入れる */ +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++ = LWRMSK (*l1p++); + *l2p++ = 0; + break; /* EOLではない */ + case 5: + *l2p++ = CHMSIG; + *l2p++ = LWRMSK (*l1p++); + *l2p++ = 1; + break; + case 6: + *l2p++ = CHMSIG; + *l2p++ = XY2INT (2, LWRMSK (*l1p++)); + *l2p++ = 1; + 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 (!modesw[LWRMSK (*l1p++)].curmode) + *l2p++ = UNUSDC; + break; + case 21: + if (modesw[LWRMSK (*l1p++)].curmode) + *l2p++ = UNUSDC; + break; + case 22: + *l2p++ = REASIG; + break; + case 23: + *l2p++ = delchr; + break; + case 24: + *l2p++ = CHMSIG; + *l2p++ = XY2INT (1, 0); + /* これで「all」を表す */ + *l2p++ = 0; + break; + case 25: + *l2p++ = CHMSIG; + *l2p++ = XY2INT (1, 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 (eofflg != 2 || *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++; + 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 (modesw[modnum].curmode != *l1p++) + *l2p++ = UNUSDC; + break; + } + case 41: + { + letter modnum; + + modnum = LWRMSK (*l1p++); + if (modesw[modnum].curmode == *l1p++) + *l2p++ = UNUSDC; + break; + } + case 42: + { + letter modnum; + + modnum = LWRMSK (*l1p++); + if (modesw[modnum].curmode >= *l1p++) + *l2p++ = UNUSDC; + break; + } + case 43: + { + letter modnum; + + modnum = LWRMSK (*l1p++); + if (modesw[modnum].curmode <= *l1p++) + *l2p++ = UNUSDC; + break; + } + case 44: + mchevl (&l1p, tmpevl); + *l2p++ = SENDCH; + *l2p++ = *tmpevl; + break; + default: /* case 0及び上記以外 */ ; + BUGreport (7); + } + } + + *l2p = EOLTTR; + *l1pp = l1p; +} + + /** num番目の変数の変域が文字 l を含むかどうかを返す */ +static int +hen_ikisrc (num, l) + int num; + letter l; +{ + letter *defptr; + + defptr = hyo_n[hyonum].hensudef[num]; + 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を返す */ +int +match () +{ + int henkanflg = 0, okcode = 0, chm_exist; + letter *p; + letter urabufcreate[KBFSIZ], orgkeybuf[KBFSIZ], kbftail[KBFSIZ]; + letter *urabufjunbi, *outcutptr, *dis_end; + + if (*keybuf == EOLTTR) + { + *urabuf = EOLTTR; + return (1); + } + + ltrcpy (urabufjunbi = orgkeybuf, keybuf); + outcutptr = rk_output; + + while ((okcode = henkan_ok ()) > 0) + { + henkanflg = 1; + + codeout_chg (); + ltrcat (rk_output, codeout); + + ltrcpy (kbftail, keybuf + codein_len); + ltrcat (ltrcpy (keybuf, remainkbf), kbftail); + + if (okcode == 2) + { + ltrcpy (urabufjunbi = urabufcreate, keybuf); + totail (outcutptr); + } + } + + if (okcode == 0) + { + ltr1cut (ltrcpy (keybuf, orgkeybuf)); + ltr_to_ltrseq (disout, NISEBP); + *rk_output = EOLTTR; + return (0); + } + if (henkanflg) + { + ltrcpy (urabuf, urabufjunbi); + + set_rubout (disout, ltrlen (orgkeybuf) - 1, nisedl); + + dis_end = disout; + totail (dis_end); + ltrcpy (dis_end, rk_output); + + /* モードチェンジを直ちに知らせるため CHMSIGを出力 + (flags中のRK_CHMOUTが立ってないと、あとで一文字ずつに + 分解する時点で、CHMSIGをカット)。 + 但し、rk_outputからは、CHMSIGを抜く。 + また、CHMSIGは末尾に1回しか出力しない + (2回以上あっても、1回にまとめて、末尾に置く)。 */ + for (chm_exist = 0, p = rk_output;; p++) + { + while (*p == CHMSIG) + { + chm_exist = 1; + if (ltrcpy (p, p + 1) < outcutptr) + outcutptr--; + } + if (*p == EOLTTR) + break; + } + if (chm_exist) + { + /* CHMSIGを1つにまとめたものをdis_endにつなげ直す。 + このif文をカットすれば、CHMSIGのとりまとめはやらない */ + ltr1cat (ltrcpy (dis_end, rk_output), CHMSIG); + } + + bitup_ltrcat (disout, keybuf); + lastoutlen = ltrlen (outcutptr); + lastkbflen = ltrlen (keybuf); + } + return (1); +} + + /** LTREOFが入ったときに、何か出すように指定されているか調べて、 + codeoutをその結果の文字列(指定がなかったら当然空)にポイントする。 + 超急ごしらえで、特殊コード等は一切無視する。*/ +static void +add_at_eof () +{ + register struct dat *datptr; + register int i; + int hyoseq; + letter evlrsl[RSLMAX], *p; + + for (hyoseq = 0; (hyonum = usehyo[hyoseq]) != -1; hyoseq++) + { + for (i = 0, datptr = hyo_n[hyonum].data; NULL != (p = datptr[i].code[0]); i++) + { + henmatch[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 (codeout = p = evalbuf[0][0], datptr[i].code[1]); + while (*p != EOLTTR) + { + if (isSPCL (*p)) + ltrcpy (p, p + 1); + else + p++; + } + codeout_chg (); + return; + + Pass:; + } + } + codeout = nil; +} + + /** 一回マッチを試みる。返値は、マッチして確定した場合1(モードチェンジが + 混じっている場合は2)、マッチしたが未確定の時-1、マッチしなかったら0。 + 実行中は、変数 l に、それまでに一致した長さの最高記録を入れており、 + より長く一致するものが見つかるごとに、これを更新する。lの値は、マッチ + していても0になることもある。p_eq() 及び prefixp() の注釈文を参照。*/ +static int +henkan_ok () +{ + register struct dat *datptr; + register int i, k; + int l, j, hyoseq; + char urabuf_clrf; /* モードチェンジなどで、urabufをクリアする必要が + 生じた場合はこれが立ち、その結果、henkan_ok() + が1を返すべきところで2を返す。それを見て、 + match()がurabufなどの調整をする。 */ + register letter *p; + + if (*keybuf == EOLTTR) + return (-1); + + for (l = -1, hyoseq = 0; (hyonum = usehyo[hyoseq]) != -1; hyoseq++) + { + for (i = 0, datptr = hyo_n[hyonum].data; NULL != (p = datptr[i].code[0]); i++) + { + henmatch[0].ltrmch = EOLTTR; + switch (k = prefixp (keybuf, p)) + { + case -2: + break; + case -1: + if (eofflg != 0) + break; + /* eofflgが立っていたら、未確定の可能性は + 捨てる。 */ + + return (-1); + default: + if (k > l) + { + ebf_sw = !ebf_sw; + for (j = 1; j <= 2; j++) + { + ltrevlcpy (evalbuf[ebf_sw][j - 1], datptr[i].code[j]); + } + + l = k; + } + } + } + } + + if (l >= 0) + { + codein_len = l; + codeout = evalbuf[ebf_sw][0]; + remainkbf = evalbuf[ebf_sw][1]; + + for (urabuf_clrf = 0, p = codeout; *p != EOLTTR;) + { + switch (*p) + { + case CHMSIG: + p++; + /* codeoutの1バイト目に関数のスイッチとモード番号、 + 2バイト目にモードの新状態が入ってる */ + switch (SHUBET (*p)) + { + case 0: + chgmod ((int) *p, (modetyp) * (p + 1)); + break; + case 1: + allchgmod ((modetyp) * (p + 1)); + break; + case 2: + incmod ((int) LWRMSK (*p), (modetyp) * (p + 1)); + break; + case 3: + decmod ((int) LWRMSK (*p), (modetyp) * (p + 1)); + break; + } + ltrcpy (p, p + 2); + /* CHMSIGだけ残して1,2バイト目cut */ + + urabuf_clrf = 1; + break; + case URBFCL: + /* urabufのクリアを明示的に指定する */ + urabuf_clrf = 1; + ltrcpy (p, p + 1); + break; + default: + p++; + } + } + + if (*codeout == ERRCOD) + { + if (eofflg == 0) + { + rk_errstat = 1; + return (0); + } + + /* (error)であって、しかもeofflgが立ってたら、keybuf + の末尾まで、そのまま出す。 */ + codein_len = ltrlen (keybuf); + codeout = ltrcpy (evalbuf[ebf_sw][0], keybuf); + remainkbf = nil; + rk_errstat = 2; + + return (1); + } + /* (error)は単独でしか書けないので、エラー検出はこれで十分。 */ + + if (*codeout == REASIG) + { + *codeout = (rk_rst () != 0 ? EOLTTR : CHMSIG); + /* 再readでエラったらモードチェンジの通知はしない */ + + urabuf_clrf = 1; + } + /* 表の再read。但し、これが起こったことを外に知らせるのはCHMSIGで + このコードそのものは外へ出ない。(restart)は、(error)同様、 + 単独でしか書けないので、検出はこれで十分。 */ + + return (urabuf_clrf ? 2 : 1); + } + + /* 表に現れていないコードはそのまま返す */ + + codein_len = 1; + *(codeout = oneletter) = *keybuf; + remainkbf = nil; + return (1); +} + + /* rk_rst内で使うマクロ */ +#define taihi(X, Y, N) {for(i = 0; i < N; i++) X[i] = Y[i];} +#define recov(X, Y, N) taihi(Y, X, N) + + /** 表の動的再読み込みをする。現在の内部表現を全て退避し、前と同じ + ディレクトリ(に、現在のところ限定)から表を読み込む。もし、 + 読み込み中にエラーを検出すれば、もとの内部データを復活し非0を返す。*/ +static int +rk_rst () +{ + register int i; + int j; + + letter memoryt[SIZALL]; + struct dat datat[LINALL]; + struct hyo hyo_nt[HYOMAX]; + letter *hensudefhyot[VARTOT]; + struct modestat modeswt[MODMAX]; + char hyoshut[HYOMAX]; + char *modmeibgnt[MODMAX], modmeimem_t[MODMEI]; + char *dspnambgnt[DMDMAX], dspcod_t[DMDCHR]; + int usemaehyot[HYOMAX], usehyot[HYOMAX], useatohyot[HYOMAX]; + int naibu_t[NAIBMX]; + char *dspmodt[2][2]; + + taihi (memoryt, memory, SIZALL); + taihi (datat, data, LINALL); + taihi (hyo_nt, hyo_n, HYOMAX); + taihi (hensudefhyot, hensudefhyo, VARTOT); + taihi (modeswt, modesw, MODMAX); + taihi (hyoshut, hyoshu, HYOMAX); + taihi (modmeibgnt, modmeibgn, MODMAX); + taihi (modmeimem_t, modmeimem_, MODMEI); + taihi (dspnambgnt, dspnambgn, DMDMAX); + taihi (dspcod_t, dspcod_, DMDCHR); + taihi (usemaehyot, usemaehyo, HYOMAX); + taihi (usehyot, usehyo, HYOMAX); + taihi (useatohyot, useatohyo, HYOMAX); + taihi (naibu_t, naibu_, NAIBMX); + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + dspmodt[i][j] = dspmod[i][j]; + + if (0 == romkan_init3 (prv_modfnm, delchr, nisedl, delchr2, keyin_method, bytcnt_method, kbytcnt_method, 1, flags & ~RK_VERBOS)) + return (0); /* 正常終了 */ + + recov (memoryt, memory, SIZALL); + recov (datat, data, LINALL); + recov (hyo_nt, hyo_n, HYOMAX); + recov (hensudefhyot, hensudefhyo, VARTOT); + recov (modeswt, modesw, MODMAX); + recov (hyoshut, hyoshu, HYOMAX); + recov (modmeibgnt, modmeibgn, MODMAX); + recov (modmeimem_t, modmeimem_, MODMEI); + recov (dspnambgnt, dspnambgn, DMDMAX); + recov (dspcod_t, dspcod_, DMDCHR); + recov (usemaehyot, usemaehyo, HYOMAX); + recov (usehyot, usehyo, HYOMAX); + recov (useatohyot, useatohyo, HYOMAX); + recov (naibu_t, naibu_, NAIBMX); + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + dspmod[i][j] = dspmodt[i][j]; + return (1); +} + + /** lp2から評価して得た文字列をlp1にコピー */ +static void +ltrevlcpy (lp1, lp2) + letter *lp1, *lp2; +{ + while (*lp2 != EOLTTR) + { + mchevl (&lp2, lp1); + totail (lp1); + } + *lp1 = EOLTTR; +} + +static void +set_rubout (lp, n, del) + /** lpに 「del」n個の列をセットする。ここに del は 'delchr'か'nisedl' */ + letter *lp, del; + int n; +{ + for (; n; n--) + *lp++ = del; + *lp = EOLTTR; +} + + /** これが実行されたらバグ。但し実行はそのまま続く */ +void +BUGreport (n) + int n; +{ + fprintf (stderr, "\r\nromkan-Bug%d!!\r\n", n); +} + + /** 前処理(mae_in→mae_out)又は後処理(ato_in→ato_out)を行う。*/ +static void +maeato_henkan (in, outp, m_a_hyo) + letter in; /* 入力の一文字 */ + letter *outp; /* 出力はここに入る */ + int *m_a_hyo; /* どの前・後処理表が選択されているかの情報 */ +{ + struct dat *datptr; + int i, hyoseq; + letter *curdat; + + if (isSPCL (in)) + { + /* LTREOFやCHMSIGが来うるので、特殊コードはそのまま返すように + 細工しておかないといけない。 */ + ltr_to_ltrseq (outp, in); + return; + } + + for (hyoseq = 0; (hyonum = m_a_hyo[hyoseq]) != -1; hyoseq++) + { + for (i = 0, datptr = hyo_n[hyonum].data; NULL != (curdat = datptr[i].code[0]); i++) + { + henmatch[0].ltrmch = EOLTTR; + if (!l_eq (curdat, in)) + continue; + + ltrevlcpy (outp, datptr[i].code[1]); + return; + } + } + ltr_to_ltrseq (outp, in); +} + + /** 後処理 */ +static void +codeout_chg () +{ + letter *saishu_outp; + + *(saishu_outp = saishu_out) = EOLTTR; + + for (; *codeout != EOLTTR; codeout++) + { + maeato_henkan (*codeout, saishu_outp, useatohyo); + totail (saishu_outp); + } + + codeout = saishu_out; +} + + /** 一文字プッシュ・バック */ +/* *INDENT-OFF* */ +letter +romkan_ungetc (l) + letter l; +/* *INDENT-ON* */ +{ + return (ungetc_buf = l); +} + + /** romkan_nextに対し一文字プッシュ・バック */ +/* *INDENT-OFF* */ +letter +romkan_unnext (l) + letter l; +/* *INDENT-ON* */ +{ + return (unnext_buf = l); +} + + /** deleteとして使うキャラクタの設定(偽deleteも)。これを実行後は + romkan_clearを実行しておかないと混乱のもとになります。*/ +/* (廃止) +void +romkan_setdel(delchr_, nisedl_) +letter delchr_, nisedl_; +{ + delchr = delchr_; + nisedl = nisedl_; +} +*/