The CONTAINS statement basically provides an extension of the old but useful FORTRAN construct the statement function. The statement function in FORTRAN provided a means for a program unit to use a single line of FORTRAN as an internal function. The contains statement took this concept a step further by allowing a programmer to use entire blocks of code as internal procedures. Making entire blocks of code internal procedures can be very useful if there is a specific function that will be repeated several times within the program unit or as a way to store subprograms in modules. It is important to note that when a function or subroutine is declared as an internal procedure through the use of a contains statement, it can only be accessed by that program unit in which it was declared and not by any other (unless used in a Module).
The most important for any programmer to remember about the use of CONTAINS is that it must always be placed at the end of the program unit in which it is going to be used. For instance, take a look at the following example in which the subroutine that converts angles for degrees to radians appears.
subroutine input_angles(a,ldata) implicit none Integer ldata,i real a(1:ldata),aa do i=1,ldata read (12,'(f5.2)') a(i) aa = a(i) call convert a(i) = aa end do contains subroutine convert real, parameter :: pi = 3.1415926 aa = aa*pi/180.0 end subroutine convert return end subroutine input_angles
Now, from this example it can be clearly seen that the CONTAINS statement goes after all the executable statements in the program unit in which it appears. However, there are other things illustrated in this example that you need to know. First, notice that when the internal subroutine convert is called there is no argument list after it and yet it uses the variable aa from the calling subroutine input_angles. The reason why this works is that internal program units declared after a CONTAINS statement have total knowledge of the variable values and names that appear inside the calling procedure. This is a most remarkable difference from the use of external subroutines and functions that only know the memory location of those arguments passed to them via the argument list. Although, there is one exception to the rule of internal subprograms having complete knowledge all variables that appear in the calling procedure. An internal subprogram will not have access to any variables in the main program that have the same name as a variable that was declared in a type statement (REAL, INTEGER, LOGICAL, ...) within the internal procedure. For example, if ldata was declared "integer ldata" inside the subroutine convert above, then convert would not be allowed access to the value of ldata in the original program unit. Therefore, if this was the case, ldata in the subroutine convert would have a completely autonomous memory location and value form ldata in the original program unit. There is one last thing worth noting in this example. Notice that the implicit none statement does not appear in the internal subroutine convert. This is because the implicit none statement from the calling procedure is still in effect. This is the case anytime that an internal subprogram is declared in this manner.
There is one additional rule and one additional application of the contains statement that you should know. A CONTAINS statement can not be used inside a block data unit or inside an internal subprogram. Also, CONTAINS statements can provide a way to store subroutines and functions inside of modules. After all variable declaration has been carried out inside of the module, a CONTAINS statement may be included, followed by as many subroutines and functions that you want to store inside of the module. These subprograms can then be accessed by another program unit through the use of the use statement. The procedures following the CONTAINS statement of a module are only internal subroutines relative to the module itself. They have access to all variables declared in the module's type statements above the CONTAINS statement. However, they do not have access to local variables in the program unit using the module, nor does that program unit have access to variables set in the module procedure, but not declared in the main body of the module. Try the example modproc.f to understand this isolation of variables.
lecture thirty seven
examples: contains.f , modproc.f sifunc.f and funspeed.f
Written by Jason Wehr : email@example.com and Maintained by John Mahaffy : firstname.lastname@example.org