Notes on Fortran and ITAPS interfaces

This is just a chain of conciousness set of issues I've run into (I am sure others have too) compiling and linking Fortran clients with iMesh implementations.

Fortran Header Generation tool (mkforth)

We have a perl script in the tools directory, mkforth, that is designed to read an existing C header file and produce the essential Fortran header file. For the most part, this is a trivial mapping. However, there are issues with how #include directives in original C file make it through. iMeshP includes MPI header file, mpi.h, due to reference to MPI_Comm datatype. However, that is not needed in the Fortran header file. So, mkforth ignores any non-ITAPS include files. In addition, if an ITAPS header file is referenced from a C header file, its fortran equivalent has to be referenced from the generated Fortran header (e.g. #include "iBase.h" in C iMesh.h translates to #include "iBase_f.h" in iMesh_f.h)

C Pre-Processor and Fortran Source Code

So far, we've exploited cpp to handle some issues with the fortran interface. For example, in a fortran header file, we have something like...

#define iMesh_Instance integer*8
There are a variety of limitations and issues with using the C Pre-Processor on Fortran source code.
  • Google the issue and you'll learn about this.
  • GNU products don't automatically run cpp on fortran sources. You have to either explicitly tell it to or name the file such that it has a .F extension as in foo.F.
  • When CPP is invoked by compiler automatically, it uses -traditional-cpp mode and may also use -undef.
    • -traditional-cpp means you can't use any macros that use # (token stringification) or ## (token pasting) CPP operators.
    • -undef means that none of the symbols the GNU C compiler ordinarily defines, such as __SIZEOF_POITNER__, for example, are not defined.
  • Macro substitutions can change the length of a line. Since non-free-form Fortran language is sensitive to line length issues, if any macro substitutions increase the line length (e.g. the replacement text is longer than the text being replaced), its possible the line length could run beyond fortran limit cause compilation errors.
    • The solution, of course, is to ensure that all such macros' replacement text is less-than or equal in length to the text being replaced.
  • The line-formatting of CPP statements in source files prior to running cpp on the files isn't an issue. The CPP statements need not obey Fortran line formatting requirements. However, after all CPP is completed, the resulting files must obey Fortran line formatting.

ITAPS Interface Pointers and Fortran

Fortran 77 didn't support pointers. An extension to Fortran 77, also known as cray pointers, was created to handle pointers in Fortran 77. The new pointer statement was added to the language to support them. With GNU compilers, you have to invoke the compiler with -fcray-pointer if you want support for pointers.

In Fortran, a pointer involves two variables, the pointer and the pointee. This is somewhat analagous C language where char *p defines p to be a pointer and then *p is the pointee. But, in Fortran, these two parts of a pointer are actually different program variables defined with a pointer statements as in

      integer rpents
      integer*80 ents
      pointer (rpents, ents)

In the above, rpents is the pointer and ents is the pointee. it turns out the integer rpents statement is not necessary and can actually lead to problems if the sizes of integer and pointer datatypes are different. It is more portable to allow the compiler to determine correct size of the pointer. But, to do this, you cannot have an implicit none statement. In addition, in ITAPS interfaces we need to support two-levels of indirection. That is pointers to pointers to data. And, it still isn't clear to me how to support that using an implicit approach to defining the pointer types.

POINTER_SIZE symbol defined by ITAPS header files

For now, we've taken to requiring the client to explicitly set size of a pointer to either integer*8, integer*4 or integer by using something like FCFLAGS=-DPOINTER_SIZE=8 prior to compiling Fortran ITAPS code.

The GNU C compiler defines __SIZEOF_POINTER__ symbol and it would be nice to rely upon that to bootstrap the POINTER_SIZE setting. However, I have yet to be able to find __SIZEOF_POINTER__ defined while processing a .F Fortran file. Somehow, the definition of this symbol is being turned off (maybe by GNU's automatic invokation of cpp with -undef option).