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だけです。以下のようになっています。
セコメントをする