#! /usr/bin/perl


my ($prefix, $globus_prefix, $exec_prefix, $bindir, $sbindir, $libdir);
my ($datarootdir, $datadir, $perlmoduledir, $gptdatadir);
my ($gptexecsharedir, $amdir, $pkg_confdir, $aclocaldir);

if (exists $ENV{GPT_LOCATION})
{
    $prefix = $ENV{GPT_LOCATION};
}
else
{
    $prefix = "/usr";
}

if (exists $ENV{GLOBUS_LOCATION})
{
    $globus_prefix = $ENV{GLOBUS_LOCATION};
}
else
{
    $globus_prefix = "/usr";
}

$exec_prefix = "${prefix}";
$bindir = "${exec_prefix}/bin";
$sbindir = "${exec_prefix}/sbin";
$libdir = "${exec_prefix}/lib";
$datarootdir = "${prefix}/share";
$datadir = "${prefix}/share";
$perlmoduledir = "/usr/share/perl5";
$gptdatadir = "${datadir}/globus/gpt";
$gptexecsharedir = "${datadir}/globus/gpt";
$amdir = "${datadir}/globus/amdir";
$pkg_confdir = "${datadir}/globus/gpt";
$aclocaldir = "${datadir}/globus/aclocal";

unshift(@INC, "${perlmoduledir}");

use strict;
use Getopt::Long;
use File::Find;
use Cwd;
use Config;

#
# Do a perl check for version >= 5.005.
#

if ( ! ( defined eval "require 5.005" ) )
{
    die "GPT requires at least Perl version 5.005";
}

if ( ! ( defined eval "require Grid::GPT::GPTObject" ) )
{
    die("$prefix does not appear to hold a valid GPT installation\n");
}

my $VERSION = 0.01;
my $verbose = 0;
my $topdir = cwd();
my @excludes;
my ($help, $man);

require Pod::Usage;

# sub pod2usage {
#   my $ex = shift;
#   print "gpt_create_automake_rules [-srcdir=<PATH> --exclude=<PATH> -verbose -help]\n";
#   exit $ex;
# }

GetOptions( '-srcdir=s' => \$topdir, '-excludes=s@' => \@excludes, 
            'verbose=i' => \$verbose, 'help' => \$help) 
  or Pod::Usage::pod2usage(1);

Pod::Usage::pod2usage(0) if $help;

$topdir = Cwd::abs_path($topdir);


# target types defined by automake
my @target_types = ("PROGRAMS", "LTLIBRARIES", "LIBRARIES","SCRIPTS", "HEADERS","DATA", "MANS");

my %excluded_dirs;
for my $p (@excludes) {
  $excluded_dirs{$p}++;
}

find(\&find_makefile_am, $topdir);


sub generate_rule
  {
    my ($target, $installdir, $mpage) = @_;
    my ($realdir);
    my $target2file = {
		       PROGRAMS => "progs.am",
		       LTLIBRARIES => "ltlib.am",
		       LIBRARIES => "libs.am",
		       SCRIPTS => "scripts.am",
		       HEADERS => "header.am",
		       DATA => "data.am",
		       MANS => "mans.am",
		      };

    if (!defined($target2file->{$target})) {
      die "ERROR: I have no rules file for $target\n";
    }
    open (RULES, "$amdir/$target2file->{$target}");
    $realdir = $installdir;
    $realdir =~ s/^nodist_//;

#    print "$target $installdir $target2file->{$target}\n";

    my $result = "";
    while (<RULES>) {
      s/\@DIR\@dir/${realdir}dir/g;
      s/\@DIR\@/$installdir/g;
      s!\%SECTION\%!$mpage!g if defined $mpage;
      $result .= $_ if (!/^\#\#/);
    }

    close(RULES);
    $result .="\n";
    return $result;      
}

sub find_makefile_am {
    if ($_ ne "Makefile.am") {
      return;
    }
    my $file = $_;
    my $dir = $File::Find::dir;
#    print "find_makefile_am: $dir\n";
    $dir =~ s!\Q$topdir\E/+!!;
    process_automake_file($file) if ! defined $excluded_dirs{$dir};
}

sub process_automake_file {
  my $file = shift;
  my $rulefile = "Makefile.in";
  open (QUICK_CHECK, "$rulefile");

# Look for generated output.
  while (<QUICK_CHECK>) {
    if (m!filelist-recursive!) {
      # found some abort this generation.
      close QUICK_CHECK;
      return;
    }
  }
  close QUICK_CHECK;

  my ($dir_targets, $mpages) = scan_automake_file($file);
  my $dir = cwd();
#  print "process_automake_file: $dir\n";
  open (OUTPUT, "+<$rulefile");

  my $trunc_point = 0;
  while (<OUTPUT>)
  {
      chomp();
      if ($_ =~ m/# BEGIN GPT AUTOMAKE RULES/)
      {
          truncate(OUTPUT, $trunc_point);
          last;
      }
      else
      {
          $trunc_point = tell(OUTPUT);
      }
  }
  my ($d, $t);
  my ($link, $unlink, $rules, $filelist, $phony) = ("link: link-recursive ",
                                                    "unlink: unlink-recursive ",
                                                    "", 
                                                    "filelist: filelist-recursive ",
                                                    ".PHONY: link unlink link-recursive unlink-recursive link-am unlink-am filelist-am");
  for $d (sort keys %$dir_targets) {
    my @targets = (sort keys %{$dir_targets->{$d}});
    for $t (@targets) {
      if ($t eq 'MANS') {
            # man_MANS is legal, if that's the case, we'll pull out
            # all possible mandirs based on the pages in the list
            if ($d eq 'man') {
                for my $m (sort keys %$mpages) {
                    my $mansectdir = $d;
                    $mansectdir .= $m if ($mansectdir eq 'man');
                    $filelist .= " filelist-$mansectdir ";
                    $phony .= " filelist-$mansectdir ";
                    $rules .= generate_rule($t, $d, $m);
                }
            } else {
                my $mansectdir = $d;
                my $m = $mansectdir;
                $m =~ s/.*man//;
                $filelist .= " filelist-$mansectdir ";
                $phony .= " filelist-$mansectdir ";
                $rules .= generate_rule($t, $d, $m);
            }
      } else {
        $link .= "link-$d$t ";
        $unlink .= "unlink-$d$t ";
        $filelist .= "filelist-$d$t ";
        $phony .= "link-$d$t unlink-$d$t filelist-$d$t ";
        $rules .= generate_rule($t, $d);
      }
    }
  }
  print OUTPUT "# BEGIN GPT AUTOMAKE RULES\n";
  print OUTPUT "link-am:\n\nunlink-am:\n\nfilelist-am:\n\n";
  print OUTPUT "$link\n\t:\n\n";
  print OUTPUT "$unlink\n\t:\n\n";
  
  print OUTPUT "$phony\n\n";
  
  print OUTPUT "$filelist\n\t:\n\n";
  
  print OUTPUT $rules;
  close OUTPUT;
  
  my $result = `cat $amdir/subdirs.am >> $rulefile`;
}

sub scan_automake_file {
  my ($file) = @_;
  my %targets;
  my %mpages;
  my $curdir = cwd();
  local *AUTOMAKE;
  my $result = open(AUTOMAKE, $file);
  if (! $result) {
    die "ERROR: Could not open $curdir/$file\n";
  }

  my $line;
  my $manstarget = 0;
  while ($line = <AUTOMAKE>) {
    if ($line =~ m!^\s*include\s+(?\!\\)(\S+)!) {
      my $incfile = $1;
      $incfile =~ s!\$\(top_srcdir\)!$topdir!;
      $incfile =~ s!\$\(srcdir\)/!$curdir/!;
      $incfile =~ m!(\S*)/([^/]+)$!;
      my ($dir, $file) = ($1, $2);
      chdir $dir if $dir ne $curdir;
      my ($more_targets, $more_mpages) = scan_automake_file($file);
      chdir $curdir if $dir ne $curdir;
      for my $d (sort keys %$more_targets) {
        $targets{$d} = {} if ! defined $targets{$d};
        for my $t (sort keys %{$more_targets->{$d}}) {
          $targets{$d}->{$t}++;
        }
      }
      for my $m (sort keys %$more_mpages) {
        $mpages{$m}++;
      }
    }

    for my $t (@target_types) {
      next if $line =~ m!noinst!;
      if ($line =~ m!^\s*(\w+)_$t\s*=!) {
        my $tdir = $1;
        if (!defined($targets{$tdir})) {
          $targets{$tdir} = {};
        }
        $targets{$tdir}->{$t}++;
        if ($t eq 'MANS') {
          $manstarget++;
        }
      }
      next if ! $manstarget;
      while ($line =~ m!\w+\.(\d+)!cg) {
        $mpages{$1}++;
      }
      $manstarget = 0 if $line !~ m!\\\n!;
    }
  }
  close AUTOMAKE;
  return (\%targets, \%mpages);
}
