packages feed

language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/general/filesys.mod

IMPLEMENTATION MODULE FileSys;

   (****************************************************************)
   (*                      *)
   (*       File operations.        *)
   (*                      *)
   (*  Programmer:      P. Moylan            *)
   (*  Last edited:  6 September 1993        *)
   (*  Status:    Working              *)
   (*                      *)
   (****************************************************************)

IMPORT FIO;

FROM Str IMPORT Caps, Compare;

(************************************************************************)
(*        TRANSLATING THE LIBRARY ERROR CODES         *)
(************************************************************************)

PROCEDURE IOstatus(): ErrorCode;

    (* Returns the status of the last I/O operation.  We do a "best  *)
    (* guess" approximation to the error code.           *)

    BEGIN
   CASE FIO.IOresult() OF
     0:  RETURN OK;
    |
     0A0H:  RETURN FileNotOpen;
    |
     0A2H:  RETURN NameNotFound;
    |
     0A5H:  RETURN DeviceFull;
    |
    ELSE
		RETURN UndiagnosedFailure;
	END (*CASE*);
    END IOstatus;

(************************************************************************)
(*			     OPENING A FILE				*)
(************************************************************************)

PROCEDURE OpenFile (VAR (*OUT*) f: File;  name: ARRAY OF CHAR;
					newfile: BOOLEAN): ErrorCode;

    (* Opens the file named by the given character string, and returns	*)
    (* f as the identification to be used when specifying this file in	*)
    (* future.  If newfile is TRUE, a new file is created.  If newfile	*)
    (* is FALSE, the file must already exist.				*)

    VAR FileExists: BOOLEAN;

    BEGIN
	Caps (name);
	IF Compare (name, "PRN") = 0 THEN
	    f := FIO.PrinterDevice;
	    RETURN OK;
	END (*IF*);
	FileExists := FIO.Exists(name);
	IF newfile THEN
	    IF FileExists THEN RETURN DuplicateFileName;
	    ELSE
		f := FIO.Create(name);
		RETURN IOstatus();
	    END (*IF*);
	ELSIF FileExists THEN
	    f := FIO.Open(name);
	    IF f = MAX(CARDINAL) THEN RETURN NameNotFound
	    ELSE RETURN IOstatus();
	    END (*IF*);
	ELSE
	    RETURN NameNotFound;
	END (*IF*);
    END OpenFile;

(************************************************************************)
(*			     CLOSING A FILE				*)
(************************************************************************)

PROCEDURE CloseFile (VAR (*INOUT*) f: File);

    (* Closes file f. *)

    VAR dummy: CARDINAL;

    BEGIN
	FIO.Close(f);
	dummy := FIO.IOresult();
    END CloseFile;

(************************************************************************)
(*			    END-OF-FILE TEST				*)
(************************************************************************)

PROCEDURE EOF (f: File): BOOLEAN;

    (* Returns TRUE iff we are currently at the end of file f.		*)
    (* Remark: the library procedure FIO.EOF is inadequate for this	*)
    (* purpose, because (a) it is only updated after a read, and	*)
    (* (b) there is no feedback about WHICH file has reached its end.	*)

    BEGIN
	RETURN FIO.GetPos(f) >= FIO.Size(f);
    END EOF;

(************************************************************************)
(*				WRITING					*)
(************************************************************************)

PROCEDURE WriteByte (f: File;  value: BYTE): ErrorCode;

    (* Writes one byte to the file.  The returned value is an error	*)
    (* code (OK if no error).						*)

    BEGIN
	FIO.WrChar (f, value);
	RETURN IOstatus();
    END WriteByte;

(************************************************************************)

PROCEDURE WriteRecord (f: File;  buffaddr: ADDRESS;
					count: CARDINAL): ErrorCode;

    (* Writes count bytes from memory location buffaddr.	*)

    BEGIN
	FIO.WrBin (f, buffaddr^, count);
	RETURN IOstatus();
    END WriteRecord;

(************************************************************************)
(*				READING					*)
(************************************************************************)

PROCEDURE ReadByte (f: File): BYTE;

    (* Returns the next byte from the file.	*)

    BEGIN
	RETURN FIO.RdChar(f);
    END ReadByte;

(************************************************************************)

PROCEDURE ReadRecord (f: File;  buffaddr: ADDRESS;  desired: CARDINAL;
				VAR (*OUT*) actual: CARDINAL): ErrorCode;

    (* Reads up to "desired" bytes from file f to memory location	*)
    (* "buffaddr".  On return, "actual" gives the number of bytes read.	*)

    BEGIN
	actual := FIO.RdBin (f, buffaddr^, desired);
	RETURN IOstatus();
    END ReadRecord;

(************************************************************************)
(*				RANDOM ACCESS				*)
(************************************************************************)

PROCEDURE SetPosition (f: File;  position: LONGCARD): ErrorCode;

    (* Ensures that the next read or write on this file will be at	*)
    (* byte number position in the file.  (The first byte in the file	*)
    (* is byte number 0.)  If a position greater than the file size	*)
    (* is specified, the length of the file will increase.		*)

    VAR size, amount: LONGCARD;

    BEGIN
	size := FIO.Size(f);
	IF position > size THEN
	    FIO.Seek (f, size);
	    IF IOstatus() <> OK THEN
		RETURN SeekFailure;
	    END (*IF*);
	    amount := position - size;
	    WHILE amount > MAX(CARDINAL) DO
		FIO.WrCharRep (f, CHR(0), MAX(CARDINAL));
		DEC (amount, VAL(LONGCARD, MAX(CARDINAL)));	
	    END (*WHILE*);
	    FIO.WrCharRep (f, CHR(0), VAL(CARDINAL,amount));	
	END (*IF*);
	FIO.Seek (f, position);
	IF IOstatus() <> OK THEN RETURN SeekFailure;
	ELSE RETURN OK;
	END (*IF*);
    END SetPosition;

(************************************************************************)

PROCEDURE SavePosition (f: File): LONGCARD;

    (* Returns the current byte number in file f.	*)

    BEGIN
	RETURN FIO.GetPos(f);
    END SavePosition;

(************************************************************************)

PROCEDURE FileSize (f: File): LONGCARD;

    (* Returns the length of the file in bytes.	*)

    BEGIN
	RETURN FIO.Size(f);
    END FileSize;

(************************************************************************)

BEGIN
    FIO.IOcheck := FALSE;
END FileSys.