#  Copyright (c) 1997-2010
#  Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Darmstadt, Germany)
#  http://www.polymake.de
#
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by the
#  Free Software Foundation; either version 2, or (at your option) any
#  later version: http://www.gnu.org/licenses/gpl.txt.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#-------------------------------------------------------------------------------
#  $Project: polymake $$Id: config_utils.pl 9991 2010-12-12 23:36:28Z gawrilow $

#  utilities needed only in CONFIGURE clauses

use strict;

package Polymake;

###############################################################################################
# "progname", ..., \&check_code => (first_shot, full_path) || (undef, full_path, "error text") || ()
# check_code (optional) : full_path => "error text" || "" if OK.
sub find_program_in_path {
   my $check_code = ref($_[-1]) eq "CODE" && pop;
   my @tried;
   foreach my $progname (@_) {
      my $first_shot=1;
      foreach my $dir (split /:/, $ENV{PATH}) {
	 if (-x (my $full_path="$dir/$progname") && !-d _) {
	    if ($check_code && (my $error=$check_code->($full_path))) {
               @tried=(undef, $full_path, $error);
	    } else {
	       return ($first_shot, $full_path);
            }
	    $first_shot=0;
	 }
      }
   }
   @tried
}
###############################################################################################
#  $variable, "program", ..., { prompt => "Prompt", check => \&code, also => \&code }
sub find_program {
   my $opts= ref($_[-1]) eq "HASH" ? pop : { };
   my @prognames=splice @_, 1;
   my $check_code=$opts->{check};
   my $prompt=($opts->{prompt} ||= @prognames>1 ? "one of the programs (".join(",",@prognames).")" : "the program `@prognames'");
   my $also=$opts->{also};

   if ($_[0] =~ m{^/}) {
      if (-x $_[0] && -f _ && !($check_code && $check_code->($_[0]))) {
         if ($Shell->interactive) {
            print "Please confirm the path to $prompt or enter an alternative location:\n";
            $_[0]=$Shell->enter_program($_[0], $opts);
         }
         return $_[0];
      }
      undef $_[0];
   }

   my ($first_shot, $full_path, $error)=find_program_in_path(defined($_[0]) ? $_[0] : (), @prognames, $check_code ? $check_code : ());
   if (defined($first_shot) or
       defined($also) && defined($full_path=$also->()) &&
       -x $full_path && -f _ && !($check_code && ($error=$check_code->($full_path)))) {
      if ($Shell->interactive) {
         print "Please confirm the path to $prompt or enter an alternative location:\n";
         $_[0]=$Shell->enter_program($full_path, $opts);
         return $_[0] if $_[0] ne $full_path;
      }
      $_[0]= $first_shot ? @prognames>1 ? ($full_path =~ $filename_re)[0] : $prognames[0] : $full_path;
      $full_path;
   } elsif ($Shell->interactive) {
      if (defined $error) {
         print "$prompt found at location $full_path, but did not met the requirements: $error\n",
               "Please enter an alternative location or an empty string to abort.\n";
      } else {
         print "Could not find $prompt anywhere along your PATH.\n",
               "Please enter the full path or an empty string to abort.\n";
      }
      $_[0]=$Shell->enter_program("", $opts);
   } else {
      undef $_[0];
   }
}

###############################################################################################
# $variable, "filename", "dir", ..., { prompt => "Prompt", check => \&code, abort => "text" }
sub find_file_and_confirm {
   my $opts= is_hash($_[-1]) ? pop : { };
   my $prompt=($opts->{prompt} ||= "file $_[1]");
   my $abort=$opts->{abort} || "abort";
   my $check_code=$opts->{check};
   $opts->{check}=sub { -f $_[0] ? !($check_code && &$check_code) : "file $_[0] does not exist" };

   if (defined $_[0]) {
      if (-f $_[0] && !($check_code && $check_code->($_[0]))) {
         if ($Shell->interactive) {
            print "Please confirm the location of $prompt or enter an alternative location:\n";
            $_[0]=$Shell->enter_filename($_[0], $opts);
         }
         return $_[0];
      }
      undef $_[0];
   }

   my $filename=$_[1];
   my $full_path;
   foreach my $dir (@_[2..$#_]) {
      if (-d $dir && -f ($full_path="$dir/$filename") && !($check_code && $check_code->($full_path))) {
         if ($Shell->interactive) {
            print "Please confirm the location of $prompt or enter an alternative location:\n";
            $_[0]=$Shell->enter_filename($full_path, $opts);
         } else {
	    $_[0]=$full_path;
	 }
         return $_[0];
      }
   }
   if ($Shell->interactive) {
      print "Could not find $prompt at any usual place.\n",
            "Please enter the location or an empty string to $abort.\n";
      $_[0]=$Shell->enter_filename("", $opts);
   } else {
      undef $_[0];
   }
}

###############################################################################################
# $variable, "path", ..., { prompt => "Prompt", check => \&code, abort => "text" }
sub find_location {
   my $opts= is_hash($_[-1]) ? pop : { };
   my $prompt=($opts->{prompt} ||= ($_[1] =~ $filename_re)[0] . " directory");
   my $check_code=$opts->{check};

   if (defined $_[0]) {
      if (-d $_[0] && !($check_code && $check_code->($_[0]))) {
         if ($Shell->interactive) {
            print "Please confirm the location of $prompt or enter an alternative location:\n";
            $_[0]=$Shell->enter_filename($_[0], $opts);
         }
         return $_[0];
      }
      undef $_[0];
   }

   foreach my $dir (@_[1..$#_]) {
      if (-d $dir && !($check_code && $check_code->($dir))) {
         if ($Shell->interactive) {
            print "Please confirm the location of $prompt or enter an alternative location:\n";
            $_[0]=$Shell->enter_filename($dir, $opts);
         } else {
	    $_[0]=$dir;
	 }
         return $_[0];
      }
   }
   if ($Shell->interactive) {
      print "Could not find $prompt at any usual place.\n",
            "Please enter the location or an empty string to abort.\n";
      $_[0]=$Shell->enter_filename("", $opts);
   } else {
      undef $_[0];
   }
}

1

# Local Variables:
# cperl-indent-level:3
# End:
