HI, I have this relatively huge program, about 40,000 lines in 183 source files.
I've found lots of errors in the source code caused by arguments that don't match the subroutine dummy argument type.
But the compiler doesnt find many of these by itself, as none of the subroutines had interfaces (to start out with). I'm building up interfaces as I go along, but the task is error-prone-- if I forget to add "use glue" to a subroutine, it will silently compile anyway and generate bad calls.
It sure would be nice if the compiler required interfaces for every called function or subroutine.
On Jan 31, 12:01 pm, "Ancient_Hacker" <g...@comcast.net> wrote:
> HI, I have this relatively huge program, about 40,000 lines in 183 > source files.
> I've found lots of errors in the source code caused by arguments that > don't match the subroutine dummy argument type.
> But the compiler doesnt find many of these by itself, as none of the > subroutines had interfaces (to start out with). I'm building up > interfaces as I go along, but the task is error-prone-- if I forget to > add "use glue" to a subroutine, it will silently compile anyway and > generate bad calls.
> It sure would be nice if the compiler required interfaces for every > called function or subroutine.
You could put all the code for functions and subroutines in a module foo and insert "use foo" in the main program -- doing so provides an explicit interface.
It looks like you are working with a FORTRAN 77 code -- the free program FTNCHEK is invaluable for checking interfaces.
> HI, I have this relatively huge program, about 40,000 lines in 183 > source files.
> I've found lots of errors in the source code caused by arguments that > don't match the subroutine dummy argument type.
> But the compiler doesnt find many of these by itself, as none of the > subroutines had interfaces (to start out with). I'm building up > interfaces as I go along, but the task is error-prone-- if I forget to > add "use glue" to a subroutine, it will silently compile anyway and > generate bad calls.
> It sure would be nice if the compiler required interfaces for every > called function or subroutine.
> Is there some Fortran option to require these?
> Thanks,
> grg
A way to get there with a small amount of work is to make everything into CONTAINed units. You end up with
program all_of_it implicit none
call old_main
contains
subroutine old_main ! which used to be program main ... end subroutine ! use a text editor to turn END into END SUBROUTINE
subroutine xxx ... end subroutine ! use a text editor to turn END into END SUBROUTINE
function yyy ... end function ! use a text editor to turn END into END FUNCTION
end
and note a couple gotchas 1. external units don't work as you can not pass the internal units as arguements 2. external statments need to be taken out as they force things to not be internal. To bad as an otherwise good style bites. 3. no declarations at all before the CONTAINs to keep from accidental host associations for undeclared variables. But then you have implicit none everywhere don't you!
All this may solve your problems if you do not have the gotchas. They can be worked around. You will need lots of include statements and fixing all the ENDs is a bother. But you have to choose what is the least fuss to get the F90 checking. Do it on a copy etc, etc.
When you are done it will be time to make up various modules of groups of your units.
On Jan 31, 12:01 pm, "Ancient_Hacker" <g...@comcast.net> wrote:
> It sure would be nice if the compiler required interfaces for every > called function or subroutine.
You don't say which compiler you're using. The Intel Fortran compiler has options "-gen-interface -warn interface" which, used together, tells the compiler to automatically generate modules with interfaces for each routine compiled and then to look for the corresponding module when it sees a call to a routine for the purpose of error checking. This can be quite handy.
Steve Lionel Developer Products Division Intel Corporation Nashua, NH
In article <1170262895.101225.227...@a34g2000cwb.googlegroups.com>,
Ancient_Hacker <g...@comcast.net> wrote: >HI, I have this relatively huge program, about 40,000 lines in 183 >source files.
>I've found lots of errors in the source code caused by arguments that >don't match the subroutine dummy argument type.
If your compiler checks arguments within the same source file (a common feature), the laziest way to do this once is to cat the sources into a single file, and compile that.
Of course, in the long run you'll want proper interfaces.
In message <1170263701.807339.186...@k78g2000cwa.googlegroups.com>, Beliavsky <beliav...@aol.com> writes
>You could put all the code for functions and subroutines in a module >foo >and insert "use foo" in the main program -- doing so provides an >explicit >interface.
That's a good idea in principle, but if it is old code it probably doesn't have the required END SUBROUTINE or END FUNCTION statements. That's what thwarted me when in a similar predicament. You may be able to fix that with a good text editor, but it can be hard work.
>It looks like you are working with a FORTRAN 77 code -- the free >program >FTNCHEK is invaluable for checking interfaces.
I'd strongly recommend that option for Fortran77-style code. Indeed I'd never trust old code without doing a such a check. Some of the warnings may be unimportant, but looking through them nearly always brings problems to light that desperately need fixing.
Forget interface blocks. Just create a little module, about 188 lines long, that reads something like:
module all_module contains
include "source1.f" : include "source183.f"
end module
This takes about 10 seconds to do with any competent text editor. Do not INCLUDE your main program, nor any BLOCK DATA routines.
Then write a simple program to change lines containing "END" to "END SUBROUTINE". Run all of the 183 files through it. Takes a few minutes to do this step.
Then compile all_module. Some problems will occur because some of the END SUBROUTINEs really need to be END FUNCTIONs. But these are quickly fixed.
Then you can then start to fix all of the problems... (And Gordon Sande outlined a few important gotchas.)
Once done, do a USE ALL in your main program. Fix any last problems, and then congratulate yourself on a job well done!
> Forget interface blocks. Just create a little module, about 188 lines long, that > reads something like:
> module all_module > contains
> include "source1.f" > : > include "source183.f"
> end module
> This takes about 10 seconds to do with any competent text editor. Do not INCLUDE > your main program, nor any BLOCK DATA routines.
> Then write a simple program to change lines containing "END" to "END SUBROUTINE". > Run all of the 183 files through it. Takes a few minutes to do this step.
> Then compile all_module. Some problems will occur because some of the END SUBROUTINEs > really need to be END FUNCTIONs. But these are quickly fixed.
I would prefer to avoid this manual step. There are programs (search "split Fortran") to split a Fortran 77 code into files containing a single function or subroutine. It should not be hard to write a program in Python/Perl etc. that looks at the beginning of the file, determines whether it is a function or subroutine, and replaces the "end" statement with the correct "end function foo" or "end subroutine foo" statement at the end of the file. Then the files can be strung together and put in a module.
> I would prefer to avoid this manual step. There are programs (search > "split Fortran") to split a Fortran 77 code into files containing a > single function or subroutine
Also a reminder that convert.f90 has an option to take a Fortran 77 file and produce a module containing all its interface blocks that can then be USEd: (ftp.numerical.rl.ac.uk/pub/MRandC/convert.f90).
> > I would prefer to avoid this manual step. There are programs (search > > "split Fortran") to split a Fortran 77 code into files containing a > > single function or subroutine
> Also a reminder that convert.f90 has an option to take a Fortran 77 file and > produce a module containing all its interface blocks that can then be USEd: > (ftp.numerical.rl.ac.uk/pub/MRandC/convert.f90).
While convert.f90 is a useful program, it seems like overkill for what is needed in the OPs case. First, while free-form looks and works a bit better than fixed, there is no pressing need to convert to free-form. Indeed forcing a fixed->free conversion also means that he is suddenly less able to 'diff' his hopefully repaired code to the original.
And second, automatic interface block generation is not really useful for the task. You'd then have to insert USE statements into every routine. And do renaming on each and every USE to avoid the scoping conflict between the routine and its own interface. This is a lot of hand work, and IMO of questionable value. Because F90 really works best when all subprograms are CONTAINed in the first place.
Where convert.f90s interface block generation capability would be useful is when a library developer wants to give a customer the source code to his interfaces. But not the source code for the library itself.
> In message <1170263701.807339.186...@k78g2000cwa.googlegroups.com>, > Beliavsky <beliav...@aol.com> writes > >You could put all the code for functions and subroutines in a module > >foo > >and insert "use foo" in the main program -- doing so provides an > >explicit > >interface.
> That's a good idea in principle, but if it is old code it probably > doesn't have the required END SUBROUTINE or END FUNCTION statements. > That's what thwarted me when in a similar predicament. You may be able > to fix that with a good text editor, but it can be hard work.
No hard work required. It's easy to whip up a short Fortran program to look for SUBROUTINE and FUNCTION statements and to find the corresponding END statements.