The semantics of SIMULA I/O facilities rely on the intuitive notion of "files" ("data sets"), i.e. collections of data external to the the program, organized for sequential or random access. In the language, sequential access files are called "sequential files" and random access files "direct files". When it is necessary to distinguish between the file concept of the language and the underlying files of the environment the latter are called external files.
Actually a file may in practice be any kind of external device with communication capabilities, such as a terminal, a sensory device, etc.
Examples of sequential files are:
An example of a direct file is a collection of data items on a disk, with each item identified by a unique integer.
The standard I/O facilities are contained by a class called "BASICIO". They are available to the program through block prefixing as described below.
Note: The use of upper case letters indicates that this identifier is inaccessible to the user program (cf 1.10).
The user's main program acts as if it were embedded as follows:
BASICIO (inlength, outlength) Note ! prefixed block; inspect SYSIN do inspect SYSOUT do begin <external-head> <program> end end prefixed block
In any program execution the unique instance of this prefixed block constitutes the system head of the outermost quasi-parallel system (see 7.2).
The values of inlength and outlength are implementation-defined; they normally depend upon the actual device(s) associated with SYSIN and SYSOUT (the standard input and output files).
SYSIN and SYSOUT may represent the input and output features of an interactive terminal, in which case inlength and outlength are probably equal. In other cases, for example batch runs, SYSIN may represent record-oriented input and SYSOUT may represent line printer oriented output. Typical values of inlength and outlength would then be 80 and 132, resp.
A program may refer to the corresponding file objects through sysin and sysout respectively. Most attributes of these file objects are directly available as the result of the connection blocks enclosing the program.
Note: Within this chapter the term "file object" refers to an instance of one of the classes "in(byte)file", "out(byte)file" and "direct(byte)file" or of a subclass of one of these.
The overall organization of "BASICIO" is as follows:
ENVIRONMENT class BASICIO (INPUT_LINELENGTH, OUTPUT_LINELENGTH); integer INPUT_LINELENGTH, OUTPUT_LINELENGTH; begin ref (infile) SYSIN; ref (printfile) SYSOUT; ref (infile) procedure sysin; sysin :- SYSIN; ref (printfile) procedure sysout; sysout :- SYSOUT; procedure terminate_program; begin ... ; goto STOP end terminate_program; class file ............................ 10.1 ; file class imagefile ....................... 10.3 ; file class bytefile ........................ 10.8 ; imagefile class infile .......................... 10.4 ; imagefile class outfile ......................... 10.5 ; imagefile class directfile ...................... 10.6 ; outfile class printfile ....................... 10.7 ; bytefile class inbytefile ...................... 10.9 ; bytefile class outbytefile ..................... 10.10 ; bytefile class directbytefile .................. 10.11 ; SYSIN :- new infile("..."); ! Implementation-defined SYSOUT :- new printfile("..."); ! files names; SYSIN.open(blanks(INPUT_LINELENGTH)); SYSOUT.open(blanks(OUTPUT_LINELENGTH)); inner; STOP: SYSIN.close; SYSOUT.close end BASICIO;
Note: The files SYSIN and SYSOUT are opened and (if not done explicitly prior to program termination) closed within "BASICIO", i.e. outside the program itself.
The class file and its predefined subclasses are available at any block level of a program (but see (2) of 5.5.1). An implementation may restrict, in any way, the use of these classes for class or block prefixing. An implementation may provide additional subclasses of class file.
Within a program, an object of a subclass of file may represent an external file. The effect of several such file objects representing the same external file is implementation-defined.
The procedure "terminate_program" terminates program execution. It closes SYSIN and SYSOUT. It is implementation-dependent with respect to whether or not other open files are also closed.
class file(FILENAME); value FILENAME; text FILENAME; begin Boolean OPEN; text procedure filename; filename :- copy(FILENAME); Boolean procedure isopen; isopen := OPEN; Boolean procedure setaccess(mode); text mode; ... 10.1.1; if FILENAME = notext then error("..."); end file;
"File" is the common prefix class for all input/output classes.
A file is either open or inaccessible as indicated by the variable "OPEN". The procedure "isopen" returns the current value of "OPEN". A file is initially inaccessible (e.g. closed).
Each file object has a text attribute FILENAME. This text value must at "open" identify an external file which, through an implementation-defined mechanism, becomes associated with the file object. If the parameter value is notext, a run-time error occurs.
The procedure "filename" retrieves the value of FILENAME.
Certain attributes (not specified in the file outline) control the access to the external file. The values of these attributes are set when the file object is opened or closed, from a set of default values possibly modified by successive calls to the procedure "setaccess".
The standard attribute modes are SHARED, APPEND, CREATE, READWRITE, BYTESIZE, REWIND and PURGE.
SHARED: If the value is "shared", the external file may be shared by other programs. The value "noshared" implies that the file must be exclusively assigned to this program. APPEND: If the value is "append", output to the file is added to the existing contents of the file. The value "noappend" implies for a sequential file that, after "close", the external file will contain only the output produced while the file was open. The mode is not relevant for in(byte)files. For direct files "append" prohibits output before "lastloc". For out(byte)files, the value "append" implies that SHARED has the value "noshared". CREATE: If the value is "create", the external file associated with FILENAME must not exist at "open" (if it does, "open" returns false); a new file is created by the environment. If the value is "nocreate", the associated file must exist at "open". The value "anycreate" implies that if the file does exist at "open" the file is opened, otherwise a new file is created. READWRITE: If the value is "readonly", output operations cannot be performed. If the value is "writeonly", input operations cannot be performed. The value "readwrite" enables both input and output. This mode is relevant only for direct files. BYTESIZE: The value of this mode is a positive integer specifying the size of bytes, measured in bits. This mode is relevant only for bytefiles. An implementation may restrict the possible values in any way. If not set explicitly the value is implementation-defined. REWIND: The value "rewind" indicates that some resetting of the external file occurs at "close" (e.g. rewind of a magnetic tape). The value "norewind" implies no such reset. PURGE: The value "purge" implies that the external file may be deleted by the environment when it is closed (in the sense that it becomes inaccessible to further program access). The value "nopurge" implies no such deletion.
Additional values and modes may be defined by an implementation.
The parameter "mode" to procedure "setaccess" contains one of the standard values as given above, namely "shared", "noshared", "append", "noappend", "create", "nocreate", "anycreate", "readonly", "writeonly", "readwrite", "bytesize:X" (where X is a positive integer), "rewind", "norewind", "purge" and "nopurge". It is recommended that implementation-defined parameter values have the percent character % as the first character of the text.
The parameter "bytesize:0" (zero) specifies the (implementation-defined) default byte size for bytefiles.
Only one mode may be specified in each "setaccess" call, the case of the individual letters of the parameter being insignificant. Unrecognized modes are ignored and "setaccess" then returns the value false. The value is true otherwise. A specific mode is interpreted either at next "open" or next "close". A mode which is set after "open" or "close" has no effect until the next "close" or "open" respectively.
The default values of the access modes are given in table 10.1, where "NA" means "not applicable" (i.e. ignored for this file kind) and "*" means that the value is implementation-defined.
Files of kind Mode: In- Out- Direct- Takes effect at SHARED shared noshared noshared open APPEND NA noappend noappend open CREATE NA anycreate nocreate open READWRITE NA NA readwrite open BYTESIZE:x * * * open REWIND norewind norewind NA open,close PURGE nopurge nopurge nopurge close Table 10.1. Default values of file access modes.
Most subclasses of "file" defined in BASICIO contain these procedures.
Procedure "open" establishes the association with an external file (as identified by FILENAME), checks the access modes and causes corresponding opening actions on the external file. If the external file is closed, it is opened.
Procedure "close" causes closing actions on the external file, as specified by the access modes. In addition, the association between the file object and the external file is dissolved. If possible, the external file is closed.
The details of these procedures are subclass- and implementation-defined. All versions conform, however, to the following patterns.
OPEN Boolean procedure open ... ; if not OPEN and ... ! FILENAME association is established; and ... ! access modes compatible with external file; and ... ! external file is opened; then begin ... ; ! implementation-defined and access mode specified actions on external file, followed by subclass dependent actions; open := OPEN := true; end open; CLOSE Boolean procedure close; if OPEN then begin ... ; ! implementation-defined and access mode specified actions on external file; ... ; ! subclass dependent actions; OPEN := false; close := true; end close;
These patterns will not be repeated in detail for each subclass; a short comment will serve to remind the reader of these general actions of the procedures.
There are two predefined subclasses of class file:
"imagefile" - image (record) oriented files "bytefile" - character (stream) oriented files
These subclasses each have three subclasses defining the direction of data transfer and the file organisation: input-oriented sequential files (i.e. in(byte)files), output-oriented sequential files (i.e. out(byte)files) and bidirectional direct files (i.e. direct(byte)files).
--------------------------------------- |imagefile subclass | bytefile subclass | -----------------+-------------------+-------------------| |sequential input | infile | inbytefile | |-----------------+-------------------+-------------------| |sequential output| outfile | outbytefile | |-----------------+-------------------+-------------------| |direct file | directfile | directbytefile | --------------------------------------------------------- Table 10.2. Subclasses of class "file".
In addition, a standard subclass for line printer oriented output, outfile class printfile, is defined.
All files producing output (sequential output or direct files) contain a Boolean procedure "checkpoint". The procedure causes the environment to attempt to secure the output produced so far. Depending on the nature of the associated external device, this causes completion of output transfer (i.e. intermediate buffer contents are transferred). If this is not possible or meaningful, "checkpoint" is a dummy operation in which case the value false is returned.
Direct files contain the following variable and procedures for control of simultaneous access to the external file (cf. access mode SHARED).
Boolean LOCKED; LOCKED Boolean procedure locked; locked:= LOCKED; LOCK integer procedure lock(timelimit,loc1,loc2); real timelimit; integer loc1,loc2; begin lock := -1; if timelimit>0.0 then begin if LOCKED then unlock; ... ! try to lock indicated part of file, see below; if !success; then begin LOCKED := true; lock := 0 end end end lock; UNLOCK Boolean procedure unlock; begin unlock := checkpoint; if LOCKED then begin !release file; LOCKED := false end end unlock;
The variable "LOCKED" indicates whether the file is currently locked by the executing program. The procedure "locked" returns the current value.
Procedure "lock" enables the program to get exclusive access to all or part of the file. The effect of a "lock" call while the file is locked ("LOCKED" is true) is that the previous lock is immediately released (prior to the new locking attempt).
The parameter "timelimit" is the (clock) time in seconds that is the maximum waiting time for the resource. If "timelimit" is less than or equal to zero, the procedure returns immediately without performing any actions upon the file.
The parameters "loc1" and "loc2" identify the part of the file to be locked, by giving the ordinal numbers of two external images (bytes). The program is given exclusive access to a part of the file which includes the requested region. If the two parameters are both zero, this implies locking the whole file. Otherwise, the size of the part of the file that is actually locked, is implementation-dependent; it may even include the entire file.
A return value of zero indicates a successful "lock" operation. The value -1 indicates that "timelimit" was exceeded (or was zero or negative). A negative value less than -1 indicates "lock" failure and its interpretation is implementation-defined.
The Boolean procedure "unlock" eliminates the effect of any preceding "lock" call. The Boolean procedure "checkpoint" is called initially. The returned value is that returned by the "checkpoint" call.
The (file) class "imagefile" defines the common attributes for all image- oriented files.
file class imagefile; begin text image; 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;
The individual logical unit of an external file associated with an imagefile is called an "external image". Each external image is an an ordered sequence of characters.
The variable "image" is used to reference a text frame which acts as a buffer, in the sense that it contains the external image currently being processed.
The procedures "setpos", "pos", "more" and "length" are introduced for reasons of convenience.
The three standard subclasses of imagefile are "infile" (sequential input file), "outfile" (sequential output file) and "directfile" (bidirectional direct file). In addition, "printfile", a standard subclass of class outfile, is available. It represents a line printer oriented file.
imagefile class infile; begin Boolean ENDFILE; Boolean procedure endfile; endfile:= ENDFILE; Boolean procedure open(fileimage); text fileimage; ... 10.4.1; Boolean procedure close; ............................. 10.4.1; procedure inimage; ................................... 10.4.2; Boolean procedure inrecord; .......................... 10.4.2; character procedure inchar; .......................... 10.4.3; Boolean procedure lastitem; .......................... 10.4.4; text procedure intext(w); integer w; ................. 10.4.5; integer procedure inint; ............................. 10.4.6; long real procedure inreal; .......................... 10.4.6; integer procedure infrac; ............................ 10.4.6; ENDFILE:= true ... end infile;
An object of the class "infile" is used to represent an image-oriented sequential input file.
The variable ENDFILE is true whenever the file object is closed or the external file is exhausted (i.e. "end of file" has been encountered). The procedure "endfile" gives access to the value of ENDFILE.
OPEN Boolean procedure open(fileimage); text fileimage; if ... then begin ... ! see 10.1.2; ENDFILE := false; image :- fileimage; image := notext; setpos(length+1); open := OPEN := true; end open;
If successful, "open" returns true and sets ENDFILE false. In addition, "image" references the parameter "fileimage" which is space-filled.
CLOSE Boolean procedure close; if OPEN then begin ... ; ! perform closing actions, see 10.1.2; image :- notext; OPEN := false; close := ENDFILE := true end close;
If successful, "close" returns true. In addition, OPEN is false, ENDFILE is true and "image" references notext.
INIMAGE procedure inimage; if not OPEN or ENDFILE then error("...") else begin ... ; ! attempt to transfer external image to "image"; if ... ! "image" too short; then error("...") else if ... ! there was no more to read; then begin ENDFILE := true; image := "!25!" end else ... ; ! pad "image" with space(s); setpos(1) end inimage;
The procedure "inimage" performs the transfer of an external file image into "image". A run-time error occurs if "image" is notext or too short to contain the external image. If it is longer than the external image, the latter is left-adjusted within "image" and the remainder of the text is filled with spaces. The position indicator is set to one.
INRECORD Boolean procedure inrecord; if not OPEN or ENDFILE then error("...") else begin ... ; ! transfer external image to "image" (no space-filling); if ... ! no more to read; then begin ENDFILE := true; setpos(1); image.putchar('!25!') end Note - POS = 2 now else begin setpos(... !number of characters transferred + 1; ); inrecord:= not ...! whole external image received?; end if end inrecord;
The procedure "inrecord" is similar to "inimage" with the following exceptions. Whenever the number of characters accessible in the external image is less than "length", the rest of "image" is left unchanged. The part of the "image" that was changed is from pos 1 upto (but not including) the resulting value of POS. Moreover, if the external image is too long, only the "length" first characters are input. The value returned by the procedure is true and the remaining characters may be input through subsequent "inrecord" (or possibly "inimage") statements. Otherwise, if the input of the external image was completed, the value false is returned.
Note: If an "end of file" is encountered, EM ('!25!') is generated as a single character external image, and the variable ENDFILE is given the value true. A call on "inimage" or "inrecord" when ENDFILE already has the value true constitutes a run-time error.
INCHAR character procedure inchar; begin if not more then inimage; inchar:= image.getchar end inchar;
The procedure "inchar" gives access to and scans past the next character. Note: The result may be the "EOF-character" EM (ISOrank 25).
LASTITEM Boolean procedure lastitem; begin character c; c := ' '; while not ENDFILE and then (c=' ' or else c='!9!') do c := inchar; lastitem := ENDFILE; if c <> ' ' then setpos(pos-1) end lastitem;
The purpose of the procedure "lastitem" is to skip past all SP and HT characters (ISOrank 32 and 9 respectively). The process of scanning may involve the transfer of several successive external images. If the file contains no further non-space, non-tab characters the value true is returned.
INTEXT text procedure intext(w); integer w; begin text t; intext :- t :- blanks(w); while t.more do t.putchar(inchar) end intext;
The expression "intext(w)" where "w" is a positive integer is a reference to a new alterable main frame of length w containing a copy of the next w characters of the file. POS is set to the following character. The expression "intext(0)" references notext. In contrast to the item-oriented procedures (see below), "intext" operates on a continuous stream of characters, reading several images if necessary.
Note: The result may be a reference to an "EOF-image" (cf. 10.4.2).
ININT integer procedure inint; if lastitem then error("..." ! Inint: End of file ;) else begin text t; t :- image.sub(pos,length-pos+1); inint := t.getint; setpos(pos+t.pos-1) end inint; INREAL long real procedure inreal; if lastitem then error("..." ! Inreal: End of file; ) else begin text t; t :- image.sub(pos,length-pos+1); inreal := t.getreal; setpos(pos+t.pos-1) end inreal; INFRAC integer procedure infrac; if lastitem then error("..." ! Infrac: End of file; ) else begin text t; t :- image.sub(pos,length-pos+1); infrac := t.getfrac; setpos(pos+t.pos-1) end infrac;
The procedures "inint", "inreal" and "infrac" are defined in terms of the corresponding de-editing procedures of "image". These three procedures, starting at the current "pos", skip spaces and tab's, and then scan past and convert a numeric item.
file class outfile; begin Boolean procedure open(fileimage); text fileimage; ... 10.5.1; Boolean procedure close; .............................. 10.5.1; procedure outimage; ................................... 10.5.2; procedure outrecord; .................................. 10.5.3; procedure breakoutimage; .............................. 10.5.4; Boolean procedure checkpoint; ......................... 10.2.1; procedure outchar(c); character c; .................... 10.5.6; procedure outtext(t); text t; ......................... 10.5.7; text procedure FIELD(w); integer w; ................... 10.5.8; procedure outint(i,w); integer i,w; ................... 10.5.8; procedure outfix(r,n,w); long real r; integer n,w; .... 10.5.8; procedure outreal(r,n,w); long real r; integer n,w; ... 10.5.8; procedure outfrac(i,n,w); integer i,n,w; .............. 10.5.8; ... ; end outfile;
An object of the class "outfile" is used to represent an image-oriented sequential output file.
Note: See 10.7 for a special property of procedures "open", "close", "outimage" and "outrecord".
OPEN Boolean procedure open(fileimage); text fileimage; if ... then begin ... ! see 10.1.2; image :- fileimage; setpos(1); open := OPEN := true; end open; CLOSE Boolean procedure close; if OPEN then begin ... ! see 10.1.2; if pos <> 1 then outimage; image :- notext; ... ; ! perform closing actions on external file; OPEN := false; close := true; end close;
The procedure "close" calls "outimage" if the position indicator is not equal to 1.
OUTIMAGE procedure outimage; if not OPEN then error("..." ! file closed; ) else begin ... ; ! transfer "image" to external image; image := notext; setpos(1) end outimage;
The transfer of an image from the text "image" to the file is performed by the procedure "outimage". The procedure reacts in an implementation-defined way if the "image" length is not appropriate for the external file. (Depending on file type and host system, the external file does not necessarily record trailing blanks from the "image".) After the transfer, "image" is cleared to blanks and the position indicator is set to 1.
OUTRECORD procedure outrecord; if not OPEN then error("..." ! file closed; ) else begin ... ; ! transfer image.sub(1,pos-1); ! Note: no blanking of "image"; setpos(1) end outrecord;
The procedure "outrecord" transfers to the file only that part of "image" which precedes POS. The contents are not blanked after the transfer, although POS is set to one.
BREAKOUTIMAGE procedure breakoutimage; if not OPEN then error("..." ! file closed; ) else begin ... ; ! output image.sub(1,pos-1); image := notext; setpos(1) end breakoutimage;
The procedure "breakoutimage" outputs the part of "image" that precedes POS. The output is performed as a partial output of an external image, in the sense that implicit line terminators are suppressed. On some external files this operation is not possible. It then has an effect identical to "outrecord".
After transfer the "image" is blanked and POS is set to one.
One use of "breakoutimage" is to allow input from a terminal display on the same line as one on which output (e.g. a prompt) has already been written.
The procedure "checkpoint" is described in 10.2.1.
OUTCHAR procedure outchar(c); character c; begin if not more then outimage; image.putchar(c) end outchar;
The procedure "outchar" stores a character in the POS position of "image". If "more" is false, "outimage" is called first.
OUTTEXT procedure outtext(t); text t; begin if pos>1 and then t.length>length-pos+1 then outimage; t.setpos(1); while t.more do outchar(t.getchar); end outtext;
Procedure "outtext" always transfers the complete contents of the text parameter to the file.
text procedure FIELD(w); integer w; if w>length then error("..." ! Item too long; ) else begin if pos+w-1 > length then outimage; FIELD :- image.sub(pos,w); setpos(pos+w) end FIELD; OUTINT procedure outint(i,w); integer i,w; if w = 0 then FIELD(...).putint(i) ! see below; else if w < 0 then begin text f; f :- FIELD(-w); f := notext; f.sub(1,...).putint(i) end else FIELD(w).putint(i); OUTFIX procedure outfix(r,n,w); long real r; integer n,w; ... ; ! as body of outint, with "putfix" substituted for "putint"; OUTREAL procedure outreal(r,n,w); long real r; integer n,w; ... ; ! as body of outint, with "putreal" substituted for "putint"; OUTFRAC procedure outfrac(i,n,w); integer i,n,w; ... ; ! as body of outint, with "putfrac" substituted for "putint";
The procedures "outint", "outfix", "outreal" and "outfrac" are defined in terms of the corresponding editing procedures of "image". They provide facilities for "item-oriented" output. Each item is edited into a "field" (subtext of "image") normally starting at the current accessible character. POS is advanced correspondingly. If the remainder of "image" is too short to contain the item, "outimage" is called implicitly prior to the editing operation. The field is space-filled before the editing operation.
A run-time error occurs if a field cannot be contained within the full length of "image".
Parameter "w" determines both the length of this field and the adjustment of the item within it, as follows.
w > 0 The field length is w, the item is right-adjusted. w < 0 The field length is abs(w), the item is left-adjusted. w = 0 The field length is the exact number of characters needed to contain the item (i.e. no leading or trailing spaces).
imagefile class directfile; begin integer LOC, MAXLOC; Boolean ENDFILE, LOCKED; integer procedure location; location:= LOC; Boolean procedure endfile; endfile := ENDFILE; Boolean procedure locked; locked := LOCKED; Boolean procedure open(fileimage); text fileimage; ...... 10.6.1; Boolean procedure close; ................................ 10.6.1; integer procedure lastloc; .............................. 10.6.2; integer procedure maxloc; ............................... 10.6.2; procedure locate(i); integer i; ......................... 10.6.2; procedure inimage; ...................................... 10.6.3; procedure outimage; ..................................... 10.6.4; Boolean procedure deleteimage; .......................... 10.6.5; character procedure inchar; ............................. 10.6.6; integer procedure lock(t,i,j); real t; integer i,j; ..... 10.6.7; Boolean procedure unlock; ............................... 10.6.7; Boolean procedure checkpoint; ........................... 10.2.1; Boolean procedure lastitem; ............................. 10.4.4; text procedure intext; .................................. 10.4.5; integer procedure inint; ................................ 10.4.6; long real procedure inreal; ............................. 10.4.6; integer procedure infrac; ............................... 10.4.6; procedure outchar(c); character c; ...................... 10.5.6; procedure outtext(t); text t; ........................... 10.5.7; text procedure FIELD(w); integer w; ..................... 10.5.8; procedure outint(i,w); integer i,w; ..................... 10.5.8; procedure outfix(r,n,w); long real r; integer n,w; ..... 10.5.8; procedure outreal(r,n,w); long real r; integer n,w; ..... 10.5.8; procedure outfrac(i,n,w); integer i,n,w; ................ 10.5.8; ENDFILE:= true ... end directfile;
An object of the class "directfile" is used to represent an image-oriented direct file in which the individual images are addressable by ordinal numbers.
The variable LOC contains the current ordinal number. When the file is closed, the value of LOC is set to zero. The procedure "location" gives access to the current value of LOC.
The variable ENDFILE is true when the file is closed or when an image with location greater than "lastloc" has been input (through "inimage"). It is set after each "inimage" statement. The procedure "endfile" returns the current value.
The variable MAXLOC indicates the highest permitted value of LOC. On some systems this value corresponds to the size of a preallocated file while, on other systems which allow the file to be dynamically extended, this variable is assigned the value "maxint"-1.
OPEN Boolean procedure open(fileimage); text fileimage; if ... then begin ... ! see 10.1.2; MAXLOC := ... ; ! See below; image :- fileimage; setpos(1); locate(1); open := OPEN := true; end open; CLOSE Boolean procedure close; if OPEN then begin ... ! see 10.1.2; image :- notext; if LOCKED then unlock; LOC := MAXLOC := 0; ... ; OPEN := false; close := ENDFILE := true; end close;
The procedure "open" locates the first image of the file. The length of "image" must, at all "inimage" and "outimage" statements, be identical to the length of "image" at the "open" call. The value assigned to MAXLOC at "open" is either a maximum length determined from the external file, or it is "maxint"-1 if no such length exists.
LOCATE procedure locate(i); integer i; if i<1 or i>MAXLOC then error("..." ! Parameter out of range; ) else begin LOC:= i; ... ; end locate; LASTLOC integer procedure lastloc; if not OPEN then error("..." ! file closed; ) else lastloc := ... ; MAXLOC integer procedure maxloc; if not OPEN then error("..." ! file closed; ) else maxloc := MAXLOC;
Procedure "locate" may be used to assign a given value to the variable LOC. This assignment may be accompanied by implementation-defined checks and (possibly asynchronous) instructions to an external memory device associated with the file; no transfer to/from "image" is, however, performed. A parameter to "locate" less than one or greater than MAXLOC constitutes a run-time error.
The procedure "lastloc" indicates the largest location of any written image. For a new file the value returned is zero.
INIMAGE procedure inimage; if not OPEN then error("..." !file closed; ) else begin setpos(1); ENDFILE:= LOC > lastloc; if ENDFILE then image:= "!25!" else if ... ! external written image at LOC exists ; then ... ! transfer to "image";... else begin while more do image.putchar('!0!') ! Note: now pos = length+1; end not written; locate(LOC+1) ! Location for *next* image; end inimage;
The procedure "inimage" transfers into the text "image" a copy of the external image as currently identified by the variable LOC. If the file does not contain an image with an ordinal number equal to the value of LOC, the effect of the procedure "inimage" is as follows. If the location indicated is greater than "lastloc", then ENDFILE is set to true and the end of file text ("!25!") is assigned to "image". Otherwise, if the image is a non-written image but there exists at least one written image whose LOC is greater than current LOC, then the "image" is filled with NUL ('!0!') characters and the position indicator is set to "length"+1 (i.e. "more" becomes false). Finally the value of LOC is incremented by one through a "locate" call.
OUTIMAGE procedure outimage; if not OPEN then error("..." !file closed; ) else if LOC > MAXLOC then error("..." ! file overflow; ); else begin ... ; ! output "image" to external image at LOC; locate(LOC+1); image := notext; setpos(1) end outimage;
The procedure "outimage" transfers a copy of the text value "image" to the external image, thereby storing in the file an external image whose ordinal number is equal to the current value of LOC. If the file contains another image with the same ordinal number, that image is overwritten. The value of LOC is then incremented by one through a "locate" call.
DELETEIMAGE Boolean procedure deleteimage; if OPEN and then ... ! image LOC was written; then begin ... ; ! attempt to delete image; if ... ! delete operation successful; then begin deleteimage := true; locate(LOC+1); end successful end deleteimage;
The Boolean procedure "deleteimage" makes the image identified by the current value of LOC effectively un-written. Irrespective of any physical differences on the external medium between never-written images and deleted ones, there is no difference from the program's point of view. Note that this means that "deleteimage" may decrement the value returned by "lastloc" (in case LOC was equal to "lastloc").
Note: Outputting a NUL-filled image at location "lastloc" in the file does not necessarily decrement the "lastloc" value; explicit writing (outimage) of such images should be avoided.
INCHAR character procedure inchar; begin while not more do inimage; inchar:= image.getchar end inchar;
Note: Inchar skips all unwritten images.
The procedures "lock" and "unlock" (see 10.2.2) provide locking mechanisms. The last two parameters of "lock" indicate the minimum range of locations to be locked (inclusive).
The remaining procedures ("lastitem" to "intext" and "outchar" to "outtext") are defined in accordance with the corresponding procedures of "infile" and "outfile" respectively, i.e. their definitional algorithms are exact copies of those given in these two classes.
The class "printfile" defines a class for line printer oriented output.
outfile class printfile; begin integer LINE, LINES_PER_PAGE, SPACING, PAGE; integer procedure line; line := LINE; integer procedure page; page := PAGE; Boolean procedure open(fileimage); text fileimage; ..... 10.7.1; Boolean procedure close; ................................ 10.7.1; procedure linesperpage(n); integer n; ................... 10.7.2; procedure spacing(n); integer n; ........................ 10.7.3; procedure eject(n); integer n; ......................... 10.7.4; procedure outimage; ..................................... 10.7.5; procedure outrecord; .................................... 10.7.5; SPACING := 1; LINES_PER_PAGE := ... ; ... end printfile;
An object of the class "printfile" is used to represent a line printer oriented output file. The class is a subclass of "outfile". A file image normally represents a line on a printed page.
It is a property of this class that "outfile" attributes, which are redeclared at "printfile" level, are not accessible to the user's program through explicit qualification (qua). Thus these "outfile" procedures ("open", "close", "outimage", "outrecord") may be envisaged as including the following initial code:
procedure X...; inspect this outfile when printfile do X... otherwise ...;
Note: Consequently, possible implicit calls of outimage from outchar, close and the item-oriented output procedures are understood to invoke "printfile.outimage".
The variable LINE indicates the ordinal number of the next line to be printed (on the current page), provided that no implicit or explicit "eject" statement occurs. Its value is accessible through the procedure "line". Note that the value of LINE may be greater than LINES_PER_PAGE (see 10.7.5).
The variable PAGE indicates the ordinal number of the current page. Its value may be retrieved by means of procedure "page".
OPEN Boolean procedure open(fileimage); text fileimage; if ... then begin ... ! see 10.1.2; image :- fileimage; PAGE := 0; LINE := 1; setpos(1); eject(1); open := OPEN := true; end open; CLOSE Boolean procedure close; if OPEN then begin ... ! see 10.1.2; if pos <> 1 then outimage; eject(LINES_PER_PAGE); LINE := 0; SPACING := 1; LINES_PER_PAGE:= ... ; image :- notext; ... ; OPEN := false; close := true; end close;
The procedures "open" and "close" conform to the rules of 10.2. In addition, "close" outputs the current value of "image" if POS is not equal to 1 and set LINE to zero.
LINESPERPAGE integer procedure linesperpage(n); integer n; begin linesperpage := LINES_PER_PAGE; LINES_PER_PAGE:= if n > 0 then n else if n < 0 then maxint else ... ; ! default value;
The variable LINES_PER_PAGE indicates the maximum number of physical lines that may be printed on each page, including intervening blank lines. An implementation-defined value is assigned to the variable at the time of object generation, and when the printfile is closed. The value of the variable may be retreived by a call on "linesperpage"; in addition the variable is givan a new value as follows.
If the parameter to "linesperpage" is zero, LINES_PER_PAGE is reset to the original value (assigned at object generation). A parameter value less than zero may be used to indicate an "infinite" value of LINES_PER_PAGE, thus avoiding any automatic calls on "eject".
SPACING procedure spacing(n); integer n; if 0<=n and n<=LINES_PER_PAGE then SPACING := n else error("..." ! Parameter out of range; );
The variable SPACING represents the value by which the variable LINE is incremented after the next printing operation. Its value may be changed by the procedure "spacing". A call on the procedure "spacing" with a parameter less than zero or greater than LINES_PER_PAGE constitutes an error. The effect of a a parameter to "spacing" which is equal to zero may be defined as forcing successive printing operations on the same physical line. Note, however, that on some physical media this may not be possible, in which case spacing(0) has the same effect as spacing(1) (i.e. no overprinting).
EJECT procedure eject(n); integer n; if not OPEN then error("..." ! file closed;) else if n <= 0 then error("..." ! Parameter out of range;) else begin if n > LINES_PER_PAGE then n := 1; if n <= LINE then begin ... ; ! change to new page on external file; PAGE := PAGE + 1 end; ... ; ! move to line "n" on current (external) page; LINE := n end eject;
The procedure "eject" is used to position to a certain line identified by the parameter, n. The variable "PAGE" is incremented by one each time an explicit or implicit "eject" implies a new page.
The following cases can be distinguished:
n <= 0 : ERROR n > LINES_PER_PAGE : Equivalent to eject (1) n <= LINE : Position to line number n on the next page n > LINE : Position to line number n on the current page
The tests above are performed in the given sequence.
OUTIMAGE procedure outimage; if not OPEN then error("..." ! file closed; ) else begin if LINE > LINES_PER_PAGE then eject(1); ... ; ! output the image on the line indicated by LINE; LINE := LINE + SPACING; image := notext; setpos(1) end outimage; OUTRECORD procedure outrecord; if not OPEN then error("..." ! file closed; ) else begin if LINE > LINES_PER_PAGE then eject(1); ... ; ! output image.sub(1,pos-1) on the line indicated by LINE; LINE := LINE + SPACING; setpos(1) end outrecord;
The procedures "outimage" and "outrecord" operate according to the rules of 10.2.3. In addition, they update the variable LINE (and possibly PAGE).
Note: In addition, the procedure "breakoutimage" is inherited from the class prefix "outfile". This procedure does not update LINE or PAGE.
The class bytefile is the common prefix class for all byte-oriented files.
file class bytefile; begin short integer BYTESIZE; short integer procedure bytesize; bytesize := BYTESIZE; end bytefile;
Bytefiles read and write files as continuous streams of bytes. The variable BYTESIZE defines the range of the byte values transferred. Byte values are integers in the range (0:2**BYTESIZE-1). The BYTESIZE value of the file object is accessible through procedure "bytesize".
Note: "Bytesize" returns zero before first "open" of the bytefile.
There are three standard subclasses of "bytefile":
"inbytefile" representing a sequential file for which input operations are available. "outbytefile" representing a sequential file for which output operations are available. "directbytefile" representing a direct file with facilities for both input and output.
bytefile class inbytefile; begin Boolean ENDFILE; Boolean procedure endfile; endfile:= ENDFILE; Boolean procedure open; ......................... 10.9.1; Boolean procedure close; ........................ 10.9.1; short integer procedure inbyte; ................. 10.9.2; text procedure intext(t); text t; ............. 10.9.3; ENDFILE:= true; ... end inbytefile;
An object of the class "inbytefile" is used to represent a byte-oriented sequential input file.
Variable "ENDFILE" is true if there are no more bytes to read. The procedure "endfile" returns the value of ENDFILE.
OPEN Boolean procedure open; if ... then begin ... ! see 10.1.2; ENDFILE := false; BYTESIZE := ... ! value of access mode BYTESIZE; open := OPEN := true; end open; CLOSE Boolean procedure close; if OPEN then begin ... ! see 10.1.2; ... ; OPEN := false; close := ENDFILE := true; end close;
INBYTE short integer procedure inbyte; if ENDFILE then error("..." ! End of file ;) else if ... ! no more bytes to read; then ENDFILE := true ! inbyte returns zero; else inbyte := ...! next byte of size BYTESIZE;
The procedure "inbyte" returns the short integer value corresponding to the input byte. If there are no more bytes to read, a zero result is returned. If prior to an "inbyte" call ENDFILE is true, a run-time error occurs.
INTEXT text procedure intext(t); text t; begin 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 intext;
The procedure "intext" fills the frame of the parameter "t" with successive input bytes.
bytefile class outbytefile; begin Boolean procedure open; ....................... 10.10.1; Boolean procedure close; ...................... 10.10.1; procedure outbyte(x); short integer x; ........ 10.10.2; procedure outtext(t); text t; ................. 10.10.3; Boolean procedure checkpoint; ................. 10.2.1; end outbytefile;
An object of the class "outbytefile" is used to represent a sequential output file of bytes.
OPEN Boolean procedure open; if ... then begin ... ! see 10.1.2; BYTESIZE := ... ! value of access mode BYTESIZE; open := OPEN:= true; end open; CLOSE Boolean procedure close; if OPEN then begin ... ! see 10.1.2; OPEN := false; close := true; end close;
OUTBYTE procedure outbyte(x); short integer x; if not OPEN then error("..." ! file closed; ) else if x < 0 or else x >= 2**BYTESIZE then error("..." ! Outbyte, illegal byte value ;) else ... ; ! output of x;
The procedure "outbyte" outputs a byte corresponding to the parameter value. If the parameter value is less than zero or exceeds the maximum permitted value, as defined by BYTESIZE, a run-time error occurs. If the file is not open, a run-time error occurs.
OUTTEXT procedure outtext(t); text t; begin t.setpos(1); while t.more do outbyte(rank(t.getchar)) end outtext;
The procedure "outtext" outputs all characters in the parameter "t" as bytes.
The class "directbytefile" defines a byte-oriented direct file.
bytefile class directbytefile; begin integer LOC, MAXLOC; Boolean LOCKED; Boolean procedure endfile; endfile:=OPEN and then LOC>lastloc; integer procedure location; location := LOC; integer procedure maxloc; maxloc := MAXLOC; Boolean procedure locked; locked := LOCKED; Boolean procedure open; ............................... 10.11.1; Boolean procedure close; .............................. 10.11.1; integer procedure lastloc; ............................ 10.11.2; procedure locate(i); integer i; ..................... 10.11.2; short integer procedure inbyte; ....................... 10.11.3; procedure outbyte(x); short integer x; ............... 10.11.3; Boolean procedure checkpoint; ......................... 10.2.1; integer procedure lock(t,i,j); real t; integer i,j; ... 10.11.4; Boolean procedure unlock; ............................. 10.11.4; procedure intext(t); text t; ........................ 10.9.3; procedure outtext(t); text t; ........................ 10.10.3; ... end directbytefile;
An object of the class "directbytefile" is used to represent an external file in which the individual bytes are addressable by ordinal numbers. The variable LOC is defined to represent such ordinal numbers. When the file is closed, the value of LOC is zero.
The variable MAXLOC indicates the maximum possible location on the external file. If this is not meaningful MAXLOC has the value of "maxint"-1. The procedure "maxloc" gives access to the current MAXLOC value.
The procedure "endfile" returns true whenever LOC indicates an address greater than "lastloc".
The procedures "intext" and "outtext" conform to the pattern for "inbytefile" and "outbytefile", respectively.
OPEN Boolean procedure open; if ... then begin ... ! see 10.1.2; LOC := 1; MAXLOC := ...; ! fixed size, or maxint-1; BYTESIZE := ... ! value of access mode BYTESIZE; open := OPEN := true; end open; CLOSE Boolean procedure close; if OPEN then begin ... ! see 10.1.2; MAXLOC := 0; OPEN := false; close := true; end close;
LOCATE procedure locate(p); integer p; if p < 1 or p > MAXLOC then error("..." ! Parameter out of range; ) else LOC := p; LASTLOC integer procedure lastloc; if not OPEN then error("..." ! file closed; ) else lastloc := ...;
The current last written location is returned by the procedure "lastloc". The procedure "location" returns the current value of LOC. The procedure "locate" may be used to assign a given value to the variable. A parameter value to "locate" which is less than one or greater than MAXLOC constitutes a run-time error.
INBYTE short integer procedure inbyte; if not OPEN then error("..." !file closed; ) else if LOC <= lastloc then begin inbyte := ... ! next byte of size BYTESIZE;...; LOC := LOC+1 end inbyte; OUTBYTE procedure outbyte(x); short integer x; if not OPEN then error("..." !file closed; ) else if x < 0 or else x >= 2**BYTESIZE then error("..." ! Outbyte, illegal byte value ;); else if LOC > MAXLOC then error("..." !file overflow; ) else begin ... ! output of x; LOC := LOC + 1 end outbyte;
The procedure "inbyte" reads one byte, returning its integer value. The result of "inbyte" from an unwritten LOC is zero (cf. 10.3.2).
The procedure "outbyte" outputs a byte according to the given parameter value (cf. 10.3.3).
The procedures "lock" and "unlock" (see 10.2.2) provide locking mechanisms. The last two parameters of "lock" indicate the minimum range of (byte) locations to be locked (inclusive).