Math::PariBuild - utility functions used during configuration of C.


Math-Pari documentation  | view source Contained in the Math-Pari distribution.

Index


NAME

Top

Math::PariBuild - utility functions used during configuration of Math::Pari.

SYNOPSIS

Top

  use Math::PariBuild;

DESCRIPTION

Top

get_pari_version($dir)

extracts the version of GP/PARI given the build directory $dir; version is read from $$dir/config/version and has the form as in "2.3.1". Returns undef on failure.

pari_formatted_version($dir)

extracts the version of GP/PARI given the build directory $dir; version has the form as in "2003001" for version 2.3.1. Returns the directory name on failure.

find_pari_dir()

Returns the GP/PARI build directory, looking for it as a kid, sibling, or parent of the current directory. [Currently skips versions 2.3.* if possible.]

download_pari()

Using FTP connection, downloads the latest version of GP/PARI, and extracts it. Returns the GP/PARI build directory and the version in the format "2.3.1". [Currently skips versions 2.3.*]

Optional arguments: name of the tar file with GP/PARI source (undef OK), force download.

If the output from FTP session above successfully lists

directories, your installs of Net::FTP and, possibly, LWP

is completely broken. How comes???

EOW warn(<<'EOW'), return unless $ENV{MATHPARI_USEFTP}; FTP session is for debugging only; I'm ignoring the downloaded file. (Set $ENV{MATHPARI_USEFTP} to TRUE to actually use the downloaded file.)

EOW return 'pari-2.1.7.tgz'; }

sub download_pari { my ($srcfile, $force) = (shift, shift); my $host = 'megrez.math.u-bordeaux.fr'; my $dir = '/pub/pari/unix/'; my($ftp, $ua, $base_url);

  print "Did not find GP/PARI build directory around.\n" unless defined $srcfile;

  my @match = ( '((?:.*\/)?pari\W*', '(\d+\.\d+\.\d+).*\.t(?:ar\.)?gz)$' );
  my $match1 = "$match[0]$match[1]";
  my $match  = "$match[0](?!$common::skip_versions)$match[1]";

  my %archive;
  my $match_pari_archive = sub {
    my ($file, $ok23) = (shift, shift);
    return unless $ok23 ? $file =~ /$match1/o : $file =~ /$match/o;
    $file = $1;
    my $version = $2;
    if ($file =~ /alpha/) {
      $archive{alpha}{$version} = $file;
    } elsif ($file =~ /beta/) {
      $archive{beta}{$version} = $file;
    } else {
      $archive{golden}{$version} = $file;
    }
  };

  if ($srcfile and -s $srcfile) {
    die "The FILE supplied via the pari_tgz=$srcfile option did not match /$match/"
      unless $match_pari_archive->($srcfile, 'ok2.3');
  } else {
    if ($force) {
      print "Forced autofetching...\n\n"
    } elsif (not $ENV{AUTOMATED_TESTING} and not $ENV{PERL_MM_USE_DEFAULT}
	     and -t STDIN and (-t STDOUT or -p STDOUT)) { # Interactive
      $| = 1;	# Usually, we run under MakeMaker, so test PERL_MM_USE_DEFAULT
      my $mess = <<EOP;

Do you want to me to fetch GP/PARI automatically?

  (If you do not, you will need to fetch it manually, and/or direct me to
   the directory with GP/PARI source via the command-line option paridir=/dir)

Make sure you have a large scrollback buffer to see the messages, or `tee' the STDOUT/STDERR to a file.

Fetch? (y/n, press Enter) EOP chomp $mess; print "$mess "; my $ans = <STDIN>; if ($ans !~ /y/i) { my ($eA, $eM, $tI, $tO, $tE, $pO, $pE) = (@ENV{ qw(AUTOMATED_TESTING PERL_MM_USE_DEFAULT) }, -t STDIN, -t STDOUT, -t STDERR, -p STDERR, -p STDOUT); defined() ? $_ = "'$_'" : $_ = '<undef>' for $eA, $eM; print <<EOP; # Is AUTOMATED_TESTING ALWAYS defined on smoke???

Well, as you wish...

  [ to debug Smoke Tests: AUTOMATED_TESTING=$eA PERL_MM_USE_DEFAULT=$eM
        -t STDIN/STDOUT/ERR = $tI/$tO/$tE		-p STDOUT/ERR = $pO/$pE ]

EOP print manual_download_instructions(); return; } } else { print "Non-interactive session, autofetching...\n\n" }

    $base_url = "ftp://$host$dir";
    my @extra_chdir = qw(OLD);
    print "Getting GP/PARI from $base_url\n";

    eval {
      require Net::FTP;

      $ftp = Net::FTP->new($host) or die "Cannot create FTP object: $!";
      $ftp->login("anonymous","Math::Pari@")
        or die "Cannot login anonymously (",$ftp->message(),"): $!";
      my $c = 0;
      my @Extra = @extra_chdir;
      while (not $c) {
	$ftp->cwd($dir) or die "Cannot cwd (",$ftp->message(),"): $!";
	$ftp->binary() or die "Cannot switch to binary (",$ftp->message(),"): $!";
	my @lst = $ftp->ls();
	@lst or ($ftp->pasv() and @lst = $ftp->ls()) or die "Cannot list (",$ftp->message(),"): $!";
	#print "list = `@lst'\n";

	%archive = ();
	for my $file (@lst) {
	  $c++ if $match_pari_archive->($file);
	}
	unless ($c) {
	  die "Did not find any file matching /$match/ via FTP\n\n"
	    . manual_download_instructions() unless @Extra;
	  $dir = shift @Extra;
	  print "Not in this directory, now chdir('$dir')...\n";
	}
      }
    };
    if ($@) {
      undef $ftp;
      warn "$@\nCan't fetch file with Net::FTP, now trying with LWP::UserAgent...\n";
      # second try with LWP::UserAgent
      eval { require LWP::UserAgent; require HTML::LinkExtor }
        or die "You do not have LWP::UserAgent and/or HTML::LinkExtor installed, cannot download, exiting...\n\n" . manual_download_instructions();
      my $c = 0;
      my @Extra = @extra_chdir;
      while (not $c) {
	$ua = LWP::UserAgent->new;
	$ua->env_proxy;
	my $req = HTTP::Request->new(GET => $base_url);
	my $resp = $ua->request($req);
	$resp->is_success
	  or die "Can't fetch directory listing from $base_url: " . $resp->as_string;
	%archive = ();
	if ($resp->content_type eq 'text/html') {
	  my $p = HTML::LinkExtor->new;
	  $p->parse($resp->content);
	  for my $link ($p->links) {
	    my($tag, %attr) = @$link;
	    next if $tag ne 'a';
	    $c++ if $match_pari_archive->($attr{href});
	  }
	} else {
	  foreach my $file (split /\n/, $resp->content) {
	    $c++ if $match_pari_archive->($file);
	  }
	}
	unless ($c) {
	  unless (@Extra) {
	    warn debug_no_response($resp)
	      . "Did not find any file matching /$match/ via FTP.\n\n";
	    my $f = ll_ftp or die manual_download_instructions();
	    return download_pari($f);
	  }
	  my $dir = shift @Extra;
	  $base_url .= "$dir/";
	  print "Not in this directory, trying `$base_url'...\n";
	}
      }
    }
  }

  sub fmt_version {sprintf "%03d%03d%03d", split /\./, shift}

  my ($type, %have, %types, $best, %latest_version, %latest_file);
  for $type (qw(alpha beta golden)) {
    if ($archive{$type}) {
      $have{$type}++;
      $best = $type;
      my @files = keys %{$archive{$type}};
      print "Available $type versions: `@files'\n";
      $latest_version{$type} = (sort {fmt_version($a) cmp fmt_version($b)}
				keys %{$archive{$type}})[-1];
      $latest_file{$type} = $archive{$type}{$latest_version{$type}};
      print qq(Latest supported $type is `$latest_file{$type}'\n);
    }
  }

  # Special-case v2.0.14
  if (!$archive{golden} and $latest_version{beta} eq '2.0.11'
      and $latest_version{alpha} eq '2.0.14') {
    $best = 'alpha';		# It is tested!
  }

  undef $dir;
  my $version;
  if ($best) {
    my $file = $latest_file{$best};
    $version = $latest_version{$best};
    print qq(Picking $best version $version, file $file\n);
    if (-f $file) {
      print qq(Well, I already have it, using the disk copy...\n);
    } else {
      print qq(Downloading `$base_url$file'...\n);
      if ($ftp) {
        $ftp->get($file) or die "Cannot get via FTP (",$ftp->message(),"): $!";
	$ftp->quit or warn "Warning: cannot quit FTP: ", $ftp->message();
      } else {
	my $req = HTTP::Request->new(GET => "$base_url$file");
	my $resp = $ua->request($req);
	$resp->is_success
	  or die "Can't fetch $base_url/$file: " . $resp->as_string;
	my $base = basename($file);
	open(F, ">$base") or die "Can't write to $base: $!";
	binmode F or die "Can't binmode(): $!";
	print F $resp->content;
	close F;
      }
      print qq(Downloaded...\n);
    }
    print qq(Extracting...\n);
    my $zcat = "gzip -dc";	# zcat may be the old .Z-extractor
    print  "$zcat $file | tar -xvf -\n";
    system "$zcat $file | tar -xvf -"
      and do {
	  print "Can't un-targz PARI: \$!=$!, exitcode=$?.\n";
	  my @cmd = ($^X, qw(-MArchive::Tar -wle),
		     'Archive::Tar->new(shift)->extract()', $file);
	  print '  Now retry with "', join('" "', @cmd), "\"\n";
	  system @cmd and die "Can't un-targz PARI: \$!=$!, exitcode=$?.\n"
        };
    ($dir = $file) =~ s,(?:.*[\\/])?(.*)\.t(ar\.)?gz$,$1,
      or die "malformed name `$file'";
    -d $dir or die "Did not find directory $dir!";
  }
  return ($dir, $version);
}

patches_for($version)

Returns patches appropriate for GP/PARI version $version (formatted as in 2.2.2).

patch_pari($dir [, $version])

Applies known necessary fixes to GP/PARI build directory $dir if needed.

Returns empty if no patching is needed, otherwise the string encoding return values of patch commands.

download_and_patch_pari()

Using FTP connection, downloads the latest version of GP/PARI, extracts it, and applies known necessary fixes if needed. Returns the GP/PARI build directory (in scalar context), otherwise the directory and the result of patching.

Same optional arguments as for download_pari().

make_pod($podfile, $gphelp_opt, $dir)

Makes POD documentation for functions in the PARI library. Converts the TeX file found in GP/PARI build directory $dir to POD using the given options for gphelp.

build_tests($dir)

Converts GP/PARI test files in GP/PARI build directory $dir to Perl test suite.

find_paricfg($dir)

Finds suitable (?) files paricfg.h in GP/PARI build directory $dir.

find_paricfg($dir, $do_configure)

Finds suitable (?) files paricfg.h in GP/PARI build directory $dir. If $do_configure is true, runs GP/PARI's Configure script to build one. Returns FALSE if paricfg.h needs to be build by Perl.

write_paricfg($formatted_version)

Writes PARI configuration file libPARI/paricfg.h. Returns hash with options found during the scan of the header files.

build_paricfg($dir, $do_configure)

Builds libPARI/paricfg.h either ourselves, or by looking for it in GP/PARI build directory $dir - and running GP/PARI's Configure script if needed. Returns hash with options found during the scan of the header files.

find_machine_architecture()

Returns the type of the processor of the current machine.

ep_codes_from_file($filename,%hash,%names)

Adds to the %hash the string interface descriptions corresponding to the numeric codes use in the file's entree array. %hash is indexed by by the numeric codes; the value are references to arrays with the corresponding string interface descriptions.

Adds to %names the list of name => code values.

ep_hash_report(%hash, %names, $fh)

Writes to $fh the diagnostic about problemes with the string interface descriptions corresponding to the numeric codes. If $fh is false, returns TRUE if no problem were found.

ep_in_version($version)

Updates the list of codes for the given version of GP/PARI (formatted as in 2002002).

code_C_translator()

Returns string for C code to translate code string to the interface number.

Due to a bug in C_constant(), need to translate '' to 9900 by hand outside of this subroutine.


Math-Pari documentation  | view source Contained in the Math-Pari distribution.