6 Reporting and handling errors

 6.1 Handling errors
 6.2 Note to software developers

FIO/RIO routines all report errors if they return bad status values, so programs that do all I/O through calls to FIO/RIO do not have to worry about this. However, some programs use direct FORTRAN statements to perform I/O and may still need to report errors. Two routines are provided to assist with this; FIO_SERR and FIO_REP. FIO_SERR is the simpler of the two. It takes an IOSTAT value as its first argument, returns a corresponding FIO error value in its status argument and reports an error. The error report is of the form:

  FIO_SERR: IOSTAT error = Unit not connected

This is fine if all you want to do is translate the IOSTAT value, but the error report does not contain any contextual information such as the unit that was not connected nor the file that it should have been connected to. For a fuller report, the routine FIO_REP is provided. This takes as input arguments the unit number, the file name, the IOSTAT value and a message to be printed. FIO_REP sets three message tokens, FNAME, UNIT and IOSTAT and then reports the message that it was given. This message can contain references to the message tokens to provide a more meaningful error message. For example:

        OPEN( UNIT=UNUM, FILE=FILNAM, STATUS=’OLD’, IOSTAT=ISTAT )
        CALL FIO_REP( UNUM, FILNAM, ISTAT,
       :  ’Error opening file ^FNAME. Status = ^IOSTAT’, STATUS )

In this case, the error report contains the fact that this error has been generated when trying to open a file. To save having to generate an error message for every call to FIO_REP, it is possible to give a blank message, which is equivalent to

  ’Error with file ^FNAME on unit number ^UNIT; IOSTAT = ^IOSTAT’

For a given value of IOSTAT, the value of status that is returned by FIO_REP is the same as that returned by FIO_SERR.

6.1 Handling errors

Sometimes it is desired to take corrective action if a routine returns a particular bad status value, and section 5 contains an example of how you might do this. Unfortunately there is a problem with testing FIO/RIO status values that does not occur with most other packages.

FIO/RIO can generate two sorts of error codes. Firstly there are internal FIO/RIO codes. There is no problem testing for these. Secondly there are codes that are a translation of a FORTRAN IOSTAT value. It is these status codes that gives rise to the problem as such values are inherently machine specific, thus making it very difficult to write portable applications that test for bad status values. It might be thought that the things that could go wrong with FORTRAN I/O were sufficiently similar from one machine to another, that a common set of error codes could be devised, but surprisingly this is not the case in practice. The list of error codes that can be returned as IOSTAT values are very different from one machine to another. Even when it looks like two errors on different machines will be equivalent in practice, this does not always turn out to be the case.

On account of these difficulties, FIO/RIO adopts the following strategy:

If the text of an error message in the computer manufacturer’s documentation is the same for two different machines, then FIO/RIO will return the same status value on those two machines. Otherwise different status values are returned on the different machines.

This strategy is applied quite rigorously, even when, at first sight, it looks like two error messages might be equivalent. The only exception at present is that ‘Cannot stat file’ (on Ultrix) and ‘can’t stat file’ (on SunOS) return the same error code. Not to do so smacks of pedantry of the highest order! This strategy has been chosen as a balance between returning unique error codes on all machines (which is barely any better than using the raw IOSTAT value) and trying to guess which error codes are equivalent to each other (with the likelihood of getting it wrong). Presumably if the text of two error messages are identical, then they are intended to apply to the same situation. Even this cannot be guaranteed, but it is the best one can do.

Occasionally, the Fortran run time system will return an IOSTAT value that corresponds to a operating system error rather than a Fortran error. In such a case, an error message describing the error will be generated and the status will be set to the value of the symbolic constant FIO__OSERR.

The strategy of only returning the same error number when the text of the message is the same definitely errs on the side of caution. It means that programs that are intended to be run on several different machines must often test for different error codes, one for each machine type. For example, it is quite common to test for FIO__FILNF (file not found) on VAX/VMS. Unfortunately, there is no error that corresponds sufficiently closely to this on SunOS. As well as being very tedious, it means that tests for bad status values in application programs probably need to be modified to run on a new computer. To minimize this problem, FIO/RIO provides the ability to test status values for classes of errors. This is best described by an example. Suppose that you have prompted a user for the name of an input file and you then try to open a file using the returned string. If the program fails to open the file, this might be for one of several reasons. It may be that the file does not exist, or that the file exists, but you do not have the right to access the file, or that the string typed in is not a valid file name (e.g. [PMA}TEST.DAT on VMS). In all of these situations, you can rely on the error reporting to tell the user what has gone wrong, but all the program cares about is that it has failed to open the file and that it should re-prompt the user. A program can test for a general class of errors by using the logical function FIO_TEST. This takes a character argument and a status value and returns TRUE if the value of STATUS is in the class of errors described by the character argument. Here is an example:

        IF( FIO_TEST( ’OPEN error’, STATUS ) ) THEN
           ...
        ENDIF

Note that FIO_TEST is not sensitive to the case of the character string given as its first argument. An example of attempting to open a file using FORTRAN I/O and then testing to see if this was successful is:

        CALL ERR_MARK
        OPEN( UNIT=UNUM, FILE=FILNAM, STATUS=’OLD’, IOSTAT=ISTAT )
        CALL FIO_REP( UNUM, FILNAM, ISTAT, ’ ’, STATUS )
  *  Test for ‘could not open file’.
        IF( FIO_TEST( ’OPEN error’, STATUS ) ) THEN
  *  Handle the error if we can.
           ...
           CALL ERR_ANNUL( STATUS )
        END IF
        CALL ERR_RLSE

This example has used a FORTRAN OPEN statement in the application code. It is generally better to let FIO handle all file access as this makes for more portable code. (It is also less typing.) In this case, the above example would be written as:

        CALL ERR_MARK
        CALL FIO_OPEN( FILNAM, ’UPDATE’, ’LIST’, 0, FD, STATUS )
        IF( FIO_TEST( ’OPEN error’, STATUS ) ) THEN
  *  Handle the error if we can.
           ...
           CALL ERR_ANNUL( STATUS )
        END IF
        CALL ERR_RLSE

A list of all the classes of errors that can be handled in this manner is given in appendix E. At present, the list of error classes is fixed, but it is intended that users will be able to define their own error classes in a future release of FIO/RIO.

6.2 Note to software developers

The routines that provide the interface to the ADAM parameter system report errors by calling the ERR library. All other routines report errors by calling the EMS library.