
package ExtUtils::Depends;
require Exporter;
use File::Basename;
use Carp;

@ISA = (@ISA, qw(Exporter));

@EXPORT = qw(	add_xs add_raw_xs remove_xs add_pm add_c remove_c 
		add_typemap remove_tyemap add_defs remove_defs 
		add_headers remove_headers add_boot remove_boot sort_libs
		setup_xs write_ext);

@defines = ();
%xs = ();
%c = ();
%typemaps = ();
%defs = ();
%boot = ();
%headers = ();
$pm = {};
@clean = ();

$add = 0;
$Directory = '';


sub add_xs
{
	foreach (@_) { $xs{$Directory . "xs/" .$_} = $add++; }
}

sub add_raw_xs
{
	foreach (@_) { $xs{$_} = $add++; }
}

sub remove_xs
{
	foreach (@_) { delete $xs{$Directory . "xs/". $_}; }
}

sub add_pm
{
	my($k,$v);
	while (($k,$v) = splice(@_, 0, 2)) {
		$k = $Directory . $k;
		$pm->{$k} = $v;
	}
}

sub add_c
{
	foreach (@_) { $c{$Directory . $_} = $add++; }
}

sub remove_c
{
	foreach (@_) { delete $c{$Directory . $_}; }
}

sub add_typemap
{
	foreach (@_) { $typemap{$Directory . $_} = $add++; }
}

sub remove_typemap
{
	foreach (@_) { delete $typemap{$Directory . $_}; }
}

sub add_defs
{
	foreach (@_) { $defs{$Directory . $_} = $add++; }
}

sub remove_defs
{
	foreach (@_) { delete $defs{$Directory . $_}; }
}

sub add_headers
{
	foreach (@_) { $headers{$_} = $add++; }
}

sub remove_headers
{
	foreach (@_) { delete $headers{$_}; }
}

sub add_boot
{
	foreach (@_) { $boot{$_} = $add++; }
}

sub remove_boot
{
	foreach (@_) { delete $boot{$_}; }
}

sub sort_libs {
	my ($libs) = shift;
	my (@libs, %seenlibs, @revlibs, @lflags);
	
	$libs =~ s/(^|\s)-[rR]\S+//g;
	
	@libs = split(/\s+/, $libs);
	%seenlibs = ();
	@revlibs=();
	@lflags=();

	foreach (@libs) {
		if (/^-l/) {
			unshift(@revlibs, $_);
		} else {
			unshift(@lflags, $_) unless $seenlibs{$_}++;
		}
	}
	@libs=();
	foreach (@revlibs) {
		unshift(@libs, $_) unless $seenlibs{$_}++;
	}
	return (@lflags, @libs);
}

sub save_config {
	my ($module, $fname, $inc, $libs, $typemaps, $defs, $defines, $headers, $pm) = @_;
	# genera IFiles.pm
	local(*IF);
	my ($mdir) = $module;
	my ($mdir2) = $module;
	
	$mdir =~ s/.*:://;
	$mdir2 =~ s.::./.g;
	
	open(IF, ">$fname") || die "Cannot open '$fname': $!";
	$pm->{$fname} = '$(INST_ARCHLIBDIR)/'."$mdir/Install/Files.pm";

	print IF "#!/usr/bin/perl\n\npackage ${module}::Install::Files;\n\n";
	print IF "\@typemaps = qw(\n";
	foreach (@$typemaps) {
		my($b) = basename($_);
		print IF "\t$b\n";
		$pm->{$_} = '$(INST_ARCHLIBDIR)/'. "$mdir/Install/" . $b;
	}
	print IF ");\n\n\@defs = qw(\n";
	foreach (@$defs) {
		my($b) = basename($_);
		print IF "\t$b\n";
		$pm->{$_} = '$(INST_ARCHLIBDIR)/'. "$mdir/Install/" . $b;
	}
	print IF ");\n\n\@headers = qw(\n";
	foreach (@$headers) {
		my($b) = $_;
		$b =~ s(^[^<"]+/)(); #"
		print IF "\t$b\n";
		#$pm->{$_} = '$(INST_ARCHLIBDIR)/'. "$mdir/Install/" . $b;
	}
	print IF ");\n\n\@defines = qw(\n";
	foreach (@$defines) {
		print IF "\t$_\n";
	}
	print IF ");\n\n";
	print IF "\$libs = '$libs';\n";
	print IF "\$inc = '$inc';\n";

print IF <<"EOT";

\$CORE = undef;
foreach (\@INC) {
	if ( -f \$_ . "/$mdir2/Install/Files.pm") {
		\$CORE = \$_ . "/$mdir2/Install/";
		last;
	}
}

1;

EOT
	close(IF);
}

sub setup_xs {
	my $xfiles = {};
	my ($ldfrom, $object);
	$ldfrom = $object = '';
	foreach (keys %xs) {
		my($xs) = $_;
		s/\.xs$/.c/;
		$xfiles->{$xs} = $_;
		push(@clean, $_);
		s/\.c$/.o/;
		push(@clean, $_);
		$object .= " $_";
		s(.*/)();
		$ldfrom .= " $_";
	}
	foreach (keys %c) {
		s/\.c$/.o/;
		push(@clean, $_);
		$object .= " $_";
	}
	return ($xfiles, $object, $ldfrom);
}

sub write_ext {
open (EXT, ">build/extension.xsh");
print EXT "\n\n# Do not edit this file, as it is automatically generated by Makefile.PL\n\n";

print EXT "BOOT:\n{\n";

foreach (sort {$boot{$a} <=> $boot{$b}} keys %boot) {
        my($b) = $_;
        $b =~ s/::/__/g;
        $b = "boot_$b";
        print EXT "extern void $b(CV *cv);\n";
}
foreach (sort {$boot{$a} <=> $boot{$b}} keys %boot) {
        my($b) = $_;
        $b =~ s/::/__/g;
        $b = "boot_$b";
        print EXT "callXS($b, cv, mark);\n";
}

print EXT "}\n";
close(EXT);

}

1;

