#!/usr/bin/perl -w

require 5.000;

use strict;
use English;
use File::Basename;
use Cwd 'abs_path';
use Fcntl;
#use File::Temp "tempfile";   Not available before Perl 5.6.1
    

my ($TRUE, $FALSE) = (1,0);

# This program generates Makefile.config, which is included by all of the
# Netpbm makefiles.  You run this program as the first step in building 
# Netpbm.  (The second step is 'make').

# This program is only a convenience.  It is supported to create 
# Makefile.config any way you want.  In fact, an easy way is to copy
# Makefile.config.in and follow the instructions in the comments therein
# to uncomment certain lines and make other changes.

# Note that if you invoke 'make' without having first run 'configure',
# the make will call 'configure' itself when it finds
# 'Makefile.config' missing.  That might look a little messy to the
# user, but it isn't the normal build process.

# The argument to this program is the filepath of the Makefile.config.in
# file.  If unspecified, the default is 'Makefile.config.in' in the 
# Netpbm source directory.

# For explanations of the stuff we put in the make files, see the comments
# in Makefile.config.in.


#******************************************************************************
#
#  SUBROUTINES
#
#*****************************************************************************

sub prompt($$) {

    my ($prompt, $default) = @_;

    print("$prompt ($default) ==> ");

    my $response = <STDIN>;

    if (defined($response)) {
        chomp($response);
        if ($response eq "") {
            $response = $default;
        }
    } else {
        print("\n");
        die("End of file on Standard Input when expecting response to prompt");
    }

    return $response;
}



sub getPlatform() {

    my $platform;

    print("Which of the following best describes your platform?\n");
 
    print("gnu      GNU/Linux\n");
    print("sun      Solaris or SunOS\n");
    print("hp       HP-UX\n");
    print("aix      AIX\n");
    print("win      Windows/DOS (Cygwin, DJGPP, Mingw32)\n");
    print("tru64    Tru64\n");
    print("irix     Irix\n");
    print("bsd      NetBSD, BSD/OS\n");
    print("openbsd  OpenBSD\n");
    print("freebsd  FreeBSD\n");
    print("osx      Darwin or Mac OS X\n");
    print("unixware Unixware\n");
    print("sco      SCO OpenServer\n");
    print("beos     BeOS\n");
    print("none     none of these are even close\n");
    print("\n");
    
    my $default;
    if ($OSNAME eq "linux") {
        $default = "gnu";
    } elsif ($OSNAME eq "aix") {
        $default = "aix";
    } elsif ($OSNAME eq "cygwin") {
        $default = "win";
    } elsif ($OSNAME eq "freebsd") {
        $default = "freebsd";
    }
    # OK - if you know what $OSNAME is on any other platform, send me a patch!

    print("Your choice ");

    if (defined($default)) {
        print("($default)");
    }
    print("==> ");

    my $response = <STDIN>;

    print("\n");

    if (!defined($response)) {
        print("Aborting.\n");
        exit;
    }

    chomp($response);

    if ($response eq "") {
        if (defined($default)) {
            $response = $default;
        } else {
            print("Aborting.\n");
            exit;
        }
    }
        
    my %platform = ("gnu"      => "GNU",
                    "sun"      => "SOLARIS",
                    "hp"       => "HP-UX",
                    "aix"      => "AIX",
                    "tru64"    => "TRU64",
                    "irix"     => "IRIX",
                    "win"      => "WINDOWS",
                    "beos"     => "BEOS",
                    "bsd"      => "NETBSD",
                    "openbsd"  => "OPENBSD",
                    "freebsd"  => "FREEBSD",
                    "unixware" => "UNIXWARE",
                    "sco"      => "SCO",
                    "osx"      => "DARWIN",
                    "none"     => "NONE"
                    );

    $platform = $platform{$response};
    if (!defined($platform)) {
        print("'$response' isn't one of the choices.\n");
        exit 8;
    }

    my $subplatform;

    if ($platform eq "WINDOWS") {
        print("Are you building in/for the Cygwin environment?\n");
        print("\n");

        my $default;
        if ($OSNAME eq "cygwin") {
            $default = "y";
        } else {
            $default = "n";
        }

        my $response = prompt("(y)es or (n)o", $default);

        if (uc($response) =~ /^(Y|YES)$/)  {
            $subplatform = "cygwin";
        } elsif (uc($response) =~ /^(N|NO)$/)  {
            $subplatform = "other";
        } else {
            print("'$response' isn't one of the choices.  \n" .
                  "You must choose 'yes' or 'no' (or 'y' or 'n').\n");
            exit 12;
        }
    }

    return($platform, $subplatform);
}



sub getCompiler($) {
#-----------------------------------------------------------------------------
#  Here are some of the issues surrounding choosing a compiler:
#
#  - It's not just the name of the program we need -- different compilers
#    need different options.
#
#  - There are basically two choices on any system:  native compiler or
#    GNU compiler.  That's all this program recognizes, anyway.
#
#  - A user may well have various compilers.  Different releases, using
#    different standard libraries, for different target machines, etc.
#
#  - The CC environment variable tells the default compiler.
#
#  - In the absence of a CC environment variable, 'cc' is the default
#    compiler.
#
#  - The user must be able to specify the compiler by overriding the CC
#    make variable (e.g. make CC=gcc2).
#
#  - Configure needs to do test compiles.  The test is best if it uses
#    the same compiler that the build eventually will use, but it's 
#    useful even if not.
#
# The value this subroutine returns is NOT the command name to invoke the
# compiler.  It is simply "cc" to mean native compiler or "gcc" to mean
# GNU compiler or undefined to express no preference.
#-----------------------------------------------------------------------------
    my ($platform) = @_;

    my $compiler;

    if ($platform eq "SOLARIS" || $platform eq "TRU64" || $platform eq "SCO") {
        print("GNU compiler or native operating system compiler (cc)?\n");
        print("\n");

        my $default;

        if ($platform eq "SOLARIS" || $platform eq "SCO" ) {
            $default = "gcc";
        } else {
            $default = "cc";
        }

        my $response = prompt("gcc or cc", $default);

        if ($response eq "gcc") {
            $compiler = "gcc";
        } elsif ($response eq "cc") {
            $compiler = "cc";
        } else {
            print("'$response' isn't one of the choices.  \n" .
                  "You must choose 'gcc' or 'cc'.\n");
            exit 12;
        }

        if ($compiler eq "gcc" && !commandExists("gcc")) {
            print("WARNING: You selected the GNU compiler, " .
                  "but do not appear to have a program " .
                  "named 'gcc' in your PATH.  This may " .
                  "cause trouble later.  You may need to " .
                  "set the CC environment variable or CC " .
                  "makefile variable or install 'gcc'\n");
        }
    }
    return($compiler);
}


# TODO: These should do test compiles to see if the headers are in the
# default search path, both to create a default to offer and to issue a
# warning after user has chosen.  Also test links to test the link library.

# Before we had prompts for library locations, we set values based on 
# the platform type, as follows:
#
#    TRU64: /usr/local1/DEC/include, /usr/local1/DEC/lib
#    IRIX:  default                  /usr/lib32
#                                        this goes with our -n32 option
#    NETBSD: $(LOCALBASE)/include    $(LOCALBASE)/lib
#            where LOCALBASE is a build-time environment variable.
#    DARWIN: same as NETBSD
#
# It looks like these should all be in the default search paths and were there
# just to override defaults in Makefile.config.in.  Since Configure now
# creates a default of "standard search path," I'm guessing we don't need
# to set these anymore.

sub getTiffLibrary(@) {

    my $tifflib;
    {
        my $default = "libtiff.so";

        print("What is your TIFF (graphics format) library?\n");
        
        my $response = prompt("library filename or 'none'", $default);
        
        if ($response ne "none") {
            $tifflib = $response;
        }
        if (defined($tifflib) and $tifflib =~ m{/} and !-f($tifflib)) {
            printf("WARNING: No regular file named '$tifflib' exists.\n");
        }
    }
    my $tiffhdr_dir;
    if (defined($tifflib)) {
        my $default;

        if (-d("/usr/include/libtiff")) {
            $default = "/usr/include/libtiff";
        } else {
            $default = "default";
        }
        print("Where are the interface headers for it?\n");
        
        my $response = prompt("TIFF header directory", $default);
        
        if ($response ne "default") {
            $tiffhdr_dir = $response;
        }
        if (defined($tiffhdr_dir) and !-d($tiffhdr_dir)) {
            printf("WARNING: No directory named '$tiffhdr_dir' exists.\n");
        }
    }
    return($tifflib, $tiffhdr_dir);
}



sub getJpegLibrary(@) {

    my $jpeglib;
    {
        my $default = "libjpeg.so";

        print("What is your JPEG (graphics format) library?\n");
        
        my $response = prompt("library filename or 'none'", $default);
        
        if ($response ne "none") {
            $jpeglib = $response;
        }
        if (defined($jpeglib) and $jpeglib =~ m{/} and !-f($jpeglib)) {
            printf("WARNING: No regular file named '$jpeglib' exists.\n");
        }
    }
    my $jpeghdr_dir;
    if (defined($jpeglib)) {
        my $default;

        if (-d("/usr/include/jpeg")) {
            $default = "/usr/include/jpeg";
        } else {
            $default = "default";
        }
        print("Where are the interface headers for it?\n");
        
        my $response = prompt("JPEG header directory", $default);
        
        if ($response ne "default") {
            $jpeghdr_dir = $response;
        }
        if (defined($jpeghdr_dir) and !-d($jpeghdr_dir)) {
            printf("WARNING: No directory named '$jpeghdr_dir' exists.\n");
        }
    }
    return($jpeglib, $jpeghdr_dir);
}



sub getPngLibrary(@) {

    my $pnglib;
    {
        my $default = "libpng.so";

        print("What is your PNG (graphics format) library?\n");
        
        my $response = prompt("library filename or 'none'", $default);
        
        if ($response ne "none") {
            $pnglib = $response;
        }
        if (defined($pnglib) and $pnglib =~ m{/} and !-f($pnglib)) {
            printf("WARNING: No regular file named '$pnglib' exists.\n");
        }
    }
    my $pnghdr_dir;
    if (defined($pnglib)) {
        my $default;

        $default = "default";
        
        print("Where are the interface headers for it?\n");
        
        my $response = prompt("PNG header directory", $default);

        if ($response ne "default") {
            $pnghdr_dir = $response;
        }
        if (defined($pnghdr_dir) and !-d($pnghdr_dir)) {
            printf("WARNING: No directory named '$pnghdr_dir' exists.\n");
        }
    }
    return($pnglib, $pnghdr_dir);
}



sub getZLibrary(@) {

    my $zlib;
    {
        my $default = "libz.so";

        print("What is your Z (compression) library?\n");
        
        my $response = prompt("library filename or 'none'", $default);
        
        if ($response ne "none") {
            $zlib = $response;
        }
        if (defined($zlib) and $zlib =~ m{/} and !-f($zlib)) {
            printf("WARNING: No regular file named '$zlib' exists.\n");
        }
    }
    my $zhdr_dir;
    if (defined($zlib)) {
        my $default;

        $default = "default";
        
        print("Where are the interface headers for it?\n");
        
        my $response = prompt("Z header directory", $default);
        
        if ($response ne "default") {
            $zhdr_dir = $response;
        }
        if (defined($zhdr_dir) and !-d($zhdr_dir)) {
            printf("WARNING: No directory named '$zhdr_dir' exists.\n");
        }
    }
    return($zlib, $zhdr_dir);
}



sub commandExists($) {
    my ($command) = @_;
#-----------------------------------------------------------------------------
#  Return TRUE iff a shell command $command exists.
#-----------------------------------------------------------------------------

# Note that it's significant that the redirection on the following
# causes it to be executed in a shell.  That makes the return code
# from system() a lot different than if system() were to try to
# execute the program directly.

    return(system("$command 1</dev/null 1>/dev/null 2>/dev/null")/256 != 127); 
}


sub symlink_command() {

    my $retval;

    # Some Windows environments don't have symbolic links (or even a
    # simulation via a "ln" command, but have a "cp" command which works
    # in a pinch.
    
    # I wish I knew how to eliminate the stderr messages from these,
    # but I don't think I can count on /dev/null existing on these
    # systems.
    print("We now check to see if the 'ln' and 'cp' commands exist on \n");
    print("your system.  Ignore any error messages.\n");
    my $ln_rc = system("ln");
    my $cp_rc = system("cp");

    # I think 127 is universally the return code for "command not found"
    if ($ln_rc != 127) {
        $retval = "ln -s";
    } elsif ($cp_rc != 127) {
        $retval = "cp";
    } else {
        # Well, maybe we just made a mistake.
        $retval = "ln -s";
    }
    return $retval;
}

sub getLinuxsvgaLibrary($) {
    my ($platform) = @_;

    my ($linuxsvgahdr_dir, $linuxsvgalib);

    if ($platform eq "GNU") {
        # Look for SVGALIB 
        if (-f "/usr/include/vga.h") {
            $linuxsvgahdr_dir = "/usr/include";
        } elsif (-d "/usr/include/svgalib") {
            $linuxsvgahdr_dir = "/usr/include/svgalib";
        } else {
            print("Cannot find the include files for SVGALIB.  Enter the " .
                  "directory where they reside, or none.  " .
                  "If none, a default " .
                  "make will not build programs that require " .
                  "the SVGALIB library.\n");

            print("Svgalib header location (none)=> ");

            my $response = <STDIN>;
            chomp($response);
            if ($response ne "" && $response ne "none") {
                $linuxsvgahdr_dir = $response;
            }
        }
        if (defined($linuxsvgahdr_dir)) {
            if (-f "/usr/lib/libvga.so") {
                $linuxsvgalib = "/usr/lib/libvga.so";
            } elsif (-f "/usr/link/svgalib/libvga.so") {
                $linuxsvgalib = "/usr/link/svgalib/libvga.so";
            } else {
                print("Cannot find the link library for SVGALIB.  " .
                      "Enter the full pathname of the link library, " .
                      "or 'none'.  If 'none', " .
                      "a default make will not build programs that require " .
                      "the SVGALIB library.\n");

                print("Svgalib link lib location (none)=> ");

                my $response = <STDIN>;
                chomp($response);
                if ($response ne "" && $response ne "none") {
                    $linuxsvgalib = $response;
                }
            }
        }
    }
    return($linuxsvgalib, $linuxsvgahdr_dir);
}


sub help() {

    print("This is the Netpbm custom configuration program.  \n");
    print("It is not GNU Configure.\n");
    print("\n");
    print("There is one optional argument to this program:  The " .
          "name of the file to use as the basis for the Makefile.config " .
          "file.  Default is 'Makefile.config.in'\n");
    print("\n");
    print("Otherwise, the program is interactive.\n");
}



sub gnuOptimizeOpt() {
#-----------------------------------------------------------------------------
#  Compute the -O compiler flag appropriate for a GNU system.  Ordinarily,
#  this is just -O3.  But many popular GNU systems have a broken compiler
#  that causes -O3 to generate incorrect code (symptom: pnmtojpeg --quality=95
#  generates a syntax error message from shhopt).
#-----------------------------------------------------------------------------
# I don't know what are exactly the cases that Gcc is broken.  I know 
# Red Hat 7.1 and 7.2 and Mandrake 8.2, running gcc 2.96.1, commonly have
# the problem.  But it may be limited to a certain subrelease level or
# CPU type or other environment.  People who have reported the problem have
# reported that Gcc 3.0 doesn't have it.  

    my @gccVerboseResp = `gcc --verbose 2>&1`;

    my $brokenCompiler;
    
    if (@gccVerboseResp ==2) {
        if ($gccVerboseResp[1] =~ m{gcc version 2.96}) {
            $brokenCompiler = $TRUE;
        } else {
            $brokenCompiler = $FALSE;
        }
    } else {
        $brokenCompiler = $FALSE;
    }

    my $oOpt;

    if ($brokenCompiler) {
        print("You appear to have a broken compiler which would produce \n");
        print("incorrect code if requested to do inline optimization.\n");
        print("Therefore, I am configuring the build to not do inline \n");
        print("optimization.  This will make some Netpbm programs \n");
        print("noticeably slower.  If I am wrong about your compiler, just\n");
        print("edit Makefile.config and change -O0 to -O3 near the bottom.\n");
        print("\n");
        print("The problem is known to exist in the GNU Compiler \n");
        print("release 2.96.  If you upgrade, you will not have this \n");
        print("problem.\n");
        print("---------------------------------------------\n");
        print("\n");
        $oOpt = "-O0";
    } else {
        $oOpt = "-O3";
    }
    return $oOpt;
}


sub tmpdir() {
# This is our approximation of File::Spec->tmpdir(), which became part of
# basic Perl some time after Perl 5.005_03.

    if ($ENV{"TMPDIR"}) {
        return $ENV{"TMPDIR"};
    } else {
        return "/tmp";
    }
}



sub tempFile($) {

# Here's what we'd do if we could expect Perl 5.6.1 or later, instead
# of calling this subroutine:
#    my ($cFile, $cFileName) = tempfile("netpbmXXXX", 
#                                       SUFFIX=>".c", 
#                                       DIR=>File::Spec->tmpdir(),
#                                       UNLINK=>1);
    my ($suffix) = @_;
    my $fileName;
    local *file;  # For some inexplicable reason, must be local, not my
    my $i;
    $i = 0;
    do {
        $fileName = tmpdir() . "/netpbm" . $i++ . $suffix;
    } until sysopen(*file, $fileName, O_RDWR|O_CREAT|O_EXCL);

    return(*file, $fileName);
}



sub chooseTestCompiler($) {

    my ($compiler) = @_;

    my $cc;

    if (!defined($compiler)) {
        if ($ENV{"CC"}) {
            $cc = $ENV{"CC"};
        } else {
            if (commandExists("cc")) {
                $cc = "cc";
            } elsif (commandExists("gcc")) {
                $cc = "gcc";
            }
        }
    } elsif ($compiler eq "cc") {
        $cc = "cc";
    } elsif ($compiler eq "gcc") {
        $cc = "gcc";
    } else {
        die("Internal error: invalid value \"$compiler\" for \$compiler");
    }
    return $cc;
}



sub printJpegIncludeWarning() {

    print("WARNING: You said the compile-time part of the JPEG library " .
          "(the header\n");
    print("files) is in the compiler's default search path, but a test " .
          "compile failed\n");
    print("to confirm that.  If your configuration is exotic, the test " .
          "compile might\n");
    print("just be wrong, but otherwise the Netpbm build will fail.\n");
    print("\n");
    print("To fix this, either install the JPEG library in the default " .
          "search path\n");
    print("or re-run Configure and answer the question about the JPEG " .
          "library\n");
    print("differently.\n");
    print("\n");
}



sub testJpegHdrDefaultPath($) {

    my ($compiler) = @_;

    my $cc = chooseTestCompiler($compiler);

    if (defined($cc)) {

        my $cflags;

        if ($ENV{"CFLAGS"}) {
            $cflags = $ENV{"CFLAGS"};
        } else {
            $cflags = "";
        }
        my ($cFile, $cFileName) = tempFile(".c");

        print $cFile ("#include <ctype.h>\n");
        print $cFile ("#include <stdio.h>\n");
        print $cFile ("#include <jpeglib.h>\n");

        my ($oFile, $oFileName) = tempFile(".o");
        # Note: we tried using /dev/null for the output file and got complaints
        # from the Sun compiler that it has the wrong suffix.  2002.08.09.
        
        my $compileCommand = "$cc -c -o $oFileName $cflags $cFileName";
        print ("Doing test compile: $compileCommand\n");
        my $rc = system($compileCommand);

        unlink($oFileName);
        close($oFile);
        unlink($cFileName);
        close($cFile);

        if ($rc != 0) {
            print("\n");
            printJpegIncludeWarning();
        }
    }
}



sub testConfiguration($$$) {

    my ($compiler, $jpeglib, $jpeg_hdr_dir) = @_;
    
    if (defined($jpeglib)) {
        if (!defined($jpeg_hdr_dir)) {
            testJpegHdrDefaultPath($compiler);
        }
    }
}

#******************************************************************************
#
#  MAINLINE
#
#*****************************************************************************



my $configInPathArg;
if (@ARGV > 0) {
    if ($ARGV[0] =~ "^-") {
        if ($ARGV[0] eq "--help") {
            help();
            exit(0);
        } else {
            die("Unrecognized option: $ARGV[0]");
        }
    } 
    $configInPathArg = $ARGV[0];
}

if (stat("Makefile.config")) {
    print("Discard existing Makefile.config?\n");
    print("Y or N (N) ==> ");

    my $answer = <STDIN>;
    if (!defined($answer)) {
        die("\nEnd of file on Standard Input");
    }
    chomp($answer);
    if (uc($answer) ne "Y") {
        exit(1);
    }
}

print("\n");

print("This is the Netpbm configurator.  It is an interactive dialog that\n");
print("helps you build the file 'Makefile.config' and prepare to build ");
print("Netpbm.\n");
print("\n");
print("Do not be put off by all the questions.  Configure gives you the \n");
print("opportunity to make a lot of choices, but you don't have to.  If \n");
print("you don't have reason to believe you're smarter than Configure,\n");
print("Just take the defaults (hit ENTER) and don't sweat it.\n");

print("\n");

my ($platform, $subplatform) = getPlatform();

if ($platform eq "NONE") {
    print("You will have to construct Makefile.config manually.  To do \n");
    print("this, copy Makefile.config.in as Makefile.config, and then \n");
    print("edit it.  Follow the instructions and examples in the file. \n");
    print("Please report your results to the Netpbm maintainer so he \n");
    print("can improve the configure program. \n");
    exit;
}

my $compiler = getCompiler($platform);

my $netpbmlib_runtime_path;
    # Undefined if the default from Makefile.config.in is acceptable.

if ($platform eq "SOLARIS" or $platform eq "IRIX" or
    $platform eq "DARWIN" or $platform eq "NETBSD") {
    print("Where will the Netpbm shared library reside once installed?\n");
    print("Enter 'default' if it will reside somewhere that the shared\n");
    print("library loader will find them automatically.  Otherwise, \n");
    print("this directory will get built into the Netpbm programs.\n");
    print("\n");

    my $default = "default";
    my $response = prompt("Netpbm shared library directory", $default);

    if ($response eq "default") {
        $netpbmlib_runtime_path = "";
    } else {
        $netpbmlib_runtime_path = $response;
    }
}

my $default_target;

print("Do you want a regular build or a merge build?\n");
print("If you don't know what this means, " .
      "take the default or see doc/INSTALL\n");
print("\n");

{
    my $default = "regular";
    my $response = prompt("regular or merge", $default);
    
    if ($response eq "regular") {
        $default_target = "nonmerge";
    } elsif ($response eq "merge") {
        $default_target = "merge";
    } else {
        print("'$response' isn't one of the choices.  \n" .
              "You must choose 'regular' or 'merge'.\n");
        exit 12;
    }
}

print("\n");

my ($netpbmlibtype, $netpbmlibsuffix, $shlibprefixlist);
# Undefined means the default from Makefile.config.in is acceptable.

my $willBuildShared;

print("Do you want libnetpbm to be statically linked or shared?\n");
print("\n");

{
    my $default = ($default_target eq "merge") ? "static" : "shared";

    my $response = prompt("static or shared", $default);

    if ($response eq "shared") {
        $willBuildShared = $TRUE;
        if ($platform eq "WINDOWS") {
            $netpbmlibtype = "dll";
            $netpbmlibsuffix = "dll";
            if ($subplatform eq "cygwin") {
                $shlibprefixlist = "cyg lib";
            } 
        } elsif ($platform eq "DARWIN") {
            $netpbmlibtype = "dylib";
            $netpbmlibsuffix = "dylib";
        } else {
	    if ($platform eq "IRIX") {
		$netpbmlibtype = "irixshared";
	    } else {
		$netpbmlibtype = "unixshared";
	    }
            if ($platform eq "AIX") {
                $netpbmlibsuffix = "a";
                print("I don't know how to make a shared library on AIX.  " .
                      "If you do, please clue in the Netpbm maintainer.\n");
                exit(1)
            } elsif ($platform eq "HP-UX") {
                $netpbmlibsuffix = "sl";
            } else {
                $netpbmlibsuffix = "so";
            }
        }
    } elsif ($response eq "static") {
        $willBuildShared = $FALSE;
        $netpbmlibtype = "unixstatic";
        $netpbmlibsuffix = "a";
        # targets, but needed for building
        # libopt 
    } else {
        print("'$response' isn't one of the choices.  \n" .
              "You must choose 'static' or 'shared'.\n");
        exit 12;
    }
}
print("\n");

my $staticlib_too;

if ($netpbmlibtype eq "unixshared" or 
    $netpbmlibtype eq "irixshared" or 
    $netpbmlibtype eq "dll") {
    print("Do you want to build static libraries too (for linking to \n");
    print("programs not in the Netpbm package?\n");
    print("\n");

    my $default = "y";

    my $response = prompt("(y)es or (n)o", $default);

    if (uc($response) =~ /^(Y|YES)$/)  {
        $staticlib_too = "y";
    } elsif (uc($response) =~ /^(N|NO)$/)  {
        $staticlib_too = "n";
    } else {
        print("'$response' isn't one of the choices.  \n" .
              "You must choose 'yes' or 'no' (or 'y' or 'n').\n");
        exit 12;
    }
} else {
    $staticlib_too = "n";
}
print("\n");

#******************************************************************************
#
#  FIND THE PREREQUISITE LIBRARIES
#
#*****************************************************************************

print("\n\n");
print("The following questions concern the subroutine libraries that are " .
      "Netpbm\n");
print("prerequisites.  Every library has a compile-time part (header " .
      "files)\n");
print("and a link-time part.  In the case of a shared library, these are " .
      "both\n");
print("part of the \"development\" component of the library, which may be " .
      "separately\n");
print("installable from the runtime shared library.  For each library, you " .
      "must\n");
print("give the filename of the link library.  If it is not in your " .
      "linker's\n");
print("default search path, give the absolute pathname of the file.  In " .
      "addition,\n");
print("you will be asked for the directory in which the library's interface " .
      "headers\n");
print("reside, and you can respond 'default' if they are in your compiler's " .
      "default\n");
print("search path.\n");
print("\n");
print("If you don't have the library on your system, you can enter 'none' " .
      "as the\n");
print("library filename and the builder will skip any part that requires " .
      "that ");
print("library.\n");
print("\n");

my ($jpeglib, $jpeghdr_dir) = getJpegLibrary();
print("\n");
my ($tifflib, $tiffhdr_dir) = getTiffLibrary($jpeghdr_dir);
print("\n");
my ($pnglib, $pnghdr_dir)   = getPngLibrary($tiffhdr_dir, $jpeghdr_dir);
print("\n");
my ($zlib, $zhdr_dir)       = getZLibrary($pnghdr_dir,
                                          $tiffhdr_dir,
                                          $jpeghdr_dir);
print("\n");
my ($linuxsvgalib, $linuxsvgahdr_dir) = getLinuxsvgaLibrary($platform); 
print("\n");

# We should add the JBIG and URT libraries here too.  They're a little
# more complicated because there are versions shipped with Netpbm.

testConfiguration($compiler, $jpeglib, $jpeghdr_dir);

#******************************************************************************
#
#  FIND THE NETPBM SOURCE TREE AND INITIALIZE BUILD TREE
#
#*****************************************************************************

my $defaultConfigInPath;

if (-f("GNUmakefile")) {
    # He's apparently running us in the source tree or an already set up
    # build directory.
    $defaultConfigInPath = "Makefile.config.in";
} else {
    my $srcdir;
    my $done;

    $done = $FALSE;
    while (!$done) {
        print("Where is the Netpbm source code?\n");

        $srcdir = prompt("Netpbm source directory", 
                         abs_path(dirname($0) . "/.."));

        if (-f("$srcdir/GNUmakefile")) {
            $done = $TRUE;
        } else {
            print("That doesn't appear to contain Netpbm source code.\n");
            print("There is no file named 'GNUmakefile' in it.\n");
            print("\n");
        }    
    }
    unlink("GNUmakefile");
    symlink("$srcdir/GNUmakefile", "GNUmakefile");
    unlink("Makefile");
    symlink("$srcdir/Makefile", "Makefile");

    open(SRCDIR, ">Makefile.srcdir");
    print(SRCDIR "SRCDIR = $srcdir\n");
    close(SRCDIR);
    
    $defaultConfigInPath = "$srcdir/Makefile.config.in";
}

#******************************************************************************
#
#  BUILD Makefile.config
#
#*****************************************************************************

sub gnuCflags() {
    return("CFLAGS = -pedantic " . gnuOptimizeOpt() . " " .
           "-Wall -Wno-uninitialized -Wmissing-declarations -Wimplicit " .
           "-Wwrite-strings\n");
}

my @Makefile_config;
    # This is the complete Makefile.config contents.  We construct it here
    # and ultimately write the whole thing out as Makefile.config.

# First, we just read the 'Makefile.config.in' in

my $configInPath;
if (defined($configInPathArg)) {
    $configInPath = $configInPathArg;
} else {
    $configInPath = $defaultConfigInPath;
}
open (CONFIG_IN,"<$configInPath") or
    die("Unable to open file '$configInPath' for input.");

@Makefile_config = <CONFIG_IN>;

unshift(@Makefile_config, 
        "####This file was automatically created by 'configure.'\n",
        "####Many variables are set twice -- a generic setting, then \n",
        "####a system-specific override at the bottom of the file.\n",
        "####\n");

close(CONFIG_IN);

# Now, add the variable settings that override the default settings that are
# done by the Makefile.config.in contents.

push(@Makefile_config, "\n\n\n\n");
push(@Makefile_config, "####Lines above were copied from Makefile.config.in " .
     "by 'configure'.\n");
push(@Makefile_config, "####Lines below were added by 'configure' based on " .
     "the $platform platform.\n");
if (defined($subplatform)) {
    push(@Makefile_config, "####subplatform '$subplatform'\n");
}

push(@Makefile_config, "DEFAULT_TARGET = $default_target\n");

push(@Makefile_config, "NETPBMLIBTYPE=$netpbmlibtype\n");
push(@Makefile_config, "NETPBMLIBSUFFIX=$netpbmlibsuffix\n");
if (defined($shlibprefixlist)) {
    push(@Makefile_config, "SHLIBPREFIXLIST=$shlibprefixlist\n");
}
push(@Makefile_config, "STATICLIB_TOO=$staticlib_too\n");

if (defined($netpbmlib_runtime_path)) {
    push(@Makefile_config, "NETPBMLIB_RUNTIME_PATH=$netpbmlib_runtime_path\n");
}

if ($platform eq "GNU") {
    # All the defaults are designed for a typical GNU system, so we don't
    # have to do much here.

    if (!commandExists("cc") && commandExists("gcc")) {
        push(@Makefile_config, "CC = gcc\n");
    }
    push(@Makefile_config, gnuCflags());
# The merged programs have a main_XXX subroutine instead of main(),
# which would cause a warning with -Wmissing-declarations
    push(@Makefile_config, "CFLAGS_MERGE = -Wno-missing-declarations\n");
} elsif ($platform eq "SOLARIS") {
    push(@Makefile_config, 'LDSHLIB = -Wl,-Bdynamic,-G,-h,$(SONAME)', "\n");

    push(@Makefile_config, 'NEED_RUNTIME_PATH = Y', "\n");
    if ($compiler eq "cc") {
        push(@Makefile_config, "CFLAGS = -O\n");
        push(@Makefile_config, "CFLAGS_SHLIB = -Kpic\n");
    } else {
        push(@Makefile_config, "CC = gcc\n");
        push(@Makefile_config, gnuCflags());
    }
    push(@Makefile_config, "NETWORKLD = -lsocket -lnsl\n");
} elsif ($platform eq "HP-UX") {
    push(@Makefile_config, 'CFLAGS = -O3 -fPIC $(CADD)', "\n");
    push(@Makefile_config, 'LDFLAGS = -Wl,+b,/usr/pubsw/lib', "\n");
} elsif ($platform eq "AIX") {
    # These options seem to be for gcc; I don't know what to use for any
    # other compiler; I hope someone tells us so we can do like we did 
    # for SOLARIS above
    push(@Makefile_config, 'CFLAGS = -O3 -D_ALL_SOURCE $(CADD)', "\n");
    push(@Makefile_config, 'LDFLAGS = -L /usr/pubsw/lib', "\n");
    push(@Makefile_config, 'LDSHLIB = -shared', "\n");
} elsif ($platform eq "TRU64") {
#    push(@Makefile_config, "INSTALL = installbsd\n");
    if ($compiler eq "cc") {
        push(@Makefile_config, 'CFLAGS = -O2 -std1 -DLONG_32 $(CADD)', "\n");
        push(@Makefile_config, "LDFLAGS = -call_shared -oldstyle_liblookup " .
             "-L/usr/local/lib\n");
        push(@Makefile_config, "LDSHLIB = -shared -expect_unresolved \"*\"\n");
    } else {
        # We've never tested this.  This is just here to give a user a 
        # headstart on submitting to us the necessary information.  2002.07.04.
        push(@Makefile_config, "CC = gcc\n");
        push(@Makefile_config, 'CFLAGS = -O3 -DLONG_32 $(CADD)', "\n");
        push(@Makefile_config, "LDSHLIB = -shared\n");
    }
    push(@Makefile_config, "NETWORKLD = NONE\n");
} elsif ($platform eq "IRIX") {
#    push(@Makefile_config, "INSTALL = install\n");
    push(@Makefile_config, "MANPAGE_FORMAT = cat\n");
    push(@Makefile_config, "RANLIB = true\n");
    push(@Makefile_config, "CFLAGS = -n32 -O3\n");
    push(@Makefile_config, "LDFLAGS = -n32\n");
    push(@Makefile_config, "LDSHLIB = -shared -n32\n");
} elsif ($platform eq "WINDOWS") {
    if ($subplatform eq "cygwin") {
        push(@Makefile_config, "CC = gcc\n");
        push(@Makefile_config, gnuCflags());
    }
    push(@Makefile_config, "EXE = .exe\n");
    push(@Makefile_config, "NETWORKLD = NONE\n");
#    # Though it may not have the link as "ginstall", "install" in a Windows
#    # Unix environment is usually GNU install.
#    my $ginstall_result = `ginstall --version 2>/dev/null`;
#    if (!$ginstall_result) {
#        # System doesn't have 'ginstall', so use 'install' instead.
#        push(@Makefile_config, "INSTALL = install\n");
#    }
    push(@Makefile_config, 'SYMLINK = ', symlink_command(), "\n");
    push(@Makefile_config, 'DLLVER=$(NETPBM_MAJOR_RELEASE)', "\n");
    push(@Makefile_config, "LDSHLIB = " . 
         '-shared -Wl,--image-base=0x10000000 -Wl,--enable-auto-import', "\n");
} elsif ($platform eq "BEOS") {
    push(@Makefile_config, "LDSHLIB = -nostart\n");
} elsif ($platform eq "NETBSD") {
    push(@Makefile_config, "LINKERISGCC = Y\n");
    push(@Makefile_config, 'CFLAGS_SHLIB = -fpic', "\n");
    push(@Makefile_config, "\n");
} elsif ($platform eq "OPENBSD") {
    # vedge@vedge.com.ar says on 2001.04.29 that there are a ton of 
    # undefined symbols in the Fiasco stuff on OpenBSD.  So we'll just
    # cut it out of the build until someone feels like fixing it.
    push(@Makefile_config, 'BUILD_FIASCO = N', "\n");
} elsif ($platform eq "FREEBSD") {
    # Information from "alexus" <alexus@alexus.org> on 02.10.14 that
    # /usr/local/lib is not in FreeBSD's linker's default search path,
    # but that's where e.g. the JPEG library normally resides.  This is
    # probably a FreeBSD bug.
    push(@Makefile_config, "LDFLAGS = -L/usr/local/lib\n");
} elsif ($platform eq "UNIXWARE") {
    # Nothing to do.
} elsif ($platform eq "SCO") {
    # Got this from "John H. DuBois III" <spcecdt@armory.com> 2002.09.27:
    push(@Makefile_config, "RANLIB = true\n");
    if ($compiler eq "cc") {
        push(@Makefile_config, "CFLAGS = -O\n");
        push(@Makefile_config, "CFLAGS_SHLIB = -O -K pic\n");
        push(@Makefile_config, "LD_SHLIB = -G\n");
        push(@Makefile_config, "SHLIB_CLIB =\n");
    } else {
        push(@Makefile_config, "CC = gcc\n");
        push(@Makefile_config, gnuCflags());
    }
    push(@Makefile_config, "CFLAGS_SHLIB = -fPIC\n");
    push(@Makefile_config, "LDSHLIB = -shared\n"); 
    push(@Makefile_config, "NETWORKLD = -lsocket -lresolve\n");
} elsif ($platform eq "DARWIN") {
    push(@Makefile_config, "CC = cc -no-cpp-precomp\n");
    push(@Makefile_config, 'CFLAGS_SHLIB = -fno-common', "\n");
    push(@Makefile_config, "LDSHLIB = ",
         "-dynamiclib ",
         '-install_name $(NETPBM_RUNTIME_PATH)/libnetpbm.$(MAJ).dylib', 
         "\n");
#    push(@Makefile_config, "INSTALL = install\n");
} else {
    die ("Internal error: invalid value for \$platform: '$platform'\n");
}


my $flex_result = `flex --version`;
if (!$flex_result) {
    # System doesn't have 'flex'.  Maybe 'lex' will work; we don't really
    # know yet.  2001.05.16.

    # lex may work; we don't really know yet.  Schwarb Manfred reports
    # that it compiles OK, but with warnings, on Solaris.  Solaris Lex
    # has a -e option that eliminates the lex warnings, but causes
    # compiler warnings.  AIX and Flex don't have a -e option.
    # -Bryan 2001.05.16.

    print("\n");
    print("We cannot find 'flex' on your system, so will not build\n");
    print("Thinkjettopbm.  If you want to try using some other version of\n");
    print("Lex, change LEX=... at the bottom of your Makefile.config.\n");
    print("\n");
    push(@Makefile_config, "LEX=\n"); 

    # In the Latest Netpbm version, we set LEX=lex and hope for the
    # best.

#    print("\n");
#    print("There is no 'flex' command in your environment, so we will not\n");
#    print("Build the part that requires it: thinkjettopbm.\n");

#    print("\n");
#    print("Press ENTER to continue.\n");
#    my $key = <STDIN>;
}

if (defined($tiffhdr_dir)) {
    push(@Makefile_config, "TIFFHDR_DIR = $tiffhdr_dir\n");
}
if (defined($tifflib)) {
    push(@Makefile_config, "TIFFLIB = $tifflib\n");
}

if (defined($jpeghdr_dir)) {
    push(@Makefile_config, "JPEGHDR_DIR = $jpeghdr_dir\n");
}
if (defined($jpeglib)) {
    push(@Makefile_config, "JPEGLIB = $jpeglib\n");
}

if (defined($pnghdr_dir)) {
    push(@Makefile_config, "PNGHDR_DIR = $pnghdr_dir\n");
}
if (defined($pnglib)) {
    push(@Makefile_config, "PNGLIB = $pnglib\n");
}

if (defined($zhdr_dir)) {
    push(@Makefile_config, "ZHDR_DIR = $zhdr_dir\n");
}
if (defined($zlib)) {
    push(@Makefile_config, "ZLIB = $zlib\n");
}

if (defined($linuxsvgahdr_dir)) {
    push(@Makefile_config, "LINUXSVGAHDR_DIR = $linuxsvgahdr_dir\n");
}
if (defined($linuxsvgalib)) {
    push(@Makefile_config, "LINUXSVGALIB = $linuxsvgalib\n");
}



#******************************************************************************
#
#  WRITE OUT THE FILE
#
#*****************************************************************************

open(MAKEFILE_CONFIG, ">Makefile.config") or
    die("Unable to open Makefile.config for writing in the current " .
        "directory.");

print MAKEFILE_CONFIG @Makefile_config;

close(MAKEFILE_CONFIG) or
    die("Error:  Close of Makefile.config failed.\n");

print("\n");
print("We have created the file 'Makefile.config'.  Note, however, that \n");
print("we guessed a lot at your configuration and you may want to look \n");
print("at Makefile.config and edit it to your requirements and taste \n");
print("before doing the make.\n");
print("\n");


print("Now you may proceed with 'make'\n");
print("\n");


exit 0;          
