BEGIN { 
    $Is_Win32 = ($^O eq "MSWin32");
    if($Is_Win32) {
	require 5.004_02;
    }
    else {
	require 5.003_97; 
    } 
}

use ExtUtils::MakeMaker;
use Config;
use FileHandle ();
use DirHandle ();
use File::Basename qw(dirname);
use File::Path qw(mkpath rmtree);
use Cwd;
use File::Copy qw(cp);

my %vcache = (); #SERVER_VERSION
my %mcache = (); #MODULE_MAGIC_NUMBER

#version 1.5 that ships with 5.003 is broken!
*cp = sub { 
    system "cp @_";
    for (@_) { -e $_ or die $! }
} if $File::Copy::VERSION < 2.0;

$VERSION = "1.11";

use subs qw(_prompt iedit asrc);

gen_script("t/net/perl/cgi.pl");
gen_script("t/report");

if($] < 5.004_04) {
    print <<EOF;
I see you're building with Perl $]
It is strongly recommended that you upgrade to 5.004_04 or higher,
as there are memory leaks present in lower versions or Perl.
EOF
sleep(1);
}

unless ($Is_Win32) {
    readline_setup();        
}

eval 'require Apache::MyConfig' ;

$APACHE_SRC_DEFAULT = $@ ? 
    '../apache_x.x/src'  :
    $Apache::MyConfig::Setup{Apache_Src} ; 

my $PWD = cwd;
my %SSL = (
    "apache_ssl.c" => "Ben-SSL",
    "mod_ssl.h"   => "Stronghold",
);

unless ($Is_Win32) {
    # Patch up the Makefiles we are going to use with Apache
    system $^X, "-pi", "-e", "s!^PERL\\s*=.*!PERL=$Config{'perlpath'}!",
                <src/Makefile.tmpl*>, "src/modules/perl/Makefile";

    mkdir "t/logs", 0755;
}

unless (-e "t/docs/test.shtml") {
    cp "t/docs/test.html", "t/docs/test.shtml";
}

chmod 0644, "t/conf/mod_perl_srm.conf";

unless ($Is_Win32) {
     system "chmod a+x t/net/perl/* t/net/perl/io/*";
}

#generated by us at one time or another
my(@do_clean) = qw{
   t/docs/.htaccess 
   t/docs/hooks.txt
   src/Configuration
   lib/Apache/MyConfig.pm
   Apache/Apache.xs
   Constants/Constants.xs
   t/modules/ssi.t       
   /tmp/mod_perl_error_log
   /tmp/mod_perl_srm.conf
   /tmp/mod_perl_httpd.pid
};
#t/conf/httpd.conf
#t/net/config.pl

for(@do_clean) { unlink $_ }

unless ($Is_Win32) {
   rename "t/conf/httpd.conf", "t/conf/httpd.conf.old";
}

rmtree "t/docs/stacked", 0, 0;
rmtree "t/docs/subr", 0, 0;

my(@test_pre_init) = qq(
test_pre_init:
);

# Automatic setup support
my(@adirs, %seen, %mft_map, %vers_map, $src_dir, $vers, $conf, $ans);
%vers_map = (
   '1.1.1' => "Makefile.tmpl",
   '1.1.3' => "Makefile.tmpl",
   '1.2'  => "Makefile.tmpl-1.2",
   '1.1.1Xcert-Sentry' => "Makefile.tmpl-XCert",
   '1.1.1Ben-SSL' => "Makefile.tmpl-Ben-SSL",
   '1.1.3Ben-SSL' => "Makefile.tmpl-Ben-SSL",
   '1.2Ben-SSL' => "",
    NONE => "", 
);	     

$EVERYTHING = 0;
$PERL_DEBUG = "";
$PERL_DESTRUCT_LEVEL = "";
$PERL_STATIC_EXTS = "";
$PERL_EXTRA_CFLAGS = "";
$Port = $PORT = 8529;
$DO_HTTPD = $ENV{DO_HTTPD} || 0;
$NO_HTTPD = $ENV{NO_HTTPD} || 0;
$PERL_TRACE = 0;
$ALL_HOOKS  = 0;
$APACHE_SRC = "";
$APACHE_HEADER_INSTALL = 1;
$PERL_SECTIONS = 0;
$PERL_SSI = 0;
$ADD_VERSION = 1;
$STATIC = 1;
$DYNAMIC = 0;
$CONFIG = "";
$ADD_MODULE = "";

my %experimental = map { $_,1 } qw{
PERL_OBJECT_HANDLERS
PERL_MARK_WHERE
DO_INTERNAL_REDIRECT
ERRSV_CAN_BE_HTTP
PERL_SECTIONS_SELF_BOOT
PERL_RESTART_HANDLER
};

my @mp_args = 
    qw(EVERYTHING DO_HTTPD NO_HTTPD CONFIG ADD_MODULE
       ALL_HOOKS ADD_VERSION STATIC DYNAMIC);

sub is_mp_arg {
    my $arg = shift; 

    return 1 if $experimental{$arg};

    for (@mp_args) {
	return 1 if $arg eq $_;
    }
    return 0;
}

#callback hooks
@callback_hooks = qw{
   PERL_DISPATCH
   PERL_CHILD_INIT PERL_CHILD_EXIT
   PERL_POST_READ_REQUEST PERL_TRANS PERL_HEADER_PARSER
   PERL_ACCESS PERL_AUTHEN PERL_AUTHZ 
   PERL_TYPE PERL_FIXUP
   PERL_HANDLER PERL_LOG 
   PERL_INIT PERL_CLEANUP
   PERL_STACKED_HANDLERS 
   PERL_METHOD_HANDLERS
};

$callback_alias{PERL_INIT} = "PERL_HEADER_PARSER";
$callback_alias{PERL_CLEANUP} = "PERL_LOG";
%callback_hooks = map { $_,0 } @callback_hooks;
$callback_hooks{PERL_HANDLER} = 1; #PerlHandler always on
%cant_hook = ();

my @mm_args;
{
    my($fh,$file);
    for (qw(./ ../), "$ENV{HOME}/.") {
	last if $fh = FileHandle->new($file = $_."makepl_args.mod_perl");
    }
    if($fh) {
	print "Reading Makefile.PL args from $file\n";
	while(<$fh>) {
	    chomp; 
	    s/^\s+//; s/\s+$//;
	    next if /^#/ || /^$/;
	    last if /^__END__/;
	    unshift @ARGV, split /\s+/, $_;
	}
	close $fh;
    }
}

while($_ = shift) {
    ($k,$v) = split /=/, $_, 2;
    unless (/^(PERL|APACHE)/ or is_mp_arg($k)) {
	push @mm_args, $_;
    }
    $v = 1 unless defined $v;
    if($experimental{$k}) {
	$experimental{$k}++;
	$PERL_EXTRA_CFLAGS .= " -D${k}=1";
    }
    ${$k} = $v, next if defined ${$k};
    $callback_hooks{$k} = $v if exists $callback_hooks{$k};
}

@ARGV = @mm_args;
$STATIC = 0 if $DYNAMIC;
$Configuration = $CONFIG || "Configuration";

for (keys %callback_alias) {
    $callback_hooks{$callback_alias{$_}}++ 
       if $callback_hooks{$_};
}

if($EVERYTHING) {
    @callback_hooks{qw(PERL_STACKED_HANDLERS PERL_METHOD_HANDLERS)} = (1) x 2;
    for(qw(ALL_HOOKS PERL_SSI PERL_SECTIONS)) {
       $$_ = 1;
    }
}


if($ALL_HOOKS) {
    for (@callback_hooks) {
	next if /Handlers?$/i;
	$callback_hooks{$_}++;
    }
}

if($Is_Win32) {
    $NO_HTTPD = 1;
    win32_setup();
} 

unless ($NO_HTTPD) {
for $src_dir ($APACHE_SRC, <../apache*/src>, 
    <../stronghold*/src>, </usr/local/stronghold*/src>,
					"../src", "./src")
{
    next unless -d $src_dir;
    next if $seen{$src_dir}++;
    next unless $vers = httpd_version($src_dir);
    unless(exists $vers_map{$vers}) {
	print STDERR "Apache version '$vers' unsupported\n";
	next;
    }
    $mft_map{$src_dir} = $vers_map{$vers};
    #print STDERR "$src_dir -> $vers_map{$vers}\n";
    push @adirs, $src_dir;
    $modified{$src_dir} = (stat($src_dir))[9];
    last if $DO_HTTPD;
}

unless (@adirs) {
    print "Enter `q' to stop search\n";
    while(1) {
       print "Please tell me where I can find your apache src\n" ; 
       $src_dir = _prompt("", $APACHE_SRC_DEFAULT);
       last if $src_dir eq "q";
	if(-d $src_dir) {
	    push(@adirs, $src_dir);
	    $mft_map{$src_dir} = $vers_map{httpd_version($src_dir)};
	    last;
	}
	else {
	    print "Can't stat $src_dir\n";
	}
    }
}

}

for $adir (sort {$modified{$b} <=> $modified{$a}} @adirs) {
    $conf = "$adir/$Configuration";
    $httpd_h = asrc($adir)."/httpd.h";

    if (-e $httpd_h) {
	unless($NO_HTTPD and not $DYNAMIC) {
	    unless($DO_HTTPD) {
		$ans = _prompt("Configure mod_perl with $adir ?", "y");
		next unless $ans =~ /^y$/i;
	    }
	    $APACHE_SRC = $adir;
	    $IsBenSSL = -e "$adir/apache_ssl.c";
	    last unless(-e $conf || -e "$conf.tmpl"); #building from 'make offsite-tar' 
	}
	unless ($DO_HTTPD or $NO_HTTPD) {
	    $ans = _prompt("Shall I build httpd in $adir for you?", "y");
	    ++$NO_HTTPD unless $ans =~ /^y$/i;
	}

	if($NO_HTTPD) {
	    #must generate Makefile.config for 1.3bx
	    unless (-e "$adir/Makefile.config") {
		my $cfgfile = $CONFIG ? $CONFIG : "Configuration";
		print "(cd $adir && ./Configure -file $cfgfile)";
	    }
	}
	last if $NO_HTTPD;

	unless ($can_dash_make{asrc $adir}) {
	    unless (-e "$adir/Makefile.tmpl.bak") {
		print STDERR "Backing up $adir/Makefile.tmpl to $adir/Makefile.tmpl.bak\n";
		cp "$adir/Makefile.tmpl", "$adir/Makefile.tmpl.bak";
	    }
	    cp "src/$mft_map{$adir}", "$adir/Makefile.tmpl";
	    print STDERR "cp src/$mft_map{$adir} $adir/Makefile.tmpl\n";
	}

	mkpath "$adir/modules/perl";
	#ignore make's output here
	`(cd $adir/modules/perl && make clean 2> /dev/null)`;

	local(*MANI);
	open *MANI, "MANIFEST" or die "open MANIFEST $!";
	my $atopdir = dirname($adir);

	#only rm and cp files mod_perl ships with
	while(<MANI>) {
	    next unless m,^src/modules/perl/,; chomp;
	    #print "rm -f $adir/$_\n";
	    unlink "$atopdir/$_";
	    #print "cp $_ $atopdir/$_\n";
	    my $dest = "$atopdir/$_";
	    cp $_, $dest;
	    $mani_src{$_}++;
	}
	close MANI;

	if($PERL_EXTRA_CFLAGS) {
	    $PERL_EXTRA_CFLAGS = join(" ", split(",",  $PERL_EXTRA_CFLAGS));
	    $PERL_EXTRA_CFLAGS =~ s/\s+/ /g;
	}

	if($PERL_DEBUG) {
	    my $lib = "$Config{archlibexp}/CORE/libperld$Config{lib_ext}";
	    if (-e $lib) {
		$libperl = " -- -lperld";
	    }
	    $PERL_EXTRA_CFLAGS .= " -g";
	    $PERL_TRACE=1;
	    $PERL_DESTRUCT_LEVEL=2;
	    print "DEBUG mode...\n";
	    print "...adding `-g' to EXTRA_CFLAGS\n";
	    print "...turning on PERL_TRACE\n";
	    print "...setting PERL_DESTRUCT_LEVEL=2\n";
	    print "...linking against libperld\n" if $libperl;
	    sleep(1);
	}

	$PERL_EXTRA_CFLAGS .= " -DPERL_DESTRUCT_LEVEL=$PERL_DESTRUCT_LEVEL"
	    if $PERL_DESTRUCT_LEVEL;


	unless(-e "src/Configuration" and (-M "src/Configuration" < -M $conf)) {
	    unless(-e $conf) {
		cp "$conf.tmpl", $conf;
	    }
	    cp $conf, "src/Configuration";
	    $conf = "src/Configuration";

	    conf_fixup("$adir/Makefile.tmpl", $conf);
	}
    }

    if ($NO_HTTPD) {

    }
    else {
	$conf = "src/Configuration";
	my($dash_make, $cfgfile);
	$dash_make = " -make $PWD/src/$mft_map{$adir} "
	    if $can_dash_make{asrc $adir} and $mft_map{$adir};
	#print STDERR "(cd $adir; ./Configure${dash_make} -file $PWD/$conf)\n";
	$cfgfile = $CONFIG ? $CONFIG : "$PWD/$conf";
	system "(cd $adir && ./Configure${dash_make} -file $cfgfile)";

	open FH, "$APACHE_SRC/Makefile" or 
	    die "can't open $APACHE_SRC/Makefile $!";
	while(<FH>) {
	    $SSL_BASE  ||= $1 if /^\s*SSL_BASE\s*=\s*(.*)/;
	    $EXTRA_CFLAGS = $1 if /CFLAGS1\s*=\s*(.*)/;
	    $SSLINCS = $1 if /SSLINCS\s*=\s*(.*)/;
	}
	close FH;

	if($SSL_BASE) {
	    $SSL_INCLUDE = " -I$SSL_BASE/include ";
	    $SSL_CFLAGS = "-DAPACHE_SSL $SSL_INCLUDE";
	}

	#stronghold
	if($SSLINCS) {
	    $SSL_INCLUDE = " $SSLINCS ";
	    $SSL_CFLAGS = "-DAPACHE_SSL $SSL_INCLUDE";
	}
    }
    print "EXTRA_CFLAGS: $EXTRA_CFLAGS\n" if $EXTRA_CFLAGS;
    print "SSL_CFLAGS: $SSL_CFLAGS\n" if $SSL_CFLAGS;
    last if $APACHE_SRC;
}

if($DYNAMIC) {
    for (qw(Apache Constants)) {
	cp "src/modules/perl/${_}.xs", "${_}/${_}.xs" if $DYNAMIC;
    }
}

if($APACHE_SRC) {
    ++$STATIC if grep { $_ eq lc($Config{osname}) } qw(aix svr4 unixware);

    my $mmn    = magic_number($APACHE_SRC);
    my $httpdv = httpd_version($APACHE_SRC,1);

    unless($httpdv >= 120) {
	$callback_hooks{PERL_HEADER_PARSER} = 0;
	$cant_hook{PERL_HEADER_PARSER} = 
	    "(need 1.2.0 or higher)";
    }

    if($httpdv >= 130) {
	if($callback_hooks{PERL_CHILD_INIT}) {
	    $My::child_init++;

	}
    }
    else {
	$callback_hooks{PERL_CHILD_INIT} = 0;
	$cant_hook{PERL_CHILD_INIT} = 
	    "(need 1.3b2 or higher)";
    }

    if($mmn >= 19970728) {
	if($callback_hooks{PERL_CHILD_EXIT}) {
	    $My::child_exit++
	}
    }
    else {
	$callback_hooks{PERL_CHILD_EXIT} = 0;
	$cant_hook{PERL_CHILD_EXIT} = 
	    "(need 1.3b2 or higher)";
    }

    unless($mmn >= 19970825) {
	$callback_hooks{PERL_POST_READ_REQUEST} = 0;
	$cant_hook{PERL_POST_READ_REQUEST} = 
	    "(need 1.3b2 or higher)";
    }

#    if($Config{extensions} =~ /Thread/) {
#	$PERL_SSI = 0;
#	$cant_hook{PERL_SSI} = "(won't build w/ threaded Perl)";
#    }

    setup_for_static();

    for (@callback_hooks) {
	($k,$v) = ($_,$callback_hooks{$_});

	iedit "$APACHE_SRC/modules/perl/Makefile", "s/^$k /#$k /" if $v;

	$why = ($cant_hook{$k} || "(enable with $k=1)") unless $v;
	$k =~ s/([A-Z]+)/ucfirst(lc($1))/ge;
	$k =~ s/_//g;
	$k .= "Handler" unless $k =~ /Handlers?$/;
	push @mod_perl_hooks, $k;
	print $k . '.' x (28 - length($k));
	print $v ? "enabled\n" : "disabled $why\n";
    }

    unless($httpdv >= 120) {
	$PERL_SECTIONS = $PERL_SSI = 0;
	$cant_hook{PERL_SECTIONS} = $cant_hook{PERL_SSI} = 
	    "(need 1.2.0 or higher)";
    }

    for (qw(PERL_SECTIONS PERL_SSI), keys %experimental) {
	$k = $_;

	if($experimental{$_}) {
	    next unless $experimental{$_} > 1;
	    print $k . '.' x (28 - length($k));
	    print "enabled (experimental)";
	}
	else {
	    $why = ($cant_hook{$_} || "(enable with $k=1)") unless $$_;
	    $k =~ s/([A-Z]+)/ucfirst(lc($1))/ge;
	    $k =~ s/_//g;
	    $k =~ s/Ssi$/SSI/; #*shrug*
	    push @mod_perl_hooks, $k;
	    print $k . '.' x (28 - length($k));
	    print $$_ ? "enabled" : "disabled $why\n";
	}

	print "\n";

	iedit "$APACHE_SRC/modules/perl/Makefile", "s/^($_) /#\$1 /"
	    if $$_;
    }

    iedit "$APACHE_SRC/modules/perl/Makefile", "s/^#TRACE/TRACE/" if $PERL_TRACE;

    my $ssl_name = is_ssl();
    if($ssl_name) {
	print "I see you are building with $ssl_name,\nI'll set the SSL flags in mod_perl's Makefile\n";

	if($ssl_name =~ /stronghold/i) {
	    my $skey;
	    my $conf = "/usr/local/stronghold/conf/httpd.conf";
	    if(-e $conf) {
		open FH, $conf;
		while(<FH>) {
		    if(/^StrongholdKey/) {
			$skey = $_;
			last;
		    }
		}
		close FH;
	    }

	    if($skey) {
		chomp($StrongholdKey = $skey);
		print "Using $skey for 'make test'\n";
	    }
	    else {
		print "Before running `make test', ",
		"you must add your `StrongholdKey' to t/conf/httpd.conf\n"; 
	    }
	}

	iedit "$APACHE_SRC/modules/perl/Makefile",	
	"s:^#APACHE_SSL.*:APACHE_SSL = $SSL_CFLAGS:";
    }

    #my $incdir = ($mmn >= 19970825) ? "../../main" : "../..";
    my $minc = asrc($APACHE_SRC);
    $minc =~ /(main|include)/;
    my $incdir = $1 ? "../../$1" : "../..";
    my $edit_note = quotemeta(<<EOF);
#### Start of Makefile.PL created section ####
#---------------------------------------------------------------------
# This Makefile is derived from:
# $PWD/src/modules/perl/Makefile 
# which comes with the mod_perl distribution and 
# written by mod_perl's Makefile.PL.
# Rerunning Makefile.PL overwrites this file. Consequently...

# DO NOT EDIT THIS FILES, EDIT
#    $PWD/src/modules/perl/Makefile
# INSTEAD
#---------------------------------------------------------------------

MOD_PERL_VERSION = $VERSION

INCDIR = $incdir

EOF

    iedit "$APACHE_SRC/modules/perl/Makefile", "s/^#__ORIGINAL__/$edit_note/";

    #needed as of 1.3b1+ 

    #XXX: argh, what a bloody nightmare!!!
    #if($mmn >= 19970912) { 
    if(0) {
	my $fh = FileHandle->new("$APACHE_SRC/modules/perl/Makefile");
	my @file = <$fh>;
	close $fh;
	$fh = FileHandle->new(">$APACHE_SRC/modules/perl/Makefile");
	while (@file) {
	    last if $file[0] =~ /Start of Makefile.PL created section/;
    	    shift @file;
	}
	print $fh @file;
	close $fh;
    }

    if($mmn >= 19970912) {     #1.3b1
	system "cat $APACHE_SRC/Makefile.config $APACHE_SRC/modules/perl/Makefile > /tmp/mpmf.$$";
	system "mv /tmp/mpmf.$$ $APACHE_SRC/modules/perl/Makefile";
    }

    if($callback_hooks{PERL_TRANS}) {
	push @test_pre_init, 
	"\t", '$(CP) t/conf/mod_perl_srm.conf /tmp', "\n";
    }
    unless (-l "t/httpd") {
	system "$Config{lns} $APACHE_SRC/httpd t/httpd";
    }
    write_extra_tests();
}

unless (-e "t/net/config.pl") {
    cp "t/net/config.pl.dist", "t/net/config.pl";
}

unless($Is_Win32 or -e "t/conf/httpd.conf") {
    cp "t/conf/httpd.conf-dist", "t/conf/httpd.conf";
    chmod 0644, "t/conf/httpd.conf";

    $User  = $Is_Win32 ? "nobody" : (getpwuid($>) || $>);
    $Group = $Is_Win32 ? "nogroup" : (getgrgid($)) || $)); 
    if($User eq "root") {
	my $other = (getpwnam('nobody'))[0];
	$User = $other if $other;
    } 
    if($User eq "root") {
	print "Cannot run tests as User `$User'\n";
        $User = _prompt("Which User?", "nobody");
	$Group = _prompt("Which Group?", $Group); 
    }
    print STDERR "Will run tests as User: '$User' Group: '$Group'\n";

    if($Port != $PORT) {
	iedit "t/conf/httpd.conf", "s/^(Port) .*/\$1 $PORT/";
	iedit "t/net/config.pl", "s/$Port/$PORT/;";
    }

    {
	my $mmn = magic_number($APACHE_SRC) unless $NO_HTTPD;
	my $hf = FileHandle->new(">>t/net/config.pl") or 
	    die "can't open t/net/config.pl";
	my($k,$v);
	print $hf "%callback_hooks = (\n";
	while(($k,$v) = each %callback_hooks) {
	    print $hf "   $k => $v,\n";
	}
        print $hf "   MMN => $mmn,\n";
	print $hf ");\n1;\n";
	$hf->close;
    }

    #expand ./t to full path
    iedit "t/conf/httpd.conf", "s: \./t(\S*): $PWD/t\$1:";

    for (qw(User Group)) {
	iedit "t/conf/httpd.conf", "s/^$_ .*/$_ $$_/"; 
    }
    conf_append("SSLDisable") if $IsBenSSL;
    conf_append($StrongholdKey) if $StrongholdKey;

    #phooey!
    my $v = httpd_version($APACHE_SRC, 1);

    conf_append("LockFile /tmp/mod_perl.lock") if $v >= 121;
    conf_append("PerlChildInitHandler My::child_init") if $My::child_init;
    conf_append("PerlChildExitHandler My::child_exit") if $My::child_exit;

    conf_append(<<EOF) if $callback_hooks{PERL_STACKED_HANDLERS}; 
<Location /chain>
SetHandler perl-script
PerlHandler Stacked::one Stacked::two Stacked::three Stacked::four
</Location>
EOF
}

write_my_config($APACHE_SRC);
{
    (my $pmv = $VERSION) =~ s/_//g;
    $pmv =~ s/-dev$//;
    my $hooks = "@mod_perl_hooks";
    my $dummy = "hooks=`$hooks'\n" unless $hooks;
    iedit "lib/mod_perl.pm", qq(s/VERSION .*/VERSION = "$pmv";/);

    iedit "lib/mod_perl.pm", 
    qq(s/sub hooks.*/sub hooks { qw($hooks) }/);

    require "lib/mod_perl.pm";
    my @list = mod_perl::hooks();
    @list == @mod_perl_hooks or die "Edit of lib/mod_perl.pm failed $!\n";

    unlink "lib/mod_perl.pm~";
}

#checking for LWP code, borrowed from LWP's own Makefile.PL :-)
unless ($Is_Win32) {
    print "Checking for LWP::UserAgent......";
    eval {
	require LWP::UserAgent;
    };
    if ($@) {
	$no_lwp++;
	$missing_modules++;
	print "failed\n";
	print <<EOT;
$@
The libwww-perl library is needed to run the test suite.
Installation of this library is recommended, but not required.   

EOT
    sleep(2);  # Don't hurry too much
    } else {
	print "ok\n";
    }
}

sub is_ssl {
    my $d = shift || $APACHE_SRC;
    for (keys %SSL) {
	#warn "looking for $APACHE_SRC/$_\n";
	return $SSL{$_} if -e "$d/$_";
    }
    return 0;
}
  
sub write_extra_tests {
    #ensure we can find blib/ 
    local *FH;
    open FH, ">t/docs/blib.pl";
    print FH "use lib qw(\n", 
    (map { "$PWD/$_\n" } qw(blib/lib blib/arch)),
    ");\n1;\n";
    close FH;

    if($PERL_SSI) {
	cp "t/modules/ssi.test", "t/modules/ssi.t";
    }

    mkdir "t/docs/subr", 0755;
    system "date > t/docs/subr/index.html";

    return unless 
	$callback_hooks{PERL_STACKED_HANDLERS} 
    and $callback_hooks{PERL_FIXUP};
    local *FH;
    my $meth_test;
    if($callback_hooks{PERL_METHOD_HANDLERS}) {
	$meth_test = <<'EOF';
#see startup.pl
PerlFixupHandler MyClass->method 
PerlFixupHandler MyClass 
PerlFixupHandler LoadClass
PerlFixupHandler LoadClass->method
EOF
    }
    my $dir = "t/docs/stacked";
    mkdir $dir, 0755;
    cp "t/docs/test.html", $dir;
    open FH, ">$dir/.htaccess";
    print FH <<EOF;
    $meth_test
PerlFixupHandler  Apache::OK Apache::DECLINED MyClass::method
EOF
        close FH;
}

cp "t/conf/httpd.conf", "t/httpd.conf";

if($ENV{TEST_PERL_DIRECTIVES}) {
    #push @DIR, 't/TestDirectives';
    system "(cd t/TestDirectives && $^X Makefile.PL)";
}

WriteMakefile(
    #DIR => \@DIR,
    NAME    => "mod_perl",
    VERSION => $VERSION,
    #should override `CCFLAGS', can't with older perls
    #CCDLFLAGS => "$Config{ccdlflags} $EXTRA_CFLAGS", 
    DEFINE => $EXTRA_CFLAGS, 
    macro   => {
        APACHE_SRC => $APACHE_SRC,
	ARCHNAME => $Config{archname},
	PERL_VERSION => $]+0,
	HTTPD => (is_ssl() ? "httpsd" : "httpd"),
	PORT => $PORT,
	PWD => $PWD,
	CVSROOT => 'perl.apache.org:/export/home/cvs',
    },
    'dist'    => {
	COMPRESS=> 'gzip -9f', SUFFIX=>'gz',
	CI => qq(ci -u -m\\"See Changes file\\"),
    },
    clean   => {
	FILES	=> "@do_clean",
    }
);

print "*** BSDI users: be sure to read the INSTALL `Notes' section ***\n"
    if $Config{osname} =~ /bsdos/i;

cleanup_for_static();

sub MY::clean {
    my $self = shift;
    my $string = $self->MM::clean;
    return $string if $NO_HTTPD;
    my $asrc = asrc($APACHE_SRC, "http_main.c");
    return $string unless $APACHE_SRC and -e "$asrc/http_main.c";
    $string .= "\t-cd \$(APACHE_SRC) && \$(MAKE) clean\n";
    $string;
}

sub MY::top_targets {
    my $self = shift;
    my $string = $self->MM::top_targets;
    return $string unless $APACHE_SRC and -f "$APACHE_SRC/$Configuration";
    my $asrc = asrc($APACHE_SRC, "http_main.c");
    if(-e "$asrc/http_main.c" and !$NO_HTTPD) {
        $string =~ s/(pure_all\s+::\s+)(.*)/$1 apache_httpd $2/;
    }
    $string .= <<'EOF';

apache_httpd: $(APACHE_SRC)/Makefile.tmpl
	(cd $(APACHE_SRC) && $(MAKE) CC="$(CC)";)

tar_Apache:
	(cd $(INSTALLSITELIB); \
	     $(TAR) -cf $(PWD)/Apache.tar mod_perl.pm Apache.pm Apache $(ARCHNAME)/auto/Apache; )

offsite-tar:
	$(CP) MANIFEST MANIFEST.orig
	$(PERL) -e 'for (<$(APACHE_SRC)/*.h>) {' \
	-e 'system "$(CP) $$_ src/";' \
	-e 's,^$(APACHE_SRC),,;' \
	-e 'system "echo src$$_ >> MANIFEST";' \
	-e '}' 
	$(MAKE) dist
	$(RM_F) src/*.h
	$(MV) MANIFEST.orig MANIFEST

EOF

    $string;
}

sub MY::pasthru {
    return unless $APACHE_SRC;
    my $self = shift;
    chomp(my $str = $self->MM::pasthru);
    join $/, "$str\\", 
    "\t".'APACHE_SRC="$(APACHE_SRC)"\\', 
    "\t".'DEFINE="$(DEFINE)"', 
    "";   
}

sub MY::test {
    my $script = "t/TEST";
    $script .= ".win32" if $Is_Win32;
    my $my_test = $Is_Win32 ? q(

test:	run_tests

) :

q(

test:	pure_all start_httpd run_tests kill_httpd

);

    join '', @test_pre_init,
    qq(
MP_TEST_SCRIPT=$script
),
    q(
TEST_VERBOSE=0

kill_httpd:
	kill `cat /tmp/mod_perl_httpd.pid`
	@$(RM_F) /tmp/mod_perl_srm.conf
	@$(RM_F) /tmp/mod_perl.lock.*
	$(RM_F) /tmp/mod_perl_httpd.pid
	$(RM_F) /tmp/mod_perl_error_log

start_httpd: test_pre_init
	@(cd t/conf; test -f httpd.conf || cp httpd.conf-dist httpd.conf)
	@(cd t/net; test -f config.pl || cp config.pl.dist config.pl)
	@$(TOUCH) /tmp/mod_perl_srm.conf
	$(APACHE_SRC)/$(HTTPD) -f `pwd`/t/conf/httpd.conf -X -d `pwd`/t &
	@echo httpd listening on port $(PORT)
	@echo will write error_log to: /tmp/mod_perl_error_log
	@echo "letting apache warm up...\c"
	@sleep 2
	@echo done

rehttpd:   kill_httpd start_httpd

run_tests:
	$(FULLPERL) $(MP_TEST_SCRIPT) $(TEST_VERBOSE)

),

$my_test,

q(

test_report:
	$(MAKE) test | t/report
);
}

use File::Find;

sub MY::subdirs {
    my $self = shift;
    if($ENV{TEST_PERL_DIRECTIVES}) {
	push @{$self->{DIR}}, "t/TestDirectives";
    }
    $self->MM::subdirs(@_);
}

sub wanted {
    return unless /\.h$/;
    (my $d = $File::Find::dir) =~ s:^\Q$APACHE_SRC::;
    $d =~ s:^/::;

    my $from = "$File::Find::dir/$_";
    my $to   = '$(INST_ARCHLIB)/' . "auto/Apache/include/";
    $to .= "$d/" if $d;
    $to .= $_;

    $My::self->{PM}->{$from} = $to;
}

sub MY::post_initialize {
    my($self) = shift;

    return unless $APACHE_SRC and $APACHE_HEADER_INSTALL;

    $My::self = $self;

    finddepth(\&wanted, $APACHE_SRC);

    '';
}

sub MY::postamble {

    return <<'EOF';
cvs_export :
	cvs -d $(CVSROOT) export -rv$(VERSION_SYM) -d$(DISTVNAME) .

cvs_rtag :
	cvs -d $(CVSROOT) rtag v$(VERSION_SYM) .
	@echo update Makefile.PL's VERSION now

EOF
}

sub MY::manifypods {
    my $self = shift;
    my $ver = $self->{VERSION} || "";
    local($_) = $self->MM::manifypods(@_);
    s/pod2man\s*$/pod2man --release mod_perl-$ver/m;
    $_;
}

sub fold_dots {
    my $v = shift;
    $v =~ s/\.//g;
    $v .= "0" if length $v < 3;
    $v;
}

sub vcache {
    my($v,$dir) = @_;
    $vcache{$dir} = fold_dots($v);
}

sub httpd_version {
    my($dir, $vnumber) = @_;
    $dir = asrc $dir;
    if($vnumber) {
	return $vcache{$dir} if $vcache{$dir};
    }
    my $fh = FileHandle->new("$dir/httpd.h") or return;
    my($server, $version, $rest);
    my($fserver, $fversion, $frest);
    my($string, $extra, @vers);
    while(<$fh>) {
	next unless s/^#define\s+SERVER_(BASE|)VERSION\s+"(.*)\s*".*/$2/;
	chomp($string = $_);

	#print STDERR "Examining SERVER_VERSION '$string'...";
	#could be something like:
	#Stronghold-1.4b1-dev Ben-SSL/1.3 Apache/1.1.1 
	@vers = split /\s+/, $string;
	foreach (@vers) {
	    next unless ($fserver,$fversion,$frest) =  
		m,^([^/]+)/(\d\.\d+\.?\d*)([^ ]*),i;
	    #print STDERR "match ($fserver,$fversion,$frest)\n";  
	    if($fserver =~ /Xcert-Sentry/i or $fserver eq "Ben-SSL") {
		$extra ||= $fserver;
		#print STDERR "I see $fserver/$fversion, ok\n";
		next;
	    }

	    if($fserver eq "Apache") {
		($server, $version) = ($fserver, $fversion);
		if($version == 1.2 and $frest =~ s/^b(\d+).*/$1/) {
		    if($frest >= 8 and is_ssl($dir)) {
			$do_link_swap++;
			$can_dash_make{$dir}++;

			return $vnumber ? vcache($version,$dir) : "NONE";
		    }
		    warn "Apache/1.2b$frest is not supported, upgrade to 1.2.0.\n";
		    return undef;
		}
		elsif($version >= 1.2) {
		    $do_link_swap++ if is_ssl($dir);
		    $can_dash_make{$dir}++;
		    return $vnumber ? vcache($version,$dir) : "NONE";
		}
	    }
	    else {
		#print STDERR "'$fserver/$fversion' unrecognized.\n";
		next;
	    }
	    print STDERR "Found $fserver '$fversion' in $dir/httpd.h\n";
	}
    }
    $fh->close;
    #print STDERR "return $version$extra\n";
    return($version.$extra);
}

sub magic_number {
    my $d = asrc shift;
    return $mcache{$d} if $mcache{$d};
    my $fh = FileHandle->new("$d/http_config.h") or die $!;
    my $n;
    while(<$fh>) {
	if(s/^#define\s+MODULE_MAGIC_NUMBER\s+(\d+).*/$1/) {
	   chomp($n = $_);
	   last;
       }
    }
    $fh->close;
    return($mcache{$d} = $n);
}

sub cleanup_for_static {
    return unless $STATIC;
    for (qw(Apache Constants)) {
	rename "${_}/${_}.xs.disabled", "${_}/${_}.xs";
    }
}

sub setup_for_static {
    my $d = "$APACHE_SRC/modules/perl";
    my $mf = "$APACHE_SRC/modules/perl/Makefile";
    my @static_src = ();

    iedit $mf, "s/(PERL_STATIC_EXTS) =.*/\$1 = $PERL_STATIC_EXTS/"
	if $PERL_STATIC_EXTS;

    return unless $STATIC;

    cp "Apache/typemap", $d;

    for (qw(Apache Constants)) {
	rename "${_}/${_}.xs", "${_}/${_}.xs.disabled" if -e "${_}/${_}.xs";
	push @static_src, "$_.c";
    }

=pod
    my @xs_names = ();
    my @xs_files = ();
    my $dir = "src/modules/perl";
    my $dh = DirHandle->new($dir) or die;

    for my $file ($dh->read) {
	next unless $file =~ /\.xs$/;
	push @xs_names, module_name_from_xs("$dir/$file");
	push @xs_files, $file;
	unless ($mani_src{"$dir/$file"}) {
	    cp "$dir/$file", $d;
	    print "Adding module `$xs_names[-1]' to httpd\n";
	}
    }
    #print "XS_NAMES=@xs_names\n";
    #print "XS_FILES=@xs_files\n";

    #XXX think about this some more
    iedit $mf, "s/^#STATIC_SRC.*/STATIC_SRC = @xs_files/";
    iedit $mf, "s/^#STATIC_EXTS.*/STATIC_EXTS = @xs_names/";
=cut

    iedit $mf, "s/^#STATIC_/STATIC_/";

    #bloody hell, make sucks and so does this.
    #this has only cause a few people pain, enough.
    iedit $mf, "s/ \Q\$(STATIC_SRC)\E/ @static_src/";
}

sub module_name_from_xs {
    my $file = shift;
    my $fh = FileHandle->new($file) or
	die "can't open file $file $!";
    my($module, $package, $prefix, %seen);
    while(<$fh>) {
	if( ($module, $package, $prefix) =
	    /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/)
	{
	    $seen{$module}++;
	}
    }
    if(keys %seen > 1) {
	warn "$module name guess might be incorrect";
    }
    return (keys %seen)[0];
}

sub readline_setup {
    eval 'use Term::ReadLine' ;

    if ($@ eq '') {
	$::term = new Term::ReadLine 'mod_perl install';
	
	eval {
	    sub main::_prompt {
		my ($prompt, $default) = @_ ;
		
		$_ = $::term -> readline ("$prompt [$default] ") ;
		if (!/^\s*$/) {
		    s/\s+$//;
		    return $_ ;
		}
		else {
		    if ($_ eq "") {
			return $default ;
		    }
		    else {
			return "" ; 
		    }
		}
	    }
        };
	die $@ if $@;
	print "ReadLine support enabled\n" ;
    }
    else { 
	eval <<'EOT' ;
    
	sub main::_prompt {
	    prompt(@_);
	}
EOT
    }
}

sub asrc {
    my $d = shift;
    my $file = shift || "httpd.h";
    return $d if -e "$d/$file";
    return "$d/include" if -e "$d/include/$file";
    return "$d/main" if -e "$d/main/$file";
    return undef;
}

sub conf_append {
    local *CFG;
    open CFG, ">>t/conf/httpd.conf" or die "open httpd.conf $!";
    print CFG join "\n", @_, "";
    close CFG;
}

sub edit_extra_cflags {
    my($cfg) = @_;
    my $fh = IO::File->new($cfg) or die "open $cfg $!";
    my $repl = "";
    my @file = ();
    my $ccopts = ccopts();
    my $dssv = "-DSERVER_SUBVERSION";
    my $ssv = qq($dssv=\\"mod_perl/$VERSION\\" );

    my $inc = " $ccopts -I. -I../.. -DUSE_PERL_SSI" if $PERL_SSI;
    $inc .= " -DAPACHE_SSL" if is_ssl() and $PERL_SSI;
    $inc .= $SSL_INCLUDE if $SSL_INCLUDE;
    $inc .= " -DSTRONGHOLD" if is_ssl() =~ /stronghold/i;
    $inc .= " $PERL_EXTRA_CFLAGS" if $PERL_EXTRA_CFLAGS;
    $inc .= " -DMOD_PERL";

    while (<$fh>) {
	push @file, $_;
	next unless /EXTRA_CFLAGS\s*=/;
	next if /mod_perl/; 
	next if /^#/;
	chomp;

	$repl = $_;
	    
	my $backwhack = "";
	if($repl =~ s/(\\)\s*$//) {
	    $backwhack = $1;
	}

	if($ADD_VERSION) {
	    if(/$dssv=/) {
		$repl =~ 
		    s{
			$dssv\s*=\s*(.?)['"](.*?)(.?)["']
		     }[
		        qq($dssv="$1"$2 mod_perl/$VERSION$3"")
		      ]ex;
	    } 
	    else {
		$repl .= " $ssv";
	    }
	}

	$file[-1] = "$repl $inc $backwhack\n";

    }
    close $fh;

    if($repl) {
	$fh = IO::File->new(">$cfg") or die "open $cfg $!";
	print $fh @file;
	close $fh;
    }
}

sub conf_fixup {
    my($mf, $cfg) = @_;
    my $mmn    = magic_number($APACHE_SRC);
    #source re-org
    my $sro = 1 if $mmn >= 19970825;

    edit_extra_cflags($cfg);

    my $ldopts = "`$^X $PWD/src/modules/perl/ldopts $PERL_STATIC_EXTS $libperl`";
    iedit $cfg,
    q{next unless /EXTRA_LIBS\s*=/;}.
    q{next if /perl/; chomp;}.
    qq{\$_ .= q| $ldopts\n|;};

    for (split ",", $ADD_MODULE) {
	add_module($cfg,$_);
    }

    if(is_ssl() =~ /stronghold/i) {
	if($do_link_swap) {
	    warn "swapping link order in $mf for Stronghold\n";
	    my $repl = quotemeta('$(REGLIB) $(LIBS)');
	    iedit $mf, "s:\Q\$(LIBS) \$(REGLIB)\E:$repl:;";

            #XXX hack
            $repl = quotemeta('CFLAGS=$(CFLAGS)');
            iedit $mf, qq(s:\Q\"CFLAGS=\$(CFLAGS)"\E:'$repl':;);
	}
	my $repl = q{AUX_CFLAGS='\$(CFLAGS)'};
	iedit $mf, qq{s/AUX_CFLAGS="..CFLAGS."/$repl/};
    }
    {
	my $repl = q{CC='\$(CC)'};
	iedit $mf, qq{s/CC=..CC. /$repl /};
    }
    open(CONF, $cfg) || die "Can't open $cfg: $!";
    while (<CONF>) {
	$seen_modperl++ if 
	    /^Module\s+perl_module/i || 
		/^AddModule\s+.*libperl/;
    }
    close(CONF);
    unless ($seen_modperl) {
	print "Appending mod_perl to $conf\n";
	open(CONF, ">>$cfg") || die "Can't open $cfg: $!";
	my $line;
	$line = $sro ? "AddModule modules/perl/libperl.a" :
	               "Module perl_module         modules/perl/libperl.a";
	print CONF <<EOT;
		
# Embed a perl interpreter
$line


EOT
    close(CONF);
    } else {
	print "mod_perl already present in $conf\n";
    }
}


sub has_module {
    my($cfg, $name) = @_;
    local(*IN);
    open IN, $cfg or die "Can't open $cfg $!\n";
    while(<IN>) {
	if(/^\\w{0,3}Module\\s+.*$name\.[oa]/i) {
 	    close IN;
#	    print STDERR "has module $name\n";
	    return 1;
	}
    }
    return 0;
}
 
sub add_module {
    my($cfg, $name) = @_;
    iedit $cfg, "s/^#\\s+(\\w{0,3}Module\\s+.*$name\.[oa])/\$1/";
}

sub gen_script {
    my $file = shift;
    local(*IN,*OUT);
    open IN, "$file.PL" or die "Couldn't open $file.PL: $!";
    open OUT, ">$file" or die "Couldn't open $file: $!";
    print OUT "#!$Config{perlpath}\n", join '', <IN>;
    close OUT;
    close IN;
    chmod 0755, "$file";    
}

sub iedit {
    my $file = shift;
    return if $Is_Win32;

    #print STDERR "-e @_\n";
    system $^X, "-pi~", "-e", "@_", $file;
}

sub win32_setup {
    my $d = "src/modules/perl";
    dirent_kludge($d);
    cp "Apache/typemap", $d;
    chdir $d;
    system "$^X -MExtUtils::Embed -e xsinit -- -std Apache Apache::Constants $PERL_STATIC_EXTS";
    my $lib = $Config{privlibexp};
    for (qw(Constants Apache)) {    
        system "$^X $lib/ExtUtils/xsubpp -typemap $lib/ExtUtils/typemap $_.xs > $_.c";

    }
    chdir "../../../";
}

sub dirent_kludge {
    my $d = shift;
    local *FH;
    open FH, ">$d/dirent.h" or die "can't write $d/dirent.h $!";
    print FH <<EOF;
/* major kludge to workaround confilct(s) between perl's dirent.h apache's readdir.h */

#ifdef WIN32

#define _INC_DIRENT
#define DIR void

#endif

EOF
    close FH;
}

sub write_my_config {
    my $src = shift;
    local *FH;
# writing Configuration to Apache::MyConfig

    open FH, '>lib/Apache/MyConfig.pm'  ||
	die "Can't open lib/Apache/MyConfig.pm: $!";
    print FH <<EOT;
#
# Configuartion for mod_perl and Apache::...
#
package Apache::MyConfig ;

%Setup = (
   'Apache_Src' => \'$APACHE_SRC\'
);

1;

__END__
EOT
    close FH;

}

#in version 1.2505 of Embed.pm we could just import these instead of using ``,
#but it might require lots of people to upgrade

sub ccopts {
    unless ($Embed::ccopts) {
	$Embed::ccopts = `$^X -MExtUtils::Embed -e ccopts`;

	if($Config{usethreads} eq "define") {
	    $Embed::ccopts .= " -DPERL_THREADS";
	}
    }
    $Embed::ccopts;
}

sub ldopts {
    $Embed::ldopts ||= `$^X -MExtUtils::Embed -e ldopts`;
    if($^O eq "aix") {
	$Embed::ldopts =~ s,(-bE:)(perl\.exp),$1$Config{archlibexp}/$2,;
    }
    $Embed::ldopts;
}

                                    
