Simula contains a hierarchy of files for both formatted and un-formatted I/O:
Note that all files share a common ancestor in the prefix hierarchy: "file". You can also create your own sub-classes of these files for further specialization.
The two file objects Sysin (Infile) and Sysout (Printfile) are always connected to the standard input and output channel, respectively. A user program acts as if it were enclosed in the following inspect statements:
inspect Sysin do inspect Sysout do <... user program ...>
In a program, all unqualified calls to Inimage, Inint etc will refer to Sysin (stdin) and all calls to Outimage, Outint etc to Sysout (stdout). stdin and stdout can be redirected in MPW in the customary fashion (< or >).
Note that some name clashes occur: an unqualified reference to Image, Pos, SetPos, Length or More will refer to Sysout, due to the ordering of the inspect's. If you wish to access Sysin's image (pos, ...) you write Sysin.Image (Sysin.Pos, ...)
class file(FILENAME); value FILENAME; text FILENAME; begin Boolean OPEN; ! true if the file is open ; text procedure Filename; Filename:-copy(FILENAME); Boolean procedure Isopen; isopen :=OPEN; Boolean procedure Setaccess(mode);text mode ; ......; if filename==Notext then error("..."); end --- File --- ;
File class Imagefile; begin text Image; ! -- the record buffer, created at "Open"; procedure SetPos(i); integer i; Image.SetPos(i); integer procedure Pos; Pos := Image.Pos; Boolean procedure More; More := Image.More; integer procedure Length; Length := Image.Length; end;
Imagefile class Infile; begin Boolean procedure Open(FileImage); text FileImage; ...; Boolean procedure Close; ...; procedure Inimage; ...; ! -- reads the next input record --> Image; Boolean procedure inRecord; ...; Boolean procedure Endfile; ...; ! -- true if endfile has been read; character procedure Inchar; ...; ! -- gets the next character from Image; Boolean procedure Lastitem; ...; ! -- skips blanks and tabs, true if Endfile; text procedure Intext(N); integer N; ! -- a copy of the next N characters from Image; integer procedure Inint; ! -- skips blanks and tabs, reads next integer; long real procedure Inreal; ! -- skips, reads next real; end;
|inimage||reads the next record to Image, pads with blanks if necessary. Sets Endfile to true and Image to "!25!" if end-of-file (next Inimage will give an error). Note that there is no "end-of-line" character in Simula.|
|inrecord||as Inimage but does not pad with blanks. If the record is longer than Length only the first Length characters are read and inrecord returns the value TRUE. The remaining characters may be read with subsequent calls on inrecord.|
i.e. automatic inimage if Image exhausted, returns the character at Pos and increments Pos.
|lastitem||skips blanks and tabs (with Inchar), if end-of-file is met then returns true else returns false.|
|skips blanks and tabs, returns the next integer (real), changes Pos to the character after the number.|
|intext||returns a copy of the next N characters, which are read with Inchar, so Inimage is automatically called if necessary.|
File class Outfile; begin Boolean procedure Open(Fileimage); text Fileimage; ...; Boolean procedure Close; ...; procedure Outimage; ...; procedure BreakOutimage; ...; procedure OutRecord; ...; procedure Outchar(C); character C; ...; procedure Outtext(T); text T; ...; procedure Outint(Inum,Width); integer Inum,Width; ...; procedure Outfix(Rnum,Ndec,Width); (long) real Rnum; integer Ndec,Width; ...; procedure Outreal(Rnum,Ndec,Width); (long) real Rnum; integer Ndec,Width; ...; end;
|Outimage||Transfers the entire contents of Image + a NEW_LINE character to the external file.
Then it fills Image with blanks and sets Pos to 1. |
[ Note: on UNIX systems, the image has extra blanks stripped off before writing to the file. This is transparent to the programmer since these are restored upon reading.
|BreakOutimage||Outputs the contents of Image, up to Pos, without adding a "new line". Then it fills Image with blanks and sets Pos to 1. Mostly useful in interactive I/O, e.g. when writing a prompt.|
|Outrecord||Transfers the contents of Image, up to Pos, to the external file. No blank-filling, Pos is set to 1.|
|Stores a character or a text in Image. Automatic Outimage if not enough room in Image.|
|Outint||Edits an integer right-adjusted in the next Width positions of Image
(automatic Outimage if necessary). Error if Width not large enough.
|Outfix||Analogous, real number in fix format with Ndec decimals.|
|Outreal||Analogous, real number in scientific format.|
Outfile class Printfile; begin Boolean procedure Open(Fileimage); text Fileimage; ...; Boolean procedure Close; ...; integer procedure Line; ! -- return number of current line (relative to page start); integer procedure Page; ! -- return current page number; integer procedure LinesPerPage(N); integer N; ...; ! -- set page size to N lines, return -- previous value; procedure Spacing(N); integer N; ...; ! -- set line distance to N (default 1); procedure Eject(N); ...; integer N; ! -- position to line N, Eject(1) gives new page; procedure Outimage; ...; ! -- as in Outfile but increments line (& page) number; procedure Outrecord;...; ! -- analogous; end;
ref(Infile) Input; ref(Outfile) Output; Input :- new Infile("in"); if not Input.Open(Blanks(132)) then Error("Input file does not exist"); Output :- new Outfile("out"); Output.Open(Blanks(132)); Input.Inimage; while not Input.Endfile do begin Output.Image := Input.Image; Output.Outimage; Input.Inimage; end; Input.Close; Output.Close;A more efficient solution with shared buffers:
Open the output file in this way: Output.Open(INPUT.IMAGE); then copy: while not Input.Endfile do begin Output.Outimage; ! same buffer!; Input.Inimage; end;
Imagefile class Directfile; begin integer procedure Location; ...; ! -- current record number; procedure Locate(N); integer N; ...; ! -- set current record number to N; integer procedure LastLoc; ...; ! -- highest record number written; integer procedure MaxLoc; ...; ! -- highest permissible record number; Boolean procedure DeleteImage; ! -- delete current record; end;
|Location||Gives access to the ordinal number of the current record (1..., set to 1 when the file is opened). Each call to Inimage or Outimage will increment the ordinal number by 1.|
|Locate||Sets the current record number. No transfer to/from the external file is performed until Inimage/Outimage is called. If the number is > LastLoc, a call to Inimage will result in Endfile being true. If the number is <= LastLoc but refers to a record which has not been written, a call to Inimage will result in the Image being filled with null characters ('!0!').|
|LastLoc||The largest ordinal number of any written record.|
|MaxLoc||The highest permissible value of the record ordinal number.|
|DeleteImage||Makes the current record "unwritten".|
NOTE: The input routines (Inchar, Inint etc.) in directfiles skips all unwritten records.
A KeyFile allows access by KEY to variable length records.
KeyFiles are not part of the Standard SIMULA language. They are a Montreal addition defined by the external CLASS Keyfile (which uses the "textUtil CLASS). These are available under the "-diro" SIM compiler option.
Directfile class KeyFile( HashSize ); integer HashSize; begin Procedure CLOSE; ... ; Text Procedure READ ( Key ); Text Key ; Procedure WRITE ( Key, Data ); Text Key, Data ; Procedure DELETE( Key ); Text Key; end;To simplify use, the IMAGE length of a KeyFile is predefined at 60 and Keyfiles are opened automatically at creation. The user must still take care to CLOSE the file or else the FREELIST of available physical records will be corrupted.
|WRITE( Key, Data)||Writes out a record with both Key and the Data. If a record with the same KEY already exists, it is overwritten|
|READ (Key)||If a record with this Key exists, returns a text with the DATA of the record. If such a record is not found, returns a one byte text containing "!0!".|
|DELETE (Key)||Removes the record with this key. NOP is such a record doesn't exist.|
|CLOSE||Writes out the internal FreeList and updates RECORD 1.|
begin external class keyfile; external class textutil; ref(KeyFile) F; integer i; Text Key, data; F :- new KeyFile("t1.60",10); for i := 1 step 1 until 10 do begin Key :- int_as_text(i); F.WRITE(Key,"Contenu de l'enregistrement....."); end; F.DELETE( int_as_text(3) ); for i := 1 step 1 until 10 do begin Key :- int_as_text(i); data :- F.READ(Key); outint(i,3); outtext(Key & ": " & data); outimage; end; F.CLOSE; end
class Bytefile; begin short integer procedure ByteSize; ...; ! -- returns 8; end;
Bytefile class Inbytefile; begin Boolean procedure Open; ...; ! -- note that the byte buffer is internal to the file; Boolean procedure Close; ...; Boolean procedure Endfile; ...; ! -- true if there are no more bytes to read; short integer procedure Inbyte; ...; ! -- the ASCII number of the input byte, sets -- Endfile and returns 0 if no more bytes; text procedure Intext(T); text T; begin ! -- fills the frame of the text T with successive input bytes; T.Setpos(1); while T.More and not Endfile do T.Putchar(Char(Inbyte); if Endfile then T.Setpos(T.Pos-1); Intext :- T.Sub(1,T.Pos-1); end; end;
Bytefile class Outbytefile; begin Boolean procedure Open; ...; ! -- note that the byte buffer is internal to the file; Boolean procedure Close; ...; procedure Outbyte(X); short integer X; ...; ! -- writes a byte X; procedure Outtext(T); text T; begin ! -- outputs all the characters in T as bytes; T.Setpos(1); while T.More do Outbyte(Rank(T.Getchar)); end; end;
Bytefile class Directbytefile; begin integer procedure Location; ...; ! -- current byte number; procedure Locate(N); integer N; ...; ! -- set current byte number to N; integer procedure LastLoc; ...; ! -- highest byte number written; integer procedure MaxLoc; ...; ! -- highest permissible byte number; end;
|Location||Gives access to the ordinal number of the current byte (1..., set to 1 when the file is opened). Each call to Inbyte or Outbyte will increment the ordinal number by 1.|
|Locate||Sets the current byte number. No transfer to/from the external file is performed until Inbyte/Outbyte is called. If the number is > LastLoc, a call to Inbyte will result in Endfile being true. If the number is <= LastLoc but refers to a byte which has not been written, a call to Inbyte will return 0.|
|LastLoc||The largest ordinal number of any written byte.|
|MaxLoc||The highest permissible value of the byte ordinal number.|
Boolean procedure Setaccess(Mode); text Mode; ...;With this function you can control creation and other aspects of a file. The mode string is not case-sensitive. The function returns true if the call succeeds, false if it fails. The default values of the modes are given in the following table.
|Mode:||InXfile||OutXfile||DirectXfile||Takes effect at|
(NA = Not Applicable)
ref(Directfile) DF; Outtext("Enter file name: "); BreakOutimage; Inimage; DF :- new Directfile(Sysin.Image.Strip); DF.Setaccess("AnyCreate"); if not DF.Open(Blanks(30)) then Error("Could not open " & DF.Filename);
inspect new Directbytefile("temp") do begin Open; ...; Setaccess("Purge"); Close; end;
|Create||The external file must not exist at Open; if it does, Open returns false. A new file is created by the environment.|
|NoCreate||The external file MUST exist at Open.|
|AnyCreate||If the external file does exist at Open, it is opened, otherwise a new file is created.|
|Note that "NoCreate" is the default for DirectXfiles!|
|Purge||The external file is deleted by the environment when it is closed.|
|NoPurge||The external file is not deleted.|
|Append||Output to the file is added to the existing contents of the file. For Directfiles, "Append" prohibits output before LastLoc.|
|NoAppend||For sequential Outfiles, implies that, after Close, the external file will only contain the output produced while the file was open.|
|ReadOnly||Output operations cannot be performed on the file.|
|WriteOnly||Input operations cannot be performed.|
|ReadWrite||Both input and output operations can be performed.|
|Note that the readwrite mode only is relevant for Directfiles.|