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 */