SuivantPrec.Bas prec.BasNiv. sup.

9.3 External Procedures 

There are two forms of external procedure, both of which take the form of a complete program unit. In either form the last statement of the program unit must be an END statement. Any other statements (except PROGRAM or BLOCK DATA statements) may be used within the program unit.

There are two statements provided especially for use in external procedures. The SAVE statement ensures that the values of local variables and arrays are preserved after the procedure returns control to the calling unit: these values will then be available if the procedure is executed subsequently. The RETURN statement may be used to terminate the execution of the procedure and cause an immediate return to the control of the calling unit. Execution of the END statement at the end of the procedure has exactly the same effect. Both of these are described in full later in the section.

Most Fortran systems also allow external procedures to be specified in languages other than Fortran: they can be called in the same way as Fortran procedures but their internal operations are, of course, beyond the scope of this book.

It is best to think of the subroutine as the more general form of procedure; the external function should be regarded as a special case for use when you only need to return a single value to the calling unit.

Here is a simple example of a procedure which converts a time of day in hours, minutes, and seconds into a count of seconds since midnight. Since only one value needs to be returned, the procedure can have the form of an external function. (In fact this is such a simple example that it would have been possible to define it as a statement function.)
 *TSECS converts hours, minutes, seconds to total seconds.
        REAL FUNCTION TSECS(NHOURS, MINS, SECS)
        INTEGER NHOURS, MINS
        REAL SECS
        TIME = ((NHOURS * 60) + MINS) * 60 + SECS
        END
Thus if we use a function reference like TSECS(12,30,0.0) in an expression elsewhere in the program it will convert the time to seconds since midnight (about 45000.0 seconds in this case). The items in parentheses after the function name :       (12,30,0.0)  are known as the actual arguments of the function; these values are transferred to the corresponding dummy arguments       (NHOURS, MINS, SECS) of the procedure before it is executed. In this example the argument list is used only to transfer information into the function from outside, the function name itself returns the required value to the calling program. In subroutines, however, there is no function name to return information but the arguments can be used for transfers in either direction, or both. The rules permit them to be used in this more general way in functions, but it is a practice best avoided.

The next example performs the inverse conversion to the TSECS function. Since it has to return three values to the calling program unit the functional form is no longer appropriate, and a subroutine will be used instead.
 *Subroutine HMS converts TIME in seconds into hours, mins,secs.
       SUBROUTINE HMS(TIME, NHOURS, MINS, SECS)
       REAL TIME, SECS
       INTEGER NHOURS, MINS
       NHOURS = INT(TIME / 3600.0)
       SECS   = TIME - 3600.0 * NHOURS
       MINS   = INT(SECS / 60.0)
       SECS   = TIME - 60.0 * MINS
       END
In this case the subroutine could be executed by using a statement such as:
        CALL HMS(45000.0, NHRS, MINS, SECS)
        WRITE(UNIT=*, FMT=*) NHRS, MINS, SECS
Here the first argument transfers information into the subroutine, the other three are used to return the values which it calculates. You do not have to specify whether a particular argument is to transfer information in or out (or in both directions), but there are rules about the form of actual argument that you can use in each case. These are explained in full below.

Procedure Independence 

Each program unit has its own independent set of symbolic names and labels. Type statements and IMPLICIT statements may be used to specify their data types.

External procedures can themselves call any other procedures and these may call others in turn, but procedure are not allowed to call themselves either directly or indirectly; that is recursive calling is not permitted in Fortran.

Information Transfer 

Information can be transferred to and from an external procedure by any of three methods.

Procedure Execution 

It is not necessary to know how the Fortran system actually transfers information from one procedure to another to make use of the system, but the rules governing the process are somewhat complicated and it may be easier to understand them if you appreciate the basis on which they have been formulated. The rules in the Fortran Standard are based on the assumption that the address of an actual argument is transferred in each case: this may or may not be true in practice but the properties will be the same as if it is.

This means that when you reference a dummy variable or assign a new value to one you are likely to be using the memory location occupied by the actual argument. By this means even large arrays can be transferred efficiently to procedures. A slight modification of this system is needed for items of character type so that the length of the item can be transferred as well as its address.

When a function reference or CALL statement is executed any expressions in the argument list are evaluated; the addresses of the arguments are then passed to the procedure. When it returns control this automatically makes updated values available to the corresponding items in the actual argument list.

Functions with Side-effects  

The rules of Fortran allow functions to have side-effects, that is to alter their actual arguments or to change other variables within common blocks. Functions with side-effects cannot be used in expressions where any of the other operands of the expression would be affected, nor can they be used in subscript or substring references when any other expression used in the same references would be affected. This rule ensures that the value of an expression cannot depend arbitrarily on the way in which the computer chooses to evaluate it.

There are also restrictions on functions which make use of input/output statements even on internal files: these cannot be used in expressions in other I/O statements. This is to avoid the I/O system being used recursively.

By far the best course is to use the subroutine form for any procedure with side-effects.

SuivantPrec.Bas prec.HautNiv. sup.