In ADAM programs, most data will be stored in HDS objects and handled by the Data system. However, it may occasionally be necessary to read and write files directly, a need which is met by the File system which comprises the FIO and RIO libraries. They are closely related and maintain a table of ‘descriptors’ of open files to enable automatic closedown. They also assist in the production of portable software.
The FIO routines handle sequential, formatted files to produce reports for subsequent listing. The RIO routines handle direct access, unformatted files. Each can open the other’s files. When creating formatted files, it is possible to specify whether or not the file contains printer carraige control codes.
FIO and RIO use a common table of file descriptors, so RIO file descriptors may be used by appropriate FIO routines. For example, FIO_FNAME returns the filename associated with a file descriptor generated by either library.
A lot of astronomical data is stored on magnetic tape in formats which are different from the ADAM standard. Such tapes are called ‘foreign tapes’. Some of these can be read and written by ADAM packages, such as FIGARO. However, a tape may exist in a format that cannot be read by an existing ADAM program, or a programmer may wish to write a program to process a foreign tape in his own way. To answer these needs, ADAM provides a subroutine library called MAG which enables a tape device to be controlled directly. The ‘object’ which is the parameter for this system is the ‘tape drive’. It is addressed by a tape descriptor, TD.
A file is opened by associating it with parameter PAR using the FIO_ASSOC routine:
This has two more parameters (FORM and RECSZ) than most ASSOC routines. The mode of opening, MODE, may be ‘READ’, ‘WRITE’, ‘UPDATE’, or ‘APPEND’. A new file is created if it is ‘WRITE’, or if it is ‘APPEND’ and the file does not exist. FORM specifies the type of formatting and the carriage control processing to be used when listing the file. RECSZ is used with the RECL keyword in the Fortran OPEN statement (used in the implementation) to define a maximum record length for the file; if RECSZ is zero, the RECL keyword is omitted from the OPEN statement. A file descriptor, FD, is used to specify the file in other FIO subroutines — it is not the same as a Fortran unit number. STATUS is the usual status value indicator.
Routine FIO_CANCL cancels the association between a parameter and a file.
Routines FIO_READ and FIO_WRITE read into, or write from, buffers containing character strings stored as formatted records. These buffers can be coded or decoded using the CHR library or Fortran internal I/O. If Fortran carriage control is specified for the file, the first character in the buffer should be set appropriately.
Routine FIO_READF reads a record from a file, but does not return the used length of the buffer. This makes reading much faster when the used length is not requried. Example: The following example shows how FIO routines are used to write a single formatted line to a file:
The corresponding interface file could contain the following specifications:
FIO_ASSOC obtains a value for parameter FILE and uses it as the filename in an internal call to FIO_OPEN. Checks on the validity of the filename are performed by the Fortran OPEN statement called internally.
Parameter FILE is defined as type FILENAME in the interface file and not as a character string, therefore the value given for ‘default’ does not need to be enclosed in quotes. Furthermore, the name of an HDS object containing the filename cannot be given.
When the program has finished with the file, it uses FIO_CANCL to close the file and cancel the parameter. If the file parameter is required again, to open the same file for reading perhaps, FIO_CLOSE should be used instead of FIO_CANCL.
The include file ‘FIO_PAR’ defines symbolic names for various constants which may be required by programs. For example, FIO__SZMOD is used in the above example to specify the length of the access mode string. Another useful symbolic name is FIO__SZFNAM (the maximum allowed length of a filename in FIO and RIO). If you want to test for explicit status values returned from FIO routines, include the statement:
in the program. The status can then be tested by, for example:
If it is essential to use the Fortran OPEN or CLOSE statements, use FIO_GUNIT and FIO_PUNIT to obtain and release a logical unit number which does not clash with others. Note that there would be no FIO descriptor for such files.
The RIO system is very similar to the FIO system, and most of its routines have the same call sequence. For example:
There are some differences however. For example, in RIO_ASSOC, RECSZ specifies the fixed record length, while in FIO_ASSOC it specifies the maximum record length. Also, the read and write routines are different:
The RIO routines perform direct access I/O of unformatted byte arrays and need to specify a record number, RECNO. Also, they always need to specify the number of bytes, NCHAR, in a record.
Many FIO routines can be used on RIO files. For example,
will get the file name, in FNAME, for any such file.
The last example in the previous section showed some RIO routines in use.
More detailed information on FIO and RIO can be found in SUN/143, which also contains routine specifications and error codes. A classified list of routines is given in Section 21.5.1.
The routines in the MAG library have names which begin with the prefix ‘MAG_’, followed by characters which indicate their function. In this chapter, routine names will normally be written without the prefix. Thus, routine ‘MAG_READ’ will be referred to as ‘READ’.
The functions provided by the MAG library can be classified as follows:
There is also the routine that is frequently used instead of CANCL:
Then there are two routines to control the allocation of a drive directly:
Finally, there are two routines to control the availability of a tape on a drive:
Then there are two routines that position a tape at an absolute position:
Finally, there are two routines to inquire about or set an absolute position:
The magnetic tape system uses the ADAM Error Strategy. If you want to test for specific MAG status values, include the statement:
in your program. A specific status can then be tested by, for example:
Device management is concerned with the allocation of a tape drive to a program, and the mounting of tapes on this drive.
Allocation and mounting are complicated by the fact that ADAM runs programs in sub-processes under the control of its own user interface. The problem is that a tape deck is allocated to a process, and when you have several processes active it matters which one the deck is allocated to. There are three ways of doing the allocation and mounting:
The first two levels have the advantage that generic device names can be used. However, they have the disadvantage that the initial tape position may not be available to the program. If absolute tape positions are not required, there is no problem. However, if they are required, special action must be taken to obtain them. One way is to use the REW routine to position the tape at its beginning. But the preferred way is to mount the tape by running the TAPEMOUNT program from the top-level process. For example, this can be done in DCL as follows:
The first parameter of TAPEMOUNT is the name of the tape drive, and the second parameter is the access mode (READ or WRITE). When you have finished with the tape, you may dismount it using the TAPEDISM program:
The first parameter of TAPEDISM is the name of the tape drive, and the second parameter should be TRUE if tape is to be unloaded (the default), and FALSE otherwise.
The information on a tape consists of a sequence of blocks. There is a special kind of block called a ‘tape mark’ which is used to indicate the end of a file. Two consecutive tape marks indicate ‘end-of-volume’ (EOV) which normally means that there is no further information on the tape.
The ‘position’ of a tape refers to the block which will be read next when the tape moves. This block will belong to a file, so an ‘absolute position’ can be specified by a file number (FILE) and a block number (BLOCK) within that file. When a tape is in the middle of being used it will have a ‘current position’, which is the absolute position it happens to be in at a particular moment. Every absolute position has a ‘relative position’ relative to the current position. Some MAG routines specify blocks by absolute position, and others by relative position. For example:
will position the tape at the first block of the second file and will assume it is being read in a forward direction, while:
will skip forward 5 blocks. A tape’s absolute position can be found at any time by the call:
If the position is unknown, FILE and BLOCK will be set to zero.
When reading forwards, the first data block in a file is specified by BLOCK=1. However, when reading backwards, the last data block in a file is specified by BLOCK=2. Position memory: The MAG package enables the position of a tape on a specific drive to be remembered between program runs. However, this can only be done if the tape is mounted using MAG_MOUNT. When a program has finished with a tape, it must call MAG_CANCL or MAG_ANNUL, at which time the tape must be in a known absolute position. MAG_MOUNT will initialize the position at FILE=1, START=.TRUE., BLOCK=1, while MAG_DISM will make the values undefined.
The following example is a sketch of a program which reads a magnetic tape using MAG routines:
The corresponding interface file could contain:
MAG_ASSOC requests that the associated tape drive be accessed in ‘READ’ mode, and sets a tape descriptor, TD, which is used by other MAG routines to identify the drive to be used. When the program has finished with the tape, it uses MAG_ANNUL to release the drive and store the tape position in the environment.
The error symbols and full routine specifications for the MAG library can be found in APN/1. Also, a classified list of the routines is given in Section 21.5.2.