ファイルを open し, そのファイル記述子を返す組み込み関数 open_file の本体は次のようになっている.
void Popen_file(), Pclose_file(), Pget_line(), Pget_byte(); void Ppurge_stdin();
struct ftab file_tab[] = {
{"purge_stdin",Ppurge_stdin,0},
/* 関数本体は Popen_file, 引数は 1 */
{"open_file",Popen_file,1},
{"close_file",Pclose_file,1},
{"get_byte",Pget_byte,1},
...
void Popen_file(arg,rp)
NODE arg;
Q *rp;
{
char *name;
FILE *fp;
char errbuf[BUFSIZ];
int i;
/* 引数(ファイル名) のチェック */
asir_assert(ARG0(arg),O_STR,"open_file");
/* ファイルポインタ配列の空きを探す */
for ( i = 0; i < BUFSIZ && file_ptrs[i]; i++ );
if ( i == BUFSIZ )
error("open_file : too many open files");
name = BDY((STRING)ARG0(arg));
/* 読み込みモードで open */
fp = fopen(name,"r");
if ( !fp ) {
sprintf(errbuf,"open_file : \"%s\" not found",name);
error(errbuf);
}
/* ファイルポインタを格納 */
file_ptrs[i] = fp;
/* index をファイル記述子として返す */
STOQ(i,*rp);
}
この状態では, ファイルは常に読み込みモードで open されるが, 書き出しモードが指定された場合に, 対応するモードでファイルが open されるように変更する.
struct ftab file_tab[] = {
{"purge_stdin",Ppurge_stdin,0},
/* 関数本体は Popen_file, 引数は最大で 2 */
{"open_file",Popen_file,-2},
...
void Popen_file(arg,rp)
...
name = BDY((STRING)ARG0(arg));
/* 2 番目の引数が指定されたらそのモードで open */
/* そうでなければ読み込みモードで open */
if ( argc(arg) == 2 ) {
asir_assert(ARG1(arg),O_STR,"open_file");
fp = fopen(name,BDY((STRING)ARG1(arg)));
} else
fp = fopen(name,"r");
if ( !fp ) {
sprintf(errbuf,"open_file : \"%s\" not found",name);
error(errbuf);
}
...
関数の引数は NODE という, リストを表す構造体により渡される. NODE は
typedef struct oNODE {
pointer body;
struct oNODE *next;
} *NODE;
と宣言されている. 第
引数 (
)を取り出す場合, メンバ next を
回たどる必要があるが, 組み込み関数の引数取り出し用に
ARG0(arg),
, ARG10(arg) が用意されている.
file_tab[] における引数の個数指定
, 正の場合,
以外は不正,
負の場合, 0 以上
以下の任意の個数を意味する. 上の変更の場合, 無引
数の場合をチェックしていないのでやや不備である.