Index: trunk/psconfig/pschecklibs
===================================================================
--- trunk/psconfig/pschecklibs	(revision 14424)
+++ trunk/psconfig/pschecklibs	(revision 15009)
@@ -1,294 +1,454 @@
-#!/bin/csh -f
-
-# XXX : add needed subdirs (eg, DIR/mysql, DIR/jpeg...)
-# XXX : add -build option
-# XXX : additional override options for certain packages
-# XXX : add pkg-config
-
-# this scripts searches for the needed libraries in standard locations and in the 
-# current psconfig installation tree
-
-set version = ""
-set args = ""
-while ("$1" != "") 
- switch ("$1")
-  case -version:
-   shift
-   set version = $1
-   breaksw
-  case --help:
-   goto usage
-  case -*: 
-   echo ""
-   echo "Unknown option: $1"
-   goto usage
-  default:
-   set args=($args $1);
-   breaksw;
- endsw
- shift
-end
-if ($#args != 1) goto usage
-
-# set supplied PSVERSION
-if ("$version" != "") then
-  setenv PSVERSION $version
-endif
-
-# set install paths for PSVERSION
-set libdir  = `source psconfig.csh --libs $PSVERSION`
-set incdir  = `source psconfig.csh --include $PSVERSION`
-
-# make these directories
-mkdir -p $libdir
-mkdir -p $incdir
-
-# I supplement this list with LIBRARY_PATH below
-set syslibpath = "/lib /usr/lib /usr/X11R6/lib /usr/local/lib "
-set needlibs   = ""
-set needlibs   = "$needlibs png"
-set needlibs   = "$needlibs z"
-set needlibs   = "$needlibs jpeg"
-set needlibs   = "$needlibs readline"
-set needlibs   = "$needlibs X11"
-set needlibs   = "$needlibs pthread"
-set needlibs   = "$needlibs cfitsio"
-set needlibs   = "$needlibs mysqlclient"
-set needlibs   = "$needlibs gsl"
-set needlibs   = "$needlibs xml2"
-set needlibs   = "$needlibs fftw3"
-set needlibs   = "$needlibs fftw3f"
-set needlibs   = "$needlibs m"
-
-# I supplement this list with CPATH below
-set sysincpath = "/usr/include /usr/local/include /usr/X11R6/include "
-set needincs = ""
-set needincs = "$needincs X11/Xatom.h"
-set needincs = "$needincs X11/Xlib.h"
-set needincs = "$needincs X11/Xresource.h"
-set needincs = "$needincs X11/Xutil.h"
-set needincs = "$needincs X11/cursorfont.h"
-set needincs = "$needincs X11/keysym.h"
-set needincs = "$needincs X11/keysymdef.h"
-set needincs = "$needincs arpa/inet.h"
-set needincs = "$needincs assert.h"
-set needincs = "$needincs complex.h"
-set needincs = "$needincs ctype.h"
-set needincs = "$needincs errno.h"
-set needincs = "$needincs fcntl.h"
-set needincs = "$needincs fitsio.h"
-set needincs = "$needincs glob.h"
-set needincs = "$needincs gsl/gsl_randist.h"
-set needincs = "$needincs gsl/gsl_rng.h"
-set needincs = "$needincs inttypes.h"
-set needincs = "$needincs jpeglib.h"
-set needincs = "$needincs limits.h"
-set needincs = "$needincs malloc.h"
-set needincs = "$needincs math.h"
-set needincs = "$needincs memory.h"
-set needincs = "$needincs netdb.h"
-set needincs = "$needincs netinet/ip.h"
-set needincs = "$needincs png.h"
-set needincs = "$needincs pthread.h"
-set needincs = "$needincs readline/history.h"
-set needincs = "$needincs readline/readline.h"
-set needincs = "$needincs regex.h"
-set needincs = "$needincs signal.h"
-set needincs = "$needincs stdint.h"
-set needincs = "$needincs stdio.h"
-set needincs = "$needincs stdlib.h"
-set needincs = "$needincs string.h"
-set needincs = "$needincs sys/ipc.h"
-set needincs = "$needincs sys/resource.h"
-set needincs = "$needincs sys/sem.h"
-set needincs = "$needincs sys/socket.h"
-set needincs = "$needincs sys/stat.h"
-set needincs = "$needincs sys/time.h"
-set needincs = "$needincs sys/types.h"
-set needincs = "$needincs sys/uio.h"
-set needincs = "$needincs sys/un.h"
-set needincs = "$needincs sys/wait.h"
-set needincs = "$needincs time.h"
-set needincs = "$needincs unistd.h"
-set needincs = "$needincs zlib.h"
-
-# XXX need to have options for non-ANSI includes? (ie, varargs.h)
-# set needincs = "$needincs values.h" - this only provides values already defined in limits.h?
-# set needincs = "$needincs libxml/parser.h"
-# set needincs = "$needincs cfuncs.h" - from non-ANSI option in ohana.h
-# set needincs = "$needincs float.h" - is from missing_proto (CFHT)
-# set needincs = "$needincs floatingpoint.h" - is from missing_proto (CFHT)
-# set needincs = "$needincs stdarg.h" - from std includes (in gcc path)
-# set needincs = "$needincs varargs.h" - from std includes (in gcc path)
-# set needincs = "$needincs stdbool.h" - from std includes (in gcc path) ?
-
-# check the hardware architecture:
-set sys=`uname -s` 
-set ranlib = "ranlib"
-set dlltype = "so"
-switch ($sys)
- case IRIX64:
-   set arch="irix";
-   breaksw;
- case SunOS:
-   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
-   if ($ver == 5) then
-     set arch="sol";
-   else 
-     set arch="sun4";
-   endif
-   # sun (at least) seems to need the socket library (linux does not)
-   set syslibpath = "$syslibpath /usr/openwin/lib"
-   set sysincpath = "$sysincpath /usr/openwin/include"
-   set needlibs = "$needlibs libsocket libnsl"
-   set ranlib = "touch"
-   breaksw;
- case Linux:
-   set arch="linux";
-   if (-e /etc/sidious.config) set arch="sid";
-   set mach=`uname -m`
-   if ("$mach" == "x86_64") then
-    set arch="lin64";
-    set syslibpath = "/lib64 /usr/lib64 /usr/X11R6/lib64 $syslibpath"
-   endif
-   breaksw;
- case Darwin:
-   set arch="darwin";
-   set mach=`uname -m`
-   if ("$mach" == "i386") then
-    set arch="darwin_x86";
-   endif
-   set syslibpath = "$syslibpath /sw/lib /usr/local/lib/mysql"
-   set sysincpath = "$sysincpath /sw/include /usr/include/sys"
-   set dlltype = dylib
-   breaksw;
- case HP-UX:
-    set arch="hpux";
-    breaksw;
- default:
-   echo "unknown architecture";
-   exit 1;
-   breaksw;
-endsw
-echo "setting architecture to: $arch" 
-
-# add the LIBRARY_PATH
-if ($?LIBRARY_PATH) then 
-  set libpath = `echo $LIBRARY_PATH | tr ':' ' '`
-else
-  set libpath = ""
-endif
-
-# check for basic libraries
-echo ""
-echo "searching for needed external libraries..."
-set faillibs = ""
-set libflags = ""
-set libdirs  = ""
-set nonomatch
-foreach f ( $needlibs )
-    foreach g ( $libdir $libpath $syslibpath )
-        if (! -e $g) continue
-        set name = $g/lib$f.a
-        if (-e $name[1]) goto got_lib;
-        set name = $g/lib$f.$dlltype
-        if (-e $name[1]) goto got_lib;
-    end
-    # if we find a .so.N without a matching .so, we link this in
-    # the installed libdir
-    foreach g ( $libpath $syslibpath )
-        set name = $g/lib$f.$dlltype*
-        #echo "libname: $name"
-        if (-e $name[1]) then
-          echo "making link to numbered .$dlltype library $libdir/lib$f.$dlltype"
-          ln -s $name[$#name] $libdir/lib$f.$dlltype
-          if ($status) exit 1
-          goto got_lib
-        endif
-    end
-    echo "missing lib$f"
-    set faillibs = "$faillibs lib$f"
-    continue
-got_lib:
-    echo "found lib$f ($name[$#name])"
-end
-
-# we need a curses library; can choose one of the following:
-# check for termcap, curses, etc
-foreach f ( ncurses curses termcap )
-    foreach g ( $libdir $libpath $syslibpath )
-        set name = $g/lib$f.a
-        if (-e $name[1]) goto got_curses;
-        set name = $g/lib$f.$dlltype
-        if (-e $name[1]) goto got_curses;
-    end
-    # if we find a .so.N without a matching .so, we link this in
-    # the installed libdir
-    foreach g ( $libpath $syslibpath )
-        set name = $g/lib$f.$dlltype*
-        if ($#name > 0) then
-          echo "making link to numbers .$dlltype library $libdir/lib$f.$dlltype"
-          ln -s $name[$#name] $libdir/lib$f.$dlltype
-          goto got_curses;
-        endif
-    end
-end
-set faillibs = "$faillibs (ncurses | curses | termcap)"
-echo "missing a valid curses library"
-echo "missing: $faillibs"
-echo "please find one of them and install them in $libdir"
-exit 1
-
-got_curses:
-  echo "found $f ($name[$#name])"
-
-if ("$faillibs" != "") then
-  echo "your installation is missing some important libraries"
-  echo "missing: $faillibs"
-  echo "please find them and install them in $libdir"
-  exit 1
-endif    
-
-# add the CPATH
-if ($?CPATH) then 
-  set incpath = `echo $CPATH | tr ':' ' '`
-else
-  set incpath = ""
-endif
-
-# check for headers
-echo ""
-echo "searching for needed external header files..."
-set failincs = ""
-set incdirs = ""
-foreach f ( $needincs )
-  foreach g ( $incdir $incpath $sysincpath )
-    set name = "$g/$f"
-    if (-e $name) goto got_inc;
-  end
-  echo "missing $f"
-  set failincs = "$failincs $f"
-  continue
-got_inc:
-  echo "found $f ($name)"
-end
-
-if ("$failincs" != "") then
-  echo "your installation is missing some important library headers"
-  echo "please find them and install them in $incdir"
-  exit 1
-endif    
-
-exit 0
-
-usage:
-cat <<EOF
-USAGE: pschecklibs
-
-searches for needed libraries and include files in system and psconfig installation directories
-
-Additional options
-  -h, --help              display this help and exit
-
-EOF
- exit 2;
+#!/usr/bin/env perl
+
+$tagsets = "tagsets";
+
+# default system library locations
+@binpath = ( );
+@libpath = ( "/lib", "/usr/lib", "/usr/X11R6/lib", "/usr/local/lib" );
+@incpath = ( "/usr/include", "/usr/local/include", "/usr/X11R6/include" );
+
+$version = "";
+$build = 0;
+$force = "";
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-version") {
+	$version = $ARGV[1];
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-build") {
+	$build = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-force") {
+	if (@ARGV < 2) { die "-force must be coupled to a library name\n"; }
+	$force = $ARGV[1];
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-h")     { &usage (); }
+    if ($ARGV[0] eq "help")   { &usage (); }
+    if ($ARGV[0] eq "-help")  { &usage (); }
+    if ($ARGV[0] eq "--help") { &usage (); }
+    if ($ARGV[0] eq "-list")  { &list_distributions(); }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+if ( @ARGV > 1) { &usage(); }
+
+if ( @ARGV == 0) { 
+    @list = <$tagsets/*.libs>;
+    $file = $list[-1];
+} else {
+    $file = "$tagsets/$ARGV[0].libs";
+}
+print "examining C libraries based on $file\n\n";
+
+# load the C libraries list
+open (FILE, $file) || die "ERROR: can't open C libraries list: $file\n";
+@list = <FILE>;
+close (FILE);
+
+# set the psconfig version:
+if ("$version" eq "") {
+    $version = $ENV{'PSVERSION'};
+}
+if ("$version" eq "") {
+    $version = "default";
+}
+
+# set the lib and include paths set by psconfig
+$bindir      = `csh psconfig.csh --bin $version`;         chomp $bindir;
+$libdir      = `csh psconfig.csh --libs $version`;        chomp $libdir;
+$mandir      = `csh psconfig.csh --man $version`;         chomp $mandir;
+$incdir      = `csh psconfig.csh --include $version`;     chomp $incdir;
+$psconfigure = `csh psconfig.csh --psconfigure $version`; chomp $psconfigure;
+$prefix      = `csh psconfig.csh --prefix $version`;      chomp $prefix;
+$homedir     = `pwd`; chomp $homedir;
+
+print "psconfig version: $version\n";
+print "bindir: $bindir\n";
+print "libdir: $libdir\n";
+print "incdir: $incdir\n";
+print "mandir: $mandir\n";
+print "\n";
+
+# create the directories above if not found:
+if (! -e $libdir) { vsystem ("mkdir -p $libdir"); }
+if (! -e $incdir) { vsystem ("mkdir -p $incdir"); }
+if (! -e $bindir) { vsystem ("mkdir -p $bindir"); }
+if (! -e $mandir) { vsystem ("mkdir -p $mandir"); }
+if (! -e "$mandir/man1") { vsystem ("mkdir -p $mandir/man1"); }
+if (! -e "$mandir/man3") { vsystem ("mkdir -p $mandir/man3"); }
+
+# add the path defined by LIBRARY_PATH
+@tmppath = split (":", $ENV{'LIBRARY_PATH'});
+if (@tmppath) {
+    unshift @libpath, @tmppath;
+}
+# search for, and drop, existing libdir entry in libpath?
+unshift @libpath, $libdir;
+
+# add the path defined by PATH
+@tmppath = split (":", $ENV{'PATH'});
+if (@tmppath) {
+    unshift @binpath, @tmppath;
+}
+# search for, and drop, existing libdir entry in libpath?
+unshift @binpath, $bindir;
+
+# add the path defined by PATH
+@tmppath = split (":", $ENV{'CPATH'});
+if (@tmppath) {
+    unshift @incpath, @tmppath;
+}
+# search for, and drop, existing libdir entry in libpath?
+unshift @incpath, $incdir;
+
+# add the system paths specified for each architecture
+&checkarch ();
+print "setting architecture to: $arch\n"; 
+print "searching for libraries in: @libpath\n";
+print "searching for programs in: @binpath\n";
+print "\n";
+
+# read the lib distribution file, search / build each entry
+@faillibs = ();
+@failincs = ();
+foreach $line (@list) {
+    chop $line;
+    if ($line =~ m|^\s*$|) { next; }
+    if ($line =~ m|^\s*\#|) { next; }
+
+    ($type, $name, $altnames, $altpaths, $tarball, $tardir, $use_equals, $configure_opts, $make_opts, $install_opts) = split (" ", $line);
+    if (($use_equals ne "Y") && ($use_equals ne "N")) { die "invalid value for use_equals field\n"; }
+
+    if ($force ne "") {
+	if ($force eq $name) {
+	    &buildlib ($name, $tarball, $tardir, $use_equals, $configure_opts, $make_opts, $install_opts);
+	    exit 0;
+	}
+	next;
+    }
+
+    ## check for the C library
+    if ($type eq "lib") { 
+	$found = &checklib ($name, $altnames, $altpaths);
+    } 
+    if ($type eq "bin") { 
+	$found = &checkbin ($name, $altnames, $altpaths);
+    }	
+    if ($type eq "inc") { 
+	$found = &checkinc ($name, $altnames, $altpaths);
+    }	
+
+    if ($found) {
+	print "pass $name ($found)\n";
+	next;
+    } else {
+	print "fail $name\n";
+	push @faillibs, "$name";
+    }	
+
+    if (! $build) { next; }
+    if ($type eq "inc") {
+	print "ERROR: missing header file from library which is supposedly installed\n";
+	next;
+    }
+    &buildlib ($name, $tarball, $tardir, $use_equals, $configure_opts, $make_opts, $install_opts);
+}
+if ($build) { exit 0; }
+print "\n";
+
+if (@faillibs > 0) {
+    print "The following C libraries are missing from your system\n";
+    foreach $name (@faillibs) {
+	print "  $name\n";
+    }
+    print "\n";
+    print "you may install them in your local path by re-running pschecklibs with -build\n";
+} else {
+    print "no C libraries are missing from your system\n";
+}
+exit 0;
+
+sub buildlib {
+    my ($name, $tarball, $tardir, $use_equals, $configure_opts, $make_opts, $install_opts) = @_;
+
+    if ($tarball eq "NONE") {
+	print "ERROR: require tarball for $name\n";
+	exit 1;
+    }
+
+    ## try to build the module from ../../extlibs/$tarball
+
+    # go to extlibs and unpack the tarball
+    chdir "../../extlibs";
+
+    print "extract $name from $tarball\n";
+    vsystem ("tar xvzf $tarball");
+    
+    print "tardir: $tardir\n";
+
+    # enter the directory and build
+    chdir $tardir;
+
+    # build the library using psconfigure, make, make install
+    if ($configure_opts eq "NONE") { 
+	if ($use_equals eq "Y") {
+	    vsystem ("configure --prefix=$prefix");
+	} else {
+	    vsystem ("configure --prefix $prefix");
+	}
+    } else {
+	$configure_opts = join (' ', split (',', $configure_opts));
+	vsystem ("configure --prefix=$prefix $configure_opts");
+    }
+    if ($?) { &failure($name, "failure in configure"); }
+    
+    if ($make_opts eq "NONE") { 
+	vsystem ("make");
+    } else {
+	$make_opts = join (' ', split (',', $make_opts));
+	vsystem ("make $make_opts");
+    }
+    if ($?) { &failure($name, "failure in make"); }
+
+    if ($install_opts eq "NONE") {
+	vsystem ("make install");
+    } else {
+	$install_opts = join (' ', split (',', $install_opts));
+	vsystem ("make install $install_opts");
+    }
+    if ($?) { &failure($name, "failure in make install"); }
+
+    chdir $homedir;
+    return 1;
+}
+
+sub checklib {
+    my $name = $_[0];
+    my $altnames = $_[1];
+    my $altpaths = $_[2];
+    
+    @subdirs = ".";
+    if ($altpaths ne "NONE") {
+	@altpaths = split (',', $altpaths);
+	push @subdirs, @altpaths;
+    }
+    
+    @trynames = ($name);
+    if ($altnames ne "NONE") {
+	@altnames = split (',', $altnames);
+	push @trynames, @altnames;
+    }
+
+    # try each of the possible library names
+    foreach $tryname (@trynames) { 
+	# try each of the library paths, with the default as well as each altpath
+	foreach $topdir ( @libpath ) {
+	    foreach $subdir ( @subdirs ) {
+		if ($subdir eq ".") {
+		    $path = $topdir;
+		} else {
+		    $path = "$topdir/$subdir";
+		}
+		# print "trying $path\n";
+		if (! -e $path) { next; }
+		$libname = "$path/$tryname.a";
+		if (-e $libname) { return $libname; }
+		# print "no $libname\n";
+		$libname = "$path/$tryname.$dlltype";
+		if (-e $libname) { return $libname; }
+		# print "no $libname\n";
+	    }
+	}
+
+	# if we failed to find the basic named library files, try the
+	# versions libraries if we find only a .so.N without a matching
+	# .so, we link this in the installed libdir
+	foreach $topdir ( @libpath ) {
+	    foreach $subdir ( @subdirs ) {
+		if ($subdir eq ".") {
+		    $path = $topdir;
+		} else {
+		    $path = "$topdir/$subdir";
+		}
+		if (! -e $path) { next; }
+		@libnames = <$path/$tryname.$dlltype*>;
+		if (@libnames > 0) { 
+		    $libname = @libnames[-1];
+		    # print "making link to numbered .$dlltype library $libdir/$f.$dlltype\n";
+		    symlink $libname, "$libdir/$f.$dlltype";
+		    if ($?) { exit 1; }
+		    return $libname; 
+		}
+		# print "no $path/$tryname.$dlltype*\n";
+	    }
+	}
+    }
+    return 0;
+}
+
+sub checkbin {
+    my $name = $_[0];
+    my $altnames = $_[1];
+    my $altpaths = $_[2];
+    
+    # XXX drop this for bin?
+    @subdirs = ".";
+    if ($altpaths ne "NONE") {
+	@altpaths = split (',', $altpaths);
+	push @subdirs, @altpaths;
+    }
+    
+    # try each of the library paths, with the default as well as each altpath
+    foreach $topdir ( @binpath ) {
+	foreach $subdir ( @subdirs ) {
+	    if ($subdir eq ".") {
+		$path = $topdir;
+	    } else {
+		$path = "$topdir/$subdir";
+	    }
+	    # print "trying $path\n";
+	    if (! -e $path) { next; }
+	    $binname = "$path/$name";
+	    if (-e $binname) { return $binname; }
+	}
+    }
+    return 0;
+}
+
+sub checkinc {
+    my $name = $_[0];
+    my $altnames = $_[1];
+    my $altpaths = $_[2];
+    
+    @subdirs = ".";
+    if ($altpaths ne "NONE") {
+	@altpaths = split (',', $altpaths);
+	push @subdirs, @altpaths;
+    }
+    
+    # try each of the library paths, with the default as well as each altpath
+    foreach $topdir ( @incpath ) {
+	foreach $subdir ( @subdirs ) {
+	    if ($subdir eq ".") {
+		$path = $topdir;
+	    } else {
+		$path = "$topdir/$subdir";
+	    }
+	    if (! -e $path) { next; }
+	    $incname = "$path/$name";
+	    if (-e $incname) { return $incname; }
+	}
+    }
+
+    return 0;
+}
+
+sub checkarch {
+    # we are going to supplement the global libpath supplied
+    
+    # check the hardware architecture:
+    $sys=`uname -s`; chomp $sys;
+
+    # default values
+    $ranlib = "ranlib";
+    $dlltype = "so";
+
+    if ($sys eq "IRIX64") {
+	$arch = "irix";
+	return;
+    }
+
+    if ($sys eq "SunOS") {
+	$ver=`uname -r | awk '{print substr($1,1,1)}'`;
+	if ($ver == 5) {
+	    $arch = "sol";
+	} else {
+	    $arch="sun4";
+	}
+
+	# sun (at least) seems to need the socket library (linux does not)
+	push @libpath, "/usr/openwin/lib";
+	push @incpath, "/usr/openwin/include";
+
+	# XXX this is a problem
+	print STDERR "need to add system dependent libraries (eg, libsocket, libnsl)\n";
+	exit 1;
+	$needlibs = "$needlibs libsocket libnsl";
+	$ranlib = "touch";
+	return;
+    }
+
+    if ($sys eq "Linux") {
+	$arch = "linux";
+
+	if (-e "/etc/sidious.config") { 
+	    $arch = "sid";
+	    return;
+	}
+
+	$mach = `uname -m`; chomp $mach;
+
+	if ($mach eq "x86_64") {
+	    $arch = "lin64";
+	    unshift @libpath, "/lib64";
+	    unshift @libpath, "/usr/lib64";
+	    unshift @libpath, "/usr/X11R6/lib64";
+	    return;
+	}
+	return;
+    }
+
+    if ($sys eq "Darwin") {
+	$arch = "darwin";
+	$mach = `uname -m`; chomp $mach;
+	if ($mach == "i386") {
+	    $arch="darwin_x86";
+	} else {
+	    unshift @libpath, "/sw/lib";
+	    unshift @incpath, "/sw/include";
+	    unshift @incpath, "/usr/include/sys";
+	    $dlltype = "dylib";
+	}
+	return;
+    }
+
+    if ($sys eq "HP-UX") {
+	$arch = "hpux";
+	return;
+    }
+    
+    print "unknown architecture";
+    exit 1;
+}
+
+sub usage {
+    print STDERR "USAGE: pscheckperl [-version] [-build]\n";
+    exit 2;
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub list_distributions {
+    @list = <$tagsets/*.perl>;
+    foreach $line (@list) {
+	chomp $line;
+	($dist) = $line =~ m|$tagsets/(\S*).perl|;
+	print STDERR "$dist\n";
+    }
+    exit 2;
+}
+
+sub failure {
+    system ("ls");
+    die "problem building $_[0] : $_[1]\n";
+    print "\033]0; ** pschecklibs: failure  ** \007";
+}
+
