DEFINITION MODULE FileSystem; (* file manipulation routines Derived from the Modula-2 system developed by the group of Prof. N. Wirth, ETH Zurich, Switzerland. *) FROM SYSTEM IMPORT ADDRESS, WORD; EXPORT QUALIFIED (* file operations: *) File, Response, Command, Create, Close, Lookup, Rename, Delete, SetRead, SetWrite, SetModify, SetOpen, Doio, SetPos, GetPos, Length, (* Streamlike I/O: *) Flag, FlagSet, Reset, Again, ReadWord, ReadChar, ReadByte, ReadNBytes, WriteWord, WriteChar, WriteByte, WriteNBytes, (* Medium Handling: *) FileProc, DirectoryProc, MediumType, CreateMedium, RemoveMedium, FileNameChar; TYPE MediumHint = CARDINAL; (*- medium index used in DiskFiles *) MediumType = ARRAY [0..2] OF CHAR; (*- medium name (A, B...) *) Flag = (er, ef, rd, wr, ag, txt); (*- status flag for file operations er = error occured, ef = end-of-file reached, rd = in read mode, wr = in write mode, ag = "Again" has been called after last read, txt = text-file (the last access to the file was a 'WriteChar' or 'ReadChar'). *) FlagSet = SET OF Flag; (*- status flag set *) Response = (done, notdone, notsupported, callerror, unknownmedium, unknownfile, paramerror, toomanyfiles, eom, userdeverror); (*- result of a file operation *) Command = (create, close, lookup, rename, delete, setread, setwrite, setmodify, setopen, doio, setpos, getpos, length); (*- commands passed to DiskFiles *) BuffAdd = POINTER TO ARRAY [0..0FFFEH] OF CHAR; (*- file buffer pointer type *) File = RECORD bufa: BuffAdd; (* Buffer Address *) buflength: CARDINAL; (* size of buffer in bytes. In the current release it is always a multiple of 128 *) validlength: CARDINAL; (* Number of valid bytes in the buffer. *) bufind: CARDINAL; (* Byte-Index of current position in the buffer *) flags: FlagSet; (* status of the file *) eof: BOOLEAN; (* TRUE, if last access was past end of file *) res: Response; (* result of last operation *) lastRead:CARDINAL;(* the last read word or byte (char) *) mt: MediumType; (* selects the driver that supports that file *) fHint: CARDINAL; (* internally used by the device-driver *) mHint: MediumHint; (* internally used by medium-handler *) CASE com: Command OF lookup: new: BOOLEAN; | setpos, getpos, length: highpos, lowpos: CARDINAL; END; END; (*- file structure used for bookkeeping by DiskFiles *) PROCEDURE Create (VAR f: File; mediumName: ARRAY OF CHAR); (*- create a temporary file in: mediumName name of medium to create file on, in char format out: f initialized file structure A temporary file is characterised by an empty name. To make the file permanent, it has to be renamed with a non-empty name before closing it. For subsequent operations on this file, it is referenced by "f". *) PROCEDURE Close (VAR f: File); (*- Close a file in: f structure referencing an open file out: f the field f.res will be set appropriately. Terminates the operations on file "f". If "f" is a temporary file, it will be destroyed, whereas a file with a non-empty name remains on its medium and is accessible through "Lookup". When closing a text-file after writing, the end-of-file code 32C is written on the file (MS-DOS and CP/M convention). *) PROCEDURE Lookup (VAR f: File; filename: ARRAY OF CHAR; newFile: BOOLEAN); (*- look for a file in: filename drive and name of file to search for newFile TRUE if file should be created if not found out: f initialized file structure; f.res will be set appropriately. Searches the medium specified in "filename" for a file that matches the name and type given in "filename". If the file is not found and "newFile" is TRUE, a new (permanent) file with the given name and type is created. If it is not found and "newFile" is FALSE, no action takes place and "notdone" is returned in the result field of "f". *) PROCEDURE Rename (VAR f: File; newname: ARRAY OF CHAR); (*- rename a file in: f structure referencing an open file newname filename to rename to, with device:name.type specified out: f file name in f will be changed and the f.res field will be set appropriately. The medium, on which the files reside can not be changed with this command. The medium name inside "newname" has to be the old one. *) PROCEDURE Delete (name: ARRAY OF CHAR; VAR f: File); (*- delete a file in: name name of file to delete, with dev:name.type specified out: f the result field f.res will be set appropriately. *) PROCEDURE ReadWord (VAR f: File; VAR w: WORD); (*- Returns the word at the current position in f in: f structure referencing an open file out: w word read from file f the result field f.res will be set appropriately. the file will be positioned at the next word when the read is done. *) PROCEDURE WriteWord (VAR f: File; w: WORD); (*- Write one word to a file in: f structure referencing an open file w word to write out: f the field f.res will be set appropriately. *) PROCEDURE ReadChar (VAR f: File; VAR ch: CHAR); (*- Read one character from a file in: f structure referencing an open file out: ch charatcter read from file f the result field f.res will be set appropriately. the file will be positioned at the next character when the read is done. *) PROCEDURE WriteChar (VAR f: File; ch: CHAR); (*- Write one character to a file in: f structure referencing an open file ch character to write out: f the result field f.res will be set apporopriately. *) PROCEDURE ReadByte (VAR f: File; VAR b: CHAR); (*- Read one byte from a file in: f structure referencing an open file out: b byte read from file f the result field f.res will be set appropriately. the file will be positioned at the next byte when the read is completed. *) PROCEDURE WriteByte (VAR f: File; b: CHAR); (*- Write one byte to a file in: f structure referencing an open file b byte to write out: f the result field f.res will be set appropriately. *) PROCEDURE ReadNBytes (VAR f: File; bufPtr: ADDRESS; requestedBytes: CARDINAL; VAR read: CARDINAL); (*- Read a specified number of bytes from a file in: f structure referencing an open file bufPtr pointer to buffer area to read bytes into requestedBytes number of bytes to read out: bufPtr^ bytes read from file f the result field f.res will be set appropriately. read the number of bytes actually read. the file will be positioned at the next byte after the requested string. *) PROCEDURE WriteNBytes (VAR f: File; bufPtr: ADDRESS; requestedBytes: CARDINAL; VAR written: CARDINAL); (*- Write a specified number of bytes to a file in: f structure referencing an open file bufPtr pointer to string of bytes to write requestedBytes number of bytes to write out: f the result field f.res will be set appropriately. written the number of bytes actually written *) PROCEDURE Again (VAR f: File); (*- returns a character to the buffer to be read again in: f structure referencing an open file out: f the f.res field will be set appropriately. This should be called after a read operation only (it has no effect otherwise). It prevents the subsequent read from reading the next element; the element just read before will be returned a second time. Multiple calls to Again without a read in between have the same effect as one call to Again. The position in the file is undefined after a call to Again (it is defined again after the next read operation). *) PROCEDURE SetRead (VAR f: File); (*- Set the file in reading-state, without changing the current position. in: f structure referencing an open file out: f f.res will be set appropriately. Upon calling SetRead, the current position must be before the eof. In reading-state, no writing is allowed. *) PROCEDURE SetWrite (VAR f: File); (*- Sets the file in writing-state, without changing the current position. in: f structure referencing an open file out: f f.res will be set appropriately. Upon calling SetWrite, the current position must be a legal position in the file (including eof). In writing-state, no reading is allowed, and a write always takes place at the eof. The current implementation does not truncate the file. *) PROCEDURE SetModify (VAR f: File); (*- Sets the file in modifying-state, without changing the current position. in: f structure referencing an open file out: f f.res will be set appropriately. Upon calling SetModify, the current position must be before the eof. In modifying-state, reading and writing are allowed. Writing is done at the current position, overwriting whatever element is already there. The file is not truncated. *) PROCEDURE SetOpen (VAR f: File); (*- Set the file to opened-state, without changing the current position. in: f structure referencing an open file out: f f.res will be set appropriately. The buffer content is written back on the file, if the file has been in writing or modifying status. The new buffer content is undefined. In opened-state, neither reading nor writing is allowed. *) PROCEDURE Reset (VAR f: File); (*- Set the file to opened state and position it to the top of file. in: f structure referencing an open file out: f f.res will be set appropriately. *) PROCEDURE SetPos (VAR f: File; high, low: CARDINAL); (*- Set the current position in file in: f structure referencing an open file high high part of the byte offset low low part of the byte offset out: f f.res will be set appropriately. The file will be positioned (high*2^16 +low) bytes from top of file. *) PROCEDURE GetPos (VAR f: File; VAR high, low: CARDINAL); (*- Return the current byte position in file in: f structure referencing an open file out: high high part of byte offset low low part of byte offset The actual position is (high*2^16 +low) bytes from the top of file. *) PROCEDURE Length (VAR f: File; VAR high, low: CARDINAL); (*- Return the length of the file in bytes. in: f structure referencing an open file. out: high high part of byte offset low ;pw part of byte offset The actual length is (high*2^16 +low) bytes. *) PROCEDURE Doio (VAR f: File); (*- Do various read/write operations on a file in: f structure referencing an open file out: f f.res will be set appropriately. The exact effect of this command depends on the state of the file (flags): opened = NOOP. reading = reads the record that contains the current byte from the file. The old content of the buffer is not written back. writing = the buffer is written back. It is then assigned to the record, that contains the current position. Its content is not changed. modifying = the buffer is written back and the record containing the current position is read. Note that 'Doio' does not need to be used when reading through the 'stream-like' I/O routines. Its use is limited to special applications. *) PROCEDURE FileNameChar (c: CHAR): CHAR; (*- Check the character c for legality in an MS-DOS filename. in: c charater to check out: 0C for illegal characters and c otherwise; lowercase letters are transformed into uppercase letters. *) TYPE FileProc = PROCEDURE (VAR File); (*- Procedure type to be used for internal file operations A procedure of this type will be called for the functions: setread, setwrite, setmodify, setopen, doio, setpos, getpos, length, setprotect, getprotect, setpermanent, getpermanent. *) DirectoryProc = PROCEDURE (VAR File, ARRAY OF CHAR); (*- Procedure type to be used for operations on an entire file A procedure of this type will be called for the functions: create, close, lookup, rename, delete. *) PROCEDURE CreateMedium (mt: MediumType; fproc: FileProc; dproc: DirectoryProc; VAR done: BOOLEAN); (*- Install the medium "mt" in the file system in: mt medium type to install fproc procedure to handle internal file operations dproc procedure to handle operations on an entire file out done TRUE if medium was successfully installed. Before accessing or creating a file on a medium, this medium has to be announced to the file system by means of the routine CreateMedium. FileSystem calls "fproc" and "dproc" to perform operations on a file of this medium. Up to 24 mediums can be announced. *) PROCEDURE RemoveMedium (mt: MediumType; VAR done: BOOLEAN); (*- Remove the medium "mt" from the file system in: mt medium type to remove out: done true if medium was successfully removed Attempts to access a file on this medium result in an error (unknownmedium). *) END FileSystem.