Node: Block Data and Libraries, Next: , Previous: Advantages Over f2c, Up: Collected Fortran Wisdom



Block Data and Libraries

To ensure that block data program units are linked, especially a concern when they are put into libraries, give each one a name (as in BLOCK DATA FOO) and make sure there is an EXTERNAL FOO statement in every program unit that uses any common block initialized by the corresponding BLOCK DATA. g77 currently compiles a BLOCK DATA as if it were a SUBROUTINE, that is, it generates an actual procedure having the appropriate name. The procedure does nothing but return immediately if it happens to be called. For EXTERNAL FOO, where FOO is not otherwise referenced in the same program unit, g77 assumes there exists a BLOCK DATA FOO in the program and ensures that by generating a reference to it so the linker will make sure it is present. (Specifically, g77 outputs in the data section a static pointer to the external name FOO.)

The implementation g77 currently uses to make this work is one of the few things not compatible with f2c as currently shipped. f2c currently does nothing with EXTERNAL FOO except issue a warning that FOO is not otherwise referenced, and, for BLOCK DATA FOO, f2c doesn't generate a dummy procedure with the name FOO. The upshot is that you shouldn't mix f2c and g77 in this particular case. If you use f2c to compile BLOCK DATA FOO, then any g77-compiled program unit that says EXTERNAL FOO will result in an unresolved reference when linked. If you do the opposite, then FOO might not be linked in under various circumstances (such as when FOO is in a library, or you're using a "clever" linker--so clever, it produces a broken program with little or no warning by omitting initializations of global data because they are contained in unreferenced procedures).

The changes you make to your code to make g77 handle this situation, however, appear to be a widely portable way to handle it. That is, many systems permit it (as they should, since the FORTRAN 77 standard permits EXTERNAL FOO when FOO is a block data program unit), and of the ones that might not link BLOCK DATA FOO under some circumstances, most of them appear to do so once EXTERNAL FOO is present in the appropriate program units.

Here is the recommended approach to modifying a program containing a program unit such as the following:

     BLOCK DATA FOO
     COMMON /VARS/ X, Y, Z
     DATA X, Y, Z / 3., 4., 5. /
     END
     

If the above program unit might be placed in a library module, then ensure that every program unit in every program that references that particular COMMON area uses the EXTERNAL statement to force the area to be initialized.

For example, change a program unit that starts with

     INTEGER FUNCTION CURX()
     COMMON /VARS/ X, Y, Z
     CURX = X
     END
     

so that it uses the EXTERNAL statement, as in:

     INTEGER FUNCTION CURX()
     COMMON /VARS/ X, Y, Z
     EXTERNAL FOO
     CURX = X
     END
     

That way, CURX is compiled by g77 (and many other compilers) so that the linker knows it must include FOO, the BLOCK DATA program unit that sets the initial values for the variables in VAR, in the executable program.