: # use perl                                  -*- mode: Perl; -*-
        eval 'exec perl -S $0 "$@"'
			if $runnning_under_some_shell;
#
# Configure the gemsvnc server build
#

use strict;
use Cwd;
use FileHandle;
use File::Path;
use File::Copy;
use File::Basename;
use Env qw(PATH ROOTDIR);

# build root
my $ROOT = cwd();
$ROOT =~ s@^/cygdrive/([a-zA-Z])@$1:@; # fix cygwin mounted directories

# other globals
my $ARCH;
my $errors = 0;
my $warnings = 0;
my $config;
my @metrics;

my $pathsep = ':';
$pathsep = ';' if ($^O =~ /(Win32|cygwin)/);

sub usage
{
print <<__EOF
usage: configure [options]
options:
CONFIGURATION PARAMETERS
    --debug
	Compile with debug.
__EOF
}

sub warning
{
    print("WARNING: @_\n");
    $warnings++;
}

sub error
{
    print("ERROR: @_\n");
    $errors++;
}

sub option
{
    my ($key) = @_;
    return $config->{$key};
}

sub default_config
{
    my ($key, $value) = @_;
    $config->{$key} = $value;
}

sub find_dos_package
{
    my ($rpath) = @_;
    my @drives = ('c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
		  'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
		  's', 't', 'u', 'v', 'w', 'x', 'y', 'z');

    for (@drives)
    {
	my $p = sprintf("%s:%s", $_, $rpath);
	return $p if ( -r $p );
    }

    return '';
}

sub find_directory_containing
{
    my ($searchfile, @paths) = @_;

    for (@paths)
    {
	if (-r "$_/$searchfile")
	{
	    s/\\/\//g; # fix dos backslashes
	    return $_;
	}
    }

    return "";
}

sub find_user_path_containing
{
    my ($element) = @_;
    my $ps = $pathsep;
    $ps = ":" if ($^O =~ /cygwin/);
    my @paths = split /$ps/, $PATH;
    return find_directory_containing($element, @paths);
}

sub find_exe
{
    my ($element) = @_;
    my $r = find_user_path_containing $element;
    unless (-d $r)
    {
	if ($ARCH eq "nt40") 
	{
	    $element .= ".exe";
	    $r = find_user_path_containing $element;
	}
    }

    return "$r/$element" if -r "$r/$element";

    warning "could not locate executable $element";
    return $element;
}

sub find_java_method
{
    my ($base, $clazz, $method) = @_;
    my $gotit = 0;
    open FN, "$base/bin/javap $clazz | 2>&1" or return $gotit;
    while(<FN>)
    {
	$gotit = 1 if /$method/;
    }
    close FN;
    return $gotit;
}

sub fileContains
{
    my ($fn,$pattern) = @_;
    my $result = 0;
    if (-r $fn)
    {
	open FN, $fn;
	while(<FN>)
	{
	    $result = 1 if /$pattern/;
	}
	close FN;
    }
    return $result;
}

sub getarch
{
    my ($major, $minor) = split /[\.\-_\s]/, `uname -r`;

    # collapse the releases into known major versions
    $_ = `uname -s`;
    chomp();
    tr /[A-Z]/[a-z]/;
    if (/sunos/) 
    {
	$_ = "sun";
    }
    elsif (/irix/)
    {
	$_ = "irix" if /irix64/;
	$minor = "" if ( $minor < 5 ); # make irix62, 63, and 64 --> irix6
    }
    elsif (/freebsd/)
    {
	$minor = "";
	$_ = "fbsd";
    }
    elsif (/cygwin/)
    {
	$_ = "nt";
	$major = "4";
	$minor = "0";
    }
    elsif (/windows/)
    {
	$_ = "nt";
	$major = "4";
	$minor = "0";
    }

    return "$_$major$minor";
}

sub y2kdate
{
    my ($sec, $min, $hour, $mday, $mon, $year, $wday,
	$yday, $isdst) = localtime;
    return sprintf("%4d%02d%02d", $year + 1900, $mon + 1, $mday);
}

sub y2ktimedate
{
    my ($sec, $min, $hour, $mday, $mon, $year, $wday,
	$yday, $isdst) = localtime;
    return sprintf("%4d%02d%02d-%02d%02d",
	$year + 1900, $mon + 1, $mday, $hour, $min);
}

sub mylink
{
    my ($src, $dst) = @_;
    if ($^O =~ /Win32/ or $ARCH =~ "^nt")
    {
	copy($src, $dst);
	chmod(0777, $dst);
    }
    else
    {
	unlink($dst);
	symlink($src, $dst) || die "cannot make symlink from $src to $dst";
    }
}

sub describe_machine
{
    my $r = "Machine configuration:\n";

    $r .= `uname -a`;

    return $r;
}

sub create_system_mk
{
    my $mf = "system.mk";
    open MAKE, "> $mf" or die "cannot open $mf";

    print MAKE "
	# this file was automatically generated, DO NOT EDIT

	# configuration options
";
    foreach (sort keys %$config)
    {
	printf MAKE "\t%s = %s\n", $_, option($_);
    }

    close MAKE;
}

sub set_os_defaults
{
    #############################################
    ##                                         ## 
    ##   Compile options and package tweaks    ## 
    ##                                         ## 
    #############################################

    # default values
    my $CC = "CC";
    my $CXX = "CC";
    my $BASE_CFLAGS="";
    my $DEBUG_CFLAGS="-g";
    my $OPTIMIZE_CFLAGS="-O";

    my $SHLIB_PREFIX = "lib";
    my $SHLIB_SUFFIX = ".so";
    my $OBJ_SUFFIX = ".o";
    my $EXE_SUFFIX = "";

    my $LD = "ld";
    my $EXE_LDFLAGS="";
    my $SHLIB_LDFLAGS="";

    my $PTHREAD_CFLAGS = "";
    my $PTHREAD_LIBS = "";

    my $SOCKET_CFLAGS = "";
    my $SOCKET_LIBS = "";

    if ($ARCH =~ /^irix/)
    {
	$CC="/bin/cc -n32 -mips3";
	$CXX="/bin/CC -n32 -mips3";
	$LD="/bin/CC -n32 -mips3";

	printf "C++ Compiler: %s", `$CC -version 2>&1`;

	# suppress some (deemed to be harmless) remarks
	my $woff = "-woff 1375,3180";

	if ($ARCH =~ /^irix65/)
	{
	    $woff .= ",3201";
	}

	$DEBUG_CFLAGS="-g -fullwarn $woff";
	$OPTIMIZE_CFLAGS="-O3 -fullwarn $woff";
	$SHLIB_LDFLAGS .= " -shared";
	$PTHREAD_CFLAGS = "-DHAVE_PTHREADS";
	$PTHREAD_LIBS="-lpthread";
    }
    elsif ($ARCH =~ /^linux/)
    {
	$CC="gcc";
	$CXX="g++";
	$LD="g++";

	my $gccver = (reverse split /\n/, `gcc -v 2>&1`)[0];
	my $gccopt = "-mcpu=i686";
	if ($gccver =~ /version 2\.7/)
	{
	    $gccopt = "";
	}
	printf "C++ Compiler: %s\n", $gccver;

	$BASE_CFLAGS .= " $gccopt -fPIC";
	$DEBUG_CFLAGS="-g -Wall";
	$OPTIMIZE_CFLAGS="-O3 -Wall";
	$SHLIB_LDFLAGS .= " -shared -ldl";
	$PTHREAD_CFLAGS = "-DHAVE_PTHREADS";
	$PTHREAD_LIBS="-lpthread";
    }
    elsif ($ARCH =~ /^(net|f)bsd/)
    {
	$CC="gcc";
	$CXX="g++";
	$LD="g++";

	$PTHREAD_CFLAGS = "-DHAVE_PTHREADS -pthread";
	$PTHREAD_LIBS = "-pthread";

	my $gccver = (reverse split /\n/, `gcc -v 2>&1`)[0];
	my $gccopt = "-mcpu=i686";
	if ($gccver =~ /version 2\.7/)
	{
	    $gccopt = "";
	}
	printf "C++ Compiler: %s\n", $gccver;

	$BASE_CFLAGS .= " $gccopt";
	$DEBUG_CFLAGS="-g -Wall";
	$OPTIMIZE_CFLAGS="-O3 -Wall";
	$SHLIB_LDFLAGS .= " -shared";
    }
    elsif ($ARCH =~ /^sun\d\d/)
    {
	$CC = find_exe "cc";
	$CXX = find_exe "CC";

	if ($CXX =~ /SUNWspro/)
	{
	    $CXX .= " -mt -instances=static";
	}
	$LD = $CXX;

	printf "C++ Compiler: %s", `$CC -V 2>&1`;

	$BASE_CFLAGS .= " -KPIC";
	$SHLIB_LDFLAGS .= " -G"; # -h SHLIB_NAME ?

	if ($ARCH =~ /sun57/)
	{
	    # real time library has some critical functions for us
	    $LD .= " -lrt";
	    $CXX .= " -lrt";
	    $SOCKET_LIBS = "-lsocket -lposix4 -lresolv -lnsl";
	}

	if ($ARCH =~ /sun58/)
	{
	    # sockets are squirrelled away
	    $SOCKET_LIBS = "-lsocket -lposix4 -lresolv -lnsl";
	}
    }
    elsif ($ARCH =~ /^nt/)
    {
	$CC="perl $ROOT/ntCC";
	$CXX="perl $ROOT/ntCC -tp";
	$LD="perl $ROOT/ntCC";
	$SHLIB_LDFLAGS .= " -dll";
	$SHLIB_PREFIX="";
	$SHLIB_SUFFIX=".dll";
	$OBJ_SUFFIX=".obj";
	$EXE_SUFFIX=".exe";
	$BASE_CFLAGS .= " -DTERRADLL";
	$SOCKET_LIBS = "-lws2_32";

	# check for MKS
	if ( -d "$ROOTDIR/include/X11" && option("mks") eq "yes" )
	{
	    my $extra = " -fi $ROOTDIR/include/nutc.h -I$ROOTDIR/include -L$ROOTDIR/lib";
	    $CC .= $extra;
	    $CXX .= $extra;
	    print "Using MKS toolkit found at $ROOTDIR\n";
	}
    }

    unless (option("debug") eq "yes")
    {
	$BASE_CFLAGS .= " $OPTIMIZE_CFLAGS";
	$CC .= " $OPTIMIZE_CFLAGS";
	$CXX .= " $OPTIMIZE_CFLAGS";
    }
    else
    {
	$BASE_CFLAGS .= " $DEBUG_CFLAGS";
	$CC .= " $DEBUG_CFLAGS";
	$CXX .= " $DEBUG_CFLAGS";
    }

    default_config "PATHSEP", $pathsep;

    default_config "CC", $CC;
    default_config "CXX", $CXX;
    default_config "CFLAGS", $BASE_CFLAGS;
    default_config "CXXFLAGS", $BASE_CFLAGS;

    default_config "SHLIB_PREFIX", $SHLIB_PREFIX;
    default_config "SHLIB_SUFFIX", $SHLIB_SUFFIX;
    default_config "OBJ_SUFFIX", $OBJ_SUFFIX;
    default_config "EXE_SUFFIX", $EXE_SUFFIX;

    default_config "LD", $LD;
    default_config "EXE_LDFLAGS", $EXE_LDFLAGS;
    default_config "SHLIB_LDFLAGS", $SHLIB_LDFLAGS;

    default_config "PTHREAD_CFLAGS", $PTHREAD_CFLAGS;
    default_config "PTHREAD_LIBS", $PTHREAD_LIBS;

    default_config "SOCKET_CFLAGS", $SOCKET_CFLAGS;
    default_config "SOCKET_LIBS", $SOCKET_LIBS;
}

sub set_x11_defaults
{
    ######################
    ##			##
    ##	X11/Motif       ##
    ##			##
    ######################

    my @paths = (
	'/usr',
	'/usr/X11',
	'/usr/X11R6',
	'/usr/openwin',
	'/usr/openwin/share',
	'/opt/graphics/OpenGL',
	'/usr/local/LessTif/Motif2.1',
	'/usr/local/LessTif/Motif2.0',
	'/usr/X11R6/LessTif/Motif1.2/',
	'/usr/X11R6/LessTif/Motif2.1/'
	);

    if ($^O =~ /Win32/)
    {
	# check for MKS
	if ( -d "$ROOTDIR/include/X11" && option("mks") eq "yes" )
	{
	    @paths = ( $ROOTDIR, @paths );
	}
    }

    my $x11 = find_directory_containing('include/X11/Xlib.h', @paths);

    if ( -d $x11 )
    {
	my $X11_CFLAGS = "";
	my $X11_LIBS = "";
	unless ($x11 eq "/usr")
	{
	    $X11_CFLAGS = "-I$x11/include";
	    $X11_LIBS = "-L$x11/lib $X11_LIBS";
	}
	else
	{
	    if ( -d "/usr/X11R6/lib" )
	    {
		$X11_LIBS = "-L/usr/X11R6/lib $X11_LIBS";
	    }
	}

	default_config "X11_CFLAGS", $X11_CFLAGS;
	default_config "X11_LIBS", $X11_LIBS;

	print "X11: $x11\n" 
	    if (option("X11_CFLAGS") eq $X11_CFLAGS);
    }

    my $motif = find_directory_containing('include/Xm/DrawingA.h', @paths);
    if ( -d $motif )
    {
	my $MOTIF_CFLAGS = "";
	my $MOTIF_LIBS = "-lXm";
	unless ($motif eq "/usr")
	{
	    $MOTIF_CFLAGS = "-I$motif/include";
	    $MOTIF_LIBS = "-L$motif/lib $MOTIF_LIBS";
	}

	default_config "MOTIF_CFLAGS", $MOTIF_CFLAGS;
	default_config "MOTIF_LIBS", $MOTIF_LIBS;

	print "Motif: $motif\n" 
	    if (option("MOTIF_CFLAGS") eq $MOTIF_CFLAGS);
    }
}

sub set_jpeg_defaults
{
    ######################
    ##			##
    ##	JPEG            ##
    ##			##
    ######################

    my @paths = (
	'/usr/local',
	'/usr/X11',
	'/usr/X11R6',
	);

    my $jpeg = find_directory_containing('include/jpeglib.h', @paths);

    my ($JPEG_CFLAGS, $JPEG_LIBS) = ("", "-ljpeg");

    if ( -d $jpeg )
    {
	$JPEG_CFLAGS = "-I$jpeg/include";
	$JPEG_LIBS = "-L$jpeg/lib -ljpeg";
    }

    default_config "JPEG_CFLAGS", $JPEG_CFLAGS;
    default_config "JPEG_LIBS", $JPEG_LIBS;
}

sub set_java_defaults
{
    ######################
    ##			##
    ##	Java		##
    ##			##
    ######################

    my $JDK_BASE = $config->{"JDK_BASE"} ;
    my $JDK_BIN = "$JDK_BASE/bin";

    my $JDK_INCLUDE="";
    my $JDK_LIBS="";
    my $JDK_TRAILING_LIBS="";
    my $JDK_SWING_FEATURE="yes";
    my $JAVA_HEAP_OPTION="-J-Xmx180m";
    my $JAVA_TOOL_FLAGS="";
    my $OPT_JAVA="";
    my $jawt_libs = "-ljawt -lawt";

    # JDK install is not yet a common standard location.
    # Probe user environment first.
    unless ( -r "$JDK_BIN/javac" || -r "$JDK_BIN/javac.exe" )
    {
        $JDK_BIN = find_exe "javac";
        $JDK_BIN =~ s/\/[^\/]+$//;

        $JDK_BASE = $JDK_BIN;
        $JDK_BASE =~ s/\/bin$//;
    }

    default_config "JDK_BASE", $JDK_BASE;
    $JDK_BASE = option "JDK_BASE";

    return unless -d $JDK_BASE; # can't find it

    # Does this JDK implement Swing?
    if (!find_java_method($JDK_BASE, "javax.swing.JFrame", "getContentPane()"))
    {
	$JDK_SWING_FEATURE="no";
	$JAVA_HEAP_OPTION="-J-mx180m";
    }

    # some defaults
    if ($JDK_BASE eq "/usr")
    {
	$JDK_INCLUDE="";
    }
    else
    {
	$JDK_INCLUDE="-I$JDK_BASE/include";
    }
    $JDK_BIN="$JDK_BASE/bin";
    $OPT_JAVA="java";
    if ($ARCH =~ /^irix/)
    {
	$JDK_INCLUDE.=" -I$JDK_BASE/include/irix";
	$JDK_LIBS="-L$JDK_BASE/lib32/sgi $jawt_libs";
    }
    elsif ($ARCH =~ /^sun5/)
    {
	$JDK_INCLUDE.=" -I$JDK_BASE/include/solaris";
	$JDK_TRAILING_LIBS="-lC";
	# check for multiple libC -- take latest
	my @libs = glob("/usr/lib/libC.so.*");
	if (@libs > 1) 
	{
	    $JDK_TRAILING_LIBS=@libs[@libs - 1];
	    warning "Found multiple C++ runtimes, linking $JDK_TRAILING_LIBS for JDK C++ binding";
	}

	# sigh... have to test JDK version
	if (-r "$JDK_BASE/jre/lib/sparc")
	{
	    # this is for jdk1.2, the best choice
	    $JDK_LIBS="-L$JDK_BASE/jre/lib/sparc $jawt_libs";
	}
	elsif (-r "$JDK_BASE/lib/sparc/native_threads")
	{
	    # this is for jdk1.1 native threads
	    $JDK_LIBS="-L$JDK_BASE/lib/sparc/native_threads $jawt_libs";
	}
	elsif (-r "$JDK_BASE/lib/sparc/green_threads")
	{
	    # this is for jdk1.1 green threads (not recommended)
	    warning("no Java native thread support installed, linking to green threads JDK");
	    $JDK_LIBS="-L$JDK_BASE/lib/sparc/green_threads $jawt_libs";
	}
	else
	{
	    warning("unknown JDK version, will not link");
	    $JDK_LIBS=""
	}
    }
    elsif ($ARCH =~ /^fbsd/)
    {
	# are we trying to use kaffe?  linux emulation?
	my $ver = `$JDK_BIN/java -version 2>&1`;
	if ($ver =~ /[Kk]affe/)
	{
	    $JDK_INCLUDE .= " -I/usr/include/kaffe";
	}
	elsif (-d "$JDK_BASE/include/linux")
	{
	    $JDK_INCLUDE .= " -I$JDK_BASE/include/linux";
	}
	else
	{
	    $JDK_INCLUDE .= " -I$JDK_BASE/include/freebsd";
	}
	$JDK_LIBS="-L$JDK_BASE/jre/lib/i386 -Wl,-rpath,$JDK_BASE/jre/lib/i386 -L$JDK_BASE/jre/lib/i386/client -Wl,-rpath,$JDK_BASE/jre/lib/i386 $jawt_libs";

	# fix hanging javac/javap by using classic VM
	$JAVA_TOOL_FLAGS = "-classic";
    }
    elsif ($ARCH =~ /^netbsd/)
    {
	$JDK_INCLUDE .= " -I$JDK_BASE/include/netbsd";
    }
    elsif ($ARCH =~ /^linux/)
    {
	# are we trying to use kaffe?
	my $ver = `$JDK_BIN/java -version 2>&1`;
	if ($ver =~ /[Kk]affe/)
	{
	    $JDK_INCLUDE .= " -I/usr/include/kaffe";
	}
	else
	{
	    $JDK_INCLUDE .= " -I$JDK_BASE/include/linux";
	    $JDK_LIBS="-L$JDK_BASE/jre/lib/i386 -Wl,-rpath,$JDK_BASE/jre/lib/i386 -L$JDK_BASE/jre/lib/i386/client -Wl,-rpath,$JDK_BASE/jre/lib/i386 $jawt_libs";
	}
    }
    elsif ($ARCH =~ /^nt/)
    {
	$jawt_libs = "-ljawt";
	$JDK_INCLUDE .= " -I$JDK_BASE/include/win32";
	$JDK_LIBS="-L$JDK_BASE/jre/lib -L$JDK_BASE/jre/bin $jawt_libs";
    }
    else
    {
	# oops, we must punt
	warning("unknown JDK architecture");
    }

    printf("Java JDK in \"%s\"", $JDK_BASE);
    if ($JDK_SWING_FEATURE eq "yes")
    {
	printf(" (with Swing)");
    }
    printf(" version:\n");
    if (open JAVA, "$JDK_BASE/bin/java -version 2>&1 |")
    {
	while (<JAVA>)
	{
	    print "    $_";
	}
	close JAVA;
    }
    else
    {
	print "    <unknown version>\n";
    }

    # now make sure we didn't request /usr/include as a separate path
    $JDK_INCLUDE =~ s/-I\/usr\/include\S*//g;

    default_config "JDK_BIN", "$JDK_BASE/bin";
    default_config "JAVA", "\$(JDK_BIN)/java";
    default_config "JAVAC", "\$(JDK_BIN)/javac \$(JAVA_TOOL_FLAGS)";
    default_config "JAVAH", "\$(JDK_BIN)/javah \$(JAVA_TOOL_FLAGS)";
    default_config "JAVADOC", "\$(JDK_BIN)/javadoc \$(JAVA_HEAP_OPTION) \$(JAVA_TOOL_FLAGS)";
    default_config "JAR", "\$(JDK_BIN)/jar \$(JAVA_TOOL_FLAGS)";
    default_config "JDK_SWING_FEATURE", $JDK_SWING_FEATURE;
    default_config "JDK_INCLUDE", $JDK_INCLUDE;
    default_config "JDK_LIBS", $JDK_LIBS;
    default_config "JDK_TRAILING_LIBS", $JDK_TRAILING_LIBS;
}

######################################################################
######################################################################

# turn off protection
umask 0;

# Gather default settings
{
    # First principles
    default_config "ARCH", getarch();
    $ARCH = option("ARCH");
    print "$ARCH architecture\n";

    # read command line
    foreach (@ARGV)
    {
	if (/^--(\S+)=(.+)$/)
	{
	    default_config $1, $2;
	}
    }

    # need help?
    # The rest
    my $debug_suffix = "";
    $debug_suffix = "d" if (option("debug") eq "yes");

    # Properties of the host operating system
    set_os_defaults();

    # makedepend
    {
	my $md = find_exe("makedepend");
	if ($ARCH =~ "nt4")
	{
	    $md .= " -DWIN32 -D_WIN32 -o.obj";
	}
	default_config "MAKEDEPEND", $md;

	$md = "";
	my @md_cflags = split /\s/, option("CFLAGS");
	foreach (@md_cflags)
	{
	    $md .= " $_" if /^-[DI]/;
	}
	default_config "MAKEDEPEND_CFLAGS", $md;
    }

    # X11
    set_x11_defaults();

    # JPEG
    set_jpeg_defaults();

    # Java
    set_java_defaults();
}

foreach (@ARGV)
{
    # need help?
    if (/^(-h|--help)/)
    {
	usage();
	exit 0;
    }

    # only options allowed are POSIX double dash
    unless (/^--/)
    {
	usage();
	exit 1;
    }
}

create_system_mk();
