Mercurial > freewnn
view Xwnmo/romkan_m/rk_modread.c @ 23:e1aadb6dcbd4
- fixed the build rule for build_stamp.h. keywords in template for hg tip should surrounded by curly braces instead of hash marks.
- fixed usage of libtool in building jlib.V3. newer libtool does not work without mode specifier.
- replaced some libtool related files. (should remove these?)
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Fri, 23 Jan 2009 16:36:13 +0900 |
parents | bbc77ca4def5 |
children |
line wrap: on
line source
/* * $Id: rk_modread.c,v 1.2 2001/06/14 18:16:10 ura Exp $ */ /* * FreeWnn is a network-extensible Kana-to-Kanji conversion system. * This file is part of FreeWnn. * * Copyright Kyoto University Research Institute for Mathematical Sciences * 1987, 1988, 1989, 1990, 1991, 1992 * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999 * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992 * * Author: OMRON SOFTWARE Co., Ltd. <freewnn@rd.kyoto.omronsoft.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Emacs; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Commentary: * * Change log: * * Last modified date: 8,Feb.1999 * * Code: * */ /*********************************************************************** rk_modread.c 87.11.17 改 正 モード定義表の読み込みを担当するプログラム。 ***********************************************************************/ /* Version 3.1 88/06/15 H.HASHIMOTO */ #ifndef OMRON_LIB #include "rk_header.h" #include "rk_extvars.h" #ifdef MULTI #include "rk_multi.h" #endif /*MULTI*/ #include <sys/types.h> #include <sys/stat.h> #include "rext.h" #ifdef WNNDEFAULT # include "config.h" /* マクロLIBDIRの定義(のためだけ)。コンパイル時は、ヘッダファイルの サーチパスに、Wnnのインクルードファイルのありかを設定しておくこと。 */ #endif #include <pwd.h> #endif #define xyint(X, Y) (((X) << 24) | (Y)) #define Terminator 0 /* intの列(naibu[])の終止コード */ #ifdef OMRON_SPEC #define mystrcmp(s1, s2) strcmp(s1, s2) #define mystrcpy(s1, s2) strcpy(s1, s2) #endif static void cond_evl (), rd_bcksla (), rd_ctrl (), look_choose (), hyouse (), mystrcpy (), ERMOPN (), ERRMOD (); static int mystrcmp (), mod_evl (), fnmsrc_tourk (), pathsrc_tourk (), dspnamsrc_tourk (), modsrc_tourk (), chkchar_getc (), read1tm (), get_hmdir (), rd_string (), ctov (), scan1tm (), modnamchk (), look_cond (), evlcond (); static char codeeval (), *ename (); extern char *chrcat (), *strend (); #ifndef MULTI /* 88/05/31 V3.1 */ static FILE *modefile; /* モード定義表の fp */ /* 88/06/03 V3.1 */ /* エラー処理のためのもの */ static char *mcurdir; /* モード表のサーチパス */ static char *mcurfnm; /* モード表のファイル名 */ static char *mcurread; /* モード表の現在行bufへのポインタ */ #endif /*!MULTI */ /* キーワードとその内部表現の対応を与える構造体。内部表現を 持たないものに対しては0が与えられている。*/ struct kwdpair { char *name; int code; }; static /* V3.1 */ struct kwdpair modfn[] = { "defmode", 0, "if", xyint (2, 0), "when", xyint (2, 1), "path", 0, "search", 0, "on_dispmode", xyint (5, 0), "off_dispmode", xyint (5, 1), "on_unchg", xyint (6, 0), "off_unchg", xyint (6, 1), NULL }; /* 下を見よ キーワード定義表はまだあと二つあるのだ */ static /* V3.1 */ struct kwdpair modcond[] = { "not", xyint (3, 0), "and", xyint (3, 1), "or", xyint (3, 2), "true", xyint (3, 3), "false", xyint (3, 4), "=", xyint (3, 5), "!=", xyint (3, 6), "<", xyint (3, 7), ">", xyint (3, 8), NULL }; static /* V3.1 */ int condarg[] = { 1, 2, 2, 0, 0, 2, 2, 2, 2 }; /* 条件判断関数の引数の個数 */ static /* V3.1 */ struct kwdpair swstat[] = { "on", 0, "off", 0, NULL }; /** キーワード(if, andなど)が正当なものかチェックし、その番号を返す */ static /* V3.1 */ int kwdsrc (hyou, wd) struct kwdpair *hyou; /* どのキーワード表を使うか */ char *wd; /* チェックされるキーワード */ { fast int i; /* V3.1 */ for (i = 0; hyou[i].name != NULL; i++) if (!mystrcmp (hyou[i].name, wd)) return (i); ERRMOD (9); /*NOTREACHED*/ return (-1); } /** 与えられたファイルがディレクトリなら非0を返す */ static /* V3.1 */ int isdir (fnm) char *fnm; { struct stat statbuf; /* Bug!!! 88/07/20 H.HASHIMOTO */ /* return(stat(fnm, &statbuf) == 0 && (statbuf.st_mode & S_IFDIR)); */ return (stat (fnm, &statbuf) == 0 && ((statbuf.st_mode & S_IFMT) == S_IFDIR)); } /* 88/06/10 V3.1 */ /** モード表の読み込み */ #ifdef OMRON_LIB static #endif int readmode (filename) char *filename; /* ユーザが指定したモード表の名 */ { #ifndef MULTI char modefilename[REALFN + 5]; /* V3.1 */ char pathname[REALFN]; /* V3.1 */ #endif /*!MULTI */ struct stat statbuf; /* V3.1 */ char *buf, *bufp; /* V3.1 */ #ifdef RKMODPATH char *genv, *pathenv, *pathp; extern char *getenv (); /* V3.1 */ #endif /* 88/06/14 V3.1 */ /* モード定義表のパス名の長さチェックを安全性のために、 付け加えておきます。 */ cur_rk_table->mcurdir = ""; /* エラー処理用 *//* V3.1 */ if (strlen (cur_rk_table->mcurfnm = filename) > (REALFN - 1)) /* V3.1 */ ERMOPN (3); /* V3.1 */ strcpy (cur_rk_table->modefilename, filename); if (*(cur_rk_table->modefilename) == '\0' || *(strend (cur_rk_table->modefilename)) == KUGIRI) { strcat (cur_rk_table->modefilename, "mode"); } else if (isdir (cur_rk_table->modefilename)) { chrcat (cur_rk_table->modefilename, KUGIRI); strcat (cur_rk_table->modefilename, "mode"); } /* 88/06/14 V3.1 */ if (strlen (cur_rk_table->mcurfnm = cur_rk_table->modefilename) > (REALFN - 1)) /* V3.1 */ ERMOPN (3); /* V3.1 */ #ifdef RKMODPATH /* 88/06/10 V3.1 */ if (!fixednamep (cur_rk_table->modefilename) && (pathenv = genv = getenv (RKMODPATH)) != NULL && *genv != '\0') { /* PATHに少なくとも一つのサーチパスがある場合 */ for (;;) { for (pathp = cur_rk_table->pathname; *genv != ':' && *genv; genv++) *pathp++ = *genv; *pathp = '\0'; if (*(strend (cur_rk_table->pathname)) != KUGIRI) *pathp++ = KUGIRI; /* pathの区切りはDG(MV)であっても'/' */ strcpy (pathp, cur_rk_table->modefilename); if ((stat (cur_rk_table->pathname, &statbuf) == 0) && ((cur_rk_table->modefile = fopen (cur_rk_table->pathname, "r")) != NULL)) { /* Now Mode-hyo found */ /* if (cur_rk->flags & RK_VERBOS) { fprintf(stderr, "romkan: using Mode-hyo %s ...\r\n", pathname); } */ cur_rk_table->mcurdir = cur_rk_table->pathname; /* この時点ではファイル名込みだが、 あとでパス名だけになる */ cur_rk_table->mcurfnm = ename (cur_rk_table->modefilename); /* V3.1 */ break; } if (*genv != ':') { /* Mode-hyo not found */ /* if (flags & RK_VERBOS){ fprintf(stderr, "no %s in ",cur_rk->modefilename); for(genv = pathenv; *genv; genv++){ fputc((*genv == ':' ? ' ' : *genv), stderr); } fprintf(stderr, ".\n"); } */ ERMOPN (1); } /* coutinues searching Mode-hyo */ genv++; } } else #endif { /* 88/06/10 V3.1 */ if (stat (cur_rk_table->modefilename, &statbuf) != 0) ERMOPN (1); if ((cur_rk_table->modefile = fopen (cur_rk_table->modefilename, "r")) == NULL) ERMOPN (2); /* if (cur_rk->flags & RK_VERBOS) { fprintf(stderr, "romkan: using Mode-hyo %s ...\r\n", cur_rk->modefilename); } */ strcpy (cur_rk_table->pathname, cur_rk_table->modefilename); } /* サーチパスの先頭に、モード表のあるディレクトリを設定している。 */ *(ename (cur_rk_table->pathname)) = '\0'; /* V3.1 */ pathsrc_tourk (cur_rk_table->pathname); /* V3.1 */ /* 88/06/14 V3.1 */ malloc_for_modenaibu (&(cur_rk_table->rk_modenaibu), statbuf.st_size + 1); *(cur_rk_table->rk_modenaibu.next) = Terminator; malloc_for_modebuf (&(cur_rk_table->rk_modebuf), statbuf.st_size + 1); cur_rk_table->mcurread = buf = cur_rk_table->rk_modebuf.org; /* エラー処理用 *//* V3.1 */ /* モード定義表の読み込み */ while (bufp = buf, read1tm (&bufp, 0)) /* V3.1 */ mod_evl (buf); /* V3.1 */ fclose (cur_rk_table->modefile); /* 88/06/14 V3.1 */ free_for_modebuf (&(cur_rk_table->rk_modebuf)); realloc_for_modenaibu (&(cur_rk_table->rk_modenaibu)); return (cur_rk_table->rk_taiouhyo.count); /* V3.1 */ } /** モード表の一かたまり(リスト、ファイル名、モード表示文字列)を 解釈する。返す値は、defmode,search及びpathの時0、それ以外なら1。*/ static /* V3.1 */ int mod_evl (s) char *s; /* モード表の内部表現の列へのポインタ */ { char md1[MDT1LN]; /* V3.1 */ fast char *bgn, *end; /* V3.1 */ fast int num, retval = 1; /* V3.1 */ if (*s != '(') { if (*s != '"') { num = fnmsrc_tourk (s); *(cur_rk_table->rk_modenaibu.next++) = xyint (4, num); } else { s++; if (*(end = strend (s)) != '"') ERRMOD (10); *end = '\0'; num = dspnamsrc_tourk (s); *(cur_rk_table->rk_modenaibu.next++) = xyint (5, 0); *(cur_rk_table->rk_modenaibu.next++) = num; } } else { s++; scan1tm (&s, md1, 1); switch (num = kwdsrc (modfn, md1)) { case 0: /* defmode */ retval = 0; scan1tm (&s, md1, 1); /* modename */ num = modsrc_tourk (md1, 0); if (scan1tm (&s, md1, 0)) { /* 初期on-off */ switch (kwdsrc (swstat, md1)) { case 0: cur_rk_table->rk_modesw.point[num] = 1; break; case 1: cur_rk_table->rk_modesw.point[num] = 0; break; } scan1tm (&s, md1, 2); /* あればerr */ } else cur_rk_table->rk_modesw.point[num] = 0; /* defaultはoff */ break; case 1: /* if */ case 2: /* when */ *(cur_rk_table->rk_modenaibu.next++) = modfn[num].code; scan1tm (&s, md1, 1); /* condition */ cond_evl (md1); while (scan1tm (&s, md1, 0)) { if (mod_evl (md1) == 0) ERRMOD (8); } *(cur_rk_table->rk_modenaibu.next++) = Terminator; break; case 3: /* path */ /* 88/06/09 V3.1 */ cur_rk_table->rk_path.count = 1; cur_rk_table->rk_path.next = cur_rk_table->rk_path.point[1]; case 4: /* search */ retval = 0; /* 88/06/29 V3.1 */ if (cur_rk_table->rk_taiouhyo.point[0] != NULL) ERRMOD (11); /* サーチパスの指定はファイル名の出現より 先行しなければならないとしておく。 */ while (scan1tm (&s, md1, 0)) { /* find pathname */ pathsrc_tourk (md1); } break; case 5: /* on_dispmode */ case 6: /* off_dispmode */ *(cur_rk_table->rk_modenaibu.next++) = modfn[num].code; scan1tm (&s, md1, 1); /* dispmode string */ if (*(bgn = md1) != '"') ERRMOD (12); bgn++; if (*(end = strend (bgn)) != '"') ERRMOD (10); *end = '\0'; *(cur_rk_table->rk_modenaibu.next++) = dspnamsrc_tourk (bgn); scan1tm (&s, md1, 2); /* あればerr */ break; case 7: /* on-unchg */ case 8: /* off-unchg */ *(cur_rk_table->rk_modenaibu.next++) = modfn[num].code; scan1tm (&s, md1, 2); /* あればerr */ break; } } *(cur_rk_table->rk_modenaibu.next) = Terminator; return (retval); } /** 条件式(モード名 又はnot,andなどの式)一つを解釈 */ static /* V3.1 */ void cond_evl (cod) char *cod; /* 条件式の内部表現の列へのポインタ */ { char md1[MDT1LN]; fast int num, i; /* V3.1 */ if (*cod != '(') { num = modsrc_tourk (cod, 1); *(cur_rk_table->rk_modenaibu.next++) = xyint (1, num); } else { cod++; scan1tm (&cod, md1, 1); /* not;and;or */ num = kwdsrc (modcond, md1); *(cur_rk_table->rk_modenaibu.next++) = xyint (3, num); for (i = condarg[num]; i; i--) { scan1tm (&cod, md1, 0); cond_evl (md1); } scan1tm (&cod, md1, 2); } *(cur_rk_table->rk_modenaibu.next) = Terminator; } /* 88/06/09 V3.1 */ static int serach_in_modetable_struct (ptr, s, np) fast modetable *ptr; fast char *s; fast int *np; { fast int n; for (n = 0; n < ptr->count; n++) { if (!mystrcmp (ptr->point[n], s)) { *np = n; return (1); /* found */ } } *np = n; return (0); /* not found */ } /* 88/06/13 V3.1 */ static void entry_to_modetable_struct (ptr, n, s) fast modetable *ptr; int n; char *s; { ptr->point[n] = ptr->next; mystrcpy (ptr->next, s); strtail (ptr->next); ++(ptr->next); } /* 88/06/07 V3.1 */ /** sで指定されたファイル名が既登録か探し、なければ登録。但し、既登録か どうかのチェックは厳密ではないが(例えば、同じファイルでも、 パス名付きと無しとでは、同じと見ない)、ファイル名が既登録かどうか チェックするのは、メモリ節約のために同じ表を読み込むのを防ぐため だけなので、それ以外には別に困る点はない。*/ static /* V3.1 */ int fnmsrc_tourk (s) char *s; { int n; if (serach_in_modetable_struct (&(cur_rk_table->rk_taiouhyo), s, &n)) return (n); check_and_realloc_for_modetable_struct (&(cur_rk_table->rk_taiouhyo), n, s, RK_TAIOUHYO_MAX_LOT, RK_TAIOUHYO_MEM_LOT); /* チェックのみ */ if (!(filnamchk (s))) ERRMOD (3); entry_to_modetable_struct (&(cur_rk_table->rk_taiouhyo), n, s); return (n); } /* 88/06/07 V3.1 */ /** sで指定されたサーチパス名が既登録か探し、なければ登録。但し、fnmsrc_ tourk()同様、既登録かどうかのチェックは厳密ではないが問題ない。*/ /* 88/06/07 V3.1 */ static /* V3.1 */ int pathsrc_tourk (s) char *s; { int n; char fnm_addsla[MDT1LN]; mystrcpy (fnm_addsla, s); if (!(*fnm_addsla == '\0' || *(strend (fnm_addsla)) == KUGIRI)) chrcat (fnm_addsla, KUGIRI); s = fnm_addsla; /* パス名が'/'で終わってなければ、それを付加する。 */ if (serach_in_modetable_struct (&(cur_rk_table->rk_path), s, &n)) return (n); check_and_realloc_for_modetable_struct (&(cur_rk_table->rk_path), n, s, RK_PATH_MAX_LOT, RK_PATH_MEM_LOT); entry_to_modetable_struct (&(cur_rk_table->rk_path), n, s); return (n); } /* 88/06/07 V3.1 */ /** sで指定されたモード表示文字列が既登録か探し、なければ登録 */ static /* V3.1 */ int dspnamsrc_tourk (s) char *s; { int n; if (serach_in_modetable_struct (&(cur_rk_table->rk_dspmode), s, &n)) return (n); check_and_realloc_for_modetable_struct (&(cur_rk_table->rk_dspmode), n, s, RK_DSPMODE_MAX_LOT, RK_DSPMODE_MEM_LOT); entry_to_modetable_struct (&(cur_rk_table->rk_dspmode), n, s); return (n); } /* 88/06/09 V3.1 */ /** sで指定されたモード名を探し、なければ登録。但し、flgが非0なら、 見つからなければエラー */ static /* V3.1 */ int modsrc_tourk (s, flg) char *s; int flg; { int n; if (!modnamchk (s)) ERRMOD (4); /* V3.1 */ if (serach_in_modetable_struct (&(cur_rk_table->rk_defmode), s, &n)) return (n); if (flg) ERRMOD (5); check_and_realloc_for_modetable_struct (&(cur_rk_table->rk_defmode), n, s, RK_DEFMODE_MAX_LOT, RK_DEFMODE_MEM_LOT); check_and_realloc_for_modesw (&(cur_rk_table->rk_modesw), n, RK_DEFMODE_MAX_LOT, RK_DEFMODE_MEM_LOT); entry_to_modetable_struct (&(cur_rk_table->rk_defmode), n, s); return (n); } /** ファイルから一文字読む(空白文字は飛ばす)。読んだ文字がEOFなら0を返す */ static /* V3.1 */ char fspcpass () { fast int c; /* V3.1 */ while (EOF != (c = chkchar_getc (cur_rk_table->modefile)) && is_nulsp (c)); return (c == EOF ? '\0' : c); } /** モード表には空白文字以外のコントロール文字は生では混じらないものと する。混じっていた場合はチェックしつつ、getcを行う。*/ static /* V3.1 */ int chkchar_getc (f) fast FILE *f; { fast int c; /* V3.1 */ c = getc (f); if (is_cntrl (c) && !isspace (c)) { sprintf (cur_rk_table->mcurread, "\\%03o", c); ERRMOD (16); } return (c); } /** モード表の一かたまり(リスト、ファイル名、モード表示文字列)を 切り出す。その際、特殊な表記('^','\'による)は、'\(8進);' の 形に直す。flgが非0なら、EOFでエラーを起こし、')'で0を返す。*/ static /* V3.1 */ int read1tm (sptr, flg) char **sptr; /* モード表の内部表現の列へのポインタへのポインタ。 rd_bcksla()、rd_ctrl()、codeeval()でも同様 */ int flg; { fast int c; /* V3.1 */ fast char *head; /* V3.1 */ int retval = 1; /* V3.1 */ char *s; /* V3.1 */ s = *sptr; while ((c = fspcpass ()) == ';') { /* 注釈文を検出したら、行末までとばして再試行。 */ while ((c = chkchar_getc (cur_rk_table->modefile)) != '\n' && c != EOF); } switch (c) { case '\0': /* EOFを表す */ if (flg) ERRMOD (0); else retval = 0; break; case ')': if (flg) retval = 0; else ERRMOD (1); break; case '(': *s++ = c; *s++ = ' '; while (read1tm (&s, 1)) *s++ = ' '; *s++ = ')'; break; case '"': *s++ = c; while ((c = chkchar_getc (cur_rk_table->modefile)) != '"') { switch (c) { case EOF: ERRMOD (0); #ifndef OMRON_SPEC case '\\': rd_bcksla (&s); break; case '^': rd_ctrl (&s); break; #endif default: *s++ = c; } } *s++ = '"'; break; default: /* 先頭が @ 又は ~ の時は、特殊処理。 */ if (c == '@') { /* @HOME, @MODEDIR, @LIBDIR */ *s++ = c; head = s; rd_string (&s, 1); if (mystrcmp ("HOME", head) == 0) { s = --head; if (get_hmdir (&s, (char *) NULL) != 0) { cur_rk_table->mcurread = head; /* エラー表示の調整。抜けずにすぐにエラー表示 ルーチンに行くのでheadの中身は失われない。 */ ERRMOD (13); } } else if (mystrcmp ("MODEDIR", head) == 0) { /* 88/06/09 V3.1 */ strcpy (s = --head, cur_rk_table->rk_path.point[0]); if (KUGIRI == *(s = strend (s))) *s = '\0'; } else #ifdef WNNDEFAULT if (mystrcmp ("LIBDIR", head) == 0) { strcpy (s = --head, LIBDIR); strtail (s); } else #endif { cur_rk_table->mcurread = --head; ERRMOD (14); } } else if (c == '~') { /* ~user */ *s++ = c; head = s; rd_string (&s, 1); mystrcpy (head, head); s = head - 1; if ((get_hmdir (&s, (*head ? head : NULL))) != 0) { cur_rk_table->mcurread = --head; /* エラー表示の調整 */ ERRMOD (15); } } else { ungetc (c, cur_rk_table->modefile); } /* 先頭の特殊処理 終わり */ if ((c = rd_string (&s, 0)) == EOF && flg) ERRMOD (0); if (c == ')' && !flg) ERRMOD (1); } *s = '\0'; *sptr = s; return (retval); } /* 88/06/03 V3.1 */ /** socの名のユーザのログイン・ディレクトリ名をdestに入れ、*destにその末尾を 指させる。但しsocが空列または、NULLなら自分のログイン・ディレクトリ名、 いずれの場合も、不成功時は、何もしない。返値は、不成功時-1。*/ static /* V3.1 */ int get_hmdir (dest, soc) char **dest, *soc; { fast struct passwd *usr; /* V3.1 */ extern struct passwd *getpwnam (), *getpwuid (); /* V3.1 */ /* 88/05/26 V3.1 */ if (soc == NULL || *soc == '\0') { if (NULL == (usr = getpwuid (getuid ()))) return (-1); } else { if (NULL == (usr = getpwnam (soc))) return (-1); } strcpy (*dest, usr->pw_dir); strtail (*dest); return (0); } /** モード表・対応表中の、ファイル名の部分の読み込み。先頭が @ 又は ~ の 時は、特殊処理を行う。引数は、一字読み込み・一字戻し・文字列取り出しの 関数と、結果を入れるエリアの番地へのポインタ、次に読まれる文字を入れる ポインタ。返値は、正常終了時0、@HOMEでホーム・ディレクトリが取れない時 1、@のあとに変なものが来たら2、~で自分のホーム・ディレクトリが取れない 時3、~のあとに存在しないユーザ名が来たら4。*/ int readfnm (readchar_func, unreadc_func, readstr_func, areap, lastcptr) register int (*readchar_func) (), (*unreadc_func) (), (*readstr_func) (); char **areap; int *lastcptr; { char *head; register int c; c = (*readchar_func) (); if (c == '@') { /* @HOME, @MODEDIR, @LIBDIR */ *(*areap)++ = c; head = *areap; (*readstr_func) (areap, 1); if (mystrcmp ("HOME", head) == 0) { *areap = --head; if (get_hmdir (areap, (char *) NULL) != 0) { *areap = head; return (1); } } else if (mystrcmp ("MODEDIR", head) == 0) { strcpy (*areap = --head, cur_rk_table->pathname); if (KUGIRI == *(*areap = strend (*areap))) **areap = '\0'; } else #ifdef WNNDEFAULT if (mystrcmp ("LIBDIR", head) == 0) { strcpy (*areap = --head, LIBDIR); strtail (*areap); } else #endif { *areap = --head; return (2); } } else if (c == '~') { /* ~user */ int err; *(*areap)++ = c; head = *areap; (*readstr_func) (areap, 1); mystrcpy (head, head); *areap = head - 1; if ((err = get_hmdir (areap, (*head ? head : NULL))) != 0) { *areap = --head; return (err == -2 ? 3 : 4); } } else { (*unreadc_func) (c); } *lastcptr = (*readstr_func) (areap, 0); return (0); } /** モード表から一文字分取り出す作業を、空白・EOF・括弧のどれかが来るまで 続ける。flgが非0なら、'/'が来ても終わる。返値は、次に読まれる文字。*/ static /* V3.1 */ int rd_string (sptr, flg) char **sptr; int flg; { fast int c; /* V3.1 */ while (c = chkchar_getc (cur_rk_table->modefile), !(is_nulsp (c) || c == EOF || c == '(' || c == ')' || (flg == 1 && c == KUGIRI))) { switch (c) { #ifndef OMRON_SPEC case '\\': rd_bcksla (sptr); break; case '^': rd_ctrl (sptr); break; #endif default: *(*sptr)++ = c; } } **sptr = '\0'; return (ungetc (c, cur_rk_table->modefile)); } /* 88/06/02 V3.1 */ #ifndef OMRON_SPEC /** モード表からバックスラッシュ形式の一文字分を取り出し、'\(8進);' の 形に直す。但し、先頭の'\\'は既に読まれたあと。*/ static /* V3.1 */ void rd_bcksla (sptr) char **sptr; { fast int c, code = 0, digflg = 0; /* V3.1 */ switch (c = chkchar_getc (cur_rk_table->modefile)) { case 'n': code = '\n'; digflg = 1; break; case 't': code = '\t'; digflg = 1; break; case 'b': code = '\b'; digflg = 1; break; case 'r': code = '\r'; digflg = 1; break; case 'f': code = '\f'; digflg = 1; break; case 'e': case 'E': code = ESCCHR; digflg = 1; break; case 'o': while (c = chkchar_getc (cur_rk_table->modefile), is_octal (c)) { code <<= 3; code += ctov (c); digflg = 1; } if (c != ';') ungetc (c, cur_rk_table->modefile); break; case 'd': while (c = chkchar_getc (cur_rk_table->modefile), is_digit (c)) { code *= 10; code += ctov (c); digflg = 1; } if (c != ';') ungetc (c, cur_rk_table->modefile); break; case 'x': while (c = chkchar_getc (cur_rk_table->modefile), is_xdigit (c)) { code <<= 4; code += ctov (c); digflg = 1; } if (c != ';') ungetc (c, cur_rk_table->modefile); break; default: if (is_octal (c)) { digflg = 1; code = ctov (c); while (c = chkchar_getc (cur_rk_table->modefile), is_octal (c)) { code <<= 3; code += ctov (c); } if (c != ';') ungetc (c, cur_rk_table->modefile); } else { code = c; digflg = 1; } } if (digflg == 0) ERRMOD (7); sprintf (*sptr, "\\%o;", code); strtail (*sptr); } /** モード表からコントロールコード形式の一文字分を取り出し、'\(8進);' の 形に直す。但し、先頭の'^'は既に読まれたあと。*/ static /* V3.1 */ void rd_ctrl (sptr) char **sptr; { fast int c; /* V3.1 */ if (!(' ' <= (c = chkchar_getc (cur_rk_table->modefile)) && c < '\177')) ERRMOD (7); if (c == '?') c = '\177'; else c &= 0x1f; sprintf (*sptr, "\\%o;", c); strtail (*sptr); } #endif /** 8・10・16進コード用のキャラクタを実際のコードに直す。入力のチェックは しない。*/ static int ctov (c) fast char c; { if (is_upper (c)) return (c - 'A' + 10); if (is_lower (c)) return (c - 'a' + 10); return (c - '0'); } /** リストの中身のscanに専用。')'で0を返す。EOLは来ないはず。 flg == 1 のとき、取り出しに失敗したらエラー。 flg == 2 のとき、取り出しに成功したらエラー。 特殊なコード表記は既に全て '\(8進);' の形に直っている筈。*/ static /* V3.1 */ int scan1tm (socp, dest, flg) char **socp, *dest; /* socpの指しているポインタが指している所から取り出してdestに入れる。 その後、socpが指しているポインタを進める。 */ int flg; { fast char c; /* V3.1 */ fast int retval = 1; /* V3.1 */ while (c = *(*socp)++, is_nulsp (c)) if (c == '\0') ERRMOD (6); switch (c) { case ')': retval = 0; break; case '(': *dest++ = c; *dest++ = ' '; while (scan1tm (socp, dest, 0)) { strtail (dest); *dest++ = ' '; } *dest++ = ')'; break; case '"': *dest++ = c; while ((c = *dest++ = *(*socp)++) != '"') { if (c == '\\') { /* '\(8進);'の解釈 */ while (c = *dest++ = *(*socp)++, is_octal (c)); } } break; default: *dest++ = c; while (!is_nulsp (**socp)) *dest++ = *(*socp)++; } *dest = '\0'; if (flg == 1 && retval == 0 || flg == 2 && retval == 1) ERRMOD (6); return (retval); } /** モード名として正当かチェック。英数字からなっていればいい */ static /* V3.1 */ int modnamchk (s) fast char *s; /* V3.1 */ { if (is_digit (*s)) return (0); for (; *s; s++) { if (!is_alnum (*s)) { if (*s != '_') { return (0); } } } return (1); /* if(is_digit(*s)) return(0); for(; *s; s++) if(!is_alnum(*s) && *s != '_') return(0); return(1); */ } /** 変換対応表の選択を行う */ #ifdef OMRON_LIB static #endif void choosehyo () { fast int i; /* V3.1 */ int *naibup; /* V3.1 */ if (cur_rk->rk_usehyo.usehyo != NULL) cur_rk->rk_usehyo.usemaehyo[0] = cur_rk->rk_usehyo.usehyo[0] = cur_rk->rk_usehyo.useatohyo[0] = -1; for (i = 0; i < 2; i++) { cur_rk->dspmod[1][i] = cur_rk->dspmod[0][i]; cur_rk->dspmod[0][i] = NULL; } if ((naibup = cur_rk_table->rk_modenaibu.org) != NULL) look_choose (&naibup, 1); /* V3.1 */ } /** モード表の内部形式を順次見ていき、使用表の選択及びモード表示文字列の 選択を行っていく。但しflgが0ならスキップするだけ */ static /* V3.1 */ void look_choose (naibupp, flg) int **naibupp; /* モード表の内部表現の列へのポインタへのポインタ。 look_cond()、evlcond()でも同様 */ int flg; { fast int naibu1, naibu2, branch, lcrsl; /* V3.1 */ int *naibup; /* V3.1 */ naibup = *naibupp; while ((naibu1 = *naibup++) != Terminator) { switch (SHUBET (naibu1)) { case 4: /* 表名 */ if (flg) hyouse (LWRMSK (naibu1)); break; case 2: /* 条件式 */ branch = LWRMSK (naibu1); /* if;when */ lcrsl = look_cond (&naibup, flg); if (branch == 0 && lcrsl) flg = 0; break; case 5: /* romkanがon・off時それぞれの モード表示文字列 */ naibu2 = *naibup++; if (flg) cur_rk->dspmod[0][LWRMSK (naibu1)] = cur_rk_table->rk_dspmode.point[naibu2]; break; case 6: /* romkanがそれぞれon・off時のモード表示 文字列を前のままに */ if (flg) cur_rk->dspmod[0][LWRMSK (naibu1)] = cur_rk->dspmod[1][LWRMSK (naibu1)]; break; default: BUGreport (6); } } *naibupp = naibup; } /** *naibupp が、内部表現の列で条件式を表すところを指している筈なので、 それを評価し、真ならその続きを解釈しにいく。偽なら読み飛ばす。 返値は、最初に評価した条件式の真偽値。*/ static /* V3.1 */ int look_cond (naibupp, flg) int **naibupp, flg; { fast int condrsl; /* V3.1 */ int *naibup; naibup = *naibupp; /* 88/06/06 V3.1 */ condrsl = evlcond (&naibup); /* 必ず評価しないといけないため */ look_choose (&naibup, flg &= condrsl); *naibupp = naibup; return (flg); } /** 条件式の真偽値の評価 */ static /* V3.1 */ int evlcond (naibupp) int **naibupp; { int *naibup, tmpval[ARGMAX]; /* V3.1 */ fast int naibu1, retval = 0, imax; /* V3.1 */ fast int i; /* V3.1 */ naibup = *naibupp; naibu1 = *naibup++; switch (SHUBET (naibu1)) { case 7: /* 数値 */ retval = *naibup++; break; case 1: /* モード名 */ retval = cur_rk->rk_modesw.point[LWRMSK (naibu1)]; break; case 3: /* if;when */ imax = condarg[LWRMSK (naibu1)]; for (i = 0; i < imax; i++) tmpval[i] = evlcond (&naibup); switch (LWRMSK (naibu1)) { /* 上から順にtrue,false,not,and,or */ case 0: retval = !tmpval[0]; break; case 1: retval = tmpval[0] && tmpval[1]; break; case 2: retval = tmpval[0] || tmpval[1]; break; case 3: retval = 1; break; case 4: retval = 0; break; case 5: retval = (tmpval[0] == tmpval[1]); break; case 6: retval = (tmpval[0] != tmpval[1]); break; case 7: retval = ((unsigned int) tmpval[0] < (unsigned int) tmpval[1]); break; case 8: retval = ((unsigned int) tmpval[0] > (unsigned int) tmpval[1]); break; } } *naibupp = naibup; return (retval); } /** num番目の表を、使用するものとして登録する。前・本・後処理の区別もする */ static /* V3.1 */ void hyouse (num) int num; { fast int *ptr = NULL; /* V3.1 */ switch (cur_rk_table->rk_hyo.point[num].hyoshu) { case 1: ptr = cur_rk->rk_usehyo.usemaehyo; break; case 2: ptr = cur_rk->rk_usehyo.usehyo; break; case 3: ptr = cur_rk->rk_usehyo.useatohyo; break; default: BUGreport (11); } if (ptr == NULL) return; for (; *ptr != -1; ptr++) if (*ptr == num) return; *ptr = num; *++ptr = -1; } /* 88/06/02 V3.1 */ #ifndef OMRON_SPEC /** strcmpと同等 但し、'\(8進);'も解釈する。*/ static /* V3.1 */ int mystrcmp (s1, s2) char *s1, *s2; { fast char c1, c2; /* V3.1 */ while ((c1 = codeeval (&s1)) == (c2 = codeeval (&s2))) if (c1 == '\0') return (0); return (c1 > c2 ? 1 : -1); } /** strcpyと同等 但し'\(8進);'も解釈する。s1 <= s2なら正常動作するはず */ static /* V3.1 */ void mystrcpy (s1, s2) fast char *s1; char *s2; { while (*s1++ = codeeval (&s2)); } /** 一文字の解釈を行う。普通の文字はそのまま、'\(8進);'は実際のコードに 直す。その後、文字列へのポインタを一文字分進めておく(少なくとも 1バイト分進むことが保証されるはず)。*/ static /* V3.1 */ char codeeval (sptr) fast char **sptr; /* V3.1 */ { fast char c; /* V3.1 */ fast char code = 0; /* V3.1 */ if ((c = *(*sptr)++) != '\\') return (c); while (c = *(*sptr)++, is_octal (c)) { code <<= 3; code += ctov (c); } if (c != ';') BUGreport (12); return (code); } #endif /** romkanがon時のモード表示文字列を返す関数。無指定であってRK_DSPNILフラグが 立っている時は空文字列を返す。*/ char * romkan_dispmode () { return (cur_rk->dspmod[0][0] == NULL && (cur_rk_table->flags & RK_DSPNIL) ? "" : cur_rk->dspmod[0][0]); /* V3.1 */ } /** romkanがoff時のモード表示文字列を返す関数。無指定であってRK_DSPNILフラグ が立っている時は空文字列を返す。*/ char * romkan_offmode () { return (cur_rk->dspmod[0][1] == NULL && (cur_rk_table->flags & RK_DSPNIL) ? "" : cur_rk->dspmod[0][1]); /* V3.1 */ } /* 88/06/02 V3.1 */ /** ファイル名からパス名を除いた部分の先頭を返す。*/ static char * ename (s) char *s; { fast char *p; /* V3.1 */ p = rindex (s, KUGIRI); return (p == NULL ? s : p + 1); } /** ファイル名のチェック。先頭(パス名は除く)が'1'〜'3'でないといけない。 正当なものなら1〜3(前・本・後処理表の区別を表す)を返し、そうでないと 0を返す。*/ #ifdef OMRON_LIB static #endif int filnamchk (s) char *s; { fast int c; /* V3.1 */ c = *(ename (s)) - '0'; return ((1 <= c && c <= 3) ? c : 0); } /* 88/06/02 V3.1 */ static void ERMOPN (n) /* モード定義表がオープンできない */ fast unsigned int n; /* V3.1 */ { static char *ermes[] = { /* 0 */ "Unprintable error", "Mode-hyo does't exist", "Can't open Mode-hyo", "Too many long Mode-hyo filenames", }; if (n >= numberof (ermes)) n = 0; fprintf (stderr, "\r\nromkan: Mode-hyo %s ---\r\n", cur_rk_table->mcurfnm); fprintf (stderr, "\tError No.%d: %s.\r\n", n, ermes[n]); longjmp (cur_rk_table->env0, 1); } /* 88/06/03 V3.1 */ static void ERRMOD (n) /* モード定義表のエラー */ fast unsigned int n; /* V3.1 */ { static char *ermes[] = { /* 0 */ "Table incomplete", "')' mismatch", "Unprintable error", "Illegal filename", "Illegal modename", /* 5 */ "Undefined mode", "Illegal content(s) of list", "Illegal ^,\\o,\\x or \\d expression", "Illegal defmode", "Unrecognized keyword", /* 10 */ "Incomplete string", "Search path specified after filename", "Argument must be a string", "Can't get home directory", "Illegal @-keyword", /* 15 */ "User doesn't exist", "Illegal character", }; if (n >= numberof (ermes)) n = 2; fprintf (stderr, "\r\nromkan: Mode-hyo %s%s ---\r\n%s\r\n", cur_rk_table->mcurdir, cur_rk_table->mcurfnm, cur_rk_table->mcurread); fprintf (stderr, "\tError No.%d: %s.\r\n", n, ermes[n]); fclose (cur_rk_table->modefile); longjmp (cur_rk_table->env0, 1); }