Modula-2でプログラミング -- FileSearch ファイルを探すモジュールの修正2024年11月02日 10:29

前回、ファイルを探すモジュール"FileSearch"を制作しました。これを利用したプログラムを いくつか作成して見た所、ファイル名リストのデータ構造の使い勝手が良くないことがわかりました ので"FileSearch"モジュールを修正しました。

修正した"FileSearch"モジュールのDefinition Moduleです。

DEFINITION MODULE FileSearch;

FROM OpSys IMPORT FCB,FCBFileName;

EXPORT QUALIFIED pFileList,FileNameNode,DMA,
	LoginDisk,MakeFileList,DumpFileList;

CONST
	DMABufferSize = 128;
	FileNameSize = 14;

TYPE
	pFileList = POINTER TO FileNameNode;
	FileNameNode = RECORD
		FileName: ARRAY [0..FileNameSize] OF CHAR;
		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 WriteHex,Write,WriteString,WriteLn;
FROM OpSys IMPORT FCB,FCBFileName,BdosFunctions,Bdos;
FROM SYSTEM IMPORT ALLOCATE,TSIZE,ADR,WORD;
FROM FileNames IMPORT StrToFCB,FCBToStr,NameState;

CONST
	EOS = 0C;

PROCEDURE LoginDisk(FCBBuf: FCB): CHAR;
VAR
	DiskCode: CARDINAL;
	Junk: WORD;

BEGIN
	IF FCBBuf.name.disk = 0C THEN
		Bdos(retCDsk,Junk,DiskCode);
		RETURN (CHR(ORD(DiskCode)+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;
	BdosRc: CARDINAL;
	DMABuffer: DMA;
	CPos: CARDINAL;
	NameStatus: NameState;
	pList: pFileList;
	pNewFileName: pFileList;
	FCBFile: FCBFileName;
	Formatted: BOOLEAN;
	Junk: WORD;

BEGIN
	pList := NIL;

	(* Clear FCB Buffer and set file name *)
	FCBBuffer.name.text := '';
	FCBBuffer.rest := '';
	NameStatus := StrToFCB(FileMatch,FCBBuffer.name);

	Disk := LoginDisk(FCBBuffer);

	(* set DMA Bufer *)
	Bdos(setDMA,ADR(DMABuffer),Junk);

	(* find first much file *)
	Bdos(searchFst,ADR(FCBBuffer),BdosRc);
	WHILE BdosRc # 255 DO
		ALLOCATE(pNewFileName,TSIZE(FileNameNode));
		FOR CPos := 0 TO 11 DO
			FCBFile.text[CPos]
				:= DMABuffer[CPos+BdosRc*32]
		END;
		FCBFile.disk := CHR(ORD(Disk) - ORD('A') + 1);
		FCBToStr(FCBFile,pNewFileName^.FileName,FALSE);
		pNewFileName^.Next := pList;
		pList := pNewFileName;

		(* find next file *)
		Bdos(searchNxt,Junk,BdosRc);
	END;	
	RETURN pList
END MakeFileList;

PROCEDURE WriteFileName(FileName: ARRAY OF CHAR);
BEGIN
	WriteString(FileName);
	WriteLn
END WriteFileName;

PROCEDURE DumpFileList(pList: pFileList);
BEGIN
	WHILE pList # NIL DO
		WriteFileName(pList^.FileName);
		pList := pList^.Next;
	END;
END DumpFileList;
END FileSearch.


大きな修正点は、見つかったファイルの名前をFCB形式からべたな文字列のファイル名に変換し、 それを保存している点です。 ファイル名の持ち方をべたな文字列にしたので、ファイル名を書き出すPROCEDURE "WriteFileName"を 修正しています。

他には、"BdosStruct"モジュールの使用をやめました。処理系が提供する Bdos関連機能の"OpSys"モジュールを一部修正し、"BdosStruct"モジュールが無くてもコンパイル できるようにしました。

Modula-2でプログラミング -- FileFindの制作2024年11月02日 11:36

FIleSearche"モジュールを利用した、ファイマッチで指定されたファイル一覧を書き出すプログラム "FileFind"を作ってみました。

使い方は、このようにします。

C0#filefind
arguments>f*.mod *.def
C:FIND.MOD
C:FILEFIND.MOD
C:FILESEAR.MOD
C:CONIO.DEF
C:ADD16.DEF
C:SILLY.DEF
C:FILESEAR.DEF
C:STDFILEI.DEF
C:BDOSSTRU.DEF
C:BASICFIL.DEF
C:CMDARGS.DEF
C:SCREEN.DEF     

探すファイル名は、ファイルマッチを指定できます。複数指定できます。 この引数を受け取るには、以前紹介した自作の"CmdArgs"モジュール を使用しています。

プログラムは、このようになりました。

MODULE FileFind;
FROM InOut IMPORT WriteString,WriteLn;
FROM CmdArgs IMPORT Argc,Argv;
FROM FileSearch IMPORT MakeFileList,DumpFileList;

CONST
	MAXLINE = 128;

VAR
	FileMatch: ARRAY [0..MAXLINE-1] OF CHAR;
	nArgc: CARDINAL;
	NthFile: CARDINAL;

PROCEDURE Usage();
BEGIN
	WriteString('Usage: filefind filematch');WriteLn;
END Usage;

BEGIN
	nArgc := Argc();
	IF nArgc < 1 THEN
		Usage();
		HALT;
	END;

	NthFile := 0;
	WHILE NthFile < nArgc DO 
		Argv(NthFile,FileMatch);
		DumpFileList(MakeFileList(FileMatch));
		INC(NthFile);
	END;
END FileFind.


次々にファイルマッチを取り出し、該当するファイル名のリストを"MakeFileList"で作成し、 そのリストを"DumpFileLIst"で書き出します。"DumpFileList"は、"FileSearch"モジュールに実装しました。 こうすることで、ファイル名の保持のしかたをメインルーチンが知る必要がありません。