/* */ /* WNN7 CLIENT LIBRARY--SOFTWARE LICENSE TERMS AND CONDITIONS Wnn7 Client Library : (C) Copyright OMRON Corporation. 1995,1998,2000,2001 all rights reserved. (C) Copyright OMRON Software Co., Ltd. 1995,1998,2000,2001 all rights reserved. Wnn Software : (C) Copyright Kyoto University Research Institute for Mathematical Sciences 1987, 1988, 1989, 1990, 1991, 1992, 1993 (C) Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1993 (C) Copyright ASCTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992, 1993 Preamble These Wnn7 Client Library--Software License Terms and Conditions (the "License Agreement") shall state the conditions under which you are permitted to copy, distribute or modify the software which can be used to create Wnn7 Client Library (the "Wnn7 Client Library"). The License Agreement can be freely copied and distributed verbatim, however, you shall NOT add, delete or change anything on the License Agreement. OMRON Corporation and OMRON Software Co., Ltd. (collectively referred to as "OMRON") jointly developed the Wnn7 Software (development code name is FI-Wnn), based on the Wnn Software. Starting from November, 1st, 1998, OMRON publishes the source code of the Wnn7 Client Library, and OMRON permits anyone to copy, distribute or change the Wnn7 Client Library under the License Agreement. Wnn7 Client Library is based on the original version of Wnn developed by Kyoto University Research Institute for Mathematical Sciences (KURIMS), OMRON Corporation and ASTEC Inc. Article 1. Definition. "Source Code" means the embodiment of the computer code, readable and understandable by a programmer of ordinary skills. It includes related source code level system documentation, comments and procedural code. "Object File" means a file, in substantially binary form, which is directly executable by a computer after linking applicable files. "Library" means a file, composed of several Object Files, which is directly executable by a computer after linking applicable files. "Software" means a set of Source Code including information on its use. "Wnn7 Client Library" the computer program, originally supplied by OMRON, which can be used to create Wnn7 Client Library. "Executable Module" means a file, created after linking Object Files or Library, which is directly executable by a computer. "User" means anyone who uses the Wnn7 Client Library under the License Agreement. Article 2. Copyright 2.1 OMRON Corporation and OMRON Software Co., Ltd. jointly own the Wnn7 Client Library, including, without limitation, its copyright. 2.2 Following words followed by the above copyright notices appear in all supporting documentation of software based on Wnn7 Client Library: This software is based on the original version of Wnn7 Client Library developed by OMRON Corporation and OMRON Software Co., Ltd. and also based on the original version of Wnn developed by Kyoto University Research Institute for Mathematical Sciences (KURIMS), OMRON Corporation and ASTEC Inc. Article 3. Grant 3.1 A User is permitted to make and distribute verbatim copies of the Wnn7 Client Library, including verbatim of copies of the License Agreement, under the License Agreement. 3.2 A User is permitted to modify the Wnn7 Client Library to create Software ("Modified Software") under the License Agreement. A User is also permitted to make or distribute copies of Modified Software, including verbatim copies of the License Agreement with the following information. Upon modifying the Wnn7 Client Library, a User MUST insert comments--stating the name of the User, the reason for the modifications, the date of the modifications, additional terms and conditions on the part of the modifications if there is any, and potential risks of using the Modified Software if they are known--right after the end of the License Agreement (or the last comment, if comments are inserted already). 3.3 A User is permitted to create Library or Executable Modules by modifying the Wnn7 Client Library in whole or in part under the License Agreement. A User is also permitted to make or distribute copies of Library or Executable Modules with verbatim copies of the License Agreement under the License Agreement. Upon modifying the Wnn7 Client Library for creating Library or Executable Modules, except for porting a computer, a User MUST add a text file to a package of the Wnn7 Client Library, providing information on the name of the User, the reason for the modifications, the date of the modifications, additional terms and conditions on the part of the modifications if there is any, and potential risks associated with using the modified Wnn7 Client Library, Library or Executable Modules if they are known. 3.4 A User is permitted to incorporate the Wnn7 Client Library in whole or in part into another Software, although its license terms and conditions may be different from the License Agreement, if such incorporation or use associated with the incorporation does NOT violate the License Agreement. Article 4. Warranty THE WNN7 CLIENT LIBRARY IS PROVIDED BY OMRON ON AN "AS IS" BAISIS. OMRON EXPRESSLY DISLCIAMS ANY AND ALL WRRANTIES, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, IN CONNECTION WITH THE WNN7 CLIENT LIBRARY OR THE USE OR OTHER DEALING IN THE WNN7 CLIENT LIBRARY. IN NO EVENT SHALL OMRON BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL DAMAGES OF ANY KIND WHATSOEVER IN CONNECTION WITH THE WNN7 CLIENT LIBRARY OR THE USE OR OTHER DEALING IN THE WNN7 CLIENT LIBRARY. *************************************************************************** Wnn7 Client Library : (C) Copyright OMRON Corporation. 1995,1998,2000,2001 all rights reserved. (C) Copyright OMRON Software Co., Ltd. 1995,1998,2000,2001 all rights reserved. Wnn Software : (C) Copyright Kyoto University Research Institute for Mathematical Sciences 1987, 1988, 1989, 1990, 1991, 1992, 1993 (C) Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1993 (C) Copyright ASCTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992, 1993 *************************************************************************** Comments on Modifications: */ /*********************************************************************** rk_read.c 88. 6.11 改 正 93.10.19 rk_main.c の部品。変換対応表の読み込みを担当。 ***********************************************************************/ /* Version 3.0 */ #include "rk_multi.h" #include #include letter onescan(); char *ename(); extern letter *ltrgrow(), *ltrend(), letterpick(), *ltr1cut(); extern char *chrcat(), *strend(); static int termsscan(), evalandcpy(), eval1cpy(), partscan(), atermscan(), serfun(), hensrc_tourk(), blankpass(), modsrcL(), chkL_get_int(); static void ERRLIN(), ERHOPN(), ltr1tostr(), ERRHYO(), vchk(), rangeset(), de_bcksla(), listscan(), singleqscan(), doubleqscan(); static void readhyo(); static int evlis(); letter *rangekettei(); extern void BUGreport(), choosehyo(), readmode(); extern int ltrcmp(), ltrstrcmp(), readfnm(), fixednamep(); #define IHENSU (1 << 24) /* 内部表現の上位1バイトで、変数を表す */ #define IKANSU (2 << 24) /* 〃 関数を表す */ #define IMODNM (3 << 24) /* 〃 モード名を表す */ #define ENDOF_NestFileArea ((FILE *)~0) /** includeファイルのディスクリプタ格納エリアのエンドマーク*/ /** 一行読み込み。一字も読み込まないうちにEOFにつきあたったら0を返す。 但しincludeを考慮している。対応表には空白文字以外のコントロール文字は 生では混じらないものとし、混じっていたらチェックする。*/ int readln(buf, cur_rk) uns_chr *buf; ARGS *cur_rk; { register uns_chr *p; register int c; if(NULL == *base){ *buf = '\0'; return(0); } p = buf; while(1){ while(EOF == (c = getc(*base))){ fclose(*base); if(NULL == *--base){ c = EOF; break; } } if(c == EOF || c == '\n') break; if(is_cntrl(c) && !isspace(c)){ sprintf(hcurread, "\\%03o", c); ERRLIN(21, cur_rk); } *p++ = c; } *p = '\0'; return(p != buf || c != EOF); } letter *memptr, *ltrbufptr, *hensumei, *hen_iki, *term, **henptr; letter *dummy; struct dat *datptr; struct hensuset { unsigned regdflg : 1; /* 既登録の変数を表す */ unsigned curlinflg : 1; /* 現在行に既出の変数を表す */ unsigned constflg : 1; /* 定数として定義されたことを表す */ letter *name; letter *range; } *hentourkptr, *henorg; /** 与えられたファイルがディレクトリなら非0を返す */ int isdir(fnm) char *fnm; { struct stat statbuf; /* return(stat(fnm, &statbuf) == 0 && (statbuf.st_mode & S_IFDIR)); */ return(stat(fnm, &statbuf) == 0 && ((statbuf.st_mode & S_IFMT) == S_IFDIR)); } /** nameで与えられた名の変換対応表をオープンする。固定名と見なされない 名前(fixednamep()参照)に対しては、サーチパスを見る。その場合、 オープンに成功したら、パス名を *dirnamptrに入れて返る。その他の場合は *dirnamptrに空文字列が入る。*errcodには次のエラーコードが入る。 与えられたファイルがディレクトリの時1(サーチパスを探した時は3)、 ファイルをオープンできない時2(同4)。*/ FILE * trytoopen(name, dirnamptr, errptr, cur_rk) char *name, **dirnamptr; int *errptr; ARGS *cur_rk; { char **src, taio_fnm[REALFN]; FILE *opened; *dirnamptr = nulstr; *errptr = 0; if(fixednamep(name)){ if(isdir(name)){ *errptr = 1; return(NULL); } if(NULL == (opened = fopen(name, "r"))){ *errptr = 2; return(NULL); } if(flags & RK_VERBOS){ fprintf(stderr, "romkan: using Taio-hyo %s ...\r\n", name); } return(opened); } else { for(src = pathmeiorg; *src != NULL; src++){ strcpy(taio_fnm, (*dirnamptr = *src)); strcat(taio_fnm, name); if(isdir(taio_fnm)){ *errptr = 3; return(NULL); } if(NULL == (opened = fopen(taio_fnm, "r"))) continue; /* Now Taio-hyo found */ if(flags & RK_VERBOS) fprintf(stderr, "romkan: using Taio-hyo %s ...\r\n", taio_fnm); return(opened); } if(flags & RK_VERBOS){ /* Taio-hyo not found */ char *p, *q; fprintf(stderr, "no %s in", name); for(src = pathmeiorg; *src != NULL; src++){ fputc(' ', stderr); q = *src; if(*q == KUGIRI && *(q + 1) == '\0') q++; else q = strend(q); for(p = *src; p < q; p++) fputc(*p, stderr); } fprintf(stderr, ".\n"); } *dirnamptr = nulstr; *errptr = 4; return(NULL); } } /** 表全部の読み込み */ void readdata(memory, data, hensudefhyo, modf, cur_rk) letter *memory; /* 対応表の内部表現を入れる配列の先頭番地を渡される */ struct dat *data; /* 対応表の行ごとのデータを入れる配列の番地 */ letter **hensudefhyo; /* 変数定義のデータを入れる配列の番地 */ char *modf; /* モード定義表の名又はそのパス名が入っている */ ARGS *cur_rk; { int i, j; char *hyomeibgn[HYOMAX]; /* 表の名へのポインタを入れる配列 */ char hyomeimem_[HYOMEI]; /* 表の名の実際の文字列を入れる配列 */ char *pathmeibgn[PTHMAX]; /* サーチパス名へのポインタを入れる配列 */ char pathmeimem_[PTHMEI]; /* サーチパス名の実際の文字列を入れる配列 */ char modfnm[REALFN]; /* モード表のファイル名をここへコピる のちにはそのパス名が入る */ memptr = memory; datptr = data; henptr = hensudefhyo; *(pathmeiptr = pathmeiorg = pathmeibgn) = NULL; *(pathmeimem = pathmeimem_) = '\0'; *(hyomeiptr = hyomeiorg = hyomeibgn) = NULL; *(hyomeimem = hyomeimem_) = '\0'; *(modmeiptr = modmeibgn) = NULL; *(modmeimem = modmeimem_) = '\0'; *(dspnamptr = dspnambgn) = NULL; *(dspcod = dspcod_) = '\0'; *(naibu = naibu_) = '\0'; strcpy(modfnm, modf); /* modfnmが与えたファイル名。パス名だけ与えられたら、デフォルトの モード表名"mode"をつなぐ。KUGIRI=ディレクトリの区切り文字 */ if(*modfnm == '\0' || *(strend(modfnm)) == KUGIRI){ strcat(modfnm, "mode"); } else if(isdir(modfnm)){ chrcat(modfnm, KUGIRI); strcat(modfnm, "mode"); } curdir = nulstr; readmode(curfnm = modfnm, cur_rk); for(i = 0; hyomeiorg[i] != NULL; i++){ int err; for(j = 0; j < FILNST; j++) nestfile[j] = NULL; nestfile[FILNST - 1] = ENDOF_NestFileArea; base = nestfile + 1; *base = trytoopen(curfnm = hyomeiorg[i], &curdir, &err, cur_rk); if(err){ switch(err){ case 1: case 3: ERHOPN(1, cur_rk); case 2: case 4: ERHOPN(0, cur_rk); } } readhyo(i, cur_rk); } hyo_n[i] . data = NULL; choosehyo(cur_rk); } /** ファイル名からパス名を除いた部分の先頭を返す。*/ char *ename(s) char *s; { char *p; p = strrchr(s, KUGIRI); return(p == NULL ? s : p + 1); } /** ファイル名のチェック。先頭(パス名は除く)が'1'〜'3'でないといけない。 正当なものなら1〜3(前・本・後処理表の区別を表す)を返し、そうでないと 0を返す。*/ int filnamchk(s) char *s; { char c; c = *(ename(s)) - '0'; return((1 <= c && c <= 3) ? c : 0); } /** linbufに入っているunsigned charの列をletterの列にしてltrbufに入れる。 エンドマークはEOLTTRになる。flgが非0の時は、先頭の空白文字は飛ばす。*/ void ustrtoltr(linbuf, ltrbuf, flg, cur_rk) uns_chr *linbuf; int flg; register letter *ltrbuf; ARGS *cur_rk; { register letter l; if(flg){ while(l = letterpick(&linbuf, cur_rk), is_eolsp(l)){ if(l == EOLTTR){ *ltrbuf = EOLTTR; return; } } *ltrbuf++ = l; } while((*ltrbuf++ = letterpick(&linbuf, cur_rk)) != EOLTTR); } /** letterの列を文字列にコンバート。二つのポインタが同一番地であっても 動作を保証すること。*/ void ltrtostr(ltrbuf, linbuf) char *linbuf; letter *ltrbuf; { letter l; while((l = *ltrbuf++) != EOLTTR) ltr1tostr(l, &linbuf); *linbuf = '\0'; } /** letterを文字列にコンバート */ static void ltr1tostr(l, sptr) char **sptr; letter l; { int i; for(i = 0; i < 3 && 0 == (l & (0xff000000)); i++) l <<= 8; for(; i < 4; i++){ *(*sptr)++ = (char)(l >> 24); l <<= 8; } } /** 変数の「現在行既出フラグ」を全てクリア */ void hen_useflgclr(hensu) struct hensuset *hensu; { for(; hensu -> name != NULL; hensu++) hensu -> curlinflg = 0; /* 現在行に未出 */ } /** 対応表一つ読み込み */ static void readhyo(n, cur_rk) int n; ARGS *cur_rk; { uns_chr linbuf[LINSIZ]; letter ltrbuf[LINSIZ], *lp; letter termbuf[SIZALL]; /* エラーを考慮して、表のサイズ分取っておく*/ letter dummybuf[TRMSIZ], hensumei_[VARLEN], hen_iki_[SIZALL]; struct hensuset hensu[VARMAX]; int m, hyosw, rsltyp[3]; hcurread = (char *)linbuf; /* エラー処理用 */ ltrbufbgn = ltrbuf; *(hensumei = hensumei_) = EOLTTR; *(hen_iki = hen_iki_) = EOLTTR; (henorg = hentourkptr = hensu) -> name = NULL; dummy = dummybuf; hyo_n[n] . hensudef = henptr; hyo_n[n] . data = datptr; hyosw = hyoshu[n]; while(readln(linbuf, cur_rk)){ hen_useflgclr(henorg); ustrtoltr(linbuf, ltrbuf, 1, cur_rk); ltrbufptr = ltrbuf; for(m = 0; termsscan(<rbufptr, term = termbuf, 1, cur_rk); m++){ /* mは、何番目の項目を見ているかを表す */ if(*term == ';') break; /* 注釈行 */ if(m == 3) ERRLIN(15, cur_rk); if(m != 0 && rsltyp[0] == 4) ERRLIN(12, cur_rk); datptr -> code[m] = memptr; if((rsltyp[m] = evalandcpy(&term, m, cur_rk)) == 4){ if(m) ERRLIN(14, cur_rk); /* 宣言は最初の項目にしか来れない。 funstr[]のappearフラグでもチェックしているが 将来のために一応ここにもチェックを入れておく。*/ } else { /* 宣言の時には内部表現へのポインタは進めない */ totail(memptr); memptr++; } } if(m != 0 && rsltyp[0] != 4){ for( /* m=? */ ; m < 3; m++){ datptr -> code[m] = nil; rsltyp[m] = -1; /* doesn't exist */ } datptr++; /* rsltyp: 0=文字項 1=文字列連 2=データ連 3=機能項 4=宣言項 -1=存在せず */ switch(hyosw){ /* 前・後処理は、表の内容に制限がある。それを検査 */ case 1: if(!(rsltyp[0] == 0 && rsltyp[1] == 0 && rsltyp[2] == -1 )) ERRLIN(17, cur_rk); break; case 2: if(rsltyp[1] == 3 && rsltyp[2] != -1) ERRLIN(19, cur_rk); break; case 3: if(!(rsltyp[0] == 0 && (rsltyp[1] == 0 || rsltyp[1] == 1) && rsltyp[2] == -1 )) ERRLIN(18, cur_rk); break; default: BUGreport(10); } } } (datptr++) -> code[0] = NULL; /* 変数登録ここでまとめてする */ for(lp = hen_iki_; lp < hen_iki; ) *memptr++ = *lp++; for(hentourkptr = henorg; hentourkptr -> name != NULL; hentourkptr++){ if(hentourkptr -> regdflg == 0) ERRHYO(0, cur_rk); *henptr++ = memptr - (lp - hentourkptr -> range); } *henptr++ = NULL; /* ここで fclose(*base); は不要。readln内ですんでいる */ } /** 変換対応表の項目一つを、解釈して、内部形式のデータエリアにコピーする。 返す値は、解釈した項目が文字項なら0、それ以外で文字列連なら1、それ以外 でデータ連なら2、機能項なら3、宣言項なら4。それ以外はエラー。*/ static int evalandcpy(socp, m, cur_rk) register letter **socp; /* 項目へのポインタ(へのポインタ)*/ int m; /* 対応表の何番目の項目を見ているかを表す。入力コード部を 見ているときは0、出力コード部なら1、バッファ残り部なら2 */ ARGS *cur_rk; { #define TYPMAX 5 char exist[TYPMAX], total; /* existは、それぞれタイプ0〜4の項の出現のフラグ(eval1cpy()参照)。 totalは全体としての出現フラグ。どちらも、1=未出 2=一回出 その他の 時は下2ビット0 */ int type; #define TIME_0(flag) ((flag) == 1) #define TIME_1(flag) ((flag) == 2) #define TIME_n(flag) (((flag) & 3) == 0) total = 1; for(type = 0; type < TYPMAX; type++) exist[type] = 1; while(!is_eolsp(**socp)){ if(!(0 <= (type = eval1cpy(socp, m, 0, cur_rk)) && type < TYPMAX)) BUGreport(3); exist[type] <<= 1; total <<= 1; } if(TIME_0(total)) BUGreport(13); /* 項目が空ならevalandcpyは実行しない筈 */ if(!TIME_0(exist[3]) || !TIME_0(exist[4])){ if(TIME_n(total)) ERRLIN(9, cur_rk); return(type); /* 3又は4。typeが値を保持している筈 */ } if(TIME_1(total) && TIME_1(exist[0])) return(0); return(!TIME_0(exist[2]) ? 2 : 1); } /** 対応表の項目の中の項一つを解釈し、内部形式のデータエリアにコピーし、 それのタイプ(文字項=0 文字列項=1 特殊関数項=2 機能項=3 宣言項=4)を 返す。flgが非0なら、再帰的に呼ばれたことを意味し、その場合、 現在行に未出の変数を検出したらエラー。また、mが非0のとき(入力コード部 以外の所を見ている時)も、現在行に未出の変数を検出したらエラー。*/ static int eval1cpy(socp, m, flg, cur_rk) letter **socp; /* flg以外の引数の意味はevalandcpyと同じ */ int m, flg; ARGS *cur_rk; { letter t1buf[TRMSIZ], *t1bufp; t1bufp = t1buf; *memptr = EOLTTR; switch(partscan(socp, t1bufp, cur_rk)){ case 1: /* 単文字 */ memptr = ltrgrow(memptr, t1bufp); *memptr = EOLTTR; return(0); case 2: /* 引用文字 */ t1bufp++; *memptr++ = onescan(&t1bufp, dummy, cur_rk); *memptr = EOLTTR; return(0); case 3: /* 引用文字列 */ t1bufp++; while(*t1bufp != '"'){ *memptr++ = onescan(&t1bufp, dummy, cur_rk); } *memptr = EOLTTR; return(1); case 0: /* リスト */ return(evlis(m, &t1bufp, flg, cur_rk)); /* evlis内で *memptr = EOLTTR; をしている。*/ default: BUGreport(4); return(-1); /*NOTREACHED*/ } /*NOTREACHED*/ } #define bitchk(x, n) ((x) & (1 << (n))) #define get_ltr(lp) (*(lp)++) #define unget_ltr(l, lp) (*--(lp) = (l)) /** globalなポインタから指されているletter列から一文字取ってくる。*/ letter get1ltr(cur_rk) ARGS *cur_rk; { return(get_ltr(lptr)); } letter unget1ltr(l, cur_rk) letter l; ARGS *cur_rk; { return(unget_ltr(l, lptr)); } int int_get1ltr(cur_rk) ARGS *cur_rk; { return((int)(get1ltr(cur_rk))); } int int_unget1ltr(c, cur_rk) letter c; ARGS *cur_rk; { return((int)(unget1ltr((letter) c, cur_rk))); } /** 汚いことこの上なし!なぜ関数の型のcastができないの? 「(int ()) get1ltr」と書きたい! */ /** includeファイル名のletter列をstringに取り出す作業を、letter列の終わり まで続ける。flg & 01が非0なら、'/'でも終了。*/ letter getfrom_dblq(socp, destp, flg, cur_rk) letter **socp; char **destp; int flg; ARGS *cur_rk; { letter l; while(**socp != EOLTTR && !(flg & 01 && **socp == KUGIRI)){ if (**socp == '\\') *(*destp)++ = '\\'; l = onescan(socp, dummy, cur_rk); ltr1tostr(l, destp); } *(*destp)++ = '\0'; return(**socp); } int getfrom_lptr(sptr, flg, cur_rk) char **sptr; int flg; ARGS *cur_rk; { return((int)getfrom_dblq(&lptr, sptr, flg, cur_rk)); } /** リストを解釈して内部表現にする。返値は、そのリストのタイプを表す数。 文字変数項又は文字関数項:0 文字列関数項:1 特殊関数項:2 機能項:3 宣言項:4 */ static int evlis(m, socp, flg, cur_rk) letter **socp; /* 引数の意味はeval1cpyを参照 */ int m, flg; ARGS *cur_rk; { int fnnum, hennum, i; letter t1buf[TRMSIZ]; (*socp)++; /* '('をスキップ */ atermscan(socp, t1buf, 3, cur_rk); fnnum = serfun(t1buf); if(fnnum != -1 && !bitchk(func[fnnum] . appear, m)) ERRLIN(14, cur_rk); /* mの値によって、現れてはいけない所への出現かどうか見ている。*/ switch(fnnum){ /* defaultの所以外は func[fnnum].argnumを使ってない */ case -1: /* 変数 */ vchk(t1buf, cur_rk); atermscan(socp, dummy, 2, cur_rk); /* あればERR */ hennum = hensrc_tourk(t1buf, ((m==0 && !flg)? 0 : 1), cur_rk); *memptr++ = (henorg[hennum] . constflg ? *(henorg[hennum].range) : hennum|IHENSU); break; case 0: /* fn No.0 defvar */ atermscan(socp, t1buf, 3, cur_rk); if(*t1buf == '('){ letter *soc2, t1buf2[TRMSIZ], t1buf3[TRMSIZ]; letter *common_hen; atermscan(socp, t1buf3, 3, cur_rk); soc2 = t1buf + 1; /* skip '(' */ atermscan(&soc2, t1buf2, 3, cur_rk); vchk(t1buf2, cur_rk); if(-1 != serfun(t1buf2)) ERRLIN(11, cur_rk); hennum = hensrc_tourk(t1buf2, 2, cur_rk); common_hen = rangekettei(hennum, t1buf3, cur_rk); while(atermscan(&soc2, t1buf2, 0, cur_rk)){ vchk(t1buf2, cur_rk); if(-1 != serfun(t1buf2)) ERRLIN(11, cur_rk); hennum = hensrc_tourk(t1buf2, 2, cur_rk); rangeset(hennum, common_hen, cur_rk); } } else { vchk(t1buf, cur_rk); if(-1 != serfun(t1buf)) ERRLIN(11, cur_rk); hennum = hensrc_tourk(t1buf, 2, cur_rk); /* defvar・defconstの変数名の重複を避けるため */ atermscan(socp, t1buf, 3, cur_rk); rangekettei(hennum, t1buf, cur_rk); } atermscan(socp, dummy, 2, cur_rk); break; case 36: /* fn No.36 defconst */ atermscan(socp, t1buf, 3, cur_rk); vchk(t1buf, cur_rk); if(-1 != serfun(t1buf)) ERRLIN(11, cur_rk); hennum = hensrc_tourk(t1buf, 6, cur_rk); /* defvar・defconstの変数名重複を避けるため */ rangeset(hennum, hen_iki, cur_rk); blankpass(socp, 1, cur_rk); if(*(*socp)++ != '\'') ERRLIN(8, cur_rk); *hen_iki++ = onescan(socp, dummy, cur_rk); (*socp)++; /*「'」が閉じていることの検査は済んでいる*/ *hen_iki++ = EOLTTR; /* needed? */ *hen_iki = EOLTTR; atermscan(socp, dummy, 2, cur_rk); break; case 1: /* fn No.1 include */ { char fnmtmparea[REALFN], *s, *dirnamptr; int dummyc = 0, err; blankpass(socp, 1, cur_rk); if(3 != partscan(socp, t1buf, cur_rk)) ERRLIN(22, cur_rk); atermscan(socp, dummy, 2, cur_rk); /* 余分にあればERR */ ltr1cut(lptr = t1buf + 1); *(s = fnmtmparea) = '\0'; err = readfnm(int_get1ltr, int_unget1ltr, getfrom_lptr, &s, &dummyc, cur_rk); if(err){ hcurread = s; switch(err){ case 1: case 3: ERRLIN(25, cur_rk); case 2: ERRLIN(26, cur_rk); case 4: ERRLIN(27, cur_rk); } } de_bcksla(fnmtmparea, fnmtmparea); if(*++base == ENDOF_NestFileArea){ base--; ERRLIN(23, cur_rk); } *base= trytoopen(fnmtmparea, &dirnamptr,&err, cur_rk); if(err){ switch(err){ case 1: case 3: case 2: case 4: base--; ERRLIN(24, cur_rk); } } } break; /* モード名一つを引数に取るもの */ case 4: /* fn No.4〜6 off,on,switch */ case 5: case 6: case 20: /* fn No.20,21 if,unless */ case 21: *memptr++ = fnnum | IKANSU; atermscan(socp, t1buf, 3, cur_rk); *memptr++ = modsrcL(t1buf, cur_rk) | IMODNM; atermscan(socp, t1buf, 2, cur_rk); break; /* モード名と文字 一つずつを引数に取るもの */ case 37: /* fn No.37〜43 setmodeなど */ case 38: case 39: case 40: case 41: case 42: case 43: { int err, n; modetyp stat; *memptr++ = fnnum | IKANSU; atermscan(socp, t1buf, 3, cur_rk); *memptr++ = (n = modsrcL(t1buf, cur_rk))| IMODNM; atermscan(socp, t1buf, 3, cur_rk); err = chkL_get_int(t1buf, &stat, modesw[n] . moderng); if(err != 0) ERRLIN(29, cur_rk); *memptr++ = stat; atermscan(socp, t1buf, 2, cur_rk); break; } /* 普通(引数を取らないものを含む) */ default: /* toupper,tolower… */ *memptr++ = fnnum | IKANSU; *memptr = EOLTTR; for(i = 0; i < func[fnnum] . argnum; i++){ blankpass(socp, 1, cur_rk); if(eval1cpy(socp, m, 1, cur_rk) != 0) ERRLIN(13, cur_rk); } atermscan(socp, dummy, 2, cur_rk); /* 余分にあればERR */ break; } *memptr = EOLTTR; return(fnnum == -1 ? 0 : func[fnnum] . fntype); } /** 文字列中の「\」を抜く */ static void de_bcksla(s, r) char *s, *r; { for(; *s; *r++ = *s++) if(*s == '\\') s++; *r = '\0'; } /** defvarの第二引数(shikiに入る)を解釈して、その変数の変域を決定する。 変数列の最後にエンドマークもちゃんと入る。返値は、変域を格納した 所へのポインタ。*/ letter * rangekettei(num, shiki, cur_rk) letter *shiki; int num; /* 変域を決定しつつある変数の内部番号 */ ARGS *cur_rk; { letter hyoukabuf[TRMSIZ]; rangeset(num, hen_iki, cur_rk); *hen_iki = EOLTTR; if(*shiki++ != '(') ERRLIN(8, cur_rk); atermscan(&shiki, hyoukabuf, 1, cur_rk); if(!ltrstrcmp(hyoukabuf, "all")){ *hen_iki++ = VARRNG; *hen_iki++ = 0; *hen_iki++ = LTRHUG; /* 変域は全文字 */ *hen_iki++ = EOLTTR; *hen_iki = EOLTTR; atermscan(&shiki, dummy, 2, cur_rk); /* 余分にあればERR */ } else if(!ltrstrcmp(hyoukabuf, "between")){ int i; *hen_iki++ = VARRNG; while(blankpass(&shiki, 1, cur_rk), *shiki != ')'){ for(i = 1; i <= 2; i++){ switch(*shiki){ case '\'': shiki++; *hen_iki++ = onescan(&shiki, dummy, cur_rk); shiki++; break; case ')': case '"': case '(': ERRLIN(8, cur_rk); default: *hen_iki++ = *shiki++; } if(i < 2){ if(!is_eolsp(*shiki)) ERRLIN(8, cur_rk); blankpass(&shiki, 1, cur_rk); } } } *hen_iki++ = EOLTTR; *hen_iki = EOLTTR; } else if(!ltrstrcmp(hyoukabuf, "list")){ while(blankpass(&shiki, 1, cur_rk), *shiki != ')'){ switch(*shiki){ case '"': case '(': ERRLIN(8, cur_rk); case '\'': shiki++; *hen_iki++ = onescan(&shiki, dummy, cur_rk); shiki++; /* 本当に「'」が閉じているか どうかの検査はもう済んでいる。*/ break; default: *hen_iki++ = *shiki++; } if(!is_eolsp(*shiki)) ERRLIN(8, cur_rk); } *hen_iki++ = EOLTTR; *hen_iki = EOLTTR; } else { ERRLIN(8, cur_rk); /* 将来はこの他の構文も許す予定であった */ } return(henorg[num] . range); } /** num番目の変数の変域を指すべきポインタの指し先を決定し、その変数を 既登録状態にする。*/ static void rangeset(num, range, cur_rk) letter *range; /* 変域の入る場所のポインタ */ int num; ARGS *cur_rk; { henorg[num] . range = range; henorg[num] . regdflg = 1; } /** nameで指定された名の変数を探し、なければ登録。変数名の最後に エンドマークもちゃんと入る。 flg & 01が非0の時、その名の変数が現在行に未出ならエラー(constとして 既登録の時を除く)。また flg & 02が非0の時、その名の変数が既定義なら エラー(defvarの重複チェック用)。flg & 04が非0ならconstとして登録。*/ static int hensrc_tourk(name, flg, cur_rk) letter *name; int flg; ARGS *cur_rk; { int i; for(i = 0; henorg[i] . name != NULL; i++){ if(ltrcmp(henorg[i] . name, name)) continue; /* found */ if(flg & 04) ERRLIN(28, cur_rk); if(flg & 02 && henorg[i] . regdflg != 0) ERRLIN(10, cur_rk); if(flg & 01 && henorg[i] . curlinflg == 0 && henorg[i] . constflg == 0) ERRLIN(5, cur_rk); henorg[i] . curlinflg = 1; return(i); } if(henorg + i != hentourkptr) BUGreport(5); /* ここへ来たということは、初出の変数ということ。当然、flg & 01が 非0ならエラー。*/ if(flg & 01) ERRLIN(5, cur_rk); hentourkptr -> name = hensumei; hentourkptr -> curlinflg = 1; hentourkptr -> regdflg = 0; /* 初出だからrangeのdefは未だの筈 */ hentourkptr -> constflg = ((flg & 04) != 0); (++hentourkptr) -> name = NULL; hensumei = ltrgrow(hensumei, name); *++hensumei = EOLTTR; return(i); } /** 組み込み関数・機能名に対してはその番号を、そうでないものなら-1を返す */ static int serfun(lp) register letter *lp; /* 関数・機能名もしくは変数名 */ { register int i; for(i = 0; func[i] . fnname != NULL; i++){ if(! ltrstrcmp(lp, func[i] . fnname)) return(i); } return(-1); } /** 変数の名前のチェック おかしいとエラー */ static void vchk(lp, cur_rk) letter *lp; ARGS *cur_rk; { if(is_digit(*lp)) ERRLIN(3, cur_rk); for(; *lp != EOLTTR; lp++){ /* if(is_lower(*lp)) *lp = to_upper(*lp); */ if(!is_alnum(*lp) && *lp != '_') ERRLIN(3, cur_rk); } } /** 一項目を取り出す。取り出しに成功すると1を返す。flgが非0の時は、')'が 見つかるとエラー、';'はそれだけで一項目扱い。*/ static int termsscan(socp, dest, flg, cur_rk) register letter **socp, *dest; /* socpの指しているポインタが指している所から取り出してdestに入れる。 その後、socpが指しているポインタを進める。このファイルの **scan() という関数は全てそうなってる。*/ int flg; ARGS *cur_rk; { letter *bgn; bgn = dest; if(blankpass(socp, 0, cur_rk) == 0){ if(flg && **socp == ';'){ *dest++ = *(*socp)++; } else while(!is_eolsp(**socp)){ if(**socp == ')'){ if(flg) ERRLIN(0, cur_rk); break; } else { partscan(socp, dest, cur_rk); totail(dest); } } } *dest = EOLTTR; return(bgn != dest); } /** リスト一つか、単純項の一まとまりを取り出す。成功したら1を返す。 flgが1のとき、')'が見つかるとエラー。 flgが2のとき、取り出しに成功したらエラー。 flgが3のとき、取り出しに失敗したらエラー。*/ static int atermscan(socp, dest, flg, cur_rk) register letter **socp, *dest; int flg; ARGS *cur_rk; { letter *bgn; int found; bgn = dest; if(blankpass(socp, 0, cur_rk) == 0){ if(**socp == '('){ listscan(socp, dest, cur_rk); totail(dest); } else { while(!is_eolsp(**socp) && **socp != '('){ if(**socp == ')'){ if(flg == 1) ERRLIN(0, cur_rk); break; } else { partscan(socp, dest, cur_rk); totail(dest); } } } } *dest = EOLTTR; found = (bgn != dest); if((!found && (flg == 3)) || (found && (flg == 2))) ERRLIN(7, cur_rk); return(found); } /** 項一つを取り出す。取り出したものがリストなら返値は0、単文字なら1、 引用文字なら2、引用文字列なら3。*/ static int partscan(socp, dest, cur_rk) register letter **socp, *dest; ARGS *cur_rk; { switch(**socp){ case '(': listscan(socp, dest, cur_rk); return(0); case '\'': singleqscan(socp, dest, cur_rk); return(2); case '"': doubleqscan(socp, dest, cur_rk); return(3); default: *dest++ = *(*socp)++; *dest = EOLTTR; return(1); } } /** シングルクォート表現一つを取り出す。*/ static void singleqscan(socp, dest, cur_rk) letter **socp, *dest; ARGS *cur_rk; { *dest++ = *(*socp)++; onescan(socp, dest, cur_rk); totail(dest); if((*dest++ = *(*socp)++) != '\'') ERRLIN(1, cur_rk); *dest = EOLTTR; } /** ダブルクォート表現一つを取り出す。*/ static void doubleqscan(socp, dest, cur_rk) letter **socp, *dest; ARGS *cur_rk; { *dest++ = *(*socp)++; while(**socp != '"'){ if(**socp == EOLTTR) ERRLIN(1, cur_rk); onescan(socp, dest, cur_rk); totail(dest); } *dest++ = *(*socp)++; *dest = EOLTTR; } /** 8・10・16進コード用キャラクタを実際のコードに直す。入力のチェックは せず、英文字と数字以外の入力に対しては単に0を返す。*/ int ltov(l) letter l; { if(is_upper(l)) return(l - 'A' + 10); if(is_lower(l)) return(l - 'a' + 10); if(is_digit(l)) return(l - '0'); else return(0); } /** ltovの逆 */ letter vtol(l) letter l; { if(BASEMX <= l) return('*'); return(l + (l < 10 ? '0' : 'A' - 10)); } /** シングル・ダブルクォートの中での一文字取り出し。 「^」によるコントロールコード表現、「\」による8・10・16進表現にも 対応。「\」表現は、「\[o又はd又はx]数字の並び[;]」である。*/ letter onescan(socp, dest, cur_rk) letter **socp, *dest; ARGS *cur_rk; { letter l, realcode; int digflg; switch(realcode = *dest++ = *(*socp)++){ case '^': if(!(' ' <= (l = *(*socp)++) && l < '\177')) ERRLIN(2, cur_rk); realcode = ((*dest++ = l) == '?' ? '\177' : l & 0x1f); break; case '\\': digflg = 0; switch(**socp){ case 'n': *dest++ = *(*socp)++; realcode = '\n'; break; case 't': *dest++ = *(*socp)++; realcode = '\t'; break; case 'b': *dest++ = *(*socp)++; realcode = '\b'; break; case 'r': *dest++ = *(*socp)++; realcode = '\r'; break; case 'f': *dest++ = *(*socp)++; realcode = '\f'; break; case 'e': case 'E': *dest++ = *(*socp)++; realcode=ESCCHR; break; case 'o': *dest++ = *(*socp)++; for(realcode = 0; is_octal(**socp);){ digflg = 1; realcode <<= 3; realcode += ltov (*dest++ = *(*socp)++); } if(!digflg) ERRLIN(2, cur_rk); if(**socp== ';') *dest++ = *(*socp)++; break; case 'x': *dest++ = *(*socp)++; for(realcode = 0; is_xdigit(**socp);){ digflg = 1; realcode <<= 4; realcode += ltov (*dest++ = *(*socp)++); } if(!digflg) ERRLIN(2, cur_rk); if(**socp== ';') *dest++ = *(*socp)++; break; case 'd': *dest++ = *(*socp)++; for(realcode = 0; is_digit(**socp);){ digflg = 1; realcode *= 10; realcode += ltov (*dest++ = *(*socp)++); } if(!digflg) ERRLIN(2, cur_rk); if(**socp== ';') *dest++ = *(*socp)++; break; default: if(is_octal(**socp)){ for(realcode = 0; is_octal(**socp);){ realcode <<= 3; realcode += ltov( *dest++ = *(*socp)++); } if(**socp == ';') *dest++ = *(*socp)++; } else { realcode= *dest++= *(*socp)++; } } break; default: ; } *dest = EOLTTR; return(realcode); } /** letterの列の先頭にある空白をスキップする。 行末に達したら、flgが0のときは1を返し、そうでないとエラー。*/ static int blankpass(pptr, flg, cur_rk) register letter **pptr; /* letterの列のポインタへのポインタ。これが指しているものを進める */ int flg; ARGS *cur_rk; { while(is_eolsp(**pptr)){ if(EOLTTR == **pptr){ if(flg) ERRLIN(4, cur_rk); return(1); } (*pptr)++; } return(0); } /** リスト一個取り出し */ static void listscan(socp, dest, cur_rk) register letter **socp, *dest; ARGS *cur_rk; { int eofreach; *dest++ = *(*socp)++; /* = '(' */ *dest++ = ' '; while(eofreach = blankpass(socp, 0, cur_rk), **socp != ')'){ if(eofreach){ if(! readln((uns_chr *)hcurread, cur_rk)) ERRLIN(20, cur_rk); ustrtoltr((uns_chr *)hcurread, (*socp= ltrbufbgn), 1, cur_rk); /* listの中で行が切れている場合、一行追加読み込みを する。uns_chr用のバッファも、letter用のものも、 以前の物を先頭から再利用しているので注意。また、 エラーが起きた場合、 エラーの位置にかかわらず、 現在行として表示されるのは、最後に読まれた行のみ*/ } else { termsscan(socp, dest, 0, cur_rk); totail(dest); *dest++ = ' '; } } *dest++ = *(*socp)++; /* = ')' */ *dest = EOLTTR; } /** lpで指定されたモード名を探す。見つからないとエラー */ static int modsrcL(lp, cur_rk) letter *lp; ARGS *cur_rk; { int n; for(n = 0; modmeibgn[n] != NULL; n++) if(!ltrstrcmp(lp, modmeibgn[n])) return(n); ERRLIN(16, cur_rk); /*NOTREACHED*/ return(-1); } /** chk_get_int(rk_modread.c)のletter版 */ static int chkL_get_int(lp, ip, range) letter *lp; modetyp *ip; modetyp range; { int sgn = 1; modetyp out; if(*lp == '-'){ lp++; sgn = -1; } for(out = 0; *lp != EOLTTR; lp++){ if(!is_digit(*lp)) return(-1); #if defined(UX386) || defined(sun386) out = out * 10; #else out *= 10; #endif out += ltov(*lp); } if(range != 0) out %= range; if(sgn == -1 && out != 0) out = range - out; *ip = out; return(0); } /** この先は、表読み込みでエラった時に警告するルーチン。nはエラーコード。 またこれらは全て、romkan_initのエラーコードとして、longjmp経由で 1を返す。*/ void ERMOPN(n, cur_rk) /* モード定義表がオープンできない */ unsigned int n; ARGS *cur_rk; { static char *ermes[] = { /* 0 */ "Can't open Mode-hyo", "Unprintable error" }; if(n >= numberof(ermes)) n = 1; fprintf(stderr, "\r\nMode-hyo %s ---\r\n", curfnm); fprintf(stderr, "%d: %s.\r\n", n, ermes[n]); longjmp(env0, 1); } static void ERHOPN(n, cur_rk) /* 変換対応表がオープンできない */ unsigned int n; ARGS *cur_rk; { static char *ermes[] = { /* 0 */ "Can't open Taio-hyo", "Is a directory", "Unprintable error" }; if(n >= numberof(ermes)) n = 2; fprintf(stderr, "\r\nTaio-hyo %s%s ---\r\n", curdir, curfnm); fprintf(stderr, "%d: %s.\r\n", n, ermes[n]); longjmp(env0, 1); } void ERRMOD(n, cur_rk) /* モード定義表のエラー */ unsigned int n; ARGS *cur_rk; { 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", "Defmode or set-path placed wrong" }; if(n >= numberof(ermes)) n = 2; fprintf(stderr, "\r\nMode-hyo %s%s ---\r\n%s\r\n", curdir, curfnm, mcurread); fprintf(stderr, "%d: %s.\r\n", n, ermes[n]); fclose(modefile); longjmp(env0, 1); } static void ERRLIN(n, cur_rk) /* 変換対応表のエラー */ unsigned int n; ARGS *cur_rk; { static char *ermes[] = { /* 0 */ "')' mismatch", "Incomplete single-quote or double-quote expression", "Illegal ^,\\o,\\x or \\d expression", "Illegal variable name", "Incomplete line", /* 5 */ "Evaluation of unbound variable", "Unprintable error", "Too many or too few contents of list", "Illegal defvar/defconst", "Faculity or declaration joined other item(s)", /* 10 */ "Duplicate defvar/defconst", "Variable/constant name conflicts with Function name", "A line contains both declaration and other output item(s)", "Argument isn't a letter", "Function, faculity or declaration in illegal place", /* 15 */ "More than 3 items", "Undefined mode", "Against the restriction of pre-transform table", "Against the restriction of after-transform table", "Item comes after faculity", /* 20 */ "Incomplete list", "Illegal character", "Illegal include", "Too many levels of 'include' nest", "Can't open include file", /* 25 */ "Can't get home directory", "Illegal @-keyword", "User doesn't exist", "Constant must be defined before used", "Illegal mode status" }; if(n >= numberof(ermes)) n = 6; fprintf(stderr, "\r\nTaio-hyo %s%s ---\r\n%s\r\n", curdir, curfnm, hcurread); fprintf(stderr, "%d: %s.\r\n", n, ermes[n]); while(NULL != *base) fclose(*base--); longjmp(env0, 1); } static void ERRHYO(n, cur_rk) /* ERRLINと同様、対応表のエラーだが、一行だけの誤りでなく 全体を見ないとわからない誤り。今の所、「未定義変数の出現」のみ。*/ unsigned int n; ARGS *cur_rk; { static char *ermes[] = { /* 0 */ "Undefined variable was found", "Unprintable error" }; if(n >= numberof(ermes)) n = 1; fprintf(stderr, "\r\nTaio-hyo %s%s ---\r\n", curdir, curfnm); fprintf(stderr, "%d: %s.\r\n", n, ermes[n]); while(NULL != *base) fclose(*base--); longjmp(env0, 1); }