Modula-2でプログラミング -- FileSearch ファイルを探すモジュールの制作 ― 2024年10月19日 09:49
ファイルを探すことは、結構よくあることです。CP/Mでプログラムを作る場合でも同じこと。 今回は、Modula-2からBDOSの機能を呼び出し、ファイルを探す"FileSearch"モジュールを紹介します。
"FileSearch"モジュールは、処理系が提供するモジュールをいくつか使用しています。
- "OpSys"モジュールは、BDOSやBIOSを呼び出すためのBdos手続きやFCBなどのレコード型などを提供しています。
- "FileNames"モジュールは、FCBのファイル名領域にファイル名を設定する手続きや、その手続きの戻り値の型を提供しています。
- "SYSTEM"モジュールは、メモリーの動的確保や変数のサイズなどを調べる手続きを提供しています。
このほかに自作モジュール"BdosStruct"があります。これは、BDOSを呼び出すBdos手続きがちょっと使いにくかったので、
処理系を騙す仕組みを作り込みました。
"FileSearch"モジュールのDefinition Moduleです。
DEFINITION MODULE FileSearch;
FROM InOut IMPORT Write,WriteString,WriteLn;
FROM OpSys IMPORT FCB,CPMStringBuffer,BdosFunctions,Bdos;
FROM SYSTEM IMPORT ALLOCATE,SIZE,ADR,WORD;
FROM FileNames IMPORT StrToFCB,NameState;
FROM BdosStruct IMPORT BdosCommand,BdosReturn;
EXPORT QUALIFIED pFileList,FileList,FileStruct,DMA,
LoginDisk,MakeFileList,DumpFileList;
CONST
DMABufferSize = 128;
TYPE
FileStruct = RECORD
CASE BOOLEAN OF
TRUE: Disk: CHAR;
Fill1: CHAR;
Name: ARRAY [0..7] OF CHAR;
Fill2: CHAR;
Extention: ARRAY [0..2] OF CHAR;
| FALSE: Text: ARRAY [0..13] OF CHAR;
END;
END;
pFileList = POINTER TO FileList;
FileList = RECORD
File: FileStruct;
Next: pFileList;
END;
DMA = ARRAY [0..DMABufferSize-1] OF CHAR;
PROCEDURE LoginDisk(FCBBuf: FCB): CHAR;
PROCEDURE MakeFileList(FileMatch: ARRAY OF CHAR): pFileList;
PROCEDURE DumpFileList(pList: pFileList);
END FileSearch.
Imprementation Moduleは、このとおり。
IMPLEMENTATION MODULE FileSearch;
FROM InOut IMPORT Write,WriteString,WriteLn;
FROM OpSys IMPORT FCB,BdosFunctions,Bdos;
FROM SYSTEM IMPORT ALLOCATE,SIZE,ADR,WORD;
FROM FileNames IMPORT StrToFCB,NameState;
FROM BdosStruct IMPORT BdosCommand,BdosReturn,FileStruct,DMA;
PROCEDURE LoginDisk(FCBBuf: FCB): CHAR;
VAR
BdosCmd: BdosCommand;
Junk: WORD;
DiskCode: BdosReturn;
BEGIN
IF FCBBuf.name.disk = 0C THEN
BdosCmd.Func := retCDsk;
Bdos(BdosCmd.Cmd,Junk,DiskCode.Rc);
RETURN (CHR(ORD(DiskCode.Cc)+ORD('A')));
ELSE
RETURN (CHR(ORD(FCBBuf.name.disk)+ORD('A')-1));
END;
END LoginDisk;
PROCEDURE MakeFileList(FileMatch: ARRAY OF CHAR): pFileList;
VAR
Disk: CHAR;
FCBBuffer: FCB;
BdosFunc: BdosCommand;
BdosRc: BdosReturn;
DMABuffer: DMA;
ToPos, FromPos: CARDINAL;
NameStatus: NameState;
pList: pFileList;
pNewFile: pFileList;
NewFile: FileList;
Junk: WORD;
BEGIN
(* Clear FCB Buffer and set file name *)
FCBBuffer.name.text := '';
FCBBuffer.rest := '';
NameStatus := StrToFCB(FileMatch,FCBBuffer.name);
(* get target disk *)
Disk := LoginDisk(FCBBuffer);
(* set DMA Bufer *)
BdosFunc.Func := setDMA;
Bdos(BdosFunc.Cmd,ADR(DMABuffer),Junk);
(* initialize File Name List pointer *)
pList := NIL;
(* find first much file *)
BdosFunc.Func := searchFst;
Bdos(BdosFunc.Cmd,ADR(FCBBuffer),BdosRc.Rc);
WHILE BdosRc.Cc # 255 DO
(* copy from FCB buffer to file struct *)
ALLOCATE(pNewFile,SIZE(NewFile));
pNewFile^.File.Disk := Disk;
pNewFile^.File.Fill1 := ':';
ToPos := 0;
FOR FromPos := 1 TO 8 DO
pNewFile^.File.Name[ToPos]
:= DMABuffer[FromPos+BdosRc.Cc*32];
INC(ToPos);
END;
pNewFile^.File.Fill2 := '.';
ToPos := 0;
FOR FromPos := 9 TO 11 DO
pNewFile^.File.Extention[ToPos]
:= DMABuffer[FromPos+BdosRc.Cc*32];
INC(ToPos);
END;
(* insert new one *)
pNewFile^.Next := pList;
pList := pNewFile;
(* find next file *)
BdosFunc.Func := searchNxt;
Bdos(BdosFunc.Cmd,Junk,BdosRc.Rc);
END;
RETURN pList
END MakeFileList;
PROCEDURE WriteFileStruc(FileStruc: FileStruct);
BEGIN
Write(FileStruc.Disk);
Write(FileStruc.Fill1);
WriteString(FileStruc.Name);
Write(FileStruc.Fill2);
WriteString(FileStruc.Extention);
WriteLn;
END WriteFileStruc;
PROCEDURE DumpFileList(pList: pFileList);
BEGIN
WHILE pList # NIL DO
WriteFileStruc(pList^.File);
pList := pList^.Next;
END;
END DumpFileList;
END FileSearch.
MakeFileList手続きが処理の中心です。ファイルを探すにはBDOSの機能番号16 最初のデータを探す(SearchFirst)、 機能番号17 次にデータを探す(SearchNext)を使います。 はじめに、FCBとDMAを準備します。そして、FCB領域を初期化します。
(* Clear FCB Buffer and set file name *)
FCBBuffer.name.text := '';
FCBBuffer.rest := '';
NameStatus := StrToFCB(FileMatch,FCBBuffer.name);
ここで躓きました。"FCBBuffer.rest"を初期化をしなかったために、
最初のデータを取得できたりできなかったりと、動作が不安定でした。
アセンブラでテストルーチンを書くとうまく動作します。悩みました。
使用したアセンブラでは、確保したデータ領域を自動的に0を埋め込んでいました。
しかし、Modula-2処理系では領域内の値は不定になるため、動作がおかしくなった様です。
最初のデータを見つけてしまえば、後は順に見つけることができました。
見つけたファイル名をリスト構造にして、返します。
DumpFileList手続きは、ファイル名リストを表示します。下受けルーチンとして、WriteFileStruc手続きを 使っています。
特に難しいロジックはありません。
BdosStructは、Definition Moduleだけです。以下のようになっています。
DEFINITION MODULE BdosStruct;
FROM OpSys IMPORT BdosFunctions;
FROM SYSTEM IMPORT WORD;
EXPORT QUALIFIED
BdosCommand,BdosReturn;2
TYPE
BdosCommand = RECORD
CASE BOOLEAN OF
TRUE: Func: BdosFunctions;
| FALSE: Cmd: WORD;
END;
END;
BdosReturn = RECORD
CASE BOOLEAN OF
TRUE: Rc: WORD;
| FALSE: Cc: CARDINAL;
END;
END;
END BdosStruct.
次回は、これを応用したファイルマッチで指定されたファイルをリストするコマンド"FileFind"紹介します。
最近のコメント