#!/usr/bin/perl -w
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Tinderbox build tool.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#

# complete rewrite by Ken Estes for contact info see the
#     mozilla/webtools/tinderbox2/Contact file.
# Contributor(s): Stephen Lamm (slamm@yahoo-inc.com)
#                 Mike Taylor (bear@code-bear.com)

use Cwd;
use Getopt::Long;
use File::Basename;
use File::Find;

# Users can set these variables or accept the defaults.  These
# variables can either be set in configure (like in gnu configure) or
# overridden in the makefile.

sub usage {
    my $usage=<<EOF;
usage: $0 [options]
    Common options:
        --prefix=[path]         Where to install most files
	    			(default: '$prefix')
        --cgibin-prefix=[path]  Where to install cgi scripts
	    			(default: '$cgibin_prefix')
        --html-prefix=[path]    Where to install html files
	    			(default: '$html_prefix')
    Other options:
        --help | -h             This usage text
	--perl=[path]           Full path to perl executable (on target 
			        machine if different from perl on build 
				machine).
	    			(default: '$perl_cmd')
	--perl-flags=[flags]    How to run the scripts
	    			(default: '$perl_flags')
	--build-dir=[path]      Directory to construct the binaries
	    			(default: '$builddir')
				
	--config-script=[name]  File to get the configuration options
	    			(default: '$config_script')

EOF

  print STDERR $usage;
  exit 0;
}

# set default variables

$help = 0;
$prefix = '/home/tinderbox2';
$cgibin_prefix = '/var/www/cgi-bin/tinderbox';
$html_prefix = '/home/httpd/html/tinderbox';
# null string means use 'which' to find default
$perl_cmd = ''; 
$perl_flags = '-T';
$builddir = './build';
$config_script = './config.out';
$tinder_version = '0.09';

@replacements = qw( 
		    prefix cgibin_prefix html_prefix 
		    builddir config_script
		    xargs_single CONFIGURE_ARGS
		    );

@cmds = (

	 # commands tinderbox uses
	 'perl',

	 # these commands are used by the Makefile not by tinderbox

	 'find',
	 'egrep',
	 'xargs',
	 'rm',
	 'echo',
	 'mkdir',
	 'chmod',

	 );

# xargs takes one of these arguments
# this is very OS specific

@XARGS_SINGLE_ARGS = ('-l1', '-L1', '-n1');


@ORIG_ARGS = @ARGV;
$PROGRAM = $0;


if ( ($ARGV[0]) && ($ARGV[0] !~ m/^-/) ) {
    die("Command line arguments must begin with a '-'\n");
}

$CONFIGURE_ARGS= (
	    "# Configure was run like this:\n\n".
	     "# \t".
	     $PROGRAM.
	     "\t\'".
	     join ("\' \\\n\#\t\'", @ORIG_ARGS).
	     "\'".
	    "");

Getopt::Long::config('require_order', 'auto_abbrev', 'ignore_case');

GetOptions(
	   'help|h' => \$help,
	   'prefix=s' => \$prefix,
	   'cgibin-prefix=s' => \$cgibin_prefix,
	   'html-prefix=s' => \$html_prefix,
	   'perl=s' => \$perl_cmd,
	   'perl-flags=s' => \$perl_flags,
	   'build-dir=s' => \$builddir,
	   'config-script=s' => \$config_script,
	   ) or usage();

usage() if $help;


for my $cmd (@cmds) {

  my $variable = $cmd.'_cmd';

  my $explicit_cmd = $$variable;

  if ($explicit_cmd) {
    # Use explicitly set command path if defined
    $full_cmd = $explicit_cmd;
  } else {

    # Search for command in the $PATH and assume that this is in the
    # same place on the machine where the files are installed.

    $full_cmd=`which $cmd 2> /dev/null`;
    chomp($full_cmd);

    if ($? != 0) {
      print STDERR "Could not find program: $cmd\n";
      exit 9;
  }
  }

  $CMD{$cmd} = $full_cmd;
}

my $arg;
foreach $arg (@XARGS_SINGLE_ARGS) {
    my $output = `$CMD{'echo'} /bin/true |   $CMD{'xargs'} 2>/dev/null $arg $CMD{'echo'}`;
    if ($output eq "/bin/true\n") {
	$xargs_single=$arg;
	last;
    }
}

# Build Makefile
#------------------------------------------------------------
# Build a makefile to copy our executables into place and perform
# subsitutions on them.


print STDERR "Building Makefile\n";

open(MAKEFILE_IN, "<Makefile.in") or 
    die "Unable to open Makefile.in: $!\n";

open(MAKEFILE, ">Makefile") or 
    die "Unable to open Makefile: $!\n";


while (<MAKEFILE_IN>) {

    # perform substitutions

    if (/@\S*@/) {
	for my $replace (@replacements) {
	    s/\@$replace\@/eval "\$$replace"/ge;
	}
    }
    
    print MAKEFILE $_;
}

close(MAKEFILE_IN) or
    die "Unable to close Makefile: $!\n";

# Add Makefile build/install rules
#------------------------------------------------------------

# Get the list of source files
my @source_files = ();
my %install_dirs=();
my %build_dirs=();
my @build_files=();
my @install_files=();

sub wanted_source_files {
  $File::Find::prune = 1, return if $_ eq 'CVS';
  return unless -T $_;
  return if /^\#/ or /~$/ or /^\./;
  push @source_files, $File::Find::name;
}

find(\&wanted_source_files, 'src');

for my $src_file (@source_files) {
  my $build_file = $src_file;
  my $install_file = $src_file;

  $build_file =~ s/^src/\$(builddir)/;

  if ($build_file =~ m/\.cgi$/) {
    $install_file = '$(cgibin_prefix)/'.basename($install_file);
  } else {
    $install_file =~ s/^src/\$(prefix)/;
  }

  push @build_files, $build_file;
  push @install_files, $install_file;
  $install_dirs{File::Basename::dirname($install_file)} = 1;
  $build_dirs{File::Basename::dirname($build_file)} = 1;

  $deps=<<EOF2;

build_files: $build_file
install_files: $install_file

$build_file: $src_file Makefile config.out
	\@\$(STAGE_FILE) \$\< \$\@

$install_file: $build_file
	\@\$(INSTALL_FILE) \$\< \$\@

EOF2

  print MAKEFILE $deps;
}

foreach $build_file (@build_files) {
    print MAKEFILE "build_files: $build_file\n";
}

foreach $install_file (@install_files) {
    print MAKEFILE "install_files: $install_file\n";
}

my @install_dirs = sort keys %install_dirs;
my @build_dirs = sort keys %build_dirs;

print MAKEFILE <<EOF3;


make_build_dirs: @build_dirs

make_install_dirs: @install_dirs

@build_dirs:
	mkdir -p \$\@

@install_dirs:
	mkdir -p \$\@

EOF3

# Build config.out
#------------------------------------------------------------

print STDERR "Building config.out\n";

# this file will exist only if we have run this script before.

unlink($config_script);

my $pwd = cwd;

open(CONFIG_SCRIPT, ">$config_script")
    or die "Unable to open $config_script: $!\n";


print CONFIG_SCRIPT <<EOF4;
#!perl - this script is run from makefile with -n

# This script is automatically generated by configure.
# This script configures various global variables.


$CONFIGURE_ARGS


while (<>) {
  # Set the library search path with suitable interposing directories.

  s!\#tinder_libdir\#!$prefix/local_conf',
   '$prefix/default_conf',
   '$prefix/lib',
   '$pwd/$builddir/local_conf',
   '$pwd/$builddir/default_conf',
   '$pwd/$builddir/lib!;

  s!\#prefix\#!$prefix!;
  s!\#cgibin_prefix\#!$cgibin_prefix!;
  s!\#html_prefix\#!$html_prefix!;

  # Use Taint Perl mode for security.
  s!\#perlflags\#!$perl_flags!;
  s!\#tinder_version\#!$tinder_version!;

EOF4
    ;


{
    print CONFIG_SCRIPT "  # Hard code various executable paths into ";
     print CONFIG_SCRIPT	"the source for security reasons.\n";
	foreach $cmd (sort keys %CMD) {
	    my $full_cmd = $CMD{$cmd};
	    print CONFIG_SCRIPT "  s!\#$cmd\#!$full_cmd!;\n";
	}
	print CONFIG_SCRIPT "\n";
	print CONFIG_SCRIPT "  s!\#xargs_single\#!$xargs_single!;\n";
}


print CONFIG_SCRIPT <<EOF5;

} continue {
  print or die "-p destination: $!\n";
}
EOF5


chmod 0755, $config_script or 
    die "Could not 'chmod 0755, $config_script': $!\n";

exit 0;


