# $Id: AutomakeFixer.pm,v 1.3 2010/10/18 21:48:19 pfeiffer Exp $

=head1 NAME

Mpp::AutomakeFixer - Cleanup Automake crap

=head1 DESCRIPTION

This module cleans out all the crap that automake puts into makefiles.
This is activated automatically whenever we detect a makefile that
was generated by automake.

=cut

package Mpp::AutomakeFixer;

#
# This subroutine removes all the automake junk, as best as we can, from
# a makefile.
# Arguments: the string containing the makefile contents.
# Returns the text of a modified, hopefully simpler makefile.
#
sub remove_automake_junk {
  local $_ = $_[0];
  my $lineno = 0;
  s/\n/++$lineno; "\05$lineno\n"/eg; # Append the line number to each line, so
                                # we can preserve the line numbers when we
                                # remake the final file.
  s/\\\05\d+\n//g;              # Get rid of all the trailing backslashes,
                                # so we can parse things easier.

#
# Extract a list of the targets that are handled by recursive make, and
# fix them so they use Makepp's method instead.  This converts a line like
# this:
#
#    RECURSIVE_TARGETS = info-recursive dvi-recursive ...
#
# into something like this:
#
#    info-recursive: $(SUBDIRS)/info info-am
#
#    dvi-recursive: $(SUBDIRS)/dvi dvi-am
#
#    ...
#
  if (/\nRECURSIVE_TARGETS\s*=(.*)\05/) {
    $_ .= join("\n\n", map {      # Add the makepp version at the bottom.
      my $target = $_;
      $target =~ s/-recursive$//;
      "$_ : \$(SUBDIRS)/$target $target-am";
    } split(' ', $1));

    s/\n\$\(RECURSIVE_TARGETS\):[\s\S]+?\n\05\d+\n//;
                                # Get rid of the action rule that we're
                                # replacing.  Delete everything from the rule
                                # start to the blank line afterwards.
  }

#
# Replace a simple recursive make invocation like this:
#   xyz : dependencies
#        cd subdir && $(MAKE) targets
# with this:
#   xyz: dependencies subdir/targets
#
  s{\n([-\w]+)\s*: *([^\n]*)\05\d+\n\t(?:cd (.*?)\s*\&\&\s*)?\$\(MAKE\) (?:-C (\S+)\s+)?(?:\$\(AM_MAKEFLAGS\)\s+)?([-\s\w]+)}{
    my $target = $1;
    my $deps = $2;
    my $subdir = $3 || $4;
    my $subdir_targets = $5;
    $subdir and              # Is there a subdirectory at all?
      $subdir_targets = join(" ", map { "$subdir/$_" } split(" ", $subdir_targets));
    "\n$target : $deps $subdir_targets\n";
  }e;

#
# Forward all other recursive invocations of make to the real make program,
# because makepp probably can't handle it well.
#
  s/\$\(MAKE\)/make/g;

#
# Remove the dependency tracking junk since we have no use for it with makepp.
#
  s/\ndepcomp\s*=.*//;
  s/\n\tsource=.*?(\$\((?:LT)?CXXCOMPILE\))/\n\t$1/g;
                                # Strip out the depcomp script invocation.
  s/\`test -f \'\$\<\' \|\| echo \'\$\(srcdir\)\/\'\`\$\</\$\</g;
                                # Fix something that makepp won't be able
                                # to parse.
  s/\ninclude .*\.Po\05\d+\n/\n/g;      # Don't include the dependency files.

#
# Make it so autoconf doesn't get invoked too often:
#
  s{\n
    ( (?:\$\(\w+\)/ )?
      (?: Makefile |             # These are the targets that are in the
          config\.h |            # makefile to rerun automake and configure.
          stamp-h1 |
          config\.h\.in |
          Makefile\.in |
          config\.status |
          configure |
          configure\.in |
          \$\(ACLOCAL_M4\) ) ) \s* : ([^\n\05]*) }
      {\n$1 : $2 : build_check target_newer}xg;

#
# Now strip out the line numbers we put in, inserting enough newlines so
# the new line numbers are the same as the old line numbers.
#
  $lineno = 0;
  s{(?:\05(\d+))?\n}{
    $ret_str = "\n";
    ++$lineno;                  # Update our line count.
    if (defined($1)) {          # Do we have a target line number?
      $ret_str .= "#\n" x ($1 - $lineno); # Add extra newlines so the line
                                # numbers match.  Add comment lines instead
                                # of blank lines so we don't prematurely
                                # terminate a rule.
      $lineno = $1;
    }
    $ret_str;
  }eg;

  return $_;
}

1;
