#!/usr/bin/env perl

use strict;

my @makearg; # It's a perl script because of this: arrays suck in bourne shell.
my $conf = 'config.mk';
my $qconf = 'config-query.mk';
my $make = defined $ENV{MAKE} ? $ENV{MAKE} : 'make'; # could be gmake ...
my $format = `scripts/wrap.sh`;

if(`$make --version` =~ /^GNU Make/)
{
	print "Looks like you are sporting GNU Make, good.\n";
}
else
{
	print STDERR "Your make tool does not seem to be GNU Make. I require the latter (version 3.81 tested). I will continue trying the 'gmake' command, hoping that there is a GNU make available that way.\n";
	$make = 'gmake';
}

my %makepars;
my %makedirs;
my @makedirs;
makepars(\%makepars, \%makedirs, \@makedirs);

for my $arg (@ARGV)
{
	if($arg eq '--help')
	{
		# re-create the parameter structures to capture changed values due to preceeding configure parameters
		# makes sense at least for the directories
		%makepars = ();
		%makedirs = ();
		@makedirs = ();
		makepars(\%makepars, \%makedirs, \@makedirs);
		help();
		exit(0);
	}
	elsif($arg =~ /^--(enable|disable|with|without)-([a-z0-9]+)(|=(.*))$/)
	{
		my ($op, $cfname, $val) = ($1, $2, $4);
		unless(defined $makepars{$cfname})
		{
			print STDERR "WARNING: Unknown parameter: $arg\n";
			next;
		}
		if($op eq 'with')
		{
			$val = 'yes' unless defined $val
		}
		else
		{
			die "Bad usage, only --with-thing gets a value: $arg\n" if defined $val;
			if($op eq 'enable'){ $val = 'yes'; }
			else{ $val = 'no'; }
		}
		push(@makearg, "$makepars{$cfname}{mkname}=$val");
	}
	elsif($arg =~ /^--([a-z0-9]+)=(.*)$/ and defined $makedirs{$1})
	{
		push(@makearg, "$makedirs{$1}{mkname}=$2");
	}
	else{ print STDERR "WARNING: Unknown parameter: $arg\n"; }
}


unlink($conf) if -e $conf;
print "Now call $make to get a build...\n";
system($make, 'DRY_RUN=yes', @makearg, $conf) and die "Failed to make a config:-(\n";
print "\nThis is what you got now:\n\n";
system('cat', $conf); # lazy

sub help
{
	par('This is a crude frontend to DerMixD\'s Makefile to fake the usual GNU configure && make invokation. It turns tunable Makefile variables into paramters in the usual --enable-thing / --disable-thing / --with-thing / --without-thing syntax.');
	par('Those are the things (you shall prepend one of --enable- / --disable- / --with- / --without- for obvious semantics, when there is a value to set apart from enabling/disabling, you shall use --with-thing=value):');
	print "\n";

	my @parpar;
	for my $pn (sort keys %makepars)
	{
		my $parstring = $makepars{$pn}{desc} =~ m:^enable/disable: ? "--enable-$pn / --disable-$pn" : "--with-$pn";
		push(@parpar, "$parstring [$makepars{$pn}{val}]", "\t$makepars{$pn}{desc}");
	}
	par(@parpar);
	print "\n";

	par('Note that you can enforce autodetection (if appropriate) via providing an empty value in the "with" syntax: --with-thing=');
	par('Those are equivalent:');
	par("\t--with-thing=yes and --enable-thing", "\t--with-thing=no and --disable-thing");

	par('You can tune installation paths using the following parameters:');
	my @dirpar;
	for my $pn (@makedirs)
	{
		push(@dirpar, "--$makedirs{$pn}{cfname}=DIR [$makedirs{$pn}{val}]", "\t$makedirs{$pn}{desc}");
	}
	par(@dirpar);

	par("After running `$0`, you should be able to build using `$make`, then install using `$make install`. You can ask about additional targets in the Makefile via `$make help`.");
}

sub cfname
{
	my $name = lc(shift);
	$name =~ s:_:-:g;
	return $name;
}

sub mkname
{
	my $name = uc(shift);
	$name =~ s:-:_:g;
	return $name;
}

sub makepars
{
	my $pars = shift;
	my $dirs = shift;
	my $dirlist = shift;

	unlink($qconf) if -e $qconf;
	system($make, @makearg, 'SKIP_CONFIG=yes', 'DRY_RUN=yes', $qconf);
	open(DAT, '<', $qconf) or die "Cannot read $qconf (is your make tool broken?)!\n";
	my $desc = undef;
	while(<DAT>)
	{
		if(/#\s*(.+)$/)
		{
			$desc = $1;
		}
		elsif(/^([A-Z_0-9]+)\s*:=\s*(.*)/)
		{
			my $mkname = $1;
			my $val = $2;
			my $cfname = cfname($mkname);
			my %par = ('cfname'=>$cfname, 'mkname'=>$mkname, 'val'=>$val, 'desc'=>$desc);
			next if $par{desc} =~ /^internal /;

			if($par{desc} =~ /^directory /)
			{
				$dirs->{$cfname} = \%par;
				push(@{$dirlist}, $par{cfname});
			}
			else
			{
				$pars->{$cfname} = \%par;
			}
		}
	}
	close(DAT);
	unlink($qconf);
}

sub par
{
	print "\n";
	open(FMT, "|$format");
	for(@_){ print FMT $_, "\n"; }
	close(FMT);
}
