外部ファイルの結びつけ、fopen(),fclose(),initfile() ― 2015年01月11日 21:05
Watcom Fortran 77では、外部ファイルと措置番号を実行時に結びつけることができます。 しかし、あまり使い勝手がよいとは、限りません。 装置番号1とファイル"ABC.TXT"を結びつけるには、環境変数を設定する必要があります。
set 1=ABC.TXTこの方法だと、使っている装置番号を知っておく必要があります。あまり、賢くないやり方です。 別の方法を考えます。コマンドラインのパラメーターにファイル名を指定する方法を考えてみます。
program ABC.TXTこの方法は便利です。プログラム内部で使用されている装置番号を知る必要はありませんが、 外部ファイルと装置番号結びつける仕組みが必要です。その仕組みがWatcom Fortran 77にあり、それはopen文です。
open(unit=uid, file=fname, action=act, err=99) uid : 装置番号 fname : ファイル名(character型の文字列) act : 'READ','WRITE' 99 : ERRORが起きたときにジャンプする先このままでは、使いにくいので一枚、皮をかぶせます。fopen()です。
c fopen.for -- connect intenal file descripter and external file integer function fopen(uid, fn, act) integer uid integer*1 fn(*), act integer i character*261 cfn ! MAXNAME(261) character*5 cact ! READ WRITE include 'files.fi' if (act .eq. 82) then ! READ(LETR) cact = 'READ' else if (act .eq. 87) then ! WRITE(LETW) cact = 'WRITE' else ! error uid = -1 ! ERR(-1) fopen = -1 ! ERR(-1) return end if call is2cs(fn,cfn,261) ! MAXNAME(261) convert integer string to character string i = 1 while (i .le. 20) do ! MAXFIELS(20) if (finuse(i) .eq. 0) then ! NOUSE(0) open(unit=i, file=cfn, action=cact, err=99) finuse(i) = 1 ! INUSE(1) uid = i fopen = i if (act .eq. 82) then ! READ(LETR) flastc(i) = 81 ! MAXCARD+1(81) fbuf(i,81) = 10 ! NEWLINE(10) fbuf(i,82) = -2 ! EOS(-2) fmode(i) = 82 ! READ(LETR) else if (act .eq. 87) then ! WRITE(LETW) flastc(i) = 0 fmode(i) =87 ! WRITE(LETW) end if return endif i = i + 1 end while 99 continue uid = -1 ! ERR(-1) fopen = -1 ! ERR(-1) return end
includeは、Watcom Fortran 77の機能で、'files.fi'をコンパイル時に、読み込みます。
この中で、is2cs()は、integer*1の文字列をcharacter型の 文字列に変換するものです。
c is2cs -- copy integer string to character string subroutine is2cs(is,cs,maxsiz) integer*1 is(*) character cs(maxsiz) integer maxsiz character char integer i i = 1 ! clear character string while (i .le. maxsiz) do cs(i) = ' ' i = i + 1 end while i = 1 while (is(i) .ne. -2) do ! EOS(-2) if (i .ge. maxsiz) then ! MAXNAME(261) exit end if cs(i) = char(is(i)) i = i + 1 end while return end
files.fiは下記の通りです。
c files.fi -- file interface common valiables common /files/finuse,fbuf,flastc,fmode integer finuse(20) ! inuse flag MAXFILES(20) integer*1 fbuf(20,82) ! I/O buffer MAXFILES(20) MAXLINE(81)+1 integer flastc(20) ! characters in I/O buffer MAXFILES(20) integer*1 fmode(20) ! READ/WIRTE flag MAXFILES(20)
- finuse(i) : 装置番号iが使用中ならばINUSE、そうでなければNOUSE
- fbuf(i,82) : i番目の装置の入出力バッファー
- flastc(i) : i番目の装置の次の読み出し文字位置、または、次の書き出し位置
- fmode(i) : i番目の装置が入出力モード
fopen()の逆で、ファイルを切り離すfclose()を示します。これは、Watcom Fortran 77のclose()に皮をかぶせたものです。 uid=5,6を除外しているのは、標準入力と標準出力だからです。
c fclose.for -- disconnect internal filedescripter and extenal file subroutine fclose(uid) integer uid include 'files.fi' if (.not. ((uid .eq. 5) .or. (uid .eq. 6))) then if (fmode(uid) .eq. 87) then ! WRITE(LETW) call fputc(uid,-1) ! flush buffer by put EOF end if close(unit=uid, status='keep') finuse(uid) = 0 ! NOUSE(0) uid = 0 end if return end
'files.fi'にある変数を、fopen(),fclose()などを使う前に初期化する必要があります。初期化 モジュールinitfile()を作成します。標準入力と標準出力は事前にオープンする必要がないため、 読み出し位置、書き出し位置の初期値をここで設定します。
c initfile.for -- setup file manage array funit subroutine initfile() integer i include 'files.fi' i = 1 while (i .le. 20) do ! MAXFILES(20) finuse(i) = 0 ! NOUSE(0) i = i + 1 end while finuse(5) = 1 ! INUSE(1) for STDIN flastc(5) = 81 ! lastc of read buffer fbuf(5,81) = 10 ! NEWLINE(10) fbuf(5,82) = -2 ! EOS(-2) fmode(5) = 82 ! READ(LETR) finuse(6) = 1 ! INUSE(1) for STDOUT flastc(6) = 0 ! lastc of write buffer fmode(6) = 87 ! WRITE(LETW) return end
これらをコンパイルするのに、fc.batに修正が必要です。includeするファイルをサーチする場所を指定するオプションを 追加します。
@echo off rem fc2.for wfc386 ..\src\%1.for /INCPATH=..\src move ..\bat\%1.obj ..\obj
最近のコメント