#!/usr/bin/perl

# This script should be used to make the file "f90depends" any time the
# source code is changed.  Then, "f90depends" will be included in the
# makefile.  The script identifies dependencies associated with module use
# statements, f90-style include statements, and cpp style include statements.
# A specific format for module use statements is required:
# "use <source file basename>_mod"; eg. to use the file foo_dat.f90, you
# would specify "use foo_dat_mod".  The dependencies will be linked through
# the used module object; this avoids requirements on module file endings, and
# the object and module files are always produced during compilation
# anyway (assuming the source is for a module, that is). Both f90 and cpp style 
# include statements are supported, but require use of enclosing double quotes
# ("filename").  CPP dependencies won't be picked up for system headers if they
# are enclosed in brackets (<filename>), per the usual conventions.  An
# assumption is made that the f90 source is in a file with an .fpp (fortran
# pre-processor source) suffix.  This is done because the actual .f90's that
# are compiled are intermediate files that may or may not be present.  This
# means that in conditional code, unneeded dependencies may be included for
# code segments that will be dropped by the preprocessor, but this is not a
# major problem.  If included files require further cpp processing, they should
# be included using #include, not an f90 include.

use File::Basename;
use Cwd;

foreach $fpp_filename ( <*.fpp> )
{

  ($file_basename) = $fpp_filename =~ /(.+)\.fpp$/;
  open(HDL, "$fpp_filename") || die "$fpp_filename could not be opened!\n";
  while (<HDL>)
  {
    next unless /^ *use +.*_mod/;
    ($dep_basename) = / *use +(.*)_mod/;
    if (!defined $dep_list{$file_basename, $dep_basename})
    {
      printf "$file_basename.o: $dep_basename.o\n";
    }
    $dep_list{$file_basename,$dep_basename} = 1;
  }
  close(HDL);
  open(HDL, "$fpp_filename");
  while (<HDL>)
  {
    next unless /^ *#?include +".*"/;
    ($dep_name) = / *#?include +"(.*)"/;
    if (!defined $dep_list{$file_basename, $dep_name})
    {
      printf "$file_basename.o: $dep_name\n";
    }
    $dep_list{$file_basename, $dep_name} = 1;
  }
  close(HDL);
}
