Mercurial > freewnn
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:bbc77ca4def5 |
---|---|
1 /* | |
2 * $Id: rk_main.c,v 1.4 2005/04/10 15:26:38 aonoto Exp $ | |
3 */ | |
4 | |
5 /* | |
6 * FreeWnn is a network-extensible Kana-to-Kanji conversion system. | |
7 * This file is part of FreeWnn. | |
8 * | |
9 * Copyright Kyoto University Research Institute for Mathematical Sciences | |
10 * 1987, 1988, 1989, 1990, 1991, 1992 | |
11 * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999 | |
12 * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992 | |
13 * Copyright FreeWnn Project 1999, 2000 | |
14 * | |
15 * Maintainer: FreeWnn Project <freewnn@tomo.gr.jp> | |
16 * | |
17 * This library is free software; you can redistribute it and/or | |
18 * modify it under the terms of the GNU Lesser General Public | |
19 * License as published by the Free Software Foundation; either | |
20 * version 2 of the License, or (at your option) any later version. | |
21 * | |
22 * This library is distributed in the hope that it will be useful, | |
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
25 * Lesser General Public License for more details. | |
26 * | |
27 * You should have received a copy of the GNU Lesser General Public | |
28 * License along with this library; if not, write to the | |
29 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
30 * Boston, MA 02111-1307, USA. | |
31 */ | |
32 | |
33 /*********************************************************************** | |
34 rk_main.c | |
35 88. 6.10 改 正 | |
36 | |
37 ローマ字かな変換・その他、入力コードを変換するプログラム。 | |
38 ASCIIコード使用を、前提としている。 | |
39 このファイルは、変換のメインルーチン。 | |
40 ***********************************************************************/ | |
41 | |
42 #include "rk_header.h" | |
43 #include "rk_extvars.h" | |
44 #include "rk_fundecl.h" | |
45 | |
46 struct matchpair /* 現在マッチされている変数の番号と、マッチした文字の | |
47 組を保持。 */ | |
48 { | |
49 int hennum; | |
50 letter ltrmch; | |
51 }; | |
52 | |
53 letter memory[SIZALL]; /* 変換対応表や、変数の変域などを入れる領域 */ | |
54 struct dat data[LINALL]; /* 対応表の一行ごとのデータへのポインタ */ | |
55 letter *hensudefhyo[VARTOT]; /* 変数ごとの変域データへのポインタ */ | |
56 struct matchpair henmatch[VARTOT]; /* 変数のマッチ状況をためておく */ | |
57 | |
58 #ifdef KDSP | |
59 # ifdef MVUX | |
60 letter displine[DSPLIN]; /* デバッグ用 表示の一行分を記憶 */ | |
61 # endif | |
62 #endif | |
63 | |
64 letter *curdis; | |
65 int codein_len; | |
66 letter *codeout, *remainkbf; | |
67 letter ungetc_buf = EOLTTR; /* romkan_ungetcが一文字退避しておくバッファ */ | |
68 letter unnext_buf = EOLTTR; /* romkan_unnextが 〃 */ | |
69 | |
70 letter (*keyin_method) (); /* キーイン関数のアドレス */ | |
71 int (*bytcnt_method) (); /* バイトカウント関数のアドレス */ | |
72 int (*kbytcnt_method) (); /* キー入力解釈用バイトカウント関数のアドレス */ | |
73 char prv_modfnm[REALFN] = "\0"; /* モード表名(又はそのパス名)を保存 */ | |
74 /* 初期設定がいい加減! */ | |
75 | |
76 #define DISOUT ((flags & RK_NONISE) ? rk_output : disout) | |
77 /* フラグの値はromkan_init3()の中で設定され、そのRK_NONISEのビットの値の | |
78 標準は0。従ってDISOUTの標準値はdisout。これをrk_outputに変えると、偽コード | |
79 (除:LTREOF)を一切出さない(但し、キー入力があれば必ず何かを返すように | |
80 してある時に限り、EOLTTRをも返す)。 */ | |
81 | |
82 char eofflg; /* romkan_next()からLTREOFが来たときに、romkan_henkan()内で1 | |
83 にする。これの値が非0なら変換対応表の(error)を無視して、 | |
84 本処理バッファ内の未確定コードも、強制的に変換させる。更に | |
85 LTREOFが来た時に特別にある出力を出すように指定されていれば | |
86 その処理も行う(但し、その処理は急ごしらえで不完全)。その | |
87 処理中はeofflgは2。 */ | |
88 | |
89 letter evalbuf[2][2][OUTSIZ]; | |
90 char ebf_sw = 0; | |
91 letter saishu_out[OUTSIZ]; | |
92 letter delchr, delchr2 = EOLTTR, nisedl; /* DELのキャラクタは二個まで持てる */ | |
93 | |
94 modetyp chgmod (), incmod (), decmod (); | |
95 | |
96 | |
97 /* letterを返す関数の定義及び宣言(一部にはcharのものも混じっている) */ | |
98 | |
99 static letter mchedsrc (); | |
100 letter romkan_next (), romkan_unnext (); | |
101 letter romkan_getc (), romkan_ungetc (), *romkan_henkan (); | |
102 letter to_zenalpha (), to_zenhira (), to_zenkata (); | |
103 /* to_zenhira;kata は濁点を持つ文字を一まとめにしない。 */ | |
104 | |
105 void BUGreport (); | |
106 static void maeato_henkan (), add_at_eof (), rk_delete (), set_rubout (), mchevl (), codeout_chg (), ltrevlcpy (); | |
107 int match (); | |
108 static int p_eq (), hen_ikisrc (), henkan_ok (), rk_rst (), head_bytecount (); | |
109 extern void readdata (), romkan_reset (), hank_setup (), to_hankata (), to_digit (), dakuadd (), handakuadd (), allchgmod (); | |
110 extern int ltov (); | |
111 | |
112 static letter * | |
113 ltrcpy (lp1, lp2) | |
114 letter *lp1, *lp2; | |
115 { | |
116 letter *org; | |
117 | |
118 org = lp1; | |
119 while ((*lp1++ = *lp2++) != EOLTTR); | |
120 return (org); | |
121 } | |
122 | |
123 #ifdef notuse | |
124 letter * | |
125 ltrncpy (lp1, lp2, n) /* 末尾に'EOLTTR'をセット */ | |
126 letter *lp1, *lp2; | |
127 int n; | |
128 { | |
129 letter *org; | |
130 | |
131 org = lp1; | |
132 for (; n; --n) | |
133 if (EOLTTR == (*lp1++ = *lp2++)) | |
134 return (org); | |
135 *lp1 = EOLTTR; | |
136 return (org); | |
137 } | |
138 #endif | |
139 | |
140 /** letterの列の末尾に一文字つなげる */ | |
141 static letter * | |
142 ltr1cat (lp, l) | |
143 letter *lp, l; | |
144 { | |
145 letter *org; | |
146 | |
147 org = lp; | |
148 totail (lp); | |
149 *lp++ = l; | |
150 *lp = EOLTTR; | |
151 return (org); | |
152 } | |
153 | |
154 /** 文字列の末尾に一文字つなげる。ltr1catのchar版 */ | |
155 char * | |
156 chrcat (s, c) | |
157 char *s, c; | |
158 { | |
159 char *org; | |
160 | |
161 org = s; | |
162 strtail (s); | |
163 *s++ = c; | |
164 *s = '\0'; | |
165 return (org); | |
166 } | |
167 | |
168 static letter * | |
169 ltrcat (lp1, lp2) | |
170 letter *lp1, *lp2; | |
171 { | |
172 letter *org; | |
173 | |
174 org = lp1; | |
175 totail (lp1); | |
176 ltrcpy (lp1, lp2); | |
177 return (org); | |
178 } | |
179 | |
180 /** letterの列lp2の各要素の最上位ビットを立ててから、lp1の後ろにつなげる。*/ | |
181 static letter * | |
182 bitup_ltrcat (lp1, lp2) | |
183 letter *lp1, *lp2; | |
184 { | |
185 letter *org; | |
186 | |
187 org = lp1; | |
188 totail (lp1); | |
189 | |
190 while ((*lp1 = *lp2++) != EOLTTR) | |
191 *lp1++ |= HG1BIT; | |
192 /** lp2 の要素全ての最上位ビットを立てる。*lp2がNISEBP(rk_spclval.h | |
193 でdefine)などのときは最初から最上位が立ってるからよい */ | |
194 | |
195 return (org); | |
196 } | |
197 | |
198 /** ltrcatしたあと、結果の文字列の末尾にポインタをもっていく。*/ | |
199 letter * | |
200 ltrgrow (lp1, lp2) | |
201 letter *lp1, *lp2; | |
202 { | |
203 totail (lp1); | |
204 while ((*lp1 = *lp2++) != EOLTTR) | |
205 lp1++; | |
206 return (lp1); | |
207 } | |
208 | |
209 static int | |
210 ltrlen (lp) | |
211 letter *lp; | |
212 { | |
213 letter *org; | |
214 | |
215 for (org = lp; *lp != EOLTTR; lp++); | |
216 return (lp - org); | |
217 } | |
218 | |
219 /** letterの列の最後の文字へのポインタを返す。但し空文字列に対しては | |
220 そのまま返す。*/ | |
221 letter * | |
222 ltrend (lp) | |
223 letter *lp; | |
224 { | |
225 return ((*lp != EOLTTR) ? (lp + ltrlen (lp) - 1) : lp); | |
226 } | |
227 | |
228 /** 文字列の最後の文字へのポインタを返す。ltrend()のchar版。ltrend()と | |
229 同様、空文字列のときは特例がある。*/ | |
230 char * | |
231 strend (s) | |
232 char *s; | |
233 { | |
234 return (*s ? (s + strlen (s) - 1) : s); | |
235 } | |
236 | |
237 int | |
238 ltrcmp (lp1, lp2) | |
239 letter *lp1, *lp2; | |
240 { | |
241 for (; *lp1 == *lp2; lp1++, lp2++) | |
242 if (*lp1 == EOLTTR) | |
243 return (0); | |
244 return (*lp1 > *lp2 ? 1 : -1); | |
245 } | |
246 | |
247 #ifdef notuse | |
248 int | |
249 ltrncmp (lp1, lp2, n) | |
250 letter *lp1, *lp2; | |
251 int n; | |
252 { | |
253 for (; n && *lp1 == *lp2; n--, lp1++, lp2++) | |
254 if (*lp1 == EOLTTR) | |
255 return (0); | |
256 return (n == 0 ? 0 : (*lp1 > *lp2 ? 1 : -1)); | |
257 } | |
258 | |
259 letter * | |
260 ltr_index (lp, l) | |
261 letter l, *lp; | |
262 { | |
263 for (; *lp != EOLTTR; lp++) | |
264 if (*lp == l) | |
265 return (lp); | |
266 return (NULL); | |
267 } | |
268 #endif | |
269 | |
270 static letter * | |
271 ltr_rindex (lp, l) | |
272 letter l, *lp; | |
273 { | |
274 letter *lp2; | |
275 | |
276 for (lp += ltrlen (lp2 = lp); lp2 != lp;) | |
277 if (*--lp == l) | |
278 return (lp); | |
279 return (NULL); | |
280 } | |
281 | |
282 /** 文字列の末尾一文字をカットする。*/ | |
283 letter * | |
284 ltr1cut (lp) | |
285 letter *lp; | |
286 { | |
287 int l; | |
288 | |
289 if (0 == (l = ltrlen (lp))) | |
290 BUGreport (0); /* Illegal POP */ | |
291 *(lp + --l) = EOLTTR; | |
292 return (lp); | |
293 } | |
294 | |
295 /** letterの一文字を長さ1の文字列に変換する */ | |
296 static letter * | |
297 ltr_to_ltrseq (lp, l) | |
298 letter *lp, l; | |
299 { | |
300 *lp++ = l; | |
301 *lp-- = EOLTTR; | |
302 return (lp); | |
303 } | |
304 | |
305 /** charの列からletterを一つ取り出す。但し'\0'はEOLTTRに変える */ | |
306 /* *INDENT-OFF* */ | |
307 letter | |
308 letterpick (lbfpptr) | |
309 uns_chr **lbfpptr; | |
310 /* *INDENT-ON* */ | |
311 { | |
312 letter l = 0; | |
313 register int i; | |
314 | |
315 for (i = (*bytcnt_method) (*lbfpptr); i; i--) | |
316 l = (l << 8) + *(*lbfpptr)++; | |
317 return (l == 0 ? EOLTTR : l); | |
318 } | |
319 | |
320 /** 入力されたコードを文字単位にまとめる。但しEOFはLTREOF(rk_spclval.h | |
321 にて定義)に変える。*/ | |
322 /* *INDENT-OFF* */ | |
323 letter | |
324 romkan_next () | |
325 /* *INDENT-ON* */ | |
326 { | |
327 letter in; | |
328 int i, n; | |
329 uns_chr c; | |
330 | |
331 /* unnextされている場合は、それを取り出す。 */ | |
332 if (unnext_buf != EOLTTR) | |
333 return (in = unnext_buf, unnext_buf = EOLTTR, in); | |
334 | |
335 if ((letter) EOF == (in = (*keyin_method) ())) | |
336 return (LTREOF); | |
337 c = (in &= 0xff); | |
338 n = (*kbytcnt_method) (&c); | |
339 for (i = 1; i < n; i++) | |
340 in = (in << 8) + ((*keyin_method) () & 0xff); | |
341 return (in); | |
342 } | |
343 | |
344 /* letterの文字 l とcharの文字 c の比較。エンドマーク同士(letter列の | |
345 エンドマークはEOLTTR、char列のは'\0')も一致とみなす。 */ | |
346 #define ltrchreq(l, c) ((l) == ((c) != 0 ? (c) : EOLTTR)) | |
347 | |
348 /** letterの文字列とcharの文字列の比較 但し大小比較は符号なしとしてやる */ | |
349 int | |
350 ltrstrcmp (l, s) | |
351 register letter *l; | |
352 register char *s; | |
353 { | |
354 for (; ltrchreq (*l, *s); l++, s++) | |
355 if (*s == 0) | |
356 return (0); | |
357 return ((*l < (uns_chr) * s || *l == EOLTTR) ? -1 : 1); | |
358 } | |
359 | |
360 /** 最後にマッチした文字 つまりurabufの最後。urabufが空だとEOLTTRを返す */ | |
361 static letter | |
362 lastmch () | |
363 { | |
364 return (*(ltrend (urabuf))); | |
365 } | |
366 | |
367 /* end of 'letter' functions */ | |
368 | |
369 | |
370 #ifdef OMAKE | |
371 /** お ま け | |
372 TVアニメのご案内(一部特撮を含む)。引数が非負整数の時はどれか一つ、 | |
373 -1なら全てを出力し、それ以外なら何も出力しない。いずれの場合も、データ | |
374 の個数を返す。*/ | |
375 takeoka (i) | |
376 int i; | |
377 { | |
378 #define OPIMAX (numberof(opinion)) | |
379 | |
380 static char *opinion[] = { | |
381 "「魔法のアイドル パステルユーミ」は良い番組だ。by竹岡", | |
382 "「機動戦士ガンダムΖΖ」の地球編は良い番組だ。by服部", | |
383 "「魔法のスター マジカルエミ」は良い番組だ。by竹岡", | |
384 "(参考意見)「マジカルエミ〔蝉時雨〕」は良いアニメだ。by森島", | |
385 "「魔法の天使 クリィミーマミ」は良い番組だ。by竹岡", | |
386 "「サザエさん」は良い番組だ。by鈴木", | |
387 "「ムーミン」は良い番組だ。by鈴木", | |
388 "「マンガ大作戦」のロードランナーシリーズは良い番組だ。by新出", | |
389 "「スプーンおばさん」は良い番組だ。by鴨", | |
390 "「はじめ人間ギャートルズ」は良い番組だ。by富永", | |
391 "「宇宙の騎士テッカマン」は良い番組だ。by駒嵐", | |
392 "「妖怪人間ベム」は良い番組だ。by鴨", | |
393 "「アルプスの少女ハイジ」は良い番組だ。by富永", | |
394 "「ときめきトゥナイト」は良い番組だ。by駒嵐", | |
395 "「あしたのジョー」は良い番組だったね。by立木(ついき)", | |
396 "「きまぐれオレンジ・ロード」は良い番組だ。by三好・服部", | |
397 "「ゲッターロボ」(「ゲッターロボG」を含む)は良い番組だ。by新出", | |
398 "「テッちゃん」(「じゃりン子チエ」のこと)は良い番組だ。by松田", | |
399 "「チキチキマシン猛レース」は良い番組だ。by服部", | |
400 "「小公女セーラ」は良い番組だ。by森島", | |
401 "「秘密戦隊ゴレンジャー」は良い番組だ。by新出", | |
402 "(白黒時代の)「鉄人28号」は良い番組だ。by桜川" | |
403 }; | |
404 | |
405 if (i >= 0) | |
406 printf ("%s\n", opinion[i % OPIMAX]); | |
407 else if (i == -1) | |
408 for (i = 0; i < OPIMAX; i++) | |
409 printf ("%s\n", opinion[i]); | |
410 return (OPIMAX); | |
411 } | |
412 #endif /* OMAKE */ | |
413 | |
414 | |
415 /** 変換バッファのクリア */ | |
416 void | |
417 romkan_clear () | |
418 { | |
419 #ifdef KDSP | |
420 # ifdef MVUX | |
421 *displine = EOLTTR; | |
422 # endif | |
423 #endif | |
424 ungetc_buf = *keybuf = *urabuf = *disout = *rk_output = EOLTTR; | |
425 curdis = DISOUT; | |
426 lastoutlen = lastkbflen = 0; | |
427 } | |
428 | |
429 /** 表を読み込んで変換の初期設定をする。(part 1)*/ | |
430 int | |
431 romkan_init (modhyo, delchr_, chmoutf, keyinfn, bytcntfn) | |
432 char *modhyo, chmoutf; | |
433 letter delchr_; | |
434 letter (*keyinfn) (); | |
435 int (*bytcntfn) (); /* 引数の詳細はromkan_init3を参照 */ | |
436 { | |
437 return (romkan_init2 (modhyo, delchr_, chmoutf, keyinfn, bytcntfn, 0, 0, 0)); | |
438 } | |
439 | |
440 #define ifflg(a, b) ((a) ? (b) : 0) | |
441 | |
442 /** 表を読み込んで変換の初期設定をする。(part 2: キー入力に対し必ず何か | |
443 返すようにするか、キーバッファをクリアするかどうかなども指定可)*/ | |
444 int | |
445 romkan_init2 (modhyo, delchr_, chmoutf, keyinfn, bytcntfn, keyackf, restartf, nonisecodf) | |
446 char *modhyo, chmoutf, keyackf, restartf, nonisecodf; | |
447 letter delchr_; | |
448 letter (*keyinfn) (); | |
449 int (*bytcntfn) (); /* 引数の詳細はromkan_init3を参照 */ | |
450 { | |
451 return (romkan_init3 (modhyo, delchr_, toNISE (delchr_), EOLTTR, | |
452 keyinfn, bytcntfn, (int (*)()) NULL, restartf, ifflg (chmoutf, RK_CHMOUT) | ifflg (keyackf, RK_KEYACK) | ifflg (nonisecodf, RK_NONISE) | RK_DSPNIL)); | |
453 } | |
454 | |
455 /** 表を読み込んで変換の初期設定をする。(part 3)*/ | |
456 int | |
457 romkan_init3 (modhyo, delchr_, nisedl_, delchr2_, keyinfn, bytcntfn, kbytcntfn, restartf, flags_) | |
458 char *modhyo; /* モード定義表の名又はそのパス名 */ | |
459 letter delchr_; /* DELとして使うコード */ | |
460 letter nisedl_; /* 偽DELとして使うコード */ | |
461 letter delchr2_; /* DELとして使うコードが二つある場合そのもう一方 */ | |
462 letter (*keyinfn) (); /* キーイン関数 */ | |
463 int (*bytcntfn) (); /* バイトカウント関数 */ | |
464 int (*kbytcntfn) (); /* キーインの解釈用バイトカウント関数。NULL指定の時は | |
465 bytcntfnと同じものが使われる */ | |
466 char restartf; | |
467 /* rk_rst()内から呼ばれた時に立つフラグ。これが立つと、バッファをクリア | |
468 せずに済ます。この時はエラー検出時のメッセージも少し異なる */ | |
469 int flags_; | |
470 /* 以下のフラグが利用可。これらはrk_spclval.hにて定義。 | |
471 RK_CHMOUT:モードチェンジを知らせるコードを返すか? | |
472 RK_KEYACK:キーインに対し必ず何かを返すか | |
473 RK_DSPNIL:romkan_disp(off)modeのデフォルトを空文字列にするか | |
474 RK_NONISE:偽コードを出さないようにするか | |
475 RK_REDRAW:Wnn用特殊フラグ(redraw用のフラグを出すかどうか) | |
476 RK_SIMPLD:deleteの動作を単純にするか | |
477 RK_VERBOS:verboseモードで起こすか | |
478 */ | |
479 { | |
480 int errcod; /* 今の所1のみ */ | |
481 | |
482 /* 偽コードを出すかの設定はromkan_clearで使うので、フラグの設定を | |
483 先にやっておかないといけない。 */ | |
484 if ((flags = flags_) & RK_VERBOS) | |
485 { | |
486 fprintf (stderr, "romkan_init invoked.\r\n"); | |
487 fflush (stderr); | |
488 } | |
489 | |
490 #ifdef OMAKE | |
491 if (modhyo == NULL) | |
492 takeoka (-1); /* おまけ;通常は実行されない */ | |
493 #endif /* OMAKE */ | |
494 | |
495 keyin_method = keyinfn; | |
496 bytcnt_method = (bytcntfn == NULL ? head_bytecount : bytcntfn); | |
497 kbytcnt_method = (kbytcntfn == NULL ? bytcnt_method : kbytcntfn); | |
498 strcpy (prv_modfnm, modhyo); | |
499 | |
500 delchr = delchr_; | |
501 nisedl = nisedl_; | |
502 delchr2 = delchr2_; | |
503 /** 実はDELのキャラクタを二個まで持てる。二個目:delchr2は、未設定の | |
504 とき(値がEOLTTR)は無視される。それ以外は、delchr2が入力されると | |
505 delchrが入力されたのと同じ振る舞いをする。*/ | |
506 | |
507 if ((errcod = setjmp (env0)) != 0) | |
508 { | |
509 fprintf (stderr, "romkan_init failed."); | |
510 if (!restartf) | |
511 { | |
512 romkan_reset (); | |
513 /* fprintf(stderr, | |
514 "No conversion is currently performed."); */ | |
515 fprintf (stderr, "\r\n"); | |
516 } | |
517 else | |
518 { | |
519 fprintf (stderr, "Conversion method was unchanged.\r\n"); | |
520 } | |
521 } | |
522 else | |
523 { | |
524 readdata (memory, data, hensudefhyo, modhyo); | |
525 if (!restartf) | |
526 { | |
527 romkan_clear (); | |
528 hank_setup (); | |
529 } | |
530 } | |
531 | |
532 if (!errcod && (flags & RK_VERBOS)) | |
533 { | |
534 fprintf (stderr, "romkan_init finished.\r\n"); | |
535 fflush (stderr); | |
536 } | |
537 return (errcod); /* 正常終了なら0 */ | |
538 } | |
539 | |
540 /** バイトカウント関数のデフォルト。sの指している所に入っているのが | |
541 何バイトコードかを返す。 | |
542 romkan_nextに注意。そちらでは、バイトカウント関数の値は | |
543 引数の一文字目にのみ依存すると仮定している。*/ | |
544 static int | |
545 head_bytecount (s) | |
546 uns_chr *s; | |
547 { | |
548 #ifdef IKIS | |
549 return ((*s <= 0xa0 || *s == 0xff) ? 1 : 2); | |
550 #else | |
551 return (((*s <= 0xa0 && *s != HNKAK1) || *s == 0xff) ? 1 : 2); | |
552 #endif | |
553 } | |
554 | |
555 /** 変換された文字を順次返す */ | |
556 /* *INDENT-OFF* */ | |
557 letter | |
558 romkan_getc () | |
559 /* *INDENT-ON* */ | |
560 { | |
561 letter l; | |
562 | |
563 /* ungetcされている場合は、それを取り出す。 */ | |
564 if (ungetc_buf != EOLTTR) | |
565 return (l = ungetc_buf, ungetc_buf = EOLTTR, l); | |
566 | |
567 while (*curdis == EOLTTR) | |
568 { | |
569 /* romkan_next()の値がLTREOFの時も、そのまま送れば良い。 */ | |
570 curdis = romkan_henkan (romkan_next ()); | |
571 | |
572 /* keyackflgが非0なら、キーインがあれば必ず何か返す。その | |
573 ため、返すべきものがない時はEOLTTRを返すことにする。 */ | |
574 if (flags & RK_KEYACK) | |
575 break; | |
576 } | |
577 | |
578 if (EOLTTR != (l = *curdis)) | |
579 curdis++; | |
580 return (l); | |
581 /* 偽物の文字なら、HG1BITが立っている。 */ | |
582 /* 特別なコード(例えば偽のBEEPとしてNISEBP)を返すときがある。それらは | |
583 rk_spclval.hに定義されている。 */ | |
584 } | |
585 | |
586 /** romkan_getcの下位関数として、入力を一文字受け取って | |
587 変換結果の文字列を出力する。*/ | |
588 letter * | |
589 romkan_henkan (mae_in) | |
590 letter mae_in; | |
591 { | |
592 letter mae_out[2], *p; | |
593 | |
594 /* if(*curdis != EOLTTR){p = curdis; curdis = nil; return(p);} */ | |
595 /* ↑これではmae_inが無視される */ | |
596 curdis = nil; | |
597 | |
598 /* 前・後処理への入力は常にただ一文字 */ | |
599 mae_out[0] = mae_out[1] = EOLTTR; | |
600 | |
601 eofflg = rk_errstat = 0; | |
602 *rk_output = *disout = EOLTTR; | |
603 | |
604 maeato_henkan (mae_in, mae_out, usemaehyo); | |
605 rk_input = *mae_out; | |
606 | |
607 if (rk_input == LTREOF) | |
608 { | |
609 /* LTREOFが来た場合、(error)を無視し、本処理バッファの末尾迄 | |
610 強制変換する。そのためにeofflgを1にする。その後、結果の | |
611 末尾に、LTREOFが来た時の特別コード(指定されていれば)と、 | |
612 LTREOFをつなぐ。 */ | |
613 eofflg = 1; | |
614 match (); | |
615 | |
616 eofflg = 2; | |
617 add_at_eof (); /* codeoutに、LTREOFが来た時出すコードが入る。 */ | |
618 ltr1cat (codeout, LTREOF); | |
619 | |
620 ltrcat (disout, codeout); | |
621 ltrcat (rk_output, codeout); | |
622 } | |
623 else if (rk_input == EOLTTR) | |
624 { | |
625 /* EOLTTRが来た場合も、上と同様の処理を行うが、LTREOFは | |
626 つながない。なお、これはromkan_getc()を呼んでいる時は | |
627 起こらない(romkan_next()がEOLTTRを返さないから)。 */ | |
628 eofflg = 1; | |
629 match (); | |
630 } | |
631 else if (rk_input == delchr || rk_input == delchr2) | |
632 { | |
633 /* delchr2が未設定ならその値はEOLTTRなのでrk_inputと等しくない。 */ | |
634 rk_delete (rk_input); | |
635 } | |
636 else | |
637 { | |
638 ltr1cat (keybuf, rk_input); | |
639 ltr1cat (disout, toNISE (rk_input)); | |
640 match (); | |
641 } | |
642 | |
643 if (!(flags & RK_CHMOUT)) | |
644 { | |
645 /* chmoutflgが0の時は、CHMSIGを出さない。 */ | |
646 for (p = DISOUT;; p++) | |
647 { | |
648 while (*p == CHMSIG) | |
649 ltrcpy (p, p + 1); | |
650 if (*p == EOLTTR) | |
651 break; | |
652 } | |
653 } | |
654 | |
655 if ((flags & RK_REDRAW) && NULL != (p = ltr_rindex (disout, nisedl))) | |
656 { | |
657 for (p++; *p != EOLTTR || (ltr1cat (disout, REDRAW), 0); p++) | |
658 if (!isSPCL (*p)) | |
659 break; | |
660 } | |
661 /* wnnのredrawのフラグが立っていて、disoutがnisedl以後特殊コードのみ | |
662 で終わっていたら、REDRAWを出して、Wnnに変換行のredrawをさせる。 */ | |
663 | |
664 return (DISOUT); | |
665 } | |
666 | |
667 | |
668 /* デバッグ用関数 */ | |
669 #ifdef KDSP | |
670 # ifdef MVUX | |
671 | |
672 void | |
673 pridbg2 (a, b, c) | |
674 char *a, *c; | |
675 letter *b; | |
676 { | |
677 printf ("%s", a); | |
678 dump_fordbg (b); | |
679 printf ("%s", c); | |
680 } | |
681 | |
682 int | |
683 ltr_displen (l) | |
684 letter l; | |
685 { | |
686 while (l >= 256) | |
687 l >>= 8; | |
688 | |
689 if (l == 0) | |
690 return (0); | |
691 if (l < ' ') | |
692 return (0); | |
693 if (168 <= l && l <= 170) | |
694 return (1); | |
695 return (l > 160 ? 2 : 1); | |
696 } | |
697 | |
698 void | |
699 dump_fordbg (lp) | |
700 letter *lp; | |
701 { | |
702 while (*lp != EOLTTR) | |
703 printf ("%x/", *lp++); | |
704 } | |
705 | |
706 void | |
707 print_fordbg (lp) | |
708 letter *lp; | |
709 { | |
710 while (*lp != EOLTTR) | |
711 putletter (*lp++ & ~HG1BIT); | |
712 } | |
713 | |
714 void | |
715 print_ltrseq (lp) | |
716 letter *lp; | |
717 { | |
718 while (*lp != EOLTTR) | |
719 print_ltr (*lp++ & ~HG1BIT); | |
720 } | |
721 | |
722 void | |
723 print_ltr (l) | |
724 letter l; | |
725 { | |
726 letter *disptail; | |
727 int i; | |
728 | |
729 if (!isSPCL (l)) | |
730 l &= ~HG1BIT; | |
731 | |
732 if (l == CHMSIG) | |
733 #ifdef CHMDSP | |
734 printf ("...mode=%s\n", romkan_dispmode ()) | |
735 #endif | |
736 ; | |
737 else | |
738 #define BEEPCH '\007' | |
739 #define NEWLIN '\n' | |
740 if (l == BEEPCH || l == NISEBP) | |
741 putchar (BEEPCH); | |
742 else if (l == NEWLIN) | |
743 { | |
744 *displine = *keybuf = *urabuf = EOLTTR; | |
745 lastoutlen = lastkbflen = 0; | |
746 putchar (l); | |
747 } | |
748 else if (l == delchr || l == nisedl) | |
749 { | |
750 if (*displine == EOLTTR) | |
751 putchar (BEEPCH); | |
752 else | |
753 { | |
754 disptail = ltrend (displine); | |
755 for (i = ltr_displen (*disptail); i; i--) | |
756 printf ("\031 \031"); | |
757 *disptail = EOLTTR; | |
758 } | |
759 } | |
760 else | |
761 { | |
762 ltr1cat (displine, l); | |
763 putletter (l); | |
764 } | |
765 } | |
766 | |
767 # endif /* of #ifdef MVUX */ | |
768 #endif | |
769 /* デバッグ用関数終わり */ | |
770 | |
771 | |
772 /** DELが入力されたときの処理をする */ | |
773 static void | |
774 rk_delete (input_del) | |
775 letter input_del; | |
776 { | |
777 if (ltrlen (keybuf) > ((flags & RK_SIMPLD) ? 0 : lastkbflen)) | |
778 { | |
779 ltr1cut (keybuf); | |
780 set_rubout (disout, 1, nisedl); | |
781 } | |
782 else | |
783 { | |
784 if (*urabuf != EOLTTR && !(flags & RK_SIMPLD)) | |
785 { | |
786 ltr1cut (ltrcpy (keybuf, urabuf)); | |
787 *urabuf = EOLTTR; | |
788 | |
789 set_rubout (rk_output, lastoutlen, input_del); | |
790 | |
791 set_rubout (disout, lastkbflen, nisedl); | |
792 bitup_ltrcat (ltrcat (disout, rk_output), keybuf); | |
793 | |
794 lastkbflen = lastoutlen = 0; | |
795 } | |
796 else | |
797 { | |
798 set_rubout (disout, 1, input_del); | |
799 set_rubout (rk_output, 1, input_del); | |
800 } | |
801 } | |
802 } | |
803 | |
804 /** letterの列 lp1 と lp2 のマッチを試みる。返値は、lp1がlp2の頭部と | |
805 一致の時 -1、lp1またはその頭部とlp2が一致のときは一致長(lp2が | |
806 空文字列の時を含む。この場合返値は0)、それ以外は -2。 | |
807 lp2側に式が含まれていたら評価をする。lp1側には式を含んではだめ */ | |
808 static int | |
809 prefixp (lp1, lp2) | |
810 letter *lp1, *lp2; | |
811 { | |
812 /* 1行マッチさせるごとに、まずmatch情報をクリアしてから。 | |
813 つまり、henmatch[0] . ltrmch = EOLTTR; としておく。 */ | |
814 | |
815 register int mch_len = 0, d_len; | |
816 | |
817 for (;;) | |
818 { | |
819 if (*lp2 == EOLTTR) | |
820 return (mch_len); | |
821 if (*lp1 == EOLTTR) | |
822 return (-1); | |
823 if ((d_len = p_eq (&lp2, &lp1)) < 0) | |
824 return (d_len); | |
825 mch_len += d_len; | |
826 } | |
827 } | |
828 | |
829 /** num番目の変数が既にある文字とマッチしていると仮定して、その文字を返す */ | |
830 static letter | |
831 mchedsrc (num) | |
832 int num; | |
833 { | |
834 struct matchpair *pairptr; | |
835 | |
836 for (pairptr = henmatch; pairptr->ltrmch != EOLTTR; pairptr++) | |
837 { | |
838 if (num == pairptr->hennum) | |
839 return (pairptr->ltrmch); | |
840 } | |
841 return (BUGreport (8), 0); | |
842 } | |
843 | |
844 /** num番目の変数が文字 l とマッチするか調べる。その変数がunboundだった | |
845 場合は l にbindする。マッチしたら(bindの時を含む)1、しないと0を返す */ | |
846 static int | |
847 mchsrc (num, l) | |
848 int num; | |
849 letter l; | |
850 { | |
851 struct matchpair *pairptr; | |
852 | |
853 if (hen_ikisrc (num, l) == 0) | |
854 return (0); | |
855 for (pairptr = henmatch; pairptr->ltrmch != EOLTTR; pairptr++) | |
856 { | |
857 if (num == pairptr->hennum) | |
858 return (pairptr->ltrmch == l); | |
859 } | |
860 | |
861 pairptr->ltrmch = l; | |
862 pairptr->hennum = num; | |
863 (++pairptr)->ltrmch = EOLTTR; | |
864 return (1); | |
865 } | |
866 | |
867 /** l1pから一単位を取って評価し、文字l2と一致するかどうかを返す。評価した | |
868 結果が一文字にならなかったら、当然一致しない。*/ | |
869 static int | |
870 l_eq (l1p, l2) | |
871 letter *l1p, l2; | |
872 { | |
873 letter evlrsl[RSLMAX]; | |
874 | |
875 switch (SHUBET (*l1p)) | |
876 { | |
877 case 0: | |
878 return (*l1p == l2); | |
879 case 1: | |
880 return (mchsrc ((int) LWRMSK (*l1p), l2)); | |
881 case 2: | |
882 mchevl (&l1p, evlrsl); | |
883 return (evlrsl[0] == l2 && evlrsl[1] == EOLTTR); | |
884 default: | |
885 return (BUGreport (1), 0); | |
886 } | |
887 } | |
888 | |
889 /** prefixp内で使用 但し引数の順序は逆、すなわち式が含まれうるのはl1pp側 | |
890 のみ。l1ppから一単位ぶん取って評価したものとl2ppのマッチを試みる。それ | |
891 がl2ppまたはその頭部とマッチすれば一致長を返し(l1ppの評価結果が空文字 | |
892 列の時を含む。この場合返値は0)、逆にl1ppの評価結果の頭部とl2ppがマッ | |
893 チした時は -1を返す。マッチが失敗したら返値は -2。*/ | |
894 static int | |
895 p_eq (l1pp, l2pp) | |
896 register letter **l1pp, **l2pp; | |
897 { | |
898 int num; | |
899 letter evlrsl[RSLMAX], *rslptr; | |
900 register int retval = -2; | |
901 | |
902 /* l2pp側には式を含まない筈 */ | |
903 if (!is_HON (**l2pp)) | |
904 { | |
905 /* if(is_HON(**l1pp)) retval = p_eq(l2pp, l1pp); else */ | |
906 BUGreport (9); | |
907 } | |
908 else | |
909 { | |
910 switch (SHUBET (**l1pp)) | |
911 { | |
912 case 0: /* 文字同士 */ | |
913 retval = (*(*l1pp)++ == *(*l2pp)++ ? 1 : -2); | |
914 break; | |
915 case 1: /* 変数と文字 */ | |
916 num = LWRMSK (*(*l1pp)++); | |
917 retval = (mchsrc (num, *(*l2pp)++) ? 1 : -2); | |
918 break; | |
919 case 2: /* 式と文字 */ | |
920 mchevl (l1pp, rslptr = evlrsl); | |
921 for (retval = 0; *rslptr != EOLTTR; retval++) | |
922 { | |
923 if (**l2pp == EOLTTR) | |
924 { | |
925 retval = -1; | |
926 break; | |
927 } | |
928 else if (*rslptr++ != *(*l2pp)++) | |
929 { | |
930 retval = -2; | |
931 break; | |
932 } | |
933 } | |
934 break; | |
935 default: | |
936 BUGreport (2); | |
937 } | |
938 } | |
939 | |
940 return (retval); | |
941 } | |
942 | |
943 /** l1pから一単位評価してl2pに入れる */ | |
944 static void | |
945 mchevl (l1pp, l2p) | |
946 letter **l1pp, *l2p; | |
947 { | |
948 letter *l1p, tmpevl[RSLMAX]; | |
949 | |
950 l1p = *l1pp; | |
951 | |
952 switch (SHUBET (*l1p)) | |
953 { | |
954 case 0: | |
955 *l2p++ = *l1p++; | |
956 break; | |
957 case 1: | |
958 *l2p++ = mchedsrc ((int) LWRMSK (*l1p++)); | |
959 break; | |
960 case 2: /* toupper, tolower, error, … */ | |
961 switch (LWRMSK (*l1p++)) | |
962 { | |
963 case 2: | |
964 mchevl (&l1p, tmpevl); | |
965 *l2p++ = to_upper (*tmpevl); | |
966 break; | |
967 case 3: | |
968 mchevl (&l1p, tmpevl); | |
969 *l2p++ = to_lower (*tmpevl); | |
970 break; | |
971 case 4: | |
972 *l2p++ = CHMSIG; | |
973 *l2p++ = LWRMSK (*l1p++); | |
974 *l2p++ = 0; | |
975 break; /* EOLではない */ | |
976 case 5: | |
977 *l2p++ = CHMSIG; | |
978 *l2p++ = LWRMSK (*l1p++); | |
979 *l2p++ = 1; | |
980 break; | |
981 case 6: | |
982 *l2p++ = CHMSIG; | |
983 *l2p++ = XY2INT (2, LWRMSK (*l1p++)); | |
984 *l2p++ = 1; | |
985 break; | |
986 case 7: | |
987 mchevl (&l1p, tmpevl); | |
988 *l2p++ = to_updown (*tmpevl); | |
989 break; | |
990 case 8: | |
991 mchevl (&l1p, tmpevl); | |
992 *l2p++ = to_zenalpha (*tmpevl); | |
993 break; | |
994 case 9: | |
995 mchevl (&l1p, tmpevl); | |
996 *l2p++ = to_hira (*tmpevl); | |
997 break; | |
998 case 10: | |
999 mchevl (&l1p, tmpevl); | |
1000 *l2p++ = to_kata (*tmpevl); | |
1001 break; | |
1002 case 11: | |
1003 mchevl (&l1p, tmpevl); | |
1004 to_hankata (*tmpevl, &l2p); | |
1005 break; /* 特殊 */ | |
1006 case 12: | |
1007 mchevl (&l1p, tmpevl); | |
1008 *l2p++ = to_zenhira (*tmpevl); | |
1009 break; | |
1010 case 13: | |
1011 mchevl (&l1p, tmpevl); | |
1012 *l2p++ = to_zenkata (*tmpevl); | |
1013 break; | |
1014 case 14: | |
1015 mchevl (&l1p, tmpevl); | |
1016 *l2p = *tmpevl; | |
1017 mchevl (&l1p, tmpevl); | |
1018 *l2p += *tmpevl; | |
1019 LWRCUT (*l2p++); | |
1020 break; | |
1021 case 15: | |
1022 mchevl (&l1p, tmpevl); | |
1023 *l2p = *tmpevl; | |
1024 mchevl (&l1p, tmpevl); | |
1025 *l2p -= *tmpevl; | |
1026 LWRCUT (*l2p++); | |
1027 break; | |
1028 case 16: | |
1029 mchevl (&l1p, tmpevl); | |
1030 *l2p = *tmpevl; | |
1031 mchevl (&l1p, tmpevl); | |
1032 *l2p *= *tmpevl; | |
1033 LWRCUT (*l2p++); | |
1034 break; | |
1035 case 17: | |
1036 mchevl (&l1p, tmpevl); | |
1037 *l2p = *tmpevl; | |
1038 mchevl (&l1p, tmpevl); | |
1039 if (!*tmpevl) | |
1040 *l2p = LTRHUG; | |
1041 else | |
1042 *l2p /= *tmpevl; | |
1043 LWRCUT (*l2p++); | |
1044 break; | |
1045 case 18: | |
1046 mchevl (&l1p, tmpevl); | |
1047 *l2p = *tmpevl; | |
1048 mchevl (&l1p, tmpevl); | |
1049 if (!*tmpevl) | |
1050 *l2p = LTRHUG; | |
1051 else | |
1052 *l2p %= *tmpevl; | |
1053 LWRCUT (*l2p++); | |
1054 break; | |
1055 /* 19〜21・30は、条件を満たすと空文字列、 | |
1056 そうでないとUNUSDCを文字列として返す。 */ | |
1057 case 19: | |
1058 mchevl (&l1p, tmpevl); | |
1059 if (lastmch () != *tmpevl) | |
1060 *l2p++ = UNUSDC; | |
1061 break; | |
1062 case 20: | |
1063 if (!modesw[LWRMSK (*l1p++)].curmode) | |
1064 *l2p++ = UNUSDC; | |
1065 break; | |
1066 case 21: | |
1067 if (modesw[LWRMSK (*l1p++)].curmode) | |
1068 *l2p++ = UNUSDC; | |
1069 break; | |
1070 case 22: | |
1071 *l2p++ = REASIG; | |
1072 break; | |
1073 case 23: | |
1074 *l2p++ = delchr; | |
1075 break; | |
1076 case 24: | |
1077 *l2p++ = CHMSIG; | |
1078 *l2p++ = XY2INT (1, 0); | |
1079 /* これで「all」を表す */ | |
1080 *l2p++ = 0; | |
1081 break; | |
1082 case 25: | |
1083 *l2p++ = CHMSIG; | |
1084 *l2p++ = XY2INT (1, 0); | |
1085 *l2p++ = 1; | |
1086 break; | |
1087 case 26: | |
1088 mchevl (&l1p, tmpevl); | |
1089 *l2p = *tmpevl; | |
1090 mchevl (&l1p, tmpevl); | |
1091 *l2p &= *tmpevl; | |
1092 LWRCUT (*l2p++); | |
1093 break; | |
1094 case 27: | |
1095 mchevl (&l1p, tmpevl); | |
1096 *l2p = *tmpevl; | |
1097 mchevl (&l1p, tmpevl); | |
1098 *l2p |= *tmpevl; | |
1099 LWRCUT (*l2p++); | |
1100 break; | |
1101 case 28: | |
1102 mchevl (&l1p, tmpevl); | |
1103 *l2p = ~(*tmpevl); | |
1104 LWRCUT (*l2p++); | |
1105 break; | |
1106 case 29: | |
1107 *l2p++ = URBFCL; | |
1108 break; | |
1109 case 30: | |
1110 if (eofflg != 2 || *keybuf != EOLTTR) | |
1111 *l2p++ = UNUSDC; | |
1112 break; | |
1113 case 31: | |
1114 { | |
1115 letter code, basenum; | |
1116 | |
1117 mchevl (&l1p, tmpevl); | |
1118 code = *tmpevl; | |
1119 mchevl (&l1p, tmpevl); | |
1120 if ((basenum = *tmpevl) <= 1 || BASEMX < basenum) | |
1121 basenum = 10; | |
1122 to_digit (code, basenum, &l2p); | |
1123 } | |
1124 break; | |
1125 case 32: | |
1126 mchevl (&l1p, tmpevl); | |
1127 dakuadd (*tmpevl, &l2p); | |
1128 break; /* 特殊 */ | |
1129 case 33: | |
1130 mchevl (&l1p, tmpevl); | |
1131 handakuadd (*tmpevl, &l2p); | |
1132 break; /* 特殊 */ | |
1133 case 34: | |
1134 mchevl (&l1p, tmpevl); | |
1135 *l2p++ = ltov (*tmpevl); | |
1136 break; | |
1137 case 35: | |
1138 *l2p++ = ERRCOD; | |
1139 break; | |
1140 /* case 36: omitted */ | |
1141 case 37: | |
1142 *l2p++ = CHMSIG; | |
1143 *l2p++ = LWRMSK (*l1p++); | |
1144 *l2p++ = *l1p++; | |
1145 break; | |
1146 case 38: | |
1147 *l2p++ = CHMSIG; | |
1148 *l2p++ = XY2INT (2, LWRMSK (*l1p++)); | |
1149 *l2p++ = *l1p++; | |
1150 break; | |
1151 case 39: | |
1152 *l2p++ = CHMSIG; | |
1153 *l2p++ = XY2INT (3, LWRMSK (*l1p++)); | |
1154 *l2p++ = *l1p++; | |
1155 break; | |
1156 case 40: | |
1157 { | |
1158 letter modnum; | |
1159 | |
1160 modnum = LWRMSK (*l1p++); | |
1161 if (modesw[modnum].curmode != *l1p++) | |
1162 *l2p++ = UNUSDC; | |
1163 break; | |
1164 } | |
1165 case 41: | |
1166 { | |
1167 letter modnum; | |
1168 | |
1169 modnum = LWRMSK (*l1p++); | |
1170 if (modesw[modnum].curmode == *l1p++) | |
1171 *l2p++ = UNUSDC; | |
1172 break; | |
1173 } | |
1174 case 42: | |
1175 { | |
1176 letter modnum; | |
1177 | |
1178 modnum = LWRMSK (*l1p++); | |
1179 if (modesw[modnum].curmode >= *l1p++) | |
1180 *l2p++ = UNUSDC; | |
1181 break; | |
1182 } | |
1183 case 43: | |
1184 { | |
1185 letter modnum; | |
1186 | |
1187 modnum = LWRMSK (*l1p++); | |
1188 if (modesw[modnum].curmode <= *l1p++) | |
1189 *l2p++ = UNUSDC; | |
1190 break; | |
1191 } | |
1192 case 44: | |
1193 mchevl (&l1p, tmpevl); | |
1194 *l2p++ = SENDCH; | |
1195 *l2p++ = *tmpevl; | |
1196 break; | |
1197 default: /* case 0及び上記以外 */ ; | |
1198 BUGreport (7); | |
1199 } | |
1200 } | |
1201 | |
1202 *l2p = EOLTTR; | |
1203 *l1pp = l1p; | |
1204 } | |
1205 | |
1206 /** num番目の変数の変域が文字 l を含むかどうかを返す */ | |
1207 static int | |
1208 hen_ikisrc (num, l) | |
1209 int num; | |
1210 letter l; | |
1211 { | |
1212 letter *defptr; | |
1213 | |
1214 defptr = hyo_n[hyonum].hensudef[num]; | |
1215 if (*defptr == VARRNG) | |
1216 { | |
1217 for (defptr++; *defptr != EOLTTR;) | |
1218 if (*defptr++ <= l && l <= *defptr++) | |
1219 return (1); | |
1220 return (0); | |
1221 } | |
1222 | |
1223 for (; *defptr != EOLTTR; defptr++) | |
1224 { | |
1225 if (l == *defptr) | |
1226 return (1); | |
1227 } | |
1228 return (0); | |
1229 } | |
1230 | |
1231 /** 変換のメインルーチン。本処理を行うが、ついでに後処理もやっている。 | |
1232 ちなみに前処理は、romkan_getcの下位関数romkan_henkanの中で、 | |
1233 この関数を呼ぶ前にやっている。 | |
1234 この関数は、romkan_nextから一文字来る度に呼ばれる。呼び出された直後は | |
1235 outputは空文字列、disoutには入力コード一文字が入っている。 | |
1236 この関数で得られる文字の列が、romkan_henkanに渡り、 | |
1237 romkan_getcは、それを文字ごとに分解して返す。 | |
1238 (error)でエラーが引き起こされた場合は0を返し、正常終了時は1を返す */ | |
1239 int | |
1240 match () | |
1241 { | |
1242 int henkanflg = 0, okcode = 0, chm_exist; | |
1243 letter *p; | |
1244 letter urabufcreate[KBFSIZ], orgkeybuf[KBFSIZ], kbftail[KBFSIZ]; | |
1245 letter *urabufjunbi, *outcutptr, *dis_end; | |
1246 | |
1247 if (*keybuf == EOLTTR) | |
1248 { | |
1249 *urabuf = EOLTTR; | |
1250 return (1); | |
1251 } | |
1252 | |
1253 ltrcpy (urabufjunbi = orgkeybuf, keybuf); | |
1254 outcutptr = rk_output; | |
1255 | |
1256 while ((okcode = henkan_ok ()) > 0) | |
1257 { | |
1258 henkanflg = 1; | |
1259 | |
1260 codeout_chg (); | |
1261 ltrcat (rk_output, codeout); | |
1262 | |
1263 ltrcpy (kbftail, keybuf + codein_len); | |
1264 ltrcat (ltrcpy (keybuf, remainkbf), kbftail); | |
1265 | |
1266 if (okcode == 2) | |
1267 { | |
1268 ltrcpy (urabufjunbi = urabufcreate, keybuf); | |
1269 totail (outcutptr); | |
1270 } | |
1271 } | |
1272 | |
1273 if (okcode == 0) | |
1274 { | |
1275 ltr1cut (ltrcpy (keybuf, orgkeybuf)); | |
1276 ltr_to_ltrseq (disout, NISEBP); | |
1277 *rk_output = EOLTTR; | |
1278 return (0); | |
1279 } | |
1280 if (henkanflg) | |
1281 { | |
1282 ltrcpy (urabuf, urabufjunbi); | |
1283 | |
1284 set_rubout (disout, ltrlen (orgkeybuf) - 1, nisedl); | |
1285 | |
1286 dis_end = disout; | |
1287 totail (dis_end); | |
1288 ltrcpy (dis_end, rk_output); | |
1289 | |
1290 /* モードチェンジを直ちに知らせるため CHMSIGを出力 | |
1291 (flags中のRK_CHMOUTが立ってないと、あとで一文字ずつに | |
1292 分解する時点で、CHMSIGをカット)。 | |
1293 但し、rk_outputからは、CHMSIGを抜く。 | |
1294 また、CHMSIGは末尾に1回しか出力しない | |
1295 (2回以上あっても、1回にまとめて、末尾に置く)。 */ | |
1296 for (chm_exist = 0, p = rk_output;; p++) | |
1297 { | |
1298 while (*p == CHMSIG) | |
1299 { | |
1300 chm_exist = 1; | |
1301 if (ltrcpy (p, p + 1) < outcutptr) | |
1302 outcutptr--; | |
1303 } | |
1304 if (*p == EOLTTR) | |
1305 break; | |
1306 } | |
1307 if (chm_exist) | |
1308 { | |
1309 /* CHMSIGを1つにまとめたものをdis_endにつなげ直す。 | |
1310 このif文をカットすれば、CHMSIGのとりまとめはやらない */ | |
1311 ltr1cat (ltrcpy (dis_end, rk_output), CHMSIG); | |
1312 } | |
1313 | |
1314 bitup_ltrcat (disout, keybuf); | |
1315 lastoutlen = ltrlen (outcutptr); | |
1316 lastkbflen = ltrlen (keybuf); | |
1317 } | |
1318 return (1); | |
1319 } | |
1320 | |
1321 /** LTREOFが入ったときに、何か出すように指定されているか調べて、 | |
1322 codeoutをその結果の文字列(指定がなかったら当然空)にポイントする。 | |
1323 超急ごしらえで、特殊コード等は一切無視する。*/ | |
1324 static void | |
1325 add_at_eof () | |
1326 { | |
1327 register struct dat *datptr; | |
1328 register int i; | |
1329 int hyoseq; | |
1330 letter evlrsl[RSLMAX], *p; | |
1331 | |
1332 for (hyoseq = 0; (hyonum = usehyo[hyoseq]) != -1; hyoseq++) | |
1333 { | |
1334 for (i = 0, datptr = hyo_n[hyonum].data; NULL != (p = datptr[i].code[0]); i++) | |
1335 { | |
1336 henmatch[0].ltrmch = EOLTTR; | |
1337 while (*p != EOLTTR) | |
1338 { | |
1339 switch (SHUBET (*p)) | |
1340 { | |
1341 case 0: /* 文字 */ | |
1342 case 1: /* 変数 */ | |
1343 /* これらがある場合は、NULLとは | |
1344 マッチし得ない。 */ | |
1345 goto Pass; | |
1346 case 2: /* 式 */ | |
1347 mchevl (&p, evlrsl); | |
1348 if (*evlrsl != EOLTTR) | |
1349 goto Pass; | |
1350 /* 入力コード部に、評価すると | |
1351 空文字列になるものが、他にはない | |
1352 ことが前提。 */ | |
1353 } | |
1354 } | |
1355 | |
1356 ltrevlcpy (codeout = p = evalbuf[0][0], datptr[i].code[1]); | |
1357 while (*p != EOLTTR) | |
1358 { | |
1359 if (isSPCL (*p)) | |
1360 ltrcpy (p, p + 1); | |
1361 else | |
1362 p++; | |
1363 } | |
1364 codeout_chg (); | |
1365 return; | |
1366 | |
1367 Pass:; | |
1368 } | |
1369 } | |
1370 codeout = nil; | |
1371 } | |
1372 | |
1373 /** 一回マッチを試みる。返値は、マッチして確定した場合1(モードチェンジが | |
1374 混じっている場合は2)、マッチしたが未確定の時-1、マッチしなかったら0。 | |
1375 実行中は、変数 l に、それまでに一致した長さの最高記録を入れており、 | |
1376 より長く一致するものが見つかるごとに、これを更新する。lの値は、マッチ | |
1377 していても0になることもある。p_eq() 及び prefixp() の注釈文を参照。*/ | |
1378 static int | |
1379 henkan_ok () | |
1380 { | |
1381 register struct dat *datptr; | |
1382 register int i, k; | |
1383 int l, j, hyoseq; | |
1384 char urabuf_clrf; /* モードチェンジなどで、urabufをクリアする必要が | |
1385 生じた場合はこれが立ち、その結果、henkan_ok() | |
1386 が1を返すべきところで2を返す。それを見て、 | |
1387 match()がurabufなどの調整をする。 */ | |
1388 register letter *p; | |
1389 | |
1390 if (*keybuf == EOLTTR) | |
1391 return (-1); | |
1392 | |
1393 for (l = -1, hyoseq = 0; (hyonum = usehyo[hyoseq]) != -1; hyoseq++) | |
1394 { | |
1395 for (i = 0, datptr = hyo_n[hyonum].data; NULL != (p = datptr[i].code[0]); i++) | |
1396 { | |
1397 henmatch[0].ltrmch = EOLTTR; | |
1398 switch (k = prefixp (keybuf, p)) | |
1399 { | |
1400 case -2: | |
1401 break; | |
1402 case -1: | |
1403 if (eofflg != 0) | |
1404 break; | |
1405 /* eofflgが立っていたら、未確定の可能性は | |
1406 捨てる。 */ | |
1407 | |
1408 return (-1); | |
1409 default: | |
1410 if (k > l) | |
1411 { | |
1412 ebf_sw = !ebf_sw; | |
1413 for (j = 1; j <= 2; j++) | |
1414 { | |
1415 ltrevlcpy (evalbuf[ebf_sw][j - 1], datptr[i].code[j]); | |
1416 } | |
1417 | |
1418 l = k; | |
1419 } | |
1420 } | |
1421 } | |
1422 } | |
1423 | |
1424 if (l >= 0) | |
1425 { | |
1426 codein_len = l; | |
1427 codeout = evalbuf[ebf_sw][0]; | |
1428 remainkbf = evalbuf[ebf_sw][1]; | |
1429 | |
1430 for (urabuf_clrf = 0, p = codeout; *p != EOLTTR;) | |
1431 { | |
1432 switch (*p) | |
1433 { | |
1434 case CHMSIG: | |
1435 p++; | |
1436 /* codeoutの1バイト目に関数のスイッチとモード番号、 | |
1437 2バイト目にモードの新状態が入ってる */ | |
1438 switch (SHUBET (*p)) | |
1439 { | |
1440 case 0: | |
1441 chgmod ((int) *p, (modetyp) * (p + 1)); | |
1442 break; | |
1443 case 1: | |
1444 allchgmod ((modetyp) * (p + 1)); | |
1445 break; | |
1446 case 2: | |
1447 incmod ((int) LWRMSK (*p), (modetyp) * (p + 1)); | |
1448 break; | |
1449 case 3: | |
1450 decmod ((int) LWRMSK (*p), (modetyp) * (p + 1)); | |
1451 break; | |
1452 } | |
1453 ltrcpy (p, p + 2); | |
1454 /* CHMSIGだけ残して1,2バイト目cut */ | |
1455 | |
1456 urabuf_clrf = 1; | |
1457 break; | |
1458 case URBFCL: | |
1459 /* urabufのクリアを明示的に指定する */ | |
1460 urabuf_clrf = 1; | |
1461 ltrcpy (p, p + 1); | |
1462 break; | |
1463 default: | |
1464 p++; | |
1465 } | |
1466 } | |
1467 | |
1468 if (*codeout == ERRCOD) | |
1469 { | |
1470 if (eofflg == 0) | |
1471 { | |
1472 rk_errstat = 1; | |
1473 return (0); | |
1474 } | |
1475 | |
1476 /* (error)であって、しかもeofflgが立ってたら、keybuf | |
1477 の末尾まで、そのまま出す。 */ | |
1478 codein_len = ltrlen (keybuf); | |
1479 codeout = ltrcpy (evalbuf[ebf_sw][0], keybuf); | |
1480 remainkbf = nil; | |
1481 rk_errstat = 2; | |
1482 | |
1483 return (1); | |
1484 } | |
1485 /* (error)は単独でしか書けないので、エラー検出はこれで十分。 */ | |
1486 | |
1487 if (*codeout == REASIG) | |
1488 { | |
1489 *codeout = (rk_rst () != 0 ? EOLTTR : CHMSIG); | |
1490 /* 再readでエラったらモードチェンジの通知はしない */ | |
1491 | |
1492 urabuf_clrf = 1; | |
1493 } | |
1494 /* 表の再read。但し、これが起こったことを外に知らせるのはCHMSIGで | |
1495 このコードそのものは外へ出ない。(restart)は、(error)同様、 | |
1496 単独でしか書けないので、検出はこれで十分。 */ | |
1497 | |
1498 return (urabuf_clrf ? 2 : 1); | |
1499 } | |
1500 | |
1501 /* 表に現れていないコードはそのまま返す */ | |
1502 | |
1503 codein_len = 1; | |
1504 *(codeout = oneletter) = *keybuf; | |
1505 remainkbf = nil; | |
1506 return (1); | |
1507 } | |
1508 | |
1509 /* rk_rst内で使うマクロ */ | |
1510 #define taihi(X, Y, N) {for(i = 0; i < N; i++) X[i] = Y[i];} | |
1511 #define recov(X, Y, N) taihi(Y, X, N) | |
1512 | |
1513 /** 表の動的再読み込みをする。現在の内部表現を全て退避し、前と同じ | |
1514 ディレクトリ(に、現在のところ限定)から表を読み込む。もし、 | |
1515 読み込み中にエラーを検出すれば、もとの内部データを復活し非0を返す。*/ | |
1516 static int | |
1517 rk_rst () | |
1518 { | |
1519 register int i; | |
1520 int j; | |
1521 | |
1522 letter memoryt[SIZALL]; | |
1523 struct dat datat[LINALL]; | |
1524 struct hyo hyo_nt[HYOMAX]; | |
1525 letter *hensudefhyot[VARTOT]; | |
1526 struct modestat modeswt[MODMAX]; | |
1527 char hyoshut[HYOMAX]; | |
1528 char *modmeibgnt[MODMAX], modmeimem_t[MODMEI]; | |
1529 char *dspnambgnt[DMDMAX], dspcod_t[DMDCHR]; | |
1530 int usemaehyot[HYOMAX], usehyot[HYOMAX], useatohyot[HYOMAX]; | |
1531 int naibu_t[NAIBMX]; | |
1532 char *dspmodt[2][2]; | |
1533 | |
1534 taihi (memoryt, memory, SIZALL); | |
1535 taihi (datat, data, LINALL); | |
1536 taihi (hyo_nt, hyo_n, HYOMAX); | |
1537 taihi (hensudefhyot, hensudefhyo, VARTOT); | |
1538 taihi (modeswt, modesw, MODMAX); | |
1539 taihi (hyoshut, hyoshu, HYOMAX); | |
1540 taihi (modmeibgnt, modmeibgn, MODMAX); | |
1541 taihi (modmeimem_t, modmeimem_, MODMEI); | |
1542 taihi (dspnambgnt, dspnambgn, DMDMAX); | |
1543 taihi (dspcod_t, dspcod_, DMDCHR); | |
1544 taihi (usemaehyot, usemaehyo, HYOMAX); | |
1545 taihi (usehyot, usehyo, HYOMAX); | |
1546 taihi (useatohyot, useatohyo, HYOMAX); | |
1547 taihi (naibu_t, naibu_, NAIBMX); | |
1548 for (i = 0; i < 2; i++) | |
1549 for (j = 0; j < 2; j++) | |
1550 dspmodt[i][j] = dspmod[i][j]; | |
1551 | |
1552 if (0 == romkan_init3 (prv_modfnm, delchr, nisedl, delchr2, keyin_method, bytcnt_method, kbytcnt_method, 1, flags & ~RK_VERBOS)) | |
1553 return (0); /* 正常終了 */ | |
1554 | |
1555 recov (memoryt, memory, SIZALL); | |
1556 recov (datat, data, LINALL); | |
1557 recov (hyo_nt, hyo_n, HYOMAX); | |
1558 recov (hensudefhyot, hensudefhyo, VARTOT); | |
1559 recov (modeswt, modesw, MODMAX); | |
1560 recov (hyoshut, hyoshu, HYOMAX); | |
1561 recov (modmeibgnt, modmeibgn, MODMAX); | |
1562 recov (modmeimem_t, modmeimem_, MODMEI); | |
1563 recov (dspnambgnt, dspnambgn, DMDMAX); | |
1564 recov (dspcod_t, dspcod_, DMDCHR); | |
1565 recov (usemaehyot, usemaehyo, HYOMAX); | |
1566 recov (usehyot, usehyo, HYOMAX); | |
1567 recov (useatohyot, useatohyo, HYOMAX); | |
1568 recov (naibu_t, naibu_, NAIBMX); | |
1569 for (i = 0; i < 2; i++) | |
1570 for (j = 0; j < 2; j++) | |
1571 dspmod[i][j] = dspmodt[i][j]; | |
1572 return (1); | |
1573 } | |
1574 | |
1575 /** lp2から評価して得た文字列をlp1にコピー */ | |
1576 static void | |
1577 ltrevlcpy (lp1, lp2) | |
1578 letter *lp1, *lp2; | |
1579 { | |
1580 while (*lp2 != EOLTTR) | |
1581 { | |
1582 mchevl (&lp2, lp1); | |
1583 totail (lp1); | |
1584 } | |
1585 *lp1 = EOLTTR; | |
1586 } | |
1587 | |
1588 static void | |
1589 set_rubout (lp, n, del) | |
1590 /** lpに 「del」n個の列をセットする。ここに del は 'delchr'か'nisedl' */ | |
1591 letter *lp, del; | |
1592 int n; | |
1593 { | |
1594 for (; n; n--) | |
1595 *lp++ = del; | |
1596 *lp = EOLTTR; | |
1597 } | |
1598 | |
1599 /** これが実行されたらバグ。但し実行はそのまま続く */ | |
1600 void | |
1601 BUGreport (n) | |
1602 int n; | |
1603 { | |
1604 fprintf (stderr, "\r\nromkan-Bug%d!!\r\n", n); | |
1605 } | |
1606 | |
1607 /** 前処理(mae_in→mae_out)又は後処理(ato_in→ato_out)を行う。*/ | |
1608 static void | |
1609 maeato_henkan (in, outp, m_a_hyo) | |
1610 letter in; /* 入力の一文字 */ | |
1611 letter *outp; /* 出力はここに入る */ | |
1612 int *m_a_hyo; /* どの前・後処理表が選択されているかの情報 */ | |
1613 { | |
1614 struct dat *datptr; | |
1615 int i, hyoseq; | |
1616 letter *curdat; | |
1617 | |
1618 if (isSPCL (in)) | |
1619 { | |
1620 /* LTREOFやCHMSIGが来うるので、特殊コードはそのまま返すように | |
1621 細工しておかないといけない。 */ | |
1622 ltr_to_ltrseq (outp, in); | |
1623 return; | |
1624 } | |
1625 | |
1626 for (hyoseq = 0; (hyonum = m_a_hyo[hyoseq]) != -1; hyoseq++) | |
1627 { | |
1628 for (i = 0, datptr = hyo_n[hyonum].data; NULL != (curdat = datptr[i].code[0]); i++) | |
1629 { | |
1630 henmatch[0].ltrmch = EOLTTR; | |
1631 if (!l_eq (curdat, in)) | |
1632 continue; | |
1633 | |
1634 ltrevlcpy (outp, datptr[i].code[1]); | |
1635 return; | |
1636 } | |
1637 } | |
1638 ltr_to_ltrseq (outp, in); | |
1639 } | |
1640 | |
1641 /** 後処理 */ | |
1642 static void | |
1643 codeout_chg () | |
1644 { | |
1645 letter *saishu_outp; | |
1646 | |
1647 *(saishu_outp = saishu_out) = EOLTTR; | |
1648 | |
1649 for (; *codeout != EOLTTR; codeout++) | |
1650 { | |
1651 maeato_henkan (*codeout, saishu_outp, useatohyo); | |
1652 totail (saishu_outp); | |
1653 } | |
1654 | |
1655 codeout = saishu_out; | |
1656 } | |
1657 | |
1658 /** 一文字プッシュ・バック */ | |
1659 /* *INDENT-OFF* */ | |
1660 letter | |
1661 romkan_ungetc (l) | |
1662 letter l; | |
1663 /* *INDENT-ON* */ | |
1664 { | |
1665 return (ungetc_buf = l); | |
1666 } | |
1667 | |
1668 /** romkan_nextに対し一文字プッシュ・バック */ | |
1669 /* *INDENT-OFF* */ | |
1670 letter | |
1671 romkan_unnext (l) | |
1672 letter l; | |
1673 /* *INDENT-ON* */ | |
1674 { | |
1675 return (unnext_buf = l); | |
1676 } | |
1677 | |
1678 /** deleteとして使うキャラクタの設定(偽deleteも)。これを実行後は | |
1679 romkan_clearを実行しておかないと混乱のもとになります。*/ | |
1680 /* (廃止) | |
1681 void | |
1682 romkan_setdel(delchr_, nisedl_) | |
1683 letter delchr_, nisedl_; | |
1684 { | |
1685 delchr = delchr_; | |
1686 nisedl = nisedl_; | |
1687 } | |
1688 */ |