0
|
1 /*
|
|
2 * $Id: rk_modread.c,v 1.9 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, 2002
|
|
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_modread.c
|
|
35 88. 6.16 改 正
|
|
36
|
|
37 モード定義表の読み込みを担当するプログラム。
|
|
38 ***********************************************************************/
|
|
39 /* Version 3.0 */
|
|
40 #ifdef HAVE_CONFIG_H
|
|
41 # include <config.h>
|
|
42 #endif
|
|
43
|
|
44 #if STDC_HEADERS
|
|
45 # include <stdlib.h>
|
|
46 # include <string.h>
|
|
47 #elif HAVE_STRINGS_H
|
|
48 # include <strings.h>
|
|
49 #endif /* STDC_HEADERS */
|
|
50 #include <sys/types.h>
|
|
51 #include <pwd.h>
|
|
52 #if HAVE_UNISTD_H
|
|
53 # include <unistd.h>
|
|
54 #endif
|
|
55
|
|
56 #include "rk_header.h"
|
|
57 #include "rk_extvars.h"
|
|
58 #ifdef WNNDEFAULT
|
|
59 # include "wnn_config.h"
|
|
60 /* マクロLIBDIRの定義(のためだけ)。コンパイル時は、ヘッダファイルの
|
|
61 サーチパスに、Wnnのインクルードファイルのありかを設定しておくこと。 */
|
|
62 #endif
|
|
63
|
|
64 #define Terminator 0 /* intの列(naibu[])の終止コード */
|
|
65
|
|
66 extern char *chrcat (), *strend (), *ename ();
|
|
67 extern void romkan_clear ();
|
|
68 char *modhyopath;
|
|
69
|
|
70 static void cond_evl (), mystrcpy (), rd_bcksla (), rd_ctrl (), hyouse (), look_choose ();
|
|
71 void choosehyo ();
|
|
72 static int mystrcmp (), read1tm (), mod_evl (), fnmsrc_tourk (), dspnamsrc_tourk (),
|
|
73 scan1tm (), modsrc_tourk (), chk_get_int (), pathsrc_tourk (), modnamchk (), ctov (), look_cond (), evlcond (), chkchar_getc ();
|
|
74 static char codeeval ();
|
|
75 extern void ERRMOD (), ERMOPN (), BUGreport ();
|
|
76 extern int filnamchk ();
|
|
77
|
|
78 struct kwdpair
|
|
79 {
|
|
80 /* キーワードとその内部表現の対応を与える構造体。内部表現を
|
|
81 持たないものに対しては0が与えられている。 */
|
|
82 char *name;
|
|
83 int code;
|
|
84 }
|
|
85 modfn[] =
|
|
86 {
|
|
87 "defmode", 0,
|
|
88 "if", XY2INT (2, 0), "when", XY2INT (2, 1), "path", 0, "search", 0, "on_dispmode", XY2INT (5, 0), "off_dispmode", XY2INT (5, 1), "on_unchg", XY2INT (6, 0), "off_unchg", XY2INT (6, 1), NULL}; /* 下を見よ キーワード定義表はまだあと二つあるのだ */
|
|
89
|
|
90 struct kwdpair modcond[] = {
|
|
91 "not", XY2INT (3, 0),
|
|
92 "and", XY2INT (3, 1),
|
|
93 "or", XY2INT (3, 2),
|
|
94 "true", XY2INT (3, 3),
|
|
95 "false", XY2INT (3, 4),
|
|
96 "=", XY2INT (3, 5),
|
|
97 "!=", XY2INT (3, 6),
|
|
98 "<", XY2INT (3, 7),
|
|
99 ">", XY2INT (3, 8),
|
|
100 NULL
|
|
101 };
|
|
102 int condarg[] = { 1, 2, 2, 0, 0, 2, 2, 2, 2 }; /* 条件判断関数の引数個数 */
|
|
103
|
|
104 struct kwdpair swstat[] = {
|
|
105 "on", 0,
|
|
106 "off", 0,
|
|
107 NULL
|
|
108 };
|
|
109 /* 1×2^24代はモード名、4×2^24代はモード表示文字列、7×2^24代はモード状態定
|
|
110 数の内部表現に使っている */
|
|
111
|
|
112 /** キーワード(if, andなど)が正当なものかチェックし、その番号を返す */
|
|
113 static int
|
|
114 kwdsrc (hyo, wd)
|
|
115 struct kwdpair *hyo; /* どのキーワード表を使うか */
|
|
116 char *wd; /* チェックされるキーワード */
|
|
117 {
|
|
118 int i;
|
|
119
|
|
120 for (i = 0; hyo[i].name != NULL; i++)
|
|
121 if (!mystrcmp (hyo[i].name, wd))
|
|
122 return (i);
|
|
123 ERRMOD (9);
|
|
124 /*NOTREACHED*/
|
|
125 }
|
|
126
|
|
127 /** モード表の読み込み */
|
|
128 void
|
|
129 readmode (modfname)
|
|
130 char *modfname; /* モード表の名 */
|
|
131 {
|
|
132 char buf[MDHMAX], *bufp;
|
|
133 #ifdef RKMODPATH
|
|
134 char *genv, *pathenv, *pathp;
|
|
135 #endif
|
|
136
|
|
137 mcurread = buf; /* エラー処理用 */
|
|
138
|
|
139 #ifdef RKMODPATH
|
|
140 if (!fixednamep (modfname) && NULL != (pathenv = genv = getenv (RKMODPATH)) && *genv != '\0')
|
|
141 {
|
|
142 /* PATHに少なくとも一つのサーチパスがある場合 */
|
|
143 for (;;)
|
|
144 {
|
|
145 /* サーチパスの各々を入れる領域には、pathmeimemを借用
|
|
146 している。後で、サーチパスの先頭に、モード表のある
|
|
147 ディレクトリを設定するので、その便宜のためもある */
|
|
148 for (pathp = pathmeimem; *genv != ':' && *genv; genv++)
|
|
149 *pathp++ = *genv;
|
|
150 *pathp = '\0';
|
|
151
|
|
152 if (*(strend (pathmeimem)) != KUGIRI)
|
|
153 *pathp++ = KUGIRI;
|
|
154 /* pathの区切りはDG(MV)であっても'/' */
|
|
155
|
|
156 strcpy (pathp, modfname);
|
|
157 if (NULL != (modefile = fopen (pathmeimem, "r")))
|
|
158 {
|
|
159 /* Now Mode-hyo found */
|
|
160 if (flags & RK_VERBOS)
|
|
161 fprintf (stderr, "romkan: using Mode-hyo %s ...\r\n", pathmeimem);
|
|
162 curdir = pathmeimem; /* この時点ではファイル名
|
|
163 込みだが、あとでパス名だけになる */
|
|
164 curfnm = ename (modfname);
|
|
165 break;
|
|
166 }
|
|
167
|
|
168 if (*genv != ':')
|
|
169 { /* Mode-hyo not found */
|
|
170 if (flags & RK_VERBOS)
|
|
171 {
|
|
172 fprintf (stderr, "no %s in ", modfname);
|
|
173 for (genv = pathenv; *genv; genv++)
|
|
174 {
|
|
175 fputc ((*genv == ':' ? ' ' : *genv), stderr);
|
|
176 }
|
|
177 fprintf (stderr, ".\n");
|
|
178 }
|
|
179 ERMOPN (0);
|
|
180 }
|
|
181 else
|
|
182 genv++; /* coutinues searching Mode-hyo */
|
|
183 }
|
|
184 }
|
|
185 else
|
|
186 #endif
|
|
187 {
|
|
188 if (NULL == (modefile = fopen (modfname, "r")))
|
|
189 ERMOPN (0);
|
|
190 if (flags & RK_VERBOS)
|
|
191 fprintf (stderr, "romkan: using Mode-hyo %s ...\r\n", modfname);
|
|
192 strcpy (pathmeimem, modfname);
|
|
193 }
|
|
194
|
|
195 /* サーチパスの先頭に、モード表のあるディレクトリを設定している。 */
|
|
196 *(ename (pathmeimem)) = '\0';
|
|
197 modhyopath = *pathmeiptr++ = pathmeimem;
|
|
198 *pathmeiptr = NULL;
|
|
199 strtail (pathmeimem);
|
|
200 *(pathareaorg = ++pathmeimem) = '\0';
|
|
201 /* pathareaorgは、pathmeimem_[]のうちモード表のあるディレクトリ名を
|
|
202 格納した残りの部分の先頭を指す。 */
|
|
203
|
|
204 while (bufp = buf, read1tm (&bufp, 0))
|
|
205 mod_evl (buf);
|
|
206 fclose (modefile);
|
|
207 }
|
|
208
|
|
209 /** 固定された(サーチパスを見る必要のない)ファイル名に対しては非0を
|
|
210 返す。現在のところ、 / ./ ../ のどれかで始まるものとしているが(作者の
|
|
211 独断)、適当に変えてよい。strchr(s,'/')!=NULL とする方が良いかも */
|
|
212 int
|
|
213 fixednamep (s)
|
|
214 char *s;
|
|
215 {
|
|
216 return (!strncmp ("/", s, 1) || !strncmp ("./", s, 2) || !strncmp ("../", s, 3));
|
|
217 }
|
|
218
|
|
219 /** モード表の一かたまり(リスト、ファイル名、モード表示文字列)を
|
|
220 解釈する。返す値は、defmode,search及びpathの時0、それ以外なら1。*/
|
|
221 static int
|
|
222 mod_evl (s)
|
|
223 char *s; /* モード表の内部表現の列へのポインタ */
|
|
224 {
|
|
225 char md1[MDT1LN], *bgn, *end;
|
|
226 int num, retval = 1;
|
|
227
|
|
228 if (*s != '(')
|
|
229 {
|
|
230 if (*s != '"')
|
|
231 {
|
|
232 num = fnmsrc_tourk (s);
|
|
233 *naibu++ = XY2INT (4, num);
|
|
234 }
|
|
235 else
|
|
236 {
|
|
237 s++;
|
|
238 if (*(end = strend (s)) != '"')
|
|
239 ERRMOD (10);
|
|
240 *end = '\0';
|
|
241 num = dspnamsrc_tourk (s);
|
|
242 *naibu++ = XY2INT (5, 0);
|
|
243 *naibu++ = num;
|
|
244 }
|
|
245 }
|
|
246 else
|
|
247 {
|
|
248 s++;
|
|
249 scan1tm (&s, md1, 1);
|
|
250 switch (num = kwdsrc (modfn, md1))
|
|
251 {
|
|
252 case 0: /* defmode */
|
|
253 retval = 0;
|
|
254 scan1tm (&s, md1, 1); /* modename */
|
|
255 num = modsrc_tourk (md1, 0);
|
|
256 if (scan1tm (&s, md1, 0) == 0)
|
|
257 {
|
|
258 /* 初期on-offについて何も書いてない時の
|
|
259 defaultはoff */
|
|
260 modesw[num].moderng = 2;
|
|
261 modesw[num].curmode = 0;
|
|
262 break;
|
|
263 }
|
|
264
|
|
265 if (*md1 == '(')
|
|
266 {
|
|
267 char tmp[MDT1LN], *s;
|
|
268 unsigned int i, j;
|
|
269
|
|
270 s = md1 + 1;
|
|
271
|
|
272 scan1tm (&s, tmp, 1);
|
|
273 if (chk_get_int (tmp, &i, 0) != 0)
|
|
274 ERRMOD (8);
|
|
275 modesw[num].moderng = i;
|
|
276 scan1tm (&s, tmp, 1);
|
|
277 if (chk_get_int (tmp, &j, modesw[num].moderng) != 0)
|
|
278 ERRMOD (8);
|
|
279 modesw[num].curmode = j;
|
|
280 if (
|
|
281 #ifdef ModeNotInt
|
|
282 modesw[num].moderng != i || modesw[num].curmode != j ||
|
|
283 #endif
|
|
284 i == 1 || (i != 0 && j >= i))
|
|
285 {
|
|
286 ERRMOD (8);
|
|
287 }
|
|
288 scan1tm (&s, tmp, 2);
|
|
289 }
|
|
290 else
|
|
291 {
|
|
292 switch (kwdsrc (swstat, md1))
|
|
293 {
|
|
294 case 0:
|
|
295 modesw[num].curmode = 1;
|
|
296 break;
|
|
297 case 1:
|
|
298 modesw[num].curmode = 0;
|
|
299 break;
|
|
300 }
|
|
301 modesw[num].moderng = 2;
|
|
302 }
|
|
303 scan1tm (&s, md1, 2); /* あればerr */
|
|
304 break;
|
|
305 case 1: /* if */
|
|
306 case 2: /* when */
|
|
307 *naibu++ = modfn[num].code;
|
|
308 scan1tm (&s, md1, 1); /* condition */
|
|
309 cond_evl (md1);
|
|
310 while (scan1tm (&s, md1, 0))
|
|
311 {
|
|
312 if (mod_evl (md1) == 0)
|
|
313 ERRMOD (17);
|
|
314 }
|
|
315 *naibu++ = Terminator;
|
|
316 break;
|
|
317 case 3: /* path */
|
|
318 *(pathmeimem = pathareaorg) = '\0';
|
|
319 *(pathmeiptr = pathmeiorg) = NULL;
|
|
320 case 4: /* search */
|
|
321 retval = 0;
|
|
322 if (hyomeiptr != hyomeiorg)
|
|
323 ERRMOD (11);
|
|
324 /* サーチパスの指定はファイル名の出現より
|
|
325 先行しなければならないとしておく。 */
|
|
326
|
|
327 while (scan1tm (&s, md1, 0))
|
|
328 { /* find pathname */
|
|
329 pathsrc_tourk (md1);
|
|
330 }
|
|
331 break;
|
|
332 case 5: /* on_dispmode */
|
|
333 case 6: /* off_dispmode */
|
|
334 *naibu++ = modfn[num].code;
|
|
335 scan1tm (&s, md1, 1); /* dispmode string */
|
|
336
|
|
337 if (*(bgn = md1) != '"')
|
|
338 ERRMOD (12);
|
|
339 bgn++;
|
|
340 if (*(end = strend (bgn)) != '"')
|
|
341 ERRMOD (10);
|
|
342 *end = '\0';
|
|
343 *naibu++ = dspnamsrc_tourk (bgn);
|
|
344 scan1tm (&s, md1, 2); /* あればerr */
|
|
345 break;
|
|
346 case 7: /* on_unchg */
|
|
347 case 8: /* off_unchg */
|
|
348 *naibu++ = modfn[num].code;
|
|
349 scan1tm (&s, md1, 2); /* あればerr */
|
|
350 break;
|
|
351 }
|
|
352
|
|
353 }
|
|
354 *naibu = Terminator;
|
|
355 return (retval);
|
|
356 }
|
|
357
|
|
358 /** 条件式(モード名 又はnot,andなどの式)一つを解釈 */
|
|
359 static void
|
|
360 cond_evl (cod)
|
|
361 char *cod; /* 条件式の内部表現の列へのポインタ */
|
|
362 {
|
|
363 char md1[MDT1LN];
|
|
364 unsigned int num;
|
|
365 int i;
|
|
366
|
|
367 if (is_digit (*cod) || *cod == '-')
|
|
368 {
|
|
369 *naibu++ = XY2INT (7, 0);
|
|
370 if (0 != chk_get_int (cod, &num, 0))
|
|
371 ERRMOD (4);
|
|
372 *naibu++ = num;
|
|
373 }
|
|
374 else if (*cod != '(')
|
|
375 {
|
|
376 num = modsrc_tourk (cod, 1);
|
|
377 *naibu++ = XY2INT (1, num);
|
|
378 }
|
|
379 else
|
|
380 {
|
|
381 cod++;
|
|
382 scan1tm (&cod, md1, 1); /* not;and;or */
|
|
383 num = kwdsrc (modcond, md1);
|
|
384 *naibu++ = XY2INT (3, num);
|
|
385 for (i = condarg[num]; i; i--)
|
|
386 {
|
|
387 scan1tm (&cod, md1, 0);
|
|
388 cond_evl (md1);
|
|
389 }
|
|
390 scan1tm (&cod, md1, 2);
|
|
391 }
|
|
392 *naibu = Terminator;
|
|
393 }
|
|
394
|
|
395 /** sで指定されたファイル名が既登録か探し、なければ登録。但し、既登録か
|
|
396 どうかのチェックは厳密ではないが(例えば、同じファイルでも、
|
|
397 パス名付きと無しとでは、同じと見ない)、ファイル名が既登録かどうか
|
|
398 チェックするのは、メモリ節約のために同じ表を読み込むのを防ぐため
|
|
399 だけなので、それ以外には別に困る点はない。*/
|
|
400 static int
|
|
401 fnmsrc_tourk (s)
|
|
402 char *s;
|
|
403 {
|
|
404 int n;
|
|
405
|
|
406 for (n = 0; hyomeiorg[n] != NULL; n++)
|
|
407 if (!mystrcmp (hyomeiorg[n], s))
|
|
408 return (n);
|
|
409
|
|
410 if (hyomeiorg + n != hyomeiptr)
|
|
411 BUGreport (101);
|
|
412
|
|
413 *hyomeiptr++ = hyomeimem;
|
|
414 *hyomeiptr = NULL;
|
|
415 mystrcpy (hyomeimem, s);
|
|
416 if (!(hyoshu[n] = filnamchk (hyomeimem)))
|
|
417 ERRMOD (3);
|
|
418 strtail (hyomeimem);
|
|
419 *++hyomeimem = '\0';
|
|
420 return (n);
|
|
421 }
|
|
422
|
|
423 /** sで指定されたサーチパス名が既登録か探し、なければ登録。但し、fnmsrc_
|
|
424 tourk()同様、既登録かどうかのチェックは厳密ではないが問題ない。*/
|
|
425 static int
|
|
426 pathsrc_tourk (s)
|
|
427 char *s;
|
|
428 {
|
|
429 int n;
|
|
430 char fnm_addsla[MDT1LN];
|
|
431
|
|
432 mystrcpy (fnm_addsla, s);
|
|
433 if (!(*fnm_addsla == '\0' || *(strend (fnm_addsla)) == KUGIRI))
|
|
434 chrcat (fnm_addsla, KUGIRI);
|
|
435 /* パス名が'/'で終わってなければ、それを付加する。 */
|
|
436
|
|
437 for (n = 0; pathmeiorg[n] != NULL; n++)
|
|
438 if (!strcmp (pathmeiorg[n], fnm_addsla))
|
|
439 return (n);
|
|
440
|
|
441 if (pathmeiorg + n != pathmeiptr)
|
|
442 BUGreport (104);
|
|
443
|
|
444 *pathmeiptr++ = pathmeimem;
|
|
445 *pathmeiptr = NULL;
|
|
446 strcpy (pathmeimem, fnm_addsla);
|
|
447
|
|
448 strtail (pathmeimem);
|
|
449
|
|
450 *++pathmeimem = '\0';
|
|
451 return (n);
|
|
452 }
|
|
453
|
|
454 /** sで指定されたモード表示文字列が既登録か探し、なければ登録 */
|
|
455 static int
|
|
456 dspnamsrc_tourk (s)
|
|
457 char *s;
|
|
458 {
|
|
459 int n;
|
|
460
|
|
461 for (n = 0; dspnambgn[n] != NULL; n++)
|
|
462 if (!mystrcmp (dspnambgn[n], s))
|
|
463 return (n);
|
|
464
|
|
465 if (dspnambgn + n != dspnamptr)
|
|
466 BUGreport (103);
|
|
467
|
|
468 *dspnamptr++ = dspcod;
|
|
469 *dspnamptr = NULL;
|
|
470 mystrcpy (dspcod, s);
|
|
471 strtail (dspcod);
|
|
472 *++dspcod = '\0';
|
|
473 return (n);
|
|
474 }
|
|
475
|
|
476 /** 登録されているモード名の中から、sで指定されたモード名を探す。*np に
|
|
477 モード番号が入る。見つからないと現モード名の総数が入る。その場合
|
|
478 返値は0。*/
|
|
479 static int
|
|
480 modnam_src (s, np)
|
|
481 char *s;
|
|
482 int *np;
|
|
483 {
|
|
484 for (*np = 0; modmeibgn[*np] != NULL; (*np)++)
|
|
485 if (!mystrcmp (modmeibgn[*np], s))
|
|
486 return (1);
|
|
487 return (0);
|
|
488 }
|
|
489
|
|
490 /** sで指定されたモード名を探し、なければ登録。但し、flgが非0なら、
|
|
491 見つからなければエラー */
|
|
492 static int
|
|
493 modsrc_tourk (s, flg)
|
|
494 char *s;
|
|
495 int flg;
|
|
496 {
|
|
497 int n;
|
|
498
|
|
499 if (modnam_src (s, &n))
|
|
500 return (n);
|
|
501
|
|
502 if (flg)
|
|
503 ERRMOD (5);
|
|
504
|
|
505 if (modmeibgn + n != modmeiptr)
|
|
506 BUGreport (102);
|
|
507
|
|
508 *modmeiptr++ = modmeimem;
|
|
509 *modmeiptr = NULL;
|
|
510 mystrcpy (modmeimem, s);
|
|
511 if (!modnamchk (modmeimem))
|
|
512 ERRMOD (4);
|
|
513 strtail (modmeimem);
|
|
514 *++modmeimem = '\0';
|
|
515 return (n);
|
|
516 }
|
|
517
|
|
518 /** ファイルから一文字読む(空白文字は飛ばす)。読んだ文字がEOFなら0を返す */
|
|
519 static char
|
|
520 fspcpass ()
|
|
521 {
|
|
522 register int c;
|
|
523
|
|
524 while (EOF != (c = chkchar_getc (modefile)) && is_nulsp (c));
|
|
525 return (c == EOF ? '\0' : c);
|
|
526 }
|
|
527
|
|
528 /** モード表には空白文字以外のコントロール文字は生では混じらないものと
|
|
529 する。混じっていた場合はチェックしつつ、getcを行う。*/
|
|
530 static int
|
|
531 chkchar_getc (f)
|
|
532 FILE *f;
|
|
533 {
|
|
534 register int c;
|
|
535
|
|
536 c = getc (f);
|
|
537 if (is_cntrl (c) && !isspace (c))
|
|
538 {
|
|
539 sprintf (mcurread, "\\%03o", c);
|
|
540 ERRMOD (16);
|
|
541 }
|
|
542 return (c);
|
|
543 }
|
|
544
|
|
545 static int
|
|
546 modehyo_getc ()
|
|
547 {
|
|
548 return (chkchar_getc (modefile));
|
|
549 }
|
|
550
|
|
551 static int
|
|
552 modehyo_ungetc (c)
|
|
553 register int c;
|
|
554 {
|
|
555 return (ungetc (c, modefile));
|
|
556 }
|
|
557
|
|
558 /** socの名のユーザのログイン・ディレクトリ名をdestに入れ、*destにその
|
|
559 末尾を指させる。但しsocが空列なら自分のログイン・ディレクトリ名、
|
|
560 NULLなら自分のホーム・ディレクトリ名。いずれの場合も、不成功時は
|
|
561 何もしない。返値は、不成功時-1(getenv("HOME")失敗時だけは-2)。*/
|
|
562 static int
|
|
563 get_hmdir (dest, soc)
|
|
564 char **dest, *soc;
|
|
565 {
|
|
566 struct passwd *usr;
|
|
567 char *p;
|
|
568
|
|
569 if (soc == NULL)
|
|
570 {
|
|
571 if (NULL == (p = getenv ("HOME")))
|
|
572 return (-2);
|
|
573 }
|
|
574 else
|
|
575 {
|
|
576 if (NULL == (usr = (*soc ? getpwnam (soc) : getpwuid (getuid ()))))
|
|
577 return (-1);
|
|
578 p = usr->pw_dir;
|
|
579 }
|
|
580 strcpy (*dest, p);
|
|
581 strtail (*dest);
|
|
582 return (0);
|
|
583 }
|
|
584
|
|
585 /** モード表・対応表中の、ファイル名の部分の読み込み。先頭が @ 又は ~ の
|
|
586 時は、特殊処理を行う。引数は、一字読み込み・一字戻し・文字列取り出しの
|
|
587 関数と、結果を入れるエリアの番地へのポインタ、次に読まれる文字を入れる
|
|
588 ポインタ。返値は、正常終了時0、@HOMEでホーム・ディレクトリが取れない時
|
|
589 1、@のあとに変なものが来たら2、~で自分のホーム・ディレクトリが取れない
|
|
590 時3、~のあとに存在しないユーザ名が来たら4。*/
|
|
591 int
|
|
592 readfnm (readchar_func, unreadc_func, readstr_func, areap, lastcptr)
|
|
593 register int (*readchar_func) (), (*unreadc_func) (), (*readstr_func) ();
|
|
594 char **areap;
|
|
595 int *lastcptr;
|
|
596 {
|
|
597 char *head;
|
|
598 register int c;
|
|
599
|
|
600 c = (*readchar_func) ();
|
|
601 if (c == '@')
|
|
602 { /* @HOME, @MODEDIR, @LIBDIR */
|
|
603 *(*areap)++ = c;
|
|
604 head = *areap;
|
|
605 (*readstr_func) (areap, 1);
|
|
606
|
|
607 if (mystrcmp ("HOME", head) == 0)
|
|
608 {
|
|
609 *areap = --head;
|
|
610 if (get_hmdir (areap, (char *) NULL) != 0)
|
|
611 {
|
|
612 *areap = head;
|
|
613 return (1);
|
|
614 }
|
|
615 }
|
|
616 else if (mystrcmp ("MODEDIR", head) == 0)
|
|
617 {
|
|
618 strcpy (*areap = --head, modhyopath);
|
|
619 if (KUGIRI == *(*areap = strend (*areap)))
|
|
620 **areap = '\0';
|
|
621 }
|
|
622 else
|
|
623 #ifdef WNNDEFAULT
|
|
624 if (mystrcmp ("LIBDIR", head) == 0)
|
|
625 {
|
|
626 strcpy (*areap = --head, LIBDIR);
|
|
627 strtail (*areap);
|
|
628 }
|
|
629 else
|
|
630 #endif
|
|
631 {
|
|
632 *areap = --head;
|
|
633 return (2);
|
|
634 }
|
|
635
|
|
636 }
|
|
637 else if (c == '~')
|
|
638 { /* ~user */
|
|
639 int err;
|
|
640
|
|
641 *(*areap)++ = c;
|
|
642 head = *areap;
|
|
643 (*readstr_func) (areap, 1);
|
|
644
|
|
645 mystrcpy (head, head);
|
|
646 *areap = head - 1;
|
|
647 if ((err = get_hmdir (areap, (*head ? head : NULL))) != 0)
|
|
648 {
|
|
649 *areap = --head;
|
|
650 return (err == -2 ? 3 : 4);
|
|
651 }
|
|
652
|
|
653 }
|
|
654 else
|
|
655 {
|
|
656 (*unreadc_func) (c);
|
|
657 }
|
|
658
|
|
659 *lastcptr = (*readstr_func) (areap, 0);
|
|
660 return (0);
|
|
661 }
|
|
662
|
|
663 /** モード表から一文字分取り出す作業を、空白・括弧のどれか
|
|
664 又はEOFが来るまで続ける。flg & 01が非0なら、'/'が来ても
|
|
665 終わる。返値は、次に読まれる文字。*/
|
|
666 static int
|
|
667 rd_string (readfile, sptr, flg)
|
|
668 register FILE *readfile;
|
|
669 char **sptr;
|
|
670 int flg;
|
|
671 {
|
|
672 int c;
|
|
673
|
|
674 while (EOF != (c = chkchar_getc (readfile)) && !(is_nulsp (c) || c == '(' || c == ')') && !(flg & 01 && c == KUGIRI))
|
|
675 {
|
|
676 switch (c)
|
|
677 {
|
|
678 case '\\':
|
|
679 rd_bcksla (readfile, sptr);
|
|
680 break;
|
|
681 case '^':
|
|
682 rd_ctrl (readfile, sptr);
|
|
683 break;
|
|
684 default:
|
|
685 *(*sptr)++ = c;
|
|
686 }
|
|
687 }
|
|
688 **sptr = '\0';
|
|
689 return (ungetc (c, readfile));
|
|
690 }
|
|
691
|
|
692 static int
|
|
693 rd_str_from_modefile (sptr, flg)
|
|
694 char **sptr;
|
|
695 int flg;
|
|
696 {
|
|
697 return (rd_string (modefile, sptr, flg));
|
|
698 }
|
|
699
|
|
700
|
|
701 /** モード表からバックスラッシュ形式の一文字分を取り出し、'\(8進);'
|
|
702 の形に直す。但し、先頭の'\\'は既に読まれたあと。*/
|
|
703 static void
|
|
704 rd_bcksla (readfile, sptr)
|
|
705 register FILE *readfile;
|
|
706 char **sptr;
|
|
707 {
|
|
708 int c, code = 0, digflg = 0;
|
|
709
|
|
710 switch (c = chkchar_getc (readfile))
|
|
711 {
|
|
712 case 'n':
|
|
713 code = '\n';
|
|
714 digflg = 1;
|
|
715 break;
|
|
716 case 't':
|
|
717 code = '\t';
|
|
718 digflg = 1;
|
|
719 break;
|
|
720 case 'b':
|
|
721 code = '\b';
|
|
722 digflg = 1;
|
|
723 break;
|
|
724 case 'r':
|
|
725 code = '\r';
|
|
726 digflg = 1;
|
|
727 break;
|
|
728 case 'f':
|
|
729 code = '\f';
|
|
730 digflg = 1;
|
|
731 break;
|
|
732 case 'e':
|
|
733 case 'E':
|
|
734 code = ESCCHR;
|
|
735 digflg = 1;
|
|
736 break;
|
|
737 case 'o':
|
|
738 while (c = chkchar_getc (readfile), is_octal (c))
|
|
739 {
|
|
740 code <<= 3;
|
|
741 code += ctov (c);
|
|
742 digflg = 1;
|
|
743 }
|
|
744 if (c != ';')
|
|
745 ungetc (c, readfile);
|
|
746 break;
|
|
747 case 'd':
|
|
748 while (c = chkchar_getc (readfile), is_digit (c))
|
|
749 {
|
|
750 code *= 10;
|
|
751 code += ctov (c);
|
|
752 digflg = 1;
|
|
753 }
|
|
754 if (c != ';')
|
|
755 ungetc (c, readfile);
|
|
756 break;
|
|
757 case 'x':
|
|
758 while (c = chkchar_getc (readfile), is_xdigit (c))
|
|
759 {
|
|
760 code <<= 4;
|
|
761 code += ctov (c);
|
|
762 digflg = 1;
|
|
763 }
|
|
764 if (c != ';')
|
|
765 ungetc (c, readfile);
|
|
766 break;
|
|
767 default:
|
|
768 if (is_octal (c))
|
|
769 {
|
|
770 digflg = 1;
|
|
771 code = ctov (c);
|
|
772 while (c = chkchar_getc (readfile), is_octal (c))
|
|
773 {
|
|
774 code <<= 3;
|
|
775 code += ctov (c);
|
|
776 }
|
|
777 if (c != ';')
|
|
778 ungetc (c, readfile);
|
|
779 }
|
|
780 else
|
|
781 {
|
|
782 code = c;
|
|
783 digflg = 1;
|
|
784 }
|
|
785 }
|
|
786
|
|
787 if (digflg == 0)
|
|
788 ERRMOD (7);
|
|
789 sprintf (*sptr, "\\%o;", code);
|
|
790 strtail (*sptr);
|
|
791 }
|
|
792
|
|
793 /** モード表からコントロールコード形式の一文字分を取り出し、
|
|
794 '\(8進);' の形に直す。但し、先頭の'^'は既に読まれたあと。*/
|
|
795 static void
|
|
796 rd_ctrl (readfile, sptr)
|
|
797 register FILE *readfile;
|
|
798 char **sptr;
|
|
799 {
|
|
800 int c;
|
|
801
|
|
802 if (!(' ' <= (c = chkchar_getc (readfile)) && c < '\177'))
|
|
803 ERRMOD (7);
|
|
804 if (c == '?')
|
|
805 c = '\177';
|
|
806 else
|
|
807 c &= 0x1f;
|
|
808
|
|
809 sprintf (*sptr, "\\%o;", c);
|
|
810 strtail (*sptr);
|
|
811 }
|
|
812
|
|
813 /** モード表の一かたまり(リスト、ファイル名、モード表示文字列)を
|
|
814 切り出す。その際、特殊な表記('^','\'による)は、'\(8進);' の
|
|
815 形に直す。flgが非0なら、EOFでエラーを起こし、')'で0を返す。*/
|
|
816 static int
|
|
817 read1tm (sptr, flg)
|
|
818 char **sptr; /* モード表の内部表現の列へのポインタへのポインタ。
|
|
819 rd_bcksla()、rd_ctrl()、codeeval()でも同様 */
|
|
820 int flg;
|
|
821 {
|
|
822 int c, err, retval = 1;
|
|
823 char *s;
|
|
824
|
|
825 s = *sptr;
|
|
826
|
|
827 while ((c = fspcpass ()) == ';')
|
|
828 {
|
|
829 /* 注釈文を検出したら、行末までとばして再試行。 */
|
|
830 while ((c = chkchar_getc (modefile)) != '\n' && c != EOF);
|
|
831 }
|
|
832
|
|
833 switch (c)
|
|
834 {
|
|
835 case '\0': /* EOFを表す */
|
|
836 if (flg)
|
|
837 ERRMOD (0);
|
|
838 else
|
|
839 retval = 0;
|
|
840 break;
|
|
841 case ')':
|
|
842 if (flg)
|
|
843 retval = 0;
|
|
844 else
|
|
845 ERRMOD (1);
|
|
846 break;
|
|
847 case '(':
|
|
848 *s++ = c;
|
|
849 *s++ = ' ';
|
|
850 while (read1tm (&s, 1))
|
|
851 *s++ = ' ';
|
|
852 *s++ = ')';
|
|
853 break;
|
|
854 case '"':
|
|
855 *s++ = c;
|
|
856 while ((c = chkchar_getc (modefile)) != '"')
|
|
857 {
|
|
858 switch (c)
|
|
859 {
|
|
860 case EOF:
|
|
861 ERRMOD (0);
|
|
862 case '\\':
|
|
863 rd_bcksla (modefile, &s);
|
|
864 break;
|
|
865 case '^':
|
|
866 rd_ctrl (modefile, &s);
|
|
867 break;
|
|
868 default:
|
|
869 *s++ = c;
|
|
870 }
|
|
871 }
|
|
872 *s++ = '"';
|
|
873 break;
|
|
874 default:
|
|
875 ungetc (c, modefile);
|
|
876 /* 先頭が @ 又は ~ の時は、特殊処理。 */
|
|
877 err = readfnm (modehyo_getc, modehyo_ungetc, rd_str_from_modefile, &s, &c);
|
|
878 if (err)
|
|
879 {
|
|
880 mcurread = s;
|
|
881 switch (err)
|
|
882 {
|
|
883 case 1:
|
|
884 case 3:
|
|
885 ERRMOD (13);
|
|
886 case 2:
|
|
887 ERRMOD (14);
|
|
888 case 4:
|
|
889 ERRMOD (15);
|
|
890 }
|
|
891 }
|
|
892
|
|
893 if (c == EOF && flg)
|
|
894 ERRMOD (0);
|
|
895 if (c == ')' && !flg)
|
|
896 ERRMOD (1);
|
|
897 }
|
|
898
|
|
899 *s = '\0';
|
|
900 *sptr = s;
|
|
901 return (retval);
|
|
902 }
|
|
903
|
|
904 /** 8・10・16進コード用のキャラクタを実際のコードに直す。入力のチェックは
|
|
905 しない。*/
|
|
906 static int
|
|
907 ctov (c)
|
|
908 char c;
|
|
909 {
|
|
910 if (is_upper (c))
|
|
911 return (c - 'A' + 10);
|
|
912 if (is_lower (c))
|
|
913 return (c - 'a' + 10);
|
|
914 return (c - '0');
|
|
915 }
|
|
916
|
|
917 /** リストの中身のscanに専用。')'で0を返す。EOLは来ないはず。
|
|
918 flg == 1 のとき、取り出しに失敗したらエラー。
|
|
919 flg == 2 のとき、取り出しに成功したらエラー。
|
|
920 特殊なコード表記は既に全て '\(8進);' の形に直っている筈。*/
|
|
921 static int
|
|
922 scan1tm (socp, dest, flg)
|
|
923 char **socp, *dest;
|
|
924 /* socpの指しているポインタが指している所から取り出してdestに入れる。
|
|
925 その後、socpが指しているポインタを進める。 */
|
|
926 int flg;
|
|
927 {
|
|
928 char c;
|
|
929 int retval = 1;
|
|
930
|
|
931 while (c = *(*socp)++, is_nulsp (c))
|
|
932 if (c == '\0')
|
|
933 ERRMOD (6);
|
|
934 switch (c)
|
|
935 {
|
|
936 case ')':
|
|
937 retval = 0;
|
|
938 break;
|
|
939 case '(':
|
|
940 *dest++ = c;
|
|
941 *dest++ = ' ';
|
|
942 while (scan1tm (socp, dest, 0))
|
|
943 {
|
|
944 strtail (dest);
|
|
945 *dest++ = ' ';
|
|
946 }
|
|
947 *dest++ = ')';
|
|
948 break;
|
|
949 case '"':
|
|
950 *dest++ = c;
|
|
951 while ((c = *dest++ = *(*socp)++) != '"')
|
|
952 {
|
|
953 if (c == '\\')
|
|
954 { /* '\(8進);'の解釈 */
|
|
955 while (c = *dest++ = *(*socp)++, is_octal (c));
|
|
956 }
|
|
957 }
|
|
958 break;
|
|
959 default:
|
|
960 *dest++ = c;
|
|
961 while (!is_nulsp (**socp))
|
|
962 *dest++ = *(*socp)++;
|
|
963 }
|
|
964
|
|
965 *dest = '\0';
|
|
966 if ((flg == 1 && retval == 0) || (flg == 2 && retval == 1))
|
|
967 ERRMOD (6);
|
|
968 return (retval);
|
|
969 }
|
|
970
|
|
971 /** モード名として正当かチェック。英数字からなっていればいい */
|
|
972 static int
|
|
973 modnamchk (s)
|
|
974 char *s;
|
|
975 {
|
|
976 if (is_digit (*s))
|
|
977 return (0);
|
|
978 for (; *s; s++)
|
|
979 if (!is_alnum (*s) && *s != '_')
|
|
980 return (0);
|
|
981 return (1);
|
|
982 }
|
|
983
|
|
984 #define modu1(a, b) ((b) ? ((a) % (b)) : (a))
|
|
985 #define curmod(num) (modesw[num] . curmode)
|
|
986 #define modrng(num) (modesw[num] . moderng)
|
|
987
|
|
988 /** num番目のモードをチェンジし、変換表を選択し直す。引数 mode の値が0なら
|
|
989 モードをoff、1ならonすることになる。なお、旧modeの値を返す。*/
|
|
990 /* *INDENT-OFF* */
|
|
991 modetyp
|
|
992 chgmod (num, mode)
|
|
993 int num;
|
|
994 modetyp mode;
|
|
995 /* *INDENT-ON* */
|
|
996 {
|
|
997 modetyp oldmod;
|
|
998
|
|
999 oldmod = curmod (num);
|
|
1000 curmod (num) = modu1 (mode, modrng (num));
|
|
1001 choosehyo ();
|
|
1002 return (oldmod);
|
|
1003 }
|
|
1004
|
|
1005 /** 全モードをまとめて切り替える */
|
|
1006 void
|
|
1007 allchgmod (mode)
|
|
1008 modetyp mode;
|
|
1009 {
|
|
1010 int i;
|
|
1011
|
|
1012 for (i = 0; modmeibgn[i] != NULL; i++)
|
|
1013 {
|
|
1014 curmod (i) = modu1 (mode, modrng (i));
|
|
1015 }
|
|
1016 choosehyo ();
|
|
1017 }
|
|
1018
|
|
1019 /** num番目のモードを指定した数だけインクリメントし、旧modeの値を返す。*/
|
|
1020 /* *INDENT-OFF* */
|
|
1021 modetyp
|
|
1022 incmod (num, dmode)
|
|
1023 int num;
|
|
1024 modetyp dmode;
|
|
1025 /* *INDENT-ON* */
|
|
1026 {
|
|
1027 modetyp oldmod, newmod;
|
|
1028
|
|
1029 newmod = oldmod = curmod (num);
|
|
1030 newmod += dmode;
|
|
1031 if (oldmod > newmod)
|
|
1032 newmod -= modrng (num);
|
|
1033 return (chgmod (num, newmod));
|
|
1034 }
|
|
1035
|
|
1036 /** num番目のモードを指定した数だけデクリメントし、旧modeの値を返す。都合
|
|
1037 により、incmodとは別に用意しなくてはならない。*/
|
|
1038 /* *INDENT-OFF* */
|
|
1039 modetyp
|
|
1040 decmod (num, dmode)
|
|
1041 int num;
|
|
1042 modetyp dmode;
|
|
1043 /* *INDENT-ON* */
|
|
1044 {
|
|
1045 modetyp oldmod, newmod;
|
|
1046
|
|
1047 newmod = oldmod = curmod (num);
|
|
1048 newmod -= dmode;
|
|
1049 if (oldmod < newmod)
|
|
1050 newmod += modrng (num);
|
|
1051 return (chgmod (num, newmod));
|
|
1052 }
|
|
1053
|
|
1054 /** nameの名のモードがなければ非0を返し、あればそのモード番号・及びその
|
|
1055 状態の最大値+1と現在の状態を取ってくる */
|
|
1056 int
|
|
1057 romkan_getmode (name, nump, modep, moderngp)
|
|
1058 char *name;
|
|
1059 int *nump;
|
|
1060 modetyp *modep, *moderngp;
|
|
1061 {
|
|
1062 if (!modnam_src (name, nump))
|
|
1063 return (-1);
|
|
1064 *modep = curmod (*nump);
|
|
1065 *moderngp = modrng (*nump);
|
|
1066 return (0);
|
|
1067 }
|
|
1068
|
|
1069 /** nameの名のモードがなければ非0を返し、あればその状態をセットして
|
|
1070 変換表を再選択の後、旧状態を取り込んで0を返す。*/
|
|
1071 int
|
|
1072 romkan_setmode (name, modep)
|
|
1073 char *name;
|
|
1074 modetyp *modep;
|
|
1075 {
|
|
1076 modetyp oldmode, moderng;
|
|
1077 int modenum;
|
|
1078
|
|
1079 if (romkan_getmode (name, &modenum, &oldmode, &moderng) != 0)
|
|
1080 return (-1);
|
|
1081 chgmod (modenum, *modep);
|
|
1082 *modep = oldmode;
|
|
1083 return (0);
|
|
1084 }
|
|
1085
|
|
1086 /** 変換表のクリア */
|
|
1087 void
|
|
1088 romkan_reset ()
|
|
1089 {
|
|
1090 naibu_[0] = Terminator;
|
|
1091 choosehyo ();
|
|
1092 romkan_clear ();
|
|
1093 }
|
|
1094
|
|
1095 /** 変換対応表の選択を行う */
|
|
1096 void
|
|
1097 choosehyo ()
|
|
1098 {
|
|
1099 int *naibup, i;
|
|
1100
|
|
1101 naibup = naibu_;
|
|
1102 usemaehyo[0] = usehyo[0] = useatohyo[0] = -1;
|
|
1103 for (i = 0; i < 2; i++)
|
|
1104 {
|
|
1105 dspmod[1][i] = dspmod[0][i];
|
|
1106 dspmod[0][i] = NULL;
|
|
1107 }
|
|
1108
|
|
1109 look_choose (&naibup, 1);
|
|
1110 }
|
|
1111
|
|
1112 /** モード表の内部形式を順次見ていき、使用表の選択及びモード表示文字列の
|
|
1113 選択を行っていく。但しflgが0ならスキップするだけ */
|
|
1114 static void
|
|
1115 look_choose (naibupp, flg)
|
|
1116 int **naibupp; /* モード表の内部表現の列へのポインタへのポインタ。
|
|
1117 look_cond()、evlcond()でも同様 */
|
|
1118 int flg;
|
|
1119 {
|
|
1120 int *naibup, naibu1, naibu2, branch, lcrsl;
|
|
1121
|
|
1122 naibup = *naibupp;
|
|
1123
|
|
1124 while ((naibu1 = *naibup++) != Terminator)
|
|
1125 {
|
|
1126 switch (SHUBET (naibu1))
|
|
1127 {
|
|
1128 case 4: /* 表名 */
|
|
1129 if (flg)
|
|
1130 hyouse (LWRMSK (naibu1));
|
|
1131 break;
|
|
1132 case 2: /* 条件式 */
|
|
1133 branch = LWRMSK (naibu1); /* if;when */
|
|
1134 lcrsl = look_cond (&naibup, flg);
|
|
1135 if (branch == 0 && lcrsl)
|
|
1136 flg = 0;
|
|
1137 break;
|
|
1138 case 5: /* romkanがon・off時それぞれの
|
|
1139 モード表示文字列 */
|
|
1140 naibu2 = *naibup++;
|
|
1141 if (flg)
|
|
1142 dspmod[0][LWRMSK (naibu1)] = dspnambgn[naibu2];
|
|
1143 break;
|
|
1144 case 6: /* romkanがそれぞれon・off時のモード表示
|
|
1145 文字列を前のままに */
|
|
1146 if (flg)
|
|
1147 dspmod[0][LWRMSK (naibu1)] = dspmod[1][LWRMSK (naibu1)];
|
|
1148 break;
|
|
1149 default:
|
|
1150 BUGreport (6);
|
|
1151 }
|
|
1152 }
|
|
1153
|
|
1154 *naibupp = naibup;
|
|
1155 }
|
|
1156
|
|
1157 /** *naibupp が、内部表現の列で条件式を表すところを指している筈なので、
|
|
1158 それを評価し、真ならその続きを解釈しにいく。偽なら読み飛ばす。
|
|
1159 返値は、最初に評価した条件式の真偽値。*/
|
|
1160 static int
|
|
1161 look_cond (naibupp, flg)
|
|
1162 int **naibupp, flg;
|
|
1163 {
|
|
1164 int *naibup, condrsl;
|
|
1165
|
|
1166 naibup = *naibupp;
|
|
1167
|
|
1168 condrsl = evlcond (&naibup); /* 必ず評価しないといけないため */
|
|
1169 flg = flg && condrsl;
|
|
1170 look_choose (&naibup, flg);
|
|
1171
|
|
1172 *naibupp = naibup;
|
|
1173 return (flg);
|
|
1174 }
|
|
1175
|
|
1176 /** 条件式の真偽値の評価 返値は0か1とは限らんぞ */
|
|
1177 static int
|
|
1178 evlcond (naibupp)
|
|
1179 int **naibupp;
|
|
1180 {
|
|
1181 int *naibup, naibu1, retval = -1, tmpval[ARGMAX], i, imax;
|
|
1182
|
|
1183 naibup = *naibupp;
|
|
1184
|
|
1185 naibu1 = *naibup++;
|
|
1186 switch (SHUBET (naibu1))
|
|
1187 {
|
|
1188 case 7: /* 数値 */
|
|
1189 retval = *naibup++;
|
|
1190 break;
|
|
1191 case 1: /* モード名 */
|
|
1192 retval = modesw[LWRMSK (naibu1)].curmode;
|
|
1193 break;
|
|
1194 case 3: /* andなど */
|
|
1195 imax = condarg[LWRMSK (naibu1)];
|
|
1196 for (i = 0; i < imax; i++)
|
|
1197 tmpval[i] = evlcond (&naibup);
|
|
1198 switch (LWRMSK (naibu1))
|
|
1199 {
|
|
1200 /* 上から順にtrue,false,not,and,or */
|
|
1201 case 0:
|
|
1202 retval = !tmpval[0];
|
|
1203 break;
|
|
1204 case 1:
|
|
1205 retval = tmpval[0] && tmpval[1];
|
|
1206 break;
|
|
1207 case 2:
|
|
1208 retval = tmpval[0] || tmpval[1];
|
|
1209 break;
|
|
1210 case 3:
|
|
1211 retval = 1;
|
|
1212 break;
|
|
1213 case 4:
|
|
1214 retval = 0;
|
|
1215 break;
|
|
1216 case 5:
|
|
1217 retval = (tmpval[0] == tmpval[1]);
|
|
1218 break;
|
|
1219 case 6:
|
|
1220 retval = (tmpval[0] != tmpval[1]);
|
|
1221 break;
|
|
1222 case 7:
|
|
1223 retval = ((unsigned int) tmpval[0] < (unsigned int) tmpval[1]);
|
|
1224 break;
|
|
1225 case 8:
|
|
1226 retval = ((unsigned int) tmpval[0] > (unsigned int) tmpval[1]);
|
|
1227 break;
|
|
1228 }
|
|
1229 break;
|
|
1230 }
|
|
1231
|
|
1232 *naibupp = naibup;
|
|
1233 return (retval);
|
|
1234 }
|
|
1235
|
|
1236 /** num番目の表を、使用するものとして登録する。前・本・後処理の区別もする */
|
|
1237 static void
|
|
1238 hyouse (num)
|
|
1239 int num;
|
|
1240 {
|
|
1241 int *ptr;
|
|
1242
|
|
1243 switch (hyoshu[num])
|
|
1244 {
|
|
1245 case 1:
|
|
1246 ptr = usemaehyo;
|
|
1247 break;
|
|
1248 case 2:
|
|
1249 ptr = usehyo;
|
|
1250 break;
|
|
1251 case 3:
|
|
1252 ptr = useatohyo;
|
|
1253 break;
|
|
1254 default:
|
|
1255 BUGreport (11);
|
|
1256 return;
|
|
1257 }
|
|
1258 for (; *ptr != -1; ptr++)
|
|
1259 if (*ptr == num)
|
|
1260 return;
|
|
1261 *ptr = num;
|
|
1262 *++ptr = -1;
|
|
1263 }
|
|
1264
|
|
1265 /** strcmpと同等 但し、'\(8進);'も解釈する。*/
|
|
1266 static int
|
|
1267 mystrcmp (s1, s2)
|
|
1268 char *s1, *s2;
|
|
1269 {
|
|
1270 char c1, c2;
|
|
1271
|
|
1272 while ((c1 = codeeval (&s1)) == (c2 = codeeval (&s2)))
|
|
1273 if (c1 == '\0')
|
|
1274 return (0);
|
|
1275 return (c1 > c2 ? 1 : -1);
|
|
1276 }
|
|
1277
|
|
1278 /** strcpyと同等 但し'\(8進);'も解釈する。s1 <= s2なら正常動作するはず */
|
|
1279 static void
|
|
1280 mystrcpy (s1, s2)
|
|
1281 char *s1, *s2;
|
|
1282 {
|
|
1283 while (*s1++ = codeeval (&s2));
|
|
1284 }
|
|
1285
|
|
1286 /** 一文字の解釈を行う。普通の文字はそのまま、'\(8進);'は実際のコードに
|
|
1287 直す。その後、文字列へのポインタを一文字分進めておく(少なくとも
|
|
1288 1バイト分進むことが保証されるはず)。*/
|
|
1289 static char
|
|
1290 codeeval (sptr)
|
|
1291 register char **sptr;
|
|
1292 {
|
|
1293 register char c;
|
|
1294 char code = 0;
|
|
1295
|
|
1296 if ((c = *(*sptr)++) != '\\')
|
|
1297 return (c);
|
|
1298 while (c = *(*sptr)++, is_octal (c))
|
|
1299 {
|
|
1300 code <<= 3;
|
|
1301 code += ctov (c);
|
|
1302 }
|
|
1303 if (c != ';')
|
|
1304 BUGreport (12);
|
|
1305 return (code);
|
|
1306 }
|
|
1307
|
|
1308 /** romkanがon時のモード表示文字列を返す関数。無指定であってRK_DSPNILフラグが
|
|
1309 立っている時は空文字列を返す。*/
|
|
1310
|
|
1311 char *
|
|
1312 romkan_dispmode ()
|
|
1313 {
|
|
1314 return (dspmod[0][0] == NULL && (flags & RK_DSPNIL) ? nulstr : dspmod[0][0]);
|
|
1315 }
|
|
1316
|
|
1317 /** romkanがoff時のモード表示文字列を返す関数。無指定であってRK_DSPNILフラグ
|
|
1318 が立っている時は空文字列を返す。*/
|
|
1319 char *
|
|
1320 romkan_offmode ()
|
|
1321 {
|
|
1322 return (dspmod[0][1] == NULL && (flags & RK_DSPNIL) ? nulstr : dspmod[0][1]);
|
|
1323 }
|
|
1324
|
|
1325 /** 文字列が10進整数ならその解釈をし、そうでなければ非0を返す */
|
|
1326 static int
|
|
1327 chk_get_int (p, ip, range)
|
|
1328 char *p;
|
|
1329 unsigned int *ip;
|
|
1330 modetyp range;
|
|
1331 {
|
|
1332 int sgn = 1;
|
|
1333 modetyp out;
|
|
1334
|
|
1335 if (*p == '-')
|
|
1336 {
|
|
1337 p++;
|
|
1338 sgn = -1;
|
|
1339 }
|
|
1340 for (out = 0; *p; p++)
|
|
1341 {
|
|
1342 if (!is_digit (*p))
|
|
1343 return (-1);
|
|
1344 out *= 10;
|
|
1345 out += ctov (*p);
|
|
1346 }
|
|
1347 if (range != 0)
|
|
1348 out %= range;
|
|
1349 if (sgn == -1 && out != 0)
|
|
1350 out = range - out;
|
|
1351 *ip = out;
|
|
1352 return (0);
|
|
1353 }
|