Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Combining F77 and F90 code

gib
New Contributor II
3,099 Views

I have some old F77 code (nleq1, horrible-looking but very effective) that I am using in F90 programs.  Currently I'm keeping the files separate, with a F90 file that defines a module, and several F77 files (*.f), one of which USEs the module.  It's all a bit messy.  I'm wondering if there is a way to collect the *.f files together in a module, and/or can a F90 file contain both free-form and fixed-form procedures.

0 Kudos
14 Replies
Arjen_Markus
Honored Contributor I
3,099 Views

Well, the simplest way to achieve that is to use the fixed-form altogether and replace the END statement by END SUBROUTINE or END FUNCTION. Then you can join the files into a module:

      module my_old_ugly_f77_code
      contains
      ... contents of file 1
      ... contents of file 2
      ...
      end module

It is possible to format code in such a way that it is acceptable as both fixed-form and free-form, modulo a few nasty aspects of fixed-form (notably the fact that spaces are not really significant - I 20 = 1 is the same as I20 = 1), but why bother? Fixed-form is still acceptable as a way to write Fortran 90 style code. And it makes life quite a bit easier.

0 Kudos
mecej4
Honored Contributor III
3,099 Views

Gib, consider whether the FREEFORM and NOFREEFORM compiler directives will help. These directives allow mixing blocks of free form  code and blocks of fixed form code in the same source file.

     https://software.intel.com/en-us/node/692821#38A9609E-0460-4243-A0F2-C47474F014D4 

0 Kudos
gib
New Contributor II
3,099 Views

Thanks to Arjen and mecej4.  I'll need to think about which method makes most sense in this case.  It looks as if the compiler directives (which I was unaware of) provide most flexibility.

0 Kudos
gib
New Contributor II
3,099 Views

Using the NOFREEFORM directive I put all the nleq1 files into a module, replacing all the EXTERNAL statements, declaring many undeclared variables, fixing END statements etc.  I'm now handling the call-back with procedure(func), another capability that I just learned of.  The result is much neater, and I'm very pleased.  Thanks.

0 Kudos
gib
New Contributor II
3,099 Views

One of my students is using gfortran.  Unfortunately the !DIR$ directives do not appear to be supported by gfortran :(

0 Kudos
Arjen_Markus
Honored Contributor I
3,099 Views

Yes, that is a risk with any non-standard features. I do not know if gfortran has an equivalent feature, but it may be worth trying to find out. The alternative is to separate the fixed-form and free-form parts into separate files. Fixed-form still allows all the benefits of modern Fortran. the only thing you cannot do is make a single module, although you can combine modules into a single one (joining the interfaces, not the modules as such)

0 Kudos
mecej4
Honored Contributor III
3,099 Views

You may try the Silverfrost FTN95 compiler's /CONVERT option and do a one-time conversion from fixed source form to free form, see http://www.silverfrost.com/ftn95-help/options/quick_reference.aspx . There are tools such as SPAG that also do code conversions.

0 Kudos
FortranFan
Honored Contributor III
3,099 Views

gib wrote:

One of my students is using gfortran.  Unfortunately the !DIR$ directives do not appear to be supported by gfortran :(

@gib,

Students should all be trained to use SUBMODULEs, PRONTO!   And to use standard language features as much as possible and consider minimal use of compiler directives and options.

See if the fixed-form code can be wrapped in SUBMODULEs and be provided with the MODULE prefix, as follows:

module collect_m

   interface

      module subroutine fugly1( a1, a2, ..)
      ! Interface to fixed-form procedure fugly1

         <type> a1
         <type> a2

      end subroutine fugly1

      module function fugly2( b1, b2, ..)
      ! Interface to fixed-form procedure fugly2

         <type> b1
         <type> a2

      end function fugly2

   end interface

contains

   subroutine sub1( .. )

      ..

   end subroutine

   function f1( .. )

      ..

   end function f1

end module
      SUBMODULE(COLLECT_M) FUGLY1_SM
      
         IMPLICIT NONE
      
      CONTAINS
      
         MODULE SUBROUTINE FUGLY1(A1, A2, ..)
      
            <TYPE> A1
            <TYPE> A2

            ..

            RETURN
      
         END SUBROUTINE FUGLY1
      
      END SUBMODULE FUGLY1_SM
      SUBMODULE(COLLECT_M) FUGLY2_SM
      
         IMPLICIT NONE
      
      CONTAINS
      
         MODULE FUNCTION FUGLY2(B1, B2, ..)
      
            <TYPE> B1
            <TYPE> B2

            ..

            RETURN
      
         END SUBROUTINE FUGLY2
      
      END SUBMODULE FUGLY2_SM

So note the fixed-form code represented by FUGLY1 and FUGLY2 above are pretty retained as-is, all that is done is standard attributes to wrap such code. 

0 Kudos
gib
New Contributor II
3,099 Views

That's not a very appealing solution, FortranFan, because there are so many subroutines and functions.

0 Kudos
gib
New Contributor II
3,099 Views

Thanks mecej4, the Silverfrost FTN95 compiler with the /CONVERT option looks interesting - free for personal use.  I might give it a try.

0 Kudos
gib
New Contributor II
3,099 Views

On Silverfrost /CONVERT - I installed it and ran the conversion on a fixed-form .f file.  The result is if anything even uglier than the original.  Interestingly, the .f file has this line

      PARAMETER (ZERO = 0.0 D0)

which is accepted by ifort.  The same line appears in the converted free-form .f90 file, but now in ifort the space creates an error.  When the space is removed the file compiles, so that's success.  Obviously a change between f77 and f90.  It still needs some attention before being packaged in a module (END statements need to be completed), but that is relatively minor.  It also strips out all the comments, which is not very friendly.

0 Kudos
Arjen_Markus
Honored Contributor I
3,099 Views

Note there are other such programs available (Alan Miller and Michael Metcalfe have written and published such programs for instance). Whether they produce something in the style you want will depend.

As for PARAMETER (ZERO = 0.0 D0) not being accepted in free-form: that is one of the few incompatibilities between the two source forms. In fixed form spaces essentially have no particular meaning, in free form they do.

0 Kudos
FortranFan
Honored Contributor III
3,099 Views

gib wrote:

That's not a very appealing solution, FortranFan, because there are so many subroutines and functions.

Suit yourself, but anyone else interested in refactoring their code will note:

  1. the compiler option /gen-interfaces (https://software.intel.com/en-us/fortran-compiler-18.0-developer-guide-and-reference-gen-interfaces) can be used to achieve a decent initial state of interfaces of all the existing legacy code that is usually in fixed-form source format and without explicit interfaces.
  2. Then one can use any of the scripting options (e.g., Perl) to quickly absorb the interfaces into a module and to wrap the legacy code in SUBMODULEs.  Note with SUBMODULEs one does not materially need to change the legacy code in any way; it can even remain in fixed-format source form which is also supported by the current Fortran standard.  One only prepends and appends 'stuff' to the source.
0 Kudos
andrew_4619
Honored Contributor III
3,099 Views
I found gen interfaced of little use to me as it resolved all data kinds e.g. Integer(handle) becomes integer(4) in the source so 32 and 64bitness change will give an incorrect interface as will also happen if you change the value of a kind parameter. I have not checked the latest compiler for this. In the end i wrote my own source parser to create interfaces for my code as this was the fastest route I found.
0 Kudos
Reply