Skip to content

Instantly share code, notes, and snippets.

@gugod
Created May 9, 2011 12:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save gugod/962406 to your computer and use it in GitHub Desktop.
Save gugod/962406 to your computer and use it in GitHub Desktop.
patchperl packed by fatpacker
all:
fatpack trace `which patchperl`
fatpack packlists-for `cat fatpacker.trace` >packlists
fatpack tree `cat packlists`
(echo "#!/usr/bin/env perl"; fatpack file; cat `which patchperl`) > patchperl
chmod +x patchperl
#!/usr/bin/env perl
# This chunk of stuff was generated by App::FatPacker. To find the original
# file's code, look for the end of this BEGIN block or the string 'FATPACK'
BEGIN {
my %fatpacked;
$fatpacked{"Devel/PatchPerl.pm"} = <<'DEVEL_PATCHPERL';
package Devel::PatchPerl;
{
$Devel::PatchPerl::VERSION = '0.52';
}
# ABSTRACT: Patch perl source a la Devel::PPPort's buildperl.pl
use strict;
use warnings;
use File::pushd qw[pushd];
use File::Spec;
use IO::File;
use IPC::Cmd qw[can_run run];
use Devel::PatchPerl::Hints qw[hint_file];
use vars qw[@ISA @EXPORT_OK];
@ISA = qw(Exporter);
@EXPORT_OK = qw(patch_source);
my $patch_exe = can_run('patch');
my @patch = (
{
perl => [
qr/^5\.00[01234]/,
qw/
5.005
5.005_01
5.005_02
5.005_03
/,
],
subs => [
[ \&_patch_db, 1 ],
],
},
{
perl => [
qw/
5.6.0
5.6.1
5.7.0
5.7.1
5.7.2
5.7.3
5.8.0
/,
],
subs => [
[ \&_patch_db, 3 ],
],
},
{
perl => [
qr/^5\.004_0[1234]$/,
],
subs => [
[ \&_patch_doio ],
],
},
{
perl => [
qw/
5.005
5.005_01
5.005_02
/,
],
subs => [
[ \&_patch_sysv, old_format => 1 ],
],
},
{
perl => [
qw/
5.005_03
5.005_04
/,
qr/^5\.6\.[0-2]$/,
qr/^5\.7\.[0-3]$/,
qr/^5\.8\.[0-8]$/,
qr/^5\.9\.[0-5]$/
],
subs => [
[ \&_patch_sysv, old_format => 0 ],
],
},
{
perl => [
qr/^5\.004_05$/,
qr/^5\.005(?:_0[1-4])?$/,
qr/^5\.6\.[01]$/,
],
subs => [
[ \&_patch_configure ],
[ \&_patch_makedepend_lc ],
],
},
{
perl => [
'5.8.0',
],
subs => [
[ \&_patch_makedepend_lc ],
],
},
{
perl => [
qr/.*/,
],
subs => [
[ \&_patch_hints ],
],
},
{
perl => [
qr/^5\.6\.[0-2]$/,
qr/^5\.7\.[0-3]$/,
qr/^5\.8\.[0-8]$/,
],
subs => [
[ \&_patch_makedepend_SH ],
],
},
{
perl => [
qr/^5\.1[0-2]/,
],
subs => [
[ \&_patch_archive_tar_tests ],
[ \&_patch_odbm_file_hints_linux ],
],
},
);
sub patch_source {
my $vers = shift;
$vers = shift if eval { $vers->isa(__PACKAGE__) };
my $source = shift || '.';
if ( !$vers ) {
$vers = _determine_version($source);
if ( $vers ) {
warn "Auto-guessed '$vers'\n";
}
else {
die "You didn't provide a perl version and I don't appear to be in a perl source tree\n";
}
}
$source = File::Spec->rel2abs($source);
{
my $dir = pushd( $source );
for my $p ( grep { _is( $_->{perl}, $vers ) } @patch ) {
for my $s (@{$p->{subs}}) {
my($sub, @args) = @$s;
push @args, $vers unless scalar @args;
$sub->(@args);
}
}
}
}
sub _is
{
my($s1, $s2) = @_;
defined $s1 != defined $s2 and return 0;
ref $s2 and ($s1, $s2) = ($s2, $s1);
if (ref $s1) {
if (ref $s1 eq 'ARRAY') {
_is($_, $s2) and return 1 for @$s1;
return 0;
}
return $s2 =~ $s1;
}
return $s1 eq $s2;
}
sub _patch
{
my($patch) = @_;
print "patching $_\n" for $patch =~ /^\+{3}\s+(\S+)/gm;
my $diff = 'tmp.diff';
_write_or_die($diff, $patch);
die "No patch utility found\n" unless $patch_exe;
_run_or_die("$patch_exe -f -s -p0 <$diff");
unlink $diff or die "unlink $diff: $!\n";
}
sub _write_or_die
{
my($file, $data) = @_;
my $fh = IO::File->new(">$file") or die "$file: $!\n";
$fh->print($data);
}
sub _run_or_die
{
# print "[running @_]\n";
die unless scalar run( command => [ @_ ], verbose => 1 );
}
sub _determine_version {
my ($source) = @_;
my $patchlevel_h = File::Spec->catfile($source, 'patchlevel.h');
return unless -e $patchlevel_h;
my $version;
{
my %defines;
open my $fh, '<', $patchlevel_h;
my @vers;
while (<$fh>) {
chomp;
next unless /^#define/;
my ($foo,$bar) = ( split /\s+/ )[1,2];
$defines{$foo} = $bar;
}
if ( my @wotsits = grep { defined $defines{$_} } qw(PERL_REVISION PERL_VERSION PERL_API_SUBVERSION) ) {
$version = join '.', map { $defines{$_} } @wotsits;
}
else {
$version = sprintf '5.%03d_%02d', map { $defines{$_} } qw(PATCHLEVEL SUBVERSION);
}
}
return $version;
}
sub _patch_hints {
return unless my ($file,$data) = hint_file();
my $path = File::Spec->catfile( 'hints', $file );
chmod 0644, $path or die "$!\n";
open my $fh, '>', $path or die "$!\n";
print $fh $data;
close $fh;
return 1;
}
sub _patch_db
{
my $ver = shift;
print "patching ext/DB_File/DB_File.xs\n";
_run_or_die($^X, '-pi.bak', '-e', "s/<db.h>/<db$ver\\/db.h>/", 'ext/DB_File/DB_File.xs');
unlink 'ext/DB_File/DB_File.xs.bak' if -e 'ext/DB_File/DB_File.xs.bak';
}
sub _patch_doio
{
_patch(<<'END');
--- doio.c.org 2004-06-07 23:14:45.000000000 +0200
+++ doio.c 2003-11-04 08:03:03.000000000 +0100
@@ -75,6 +75,16 @@
# endif
#endif
+#if _SEM_SEMUN_UNDEFINED
+union semun
+{
+ int val;
+ struct semid_ds *buf;
+ unsigned short int *array;
+ struct seminfo *__buf;
+};
+#endif
+
bool
do_open(gv,name,len,as_raw,rawmode,rawperm,supplied_fp)
GV *gv;
END
}
sub _patch_sysv
{
my %opt = @_;
# check if patching is required
return if $^O ne 'linux' or -f '/usr/include/asm/page.h';
if ($opt{old_format}) {
_patch(<<'END');
--- ext/IPC/SysV/SysV.xs.org 1998-07-20 10:20:07.000000000 +0200
+++ ext/IPC/SysV/SysV.xs 2007-08-12 10:51:06.000000000 +0200
@@ -3,9 +3,6 @@
#include "XSUB.h"
#include <sys/types.h>
-#ifdef __linux__
-#include <asm/page.h>
-#endif
#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
#include <sys/ipc.h>
#ifdef HAS_MSG
END
}
else {
_patch(<<'END');
--- ext/IPC/SysV/SysV.xs.org 2007-08-11 00:12:46.000000000 +0200
+++ ext/IPC/SysV/SysV.xs 2007-08-11 00:10:51.000000000 +0200
@@ -3,9 +3,6 @@
#include "XSUB.h"
#include <sys/types.h>
-#ifdef __linux__
-# include <asm/page.h>
-#endif
#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
#ifndef HAS_SEM
# include <sys/ipc.h>
END
}
}
sub _patch_configure
{
_patch(<<'END');
--- Configure
+++ Configure
@@ -3380,6 +3380,18 @@
test "X$gfpthkeep" != Xy && gfpth=""
EOSC
+# gcc 3.1 complains about adding -Idirectories that it already knows about,
+# so we will take those off from locincpth.
+case "$gccversion" in
+3*)
+ echo "main(){}">try.c
+ for incdir in `$cc -v -c try.c 2>&1 | \
+ sed '1,/^#include <\.\.\.>/d;/^End of search list/,$d;s/^ //'` ; do
+ locincpth=`echo $locincpth | sed s!$incdir!!`
+ done
+ $rm -f try try.*
+esac
+
: What should the include directory be ?
echo " "
$echo $n "Hmm... $c"
END
}
sub _patch_makedepend_lc
{
_patch(<<'END');
--- makedepend.SH
+++ makedepend.SH
@@ -58,6 +58,10 @@ case $PERL_CONFIG_SH in
;;
esac
+# Avoid localized gcc/cc messages
+LC_ALL=C
+export LC_ALL
+
# We need .. when we are in the x2p directory if we are using the
# cppstdin wrapper script.
# Put .. and . first so that we pick up the present cppstdin, not
END
}
sub _patch_makedepend_SH
{
my $perl = shift;
SWITCH: {
# If 5.6.0
if ( $perl eq '5.6.0' ) {
_patch(<<'BADGER');
--- makedepend.SH.org 2000-03-02 18:12:26.000000000 +0000
+++ makedepend.SH 2010-09-01 10:13:37.000000000 +0100
@@ -1,5 +1,5 @@
#! /bin/sh
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -29,6 +29,13 @@
!GROK!THIS!
$spitshell >>makedepend <<'!NO!SUBS!'
+if test -d .depending; then
+ echo "$0: Already running, exiting."
+ exit 0
+fi
+
+mkdir .depending
+
# This script should be called with
# sh ./makedepend MAKE=$(MAKE)
case "$1" in
@@ -37,7 +44,7 @@
export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh \$0; kill \$\$)
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -51,6 +58,11 @@
;;
esac
+# Avoid localized gcc messages
+case "$ccname" in
+ gcc) LC_ALL=C ; export LC_ALL ;;
+esac
+
# We need .. when we are in the x2p directory if we are using the
# cppstdin wrapper script.
# Put .. and . first so that we pick up the present cppstdin, not
@@ -58,6 +70,10 @@
PATH=".$path_sep..$path_sep$PATH"
export PATH
+case "$osname" in
+amigaos) cat=/bin/cat ;; # must be absolute
+esac
+
$cat /dev/null >.deptmp
$rm -f *.c.c c/*.c.c
if test -f Makefile; then
@@ -67,7 +83,6 @@
# to be out of date. I don't know if OS/2 has touch, so do this:
case "$osname" in
os2) ;;
- netbsd) ;;
*) $touch $firstmakefile ;;
esac
fi
@@ -99,25 +114,20 @@
$echo *.c | $tr ' ' $trnl | $egrep -v '\*' >.clist)
for file in `$cat .clist`; do
# for file in `cat /dev/null`; do
- if [ "$osname" = uwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g"
- else
- if [ "$osname" = os2 ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$archname" = cygwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- uwinfix=
- fi
- fi
- fi
+ case "$osname" in
+ uwin) uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g" ;;
+ os2) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ cygwin) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ posix-bc) uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/" ;;
+ vos) uwinfix="-e s/\#/\\\#/" ;;
+ *) uwinfix="" ;;
+ esac
case "$file" in
*.c) filebase=`basename $file .c` ;;
*.y) filebase=`basename $file .y` ;;
esac
case "$file" in
- */*) finc="-I`echo $file | sed 's#/[^/]*$##`" ;;
+ */*) finc="-I`echo $file | sed 's#/[^/]*$##'`" ;;
*) finc= ;;
esac
$echo "Finding dependencies for $filebase$_o."
@@ -130,22 +140,45 @@
-e 's|\\$||' \
-e p \
-e '}' ) >UU/$file.c
+
if [ "$osname" = os390 -a "$file" = perly.c ]; then
$echo '#endif' >>UU/$file.c
fi
- $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
- $sed \
- -e '1d' \
- -e '/^#.*<stdin>/d' \
- -e '/^#.*"-"/d' \
- -e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
- -e 's/^[ ]*#[ ]*line/#/' \
- -e '/^# *[0-9][0-9]* *[".\/]/!d' \
- -e 's/^.*"\(.*\)".*$/'$filebase'\$(OBJ_EXT): \1/' \
- -e 's/^# *[0-9][0-9]* \(.*\)$/'$filebase'\$(OBJ_EXT): \1/' \
- -e 's|: \./|: |' \
- -e 's|\.c\.c|.c|' $uwinfix | \
- $uniq | $sort | $uniq >> .deptmp
+
+ if [ "$osname" = os390 ]; then
+ $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
+ $sed \
+ -e '/^#.*<stdin>/d' \
+ -e '/^#.*"-"/d' \
+ -e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
+ -e 's/^[ ]*#[ ]*line/#/' \
+ -e '/^# *[0-9][0-9]* *[".\/]/!d' \
+ -e 's/^.*"\(.*\)".*$/'$filebase'\$(OBJ_EXT): \1/' \
+ -e 's/^# *[0-9][0-9]* \(.*\)$/'$filebase'\$(OBJ_EXT): \1/' \
+ -e 's|: \./|: |' \
+ -e 's|\.c\.c|.c|' $uwinfix | \
+ $uniq | $sort | $uniq >> .deptmp
+ else
+ $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c >.cout 2>.cerr
+ $sed \
+ -e '1d' \
+ -e '/^#.*<stdin>/d' \
+ -e '/^#.*<builtin>/d' \
+ -e '/^#.*<built-in>/d' \
+ -e '/^#.*<command line>/d' \
+ -e '/^#.*<command-line>/d' \
+ -e '/^#.*"-"/d' \
+ -e '/^#.*"\/.*\/"/d' \
+ -e '/: file path prefix .* never used$/d' \
+ -e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
+ -e 's/^[ ]*#[ ]*line/#/' \
+ -e '/^# *[0-9][0-9]* *[".\/]/!d' \
+ -e 's/^.*"\(.*\)".*$/'$filebase'\$(OBJ_EXT): \1/' \
+ -e 's/^# *[0-9][0-9]* \(.*\)$/'$filebase'\$(OBJ_EXT): \1/' \
+ -e 's|: \./|: |' \
+ -e 's|\.c\.c|.c|' $uwinfix .cout .cerr| \
+ $uniq | $sort | $uniq >> .deptmp
+ fi
done
$sed <$mf >$mf.new -e '1,/^# AUTOMATICALLY/!d'
@@ -177,6 +210,10 @@
$echo "Updating $mf..."
$echo "# If this runs make out of memory, delete /usr/include lines." \
>> $mf.new
+ if [ "$osname" = vos ]; then
+ $sed 's|.incl.c|.h|' .deptmp >.deptmp.vos
+ mv -f .deptmp.vos .deptmp
+ fi
$sed 's|^\(.*\$(OBJ_EXT):\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
>>$mf.new
else
@@ -208,7 +245,8 @@
$cp $mf.new $mf
$rm $mf.new
$echo "# WARNING: Put nothing here or make depend will gobble it up!" >> $mf
-$rm -rf .deptmp UU .shlist .clist .hlist .hsed
+$rm -rf .deptmp UU .shlist .clist .hlist .hsed .cout .cerr
+rmdir .depending
!NO!SUBS!
$eunicefix makedepend
BADGER
last SWITCH;
}
# If 5.6.1
if ( $perl eq '5.6.1' ) {
_patch(<<'BADGER');
--- makedepend.SH.org 2001-03-19 07:33:17.000000000 +0000
+++ makedepend.SH 2010-09-01 10:14:47.000000000 +0100
@@ -1,5 +1,5 @@
#! /bin/sh
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -29,6 +29,13 @@
!GROK!THIS!
$spitshell >>makedepend <<'!NO!SUBS!'
+if test -d .depending; then
+ echo "$0: Already running, exiting."
+ exit 0
+fi
+
+mkdir .depending
+
# This script should be called with
# sh ./makedepend MAKE=$(MAKE)
case "$1" in
@@ -37,7 +44,7 @@
export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh \$0; kill \$\$)
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -51,6 +58,11 @@
;;
esac
+# Avoid localized gcc messages
+case "$ccname" in
+ gcc) LC_ALL=C ; export LC_ALL ;;
+esac
+
# We need .. when we are in the x2p directory if we are using the
# cppstdin wrapper script.
# Put .. and . first so that we pick up the present cppstdin, not
@@ -58,6 +70,10 @@
PATH=".$path_sep..$path_sep$PATH"
export PATH
+case "$osname" in
+amigaos) cat=/bin/cat ;; # must be absolute
+esac
+
$cat /dev/null >.deptmp
$rm -f *.c.c c/*.c.c
if test -f Makefile; then
@@ -67,7 +83,6 @@
# to be out of date. I don't know if OS/2 has touch, so do this:
case "$osname" in
os2) ;;
- netbsd) ;;
*) $touch $firstmakefile ;;
esac
fi
@@ -99,29 +114,20 @@
$echo *.c | $tr ' ' $trnl | $egrep -v '\*' >.clist)
for file in `$cat .clist`; do
# for file in `cat /dev/null`; do
- if [ "$osname" = uwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g"
- else
- if [ "$osname" = os2 ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$archname" = cygwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$osname" = posix-bc ]; then
- uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/"
- else
- uwinfix=
- fi
- fi
- fi
- fi
+ case "$osname" in
+ uwin) uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g" ;;
+ os2) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ cygwin) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ posix-bc) uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/" ;;
+ vos) uwinfix="-e s/\#/\\\#/" ;;
+ *) uwinfix="" ;;
+ esac
case "$file" in
*.c) filebase=`basename $file .c` ;;
*.y) filebase=`basename $file .y` ;;
esac
case "$file" in
- */*) finc="-I`echo $file | sed 's#/[^/]*$##`" ;;
+ */*) finc="-I`echo $file | sed 's#/[^/]*$##'`" ;;
*) finc= ;;
esac
$echo "Finding dependencies for $filebase$_o."
@@ -134,10 +140,12 @@
-e 's|\\$||' \
-e p \
-e '}' ) >UU/$file.c
+
+ if [ "$osname" = os390 -a "$file" = perly.c ]; then
+ $echo '#endif' >>UU/$file.c
+ fi
+
if [ "$osname" = os390 ]; then
- if [ "$file" = perly.c ]; then
- $echo '#endif' >>UU/$file.c
- fi
$cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
$sed \
-e '/^#.*<stdin>/d' \
@@ -151,18 +159,24 @@
-e 's|\.c\.c|.c|' $uwinfix | \
$uniq | $sort | $uniq >> .deptmp
else
- $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
+ $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c >.cout 2>.cerr
$sed \
-e '1d' \
-e '/^#.*<stdin>/d' \
+ -e '/^#.*<builtin>/d' \
+ -e '/^#.*<built-in>/d' \
+ -e '/^#.*<command line>/d' \
+ -e '/^#.*<command-line>/d' \
-e '/^#.*"-"/d' \
+ -e '/^#.*"\/.*\/"/d' \
+ -e '/: file path prefix .* never used$/d' \
-e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
-e 's/^[ ]*#[ ]*line/#/' \
-e '/^# *[0-9][0-9]* *[".\/]/!d' \
-e 's/^.*"\(.*\)".*$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's/^# *[0-9][0-9]* \(.*\)$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's|: \./|: |' \
- -e 's|\.c\.c|.c|' $uwinfix | \
+ -e 's|\.c\.c|.c|' $uwinfix .cout .cerr| \
$uniq | $sort | $uniq >> .deptmp
fi
done
@@ -196,6 +210,10 @@
$echo "Updating $mf..."
$echo "# If this runs make out of memory, delete /usr/include lines." \
>> $mf.new
+ if [ "$osname" = vos ]; then
+ $sed 's|.incl.c|.h|' .deptmp >.deptmp.vos
+ mv -f .deptmp.vos .deptmp
+ fi
$sed 's|^\(.*\$(OBJ_EXT):\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
>>$mf.new
else
@@ -227,7 +245,8 @@
$cp $mf.new $mf
$rm $mf.new
$echo "# WARNING: Put nothing here or make depend will gobble it up!" >> $mf
-$rm -rf .deptmp UU .shlist .clist .hlist .hsed
+$rm -rf .deptmp UU .shlist .clist .hlist .hsed .cout .cerr
+rmdir .depending
!NO!SUBS!
$eunicefix makedepend
BADGER
last SWITCH;
}
# If 5.6.2
if ( $perl eq '5.6.2' ) {
_patch(<<'BADGER');
--- makedepend.SH.org 2003-07-30 23:46:59.000000000 +0100
+++ makedepend.SH 2010-09-01 10:15:47.000000000 +0100
@@ -1,5 +1,5 @@
#! /bin/sh
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -29,6 +29,13 @@
!GROK!THIS!
$spitshell >>makedepend <<'!NO!SUBS!'
+if test -d .depending; then
+ echo "$0: Already running, exiting."
+ exit 0
+fi
+
+mkdir .depending
+
# This script should be called with
# sh ./makedepend MAKE=$(MAKE)
case "$1" in
@@ -37,7 +44,7 @@
export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh \$0; kill \$\$)
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -63,6 +70,10 @@
PATH=".$path_sep..$path_sep$PATH"
export PATH
+case "$osname" in
+amigaos) cat=/bin/cat ;; # must be absolute
+esac
+
$cat /dev/null >.deptmp
$rm -f *.c.c c/*.c.c
if test -f Makefile; then
@@ -72,7 +83,6 @@
# to be out of date. I don't know if OS/2 has touch, so do this:
case "$osname" in
os2) ;;
- netbsd) ;;
*) $touch $firstmakefile ;;
esac
fi
@@ -104,29 +114,20 @@
$echo *.c | $tr ' ' $trnl | $egrep -v '\*' >.clist)
for file in `$cat .clist`; do
# for file in `cat /dev/null`; do
- if [ "$osname" = uwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g"
- else
- if [ "$osname" = os2 ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$archname" = cygwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$osname" = posix-bc ]; then
- uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/"
- else
- uwinfix=
- fi
- fi
- fi
- fi
+ case "$osname" in
+ uwin) uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g" ;;
+ os2) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ cygwin) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ posix-bc) uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/" ;;
+ vos) uwinfix="-e s/\#/\\\#/" ;;
+ *) uwinfix="" ;;
+ esac
case "$file" in
*.c) filebase=`basename $file .c` ;;
*.y) filebase=`basename $file .y` ;;
esac
case "$file" in
- */*) finc="-I`echo $file | sed 's#/[^/]*$##`" ;;
+ */*) finc="-I`echo $file | sed 's#/[^/]*$##'`" ;;
*) finc= ;;
esac
$echo "Finding dependencies for $filebase$_o."
@@ -139,10 +140,12 @@
-e 's|\\$||' \
-e p \
-e '}' ) >UU/$file.c
+
+ if [ "$osname" = os390 -a "$file" = perly.c ]; then
+ $echo '#endif' >>UU/$file.c
+ fi
+
if [ "$osname" = os390 ]; then
- if [ "$file" = perly.c ]; then
- $echo '#endif' >>UU/$file.c
- fi
$cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
$sed \
-e '/^#.*<stdin>/d' \
@@ -156,21 +159,24 @@
-e 's|\.c\.c|.c|' $uwinfix | \
$uniq | $sort | $uniq >> .deptmp
else
- $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
+ $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c >.cout 2>.cerr
$sed \
-e '1d' \
-e '/^#.*<stdin>/d' \
- -e '/^#.*<builtin>/d' \
- -e '/^#.*<built-in>/d' \
- -e '/^#.*<command line>/d' \
+ -e '/^#.*<builtin>/d' \
+ -e '/^#.*<built-in>/d' \
+ -e '/^#.*<command line>/d' \
+ -e '/^#.*<command-line>/d' \
-e '/^#.*"-"/d' \
+ -e '/^#.*"\/.*\/"/d' \
+ -e '/: file path prefix .* never used$/d' \
-e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
-e 's/^[ ]*#[ ]*line/#/' \
-e '/^# *[0-9][0-9]* *[".\/]/!d' \
-e 's/^.*"\(.*\)".*$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's/^# *[0-9][0-9]* \(.*\)$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's|: \./|: |' \
- -e 's|\.c\.c|.c|' $uwinfix | \
+ -e 's|\.c\.c|.c|' $uwinfix .cout .cerr| \
$uniq | $sort | $uniq >> .deptmp
fi
done
@@ -204,6 +210,10 @@
$echo "Updating $mf..."
$echo "# If this runs make out of memory, delete /usr/include lines." \
>> $mf.new
+ if [ "$osname" = vos ]; then
+ $sed 's|.incl.c|.h|' .deptmp >.deptmp.vos
+ mv -f .deptmp.vos .deptmp
+ fi
$sed 's|^\(.*\$(OBJ_EXT):\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
>>$mf.new
else
@@ -235,7 +245,8 @@
$cp $mf.new $mf
$rm $mf.new
$echo "# WARNING: Put nothing here or make depend will gobble it up!" >> $mf
-$rm -rf .deptmp UU .shlist .clist .hlist .hsed
+$rm -rf .deptmp UU .shlist .clist .hlist .hsed .cout .cerr
+rmdir .depending
!NO!SUBS!
$eunicefix makedepend
BADGER
last SWITCH;
}
# If 5.7.0
if ( $perl eq '5.7.0' ) {
_patch(<<'BADGER');
--- makedepend.SH.org 2000-08-13 19:35:04.000000000 +0100
+++ makedepend.SH 2010-09-01 10:47:14.000000000 +0100
@@ -1,5 +1,5 @@
#! /bin/sh
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -29,6 +29,13 @@
!GROK!THIS!
$spitshell >>makedepend <<'!NO!SUBS!'
+if test -d .depending; then
+ echo "$0: Already running, exiting."
+ exit 0
+fi
+
+mkdir .depending
+
# This script should be called with
# sh ./makedepend MAKE=$(MAKE)
case "$1" in
@@ -37,7 +44,7 @@
export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh \$0; kill \$\$)
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -51,6 +58,11 @@
;;
esac
+# Avoid localized gcc messages
+case "$ccname" in
+ gcc) LC_ALL=C ; export LC_ALL ;;
+esac
+
# We need .. when we are in the x2p directory if we are using the
# cppstdin wrapper script.
# Put .. and . first so that we pick up the present cppstdin, not
@@ -58,6 +70,10 @@
PATH=".$path_sep..$path_sep$PATH"
export PATH
+case "$osname" in
+amigaos) cat=/bin/cat ;; # must be absolute
+esac
+
$cat /dev/null >.deptmp
$rm -f *.c.c c/*.c.c
if test -f Makefile; then
@@ -67,7 +83,6 @@
# to be out of date. I don't know if OS/2 has touch, so do this:
case "$osname" in
os2) ;;
- netbsd) ;;
*) $touch $firstmakefile ;;
esac
fi
@@ -99,25 +114,20 @@
$echo *.c | $tr ' ' $trnl | $egrep -v '\*' >.clist)
for file in `$cat .clist`; do
# for file in `cat /dev/null`; do
- if [ "$osname" = uwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g"
- else
- if [ "$osname" = os2 ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$archname" = cygwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- uwinfix=
- fi
- fi
- fi
+ case "$osname" in
+ uwin) uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g" ;;
+ os2) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ cygwin) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ posix-bc) uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/" ;;
+ vos) uwinfix="-e s/\#/\\\#/" ;;
+ *) uwinfix="" ;;
+ esac
case "$file" in
*.c) filebase=`basename $file .c` ;;
*.y) filebase=`basename $file .y` ;;
esac
case "$file" in
- */*) finc="-I`echo $file | sed 's#/[^/]*$##`" ;;
+ */*) finc="-I`echo $file | sed 's#/[^/]*$##'`" ;;
*) finc= ;;
esac
$echo "Finding dependencies for $filebase$_o."
@@ -130,10 +140,12 @@
-e 's|\\$||' \
-e p \
-e '}' ) >UU/$file.c
+
+ if [ "$osname" = os390 -a "$file" = perly.c ]; then
+ $echo '#endif' >>UU/$file.c
+ fi
+
if [ "$osname" = os390 ]; then
- if [ "$file" = perly.c ]; then
- $echo '#endif' >>UU/$file.c
- fi
$cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
$sed \
-e '/^#.*<stdin>/d' \
@@ -147,18 +159,24 @@
-e 's|\.c\.c|.c|' $uwinfix | \
$uniq | $sort | $uniq >> .deptmp
else
- $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
+ $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c >.cout 2>.cerr
$sed \
-e '1d' \
-e '/^#.*<stdin>/d' \
+ -e '/^#.*<builtin>/d' \
+ -e '/^#.*<built-in>/d' \
+ -e '/^#.*<command line>/d' \
+ -e '/^#.*<command-line>/d' \
-e '/^#.*"-"/d' \
+ -e '/^#.*"\/.*\/"/d' \
+ -e '/: file path prefix .* never used$/d' \
-e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
-e 's/^[ ]*#[ ]*line/#/' \
-e '/^# *[0-9][0-9]* *[".\/]/!d' \
-e 's/^.*"\(.*\)".*$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's/^# *[0-9][0-9]* \(.*\)$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's|: \./|: |' \
- -e 's|\.c\.c|.c|' $uwinfix | \
+ -e 's|\.c\.c|.c|' $uwinfix .cout .cerr| \
$uniq | $sort | $uniq >> .deptmp
fi
done
@@ -192,6 +210,10 @@
$echo "Updating $mf..."
$echo "# If this runs make out of memory, delete /usr/include lines." \
>> $mf.new
+ if [ "$osname" = vos ]; then
+ $sed 's|.incl.c|.h|' .deptmp >.deptmp.vos
+ mv -f .deptmp.vos .deptmp
+ fi
$sed 's|^\(.*\$(OBJ_EXT):\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
>>$mf.new
else
@@ -223,7 +245,8 @@
$cp $mf.new $mf
$rm $mf.new
$echo "# WARNING: Put nothing here or make depend will gobble it up!" >> $mf
-$rm -rf .deptmp UU .shlist .clist .hlist .hsed
+$rm -rf .deptmp UU .shlist .clist .hlist .hsed .cout .cerr
+rmdir .depending
!NO!SUBS!
$eunicefix makedepend
BADGER
last SWITCH;
}
# If 5.7.1
if ( $perl eq '5.7.1' ) {
_patch(<<'BADGER');
--- makedepend.SH.org 2001-03-11 16:30:08.000000000 +0000
+++ makedepend.SH 2010-09-01 10:44:54.000000000 +0100
@@ -1,5 +1,5 @@
#! /bin/sh
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -29,6 +29,13 @@
!GROK!THIS!
$spitshell >>makedepend <<'!NO!SUBS!'
+if test -d .depending; then
+ echo "$0: Already running, exiting."
+ exit 0
+fi
+
+mkdir .depending
+
# This script should be called with
# sh ./makedepend MAKE=$(MAKE)
case "$1" in
@@ -37,7 +44,7 @@
export PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh \$0; kill \$\$)
-case $CONFIGDOTSH in
+case $PERL_CONFIG_SH in
'')
if test -f config.sh; then TOP=.;
elif test -f ../config.sh; then TOP=..;
@@ -51,6 +58,11 @@
;;
esac
+# Avoid localized gcc messages
+case "$ccname" in
+ gcc) LC_ALL=C ; export LC_ALL ;;
+esac
+
# We need .. when we are in the x2p directory if we are using the
# cppstdin wrapper script.
# Put .. and . first so that we pick up the present cppstdin, not
@@ -58,6 +70,10 @@
PATH=".$path_sep..$path_sep$PATH"
export PATH
+case "$osname" in
+amigaos) cat=/bin/cat ;; # must be absolute
+esac
+
$cat /dev/null >.deptmp
$rm -f *.c.c c/*.c.c
if test -f Makefile; then
@@ -67,7 +83,6 @@
# to be out of date. I don't know if OS/2 has touch, so do this:
case "$osname" in
os2) ;;
- netbsd) ;;
*) $touch $firstmakefile ;;
esac
fi
@@ -99,29 +114,20 @@
$echo *.c | $tr ' ' $trnl | $egrep -v '\*' >.clist)
for file in `$cat .clist`; do
# for file in `cat /dev/null`; do
- if [ "$osname" = uwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g"
- else
- if [ "$osname" = os2 ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$archname" = cygwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$osname" = posix-bc ]; then
- uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/"
- else
- uwinfix=
- fi
- fi
- fi
- fi
+ case "$osname" in
+ uwin) uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g" ;;
+ os2) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ cygwin) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ posix-bc) uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/" ;;
+ vos) uwinfix="-e s/\#/\\\#/" ;;
+ *) uwinfix="" ;;
+ esac
case "$file" in
*.c) filebase=`basename $file .c` ;;
*.y) filebase=`basename $file .y` ;;
esac
case "$file" in
- */*) finc="-I`echo $file | sed 's#/[^/]*$##`" ;;
+ */*) finc="-I`echo $file | sed 's#/[^/]*$##'`" ;;
*) finc= ;;
esac
$echo "Finding dependencies for $filebase$_o."
@@ -134,10 +140,12 @@
-e 's|\\$||' \
-e p \
-e '}' ) >UU/$file.c
+
+ if [ "$osname" = os390 -a "$file" = perly.c ]; then
+ $echo '#endif' >>UU/$file.c
+ fi
+
if [ "$osname" = os390 ]; then
- if [ "$file" = perly.c ]; then
- $echo '#endif' >>UU/$file.c
- fi
$cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
$sed \
-e '/^#.*<stdin>/d' \
@@ -151,18 +159,24 @@
-e 's|\.c\.c|.c|' $uwinfix | \
$uniq | $sort | $uniq >> .deptmp
else
- $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
+ $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c >.cout 2>.cerr
$sed \
-e '1d' \
-e '/^#.*<stdin>/d' \
+ -e '/^#.*<builtin>/d' \
+ -e '/^#.*<built-in>/d' \
+ -e '/^#.*<command line>/d' \
+ -e '/^#.*<command-line>/d' \
-e '/^#.*"-"/d' \
+ -e '/^#.*"\/.*\/"/d' \
+ -e '/: file path prefix .* never used$/d' \
-e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
-e 's/^[ ]*#[ ]*line/#/' \
-e '/^# *[0-9][0-9]* *[".\/]/!d' \
-e 's/^.*"\(.*\)".*$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's/^# *[0-9][0-9]* \(.*\)$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's|: \./|: |' \
- -e 's|\.c\.c|.c|' $uwinfix | \
+ -e 's|\.c\.c|.c|' $uwinfix .cout .cerr| \
$uniq | $sort | $uniq >> .deptmp
fi
done
@@ -196,6 +210,10 @@
$echo "Updating $mf..."
$echo "# If this runs make out of memory, delete /usr/include lines." \
>> $mf.new
+ if [ "$osname" = vos ]; then
+ $sed 's|.incl.c|.h|' .deptmp >.deptmp.vos
+ mv -f .deptmp.vos .deptmp
+ fi
$sed 's|^\(.*\$(OBJ_EXT):\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
>>$mf.new
else
@@ -227,7 +245,8 @@
$cp $mf.new $mf
$rm $mf.new
$echo "# WARNING: Put nothing here or make depend will gobble it up!" >> $mf
-$rm -rf .deptmp UU .shlist .clist .hlist .hsed
+$rm -rf .deptmp UU .shlist .clist .hlist .hsed .cout .cerr
+rmdir .depending
!NO!SUBS!
$eunicefix makedepend
BADGER
last SWITCH;
}
# If 5.7.2
if ( $perl eq '5.7.2' ) {
_patch(<<'BADGER');
--- makedepend.SH.org 2001-07-09 15:11:05.000000000 +0100
+++ makedepend.SH 2010-09-01 10:45:32.000000000 +0100
@@ -18,10 +18,6 @@
*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
esac
-case "$osname" in
-amigaos) cat=/bin/cat ;; # must be absolute
-esac
-
echo "Extracting makedepend (with variable substitutions)"
rm -f makedepend
$spitshell >makedepend <<!GROK!THIS!
@@ -33,6 +29,13 @@
!GROK!THIS!
$spitshell >>makedepend <<'!NO!SUBS!'
+if test -d .depending; then
+ echo "$0: Already running, exiting."
+ exit 0
+fi
+
+mkdir .depending
+
# This script should be called with
# sh ./makedepend MAKE=$(MAKE)
case "$1" in
@@ -55,6 +58,11 @@
;;
esac
+# Avoid localized gcc messages
+case "$ccname" in
+ gcc) LC_ALL=C ; export LC_ALL ;;
+esac
+
# We need .. when we are in the x2p directory if we are using the
# cppstdin wrapper script.
# Put .. and . first so that we pick up the present cppstdin, not
@@ -62,6 +70,10 @@
PATH=".$path_sep..$path_sep$PATH"
export PATH
+case "$osname" in
+amigaos) cat=/bin/cat ;; # must be absolute
+esac
+
$cat /dev/null >.deptmp
$rm -f *.c.c c/*.c.c
if test -f Makefile; then
@@ -71,7 +83,6 @@
# to be out of date. I don't know if OS/2 has touch, so do this:
case "$osname" in
os2) ;;
- netbsd) ;;
*) $touch $firstmakefile ;;
esac
fi
@@ -103,29 +114,20 @@
$echo *.c | $tr ' ' $trnl | $egrep -v '\*' >.clist)
for file in `$cat .clist`; do
# for file in `cat /dev/null`; do
- if [ "$osname" = uwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g"
- else
- if [ "$osname" = os2 ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$archname" = cygwin ]; then
- uwinfix="-e s,\\\\\\\\,/,g"
- else
- if [ "$osname" = posix-bc ]; then
- uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/"
- else
- uwinfix=
- fi
- fi
- fi
- fi
+ case "$osname" in
+ uwin) uwinfix="-e s,\\\\\\\\,/,g -e s,\\([a-zA-Z]\\):/,/\\1/,g" ;;
+ os2) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ cygwin) uwinfix="-e s,\\\\\\\\,/,g" ;;
+ posix-bc) uwinfix="-e s/\\*POSIX(\\(.*\\))/\\1/" ;;
+ vos) uwinfix="-e s/\#/\\\#/" ;;
+ *) uwinfix="" ;;
+ esac
case "$file" in
*.c) filebase=`basename $file .c` ;;
*.y) filebase=`basename $file .y` ;;
esac
case "$file" in
- */*) finc="-I`echo $file | sed 's#/[^/]*$##`" ;;
+ */*) finc="-I`echo $file | sed 's#/[^/]*$##'`" ;;
*) finc= ;;
esac
$echo "Finding dependencies for $filebase$_o."
@@ -138,10 +140,12 @@
-e 's|\\$||' \
-e p \
-e '}' ) >UU/$file.c
+
+ if [ "$osname" = os390 -a "$file" = perly.c ]; then
+ $echo '#endif' >>UU/$file.c
+ fi
+
if [ "$osname" = os390 ]; then
- if [ "$file" = perly.c ]; then
- $echo '#endif' >>UU/$file.c
- fi
$cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
$sed \
-e '/^#.*<stdin>/d' \
@@ -155,18 +159,24 @@
-e 's|\.c\.c|.c|' $uwinfix | \
$uniq | $sort | $uniq >> .deptmp
else
- $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
+ $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c >.cout 2>.cerr
$sed \
-e '1d' \
-e '/^#.*<stdin>/d' \
+ -e '/^#.*<builtin>/d' \
+ -e '/^#.*<built-in>/d' \
+ -e '/^#.*<command line>/d' \
+ -e '/^#.*<command-line>/d' \
-e '/^#.*"-"/d' \
+ -e '/^#.*"\/.*\/"/d' \
+ -e '/: file path prefix .* never used$/d' \
-e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
-e 's/^[ ]*#[ ]*line/#/' \
-e '/^# *[0-9][0-9]* *[".\/]/!d' \
-e 's/^.*"\(.*\)".*$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's/^# *[0-9][0-9]* \(.*\)$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's|: \./|: |' \
- -e 's|\.c\.c|.c|' $uwinfix | \
+ -e 's|\.c\.c|.c|' $uwinfix .cout .cerr| \
$uniq | $sort | $uniq >> .deptmp
fi
done
@@ -200,6 +210,10 @@
$echo "Updating $mf..."
$echo "# If this runs make out of memory, delete /usr/include lines." \
>> $mf.new
+ if [ "$osname" = vos ]; then
+ $sed 's|.incl.c|.h|' .deptmp >.deptmp.vos
+ mv -f .deptmp.vos .deptmp
+ fi
$sed 's|^\(.*\$(OBJ_EXT):\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
>>$mf.new
else
@@ -231,7 +245,8 @@
$cp $mf.new $mf
$rm $mf.new
$echo "# WARNING: Put nothing here or make depend will gobble it up!" >> $mf
-$rm -rf .deptmp UU .shlist .clist .hlist .hsed
+$rm -rf .deptmp UU .shlist .clist .hlist .hsed .cout .cerr
+rmdir .depending
!NO!SUBS!
$eunicefix makedepend
BADGER
last SWITCH;
}
# If 5.7.3
if ( $perl eq '5.7.3' ) {
_patch(<<'BADGER');
--- makedepend.SH.org 2002-03-05 01:10:22.000000000 +0000
+++ makedepend.SH 2010-09-01 10:46:13.000000000 +0100
@@ -18,10 +18,6 @@
*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
esac
-case "$osname" in
-amigaos) cat=/bin/cat ;; # must be absolute
-esac
-
echo "Extracting makedepend (with variable substitutions)"
rm -f makedepend
$spitshell >makedepend <<!GROK!THIS!
@@ -33,6 +29,13 @@
!GROK!THIS!
$spitshell >>makedepend <<'!NO!SUBS!'
+if test -d .depending; then
+ echo "$0: Already running, exiting."
+ exit 0
+fi
+
+mkdir .depending
+
# This script should be called with
# sh ./makedepend MAKE=$(MAKE)
case "$1" in
@@ -55,6 +58,11 @@
;;
esac
+# Avoid localized gcc messages
+case "$ccname" in
+ gcc) LC_ALL=C ; export LC_ALL ;;
+esac
+
# We need .. when we are in the x2p directory if we are using the
# cppstdin wrapper script.
# Put .. and . first so that we pick up the present cppstdin, not
@@ -62,6 +70,10 @@
PATH=".$path_sep..$path_sep$PATH"
export PATH
+case "$osname" in
+amigaos) cat=/bin/cat ;; # must be absolute
+esac
+
$cat /dev/null >.deptmp
$rm -f *.c.c c/*.c.c
if test -f Makefile; then
@@ -71,7 +83,6 @@
# to be out of date. I don't know if OS/2 has touch, so do this:
case "$osname" in
os2) ;;
- netbsd) ;;
*) $touch $firstmakefile ;;
esac
fi
@@ -116,7 +127,7 @@
*.y) filebase=`basename $file .y` ;;
esac
case "$file" in
- */*) finc="-I`echo $file | sed 's#/[^/]*$##`" ;;
+ */*) finc="-I`echo $file | sed 's#/[^/]*$##'`" ;;
*) finc= ;;
esac
$echo "Finding dependencies for $filebase$_o."
@@ -129,6 +140,11 @@
-e 's|\\$||' \
-e p \
-e '}' ) >UU/$file.c
+
+ if [ "$osname" = os390 -a "$file" = perly.c ]; then
+ $echo '#endif' >>UU/$file.c
+ fi
+
if [ "$osname" = os390 ]; then
$cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
$sed \
@@ -143,13 +159,16 @@
-e 's|\.c\.c|.c|' $uwinfix | \
$uniq | $sort | $uniq >> .deptmp
else
- $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c 2>&1 |
+ $cppstdin $finc -I. $cppflags $cppminus <UU/$file.c >.cout 2>.cerr
$sed \
-e '1d' \
-e '/^#.*<stdin>/d' \
-e '/^#.*<builtin>/d' \
+ -e '/^#.*<built-in>/d' \
-e '/^#.*<command line>/d' \
+ -e '/^#.*<command-line>/d' \
-e '/^#.*"-"/d' \
+ -e '/^#.*"\/.*\/"/d' \
-e '/: file path prefix .* never used$/d' \
-e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
-e 's/^[ ]*#[ ]*line/#/' \
@@ -157,7 +176,7 @@
-e 's/^.*"\(.*\)".*$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's/^# *[0-9][0-9]* \(.*\)$/'$filebase'\$(OBJ_EXT): \1/' \
-e 's|: \./|: |' \
- -e 's|\.c\.c|.c|' $uwinfix | \
+ -e 's|\.c\.c|.c|' $uwinfix .cout .cerr| \
$uniq | $sort | $uniq >> .deptmp
fi
done
@@ -191,6 +210,10 @@
$echo "Updating $mf..."
$echo "# If this runs make out of memory, delete /usr/include lines." \
>> $mf.new
+ if [ "$osname" = vos ]; then
+ $sed 's|.incl.c|.h|' .deptmp >.deptmp.vos
+ mv -f .deptmp.vos .deptmp
+ fi
$sed 's|^\(.*\$(OBJ_EXT):\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
>>$mf.new
else
@@ -222,7 +245,8 @@
$cp $mf.new $mf
$rm $mf.new
$echo "# WARNING: Put nothing here or make depend will gobble it up!" >> $mf
-$rm -rf .deptmp UU .shlist .clist .hlist .hsed
+$rm -rf .deptmp UU .shlist .clist .hlist .hsed .cout .cerr
+rmdir .depending
!NO!SUBS!
$eunicefix makedepend
BADGER
last SWITCH;
}
# If 5.8.0
if ( $perl eq '5.8.0' ) {
_patch(<<'BADGER');
--- makedepend.SH.org 2002-07-09 15:06:42.000000000 +0100
+++ makedepend.SH 2010-09-01 10:16:37.000000000 +0100
@@ -58,6 +58,11 @@
;;
esac
+# Avoid localized gcc messages
+case "$ccname" in
+ gcc) LC_ALL=C ; export LC_ALL ;;
+esac
+
# We need .. when we are in the x2p directory if we are using the
# cppstdin wrapper script.
# Put .. and . first so that we pick up the present cppstdin, not
@@ -78,7 +83,6 @@
# to be out of date. I don't know if OS/2 has touch, so do this:
case "$osname" in
os2) ;;
- netbsd) ;;
*) $touch $firstmakefile ;;
esac
fi
@@ -123,7 +127,7 @@
*.y) filebase=`basename $file .y` ;;
esac
case "$file" in
- */*) finc="-I`echo $file | sed 's#/[^/]*$##`" ;;
+ */*) finc="-I`echo $file | sed 's#/[^/]*$##'`" ;;
*) finc= ;;
esac
$echo "Finding dependencies for $filebase$_o."
@@ -136,6 +140,11 @@
-e 's|\\$||' \
-e p \
-e '}' ) >UU/$file.c
+
+ if [ "$osname" = os390 -a "$file" = perly.c ]; then
+ $echo '#endif' >>UU/$file.c
+ fi
+
if [ "$osname" = os390 ]; then
$cppstdin $finc -I. $cppflags $cppminus <UU/$file.c |
$sed \
@@ -157,7 +166,9 @@
-e '/^#.*<builtin>/d' \
-e '/^#.*<built-in>/d' \
-e '/^#.*<command line>/d' \
+ -e '/^#.*<command-line>/d' \
-e '/^#.*"-"/d' \
+ -e '/^#.*"\/.*\/"/d' \
-e '/: file path prefix .* never used$/d' \
-e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
-e 's/^[ ]*#[ ]*line/#/' \
@@ -199,6 +210,10 @@
$echo "Updating $mf..."
$echo "# If this runs make out of memory, delete /usr/include lines." \
>> $mf.new
+ if [ "$osname" = vos ]; then
+ $sed 's|.incl.c|.h|' .deptmp >.deptmp.vos
+ mv -f .deptmp.vos .deptmp
+ fi
$sed 's|^\(.*\$(OBJ_EXT):\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
>>$mf.new
else
BADGER
last SWITCH;
}
# If 5.8.[12345678]
_patch(<<'BADGER');
--- makedepend.SH.org 2003-06-05 19:11:10.000000000 +0100
+++ makedepend.SH 2010-09-01 10:24:39.000000000 +0100
@@ -83,7 +83,6 @@
# to be out of date. I don't know if OS/2 has touch, so do this:
case "$osname" in
os2) ;;
- netbsd) ;;
*) $touch $firstmakefile ;;
esac
fi
@@ -128,7 +127,7 @@
*.y) filebase=`basename $file .y` ;;
esac
case "$file" in
- */*) finc="-I`echo $file | sed 's#/[^/]*$##`" ;;
+ */*) finc="-I`echo $file | sed 's#/[^/]*$##'`" ;;
*) finc= ;;
esac
$echo "Finding dependencies for $filebase$_o."
@@ -167,7 +166,9 @@
-e '/^#.*<builtin>/d' \
-e '/^#.*<built-in>/d' \
-e '/^#.*<command line>/d' \
+ -e '/^#.*<command-line>/d' \
-e '/^#.*"-"/d' \
+ -e '/^#.*"\/.*\/"/d' \
-e '/: file path prefix .* never used$/d' \
-e 's#\.[0-9][0-9]*\.c#'"$file.c#" \
-e 's/^[ ]*#[ ]*line/#/' \
@@ -209,6 +210,10 @@
$echo "Updating $mf..."
$echo "# If this runs make out of memory, delete /usr/include lines." \
>> $mf.new
+ if [ "$osname" = vos ]; then
+ $sed 's|.incl.c|.h|' .deptmp >.deptmp.vos
+ mv -f .deptmp.vos .deptmp
+ fi
$sed 's|^\(.*\$(OBJ_EXT):\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
>>$mf.new
else
BADGER
}
}
sub _patch_archive_tar_tests
{
my $perl = shift;
if ($perl =~ /^5\.10/) {
_patch(<<'END');
--- lib/Archive/Tar/t/02_methods.t
+++ lib/Archive/Tar/t/02_methods.t
@@ -70,6 +70,20 @@ my $LONG_FILE = qq[directory/really-really-really-really-really-really-really-re
my $TOO_LONG = ($^O eq 'MSWin32' or $^O eq 'cygwin' or $^O eq 'VMS')
&& length( cwd(). $LONG_FILE ) > 247;
+if(!$TOO_LONG) {
+ my $alt = File::Spec->catfile( cwd(), $LONG_FILE);
+ eval 'mkpath([$alt]);';
+ if($@)
+ {
+ $TOO_LONG = 1;
+ }
+ else
+ {
+ $@ = '';
+ my $base = File::Spec->catfile( cwd(), 'directory');
+ rmtree $base;
+ }
+}
### warn if we are going to skip long file names
if ($TOO_LONG) {
diag("No long filename support - long filename extraction disabled") if ! $ENV{PERL_CORE};
END
}
else {
_patch(<<'END');
--- cpan/Archive-Tar/t/02_methods.t
+++ cpan/Archive-Tar/t/02_methods.t
@@ -70,6 +70,20 @@ my $LONG_FILE = qq[directory/really-really-really-really-really-really-really-re
my $TOO_LONG = ($^O eq 'MSWin32' or $^O eq 'cygwin' or $^O eq 'VMS')
&& length( cwd(). $LONG_FILE ) > 247;
+if(!$TOO_LONG) {
+ my $alt = File::Spec->catfile( cwd(), $LONG_FILE);
+ eval 'mkpath([$alt]);';
+ if($@)
+ {
+ $TOO_LONG = 1;
+ }
+ else
+ {
+ $@ = '';
+ my $base = File::Spec->catfile( cwd(), 'directory');
+ rmtree $base;
+ }
+}
### warn if we are going to skip long file names
if ($TOO_LONG) {
diag("No long filename support - long filename extraction disabled") if ! $ENV{PERL_CORE};
END
}
}
sub _patch_odbm_file_hints_linux
{
_patch(<<'END');
--- ext/ODBM_File/hints/linux.pl
+++ ext/ODBM_File/hints/linux.pl
@@ -1,8 +1,8 @@
# uses GDBM dbm compatibility feature - at least on SuSE 8.0
$self->{LIBS} = ['-lgdbm'];
-# Debian/Ubuntu have /usr/lib/libgdbm_compat.so.3* but not this file,
+# Debian/Ubuntu have libgdbm_compat.so but not this file,
# so linking may fail
-if (-e '/usr/lib/libgdbm_compat.so' or -e '/usr/lib64/libgdbm_compat.so') {
- $self->{LIBS}->[0] .= ' -lgdbm_compat';
+foreach (split / /, $Config{libpth}) {
+ $self->{LIBS}->[0] .= ' -lgdbm_compat' if -e $_.'/libgdbm_compat.so';
}
END
}
qq[patchin'];
__END__
=pod
=head1 NAME
Devel::PatchPerl - Patch perl source a la Devel::PPPort's buildperl.pl
=head1 VERSION
version 0.52
=head1 SYNOPSIS
use strict;
use warnings;
use Devel::PatchPerl;
Devel::PatchPerl->patch_source( '5.6.1', '/path/to/untarred/perl/source/perl-5.6.1' );
=head1 DESCRIPTION
Devel::PatchPerl is a modularisation of the patching code contained in L<Devel::PPPort>'s
C<buildperl.pl>.
It does not build perls, it merely provides an interface to the source patching
functionality.
=head1 FUNCTION
=over
=item C<patch_source>
Takes two parameters, a C<perl> version and the path to unwrapped perl source for that version.
It dies on any errors.
If you don't supply a C<perl> version, it will attempt to auto-determine the
C<perl> version from the specified path.
If you don't supply the path to unwrapped perl source, it will assume the
current working directory.
=back
=head1 SEE ALSO
L<Devel::PPPort>
=head1 AUTHOR
Chris Williams <chris@bingosnet.co.uk>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2011 by Chris Williams and Marcus Holland-Moritz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
DEVEL_PATCHPERL
$fatpacked{"Devel/PatchPerl/Hints.pm"} = <<'DEVEL_PATCHPERL_HINTS';
package Devel::PatchPerl::Hints;
{
$Devel::PatchPerl::Hints::VERSION = '0.52';
}
#ABSTRACT: replacement 'hints' files
use strict;
use warnings;
use MIME::Base64 qw[decode_base64];
use File::Spec;
our @ISA = qw[Exporter];
our @EXPORT_OK = qw[hint_file];
my %hints = (
'netbsd' =>
'IyBoaW50cy9uZXRic2Quc2gKIwojIFBsZWFzZSBjaGVjayB3aXRoIHBhY2thZ2VzQG5ldGJzZC5v
cmcgYmVmb3JlIG1ha2luZyBtb2RpZmljYXRpb25zCiMgdG8gdGhpcyBmaWxlLgoKY2FzZSAiJGFy
Y2huYW1lIiBpbgonJykKICAgIGFyY2huYW1lPWB1bmFtZSAtbWAtJHtvc25hbWV9CiAgICA7Owpl
c2FjCgojIE5ldEJTRCBrZWVwcyBkeW5hbWljIGxvYWRpbmcgZGwqKCkgZnVuY3Rpb25zIGluIC91
c3IvbGliL2NydDAubywKIyBzbyBDb25maWd1cmUgZG9lc24ndCBmaW5kIHRoZW0gKHVubGVzcyB5
b3UgYWJhbmRvbiB0aGUgbm0gc2NhbikuCiMgQWxzbywgTmV0QlNEIDAuOWEgd2FzIHRoZSBmaXJz
dCByZWxlYXNlIHRvIGludHJvZHVjZSBzaGFyZWQKIyBsaWJyYXJpZXMuCiMKY2FzZSAiJG9zdmVy
cyIgaW4KMC45fDAuOCopCgl1c2VkbD0iJHVuZGVmIgoJOzsKKikKCWNhc2UgYHVuYW1lIC1tYCBp
bgoJcG1heCkKCQkjIE5ldEJTRCAxLjMgYW5kIDEuMy4xIG9uIHBtYXggc2hpcHBlZCBhbiBgb2xk
JyBsZC5zbywKCQkjIHdoaWNoIHdpbGwgbm90IHdvcmsuCgkJY2FzZSAiJG9zdmVycyIgaW4KCQkx
LjN8MS4zLjEpCgkJCWRfZGxvcGVuPSR1bmRlZgoJCQk7OwoJCWVzYWMKCQk7OwoJZXNhYwoJaWYg
dGVzdCAtZiAvdXNyL2xpYmV4ZWMvbGQuZWxmX3NvOyB0aGVuCgkJIyBFTEYKCQlkX2Rsb3Blbj0k
ZGVmaW5lCgkJZF9kbGVycm9yPSRkZWZpbmUKCQljY2NkbGZsYWdzPSItRFBJQyAtZlBJQyAkY2Nj
ZGxmbGFncyIKCQlsZGRsZmxhZ3M9Ii0td2hvbGUtYXJjaGl2ZSAtc2hhcmVkICRsZGRsZmxhZ3Mi
CgkJcnBhdGhmbGFnPSItV2wsLXJwYXRoLCIKCQljYXNlICIkb3N2ZXJzIiBpbgoJCTEuWzAtNV0q
KQoJCQkjCgkJCSMgSW5jbHVkZSB0aGUgd2hvbGUgbGliZ2NjLmEgaW50byB0aGUgcGVybCBleGVj
dXRhYmxlCgkJCSMgc28gdGhhdCBjZXJ0YWluIHN5bWJvbHMgbmVlZGVkIGJ5IGxvYWRhYmxlIG1v
ZHVsZXMKCQkJIyBidWlsdCBhcyBDKysgb2JqZWN0cyAoX19laF9hbGxvYywgX19wdXJlX3ZpcnR1
YWwsCgkJCSMgZXRjLikgd2lsbCBhbHdheXMgYmUgZGVmaW5lZC4KCQkJIwoJCQljY2RsZmxhZ3M9
Ii1XbCwtd2hvbGUtYXJjaGl2ZSAtbGdjYyBcCgkJCQktV2wsLW5vLXdob2xlLWFyY2hpdmUgLVds
LC1FICRjY2RsZmxhZ3MiCgkJCTs7CgkJKikKCQkJY2NkbGZsYWdzPSItV2wsLUUgJGNjZGxmbGFn
cyIKCQkJOzsKCQllc2FjCgllbGlmIHRlc3QgLWYgL3Vzci9saWJleGVjL2xkLnNvOyB0aGVuCgkJ
IyBhLm91dAoJCWRfZGxvcGVuPSRkZWZpbmUKCQlkX2RsZXJyb3I9JGRlZmluZQoJCWNjY2RsZmxh
Z3M9Ii1EUElDIC1mUElDICRjY2NkbGZsYWdzIgoJCWxkZGxmbGFncz0iLUJzaGFyZWFibGUgJGxk
ZGxmbGFncyIKCQlycGF0aGZsYWc9Ii1SIgoJZWxzZQoJCWRfZGxvcGVuPSR1bmRlZgoJCXJwYXRo
ZmxhZz0KCWZpCgk7Owplc2FjCgojIG5ldGJzZCBoYWQgdGhlc2UgYnV0IHRoZXkgZG9uJ3QgcmVh
bGx5IHdvcmsgYXMgYWR2ZXJ0aXNlZCwgaW4gdGhlCiMgdmVyc2lvbnMgbGlzdGVkIGJlbG93LiAg
aWYgdGhleSBhcmUgZGVmaW5lZCwgdGhlbiB0aGVyZSBpc24ndCBhCiMgd2F5IHRvIG1ha2UgcGVy
bCBjYWxsIHNldHVpZCgpIG9yIHNldGdpZCgpLiAgaWYgdGhleSBhcmVuJ3QsIHRoZW4KIyAoJDws
ICQ+KSA9ICgkdSwgJHUpOyB3aWxsIHdvcmsgKHNhbWUgZm9yICQoLyQpKS4gIHRoaXMgaXMgYmVj
YXVzZQojIHlvdSBjYW4gbm90IGNoYW5nZSB0aGUgcmVhbCB1c2VyaWQgb2YgYSBwcm9jZXNzIHVu
ZGVyIDQuNEJTRC4KIyBuZXRic2QgZml4ZWQgdGhpcyBpbiAxLjMuMi4KY2FzZSAiJG9zdmVycyIg
aW4KMC45KnwxLlswMTJdKnwxLjN8MS4zLjEpCglkX3NldHJlZ2lkPSIkdW5kZWYiCglkX3NldHJl
dWlkPSIkdW5kZWYiCgk7Owplc2FjCmNhc2UgIiRvc3ZlcnMiIGluCjAuOSp8MS4qfDIuKnwzLip8
NC4qfDUuKikKCWRfZ2V0cHJvdG9lbnRfcj0iJHVuZGVmIgoJZF9nZXRwcm90b2J5bmFtZV9yPSIk
dW5kZWYiCglkX2dldHByb3RvYnludW1iZXJfcj0iJHVuZGVmIgoJZF9zZXRwcm90b2VudF9yPSIk
dW5kZWYiCglkX2VuZHByb3RvZW50X3I9IiR1bmRlZiIKCWRfZ2V0c2VydmVudF9yPSIkdW5kZWYi
CglkX2dldHNlcnZieW5hbWVfcj0iJHVuZGVmIgoJZF9nZXRzZXJ2Ynlwb3J0X3I9IiR1bmRlZiIK
CWRfc2V0c2VydmVudF9yPSIkdW5kZWYiCglkX2VuZHNlcnZlbnRfcj0iJHVuZGVmIgoJZF9nZXRw
cm90b2VudF9yX3Byb3RvPSIwIgoJZF9nZXRwcm90b2J5bmFtZV9yX3Byb3RvPSIwIgoJZF9nZXRw
cm90b2J5bnVtYmVyX3JfcHJvdG89IjAiCglkX3NldHByb3RvZW50X3JfcHJvdG89IjAiCglkX2Vu
ZHByb3RvZW50X3JfcHJvdG89IjAiCglkX2dldHNlcnZlbnRfcl9wcm90bz0iMCIKCWRfZ2V0c2Vy
dmJ5bmFtZV9yX3Byb3RvPSIwIgoJZF9nZXRzZXJ2Ynlwb3J0X3JfcHJvdG89IjAiCglkX3NldHNl
cnZlbnRfcl9wcm90bz0iMCIKCWRfZW5kc2VydmVudF9yX3Byb3RvPSIwIgoJOzsKZXNhYwoKIyBU
aGVzZSBhcmUgb2Jzb2xldGUgaW4gYW55IG5ldGJzZC4KZF9zZXRyZ2lkPSIkdW5kZWYiCmRfc2V0
cnVpZD0iJHVuZGVmIgoKIyB0aGVyZSdzIG5vIHByb2JsZW0gd2l0aCB2Zm9yay4KdXNldmZvcms9
dHJ1ZQoKIyBUaGlzIGlzIHRoZXJlIGJ1dCBpbiBtYWNoaW5lL2llZWVmcF9oLgppZWVlZnBfaD0i
ZGVmaW5lIgoKIyBUaGlzIHNjcmlwdCBVVS91c2V0aHJlYWRzLmNidSB3aWxsIGdldCAnY2FsbGVk
LWJhY2snIGJ5IENvbmZpZ3VyZQojIGFmdGVyIGl0IGhhcyBwcm9tcHRlZCB0aGUgdXNlciBmb3Ig
d2hldGhlciB0byB1c2UgdGhyZWFkcy4KY2F0ID4gVVUvdXNldGhyZWFkcy5jYnUgPDwnRU9DQlUn
CmNhc2UgIiR1c2V0aHJlYWRzIiBpbgokZGVmaW5lfHRydWV8W3lZXSopCglscHRocmVhZD0KCWZv
ciB4eHggaW4gcHRocmVhZDsgZG8KCQlmb3IgeXl5IGluICRsb2NsaWJwdGggJHBsaWJwdGggJGds
aWJwdGggZHVtbXk7IGRvCgkJCXp6ej0keXl5L2xpYiR4eHguYQoJCQlpZiB0ZXN0IC1mICIkenp6
IjsgdGhlbgoJCQkJbHB0aHJlYWQ9JHh4eAoJCQkJYnJlYWs7CgkJCWZpCgkJCXp6ej0keXl5L2xp
YiR4eHguc28KCQkJaWYgdGVzdCAtZiAiJHp6eiI7IHRoZW4KCQkJCWxwdGhyZWFkPSR4eHgKCQkJ
CWJyZWFrOwoJCQlmaQoJCQl6eno9YGxzICR5eXkvbGliJHh4eC5zby4qIDI+L2Rldi9udWxsYAoJ
CQlpZiB0ZXN0ICJYJHp6eiIgIT0gWDsgdGhlbgoJCQkJbHB0aHJlYWQ9JHh4eAoJCQkJYnJlYWs7
CgkJCWZpCgkJZG9uZQoJCWlmIHRlc3QgIlgkbHB0aHJlYWQiICE9IFg7IHRoZW4KCQkJYnJlYWs7
CgkJZmkKCWRvbmUKCWlmIHRlc3QgIlgkbHB0aHJlYWQiICE9IFg7IHRoZW4KCQkjIEFkZCAtbHB0
aHJlYWQuCgkJbGlic3dhbnRlZD0iJGxpYnN3YW50ZWQgJGxwdGhyZWFkIgoJCSMgVGhlcmUgaXMg
bm8gbGliY19yIGFzIG9mIE5ldEJTRCAxLjUuMiwgc28gbm8gYyAtPiBjX3IuCgkJIyBUaGlzIHdp
bGwgYmUgcmV2aXNpdGVkIHdoZW4gTmV0QlNEIGdhaW5zIGEgbmF0aXZlIHB0aHJlYWRzCgkJIyBp
bXBsZW1lbnRhdGlvbi4KCWVsc2UKCQllY2hvICIkMDogTm8gUE9TSVggdGhyZWFkcyBsaWJyYXJ5
ICgtbHB0aHJlYWQpIGZvdW5kLiAgIiBcCgkJICAgICAiWW91IG1heSB3YW50IHRvIGluc3RhbGwg
R05VIHB0aC4gIEFib3J0aW5nLiIgPiY0CgkJZXhpdCAxCglmaQoJdW5zZXQgbHB0aHJlYWQKCgkj
IHNldmVyYWwgcmVlbnRyYW50IGZ1bmN0aW9ucyBhcmUgZW1iZWRkZWQgaW4gbGliYywgYnV0IGhh
dmVuJ3QKCSMgYmVlbiBhZGRlZCB0byB0aGUgaGVhZGVyIGZpbGVzIHlldC4gIExldCdzIGhvbGQg
b2ZmIG9uIHVzaW5nCgkjIHRoZW0gdW50aWwgdGhleSBhcmUgYSB2YWxpZCBwYXJ0IG9mIHRoZSBB
UEkKCWNhc2UgIiRvc3ZlcnMiIGluCglbMDEyXS4qfDMuWzAtMV0pCgkJZF9nZXRwcm90b2J5bmFt
ZV9yPSR1bmRlZgoJCWRfZ2V0cHJvdG9ieW51bWJlcl9yPSR1bmRlZgoJCWRfZ2V0cHJvdG9lbnRf
cj0kdW5kZWYKCQlkX2dldHNlcnZieW5hbWVfcj0kdW5kZWYKCQlkX2dldHNlcnZieXBvcnRfcj0k
dW5kZWYKCQlkX2dldHNlcnZlbnRfcj0kdW5kZWYKCQlkX3NldHByb3RvZW50X3I9JHVuZGVmCgkJ
ZF9zZXRzZXJ2ZW50X3I9JHVuZGVmCgkJZF9lbmRwcm90b2VudF9yPSR1bmRlZgoJCWRfZW5kc2Vy
dmVudF9yPSR1bmRlZiA7OwoJZXNhYwoJOzsKCmVzYWMKRU9DQlUKCiMgU2V0IHNlbnNpYmxlIGRl
ZmF1bHRzIGZvciBOZXRCU0Q6IGxvb2sgZm9yIGxvY2FsIHNvZnR3YXJlIGluCiMgL3Vzci9wa2cg
KE5ldEJTRCBQYWNrYWdlcyBDb2xsZWN0aW9uKSBhbmQgaW4gL3Vzci9sb2NhbC4KIwpsb2NsaWJw
dGg9Ii91c3IvcGtnL2xpYiAvdXNyL2xvY2FsL2xpYiIKbG9jaW5jcHRoPSIvdXNyL3BrZy9pbmNs
dWRlIC91c3IvbG9jYWwvaW5jbHVkZSIKY2FzZSAiJHJwYXRoZmxhZyIgaW4KJycpCglsZGZsYWdz
PQoJOzsKKikKCWxkZmxhZ3M9Cglmb3IgeXl5IGluICRsb2NsaWJwdGg7IGRvCgkJbGRmbGFncz0i
JGxkZmxhZ3MgJHJwYXRoZmxhZyR5eXkiCglkb25lCgk7Owplc2FjCgpjYXNlIGB1bmFtZSAtbWAg
aW4KYWxwaGEpCiAgICBlY2hvICdpbnQgbWFpbigpIHt9JyA+IHRyeS5jCiAgICBnY2M9YCR7Y2M6
LWNjfSAtdiAtYyB0cnkuYyAyPiYxfGdyZXAgJ2djYyB2ZXJzaW9uIGVnY3MtMidgCiAgICBjYXNl
ICIkZ2NjIiBpbgogICAgJycgfCAiZ2NjIHZlcnNpb24gZWdjcy0yLjk1LiJbMy05XSopIDs7ICMg
Mi45NS4zIG9yIGJldHRlciBva2F5CiAgICAqKQljYXQgPiY0IDw8RU9GCioqKgoqKiogWW91ciBn
Y2MgKCRnY2MpIGlzIGtub3duIHRvIGJlCioqKiB0b28gYnVnZ3kgb24gbmV0YnNkL2FscGhhIHRv
IGNvbXBpbGUgUGVybCB3aXRoIG9wdGltaXphdGlvbi4KKioqIEl0IGlzIHN1Z2dlc3RlZCB5b3Ug
aW5zdGFsbCB0aGUgbGFuZy9nY2MgcGFja2FnZSB3aGljaCBzaG91bGQKKioqIGhhdmUgYXQgbGVh
c3QgZ2NjIDIuOTUuMyB3aGljaCBzaG91bGQgd29yayBva2F5OiB1c2UgZm9yIGV4YW1wbGUKKioq
IENvbmZpZ3VyZSAtRGNjPS91c3IvcGtnL2djYy0yLjk1LjMvYmluL2NjLiAgWW91IGNvdWxkIGFs
c28KKioqIENvbmZpZ3VyZSAtRG9wdGltaXplPS1PMCB0byBjb21waWxlIFBlcmwgd2l0aG91dCBh
bnkgb3B0aW1pemF0aW9uCioqKiBidXQgdGhhdCBpcyBub3QgcmVjb21tZW5kZWQuCioqKgpFT0YK
CWV4aXQgMQoJOzsKICAgIGVzYWMKICAgIHJtIC1mIHRyeS4qCiAgICA7Owplc2FjCgojIE5ldEJT
RC9zcGFyYyAxLjUuMy8xLjYuMSBkdW1wcyBjb3JlIGluIHRoZSBzZW1pZF9kcyB0ZXN0IG9mIENv
bmZpZ3VyZS4KY2FzZSBgdW5hbWUgLW1gIGluCnNwYXJjKSBkX3NlbWN0bF9zZW1pZF9kcz11bmRl
ZiA7Owplc2FjCgojIG1hbGxvYyB3cmFwIHdvcmtzCmNhc2UgIiR1c2VtYWxsb2N3cmFwIiBpbgon
JykgdXNlbWFsbG9jd3JhcD0nZGVmaW5lJyA7Owplc2FjCgojIGRvbid0IHVzZSBwZXJsIG1hbGxv
YyBieSBkZWZhdWx0CmNhc2UgIiR1c2VteW1hbGxvYyIgaW4KJycpIHVzZW15bWFsbG9jPW4gOzsK
ZXNhYwo=',
'freebsd' =>
'IyBPcmlnaW5hbCBiYXNlZCBvbiBpbmZvIGZyb20KIyBDYXJsIE0uIEZvbmdoZWlzZXIgPGNtZkBp
bnMuaW5mb25ldC5uZXQ+CiMgRGF0ZTogVGh1LCAyOCBKdWwgMTk5NCAxOToxNzowNSAtMDUwMCAo
Q0RUKQojCiMgQWRkaXRpb25hbCAxLjEuNSBkZWZpbmVzIGZyb20gCiMgT2xsaXZpZXIgUm9iZXJ0
IDxPbGxpdmllci5Sb2JlcnRAa2VsdGlhLmZybXVnLmZyLm5ldD4KIyBEYXRlOiBXZWQsIDI4IFNl
cCAxOTk0IDAwOjM3OjQ2ICswMTAwIChNRVQpCiMKIyBBZGRpdGlvbmFsIDIuKiBkZWZpbmVzIGZy
b20KIyBPbGxpdmllciBSb2JlcnQgPE9sbGl2aWVyLlJvYmVydEBrZWx0aWEuZnJtdWcuZnIubmV0
PgojIERhdGU6IFNhdCwgOCBBcHIgMTk5NSAyMDo1Mzo0MSArMDIwMCAoTUVUIERTVCkKIwojIEFk
ZGl0aW9uYWwgMi4wLjUgYW5kIDIuMSBkZWZpbmVkIGZyb20KIyBPbGxpdmllciBSb2JlcnQgPE9s
bGl2aWVyLlJvYmVydEBrZWx0aWEuZnJtdWcuZnIubmV0PgojIERhdGU6IEZyaSwgMTIgTWF5IDE5
OTUgMTQ6MzA6MzggKzAyMDAgKE1FVCBEU1QpCiMKIyBBZGRpdGlvbmFsIDIuMiBkZWZpbmVzIGZy
b20KIyBNYXJrIE11cnJheSA8bWFya0Bncm9uZGFyLnphPgojIERhdGU6IFdlZCwgNiBOb3YgMTk5
NiAwOTo0NDo1OCArMDIwMCAoTUVUKQojCiMgTW9kaWZpZWQgdG8gZW5zdXJlIHdlIHJlcGxhY2Ug
LWxjIHdpdGggLWxjX3IsIGFuZAojIHRvIHB1dCBpbiBwbGFjZS1ob2xkZXJzIGZvciB2YXJpb3Vz
IHNwZWNpZmljIGhpbnRzLgojIEFuZHkgRG91Z2hlcnR5IDxkb3VnaGVyYUBsYWZheWV0dGUuZWR1
PgojIERhdGU6IFR1ZSBNYXIgMTAgMTY6MDc6MDAgRVNUIDE5OTgKIwojIFN1cHBvcnQgZm9yIEZy
ZWVCU0QvRUxGCiMgT2xsaXZpZXIgUm9iZXJ0IDxyb2JlcnRvQGtlbHRpYS5mcmVlbml4LmZyPgoj
IERhdGU6IFdlZCBTZXAgIDIgMTY6MjI6MTIgQ0VTVCAxOTk4CiMKIyBUaGUgdHdvIGZsYWdzICIt
ZnBpYyAtRFBJQyIgYXJlIHVzZWQgdG8gaW5kaWNhdGUgYQojIHdpbGwtYmUtc2hhcmVkIG9iamVj
dC4gIENvbmZpZ3VyZSB3aWxsIGd1ZXNzIHRoZSAtZnBpYywgKGFuZCB0aGUKIyAtRFBJQyBpcyBu
b3QgdXNlZCBieSBwZXJsIHByb3BlcikgYnV0IHRoZSBmdWxsIGRlZmluZSBpcyBpbmNsdWRlZCB0
byAKIyBiZSBjb25zaXN0ZW50IHdpdGggdGhlIEZyZWVCU0QgZ2VuZXJhbCBzaGFyZWQgbGlicyBi
dWlsZGluZyBwcm9jZXNzLgojCiMgc2V0cmV1aWQgYW5kIGZyaWVuZHMgYXJlIGluaGVyZW50bHkg
YnJva2VuIGluIGFsbCB2ZXJzaW9ucyBvZiBGcmVlQlNECiMgYmVmb3JlIDIuMS1jdXJyZW50IChi
ZWZvcmUgYXBwcm94IGRhdGUgNC8xNS85NSkuIEl0IGlzIGZpeGVkIGluIDIuMC41CiMgYW5kIHdo
YXQtd2lsbC1iZS0yLjEKIwoKY2FzZSAiJG9zdmVycyIgaW4KMC4qfDEuMCopCgl1c2VkbD0iJHVu
ZGVmIgoJOzsKMS4xKikKCW1hbGxvY3R5cGU9J3ZvaWQgKicKCWdyb3Vwc3R5cGU9J2ludCcKCWRf
c2V0cmVnaWQ9J3VuZGVmJwoJZF9zZXRyZXVpZD0ndW5kZWYnCglkX3NldHJnaWQ9J3VuZGVmJwoJ
ZF9zZXRydWlkPSd1bmRlZicKCTs7CjIuMC1yZWxlYXNlKikKCWRfc2V0cmVnaWQ9J3VuZGVmJwoJ
ZF9zZXRyZXVpZD0ndW5kZWYnCglkX3NldHJnaWQ9J3VuZGVmJwoJZF9zZXRydWlkPSd1bmRlZicK
CTs7CiMKIyBUcnlpbmcgdG8gY292ZXIgMi4wLjUsIDIuMS1jdXJyZW50IGFuZCBmdXR1cmUgMi4x
LzIuMgojIEl0IGRvZXMgbm90IGNvdmVydCBhbGwgMi4xLWN1cnJlbnQgdmVyc2lvbnMgYXMgdGhl
IG91dHB1dCBvZiB1bmFtZQojIGNoYW5nZWQgYSBmZXcgdGltZXMuCiMKIyBFdmVuIHRob3VnaCBz
ZXRldWlkL3NldGVnaWQgYXJlIGF2YWlsYWJsZSwgdGhleSd2ZSBiZWVuIHR1cm5lZCBvZmYKIyBi
ZWNhdXNlIHBlcmwgaXNuJ3QgY29kZWQgd2l0aCBzYXZlZCBzZXRbdWddaWQgdmFyaWFibGVzIGlu
IG1pbmQuCiMgSW4gYWRkaXRpb24sIGEgc21hbGwgcGF0Y2ggaXMgcmVxdWlyZWQgdG8gc3VpZHBl
cmwgdG8gYXZvaWQgYSBzZWN1cml0eQojIHByb2JsZW0gd2l0aCBGcmVlQlNELgojCjIuMC41Knwy
LjAtYnVpbHQqfDIuMSopCiAJdXNldmZvcms9J3RydWUnCgljYXNlICIkdXNlbXltYWxsb2MiIGlu
CgkgICAgIiIpIHVzZW15bWFsbG9jPSduJwoJICAgICAgICA7OwoJZXNhYwoJZF9zZXRyZWdpZD0n
ZGVmaW5lJwoJZF9zZXRyZXVpZD0nZGVmaW5lJwoJZF9zZXRlZ2lkPSd1bmRlZicKCWRfc2V0ZXVp
ZD0ndW5kZWYnCgl0ZXN0IC1yIC4vYnJva2VuLWRiLm1zZyAmJiAuIC4vYnJva2VuLWRiLm1zZwoJ
OzsKIwojIDIuMiBhbmQgYWJvdmUgaGF2ZSBwaGttYWxsb2MoMykuCiMgZG9uJ3QgdXNlIC1sbWFs
bG9jIChtYXliZSB0aGVyZSdzIGFuIG9sZCBvbmUgZnJvbSAxLjEuNS4xIGZsb2F0aW5nIGFyb3Vu
ZCkKMi4yKikKIAl1c2V2Zm9yaz0ndHJ1ZScKCWNhc2UgIiR1c2VteW1hbGxvYyIgaW4KCSAgICAi
IikgdXNlbXltYWxsb2M9J24nCgkgICAgICAgIDs7Cgllc2FjCglsaWJzd2FudGVkPWBlY2hvICRs
aWJzd2FudGVkIHwgc2VkICdzLyBtYWxsb2MgLyAvJ2AKCWxpYnN3YW50ZWQ9YGVjaG8gJGxpYnN3
YW50ZWQgfCBzZWQgJ3MvIGJpbmQgLyAvJ2AKCSMgaWNvbnYgZ29uZSBpbiBQZXJsIDUuOC4xLCBi
dXQgaWYgc29tZW9uZSBjb21waWxlcyA1LjguMCBvciBlYXJsaWVyLgoJbGlic3dhbnRlZD1gZWNo
byAkbGlic3dhbnRlZCB8IHNlZCAncy8gaWNvbnYgLyAvJ2AKCWRfc2V0cmVnaWQ9J2RlZmluZScK
CWRfc2V0cmV1aWQ9J2RlZmluZScKCWRfc2V0ZWdpZD0nZGVmaW5lJwoJZF9zZXRldWlkPSdkZWZp
bmUnCgkjIGRfZG9zdWlkPSdkZWZpbmUnICMgT2Jzb2xldGUuCgk7OwoqKQl1c2V2Zm9yaz0ndHJ1
ZScKCWNhc2UgIiR1c2VteW1hbGxvYyIgaW4KCSAgICAiIikgdXNlbXltYWxsb2M9J24nCgkgICAg
ICAgIDs7Cgllc2FjCglsaWJzd2FudGVkPWBlY2hvICRsaWJzd2FudGVkIHwgc2VkICdzLyBtYWxs
b2MgLyAvJ2AKCTs7CmVzYWMKCiMgRHluYW1pYyBMb2FkaW5nIGZsYWdzIGhhdmUgbm90IGNoYW5n
ZWQgbXVjaCwgc28gdGhleSBhcmUgc2VwYXJhdGVkCiMgb3V0IGhlcmUgdG8gYXZvaWQgZHVwbGlj
YXRpbmcgdGhlbSBldmVyeXdoZXJlLgpjYXNlICIkb3N2ZXJzIiBpbgowLip8MS4wKikgOzsKCjEq
fDIqKQljY2NkbGZsYWdzPSctRFBJQyAtZnBpYycKCWxkZGxmbGFncz0iLUJzaGFyZWFibGUgJGxk
ZGxmbGFncyIKCTs7CgozKnw0Knw1Knw2KikKICAgICAgICBvYmpmb3JtYXQ9YC91c3IvYmluL29i
amZvcm1hdGAKICAgICAgICBpZiBbIHgkb2JqZm9ybWF0ID0geGFvdXQgXTsgdGhlbgogICAgICAg
ICAgICBpZiBbIC1lIC91c3IvbGliL2FvdXQgXTsgdGhlbgogICAgICAgICAgICAgICAgbGlicHRo
PSIvdXNyL2xpYi9hb3V0IC91c3IvbG9jYWwvbGliIC91c3IvbGliIgogICAgICAgICAgICAgICAg
Z2xpYnB0aD0iL3Vzci9saWIvYW91dCAvdXNyL2xvY2FsL2xpYiAvdXNyL2xpYiIKICAgICAgICAg
ICAgZmkKICAgICAgICAgICAgbGRkbGZsYWdzPSctQnNoYXJlYWJsZScKICAgICAgICBlbHNlCiAg
ICAgICAgICAgIGxpYnB0aD0iL3Vzci9saWIgL3Vzci9sb2NhbC9saWIiCiAgICAgICAgICAgIGds
aWJwdGg9Ii91c3IvbGliIC91c3IvbG9jYWwvbGliIgogICAgICAgICAgICBsZGZsYWdzPSItV2ws
LUUgIgogICAgICAgICAgICBsZGRsZmxhZ3M9Ii1zaGFyZWQgIgogICAgICAgIGZpCiAgICAgICAg
Y2NjZGxmbGFncz0nLURQSUMgLWZQSUMnCiAgICAgICAgOzsKKikKICAgICAgIGxpYnB0aD0iL3Vz
ci9saWIgL3Vzci9sb2NhbC9saWIiCiAgICAgICBnbGlicHRoPSIvdXNyL2xpYiAvdXNyL2xvY2Fs
L2xpYiIKICAgICAgIGxkZmxhZ3M9Ii1XbCwtRSAiCiAgICAgICAgbGRkbGZsYWdzPSItc2hhcmVk
ICIKICAgICAgICBjY2NkbGZsYWdzPSctRFBJQyAtZlBJQycKICAgICAgIDs7CmVzYWMKCmNhc2Ug
IiRvc3ZlcnMiIGluCjAqfDEqfDIqfDMqKSA7OwoKKikKCWNjZmxhZ3M9IiR7Y2NmbGFnc30gLURI
QVNfRlBTRVRNQVNLIC1ESEFTX0ZMT0FUSU5HUE9JTlRfSCIKCWlmIC91c3IvYmluL2ZpbGUgLUwg
L3Vzci9saWIvbGliYy5zbyB8IC91c3IvYmluL2dyZXAgLXZxICJub3Qgc3RyaXBwZWQiIDsgdGhl
bgoJICAgIHVzZW5tPWZhbHNlCglmaQogICAgICAgIDs7CmVzYWMKCmNhdCA8PCdFT00nID4mNAoK
U29tZSB1c2VycyBoYXZlIHJlcG9ydGVkIHRoYXQgQ29uZmlndXJlIGhhbHRzIHdoZW4gdGVzdGlu
ZyBmb3IKdGhlIE9fTk9OQkxPQ0sgc3ltYm9sIHdpdGggYSBzeW50YXggZXJyb3IuICBUaGlzIGlz
IGFwcGFyZW50bHkgYQpzaCBlcnJvci4gIFJlcnVubmluZyBDb25maWd1cmUgd2l0aCBrc2ggYXBw
YXJlbnRseSBmaXhlcyB0aGUKcHJvYmxlbS4gIFRyeQoJa3NoIENvbmZpZ3VyZSBbeW91ciBvcHRp
b25zXQoKRU9NCgojIEZyb206IEFudG9uIEJlcmV6aW4gPHRvYmV6QHBsYWIua3UuZGs+CiMgVG86
IHBlcmw1LXBvcnRlcnNAcGVybC5vcmcKIyBTdWJqZWN0OiBbUEFUQ0ggNS4wMDVfNTRdIENvbmZp
Z3VyZSAtIGhpbnRzL2ZyZWVic2Quc2ggc2lnbmFsIGhhbmRsZXIgdHlwZQojIERhdGU6IDMwIE5v
diAxOTk4IDE5OjQ2OjI0ICswMTAwCiMgTWVzc2FnZS1JRDogPDg2NHNyaGh2Y3YuZnNmQGxpb24u
cGxhYi5rdS5kaz4KCnNpZ25hbF90PSd2b2lkJwpkX3ZvaWRzaWc9J2RlZmluZScKCiMgc2V0IGxp
YnBlcmwuc28uWC5YIGZvciAyLjIuWApjYXNlICIkb3N2ZXJzIiBpbgoyLjIqKQogICAgIyB1bmZv
cnR1bmF0ZWx5IHRoaXMgY29kZSBnZXRzIGV4ZWN1dGVkIGJlZm9yZQogICAgIyB0aGUgZXF1aXZh
bGVudCBpbiB0aGUgbWFpbiBDb25maWd1cmUgc28gd2UgY29weSBhIGxpdHRsZQogICAgIyBmcm9t
IENvbmZpZ3VyZSBYWFggQ29uZmlndXJlIHNob3VsZCBiZSBmaXhlZC4KICAgIGlmICR0ZXN0IC1y
ICRzcmMvcGF0Y2hsZXZlbC5oO3RoZW4KICAgICAgIHBhdGNobGV2ZWw9YGF3ayAnL2RlZmluZVsg
CV0rUEVSTF9WRVJTSU9OLyB7cHJpbnQgJDN9JyAkc3JjL3BhdGNobGV2ZWwuaGAKICAgICAgIHN1
YnZlcnNpb249YGF3ayAnL2RlZmluZVsgCV0rUEVSTF9TVUJWRVJTSU9OLyB7cHJpbnQgJDN9JyAk
c3JjL3BhdGNobGV2ZWwuaGAKICAgIGVsc2UKICAgICAgIHBhdGNobGV2ZWw9MAogICAgICAgc3Vi
dmVyc2lvbj0wCiAgICBmaQogICAgbGlicGVybD0ibGlicGVybC5zby4kcGF0Y2hsZXZlbC4kc3Vi
dmVyc2lvbiIKICAgIHVuc2V0IHBhdGNobGV2ZWwKICAgIHVuc2V0IHN1YnZlcnNpb24KICAgIDs7
CmVzYWMKCiMgVGhpcyBzY3JpcHQgVVUvdXNldGhyZWFkcy5jYnUgd2lsbCBnZXQgJ2NhbGxlZC1i
YWNrJyBieSBDb25maWd1cmUgCiMgYWZ0ZXIgaXQgaGFzIHByb21wdGVkIHRoZSB1c2VyIGZvciB3
aGV0aGVyIHRvIHVzZSB0aHJlYWRzLgpjYXQgPiBVVS91c2V0aHJlYWRzLmNidSA8PCdFT0NCVScK
Y2FzZSAiJHVzZXRocmVhZHMiIGluCiRkZWZpbmV8dHJ1ZXxbeVldKikKICAgICAgICBsY19yPWAv
c2Jpbi9sZGNvbmZpZyAtcnxncmVwICc6LWxjX3InfGF3ayAne3ByaW50ICRORn0nfHNlZCAtbiAn
JHAnYAogICAgICAgIGNhc2UgIiRvc3ZlcnMiIGluICAKCTAqfDEqfDIuMCp8Mi4xKikgICBjYXQg
PDxFT00gPiY0CkkgZGlkIG5vdCBrbm93IHRoYXQgRnJlZUJTRCAkb3N2ZXJzIHN1cHBvcnRzIFBP
U0lYIHRocmVhZHMuCgpGZWVsIGZyZWUgdG8gdGVsbCBwZXJsYnVnQHBlcmwub3JnIG90aGVyd2lz
ZS4KRU9NCgkgICAgICBleGl0IDEKCSAgICAgIDs7CgogICAgICAgIDIuMi5bMC03XSopCiAgICAg
ICAgICAgICAgY2F0IDw8RU9NID4mNApQT1NJWCB0aHJlYWRzIGFyZSBub3Qgc3VwcG9ydGVkIHdl
bGwgYnkgRnJlZUJTRCAkb3N2ZXJzLgoKUGxlYXNlIGNvbnNpZGVyIHVwZ3JhZGluZyB0byBhdCBs
ZWFzdCBGcmVlQlNEIDIuMi44LApvciBwcmVmZXJhYmx5IHRvIHRoZSBtb3N0IHJlY2VudCAtUkVM
RUFTRSBvciAtU1RBQkxFCnZlcnNpb24gKHNlZSBodHRwOi8vd3d3LmZyZWVic2Qub3JnL3JlbGVh
c2VzLykuCgooV2hpbGUgMi4yLjcgZG9lcyBoYXZlIHB0aHJlYWRzLCBpdCBoYXMgc29tZSBwcm9i
bGVtcwogd2l0aCB0aGUgY29tYmluYXRpb24gb2YgdGhyZWFkcyBhbmQgcGlwZXMgYW5kIHRoZXJl
Zm9yZQogbWFueSBQZXJsIHRlc3RzIHdpbGwgZWl0aGVyIGhhbmcgb3IgZmFpbC4pCkVPTQoJICAg
ICAgZXhpdCAxCgkgICAgICA7OwoKCVszLTVdLiopCgkgICAgICBpZiBbICEgLXIgIiRsY19yIiBd
OyB0aGVuCgkgICAgICBjYXQgPDxFT00gPiY0ClBPU0lYIHRocmVhZHMgc2hvdWxkIGJlIHN1cHBv
cnRlZCBieSBGcmVlQlNEICRvc3ZlcnMgLS0KYnV0IHlvdXIgc3lzdGVtIGlzIG1pc3NpbmcgdGhl
IHNoYXJlZCBsaWJjX3IuCigvc2Jpbi9sZGNvbmZpZyAtciBkb2Vzbid0IGZpbmQgYW55KS4KCkNv
bnNpZGVyIHVzaW5nIHRoZSBsYXRlc3QgU1RBQkxFIHJlbGVhc2UuCkVPTQoJCSBleGl0IDEKCSAg
ICAgIGZpCgkgICAgICAjIDUwMDAxNiBpcyB0aGUgZmlyc3Qgb3NyZWxkYXRlIGluIHdoaWNoIG9u
ZSBjb3VsZAoJICAgICAgIyBqdXN0IGxpbmsgYWdhaW5zdCBsaWJjX3Igd2l0aG91dCBkaXNwb3Np
bmcgb2YgbGliYwoJICAgICAgIyBhdCB0aGUgc2FtZSB0aW1lLiAgNTAwMDE2IC4uLiB1cCB0byB3
aGF0ZXZlciBpdCB3YXMKCSAgICAgICMgb24gdGhlIDMxc3Qgb2YgQXVndXN0IDIwMDMgY2FuIHN0
aWxsIGJlIHVzZWQgd2l0aCAtcHRocmVhZCwKCSAgICAgICMgYnV0IGl0IGlzIG5vdCBuZWNlc3Nh
cnkuCgoJICAgICAgIyBBbnRvbiBCZXJlemluIHNheXMgdGhhdCBwb3N0IDUwMHNvbWV0aGluZyB3
ZSdyZSB3cm9uZyB0byBiZQoJICAgICAgIyB0byBiZSB1c2luZyAtbGNfciwgYW5kIHNob3VsZCBq
dXN0IGJlIHVzaW5nIC1wdGhyZWFkIG9uIHRoZQoJICAgICAgIyBsaW5rZXIgbGluZS4KCSAgICAg
ICMgU28gcHJlc3VtYWJseSByZWFsbHkgd2Ugc2hvdWxkIGJlIGNoZWNraW5nIHRoYXQgJG9zdmVy
IGlzIDUuKikKCSAgICAgICMgYW5kIHRoYXQgYC9zYmluL3N5c2N0bCAtbiBrZXJuLm9zcmVsZGF0
ZWAgLWdlIDUwMDAxNgoJICAgICAgIyBvciAtbHQgNTAwc29tZXRoaW5nIGFuZCBvbmx5IGluIHRo
YXQgcmFuZ2Ugbm90IGRvaW5nIHRoaXM6CgkgICAgICBsZGZsYWdzPSItcHRocmVhZCAkbGRmbGFn
cyIKCgkgICAgICAjIEJvdGggaW4gNC54IGFuZCA1LnggZ2V0aG9zdGJ5YWRkcl9yIGV4aXN0cyBi
dXQKCSAgICAgICMgaXQgaXMgIlRlbXBvcmFyeSBmdW5jdGlvbiwgbm90IHRocmVhZHNhZmUiLi4u
CgkgICAgICAjIFByZXN1bWFibHkgZWFybGllciBpdCBkaWRuJ3QgZXZlbiBleGlzdC4KCSAgICAg
IGRfZ2V0aG9zdGJ5YWRkcl9yPSJ1bmRlZiIKCSAgICAgIGRfZ2V0aG9zdGJ5YWRkcl9yX3Byb3Rv
PSIwIgoJICAgICAgOzsKCgkqKQoJICAgICAgIyA3LnggZG9lc24ndCBpbnN0YWxsIGxpYmNfciBi
eSBkZWZhdWx0LCBhbmQgQ29uZmlndXJlCgkgICAgICAjIHdvdWxkIGZhaWwgaW4gdGhlIGNvZGUg
Zm9sbG93aW5nCgkgICAgICAjCgkgICAgICAjIGdldGhvc3RieWFkZHJfcigpIGFwcGVhcnMgdG8g
aGF2ZSBiZWVuIGltcGxlbWVudGVkIGluIDYueCsKCSAgICAgIGxkZmxhZ3M9Ii1wdGhyZWFkICRs
ZGZsYWdzIgoJICAgICAgOzsKCgllc2FjCgogICAgICAgIGNhc2UgIiRvc3ZlcnMiIGluCiAgICAg
ICAgWzEtNF0qKQoJICAgIHNldCBgZWNobyBYICIkbGlic3dhbnRlZCAifCBzZWQgLWUgJ3MvIGMg
LyBjX3IgLydgCgkgICAgc2hpZnQKCSAgICBsaWJzd2FudGVkPSIkKiIKCSAgICA7OwogICAgICAg
ICopCgkgICAgc2V0IGBlY2hvIFggIiRsaWJzd2FudGVkICJ8IHNlZCAtZSAncy8gYyAvLydgCgkg
ICAgc2hpZnQKCSAgICBsaWJzd2FudGVkPSIkKiIKCSAgICA7OwoJZXNhYwoJICAgIAoJIyBDb25m
aWd1cmUgd2lsbCBwcm9iYWJseSBwaWNrIHRoZSB3cm9uZyBsaWJjIHRvIHVzZSBmb3Igbm0gc2Nh
bi4KCSMgVGhlIHNhZmVzdCBxdWljay1maXggaXMganVzdCB0byBub3QgdXNlIG5tIGF0IGFsbC4u
LgoJdXNlbm09ZmFsc2UKCiAgICAgICAgY2FzZSAiJG9zdmVycyIgaW4KICAgICAgICAyLjIuOCop
CiAgICAgICAgICAgICMgLi4uIGJ1dCB0aGlzIGRvZXMgbm90IGFwcGx5IGZvciAyLjIuOCAtIHdl
IGtub3cgaXQncyBzYWZlCiAgICAgICAgICAgIGxpYmM9IiRsY19yIgogICAgICAgICAgICB1c2Vu
bT10cnVlCiAgICAgICAgICAgOzsKICAgICAgICBlc2FjCgogICAgICAgIHVuc2V0IGxjX3IKCgkj
IEV2ZW4gd2l0aCB0aGUgbWFsbG9jIG11dGV4ZXMgdGhlIFBlcmwgbWFsbG9jIGRvZXMgbm90Cgkj
IHNlZW0gdG8gYmUgdGhyZWFkc2FmZSBpbiBGcmVlQlNEPwoJY2FzZSAiJHVzZW15bWFsbG9jIiBp
bgoJJycpIHVzZW15bWFsbG9jPW4gOzsKCWVzYWMKZXNhYwpFT0NCVQoKIyBtYWxsb2Mgd3JhcCB3
b3JrcwpjYXNlICIkdXNlbWFsbG9jd3JhcCIgaW4KJycpIHVzZW1hbGxvY3dyYXA9J2RlZmluZScg
OzsKZXNhYwoKIyBYWFggVW5kZXIgRnJlZUJTRCA2LjAgKGFuZCBwcm9iYWJseSBtb3N0IG90aGVy
IHNpbWlsYXIgdmVyc2lvbnMpCiMgUGVybF9kaWUoTlVMTCkgZ2VuZXJhdGVzIGEgd2FybmluZzoK
IyAgICBwcF9zeXMuYzo0OTE6IHdhcm5pbmc6IG51bGwgZm9ybWF0IHN0cmluZwojIENvbmZpZ3Vy
ZSBzdXBwb3NlZGVseSB0ZXN0cyBmb3IgdGhpcywgYnV0IGFwcGFyZW50bHkgdGhlIHRlc3QgZG9l
c24ndAojIHdvcmsuICBWb2x1bnRlZXJzIHdpdGggRnJlZUJTRCBhcmUgbmVlZGVkIHRvIGltcHJv
dmluZyB0aGUgQ29uZmlndXJlIHRlc3QuCiMgTWVhbndoaWxlLCB0aGUgZm9sbG93aW5nIHdvcmth
cm91bmQgc2hvdWxkIGJlIHNhZmUgb24gYWxsIHZlcnNpb25zCiMgb2YgRnJlZUJTRC4KZF9wcmlu
dGZfZm9ybWF0X251bGw9J3VuZGVmJwo=',
'openbsd' =>
'IyBoaW50cy9vcGVuYnNkLnNoCiMKIyBoaW50cyBmaWxlIGZvciBPcGVuQlNEOyBUb2RkIE1pbGxl
ciA8bWlsbGVydEBvcGVuYnNkLm9yZz4KIyBFZGl0ZWQgdG8gYWxsb3cgQ29uZmlndXJlIGNvbW1h
bmQtbGluZSBvdmVycmlkZXMgYnkKIyAgQW5keSBEb3VnaGVydHkgPGRvdWdoZXJhQGxhZmF5ZXR0
ZS5lZHU+CiMKIyBUbyBidWlsZCB3aXRoIGRpc3RyaWJ1dGlvbiBwYXRocywgdXNlOgojCS4vQ29u
ZmlndXJlIC1kZXMgLURvcGVuYnNkX2Rpc3RyaWJ1dGlvbj1kZWZpbmVkCiMKCiMgSW4gT3BlbkJT
RCA+IDMuNywgdXNlIHBlcmwncyBtYWxsb2MgW3BlcmwgIzc1NzQyXQpjYXNlICIkb3N2ZXJzIiBp
bgozLls4OV0qfFs0LTldKikKICAgIHRlc3QgIiR1c2VteW1hbGxvYyIgfHwgdXNlbXltYWxsb2M9
eQogICAgOzsKZXNhYwoKIyBtYWxsb2Mgd3JhcCB3b3JrcwpjYXNlICIkdXNlbWFsbG9jd3JhcCIg
aW4KJycpIHVzZW1hbGxvY3dyYXA9J2RlZmluZScgOzsKZXNhYwoKIyBDdXJyZW50bHksIHZmb3Jr
KDIpIGlzIG5vdCBhIHJlYWwgd2luIG92ZXIgZm9yaygyKS4KdXNldmZvcms9IiR1bmRlZiIKCiMg
SW4gT3BlbkJTRCA8IDMuMywgdGhlIHNldHJlP1t1Z11pZCgpIGFyZSBlbXVsYXRlZCB1c2luZyB0
aGUKIyBfUE9TSVhfU0FWRURfSURTIGZ1bmN0aW9uYWxpdHkgd2hpY2ggZG9lcyBub3QgaGF2ZSB0
aGUgc2FtZQojIHNlbWFudGljcyBhcyA0LjNCU0QuICBTdGFydGluZyB3aXRoIE9wZW5CU0QgMy4z
LCB0aGUgb3JpZ2luYWwKIyBzZW1hbnRpY3MgaGF2ZSBiZWVuIHJlc3RvcmVkLgpjYXNlICIkb3N2
ZXJzIiBpbgpbMC0yXS4qfDMuWzAtMl0pCglkX3NldHJlZ2lkPSR1bmRlZgoJZF9zZXRyZXVpZD0k
dW5kZWYKCWRfc2V0cmdpZD0kdW5kZWYKCWRfc2V0cnVpZD0kdW5kZWYKZXNhYwoKIwojIE5vdCBh
bGwgcGxhdGZvcm1zIHN1cHBvcnQgZHluYW1pYyBsb2FkaW5nLi4uCiMgRm9yIHRoZSBjYXNlIG9m
ICIkb3BlbmJzZF9kaXN0cmlidXRpb24iLCB0aGUgaGludHMgZmlsZQojIG5lZWRzIHRvIGtub3cg
d2hldGhlciB3ZSBhcmUgdXNpbmcgZHluYW1pYyBsb2FkaW5nIHNvIHRoYXQKIyBpdCBjYW4gc2V0
IHRoZSBsaWJwZXJsIG5hbWUgYXBwcm9wcmlhdGVseS4KIyBBbGxvdyBjb21tYW5kIGxpbmUgb3Zl
cnJpZGVzLgojCkFSQ0g9YGFyY2ggfCBzZWQgJ3MvXk9wZW5CU0QuLy8nYApjYXNlICIke0FSQ0h9
LSR7b3N2ZXJzfSIgaW4KYWxwaGEtMi5bMC04XXxtaXBzLTIuWzAtOF18cG93ZXJwYy0yLlswLTdd
fG04OGstKnxocHBhLSp8dmF4LSopCgl0ZXN0IC16ICIkdXNlZGwiICYmIHVzZWRsPSR1bmRlZgoJ
OzsKKikKCXRlc3QgLXogIiR1c2VkbCIgJiYgdXNlZGw9JGRlZmluZQoJIyBXZSB1c2UgLWZQSUMg
aGVyZSBiZWNhdXNlIC1mcGljIGlzICpOT1QqIGVub3VnaCBmb3Igc29tZSBvZiB0aGUKCSMgZXh0
ZW5zaW9ucyBsaWtlIFRrIG9uIHNvbWUgT3BlbkJTRCBwbGF0Zm9ybXMgKGllOiBzcGFyYykKCWNj
Y2RsZmxhZ3M9Ii1EUElDIC1mUElDICRjY2NkbGZsYWdzIgoJY2FzZSAiJG9zdmVycyIgaW4KCVsw
MV0uKnwyLlswLTddfDIuWzAtN10uKikKCQlsZGRsZmxhZ3M9Ii1Cc2hhcmVhYmxlICRsZGRsZmxh
Z3MiCgkJOzsKCTIuWzgtOV18My4wKQoJCWxkPSR7Y2M6LWNjfQoJCWxkZGxmbGFncz0iLXNoYXJl
ZCAtZlBJQyAkbGRkbGZsYWdzIgoJCTs7CgkqKSAjIGZyb20gMy4xIG9ud2FyZHMKCQlsZD0ke2Nj
Oi1jY30KCQlsZGRsZmxhZ3M9Ii1zaGFyZWQgLWZQSUMgJGxkZGxmbGFncyIKCQlsaWJzd2FudGVk
PWBlY2hvICRsaWJzd2FudGVkIHwgc2VkICdzLyBkbCAvIC8nYAoJCTs7Cgllc2FjCgoJIyBXZSBu
ZWVkIHRvIGZvcmNlIGxkIHRvIGV4cG9ydCBzeW1ib2xzIG9uIEVMRiBwbGF0Zm9ybXMuCgkjIFdp
dGhvdXQgdGhpcywgZGxvcGVuKCkgaXMgY3JpcHBsZWQuCglFTEY9YCR7Y2M6LWNjfSAtZE0gLUUg
LSA8L2Rldi9udWxsIHwgZ3JlcCBfX0VMRl9fYAoJdGVzdCAtbiAiJEVMRiIgJiYgbGRmbGFncz0i
LVdsLC1FICRsZGZsYWdzIgoJOzsKZXNhYwoKIwojIFR3ZWFrcyBmb3IgdmFyaW91cyB2ZXJzaW9u
cyBvZiBPcGVuQlNECiMKY2FzZSAiJG9zdmVycyIgaW4KMi41KQoJIyBPcGVuQlNEIDIuNSBoYXMg
YnJva2VuIG9kYm0gc3VwcG9ydAoJaV9kYm09JHVuZGVmCgk7Owplc2FjCgojIE9wZW5CU0QgZG9l
c24ndCBuZWVkIGxpYmNyeXB0IGJ1dCBtYW55IGZvbGtzIGtlZXAgYSBzdHViIGxpYgojIGFyb3Vu
ZCBmb3Igb2xkIE5ldEJTRCBiaW5hcmllcy4KbGlic3dhbnRlZD1gZWNobyAkbGlic3dhbnRlZCB8
IHNlZCAncy8gY3J5cHQgLyAvJ2AKCiMgQ29uZmlndXJlIGNhbid0IGZpZ3VyZSB0aGlzIG91dCBu
b24taW50ZXJhY3RpdmVseQpkX3N1aWRzYWZlPSRkZWZpbmUKCiMgY2MgaXMgZ2NjIHNvIHdlIGNh
biBkbyBiZXR0ZXIgdGhhbiAtTwojIEFsbG93IGEgY29tbWFuZC1saW5lIG92ZXJyaWRlLCBzdWNo
IGFzIC1Eb3B0aW1pemU9LWcKY2FzZSAke0FSQ0h9IGluCm04OGspCiAgIG9wdGltaXplPSctTzAn
CiAgIDs7CmhwcGEpCiAgIG9wdGltaXplPSctTzAnCiAgIDs7CiopCiAgIHRlc3QgIiRvcHRpbWl6
ZSIgfHwgb3B0aW1pemU9Jy1PMicKICAgOzsKZXNhYwoKIyBUaGlzIHNjcmlwdCBVVS91c2V0aHJl
YWRzLmNidSB3aWxsIGdldCAnY2FsbGVkLWJhY2snIGJ5IENvbmZpZ3VyZSAKIyBhZnRlciBpdCBo
YXMgcHJvbXB0ZWQgdGhlIHVzZXIgZm9yIHdoZXRoZXIgdG8gdXNlIHRocmVhZHMuCmNhdCA+IFVV
L3VzZXRocmVhZHMuY2J1IDw8J0VPQ0JVJwpjYXNlICIkdXNldGhyZWFkcyIgaW4KJGRlZmluZXx0
cnVlfFt5WV0qKQoJIyBhbnkgb3BlbmJzZCB2ZXJzaW9uIGRlcGVuZGVuY2llcyB3aXRoIHB0aHJl
YWRzPwoJY2NmbGFncz0iLXB0aHJlYWQgJGNjZmxhZ3MiCglsZGZsYWdzPSItcHRocmVhZCAkbGRm
bGFncyIKCWNhc2UgIiRvc3ZlcnMiIGluCglbMC0yXS4qfDMuWzAtMl0pCgkJIyBDaGFuZ2UgZnJv
bSAtbGMgdG8gLWxjX3IKCQlzZXQgYGVjaG8gIlggJGxpYnN3YW50ZWQgIiB8IHNlZCAncy8gYyAv
IGNfciAvJ2AKCQlzaGlmdAoJCWxpYnN3YW50ZWQ9IiQqIgoJOzsKCWVzYWMKCWNhc2UgIiRvc3Zl
cnMiIGluCglbMDEyXS4qfDMuWzAtNl0pCiAgICAgICAgCSMgQnJva2VuIGF0IGxlYXN0IHVwIHRv
IE9wZW5CU0QgMy42LCB3ZSdsbCBzZWUgYWJvdXQgMy43CgkJZF9nZXRzZXJ2YnluYW1lX3I9JHVu
ZGVmIDs7Cgllc2FjCmVzYWMKRU9DQlUKCiMgVGhpcyBzY3JpcHQgVVUvdXNlNjRiaXRpbnQuY2J1
IHdpbGwgZ2V0ICdjYWxsZWQtYmFjaycgYnkgQ29uZmlndXJlIAojIGFmdGVyIGl0IGhhcyBwcm9t
cHRlZCB0aGUgdXNlciBmb3Igd2hldGhlciB0byB1c2UgNjQtYml0bmVzcy4KY2F0ID4gVVUvdXNl
NjRiaXRpbnQuY2J1IDw8J0VPQ0JVJwpjYXNlICIkdXNlNjRiaXRpbnQiIGluCiRkZWZpbmV8dHJ1
ZXxbeVldKikKCWVjaG8gIiAiCgllY2hvICJDaGVja2luZyBpZiB5b3VyIEMgbGlicmFyeSBoYXMg
YnJva2VuIDY0LWJpdCBmdW5jdGlvbnMuLi4iID4mNAoJJGNhdCA+Y2hlY2suYyA8PEVPQ1AKI2lu
Y2x1ZGUgPHN0ZGlvLmg+CnR5cGVkZWYgJHVxdWFkdHlwZSBteVVMTDsKaW50IG1haW4gKHZvaWQp
CnsKICAgIHN0cnVjdCB7Cglkb3VibGUgZDsKCW15VUxMICB1OwogICAgfSAqcCwgdGVzdFtdID0g
ewoJezQyOTQ5NjczMDMuMTUsIDQyOTQ5NjczMDNVTEx9LAoJezQyOTQ5NjcyOTQuMiwgIDQyOTQ5
NjcyOTRVTEx9LAoJezQyOTQ5NjcyOTUuNywgIDQyOTQ5NjcyOTVVTEx9LAoJezAuMCwgMFVMTH0K
ICAgIH07CiAgICBmb3IgKHAgPSB0ZXN0OyBwLT51OyBwKyspIHsKCW15VUxMIHggPSAobXlVTEwp
cC0+ZDsKCWlmICh4ICE9IHAtPnUpIHsKCSAgICBwcmludGYoImJ1Z2d5XG4iKTsKCSAgICByZXR1
cm4gMDsKCX0KICAgIH0KICAgIHByaW50Zigib2tcbiIpOwogICAgcmV0dXJuIDA7Cn0KRU9DUAoJ
c2V0IGNoZWNrCglpZiBldmFsICRjb21waWxlX29rOyB0aGVuCgkgICAgbGliY3F1YWQ9YC4vY2hl
Y2tgCgkgICAgZWNobyAiWW91ciBDIGxpYnJhcnkncyA2NC1iaXQgZnVuY3Rpb25zIGFyZSAkbGli
Y3F1YWQuIgoJZWxzZQoJICAgIGVjaG8gIihJIGNhbid0IHNlZW0gdG8gY29tcGlsZSB0aGUgdGVz
dCBwcm9ncmFtLikiCgkgICAgZWNobyAiQXNzdW1pbmcgdGhhdCB5b3VyIEMgbGlicmFyeSdzIDY0
LWJpdCBmdW5jdGlvbnMgYXJlIG9rLiIKCSAgICBsaWJjcXVhZD0ib2siCglmaQoJJHJtIC1mIGNo
ZWNrLmMgY2hlY2sKCgljYXNlICIkbGliY3F1YWQiIGluCgkgICAgYnVnZ3kqKQoJCWNhdCA+JjQg
PDxFT00KCioqKiBZb3UgaGF2ZSBhIEMgbGlicmFyeSB3aXRoIGJyb2tlbiA2NC1iaXQgZnVuY3Rp
b25zLgoqKiogNjQtYml0IHN1cHBvcnQgZG9lcyBub3Qgd29yayByZWxpYWJseSBpbiB0aGlzIGNv
bmZpZ3VyYXRpb24uCioqKiBQbGVhc2UgcmVydW4gQ29uZmlndXJlIHdpdGhvdXQgLUR1c2U2NGJp
dGludCBhbmQvb3IgLUR1c2Vtb3JlYml0cy4KKioqIENhbm5vdCBjb250aW51ZSwgYWJvcnRpbmcu
CgpFT00KCQlleGl0IDEKCQk7OwoJZXNhYwplc2FjCkVPQ0JVCgojIFdoZW4gYnVpbGRpbmcgaW4g
dGhlIE9wZW5CU0QgdHJlZSB3ZSB1c2UgZGlmZmVyZW50IHBhdGhzCiMgVGhpcyBpcyBvbmx5IHBh
cnQgb2YgdGhlIHN0b3J5LCB0aGUgcmVzdCBjb21lcyBmcm9tIGNvbmZpZy5vdmVyCmNhc2UgIiRv
cGVuYnNkX2Rpc3RyaWJ1dGlvbiIgaW4KJyd8JHVuZGVmfGZhbHNlKSA7OwoqKQoJIyBXZSBwdXQg
dGhpbmdzIGluIC91c3IsIG5vdCAvdXNyL2xvY2FsCglwcmVmaXg9Jy91c3InCglwcmVmaXhleHA9
Jy91c3InCglzeXNtYW49Jy91c3Ivc2hhcmUvbWFuL21hbjEnCglsaWJwdGg9Jy91c3IvbGliJwoJ
Z2xpYnB0aD0nL3Vzci9saWInCgkjIExvY2FsIHRoaW5ncywgaG93ZXZlciwgZG8gZ28gaW4gL3Vz
ci9sb2NhbAoJc2l0ZXByZWZpeD0nL3Vzci9sb2NhbCcKCXNpdGVwcmVmaXhleHA9Jy91c3IvbG9j
YWwnCgkjIFBvcnRzIGluc3RhbGxzIG5vbi1zdGQgbGlicyBpbiAvdXNyL2xvY2FsL2xpYiBzbyBs
b29rIHRoZXJlIHRvbwoJbG9jaW5jcHRoPScvdXNyL2xvY2FsL2luY2x1ZGUnCglsb2NsaWJwdGg9
Jy91c3IvbG9jYWwvbGliJwoJIyBMaW5rIHBlcmwgd2l0aCBzaGFyZWQgbGlicGVybAoJaWYgWyAi
JHVzZWRsIiA9ICIkZGVmaW5lIiAtYSAtciBzaGxpYl92ZXJzaW9uIF07IHRoZW4KCQl1c2VzaHJw
bGliPXRydWUKCQlsaWJwZXJsPWAuIC4vc2hsaWJfdmVyc2lvbjsgZWNobyBsaWJwZXJsLnNvLiR7
bWFqb3J9LiR7bWlub3J9YAoJZmkKCTs7CmVzYWMKCiMgZW5kCg==',
'linux' =>
'IyBoaW50cy9saW51eC5zaAojIE9yaWdpbmFsIHZlcnNpb24gYnkgcnNhbmRlcnMKIyBBZGRpdGlv
bmFsIHN1cHBvcnQgYnkgS2VubmV0aCBBbGJhbm93c2tpIDxramFoZHNAa2phaGRzLmNvbT4KIwoj
IEVMRiBzdXBwb3J0IGJ5IEguSi4gTHUgPGhqbEBueW5leHN0LmNvbT4KIyBBZGRpdGlvbmFsIGlu
Zm8gZnJvbSBOaWdlbCBIZWFkIDxuaGVhZEBFU09DLmJpdG5ldD4KIyBhbmQgS2VubmV0aCBBbGJh
bm93c2tpIDxramFoZHNAa2phaGRzLmNvbT4KIwojIENvbnNvbGlkYXRlZCBieSBBbmR5IERvdWdo
ZXJ0eSA8ZG91Z2hlcmFAbGFmYXlldHRlLmVkdT4KIwojIFVwZGF0ZWQgVGh1IEZlYiAgOCAxMTo1
NjoxMCBFU1QgMTk5NgoKIyBVcGRhdGVkIFRodSBNYXkgMzAgMTA6NTA6MjIgRURUIDE5OTYgYnkg
PGRvdWdoZXJhQGxhZmF5ZXR0ZS5lZHU+CgojIFVwZGF0ZWQgRnJpIEp1biAyMSAxMTowNzo1NCBF
RFQgMTk5NgojIE5EQk0gc3VwcG9ydCBmb3IgRUxGIHJlLWVuYWJsZWQgYnkgPGtqYWhkc0BramFo
ZHMuY29tPgoKIyBObyB2ZXJzaW9uIG9mIExpbnV4IHN1cHBvcnRzIHNldHVpZCBzY3JpcHRzLgpk
X3N1aWRzYWZlPSd1bmRlZicKCiMgTm8gdmVyc2lvbiBvZiBMaW51eCBuZWVkcyBsaWJ1dGlsIGZv
ciBwZXJsLgppX2xpYnV0aWw9J3VuZGVmJwoKIyBEZWJpYW4gYW5kIFJlZCBIYXQsIGFuZCBwZXJo
YXBzIG90aGVyIHZlbmRvcnMsIHByb3ZpZGUgYm90aCBydW50aW1lIGFuZAojIGRldmVsb3BtZW50
IHBhY2thZ2VzIGZvciBzb21lIGxpYnJhcmllcy4gIFRoZSBydW50aW1lIHBhY2thZ2VzIGNvbnRh
aW4gc2hhcmVkCiMgbGlicmFyaWVzIHdpdGggdmVyc2lvbiBpbmZvcm1hdGlvbiBpbiB0aGVpciBu
YW1lcyAoZS5nLiwgbGliZ2RibS5zby4xLjcuMyk7CiMgdGhlIGRldmVsb3BtZW50IHBhY2thZ2Vz
IHN1cHBsZW1lbnQgdGhpcyB3aXRoIHZlcnNpb25sZXNzIHNoYXJlZCBsaWJyYXJpZXMKIyAoZS5n
LiwgbGliZ2RibS5zbykuCiMKIyBJZiB5b3Ugd2FudCB0byBsaW5rIGFnYWluc3Qgc3VjaCBhIGxp
YnJhcnksIHlvdSBtdXN0IGluc3RhbGwgdGhlIGRldmVsb3BtZW50CiMgdmVyc2lvbiBvZiB0aGUg
cGFja2FnZS4KIwojIFRoZXNlIHBhY2thZ2VzIHVzZSBhIC1kZXYgbmFtaW5nIGNvbnZlbnRpb24g
aW4gYm90aCBEZWJpYW4gYW5kIFJlZCBIYXQ6CiMgICBsaWJnZGJtZzEgIChub24tZGV2ZWxvcG1l
bnQgdmVyc2lvbiBvZiBHTlUgbGliYyAyLWxpbmtlZCBHREJNIGxpYnJhcnkpCiMgICBsaWJnZGJt
ZzEtZGV2IChkZXZlbG9wbWVudCB2ZXJzaW9uIG9mIEdOVSBsaWJjIDItbGlua2VkIEdEQk0gbGli
cmFyeSkKIyBTbyBtYWtlIHN1cmUgdGhhdCBmb3IgYW55IGxpYnJhcmllcyB5b3Ugd2lzaCB0byBs
aW5rIFBlcmwgd2l0aCB1bmRlcgojIERlYmlhbiBvciBSZWQgSGF0IHlvdSBoYXZlIHRoZSAtZGV2
IHBhY2thZ2VzIGluc3RhbGxlZC4KCiMgU3VTRSBMaW51eCBjYW4gYmUgdXNlZCBhcyBjcm9zcy1j
b21waWxhdGlvbiBob3N0IGZvciBDcmF5IFhUNCBDYXRhbW91bnQvUWsuCmlmIHRlc3QgLWQgL29w
dC94dC1wZQp0aGVuCiAgY2FzZSAiYGNjIC1WIDI+JjFgIiBpbgogICpjYXRhbW91bnQqKSAuIGhp
bnRzL2NhdGFtb3VudC5zaDsgcmV0dXJuIDs7CiAgZXNhYwpmaQoKIyBTb21lIG9wZXJhdGluZyBz
eXN0ZW1zIChlLmcuLCBTb2xhcmlzIDIuNikgd2lsbCBsaW5rIHRvIGEgdmVyc2lvbmVkIHNoYXJl
ZAojIGxpYnJhcnkgaW1wbGljaXRseS4gIEZvciBleGFtcGxlLCBvbiBTb2xhcmlzLCBgbGQgZm9v
Lm8gLWxnZGJtJyB3aWxsIGZpbmQgYW4KIyBhcHByb3ByaWF0ZSB2ZXJzaW9uIG9mIGxpYmdkYm0s
IGlmIG9uZSBpcyBhdmFpbGFibGU7IExpbnV4LCBob3dldmVyLCBkb2Vzbid0CiMgZG8gdGhlIGlt
cGxpY2l0IG1hcHBpbmcuCmlnbm9yZV92ZXJzaW9uZWRfc29saWJzPSd5JwoKIyBCU0QgY29tcGF0
aWJpbGl0eSBsaWJyYXJ5IG5vIGxvbmdlciBuZWVkZWQKIyAna2FmZmUnIGhhcyBhIC91c3IvbGli
L2xpYm5ldC5zbyB3aGljaCBpcyBub3QgYXQgYWxsIHJlbGV2YW50IGZvciBwZXJsLgojIGJpbmQg
Y2F1c2VzIGlzc3VlcyB3aXRoIHNldmVyYWwgcmVlbnRyYW50IGZ1bmN0aW9ucwpzZXQgYGVjaG8g
WCAiJGxpYnN3YW50ZWQgInwgc2VkIC1lICdzLyBic2QgLyAvJyAtZSAncy8gbmV0IC8gLycgLWUg
J3MvIGJpbmQgLyAvJ2AKc2hpZnQKbGlic3dhbnRlZD0iJCoiCgojIERlYmlhbiA0LjAgcHV0cyBu
ZGJtIGluIHRoZSAtbGdkYm1fY29tcGF0IGxpYnJhcnkuCmxpYnN3YW50ZWQ9IiRsaWJzd2FudGVk
IGdkYm1fY29tcGF0IgoKIyBJZiB5b3UgaGF2ZSBnbGliYywgdGhlbiByZXBvcnQgdGhlIHZlcnNp
b24gZm9yIC4vbXljb25maWcgYnVnIHJlcG9ydGluZy4KIyAoQ29uZmlndXJlIGRvZXNuJ3QgbmVl
ZCB0byBrbm93IHRoZSBzcGVjaWZpYyB2ZXJzaW9uIHNpbmNlIGl0IGp1c3QgdXNlcwojIGdjYyB0
byBsb2FkIHRoZSBsaWJyYXJ5IGZvciBhbGwgdGVzdHMuKQojIFdlIGRvbid0IHVzZSBfX0dMSUJD
X18gYW5kICBfX0dMSUJDX01JTk9SX18gYmVjYXVzZSB0aGV5CiMgYXJlIGluc3VmZmljaWVudGx5
IHByZWNpc2UgdG8gZGlzdGluZ3Vpc2ggdGhpbmdzIGxpa2UKIyBsaWJjLTIuMC42IGFuZCBsaWJj
LTIuMC43LgppZiB0ZXN0IC1MIC9saWIvbGliYy5zby42OyB0aGVuCiAgICBsaWJjPWBscyAtbCAv
bGliL2xpYmMuc28uNiB8IGF3ayAne3ByaW50ICRORn0nYAogICAgbGliYz0vbGliLyRsaWJjCmZp
CgojIENvbmZpZ3VyZSBtYXkgZmFpbCB0byBmaW5kIGxzdGF0KCkgc2luY2UgaXQncyBhIHN0YXRp
Yy9pbmxpbmUKIyBmdW5jdGlvbiBpbiA8c3lzL3N0YXQuaD4uCmRfbHN0YXQ9ZGVmaW5lCgojIG1h
bGxvYyB3cmFwIHdvcmtzCmNhc2UgIiR1c2VtYWxsb2N3cmFwIiBpbgonJykgdXNlbWFsbG9jd3Jh
cD0nZGVmaW5lJyA7Owplc2FjCgojIFRoZSBzeXN0ZW0gbWFsbG9jKCkgaXMgYWJvdXQgYXMgZmFz
dCBhbmQgYXMgZnJ1Z2FsIGFzIHBlcmwncy4KIyBTaW5jZSB0aGUgc3lzdGVtIG1hbGxvYygpIGhh
cyBiZWVuIHRoZSBkZWZhdWx0IHNpbmNlIGF0IGxlYXN0CiMgNS4wMDEsIHdlIG1pZ2h0IGFzIHdl
bGwgbGVhdmUgaXQgdGhhdCB3YXkuICAtLUFEICAxMCBKYW4gMjAwMgpjYXNlICIkdXNlbXltYWxs
b2MiIGluCicnKSB1c2VteW1hbGxvYz0nbicgOzsKZXNhYwoKIyBDaGVjayBpZiB3ZSdyZSBhYm91
dCB0byB1c2UgSW50ZWwncyBJQ0MgY29tcGlsZXIKY2FzZSAiYCR7Y2M6LWNjfSAtViAyPiYxYCIg
aW4KKiJJbnRlbChSKSBDKysgQ29tcGlsZXIiKnwqIkludGVsKFIpIEMgQ29tcGlsZXIiKikKICAg
ICMgcmVjb3JkIHRoZSB2ZXJzaW9uLCBmb3JtYXRzOgogICAgIyBpY2MgKElDQykgMTAuMSAyMDA4
MDgwMQogICAgIyBpY3BjIChJQ0MpIDEwLjEgMjAwODA4MDEKICAgICMgZm9sbG93ZWQgYnkgYSBj
b3B5cmlnaHQgb24gdGhlIHNlY29uZCBsaW5lCiAgICBjY3ZlcnNpb249YCR7Y2M6LWNjfSAtLXZl
cnNpb24gfCBzZWQgLW4gLWUgJ3MvXmljcFw/YyBcKChJQ0MpIFwpXD8vL3AnYAogICAgIyBUaGlz
IGlzIG5lZWRlZCBmb3IgQ29uZmlndXJlJ3MgcHJvdG90eXBlIGNoZWNrcyB0byB3b3JrIGNvcnJl
Y3RseQogICAgIyBUaGUgLW1wIGZsYWcgaXMgbmVlZGVkIHRvIHBhc3MgdmFyaW91cyBmbG9hdGlu
ZyBwb2ludCByZWxhdGVkIHRlc3RzCiAgICAjIFRoZSAtbm8tZ2NjIGZsYWcgaXMgbmVlZGVkIG90
aGVyd2lzZSwgaWNjIHByZXRlbmRzIChwb29ybHkpIHRvIGJlIGdjYwogICAgY2NmbGFncz0iLXdl
MTQ3IC1tcCAtbm8tZ2NjICRjY2ZsYWdzIgogICAgIyBQcmV2ZW50IHJlbG9jYXRpb24gZXJyb3Jz
IG9uIDY0Yml0cyBhcmNoCiAgICBjYXNlICJgdW5hbWUgLW1gIiBpbgoJKmlhNjQqfCp4ODZfNjQq
KQoJICAgIGNjY2RsZmxhZ3M9Jy1mUElDJwoJOzsKICAgIGVzYWMKICAgICMgSWYgd2UncmUgdXNp
bmcgSUNDLCB3ZSB1c3VhbGx5IHdhbnQgdGhlIGJlc3QgcGVyZm9ybWFuY2UKICAgIGNhc2UgIiRv
cHRpbWl6ZSIgaW4KICAgICcnKSBvcHRpbWl6ZT0nLU8zJyA7OwogICAgZXNhYwogICAgOzsKKiIg
U3VuICIqIkMiKikKICAgICMgU3VuJ3MgQyBjb21waWxlciwgd2hpY2ggbWlnaHQgaGF2ZSBhICd0
YWcnIG5hbWUgYmV0d2VlbgogICAgIyAnU3VuJyBhbmQgdGhlICdDJzogIEV4YW1wbGVzOgogICAg
IyBjYzogU3VuIEMgNS45IExpbnV4X2kzODYgUGF0Y2ggMTI0ODcxLTAxIDIwMDcvMDcvMzEKICAg
ICMgY2M6IFN1biBDZXJlcyBDIDUuMTAgTGludXhfaTM4NiAyMDA4LzA3LzEwCiAgICB0ZXN0ICIk
b3B0aW1pemUiIHx8IG9wdGltaXplPScteE8yJwogICAgY2NjZGxmbGFncz0nLUtQSUMnCiAgICBs
ZGRsZmxhZ3M9Jy1HIC1CZHluYW1pYycKICAgICMgU3VuIEMgZG9lc24ndCBzdXBwb3J0IGdjYyBh
dHRyaWJ1dGVzLCBidXQsIGluIG1hbnkgY2FzZXMsIGRvZXNuJ3QKICAgICMgY29tcGxhaW4gZWl0
aGVyLiAgTm90IGFsbCBjYXNlcywgdGhvdWdoLgogICAgZF9hdHRyaWJ1dGVfZm9ybWF0PSd1bmRl
ZicKICAgIGRfYXR0cmlidXRlX21hbGxvYz0ndW5kZWYnCiAgICBkX2F0dHJpYnV0ZV9ub25udWxs
PSd1bmRlZicKICAgIGRfYXR0cmlidXRlX25vcmV0dXJuPSd1bmRlZicKICAgIGRfYXR0cmlidXRl
X3B1cmU9J3VuZGVmJwogICAgZF9hdHRyaWJ1dGVfdW51c2VkPSd1bmRlZicKICAgIGRfYXR0cmli
dXRlX3dhcm5fdW51c2VkX3Jlc3VsdD0ndW5kZWYnCiAgICA7Owplc2FjCgpjYXNlICIkb3B0aW1p
emUiIGluCiMgdXNlIC1PMiBieSBkZWZhdWx0IDsgLU8zIGRvZXNuJ3Qgc2VlbSB0byBicmluZyBz
aWduaWZpY2FudCBiZW5lZml0cyB3aXRoIGdjYwonJykKICAgIG9wdGltaXplPSctTzInCiAgICBj
YXNlICJgdW5hbWUgLW1gIiBpbgogICAgICAgIHBwYyopCiAgICAgICAgICAgICMgb24gcHBjLCBp
dCBzZWVtcyB0aGF0IGdjYyAoYXQgbGVhc3QgZ2NjIDMuMy4yKSBpc24ndCBoYXBweQogICAgICAg
ICAgICAjIHdpdGggLU8yIDsgc28gZG93bmdyYWRlIHRvIC1PMS4KICAgICAgICAgICAgb3B0aW1p
emU9Jy1PMScKICAgICAgICA7OwogICAgICAgIGlhNjQqKQogICAgICAgICAgICAjIFRoaXMgYXJj
aGl0ZWN0dXJlIGhhcyBoYWQgdmFyaW91cyBwcm9ibGVtcyB3aXRoIGdjYydzCiAgICAgICAgICAg
ICMgaW4gdGhlIDMuMiwgMy4zLCBhbmQgMy40IHJlbGVhc2VzIHdoZW4gb3B0aW1pemVkIHRvIC1P
Mi4gIFNlZQogICAgICAgICAgICAjIFJUICMzNzE1NiBmb3IgYSBkaXNjdXNzaW9uIG9mIHRoZSBw
cm9ibGVtLgogICAgICAgICAgICBjYXNlICJgJHtjYzotZ2NjfSAtdiAyPiYxYCIgaW4KICAgICAg
ICAgICAgKiJ2ZXJzaW9uIDMuMiIqfCoidmVyc2lvbiAzLjMiKnwqInZlcnNpb24gMy40IiopCiAg
ICAgICAgICAgICAgICBjY2ZsYWdzPSItZm5vLWRlbGV0ZS1udWxsLXBvaW50ZXItY2hlY2tzICRj
Y2ZsYWdzIgogICAgICAgICAgICA7OwogICAgICAgICAgICBlc2FjCiAgICAgICAgOzsKICAgIGVz
YWMKICAgIDs7CmVzYWMKCiMgVWJ1bnR1IDExLjA0IChhbmQgbGF0ZXIsIHByZXN1bWFibHkpIGRv
ZXNuJ3Qga2VlcCBtb3N0IGxpYnJhcmllcwojIChzdWNoIGFzIC1sbSkgaW4gL2xpYiBvciAvdXNy
L2xpYi4gIFNvIHdlIGhhdmUgdG8gYXNrIGdjYyB0byB0ZWxsIHVzCiMgd2hlcmUgdG8gbG9vay4g
IFdlIGRvbid0IHdhbnQgZ2NjJ3Mgb3duIGxpYnJhcmllcywgaG93ZXZlciwgc28gd2UKIyBmaWx0
ZXIgdGhvc2Ugb3V0LgojIFRoaXMgY291bGQgYmUgY29uZGl0aW9uYWwgb24gVW5idW50dSwgYnV0
IG90aGVyIGRpc3RyaWJ1dGlvbnMgbWF5CiMgZm9sbG93IHN1aXQsIGFuZCB0aGlzIHNjaGVtZSBz
ZWVtcyB0byB3b3JrIGV2ZW4gb24gcmF0aGVyIG9sZCBnY2Mncy4KIyBUaGlzIHVuY29uZGl0aW9u
YWxseSB1c2VzIGdjYyBiZWNhdXNlIGV2ZW4gaWYgdGhlIHVzZXIgaXMgdXNpbmcgYW5vdGhlcgoj
IGNvbXBpbGVyLCB3ZSBzdGlsbCBuZWVkIHRvIGZpbmQgdGhlIG1hdGggbGlicmFyeSBhbmQgZnJp
ZW5kcywgYW5kIEkgZG9uJ3QKIyBrbm93IGhvdyBvdGhlciBjb21waWxlcnMgd2lsbCBjb3BlIHdp
dGggdGhhdCBzaXR1YXRpb24uCiMgTW9yZXZlciwgaWYgdGhlIHVzZXIgaGFzIHRoZWlyIG93biBn
Y2MgZWFybGllciBpbiAkUEFUSCB0aGFuIHRoZSBzeXN0ZW0gZ2NjLAojIHdlIGRvbid0IHdhbnQg
aXRzIGxpYnJhcmllcy4gU28gd2UgdHJ5IHRvIHByZWZlciB0aGUgc3lzdGVtIGdjYwojIFN0aWxs
LCBhcyBhbiBlc2NhcGUgaGF0Y2gsIGFsbG93IENvbmZpZ3VyZSBjb21tYW5kIGxpbmUgb3ZlcnJp
ZGVzIHRvCiMgcGxpYnB0aCB0byBieXBhc3MgdGhpcyBjaGVjay4KaWYgWyAteCAvdXNyL2Jpbi9n
Y2MgXSA7IHRoZW4KICAgIGdjYz0vdXNyL2Jpbi9nY2MKZWxzZQogICAgZ2NjPWdjYwpmaQoKY2Fz
ZSAiJHBsaWJwdGgiIGluCicnKSBwbGlicHRoPWAkZ2NjIC1wcmludC1zZWFyY2gtZGlycyB8IGdy
ZXAgbGlicmFyaWVzIHwKCWN1dCAtZjItIC1kPSB8IHRyICc6JyAkdHJubCB8IGdyZXAgLXYgJ2dj
YycgfCBzZWQgLWUgJ3M6LyQ6OidgCiAgICBzZXQgWCAkcGxpYnB0aCAjIENvbGxhcHNlIGFsbCBl
bnRyaWVzIG9uIG9uZSBsaW5lCiAgICBzaGlmdAogICAgcGxpYnB0aD0iJCoiCiAgICA7Owplc2Fj
CgojIEFyZSB3ZSB1c2luZyBFTEY/ICBUaGFua3MgdG8gS2VubmV0aCBBbGJhbm93c2tpIDxramFo
ZHNAa2phaGRzLmNvbT4KIyBmb3IgdGhpcyB0ZXN0LgpjYXQgPnRyeS5jIDw8J0VPTScKLyogVGVz
dCBmb3Igd2hldGhlciBFTEYgYmluYXJpZXMgYXJlIHByb2R1Y2VkICovCiNpbmNsdWRlIDxmY250
bC5oPgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDx1bmlzdGQuaD4KbWFpbigpIHsKCWNo
YXIgYnVmZmVyWzRdOwoJaW50IGk9b3BlbigiYS5vdXQiLE9fUkRPTkxZKTsKCWlmKGk9PS0xKQoJ
CWV4aXQoMSk7IC8qIGZhaWwgKi8KCWlmKHJlYWQoaSwmYnVmZmVyWzBdLDQpPDQpCgkJZXhpdCgx
KTsgLyogZmFpbCAqLwoJaWYoYnVmZmVyWzBdICE9IDEyNyB8fCBidWZmZXJbMV0gIT0gJ0UnIHx8
CiAgICAgICAgICAgYnVmZmVyWzJdICE9ICdMJyB8fCBidWZmZXJbM10gIT0gJ0YnKQoJCWV4aXQo
MSk7IC8qIGZhaWwgKi8KCWV4aXQoMCk7IC8qIHN1Y2NlZWQgKHllcywgaXQncyBFTEYpICovCn0K
RU9NCmlmICR7Y2M6LWdjY30gdHJ5LmMgPi9kZXYvbnVsbCAyPiYxICYmICRydW4gLi9hLm91dDsg
dGhlbgogICAgY2F0IDw8J0VPTScgPiY0CgpZb3UgYXBwZWFyIHRvIGhhdmUgRUxGIHN1cHBvcnQu
ICBJJ2xsIHRyeSB0byB1c2UgaXQgZm9yIGR5bmFtaWMgbG9hZGluZy4KSWYgZHluYW1pYyBsb2Fk
aW5nIGRvZXNuJ3Qgd29yaywgcmVhZCBoaW50cy9saW51eC5zaCBmb3IgZnVydGhlciBpbmZvcm1h
dGlvbi4KRU9NCgplbHNlCiAgICBjYXQgPDwnRU9NJyA+JjQKCllvdSBkb24ndCBoYXZlIGFuIEVM
RiBnY2MuICBJIHdpbGwgdXNlIGRsZCBpZiBwb3NzaWJsZS4gIElmIHlvdSBhcmUKdXNpbmcgYSB2
ZXJzaW9uIG9mIERMRCBlYXJsaWVyIHRoYW4gMy4yLjYsIG9yIGRvbid0IGhhdmUgaXQgYXQgYWxs
LCB5b3UKc2hvdWxkIHByb2JhYmx5IHVwZ3JhZGUuIElmIHlvdSBhcmUgZm9yY2VkIHRvIHVzZSAz
LjIuNCwgeW91IHNob3VsZAp1bmNvbW1lbnQgYSBjb3VwbGUgb2YgbGluZXMgaW4gaGludHMvbGlu
dXguc2ggYW5kIHJlc3RhcnQgQ29uZmlndXJlIHNvCnRoYXQgc2hhcmVkIGxpYnJhcmllcyB3aWxs
IGJlIGRpc2FsbG93ZWQuCgpFT00KICAgIGxkZGxmbGFncz0iLXIgJGxkZGxmbGFncyIKICAgICMg
VGhlc2UgZW1wdHkgdmFsdWVzIGFyZSBzbyB0aGF0IENvbmZpZ3VyZSBkb2Vzbid0IHB1dCBpbiB0
aGUKICAgICMgTGludXggRUxGIHZhbHVlcy4KICAgIGNjZGxmbGFncz0nICcKICAgIGNjY2RsZmxh
Z3M9JyAnCiAgICBjY2ZsYWdzPSItRE9WUl9EQkxfRElHPTE0ICRjY2ZsYWdzIgogICAgc289J3Nh
JwogICAgZGxleHQ9J28nCiAgICBubV9zb19vcHQ9JyAnCiAgICAjIyBJZiB5b3UgYXJlIHVzaW5n
IERMRCAzLjIuNCB3aGljaCBkb2VzIG5vdCBzdXBwb3J0IHNoYXJlZCBsaWJzLAogICAgIyMgdW5j
b21tZW50IHRoZSBuZXh0IHR3byBsaW5lczoKICAgICNsZGZsYWdzPSItc3RhdGljIgogICAgI3Nv
PSdub25lJwoKCSMgSW4gYWRkaXRpb24sIG9uIHNvbWUgc3lzdGVtcyB0aGVyZSBpcyBhIHByb2Js
ZW0gd2l0aCBwZXJsIGFuZCBOREJNCgkjIHdoaWNoIGNhdXNlcyBBbnlEQk0gYW5kIE5EQk1fRmls
ZSB0byBsb2NrIHVwLiBUaGlzIGlzIGV2aWRlbmNlZAoJIyBpbiB0aGUgdGVzdHMgYXMgQW55REJN
IGp1c3QgZnJlZXppbmcuICBBcHBhcmVudGx5LCB0aGlzIG9ubHkKCSMgaGFwcGVucyBvbiBhLm91
dCBzeXN0ZW1zLCBzbyB3ZSBkaXNhYmxlIE5EQk0gZm9yIGFsbCBhLm91dCBsaW51eAoJIyBzeXN0
ZW1zLiAgSWYgc29tZW9uZSBjYW4gc3VnZ2VzdCBhIG1vcmUgcm9idXN0IHRlc3QKCSMgIHRoYXQg
d291bGQgYmUgYXBwcmVjaWF0ZWQuCgkjCgkjIE1vcmUgaW5mbzoKCSMgRGF0ZTogV2VkLCA3IEZl
YiAxOTk2IDAzOjIxOjA0ICswOTAwCgkjIEZyb206IEplZmZyZXkgRnJpZWRsIDxqZnJpZWRsQG5m
Zi5uY2wub21yb24uY28uanA+CgkjCgkjIEkgdHJpZWQgY29tcGlsaW5nIHdpdGggREJNIHN1cHBv
cnQgYW5kIHN1cmUgZW5vdWdoIHRoaW5ncyBsb2NrZWQgdXAKCSMganVzdCBhcyBhZHZlcnRpc2Vk
LiBDaGVja2luZyBpbnRvIGl0LCBJIGZvdW5kIHRoYXQgdGhlIGxvY2t1cCB3YXMKCSMgZHVyaW5n
IHRoZSBjYWxsIHRvIGRibV9vcGVuLiBOb3QgKmluKiBkYm1fb3BlbiAtLSBidXQgYmV0d2VlbiB0
aGUgY2FsbAoJIyB0byBhbmQgdGhlIGp1bXAgaW50by4KCSMKCSMgVG8gbWFrZSBhIGxvbmcgc3Rv
cnkgc2hvcnQsIG1ha2luZyBzdXJlIHRoYXQgdGhlICouYSBhbmQgKi5zYSBwYWlycyBvZgoJIyAg
IC91c3IvbGliL2xpYnttLGRiLGdkYm19LnthLHNhfQoJIyB3ZXJlIHBlcmZlY3RseSBpbiBzeW5j
IHRvb2sgY2FyZSBvZiBpdC4KCSMKCSMgVGhpcyB3aWxsIGdlbmVyYXRlIGEgaGFybWxlc3MgV2hv
YSBUaGVyZSEgbWVzc2FnZQoJY2FzZSAiJGRfZGJtX29wZW4iIGluCgknJykJY2F0IDw8J0VPTScg
PiY0CgpEaXNhYmxpbmcgbmRibS4gIFRoaXMgd2lsbCBnZW5lcmF0ZSBhIFdob2EgVGhlcmUgbWVz
c2FnZSBpbiBDb25maWd1cmUuClJlYWQgaGludHMvbGludXguc2ggZm9yIGZ1cnRoZXIgaW5mb3Jt
YXRpb24uCkVPTQoJCSMgWW91IGNhbiBvdmVycmlkZSB0aGlzIHdpdGggQ29uZmlndXJlIC1EZF9k
Ym1fb3BlbgoJCWRfZGJtX29wZW49dW5kZWYKCQk7OwoJZXNhYwpmaQoKcm0gLWYgdHJ5LmMgYS5v
dXQKCmlmIC9iaW4vc2ggLWMgZXhpdDsgdGhlbgogIGVjaG8gJycKICBlY2hvICdZb3UgYXBwZWFy
IHRvIGhhdmUgYSB3b3JraW5nIGJhc2guICBHb29kLicKZWxzZQogIGNhdCA8PCAnRU9NJyA+JjQK
CioqKioqKioqKioqKioqKioqKioqKioqIFdhcm5pbmchICoqKioqKioqKioqKioqKioqKioqKgpJ
dCB3b3VsZCBhcHBlYXIgeW91IGhhdmUgYSBkZWZlY3RpdmUgYmFzaCBzaGVsbCBpbnN0YWxsZWQu
IFRoaXMgaXMgbGlrZWx5IHRvCmdpdmUgeW91IGEgZmFpbHVyZSBvZiBvcC9leGVjIHRlc3QgIzUg
ZHVyaW5nIHRoZSB0ZXN0IHBoYXNlIG9mIHRoZSBidWlsZCwKVXBncmFkaW5nIHRvIGEgcmVjZW50
IHZlcnNpb24gKDEuMTQuNCBvciBsYXRlcikgc2hvdWxkIGZpeCB0aGUgcHJvYmxlbS4KKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCkVPTQoKZmkK
CiMgT24gU1BBUkNsaW51eCwKIyBUaGUgZm9sbG93aW5nIGNzaCBjb25zaXN0ZW50bHkgY29yZWR1
bXBlZCBpbiB0aGUgdGVzdCBkaXJlY3RvcnkKIyAiL2hvbWUvbWlrZWRsci9wZXJsNS4wMDNfOTQv
dCIsIHRob3VnaCBub3QgbW9zdCBvdGhlciBkaXJlY3Rvcmllcy4KCiNOYW1lICAgICAgICA6IGNz
aCAgICAgICAgICAgICAgICAgICAgRGlzdHJpYnV0aW9uOiBSZWQgSGF0IExpbnV4IChSZW1icmFu
ZHQpCiNWZXJzaW9uICAgICA6IDUuMi42ICAgICAgICAgICAgICAgICAgICAgICAgVmVuZG9yOiBS
ZWQgSGF0IFNvZnR3YXJlCiNSZWxlYXNlICAgICA6IDMgICAgICAgICAgICAgICAgICAgICAgICBC
dWlsZCBEYXRlOiBGcmkgTWF5IDI0IDE5OjQyOjE0IDE5OTYKI0luc3RhbGwgZGF0ZTogVGh1IEp1
bCAxMSAxNjoyMDoxNCAxOTk2IEJ1aWxkIEhvc3Q6IGl0Y2h5LnJlZGhhdC5jb20KI0dyb3VwICAg
ICAgIDogU2hlbGxzICAgICAgICAgICAgICAgICAgIFNvdXJjZSBSUE06IGNzaC01LjIuNi0zLnNy
Yy5ycG0KI1NpemUgICAgICAgIDogMTg0NDE3CiNEZXNjcmlwdGlvbiA6IEJTRCBjLXNoZWxsCgoj
IEZvciB0aGlzIHJlYXNvbiBJIHN1Z2dlc3QgdXNpbmcgdGhlIG11Y2ggYnVnLWZpeGVkIHRjc2gg
Zm9yIGdsb2JiaW5nCiMgd2hlcmUgYXZhaWxhYmxlLgoKIyBOb3ZlbWJlciAyMDAxOiAgVGhhdCB3
YXJuaW5nJ3MgcHJldHR5IG9sZCBub3cgYW5kIHByb2JhYmx5IG5vdCBzbwojIHJlbGV2YW50LCBl
c3BlY2lhbGx5IHNpbmNlIHBlcmwgbm93IHVzZXMgRmlsZTo6R2xvYiBmb3IgZ2xvYmJpbmcuCiMg
V2UnbGwgc3RpbGwgbG9vayBmb3IgdGNzaCwgYnV0IHRvbmUgZG93biB0aGUgd2FybmluZ3MuCiMg
QW5keSBEb3VnaGVydHksIE5vdi4gNiwgMjAwMQppZiAkY3NoIC1jICdlY2hvICR2ZXJzaW9uJyA+
L2Rldi9udWxsIDI+JjE7IHRoZW4KICAgIGVjaG8gJ1lvdXIgY3NoIGlzIHJlYWxseSB0Y3NoLiAg
R29vZC4nCmVsc2UKICAgIGlmIHh4eD1gLi9VVS9sb2MgdGNzaCBibHVyZmwgJHB0aGA7ICR0ZXN0
IC1mICIkeHh4IjsgdGhlbgoJZWNobyAiRm91bmQgdGNzaC4gIEknbGwgdXNlIGl0IGZvciBnbG9i
YmluZy4iCgkjIFdlIGNhbid0IGNoYW5nZSBDb25maWd1cmUncyBzZXR0aW5nIG9mICRjc2gsIGR1
ZSB0byB0aGUgd2F5CgkjIENvbmZpZ3VyZSBoYW5kbGVzICRkX3BvcnRhYmxlIGFuZCBjb21tYW5k
cyBmb3VuZCBpbiAkbG9jbGlzdC4KCSMgV2UgY2FuIHNldCB0aGUgdmFsdWUgZm9yIENTSCBpbiBj
b25maWcuaCBieSBzZXR0aW5nIGZ1bGxfY3NoLgoJZnVsbF9jc2g9JHh4eAogICAgZWxpZiBbIC1m
ICIkY3NoIiBdOyB0aGVuCgllY2hvICJDb3VsZG4ndCBmaW5kIHRjc2guICBDc2gtYmFzZWQgZ2xv
YmJpbmcgbWlnaHQgYmUgYnJva2VuLiIKICAgIGZpCmZpCgojIFNoaW1wZWkgWWFtYXNoaXRhIDxz
aGltcGVpQHNvY3JhdGVzLnBhdG5ldC5jYWx0ZWNoLmVkdT4KIyBNZXNzYWdlLUlkOiA8MzNFRjE2
MzQuQjM2QjY1MDBAcG9ib3guY29tPgojCiMgVGhlIERSMiBvZiBNa0xpbnV4IChvc25hbWU9bGlu
dXgsYXJjaG5hbWU9cHBjLWxpbnV4KSBtYXkgbmVlZAojIHNwZWNpYWwgZmxhZ3MgcGFzc2VkIGlu
IG9yZGVyIGZvciBkeW5hbWljIGxvYWRpbmcgdG8gd29yay4KIyBpbnN0ZWFkIG9mIHRoZSByZWNv
bW1lbmRlZDoKIwojIGNjZGxmbGFncz0nLXJkeW5hbWljJwojCiMgaXQgc2hvdWxkIGJlOgojIGNj
ZGxmbGFncz0nLVdsLC1FJwojCiMgU28gaWYgeW91ciBEUjIgKERSMyBjYW1lIG91dCBzdW1tZXIg
MTk5OCwgY29uc2lkZXIgdXBncmFkaW5nKQojIGhhcyBwcm9ibGVtcyB3aXRoIGR5bmFtaWMgbG9h
ZGluZywgdW5jb21tZW50IHRoZQojIGZvbGxvd2luZyB0aHJlZSBsaW5lcywgbWFrZSBkaXN0Y2xl
YW4sIGFuZCByZS1Db25maWd1cmU6CiNjYXNlICJgdW5hbWUgLXIgfCBzZWQgJ3MvXlswLTkuLV0q
Ly8nYGBhcmNoYCIgaW4KIydvc2ZtYWNoM3BwYycpIGNjZGxmbGFncz0nLVdsLC1FJyA7OwojZXNh
YwoKY2FzZSAiYHVuYW1lIC1tYCIgaW4Kc3BhcmMqKQoJY2FzZSAiJGNjY2RsZmxhZ3MiIGluCgkq
LWZwaWMqKSBjY2NkbGZsYWdzPSJgZWNobyAkY2NjZGxmbGFnc3xzZWQgJ3MvLWZwaWMvLWZQSUMv
J2AiIDs7CgkqLWZQSUMqKSA7OwoJKikJIGNjY2RsZmxhZ3M9IiRjY2NkbGZsYWdzIC1mUElDIiA7
OwoJZXNhYwoJOzsKZXNhYwoKIyBTdVNFOC4yIGhhcyAvdXNyL2xpYi9saWJuZGJtKiB3aGljaCBh
cmUgbGQgc2NyaXB0cyByYXRoZXIgdGhhbgojIHRydWUgbGlicmFyaWVzLiBUaGUgc2NyaXB0cyBj
YXVzZSBiaW5kaW5nIGFnYWluc3Qgc3RhdGljCiMgdmVyc2lvbiBvZiAtbGdkYm0gd2hpY2ggaXMg
YSBiYWQgaWRlYS4gU28gaWYgd2UgaGF2ZSAnbm0nCiMgbWFrZSBzdXJlIGl0IGNhbiByZWFkIHRo
ZSBmaWxlCiMgTkktUyAyMDAzLzA4LzA3CmlmIFsgLXIgL3Vzci9saWIvbGlibmRibS5zbyAgLWEg
IC14IC91c3IvYmluL25tIF0gOyB0aGVuCiAgIGlmIC91c3IvYmluL25tIC91c3IvbGliL2xpYm5k
Ym0uc28gPi9kZXYvbnVsbCAyPiYxIDsgdGhlbgogICAgZWNobyAnWW91ciBzaGFyZWQgLWxuZGJt
IHNlZW1zIHRvIGJlIGEgcmVhbCBsaWJyYXJ5LicKICAgZWxzZQogICAgZWNobyAnWW91ciBzaGFy
ZWQgLWxuZGJtIGlzIG5vdCBhIHJlYWwgbGlicmFyeS4nCiAgICBzZXQgYGVjaG8gWCAiJGxpYnN3
YW50ZWQgInwgc2VkIC1lICdzLyBuZGJtIC8gLydgCiAgICBzaGlmdAogICAgbGlic3dhbnRlZD0i
JCoiCiAgIGZpCmZpCgoKIyBUaGlzIHNjcmlwdCBVVS91c2V0aHJlYWRzLmNidSB3aWxsIGdldCAn
Y2FsbGVkLWJhY2snIGJ5IENvbmZpZ3VyZQojIGFmdGVyIGl0IGhhcyBwcm9tcHRlZCB0aGUgdXNl
ciBmb3Igd2hldGhlciB0byB1c2UgdGhyZWFkcy4KY2F0ID4gVVUvdXNldGhyZWFkcy5jYnUgPDwn
RU9DQlUnCmlmIGdldGNvbmYgR05VX0xJQlBUSFJFQURfVkVSU0lPTiB8IGdyZXAgTlBUTCA+L2Rl
di9udWxsIDI+L2Rldi9udWxsCnRoZW4KICAgIHRocmVhZHNoYXZlcGlkcz0iIgplbHNlCiAgICB0
aHJlYWRzaGF2ZXBpZHM9Ii1EVEhSRUFEU19IQVZFX1BJRFMiCmZpCmNhc2UgIiR1c2V0aHJlYWRz
IiBpbgokZGVmaW5lfHRydWV8W3lZXSopCiAgICAgICAgY2NmbGFncz0iLURfUkVFTlRSQU5UIC1E
X0dOVV9TT1VSQ0UgJHRocmVhZHNoYXZlcGlkcyAkY2NmbGFncyIKICAgICAgICBpZiBlY2hvICRs
aWJzd2FudGVkIHwgZ3JlcCAtdiBwdGhyZWFkID4vZGV2L251bGwKICAgICAgICB0aGVuCiAgICAg
ICAgICAgIHNldCBgZWNobyBYICIkbGlic3dhbnRlZCAifCBzZWQgLWUgJ3MvIGMgLyBwdGhyZWFk
IGMgLydgCiAgICAgICAgICAgIHNoaWZ0CiAgICAgICAgICAgIGxpYnN3YW50ZWQ9IiQqIgogICAg
ICAgIGZpCgoJIyBTb21laG93IGF0IGxlYXN0IGluIERlYmlhbiAyLjIgdGhlc2UgbWFuYWdlIHRv
IGVzY2FwZQoJIyB0aGUgI2RlZmluZSBmb3Jlc3Qgb2YgPGZlYXR1cmVzLmg+IGFuZCA8dGltZS5o
PiBzbyB0aGF0CgkjIHRoZSBoYXNwcm90byBtYWNybyBvZiBDb25maWd1cmUgZG9lc24ndCBzZWUg
dGhlc2UgcHJvdG9zLAoJIyBldmVuIHdpdGggdGhlIC1EX0dOVV9TT1VSQ0UuCgoJZF9hc2N0aW1l
X3JfcHJvdG89IiRkZWZpbmUiCglkX2NyeXB0X3JfcHJvdG89IiRkZWZpbmUiCglkX2N0aW1lX3Jf
cHJvdG89IiRkZWZpbmUiCglkX2dtdGltZV9yX3Byb3RvPSIkZGVmaW5lIgoJZF9sb2NhbHRpbWVf
cl9wcm90bz0iJGRlZmluZSIKCWRfcmFuZG9tX3JfcHJvdG89IiRkZWZpbmUiCgoJOzsKZXNhYwpF
T0NCVQoKY2F0ID4gVVUvdXNlbGFyZ2VmaWxlcy5jYnUgPDwnRU9DQlUnCiMgVGhpcyBzY3JpcHQg
VVUvdXNlbGFyZ2VmaWxlcy5jYnUgd2lsbCBnZXQgJ2NhbGxlZC1iYWNrJyBieSBDb25maWd1cmUK
IyBhZnRlciBpdCBoYXMgcHJvbXB0ZWQgdGhlIHVzZXIgZm9yIHdoZXRoZXIgdG8gdXNlIGxhcmdl
IGZpbGVzLgpjYXNlICIkdXNlbGFyZ2VmaWxlcyIgaW4KJyd8JGRlZmluZXx0cnVlfFt5WV0qKQoj
IEtlZXAgdGhpcyBpbiB0aGUgbGVmdCBtYXJnaW4uCmNjZmxhZ3NfdXNlbGFyZ2VmaWxlcz0iLURf
TEFSR0VGSUxFX1NPVVJDRSAtRF9GSUxFX09GRlNFVF9CSVRTPTY0IgoKCWNjZmxhZ3M9IiRjY2Zs
YWdzICRjY2ZsYWdzX3VzZWxhcmdlZmlsZXMiCgk7Owplc2FjCkVPQ0JVCgojIFB1cmlmeSBmYWls
cyB0byBsaW5rIFBlcmwgaWYgYSAiLWxjIiBpcyBwYXNzZWQgaW50byBpdHMgbGlua2VyCiMgZHVl
IHRvIGR1cGxpY2F0ZSBzeW1ib2xzLgpjYXNlICIkUFVSSUZZIiBpbgokZGVmaW5lfHRydWV8W3lZ
XSopCiAgICBzZXQgYGVjaG8gWCAiJGxpYnN3YW50ZWQgInwgc2VkIC1lICdzLyBjIC8gLydgCiAg
ICBzaGlmdAogICAgbGlic3dhbnRlZD0iJCoiCiAgICA7Owplc2FjCgojIElmIHdlIGFyZSB1c2lu
ZyBnKysgd2UgbXVzdCB1c2Ugbm0gYW5kIGZvcmNlIG91cnNlbHZlcyB0byB1c2UKIyB0aGUgL3Vz
ci9saWIvbGliYy5hIChyZXNldHRpbmcgdGhlIGxpYmMgYmVsb3cgdG8gYW4gZW1wdHkgc3RyaW5n
CiMgbWFrZXMgQ29uZmlndXJlIHRvIGxvb2sgZm9yIHRoZSByaWdodCBvbmUpIGJlY2F1c2UgdGhl
IHN5bWJvbAojIHNjYW5uaW5nIHRyaWNrcyBvZiBDb25maWd1cmUgd2lsbCBjcmFzaCBhbmQgYnVy
biBob3JyaWJseS4KY2FzZSAiJGNjIiBpbgoqZysrKikgdXNlbm09dHJ1ZQogICAgICAgbGliYz0n
JwogICAgICAgOzsKZXNhYwoKIyBJZiB1c2luZyBnKyssIHRoZSBDb25maWd1cmUgc2NhbiBmb3Ig
ZGxvcGVuKCkgYW5kIChlc3BlY2lhbGx5KQojIGRsZXJyb3IoKSBtaWdodCBmYWlsLCBlYXNpZXIg
anVzdCB0byBmb3JjaWJseSBoaW50IHRoZW0gaW4uCmNhc2UgIiRjYyIgaW4KKmcrKyopCiAgZF9k
bG9wZW49J2RlZmluZScKICBkX2RsZXJyb3I9J2RlZmluZScKICA7Owplc2FjCgojIFVuZGVyIHNv
bWUgY2lyY3Vtc3RhbmNlcyBsaWJkYiBjYW4gZ2V0IGJ1aWx0IGluIHN1Y2ggYSB3YXkgYXMgdG8K
IyBuZWVkIHB0aHJlYWQgZXhwbGljaXRseSBsaW5rZWQuCgpsaWJkYl9uZWVkc19wdGhyZWFkPSJO
IgoKaWYgZWNobyAiICRsaWJzd2FudGVkICIgfCBncmVwIC12ICIgcHRocmVhZCAiID4vZGV2L251
bGwKdGhlbgogICBpZiBlY2hvICIgJGxpYnN3YW50ZWQgIiB8IGdyZXAgIiBkYiAiID4vZGV2L251
bGwKICAgdGhlbgogICAgIGZvciBEQkRJUiBpbiAkZ2xpYnB0aAogICAgIGRvCiAgICAgICBEQkxJ
Qj0iJERCRElSL2xpYmRiLnNvIgogICAgICAgaWYgWyAtZiAkREJMSUIgXQogICAgICAgdGhlbgog
ICAgICAgICBpZiBubSAtdSAkREJMSUIgfCBncmVwIHB0aHJlYWQgPi9kZXYvbnVsbAogICAgICAg
ICB0aGVuCiAgICAgICAgICAgaWYgbGRkICREQkxJQiB8IGdyZXAgcHRocmVhZCA+L2Rldi9udWxs
CiAgICAgICAgICAgdGhlbgogICAgICAgICAgICAgbGliZGJfbmVlZHNfcHRocmVhZD0iTiIKICAg
ICAgICAgICBlbHNlCiAgICAgICAgICAgICBsaWJkYl9uZWVkc19wdGhyZWFkPSJZIgogICAgICAg
ICAgIGZpCiAgICAgICAgIGZpCiAgICAgICBmaQogICAgIGRvbmUKICAgZmkKZmkKCmNhc2UgIiRs
aWJkYl9uZWVkc19wdGhyZWFkIiBpbgogICJZIikKICAgIGxpYnN3YW50ZWQ9IiRsaWJzd2FudGVk
IHB0aHJlYWQiCiAgICA7Owplc2FjCg==',
'dragonfly' =>
'IyBoaW50cy9kcmFnb25mbHkuc2gKIwojIFRoaXMgZmlsZSBpcyBtb3N0bHkgY29waWVkIGZyb20g
aGludHMvZnJlZWJzZC5zaCB3aXRoIHRoZSBPUyB2ZXJzaW9uCiMgaW5mb3JtYXRpb24gdGFrZW4g
b3V0IGFuZCBvbmx5IHRoZSBGcmVlQlNELTQgaW5mb3JtYXRpb24gaW50YWN0LgojIFBsZWFzZSBj
aGVjayB3aXRoIFRvZGQgV2lsbGV5IDx4dG9kZHhAZ21haWwuY29tPiBiZWZvcmUgbWFraW5nCiMg
bW9kaWZpY2F0aW9ucyB0byB0aGlzIGZpbGUuIFNlZSBodHRwOi8vd3d3LmRyYWdvbmZseWJzZC5v
cmcvCgpjYXNlICIkb3N2ZXJzIiBpbgoqKSAgdXNldmZvcms9J3RydWUnCiAgICBjYXNlICIkdXNl
bXltYWxsb2MiIGluCgkiIikgdXNlbXltYWxsb2M9J24nCgkgICAgOzsKICAgIGVzYWMKICAgIGxp
YnN3YW50ZWQ9YGVjaG8gJGxpYnN3YW50ZWQgfCBzZWQgJ3MvIG1hbGxvYyAvIC8nYAogICAgOzsK
ZXNhYwoKIyBEeW5hbWljIExvYWRpbmcgZmxhZ3MgaGF2ZSBub3QgY2hhbmdlZCBtdWNoLCBzbyB0
aGV5IGFyZSBzZXBhcmF0ZWQKIyBvdXQgaGVyZSB0byBhdm9pZCBkdXBsaWNhdGluZyB0aGVtIGV2
ZXJ5d2hlcmUuCmNhc2UgIiRvc3ZlcnMiIGluCiopICBvYmpmb3JtYXQ9YC91c3IvYmluL29iamZv
cm1hdGAKICAgIGxpYnB0aD0iL3Vzci9saWIgL3Vzci9sb2NhbC9saWIiCiAgICBnbGlicHRoPSIv
dXNyL2xpYiAvdXNyL2xvY2FsL2xpYiIKICAgIGxkZmxhZ3M9Ii1XbCwtRSAiCiAgICBsZGRsZmxh
Z3M9Ii1zaGFyZWQgIgogICAgY2NjZGxmbGFncz0nLURQSUMgLWZQSUMnCiAgICA7Owplc2FjCgpj
YXNlICIkb3N2ZXJzIiBpbgoqKSAgY2NmbGFncz0iJHtjY2ZsYWdzfSAtREhBU19GUFNFVE1BU0sg
LURIQVNfRkxPQVRJTkdQT0lOVF9IIgogICAgaWYgL3Vzci9iaW4vZmlsZSAtTCAvdXNyL2xpYi9s
aWJjLnNvIHwgL3Vzci9iaW4vZ3JlcCAtdnEgIm5vdCBzdHJpcHBlZCIgOyB0aGVuCgl1c2VubT1m
YWxzZQogICAgZmkKICAgIDs7CmVzYWMKCmNhdCA8PCdFT00nID4mNAoKU29tZSB1c2VycyBoYXZl
IHJlcG9ydGVkIHRoYXQgQ29uZmlndXJlIGhhbHRzIHdoZW4gdGVzdGluZyBmb3IKdGhlIE9fTk9O
QkxPQ0sgc3ltYm9sIHdpdGggYSBzeW50YXggZXJyb3IuICBUaGlzIGlzIGFwcGFyZW50bHkgYQpz
aCBlcnJvci4gIFJlcnVubmluZyBDb25maWd1cmUgd2l0aCBrc2ggYXBwYXJlbnRseSBmaXhlcyB0
aGUKcHJvYmxlbS4gIFRyeQogICAgICAga3NoIENvbmZpZ3VyZSBbeW91ciBvcHRpb25zXQoKRU9N
CgojIEZyb206IEFudG9uIEJlcmV6aW4gPHRvYmV6QHBsYWIua3UuZGs+CiMgVG86IHBlcmw1LXBv
cnRlcnNAcGVybC5vcmcKIyBTdWJqZWN0OiBbUEFUQ0ggNS4wMDVfNTRdIENvbmZpZ3VyZSAtIGhp
bnRzL2ZyZWVic2Quc2ggc2lnbmFsIGhhbmRsZXIgdHlwZQojIERhdGU6IDMwIE5vdiAxOTk4IDE5
OjQ2OjI0ICswMTAwCiMgTWVzc2FnZS1JRDogPDg2NHNyaGh2Y3YuZnNmQGxpb24ucGxhYi5rdS5k
az4KCnNpZ25hbF90PSd2b2lkJwpkX3ZvaWRzaWc9J2RlZmluZScKCiMgVGhpcyBzY3JpcHQgVVUv
dXNldGhyZWFkcy5jYnUgd2lsbCBnZXQgJ2NhbGxlZC1iYWNrJyBieSBDb25maWd1cmUKIyBhZnRl
ciBpdCBoYXMgcHJvbXB0ZWQgdGhlIHVzZXIgZm9yIHdoZXRoZXIgdG8gdXNlIHRocmVhZHMuCmNh
dCA+IFVVL3VzZXRocmVhZHMuY2J1IDw8J0VPQ0JVJwpjYXNlICIkdXNldGhyZWFkcyIgaW4KJGRl
ZmluZXx0cnVlfFt5WV0qKQogICAgY2FzZSAiJG9zdmVycyIgaW4KICAgICopICBsZGZsYWdzPSIt
cHRocmVhZCAkbGRmbGFncyIKCgkjIEJvdGggaW4gNC54IGFuZCA1LnggZ2V0aG9zdGJ5YWRkcl9y
IGV4aXN0cyBidXQKCSMgaXQgaXMgIlRlbXBvcmFyeSBmdW5jdGlvbiwgbm90IHRocmVhZHNhZmUi
Li4uCgkjIFByZXN1bWFibHkgZWFybGllciBpdCBkaWRuJ3QgZXZlbiBleGlzdC4KCWRfZ2V0aG9z
dGJ5YWRkcl9yPSJ1bmRlZiIKCWRfZ2V0aG9zdGJ5YWRkcl9yX3Byb3RvPSIwIgoKCTs7CiAgICBl
c2FjCmVzYWMKRU9DQlUKCiMgbWFsbG9jIHdyYXAgd29ya3MKY2FzZSAiJHVzZW1hbGxvY3dyYXAi
IGluCicnKSB1c2VtYWxsb2N3cmFwPSdkZWZpbmUnIDs7CmVzYWMK',
'darwin' =>
'IyMKIyBEYXJ3aW4gKE1hYyBPUykgaGludHMKIyBXaWxmcmVkbyBTYW5jaGV6IDx3c2FuY2hlekB3
c2FuY2hlei5uZXQ+CiMjCgojIwojIFBhdGhzCiMjCgojIENvbmZpZ3VyZSBoYXNuJ3QgZmlndXJl
ZCBvdXQgdGhlIHZlcnNpb24gbnVtYmVyIHlldC4gIEJ1bW1lci4KcGVybF9yZXZpc2lvbj1gYXdr
ICcvZGVmaW5lWyAJXStQRVJMX1JFVklTSU9OLyB7cHJpbnQgJDN9JyAkc3JjL3BhdGNobGV2ZWwu
aGAKcGVybF92ZXJzaW9uPWBhd2sgJy9kZWZpbmVbIAldK1BFUkxfVkVSU0lPTi8ge3ByaW50ICQz
fScgJHNyYy9wYXRjaGxldmVsLmhgCnBlcmxfc3VidmVyc2lvbj1gYXdrICcvZGVmaW5lWyAJXStQ
RVJMX1NVQlZFUlNJT04vIHtwcmludCAkM30nICRzcmMvcGF0Y2hsZXZlbC5oYAp2ZXJzaW9uPSIk
e3BlcmxfcmV2aXNpb259LiR7cGVybF92ZXJzaW9ufS4ke3Blcmxfc3VidmVyc2lvbn0iCgojIFBy
ZXRlbmQgdGhhdCBEYXJ3aW4gZG9lc24ndCBrbm93IGFib3V0IHRob3NlIHN5c3RlbSBjYWxscyBp
biBUaWdlcgojICgxMC40L2RhcndpbiA4KSBhbmQgZWFybGllciBbcGVybCAjMjQxMjJdCmNhc2Ug
IiRvc3ZlcnMiIGluClsxLThdLiopCiAgICBkX3NldHJlZ2lkPSd1bmRlZicKICAgIGRfc2V0cmV1
aWQ9J3VuZGVmJwogICAgZF9zZXRyZ2lkPSd1bmRlZicKICAgIGRfc2V0cnVpZD0ndW5kZWYnCiAg
ICA7Owplc2FjCgojIFRoaXMgd2FzIHByZXZpb3VzbHkgdXNlZCBpbiBhbGwgYnV0IGNhdXNlcyB0
aHJlZSBjYXNlcwojIChubyAtRGRwcmVmaXg9LCAtRHByZWZpeD0vdXNyLCAtRHByZWZpeD0vc29t
ZS90aGluZy9lbHNlKQojIGJ1dCB0aGF0IGNhdXNlZCB0b28gbXVjaCBncmllZi4KIyB2ZW5kb3Js
aWI9Ii9TeXN0ZW0vTGlicmFyeS9QZXJsLyR7dmVyc2lvbn0iOyAjIEFwcGxlLXN1cHBsaWVkIG1v
ZHVsZXMKCiMgQlNEIHBhdGhzCmNhc2UgIiRwcmVmaXgiIGluCicnKQkjIERlZmF1bHQgaW5zdGFs
bDsgdXNlIG5vbi1zeXN0ZW0gZGlyZWN0b3JpZXMKCXByZWZpeD0nL3Vzci9sb2NhbCc7CglzaXRl
cHJlZml4PScvdXNyL2xvY2FsJzsKCTs7CicvdXNyJykJIyBXZSBhcmUgYnVpbGRpbmcvcmVwbGFj
aW5nIHRoZSBidWlsdC1pbiBwZXJsCglwcmVmaXg9Jy8nOwoJaW5zdGFsbHByZWZpeD0nLyc7Cgli
aW49Jy91c3IvYmluJzsKCXNpdGVwcmVmaXg9Jy91c3IvbG9jYWwnOwoJIyBXZSBkb24ndCB3YW50
IC91c3IvYmluL0hFQUQgaXNzdWVzLgoJc2l0ZWJpbj0nL3Vzci9sb2NhbC9iaW4nOwoJc2l0ZXNj
cmlwdD0nL3Vzci9sb2NhbC9iaW4nOwoJaW5zdGFsbHVzcmJpbnBlcmw9J2RlZmluZSc7ICMgWW91
IGtuZXcgd2hhdCB5b3Ugd2VyZSBkb2luZy4KCXByaXZsaWI9Ii9TeXN0ZW0vTGlicmFyeS9QZXJs
LyR7dmVyc2lvbn0iOwoJc2l0ZWxpYj0iL0xpYnJhcnkvUGVybC8ke3ZlcnNpb259IjsKCXZlbmRv
cnByZWZpeD0nLyc7Cgl1c2V2ZW5kb3JwcmVmaXg9J2RlZmluZSc7Cgl2ZW5kb3JiaW49Jy91c3Iv
YmluJzsKCXZlbmRvcnNjcmlwdD0nL3Vzci9iaW4nOwoJdmVuZG9ybGliPSIvTmV0d29yay9MaWJy
YXJ5L1BlcmwvJHt2ZXJzaW9ufSI7CgkjIDRCU0QgdXNlcyAke3ByZWZpeH0vc2hhcmUvbWFuLCBu
b3QgJHtwcmVmaXh9L21hbi4KCW1hbjFkaXI9Jy91c3Ivc2hhcmUvbWFuL21hbjEnOwoJbWFuM2Rp
cj0nL3Vzci9zaGFyZS9tYW4vbWFuMyc7CgkjIEJ1dCB1c2VycycgaW5zdGFsbHMgc2hvdWxkbid0
IHRvdWNoIHRoZSBzeXN0ZW0gbWFuIHBhZ2VzLgoJIyBUcmFuc2llbnQgb2Jzb2xldGVkIHN0eWxl
LgoJc2l0ZW1hbjE9Jy91c3IvbG9jYWwvc2hhcmUvbWFuL21hbjEnOwoJc2l0ZW1hbjM9Jy91c3Iv
bG9jYWwvc2hhcmUvbWFuL21hbjMnOwoJIyBOZXcgc3R5bGUuCglzaXRlbWFuMWRpcj0nL3Vzci9s
b2NhbC9zaGFyZS9tYW4vbWFuMSc7CglzaXRlbWFuM2Rpcj0nL3Vzci9sb2NhbC9zaGFyZS9tYW4v
bWFuMyc7Cgk7OwogICopCSMgQW55dGhpbmcgZWxzZTsgdXNlIG5vbi1zeXN0ZW0gZGlyZWN0b3Jp
ZXMsIHVzZSBDb25maWd1cmUgZGVmYXVsdHMKCTs7CmVzYWMKCiMjCiMgVG9vbCBjaGFpbiBzZXR0
aW5ncwojIwoKIyBTaW5jZSB3ZSBjYW4gYnVpbGQgZmF0LCB0aGUgYXJjaG5hbWUgZG9lc24ndCBu
ZWVkIHRoZSBwcm9jZXNzb3IgdHlwZQphcmNobmFtZT0nZGFyd2luJzsKCiMgbm0gaXNuJ3Qga25v
d24gdG8gd29yayBhZnRlciBTbm93IExlb3BhcmQgYW5kIFhDb2RlIDQ7IHRlc3Rpbmcgd2l0aCBP
UyBYIDEwLjUKIyBhbmQgWGNvZGUgMyBzaG93cyBhIHdvcmtpbmcgbm0sIGJ1dCBwcmV0ZW5kaW5n
IGl0IGRvZXNuJ3Qgd29yayBwcm9kdWNlcyBubwojIHByb2JsZW1zLgp1c2VubT0nZmFsc2UnOwoK
Y2FzZSAiJG9wdGltaXplIiBpbgonJykKIyAgICBPcHRpbWl6aW5nIGZvciBzaXplIGFsc28gbWVh
biBsZXNzIHJlc2lkZW50IG1lbW9yeSB1c2FnZSBvbiB0aGUgcGFydAojIG9mIFBlcmwuICBBcHBs
ZSBhc3NlcnRzIHRoYXQgdGhpcyBpcyBhIG1vcmUgaW1wb3J0YW50IG9wdGltaXphdGlvbiB0aGFu
CiMgc2F2aW5nIG9uIENQVSBjeWNsZXMuICBHaXZlbiB0aGF0IG1lbW9yeSBzcGVlZCBoYXMgbm90
IGluY3JlYXNlZCBhdAojIHBhY2Ugd2l0aCBDUFUgc3BlZWQgb3ZlciB0aW1lIChvbiBhbnkgcGxh
dGZvcm0pLCB0aGlzIGlzIHByb2JhYmx5IGEKIyByZWFzb25hYmxlIGFzc2VydGlvbi4KaWYgWyAt
eiAiJHtvcHRpbWl6ZX0iIF07IHRoZW4KICBjYXNlICJgJHtjYzotZ2NjfSAtdiAyPiYxYCIgaW4K
ICAgICoiZ2NjIHZlcnNpb24gMy4iKikgb3B0aW1pemU9Jy1PcycgOzsKICAgICopIG9wdGltaXpl
PSctTzMnIDs7CiAgZXNhYwplbHNlCiAgb3B0aW1pemU9Jy1PMycKZmkKOzsKZXNhYwoKIyAtZm5v
LWNvbW1vbiBiZWNhdXNlIGNvbW1vbiBzeW1ib2xzIGFyZSBub3QgYWxsb3dlZCBpbiBNSF9EWUxJ
QgojIC1EUEVSTF9EQVJXSU46IGFwcGFyZW50bHkgdGhlIF9fQVBQTEVfXyBpcyBub3Qgc2FuY3Rp
b25lZCBieSBBcHBsZQojIGFzIHRoZSB3YXkgdG8gZGlmZmVyZW50aWF0ZSBNYWMgT1MgWC4gIChU
aGUgb2ZmaWNpYWwgbGluZSBpcyB0aGF0CiMgKm5vKiBjcHAgc3ltYm9sIGRvZXMgZGlmZmVyZW50
aWF0ZSBNYWMgT1MgWC4pCmNjZmxhZ3M9IiR7Y2NmbGFnc30gLWZuby1jb21tb24gLURQRVJMX0RB
UldJTiIKCiMgQXQgbGVhc3Qgb24gRGFyd2luIDEuMy54OgojCiMgIyBkZWZpbmUgSU5UMzJfTUlO
IC0yMTQ3NDgzNjQ4CiMgaW50IG1haW4gKCkgewojICBkb3VibGUgYSA9IElOVDMyX01JTjsKIyAg
cHJpbnRmICgiSU5UMzJfTUlOPSVnXG4iLCBhKTsKIyAgcmV0dXJuIDA7CiMgfQojIHdpbGwgb3V0
cHV0OgojIElOVDMyX01JTj0yLjE0NzQ4ZSswOQojIE5vdGUgdGhhdCB0aGUgSU5UMzJfTUlOIGhh
cyBiZWNvbWUgcG9zaXRpdmUuCiMgSU5UMzJfTUlOIGlzIHNldCBpbiAvdXNyL2luY2x1ZGUvc3Rk
aW50LmggYnk6CiMgI2RlZmluZSBJTlQzMl9NSU4gICAgICAgIC0yMTQ3NDgzNjQ4CiMgd2hpY2gg
c2VlbXMgdG8gYnJlYWsgdGhlIGdjYy4gIERlZmluaW5nIElOVDMyX01JTiBhcyAoLTIxNDc0ODM2
NDctMSkKIyBzZWVtcyB0byB3b3JrLiAgSU5UNjRfTUlOIHNlZW1zIHRvIGJlIHNpbWlsYXJseSBi
cm9rZW4uCiMgLS0gTmljaG9sYXMgQ2xhcmssIEtlbiBXaWxsaWFtcywgYW5kIEVkd2FyZCBNb3kK
IwojIFRoaXMgc2VlbXMgdG8gaGF2ZSBiZWVuIGZpeGVkIHNpbmNlIGF0IGxlYXN0IE1hYyBPUyBY
IDEwLjEuMywKIyBzdGRpbnQuaCBkZWZpbmluZyBJTlQzMl9NSU4gYXMgKC1JTlQzMl9NQVgtMSkK
IyAtLSBFZHdhcmQgTW95CiMKY2FzZSAiJChncmVwICdeI2RlZmluZSBJTlQzMl9NSU4nIC91c3Iv
aW5jbHVkZS9zdGRpbnQuaCkiIGluCiAgKi0yMTQ3NDgzNjQ4KSBjY2ZsYWdzPSIke2NjZmxhZ3N9
IC1ESU5UMzJfTUlOX0JST0tFTiAtRElOVDY0X01JTl9CUk9LRU4iIDs7CmVzYWMKCiMgQXZvaWQg
QXBwbGUncyBjcHAgcHJlY29tcGlsZXIsIGJldHRlciBmb3IgZXh0ZW5zaW9ucwppZiBbICJYYGVj
aG8gfCAke2NjfSAtbm8tY3BwLXByZWNvbXAgLUUgLSAyPiYxID4vZGV2L251bGxgIiA9ICJYIiBd
OyB0aGVuCiAgICBjcHBmbGFncz0iJHtjcHBmbGFnc30gLW5vLWNwcC1wcmVjb21wIgoKICAgICMg
VGhpcyBpcyBuZWNlc3NhcnkgYmVjYXVzZSBwZXJsJ3MgYnVpbGQgc3lzdGVtIGRvZXNuJ3QKICAg
ICMgYXBwbHkgY3BwZmxhZ3MgdG8gY2MgY29tcGlsZSBsaW5lcyBhcyBpdCBzaG91bGQuCiAgICBj
Y2ZsYWdzPSIke2NjZmxhZ3N9ICR7Y3BwZmxhZ3N9IgpmaQoKIyBLbm93biBvcHRpbWl6ZXIgcHJv
YmxlbXMuCmNhc2UgImBjYyAtdiAyPiYxYCIgaW4KICAqIjMuMSAyMDAyMDEwNSIqKSB0b2tlX2Nm
bGFncz0nb3B0aW1pemU9IiInIDs7CmVzYWMKCiMgU2hhcmVkIGxpYnJhcnkgZXh0ZW5zaW9uIGlz
IC5keWxpYi4KIyBCdW5kbGUgZXh0ZW5zaW9uIGlzIC5idW5kbGUuCmxkPSdjYyc7CnNvPSdkeWxp
Yic7CmRsZXh0PSdidW5kbGUnOwp1c2VkbD0nZGVmaW5lJzsKCiMgMTAuNCBjYW4gdXNlIGRsb3Bl
bi4KIyAxMC40IGJyb2tlIHBvbGwoKS4KY2FzZSAiJG9zdmVycyIgaW4KWzEtN10uKikKICAgIGRs
c3JjPSdkbF9keWxkLnhzJzsKICAgIDs7CiopCiAgICBkbHNyYz0nZGxfZGxvcGVuLnhzJzsKICAg
IGRfcG9sbD0ndW5kZWYnOwogICAgaV9wb2xsPSd1bmRlZic7CiAgICA7Owplc2FjCgpjYXNlICIk
Y2NkbGZsYWdzIiBpbgkJIyBJZiBwYXNzZWQgaW4gZnJvbSBjb21tYW5kIGxpbmUsIHByZXN1bWUg
dXNlciBrbm93cyBiZXN0CicnKQogICBjY2NkbGZsYWdzPScgJzsgIyBzcGFjZSwgbm90IGVtcHR5
LCBiZWNhdXNlIG90aGVyd2lzZSB3ZSBnZXQgLWZwaWMKOzsKZXNhYwoKIyBQZXJsIGJ1bmRsZXMg
ZG8gbm90IGV4cGVjdCB0d28tbGV2ZWwgbmFtZXNwYWNlLCBhZGRlZCBpbiBEYXJ3aW4gMS40Lgoj
IEJ1dCBzdGFydGluZyBmcm9tIHBlcmwgNS44LjEvRGFyd2luIDcgdGhlIGRlZmF1bHQgaXMgdGhl
IHR3by1sZXZlbC4KY2FzZSAiJG9zdmVycyIgaW4KMS5bMC0zXS4qKQogICBsZGRsZmxhZ3M9IiR7
bGRmbGFnc30gLWJ1bmRsZSAtdW5kZWZpbmVkIHN1cHByZXNzIgogICA7OwoxLiopCiAgIGxkZmxh
Z3M9IiR7bGRmbGFnc30gLWZsYXRfbmFtZXNwYWNlIgogICBsZGRsZmxhZ3M9IiR7bGRmbGFnc30g
LWJ1bmRsZSAtdW5kZWZpbmVkIHN1cHByZXNzIgogICA7OwpbMi02XS4qKQogICBsZGZsYWdzPSIk
e2xkZmxhZ3N9IC1mbGF0X25hbWVzcGFjZSIKICAgbGRkbGZsYWdzPSIke2xkZmxhZ3N9IC1idW5k
bGUgLXVuZGVmaW5lZCBzdXBwcmVzcyIKICAgOzsKKikgCiAgIGxkZGxmbGFncz0iJHtsZGZsYWdz
fSAtYnVuZGxlIC11bmRlZmluZWQgZHluYW1pY19sb29rdXAiCiAgIGNhc2UgIiRsZCIgaW4KICAg
ICAgICpNQUNPU1hfREVWRUxPUE1FTlRfVEFSR0VUKikgOzsKICAgICAgICopIGxkPSJlbnYgTUFD
T1NYX0RFUExPWU1FTlRfVEFSR0VUPTEwLjMgJHtsZH0iIDs7CiAgIGVzYWMKICAgOzsKZXNhYwps
ZGxpYnB0aG5hbWU9J0RZTERfTElCUkFSWV9QQVRIJzsKCiMgdXNlc2hycGxpYj10cnVlIHJlc3Vs
dHMgaW4gbXVjaCBzbG93ZXIgc3RhcnR1cCB0aW1lcy4KIyAnZmFsc2UnIGlzIHRoZSBkZWZhdWx0
IHZhbHVlLiAgVXNlIENvbmZpZ3VyZSAtRHVzZXNocnBsaWIgdG8gb3ZlcnJpZGUuCgpjYXQgPiBV
VS9hcmNobmFtZS5jYnUgPDwnRU9DQlUnCiMgVGhpcyBzY3JpcHQgVVUvYXJjaG5hbWUuY2J1IHdp
bGwgZ2V0ICdjYWxsZWQtYmFjaycgYnkgQ29uZmlndXJlIAojIGFmdGVyIGl0IGhhcyBvdGhlcndp
c2UgZGV0ZXJtaW5lZCB0aGUgYXJjaGl0ZWN0dXJlIG5hbWUuCmNhc2UgIiRsZGZsYWdzIiBpbgoq
Ii1mbGF0X25hbWVzcGFjZSIqKSA7OyAjIEJhY2t3YXJkIGNvbXBhdCwgYmUgZmxhdC4KIyBJZiB3
ZSBhcmUgdXNpbmcgdHdvLWxldmVsIG5hbWVzcGFjZSwgd2Ugd2lsbCBtdW5nZSB0aGUgYXJjaG5h
bWUgdG8gc2hvdyBpdC4KKikgYXJjaG5hbWU9IiR7YXJjaG5hbWV9LTJsZXZlbCIgOzsKZXNhYwpF
T0NCVQoKIyA2NC1iaXQgYWRkcmVzc2luZyBzdXBwb3J0LiBDdXJyZW50bHkgc3RyaWN0bHkgZXhw
ZXJpbWVudGFsLiBERkQgMjAwNS0wNi0wNgpjYXNlICIkdXNlNjRiaXRhbGwiIGluCiRkZWZpbmV8
dHJ1ZXxbeVldKikKY2FzZSAiJG9zdmVycyIgaW4KWzEtN10uKikKICAgICBjYXQgPDxFT00gPiY0
CgoKCioqKiA2NC1iaXQgYWRkcmVzc2luZyBpcyBub3Qgc3VwcG9ydGVkIGZvciBNYWMgT1MgWCB2
ZXJzaW9ucwoqKiogYmVsb3cgMTAuNCAoIlRpZ2VyIikgb3IgRGFyd2luIHZlcnNpb25zIGJlbG93
IDguIFBsZWFzZSB0cnkKKioqIGFnYWluIHdpdGhvdXQgLUR1c2U2NGJpdGFsbC4gKC1EdXNlNjRi
aXRpbnQgd2lsbCB3b3JrLCBob3dldmVyLikKCkVPTQogICAgIGV4aXQgMQogIDs7CiopCiAgICBj
YXNlICIkb3N2ZXJzIiBpbgogICAgOC4qKQogICAgICAgIGNhdCA8PEVPTSA+JjQKCgoKKioqIFBl
cmwgNjQtYml0IGFkZHJlc3Npbmcgc3VwcG9ydCBpcyBleHBlcmltZW50YWwgZm9yIE1hYyBPUyBY
CioqKiAxMC40ICgiVGlnZXIiKSBhbmQgRGFyd2luIHZlcnNpb24gOC4gU3lzdGVtIFYgSVBDIGlz
IGRpc2FibGVkCioqKiBkdWUgdG8gcHJvYmxlbXMgd2l0aCB0aGUgNjQtYml0IHZlcnNpb25zIG9m
IG1zZ2N0bCwgc2VtY3RsLAoqKiogYW5kIHNobWN0bC4gWW91IHNob3VsZCBhbHNvIGV4cGVjdCB0
aGUgZm9sbG93aW5nIHRlc3QgZmFpbHVyZXM6CioqKgoqKiogICAgZXh0L3RocmVhZHMtc2hhcmVk
L3Qvd2FpdCAodGhyZWFkZWQgYnVpbGRzIG9ubHkpCgpFT00KCiAgICAgICAgWyAiJGRfbXNnY3Rs
IiBdIHx8IGRfbXNnY3RsPSd1bmRlZicKICAgICAgICBbICIkZF9zZW1jdGwiIF0gfHwgZF9zZW1j
dGw9J3VuZGVmJwogICAgICAgIFsgIiRkX3NobWN0bCIgXSB8fCBkX3NobWN0bD0ndW5kZWYnCiAg
ICA7OwogICAgZXNhYwoKICAgIGNhc2UgYHVuYW1lIC1wYCBpbiAKICAgIHBvd2VycGMpIGFyY2g9
cHBjNjQgOzsKICAgIGkzODYpIGFyY2g9eDg2XzY0IDs7CiAgICAqKSBjYXQgPDxFT00gPiY0Cgoq
KiogRG9uJ3QgcmVjb2duaXplIHByb2Nlc3NvciwgY2FuJ3Qgc3BlY2lmeSA2NCBiaXQgY29tcGls
YXRpb24uCgpFT00KICAgIDs7CiAgICBlc2FjCiAgICBmb3IgdmFyIGluIGNjZmxhZ3MgY3BwZmxh
Z3MgbGQgbGRmbGFncwogICAgZG8KICAgICAgIGV2YWwgJHZhcj0iXCQke3Zhcn1cIC1hcmNoXCAk
YXJjaCIKICAgIGRvbmUKCiAgICA7Owplc2FjCjs7CmVzYWMKCiMjCiMgU3lzdGVtIGxpYnJhcmll
cwojIwoKIyB2Zm9yayB3b3Jrcwp1c2V2Zm9yaz0ndHJ1ZSc7CgojIG1hbGxvYyB3cmFwIHdvcmtz
CmNhc2UgIiR1c2VtYWxsb2N3cmFwIiBpbgonJykgdXNlbWFsbG9jd3JhcD0nZGVmaW5lJyA7Owpl
c2FjCgojIG91ciBtYWxsb2Mgd29ya3MgKGJ1dCBhbGxvdyB1c2VycyB0byBvdmVycmlkZSkKY2Fz
ZSAiJHVzZW15bWFsbG9jIiBpbgonJykgdXNlbXltYWxsb2M9J24nIDs7CmVzYWMKIyBIb3dldmVy
IHNicmsoKSByZXR1cm5zIC0xIChmYWlsdXJlKSBzb21ld2hlcmUgaW4gbGliL3VuaWNvcmUvbWt0
YWJsZXMgYXQKIyBhcm91bmQgMTRNLCBzbyB3ZSBuZWVkIHRvIHVzZSBzeXN0ZW0gbWFsbG9jKCkg
YXMgb3VyIHNicmsoKQptYWxsb2NfY2ZsYWdzPSdjY2ZsYWdzPSItRFVTRV9QRVJMX1NCUksgLURQ
RVJMX1NCUktfVklBX01BTExPQyAkY2NmbGFncyInCgojIExvY2FsZXMgYXJlbid0IGZlZWxpbmcg
d2VsbC4KTENfQUxMPUM7IGV4cG9ydCBMQ19BTEw7CkxBTkc9QzsgZXhwb3J0IExBTkc7CgojCiMg
VGhlIGxpYnJhcmllcyBhcmUgbm90IHRocmVhZHNhZmUgYXMgb2YgT1MgWCAxMC4xLgojCiMgRml4
IHdoZW4gQXBwbGUgZml4ZXMgbGliYy4KIwpjYXNlICIkdXNldGhyZWFkcyR1c2VpdGhyZWFkcyIg
aW4KICAqZGVmaW5lKikKICBjYXNlICIkb3N2ZXJzIiBpbgogICAgWzEyMzQ1XS4qKSAgICAgY2F0
IDw8RU9NID4mNAoKCgoqKiogV2FybmluZywgdGhlcmUgbWlnaHQgYmUgcHJvYmxlbXMgd2l0aCB5
b3VyIGxpYnJhcmllcyB3aXRoCioqKiByZWdhcmRzIHRvIHRocmVhZGluZy4gIFRoZSB0ZXN0IGV4
dC90aHJlYWRzL3QvbGliYy50IGlzIGxpa2VseQoqKiogdG8gZmFpbC4KCkVPTQogICAgOzsKICAg
ICopIHVzZXJlZW50cmFudD0nZGVmaW5lJzs7CiAgZXNhYwoKZXNhYwoKIyBGaW5rIGNhbiBpbnN0
YWxsIGEgR0RCTSBsaWJyYXJ5IHRoYXQgY2xhaW1zIHRvIGhhdmUgdGhlIE9EQk0gaW50ZXJmYWNl
cwojIGJ1dCBQZXJsIGR5bmFsb2FkZXIgY2Fubm90IGZvciBzb21lIHJlYXNvbiB1c2UgdGhhdCBs
aWJyYXJ5LiAgV2UgZG9uJ3QKIyByZWFsbHkgbmVlZCBPREJNX0ZJbGUsIHRob3VnaCwgc28gbGV0
J3MganVzdCBoaW50IE9EQk0gYXdheS4KaV9kYm09dW5kZWY7CgojIENvbmZpZ3VyZSBkb2Vzbid0
IGRldGVjdCByYW5saWIgb24gVGlnZXIgcHJvcGVybHkuCiMgTmVpbFcgc2F5cyB0aGlzIHNob3Vs
ZCBiZSBhY2NlcHRhYmxlIG9uIGFsbCBkYXJ3aW4gdmVyc2lvbnMuCnJhbmxpYj0ncmFubGliJwoK
IyMKIyBCdWlsZCBwcm9jZXNzCiMjCgojIENhc2UtaW5zZW5zaXRpdmUgZmlsZXN5c3RlbXMgZG9u
J3QgZ2V0IGFsb25nIHdpdGggTWFrZWZpbGUgYW5kCiMgbWFrZWZpbGUgaW4gdGhlIHNhbWUgcGxh
Y2UuICBTaW5jZSBEYXJ3aW4gdXNlcyBHTlUgbWFrZSwgdGhpcyBkb2RnZXMKIyB0aGUgcHJvYmxl
bS4KZmlyc3RtYWtlZmlsZT1HTlVtYWtlZmlsZTsK',
'hpux' =>
'IyEvdXNyL2Jpbi9zaAoKIyMjIFNZU1RFTSBBUkNISVRFQ1RVUkUKCiMgRGV0ZXJtaW5lIHRoZSBh
cmNoaXRlY3R1cmUgdHlwZSBvZiB0aGlzIHN5c3RlbS4KIyBLZWVwIGxlYWRpbmcgdGFiIGJlbG93
IC0tIENvbmZpZ3VyZSBCbGFjayBNYWdpYyAtLSBSQU0sIDAzLzAyLzk3Cgl4eE9zUmV2TWFqb3I9
YHVuYW1lIC1yIHwgc2VkIC1lICdzL15bXjAtOV0qLy8nIHwgY3V0IC1kLiAtZjFgOwoJeHhPc1Jl
dk1pbm9yPWB1bmFtZSAtciB8IHNlZCAtZSAncy9eW14wLTldKi8vJyB8IGN1dCAtZC4gLWYyYDsK
CXh4T3NSZXY9YGV4cHIgMTAwIFwqICR4eE9zUmV2TWFqb3IgKyAkeHhPc1Jldk1pbm9yYAppZiBb
ICIkeHhPc1Jldk1ham9yIiAtZ2UgMTAgXTsgdGhlbgogICAgIyBUaGlzIHN5c3RlbSBpcyBydW5u
aW5nID49IDEwLngKCiAgICAjIFRlc3RlZCBvbiAxMC4wMSBQQTEueCBhbmQgMTAuMjAgUEFbMTJd
LnguCiAgICAjIElkZWE6IFNjYW4gL3Vzci9pbmNsdWRlL3N5cy91bmlzdGQuaCBmb3IgbWF0Y2hl
cyB3aXRoCiAgICAjICIjZGVmaW5lIENQVV8qIGBnZXRjb25mICMgQ1BVX1ZFUlNJT05gIiB0byBk
ZXRlcm1pbmUgQ1BVIHR5cGUuCiAgICAjIE5vdGUgdGhlIHRleHQgZm9sbG93aW5nICJDUFVfIiBp
cyB1c2VkLCAqTk9UKiB0aGUgY29tbWVudC4KICAgICMKICAgICMgQVNTVU1QVElPTlM6IE51bWJl
cnMgd2lsbCBjb250aW51ZSB0byBiZSBkZWZpbmVkIGluIGhleCAtLSBhbmQgaW4KICAgICMgL3Vz
ci9pbmNsdWRlL3N5cy91bmlzdGQuaCAtLSBhbmQgdGhlIENQVV8qICNkZWZpbmVzIHdpbGwgYmUg
a2VwdAogICAgIyB1cCB0byBkYXRlIHdpdGggbmV3IENQVS9PUyByZWxlYXNlcy4KICAgIHh4Y3B1
PWBnZXRjb25mIENQVV9WRVJTSU9OYDsgIyBHZXQgdGhlIG51bWJlci4KICAgIHh4Y3B1PWBwcmlu
dGYgJzB4JXgnICR4eGNwdWA7ICMgY29udmVydCB0byBoZXgKICAgIGFyY2huYW1lPWBzZWQgLW4g
LWUgInMvXiNbWzpzcGFjZTpdXSpkZWZpbmVbWzpzcGFjZTpdXSpDUFVfLy9wIiAvdXNyL2luY2x1
ZGUvc3lzL3VuaXN0ZC5oIHwKCXNlZCAtbiAtZSAicy9bWzpzcGFjZTpdXSokeHhjcHVbWzpzcGFj
ZTpdXS4qLy9wIiB8CglzZWQgLWUgcy9fUklTQy8tUklTQy8gLWUgcy9IUF8vLyAtZSBzL18vLi8g
LWUgInMvW1s6c3BhY2U6XV0qLy9nImA7CmVsc2UKICAgICMgVGhpcyBzeXN0ZW0gaXMgcnVubmlu
ZyA8PSA5LngKICAgICMgVGVzdGVkIG9uIDkuMFs1N10gUEEgYW5kIFs3OF0uMCBNQzY4MFsyM10w
LiAgSWRlYTogQWZ0ZXIgcmVtb3ZpbmcKICAgICMgTUM2ODg4WzEyXSBmcm9tIGNvbnRleHQgc3Ry
aW5nLCB1c2UgZmlyc3QgQ1BVIGlkZW50aWZpZXIuCiAgICAjCiAgICAjIEFTU1VNUFRJT046IE9u
bHkgQ1BVIGlkZW50aWZpZXJzIGNvbnRhaW4gbm8gbG93ZXJjYXNlIGxldHRlcnMuCiAgICBhcmNo
bmFtZT1gZ2V0Y29udGV4dCB8IHRyICcgJyAnXDAxMicgfCBncmVwIC12ICdbYS16XScgfCBncmVw
IC12IE1DNjg4IHwKCXNlZCAtZSAncy9IUC0vLycgLWUgMXFgOwogICAgc2VsZWN0dHlwZT0naW50
IConCiAgICBmaQoKIyBGb3Igc29tZSBzdHJhbmdlIHJlYXNvbiwgdGhlIHUzMmFsaWduIHRlc3Qg
ZnJvbSBDb25maWd1cmUgaGFuZ3MgaW4KIyBIUC1VWCAxMC4yMCBzaW5jZSB0aGUgRGVjZW1iZXIg
MjAwMSBwYXRjaGVzLiAgU28gaGludCBpdCB0byBhdm9pZAojIHRoZSB0ZXN0LgppZiBbICIkeHhP
c1Jldk1ham9yIiAtbGUgMTAgXTsgdGhlbgogICAgZF91MzJhbGlnbj0kZGVmaW5lCiAgICBmaQoK
ZWNobyAiQXJjaG5hbWUgaXMgJGFyY2huYW1lIgoKIyBGaXggWFNsaWIgKENQQU4pIGNvbmZ1c2lv
biB3aGVuIHJlLXVzaW5nIGEgcHJlZml4IGJ1dCBjaGFuZ2luZyBmcm9tIElMUDMyCiMgdG8gTFA2
NCBidWlsZHMuICBUaGV5J3JlIE5PVCBiaW5hcnkgY29tcGF0aWJsZSwgc28gcXVpdCBjbGFpbWlu
ZyB0aGV5IGFyZS4KYXJjaG5hbWU2ND1MUDY0CgoKIyMjIEhQLVVYIE9TIHNwZWNpZmljIGJlaGF2
aW91cgoKIyAtbGRibSBpcyBvYnNvbGV0ZSBhbmQgc2hvdWxkIG5vdCBiZSB1c2VkCiMgLWxCU0Qg
Y29udGFpbnMgQlNELXN0eWxlIGR1cGxpY2F0ZXMgb2YgU1ZSNCByb3V0aW5lcyB0aGF0IGNhdXNl
IGNvbmZ1c2lvbgojIC1sUFcgaXMgb2Jzb2xldGUgYW5kIHNob3VsZCBub3QgYmUgdXNlZAojIFRo
ZSBsaWJyYXJpZXMgY3J5cHQsIG1hbGxvYywgbmRpciwgYW5kIG5ldCBhcmUgZW1wdHkuCnNldCBg
ZWNobyAiWCAkbGlic3dhbnRlZCAiIHwgc2VkIC1lICdzLyBsZCAvIC8nIC1lICdzLyBkYm0gLyAv
JyAtZSAncy8gQlNEIC8gLycgLWUgJ3MvIFBXIC8gLydgCnNoaWZ0CmxpYnN3YW50ZWQ9IiQqIgoK
Y2M9JHtjYzotY2N9CmFyPS91c3IvYmluL2FyCSMgWWVzLCB0cnVseSBvdmVycmlkZS4gIFdlIGRv
IG5vdCB3YW50IHRoZSBHTlUgYXIuCmZ1bGxfYXI9JGFyCSMgSSByZXBlYXQsIG5vIEdOVSBhci4g
IGFycnIuCgpzZXQgYGVjaG8gIlggJGNjZmxhZ3MgIiB8IHNlZCAtZSAncy8gLUFbZWFdIC8gLycg
LWUgJ3MvIC1EX0hQVVhfU09VUkNFIC8gLydgCnNoaWZ0CgljY19jcHBmbGFncz0iJCogLURfSFBV
WF9TT1VSQ0UiCmNwcGZsYWdzPSItQWEgLURfX1NURENfRVhUX18gJGNjX2NwcGZsYWdzIgoKY2Fz
ZSAiJHByZWZpeCIgaW4KICAgICIiKSBwcmVmaXg9Jy9vcHQvcGVybDUnIDs7CiAgICBlc2FjCgog
ICAgZ251X2FzPW5vCiAgICBnbnVfbGQ9bm8KY2FzZSBgJGNjIC12IDI+JjFgIiIgaW4KICAgICpn
Y2MqKSAgY2Npc2djYz0iJGRlZmluZSIKCSAgICBjY2ZsYWdzPSIkY2NfY3BwZmxhZ3MiCgkgICAg
aWYgWyAiWCRnY2N2ZXJzaW9uIiA9ICJYIiBdOyB0aGVuCgkJIyBEb25lIHRvbyBsYXRlIGluIENv
bmZpZ3VyZSBpZiBoaW50ZWQKCQlnY2N2ZXJzaW9uPWAkY2MgLWR1bXB2ZXJzaW9uYAoJCWZpCgkg
ICAgY2FzZSAiJGdjY3ZlcnNpb24iIGluCgkJWzAxMl0qKSAjIEhQLVVYIGFuZCBnY2MtMi4qIGJy
ZWFrIFVJTlQzMl9NQVggOi0oCgkJCWNjZmxhZ3M9IiRjY2ZsYWdzIC1EVUlOVDMyX01BWF9CUk9L
RU4iCgkJCTs7CgkJWzM0XSopICMgR0NDIChib3RoIDMyYml0IGFuZCA2NGJpdCkgd2lsbCBkZWZp
bmUgX19TVERDX0VYVF9fCiAgICAgICAgICAgICAgICAgICAgICAgIyBieSBkZWZhdWx0IHdoZW4g
dXNpbmcgR0NDIDMuMCBhbmQgbmV3ZXIgdmVyc2lvbnMgb2YKICAgICAgICAgICAgICAgICAgICAg
ICAjIHRoZSBjb21waWxlci4KICAgICAgICAgICAgICAgICAgICAgICBjcHBmbGFncz0iJGNjX2Nw
cGZsYWdzIgogICAgICAgICAgICAgICAgICAgICAgIDs7CgkJZXNhYwoJICAgIGNhc2UgImBnZXRj
b25mIEtFUk5FTF9CSVRTIDI+L2Rldi9udWxsYCIgaW4KCQkqNjQqKQoJCSAgICBlY2hvICJtYWlu
KCl7fSI+dHJ5LmMKCQkgICAgY2FzZSAiJGdjY3ZlcnNpb24iIGluCgkJCVszNF0qKQoJCQkgICAg
Y2FzZSAiJGFyY2huYW1lIiBpbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUEEtUklT
QyopCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiJGNjZmxhZ3MiIGlu
CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICotbXBhLXJpc2MqKSA7Owog
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqKSBjY2ZsYWdzPSIkY2NmbGFn
cyAtbXBhLXJpc2MtMi0wIiA7OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICBlc2FjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOzsKCQkJCWVzYWMKCQkJ
ICAgIDs7CgkJCSopICAjIGdjYyB3aXRoIGdhcyB3aWxsIG5vdCBhY2NlcHQgK0RBMi4wCgkJCSAg
ICBjYXNlICJgJGNjIC1jIC1XYSwrREEyLjAgdHJ5LmMgMj4mMWAiIGluCgkJCQkqIitEQTIuMCIq
KQkJIyBnYXMKCQkJCSAgICBnbnVfYXM9eWVzCgkJCQkgICAgOzsKCQkJCSopCQkJIyBIUGFzCgkJ
CQkgICAgY2NmbGFncz0iJGNjZmxhZ3MgLVdhLCtEQTIuMCIKCQkJCSAgICA7OwoJCQkJZXNhYwoJ
CQkgICAgOzsKCQkJZXNhYwoJCSAgICAjIGdjYyB3aXRoIGdsZCB3aWxsIG5vdCBhY2NlcHQgK3Zu
b2NvbXBhdHdhcm5pbmdzCgkJICAgIGNhc2UgImAkY2MgLW8gdHJ5IC1XbCwrdm5vY29tcGF0d2Fy
bmluZ3MgdHJ5LmMgMj4mMWAiIGluCgkJCSoiK3Zub2NvbXBhdCIqKQkJIyBnbGQKCQkJICAgIGdu
dV9sZD15ZXMKCQkJICAgIDs7CgkJCSopCQkJIyBIUGxkCgkJCSAgIGNhc2UgIiRnY2N2ZXJzaW9u
IiBpbgoJCQkgICAgICAgWzEyXSopCgkJCQkgICAjIFdoeSBub3QgMyBhcyB3ZWxsIGhlcmU/CgkJ
CQkgICAjIFNpbmNlIG5vdCByZWxldmFudCB0byBJQTY0LCBub3QgY2hhbmdlZC4KCQkJCSAgIGxk
ZmxhZ3M9IiRsZGZsYWdzIC1XbCwrdm5vY29tcGF0d2FybmluZ3MiCgkJCQkgICBjY2ZsYWdzPSIk
Y2NmbGFncyAtV2wsK3Zub2NvbXBhdHdhcm5pbmdzIgoJCQkJICAgOzsKCQkJICAgICAgIGVzYWMK
CQkJICAgIDs7CgkJCWVzYWMKCQkgICAgcm0gLWYgdHJ5LmMKCQkgICAgOzsKCQllc2FjCgkgICAg
OzsKICAgICopICAgICAgY2Npc2djYz0nJwoJICAgICMgV2hhdCBjYW5ub3QgYmUgdXNlIGluIGNv
bWJpbmF0aW9uIHdpdGggY2NhY2hlIGxpbmtzIDooCgkgICAgY2NfZm91bmQ9IiIKCSAgICBmb3Ig
cCBpbiBgZWNobyAkUEFUSCB8IHRyIDogJyAnJ2AgOyBkbwoJCXg9IiRwL2NjIgoJCWlmIFsgLWYg
JHggXSAmJiBbIC14ICR4IF07IHRoZW4KCQkgICAgaWYgWyAtaCAkeCBdOyB0aGVuCgkJCWw9YGxz
IC1sICR4IHwgc2VkICdzLC4qLT4gLCwnYAoJCQljYXNlICRsIGluCgkJCSAgICAvKikgeD0kbAkJ
OzsKCQkJICAgICopICB4PSIkcC8kbCIJOzsKCQkJICAgIGVzYWMKCQkJZmkKCQkgICAgeD1gZWNo
byAkeCB8IHNlZCAncywvXC4vLC8sZydgCgkJICAgIGNhc2UgJHggaW4KCQkJKmNjYWNoZSopIDs7
CgkJCSopIFsgLXogIiRjY19mb3VuZCIgXSAmJiBjY19mb3VuZD0keCA7OwoJCQllc2FjCgkJICAg
IGZpCgkJZG9uZQoJICAgIFsgLXogIiRjY19mb3VuZCIgXSAmJiBjY19mb3VuZD1gd2hpY2ggY2Ng
CgkgICAgd2hhdCAkY2NfZm91bmQgPiY0CgkgICAgY2N2ZXJzaW9uPWB3aGF0ICRjY19mb3VuZCB8
IGF3ayAnL0NvbXBpbGVyL3twcmludCAkMn0vSXRhbml1bS97cHJpbnQgJDYsJDd9L2ZvciBJbnRl
Z3JpdHkve3ByaW50ICQ2fSdgCgkgICAgY2FzZSAiJGNjZmxhZ3MiIGluCiAgICAgICAgICAgICAg
ICItQWUgIiopIDs7CgkJKikgIGNjZmxhZ3M9Ii1BZSAkY2NfY3BwZmxhZ3MiCgkJICAgICMgK3Zu
b2NvbXBhdHdhcm5pbmdzIG5vdCBrbm93biBpbiAxMC4xMCBhbmQgb2xkZXIKCQkgICAgaWYgWyAk
eHhPc1JldiAtZ2UgMTAyMCBdOyB0aGVuCgkJCWNjZmxhZ3M9IiRjY2ZsYWdzIC1XbCwrdm5vY29t
cGF0d2FybmluZ3MiCgkJCWZpCgkJICAgIDs7CiAgICAgICAgICAgICAgIGVzYWMKCSAgICAjIE5l
ZWRlZCBiZWNhdXNlIGNwcCBkb2VzIG9ubHkgc3VwcG9ydCAtQWEgKG5vdCAtQWUpCgkgICAgY3Bw
bGFzdD0nLScKCSAgICBjcHBtaW51cz0nLScKCSAgICBjcHBzdGRpbj0nY2MgLUUgLUFhIC1EX19T
VERDX0VYVF9fJwoJICAgIGNwcHJ1bj0kY3Bwc3RkaW4KIwkgICAgY2FzZSAiJGRfY2FzdGkzMiIg
aW4KIwkJIiIpIGRfY2FzdGkzMj0ndW5kZWYnIDs7CiMJCWVzYWMKCSAgICA7OwogICAgZXNhYwoK
IyBXaGVuIEhQLVVYIHJ1bnMgYSBzY3JpcHQgd2l0aCAiIyEiLCBpdCBzZXRzIGFyZ3ZbMF0gdG8g
dGhlIHNjcmlwdCBuYW1lLgp0b2tlX2NmbGFncz0nY2NmbGFncz0iJGNjZmxhZ3MgLURBUkdfWkVS
T19JU19TQ1JJUFQiJwoKIyMjIDY0IEJJVE5FU1MKCiMgU29tZSBnY2MgdmVyc2lvbnMgZG8gbmF0
aXZlIDY0IGJpdCBsb25nIChlLmcuIDIuOS1ocHBhLTAwMDMxMCBhbmQgZ2NjLTMuMCkKIyBXZSBo
YXZlIHRvIGZvcmNlIDY0Yml0bmVzcyB0byBnbyBzZWFyY2ggdGhlIHJpZ2h0IGxpYnJhcmllcwog
ICAgZ2NjXzY0bmF0aXZlPW5vCmNhc2UgIiRjY2lzZ2NjIiBpbgogICAgJGRlZmluZXx0cnVlfFtZ
eV0pCgllY2hvICcjaW5jbHVkZSA8c3RkaW8uaD5cbmludCBtYWluKCl7bG9uZyBsO3ByaW50Zigi
JWRcXG4iLHNpemVvZihsKSk7fSc+dHJ5LmMKCSRjYyAtbyB0cnkgJGNjZmxhZ3MgJGxkZmxhZ3Mg
dHJ5LmMKCWlmIFsgImB0cnlgIiA9ICI4IiBdOyB0aGVuCgkgICAgY2FzZSAiJHVzZTY0Yml0YWxs
IiBpbgoJCSRkZWZpbmV8dHJ1ZXxbWXldKSA7OwoJCSopICBjYXQgPDxFT00gPiY0CgoqKiogVGhp
cyB2ZXJzaW9uIG9mIGdjYyB1c2VzIDY0IGJpdCBsb25ncy4gLUR1c2U2NGJpdGFsbCBpcwoqKiog
aW1wbGljaXRseSBzZXQgdG8gZW5hYmxlIGNvbnRpbnVhdGlvbgpFT00KCQllc2FjCgkgICAgdXNl
NjRiaXRhbGw9JGRlZmluZQoJICAgIGdjY182NG5hdGl2ZT15ZXMKCSAgICBmaQoJOzsKICAgIGVz
YWMKCmNhc2UgIiR1c2U2NGJpdGFsbCIgaW4KICAgICRkZWZpbmV8dHJ1ZXxbeVldKikgdXNlNjRi
aXRpbnQ9IiRkZWZpbmUiIDs7CiAgICBlc2FjCgpjYXNlICIkdXNlbW9yZWJpdHMiIGluCiAgICAk
ZGVmaW5lfHRydWV8W3lZXSopIHVzZTY0Yml0aW50PSIkZGVmaW5lIjsgdXNlbG9uZ2RvdWJsZT0i
JGRlZmluZSIgOzsKICAgIGVzYWMKCmNhc2UgIiRhcmNobmFtZSIgaW4KICAgIElBNjQqKQoJIyBX
aGlsZSBoZXJlLCBvdmVycmlkZSBzbz1zbCBhdXRvLWRldGVjdGlvbgoJc289J3NvJwoJOzsKICAg
IGVzYWMKCmNhc2UgIiR1c2U2NGJpdGFsbCIgaW4KICAgICRkZWZpbmV8dHJ1ZXxbWXldKQoKCWlm
IFsgIiR4eE9zUmV2TWFqb3IiIC1sdCAxMSBdOyB0aGVuCgkgICAgY2F0IDw8RU9NID4mNAoKKioq
IDY0LWJpdCBjb21waWxhdGlvbiBpcyBub3Qgc3VwcG9ydGVkIG9uIEhQLVVYICR4eE9zUmV2TWFq
b3IuCioqKiBZb3UgbmVlZCBhdCBsZWFzdCBIUC1VWCAxMS4wLgoqKiogQ2Fubm90IGNvbnRpbnVl
LCBhYm9ydGluZy4KRU9NCgkgICAgZXhpdCAxCgkgICAgZmkKCglpZiBbICR4eE9zUmV2IC1lcSAx
MTAwIF07IHRoZW4KCSAgICAjIEhQLVVYIDExLjAwIHVzZXMgb25seSA0OCBiaXRzIGludGVybmFs
bHkgaW4gNjRiaXQgbW9kZSwgbm90IDY0CgkgICAgIyBmb3JjZSBtaW4vbWF4IHRvIDIqKjQ3LTEK
CSAgICBzR01USU1FX21heD0xNDA3Mzc0ODgzNTUzMjcKCSAgICBzR01USU1FX21pbj0tNjIxNjcy
MTkyMDAKCSAgICBzTE9DQUxUSU1FX21heD0xNDA3Mzc0ODgzNTUzMjcKCSAgICBzTE9DQUxUSU1F
X21pbj0tNjIxNjcyMTkyMDAKCSAgICBmaQoKCSMgU2V0IGxpYmMgYW5kIHRoZSBsaWJyYXJ5IHBh
dGhzCgljYXNlICIkYXJjaG5hbWUiIGluCgkgICAgUEEtUklTQyopCgkJbG9jbGlicHRoPSIkbG9j
bGlicHRoIC9saWIvcGEyMF82NCIKCQlsaWJjPScvbGliL3BhMjBfNjQvbGliYy5zbCcgOzsKCSAg
ICBJQTY0KikKCQlsb2NsaWJwdGg9IiRsb2NsaWJwdGggL3Vzci9saWIvaHB1eDY0IgoJCWxpYmM9
Jy91c3IvbGliL2hwdXg2NC9saWJjLnNvJyA7OwoJICAgIGVzYWMKCWlmIFsgISAtZiAiJGxpYmMi
IF07IHRoZW4KCSAgICBjYXQgPDxFT00gPiY0CgoqKiogWW91IGRvIG5vdCBzZWVtIHRvIGhhdmUg
dGhlIDY0LWJpdCBsaWJjLgoqKiogSSBjYW5ub3QgZmluZCB0aGUgZmlsZSAkbGliYy4KKioqIENh
bm5vdCBjb250aW51ZSwgYWJvcnRpbmcuCkVPTQoJICAgIGV4aXQgMQoJICAgIGZpCgoJY2FzZSAi
JGNjaXNnY2MiIGluCgkgICAgJGRlZmluZXx0cnVlfFtZeV0pCgkJIyBUaGUgZml4ZWQgc29ja2V0
LmggaGVhZGVyIGZpbGUgaXMgd3JvbmcgZm9yIGdjYy00LngKCQkjIG9uIFBBLVJJU0MyLjBXLCBz
byBTb2NrX3R5cGVfdCBpcyBzaXplX3Qgd2hpY2ggaXMKCQkjIHVuc2lnbmVkIGxvbmcgd2hpY2gg
aXMgNjRiaXQgd2hpY2ggaXMgdG9vIGxvbmcKCQljYXNlICIkZ2NjdmVyc2lvbiIgaW4KCQkgICAg
NCopIGNhc2UgIiRhcmNobmFtZSIgaW4KCQkJICAgIFBBLVJJU0MqKSBzb2Nrc2l6ZXR5cGU9aW50
IDs7CgkJCSAgICBlc2FjCgkJCTs7CgkJICAgIGVzYWMKCgkJIyBGb3IgdGhlIG1vbWVudCwgZG9u
J3QgY2FyZSB0aGF0IGl0IGFpbid0IHN1cHBvcnRlZCAoeWV0KQoJCSMgYnkgZ2NjICh1cCB0byBh
bmQgaW5jbHVkaW5nIDIuOTUuMyksIGNhdXNlIGl0J2xsIGNyYXNoCgkJIyBhbnl3YXkuIEV4cGVj
dCBhdXRvLWRldGVjdGlvbiBvZiA2NC1iaXQgZW5hYmxlZCBnY2Mgb24KCQkjIEhQLVVYIHNvb24s
IGluY2x1ZGluZyBhIHVzZXItZnJpZW5kbHkgZXhpdAoJCWNhc2UgJGdjY182NG5hdGl2ZSBpbgoJ
CSAgICBubykgY2FzZSAiJGdjY3ZlcnNpb24iIGluCgkJCSAgICBbMTIzNF0qKQoJCQkJY2NmbGFn
cz0iJGNjZmxhZ3MgLW1scDY0IgoJCQkJY2FzZSAiJGFyY2huYW1lIiBpbgoJCQkJICAgIFBBLVJJ
U0MqKQoJCQkJCWxkZmxhZ3M9IiRsZGZsYWdzIC1XbCwrREQ2NCIKCQkJCQk7OwoJCQkJICAgIElB
NjQqKQoJCQkJCWxkZmxhZ3M9IiRsZGZsYWdzIC1tbHA2NCIKCQkJCQk7OwoJCQkJICAgIGVzYWMK
CQkJCTs7CgkJCSAgICBlc2FjCgkJCTs7CgkJICAgIGVzYWMKCQk7OwoJICAgICopCgkJY2FzZSAi
JHVzZTY0Yml0YWxsIiBpbgoJCSAgICAkZGVmaW5lfHRydWV8W3lZXSopCgkJCWNjZmxhZ3M9IiRj
Y2ZsYWdzICtERDY0IgoJCQlsZGZsYWdzPSIkbGRmbGFncyArREQ2NCIKCQkJOzsKCQkgICAgZXNh
YwoJCTs7CgkgICAgZXNhYwoKCSMgUmVzZXQgdGhlIGxpYnJhcnkgY2hlY2tlciB0byBtYWtlIHN1
cmUgbGlicmFyaWVzCgkjIGFyZSB0aGUgcmlnaHQgdHlwZQoJIyAoTk9URTogb24gSUE2NCwgdGhp
cyBkb2Vzbid0IHdvcmsgd2l0aCAuYSBmaWxlcy4pCglsaWJzY2hlY2s9J2Nhc2UgImAvdXNyL2Jp
bi9maWxlICR4eHhgIiBpbgoJCSAgICAgICAqRUxGLTY0KnwqTFA2NCp8KlBBLVJJU0MyLjAqKSA7
OwoJCSAgICAgICAqKSB4eHg9L25vLzY0LWJpdCR4eHggOzsKCQkgICAgICAgZXNhYycKCgk7OwoK
ICAgICopCSMgTm90IGluIDY0LWJpdCBtb2RlCgoJY2FzZSAiJGFyY2huYW1lIiBpbgoJICAgIFBB
LVJJU0MqKQoJCWxpYmM9Jy9saWIvbGliYy5zbCcgOzsKCSAgICBJQTY0KikKCQlsb2NsaWJwdGg9
IiRsb2NsaWJwdGggL3Vzci9saWIvaHB1eDMyIgoJCWxpYmM9Jy91c3IvbGliL2hwdXgzMi9saWJj
LnNvJyA7OwoJICAgIGVzYWMKCTs7CiAgICBlc2FjCgojIEJ5IHNldHRpbmcgdGhlIGRlZmVycmVk
IGZsYWcgYmVsb3csIHRoaXMgbWVhbnMgdGhhdCBpZiB5b3UgcnVuIHBlcmwKIyBvbiBhIHN5c3Rl
bSB0aGF0IGRvZXMgbm90IGhhdmUgdGhlIHJlcXVpcmVkIHNoYXJlZCBsaWJyYXJ5IHRoYXQgeW91
CiMgbGlua2VkIGl0IHdpdGgsIGl0IHdpbGwgZGllIHdoZW4geW91IHRyeSB0byBhY2Nlc3MgYSBz
eW1ib2wgaW4gdGhlCiMgKG1pc3NpbmcpIHNoYXJlZCBsaWJyYXJ5LiAgSWYgeW91IHdvdWxkIHJh
dGhlciBrbm93IGF0IHBlcmwgc3RhcnR1cAojIHRpbWUgdGhhdCB5b3UgYXJlIG1pc3NpbmcgYW4g
aW1wb3J0YW50IHNoYXJlZCBsaWJyYXJ5LCBzd2l0Y2ggdGhlCiMgY29tbWVudHMgc28gdGhhdCBp
bW1lZGlhdGUsIHJhdGhlciB0aGFuIGRlZmVycmVkIGxvYWRpbmcgaXMKIyBwZXJmb3JtZWQuICBF
dmVuIHdpdGggaW1tZWRpYXRlIGxvYWRpbmcsIHlvdSBjYW4gcG9zdHBvbmUgZXJyb3JzIGZvcgoj
IHVuZGVmaW5lZCAob3IgbXVsdGlwbHkgZGVmaW5lZCkgcm91dGluZXMgdW50aWwgYWN0dWFsIGFj
Y2VzcyBieQojIGFkZGluZyB0aGUgIm5vbmZhdGFsIiBvcHRpb24uCiMgY2NkbGZsYWdzPSItV2ws
LUUgLVdsLC1CLGltbWVkaWF0ZSAkY2NkbGZsYWdzIgojIGNjZGxmbGFncz0iLVdsLC1FIC1XbCwt
QixpbW1lZGlhdGUsLUIsbm9uZmF0YWwgJGNjZGxmbGFncyIKaWYgWyAiJGdudV9sZCIgPSAieWVz
IiBdOyB0aGVuCiAgICBjY2RsZmxhZ3M9Ii1XbCwtRSAkY2NkbGZsYWdzIgplbHNlCiAgICBjY2Rs
ZmxhZ3M9Ii1XbCwtRSAtV2wsLUIsZGVmZXJyZWQgJGNjZGxmbGFncyIKICAgIGZpCgoKIyMjIENP
TVBJTEVSIFNQRUNJRklDUwoKIyMgTG9jYWwgcmVzdHJpY3Rpb25zIChwb2ludCB0byBSRUFETUUu
aHB1eCB0byBsaWZ0IHRoZXNlKQoKIyMgT3B0aW1pemF0aW9uIGxpbWl0cwpjYXQgPnRyeS5jIDw8
RU9GCiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3lzL3Jlc291cmNlLmg+CgppbnQgbWFp
biAoKQp7CiAgICBzdHJ1Y3QgcmxpbWl0IHJsOwogICAgaW50IGkgPSBnZXRybGltaXQgKFJMSU1J
VF9EQVRBLCAmcmwpOwogICAgcHJpbnRmICgiJWRcbiIsIChpbnQpKHJsLnJsaW1fY3VyIC8gKDEw
MjQgKiAxMDI0KSkpOwogICAgfSAvKiBtYWluICovCkVPRgokY2MgLW8gdHJ5ICRjY2ZsYWdzICRs
ZGZsYWdzIHRyeS5jCgltYXhkc2l6PWB0cnlgCnJtIC1mIHRyeSB0cnkuYyBjb3JlCmlmIFsgJG1h
eGRzaXogLWxlIDY0IF07IHRoZW4KICAgICMgNjQgTWIgaXMgcHJvYmFibHkgbm90IGVub3VnaCB0
byBvcHRpbWl6ZSB0b2tlLmMKICAgICMgYW5kIHJlZ2V4cC5jIHdpdGggLU8yCiAgICBjYXQgPDxF
T00gPiY0CllvdXIga2VybmVsIGxpbWl0cyB0aGUgZGF0YSBzZWN0aW9uIG9mIHlvdXIgcHJvZ3Jh
bXMgdG8gJG1heGRzaXogTWIsCndoaWNoIGlzIChzYWRseSkgbm90IGVub3VnaCB0byBmdWxseSBv
cHRpbWl6ZSBzb21lIHBhcnRzIG9mIHRoZQpwZXJsIGJpbmFyeS4gSSdsbCB0cnkgdG8gdXNlIGEg
bG93ZXIgb3B0aW1pemF0aW9uIGxldmVsIGZvcgp0aG9zZSBwYXJ0cy4gSWYgeW91IGFyZSBhIHN5
c2FkbWluLCBhbmQgeW91ICpkbyogd2FudCBmdWxsCm9wdGltaXphdGlvbiwgcmFpc2UgdGhlICdt
YXhkc2l6JyBrZXJuZWwgY29uZmlndXJhdGlvbiBwYXJhbWV0ZXIKdG8gYXQgbGVhc3QgMHgwODAw
MDAwMCAoMTI4IE1iKSBhbmQgcmVidWlsZCB5b3VyIGtlcm5lbC4KRU9NCnJlZ2V4ZWNfY2ZsYWdz
PScnCmRvb3BfY2ZsYWdzPScnCm9wX2NmbGFncz0nJwogICAgZmkKCmNhc2UgIiRjY2lzZ2NjIiBp
bgogICAgJGRlZmluZXx0cnVlfFtZeV0pCgoJY2FzZSAiJG9wdGltaXplIiBpbgoJICAgICIiKSAg
ICAgICAgICAgb3B0aW1pemU9Ii1nIC1PIiA7OwoJICAgICpPWzM0NTY3ODldKikgb3B0aW1pemU9
YGVjaG8gIiRvcHRpbWl6ZSIgfCBzZWQgLWUgJ3MvT1szLTldL08yLydgIDs7CgkgICAgZXNhYwoJ
I2xkPSIkY2MiCglsZD0vdXNyL2Jpbi9sZAoJY2NjZGxmbGFncz0nLWZQSUMnCgkjbGRkbGZsYWdz
PSctc2hhcmVkJwoJbGRkbGZsYWdzPSctYicKCWNhc2UgIiRvcHRpbWl6ZSIgaW4KCSAgICAqLWcq
LU8qfCotTyotZyopCgkJIyBnY2Mgd2l0aG91dCBnYXMgd2lsbCBub3QgYWNjZXB0IC1nCgkJZWNo
byAibWFpbigpe30iPnRyeS5jCgkJY2FzZSAiYCRjYyAkb3B0aW1pemUgLWMgdHJ5LmMgMj4mMWAi
IGluCgkJICAgICoiLWcgb3B0aW9uIGRpc2FibGVkIiopCgkJCXNldCBgZWNobyAiWCAkb3B0aW1p
emUgIiB8IHNlZCAtZSAncy8gLWcgLyAvJ2AKCQkJc2hpZnQKCQkJb3B0aW1pemU9IiQqIgoJCQk7
OwoJCSAgICBlc2FjCgkJOzsKCSAgICBlc2FjCglpZiBbICRtYXhkc2l6IC1sZSA2NCBdOyB0aGVu
CgkgICAgY2FzZSAiJG9wdGltaXplIiBpbgoJCSpPMiopCW9wdD1gZWNobyAiJG9wdGltaXplIiB8
IHNlZCAtZSAncy9PMi9PMS8nYAoJCQl0b2tlX2NmbGFncz0iJHRva2VfY2ZsYWdzO29wdGltaXpl
PVwiJG9wdFwiIgoJCQlyZWdleGVjX2NmbGFncz0ib3B0aW1pemU9XCIkb3B0XCIiCgkJCTs7CgkJ
ZXNhYwoJICAgIGZpCgk7OwoKICAgICopCSMgSFAncyBjb21waWxlciBjYW5ub3QgY29tYmluZSAt
ZyBhbmQgLU8KCWNhc2UgIiRvcHRpbWl6ZSIgaW4KCSAgICAiIikgICAgICAgICAgIG9wdGltaXpl
PSIrTzIgK09ub2xpbWl0IiA7OwoJICAgICpPWzM0NTY3ODldKikgb3B0aW1pemU9YGVjaG8gIiRv
cHRpbWl6ZSIgfCBzZWQgLWUgJ3MvT1szLTldL08yLydgIDs7CgkgICAgZXNhYwoJY2FzZSAiJG9w
dGltaXplIiBpbgoJICAgICotTyp8XAoJICAgICpPMiopICAgb3B0PWBlY2hvICIkb3B0aW1pemUi
IHwgc2VkIC1lICdzLy1PLytPMi8nIC1lICdzL08yL08xLycgLWUgJ3MvICorT25vbGltaXQvLydg
CgkJICAgIDs7CgkgICAgKikgICAgICBvcHQ9IiRvcHRpbWl6ZSIKCQkgICAgOzsKCSAgICBlc2Fj
CgljYXNlICIkYXJjaG5hbWUiIGluCgkgICAgSUE2NCopCgkJY2FzZSAiJGNjdmVyc2lvbiIgaW4K
CQkgICAgQjM5MTBCKkEuMDYuMFsxMjM0NV0pCgkJCSMgPiBjYyAtLXZlcnNpb24KCQkJIyBjYzog
SFAgYUMrKy9BTlNJIEMgQjM5MTBCIEEuMDYuMDUgW0p1bCAyNSAyMDA1XQoJCQkjIEhhcyBvcHRp
bWl6aW5nIHByb2JsZW1zIHdpdGggLU8yIGFuZCB1cCBmb3IgYm90aAoJCQkjIG1haW50ICg1Ljgu
OCspIGFuZCBibGVhZCAoNS45LjMrKQoJCQkjIC1PMS8rTzEgcGFzc2VkIGFsbCB0ZXN0cyAobSkn
MDUgWyAxMCBKYW4gMjAwNSBdCgkJCW9wdGltaXplPSIkb3B0IgkJCTs7CgkJICAgICopICBkb29w
X2NmbGFncz0ib3B0aW1pemU9XCIkb3B0XCIiCgkJCW9wX2NmbGFncz0ib3B0aW1pemU9XCIkb3B0
XCIiCTs7CgkJICAgIGVzYWMKCQk7OwoJICAgIGVzYWMKCWlmIFsgJG1heGRzaXogLWxlIDY0IF07
IHRoZW4KCSAgICB0b2tlX2NmbGFncz0iJHRva2VfY2ZsYWdzO29wdGltaXplPVwiJG9wdFwiIgoJ
ICAgIHJlZ2V4ZWNfY2ZsYWdzPSJvcHRpbWl6ZT1cIiRvcHRcIiIKCSAgICBmaQoJbGQ9L3Vzci9i
aW4vbGQKCWNjY2RsZmxhZ3M9JytaJwoJbGRkbGZsYWdzPSctYiArdm5vY29tcGF0d2FybmluZ3Mn
Cgk7OwogICAgZXNhYwoKIyMgTEFSR0VGSUxFUwppZiBbICR4eE9zUmV2IC1sdCAxMDIwIF07IHRo
ZW4KICAgIHVzZWxhcmdlZmlsZXM9IiR1bmRlZiIKICAgIGZpCgojY2FzZSAiJHVzZWxhcmdlZmls
ZXMtJGNjaXNnY2MiIGluCiMgICAgIiRkZWZpbmUtJGRlZmluZSJ8Jy1kZWZpbmUnKQojCWNhdCA8
PEVPTSA+JjQKIwojKioqIEknbSBpZ25vcmluZyBsYXJnZSBmaWxlcyBmb3IgdGhpcyBidWlsZCBi
ZWNhdXNlCiMqKiogSSBkb24ndCBrbm93IGhvdyB0byBkbyB1c2UgbGFyZ2UgZmlsZXMgaW4gSFAt
VVggdXNpbmcgZ2NjLgojCiNFT00KIwl1c2VsYXJnZWZpbGVzPSIkdW5kZWYiCiMJOzsKIyAgICBl
c2FjCgojIE9uY2Ugd2UgaGF2ZSB0aGUgY29tcGlsZXIgZmxhZ3MgZGVmaW5lZCwgQ29uZmlndXJl
IHdpbGwKIyBleGVjdXRlIHRoZSBmb2xsb3dpbmcgY2FsbC1iYWNrIHNjcmlwdC4gU2VlIGhpbnRz
L1JFQURNRS5oaW50cwojIGZvciBkZXRhaWxzLgpjYXQgPiBVVS9jYy5jYnUgPDwnRU9DQlUnCiMg
VGhpcyBzY3JpcHQgVVUvY2MuY2J1IHdpbGwgZ2V0ICdjYWxsZWQtYmFjaycgYnkgQ29uZmlndXJl
IGFmdGVyIGl0CiMgaGFzIHByb21wdGVkIHRoZSB1c2VyIGZvciB0aGUgQyBjb21waWxlciB0byB1
c2UuCgojIENvbXBpbGUgYW5kIHJ1biB0aGUgYSB0ZXN0IGNhc2UgdG8gc2VlIGlmIGEgY2VydGFp
biBnY2MgYnVnIGlzCiMgcHJlc2VudC4gSWYgc28sIGxvd2VyIHRoZSBvcHRpbWl6YXRpb24gbGV2
ZWwgd2hlbiBjb21waWxpbmcKIyBwcF9wYWNrLmMuICBUaGlzIHdvcmtzIGFyb3VuZCBhIGJ1ZyBp
biB1bnBhY2suCgppZiB0ZXN0IC16ICIkY2Npc2djYyIgLWEgLXogIiRnY2N2ZXJzaW9uIjsgdGhl
bgogICAgOiBubyB0ZXN0cyBuZWVkZWQgZm9yIEhQYwplbHNlCiAgICBlY2hvICIgIgogICAgZWNo
byAiVGVzdGluZyBmb3IgYSBjZXJ0YWluIGdjYyBidWcgaXMgZml4ZWQgaW4geW91ciBjb21waWxl
ci4uLiIKCiAgICAjIFRyeSBjb21waWxpbmcgdGhlIHRlc3QgY2FzZS4KICAgIGlmICRjYyAtbyB0
MDAxIC1PICRjY2ZsYWdzICRsZGZsYWdzIC1sbSAuLi9oaW50cy90MDAxLmM7IHRoZW4KICAgICAg
IGdjY2J1Zz1gJHJ1biAuL3QwMDFgCiAgICAgICBjYXNlICIkZ2NjYnVnIiBpbgogICAgICAgICAg
ICpmYWlscyopCiAgICAgICAgICAgICAgIGNhdCA+JjQgPDxFT0YKVGhpcyBDIGNvbXBpbGVyICgk
Z2NjdmVyc2lvbikgaXMga25vd24gdG8gaGF2ZSBvcHRpbWl6ZXIKcHJvYmxlbXMgd2hlbiBjb21w
aWxpbmcgcHBfcGFjay5jLgoKRGlzYWJsaW5nIG9wdGltaXphdGlvbiBmb3IgcHBfcGFjay5jLgpF
T0YKICAgICAgICAgICAgICAgY2FzZSAiJHBwX3BhY2tfY2ZsYWdzIiBpbgogICAgICAgICAgICAg
ICAgICAgJycpIHBwX3BhY2tfY2ZsYWdzPSdvcHRpbWl6ZT0nCiAgICAgICAgICAgICAgICAgICAg
ICAgZWNobyAicHBfcGFja19jZmxhZ3M9J29wdGltaXplPVwiXCInIiA+PiBjb25maWcuc2ggOzsK
ICAgICAgICAgICAgICAgICAgICopICBlY2hvICJZb3Ugc3BlY2lmaWVkIHBwX3BhY2tfY2ZsYWdz
IHlvdXJzZWxmLCBzbyB3ZSdsbCBnbyB3aXRoIHlvdXIgdmFsdWUuIiA+JjQgOzsKICAgICAgICAg
ICAgICAgICAgIGVzYWMKICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAqKSAgZWNobyAiWW91
ciBjb21waWxlciBpcyBvay4iID4mNAogICAgICAgICAgICAgICA7OwogICAgICAgICAgIGVzYWMK
ICAgIGVsc2UKICAgICAgIGVjaG8gIiAiCiAgICAgICBlY2hvICIqKiogV0hPQSBUSEVSRSEhISAq
KioiID4mNAogICAgICAgZWNobyAiICAgIFlvdXIgQyBjb21waWxlciBcIiRjY1wiIGRvZXNuJ3Qg
c2VlbSB0byBiZSB3b3JraW5nISIgPiY0CiAgICAgICBjYXNlICIka25vd2l0YWxsIiBpbgogICAg
ICAgICAgICcnKSBlY2hvICIgICAgWW91J2QgYmV0dGVyIHN0YXJ0IGh1bnRpbmcgZm9yIG9uZSBh
bmQgbGV0IG1lIGtub3cgYWJvdXQgaXQuIiA+JjQKICAgICAgICAgICAgICAgZXhpdCAxCiAgICAg
ICAgICAgICAgIDs7CiAgICAgICAgICAgZXNhYwogICAgICAgZmkKCiAgICBybSAtZiB0MDAxJF9v
IHQwMDEkX2V4ZQogICAgZmkKRU9DQlUKCmNhdCA+VVUvdXNlbGFyZ2VmaWxlcy5jYnUgPDwnRU9D
QlUnCiMgVGhpcyBzY3JpcHQgVVUvdXNlbGFyZ2VmaWxlcy5jYnUgd2lsbCBnZXQgJ2NhbGxlZC1i
YWNrJyBieSBDb25maWd1cmUKIyBhZnRlciBpdCBoYXMgcHJvbXB0ZWQgdGhlIHVzZXIgZm9yIHdo
ZXRoZXIgdG8gdXNlIGxhcmdlIGZpbGVzLgpjYXNlICIkdXNlbGFyZ2VmaWxlcyIgaW4KICAgICIi
fCRkZWZpbmV8dHJ1ZXxbeVldKikKCSMgdGhlcmUgYXJlIGxhcmdlZmlsZSBmbGFncyBhdmFpbGFi
bGUgdmlhIGdldGNvbmYoMSkKCSMgYnV0IHdlIGNoZWF0IGZvciBub3cuICAoS2VlcCB0aGF0IGlu
IHRoZSBsZWZ0IG1hcmdpbi4pCmNjZmxhZ3NfdXNlbGFyZ2VmaWxlcz0iLURfTEFSR0VGSUxFX1NP
VVJDRSAtRF9GSUxFX09GRlNFVF9CSVRTPTY0IgoKCWNhc2UgIiAkY2NmbGFncyAiIGluCgkqIiAk
Y2NmbGFnc191c2VsYXJnZWZpbGVzICIqKSA7OwoJKikgY2NmbGFncz0iJGNjZmxhZ3MgJGNjZmxh
Z3NfdXNlbGFyZ2VmaWxlcyIgOzsKCWVzYWMKCglpZiB0ZXN0IC16ICIkY2Npc2djYyIgLWEgLXog
IiRnY2N2ZXJzaW9uIjsgdGhlbgoJICAgICMgVGhlIHN0cmljdCBBTlNJIG1vZGUgKC1BYSkgZG9l
c24ndCBsaWtlIGxhcmdlIGZpbGVzLgoJICAgIGNjZmxhZ3M9YGVjaG8gIiAkY2NmbGFncyAifHNl
ZCAnc0AgLUFhIEAgQGcnYAoJICAgIGNhc2UgIiRjY2ZsYWdzIiBpbgoJCSotQWUqKSA7OwoJCSop
ICAgICBjY2ZsYWdzPSIkY2NmbGFncyAtQWUiIDs7CgkJZXNhYwoJICAgIGZpCgk7OwogICAgZXNh
YwpFT0NCVQoKIyBUSFJFQURJTkcKCiMgVGhpcyBzY3JpcHQgVVUvdXNldGhyZWFkcy5jYnUgd2ls
bCBnZXQgJ2NhbGxlZC1iYWNrJyBieSBDb25maWd1cmUKIyBhZnRlciBpdCBoYXMgcHJvbXB0ZWQg
dGhlIHVzZXIgZm9yIHdoZXRoZXIgdG8gdXNlIHRocmVhZHMuCmNhdCA+VVUvdXNldGhyZWFkcy5j
YnUgPDwnRU9DQlUnCmNhc2UgIiR1c2V0aHJlYWRzIiBpbgogICAgJGRlZmluZXx0cnVlfFt5WV0q
KQoJaWYgWyAiJHh4T3NSZXZNYWpvciIgLWx0IDEwIF07IHRoZW4KCSAgICBjYXQgPDxFT00gPiY0
CgpIUC1VWCAkeHhPc1Jldk1ham9yIGNhbm5vdCBzdXBwb3J0IFBPU0lYIHRocmVhZHMuCkNvbnNp
ZGVyIHVwZ3JhZGluZyB0byBhdCBsZWFzdCBIUC1VWCAxMS4KQ2Fubm90IGNvbnRpbnVlLCBhYm9y
dGluZy4KRU9NCgkgICAgZXhpdCAxCgkgICAgZmkKCglpZiBbICIkeHhPc1Jldk1ham9yIiAtZXEg
MTAgXTsgdGhlbgoJICAgICMgVW5kZXIgMTAuWCwgYSB0aHJlYWRlZCBwZXJsIGNhbiBiZSBidWls
dAoJICAgIGlmIFsgLWYgL3Vzci9pbmNsdWRlL3B0aHJlYWQuaCBdOyB0aGVuCgkJaWYgWyAtZiAv
dXNyL2xpYi9saWJjbWEuc2wgXTsgdGhlbgoJCSAgICAjIERDRSAoZnJvbSBDb3JlIE9TIENEKSBp
cyBpbnN0YWxsZWQKCgkJICAgIyBDaGVjayBpZiBpdCBpcyBwcmlzdGluZSwgb3IgcGF0Y2hlZAoJ
CSAgIGNtYXZzbj1gd2hhdCAvdXNyL2xpYi9saWJjbWEuc2wgMj4mMSB8IGdyZXAgMTk5NmAKCQkg
ICBpZiBbICEgLXogIiRjbWF2c24iIF07IHRoZW4KCQkgICAgICAgY2F0IDw8RU9NID4mNAoHCioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKgoKUGVybCB3aWxsIHN1cHBvcnQgdGhyZWFkaW5nIHRocm91Z2ggL3Vz
ci9saWIvbGliY21hLnNsIGZyb20KdGhlIEhQIERDRSBwYWNrYWdlLCBidXQgdGhlIHZlcnNpb24g
Zm91bmQgaXMgdG9vIG9sZCB0byBiZQpyZWxpYWJsZS4KCklmIHlvdSBhcmUgbm90IGRlcGVuZGlu
ZyBvbiB0aGlzIHNwZWNpZmljIHZlcnNpb24gb2YgdGhlIGxpYnJhcnksCmNvbnNpZGVyIHRvIHVw
Z3JhZGUgdXNpbmcgcGF0Y2ggUEhTU18yMzY3MiAocmVhZCBSRUFETUUuaHB1eCkKCioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKgoKKHNsZWVwaW5nIGZvciAxMCBzZWNvbmRzLi4uKQpFT00KCQkgICAgICAgc2xl
ZXAgMTAKCQkgICAgICAgZmkKCgkJICAgICMgSXQgbmVlZHMgIyBsaWJjbWEgYW5kIE9MRF9QVEhS
RUFEU19BUEkuIEFsc28KCQkgICAgIyA8cHRocmVhZC5oPiBuZWVkcyB0byBiZSAjaW5jbHVkZWQg
YmVmb3JlIGFueQoJCSAgICAjIG90aGVyIGluY2x1ZGVzIChpbiBwZXJsLmgpCgoJCSAgICAjIEhQ
LVVYIDEwLlggdXNlcyB0aGUgb2xkIHB0aHJlYWRzIEFQSQoJCSAgICBkX29sZHB0aHJlYWRzPSIk
ZGVmaW5lIgoKCQkgICAgIyBpbmNsdWRlIGxpYmNtYSBiZWZvcmUgYWxsIHRoZSBvdGhlcnMKCQkg
ICAgbGlic3dhbnRlZD0iY21hICRsaWJzd2FudGVkIgoKCQkgICAgIyB0ZWxsIHBlcmwuaCB0byBp
bmNsdWRlIDxwdGhyZWFkLmg+IGJlZm9yZSBvdGhlcgoJCSAgICAjIGluY2x1ZGUgZmlsZXMKCQkg
ICAgY2NmbGFncz0iJGNjZmxhZ3MgLURQVEhSRUFEX0hfRklSU1QiCiMgRmlyc3QgY29sdW1uIG9u
IHB1cnBvc2U6CiMgdGhpcyBpcyBub3QgYSBzdGFuZGFyZCBDb25maWd1cmUgdmFyaWFibGUKIyBi
dXQgd2UgbmVlZCB0byBnZXQgdGhpcyBub3RpY2VkLgpwdGhyZWFkX2hfZmlyc3Q9IiRkZWZpbmUi
CgoJCSAgICAjIEhQLVVYIDEwLlggc2VlbXMgdG8gaGF2ZSBubyBlYXN5CgkJICAgICMgd2F5IG9m
IGRldGVjdGluZyB0aGVzZSAqdGltZV9yIHByb3Rvcy4KCQkgICAgZF9nbXRpbWVfcl9wcm90bz0n
ZGVmaW5lJwoJCSAgICBnbXRpbWVfcl9wcm90bz0nUkVFTlRSQU5UX1BST1RPX0lfVFMnCgkJICAg
IGRfbG9jYWx0aW1lX3JfcHJvdG89J2RlZmluZScKCQkgICAgbG9jYWx0aW1lX3JfcHJvdG89J1JF
RU5UUkFOVF9QUk9UT19JX1RTJwoKCQkgICAgIyBBdm9pZCB0aGUgcG9pc29ub3VzIGNvbmZsaWN0
aW5nIChhbmQgaXJyZWxldmFudCkKCQkgICAgIyBwcm90b3R5cGVzIG9mIHNldGtleSAoKS4KCQkg
ICAgaV9jcnlwdD0iJHVuZGVmIgoKCQkgICAgIyBDTUEgcmVkZWZpbmVzIHNlbGVjdCB0byBjbWFf
c2VsZWN0LCBhbmQgY21hX3NlbGVjdAoJCSAgICAjIGV4cGVjdHMgaW50ICogaW5zdGVhZCBvZiBm
ZF9zZXQgKiAoanVzdCBsaWtlIDkuWCkKCQkgICAgc2VsZWN0dHlwZT0naW50IConCgoJCWVsaWYg
WyAtZiAvdXNyL2xpYi9saWJwdGhyZWFkLnNsIF07IHRoZW4KCQkgICAgIyBQVEggcGFja2FnZSBp
cyBpbnN0YWxsZWQKCQkgICAgbGlic3dhbnRlZD0icHRocmVhZCAkbGlic3dhbnRlZCIKCQllbHNl
CgkJICAgIGxpYnN3YW50ZWQ9Im5vX3RocmVhZHNfYXZhaWxhYmxlIgoJCSAgICBmaQoJICAgIGVs
c2UKCQlsaWJzd2FudGVkPSJub190aHJlYWRzX2F2YWlsYWJsZSIKCQlmaQoKCSAgICBpZiBbICRs
aWJzd2FudGVkID0gIm5vX3RocmVhZHNfYXZhaWxhYmxlIiBdOyB0aGVuCgkJY2F0IDw8RU9NID4m
NAoKSW4gSFAtVVggMTAuWCBmb3IgUE9TSVggdGhyZWFkcyB5b3UgbmVlZCBib3RoIG9mIHRoZSBm
aWxlcwovdXNyL2luY2x1ZGUvcHRocmVhZC5oIGFuZCBlaXRoZXIgL3Vzci9saWIvbGliY21hLnNs
IG9yIC91c3IvbGliL2xpYnB0aHJlYWQuc2wuCkVpdGhlciB5b3UgbXVzdCB1cGdyYWRlIHRvIEhQ
LVVYIDExIG9yIGluc3RhbGwgYSBwb3NpeCB0aHJlYWQgbGlicmFyeToKCiAgICBEQ0UtQ29yZVRv
b2xzIGZyb20gSFAtVVggMTAuMjAgSGFyZHdhcmUgRXh0ZW5zaW9ucyAzLjAgQ0QgKEIzOTIwLTEz
OTQxKQoKb3IKCiAgICBQVEggcGFja2FnZSBmcm9tIGUuZy4gaHR0cDovL2hwdXguY29ubmVjdC5v
cmcudWsvaHBwZC9ocHV4L0dudS9wdGgtMi4wLjcvCgpDYW5ub3QgY29udGludWUsIGFib3J0aW5n
LgpFT00KCQlleGl0IDEKCQlmaQoJZWxzZQoJICAgICMgMTIgbWF5IHdhbnQgdXBwaW5nIHRoZSBf
UE9TSVhfQ19TT1VSQ0UgZGF0ZXN0YW1wLi4uCgkgICAgY2NmbGFncz0iIC1EX1BPU0lYX0NfU09V
UkNFPTE5OTUwNkwgLURfUkVFTlRSQU5UICRjY2ZsYWdzIgoJICAgIHNldCBgZWNobyBYICIkbGli
c3dhbnRlZCAifCBzZWQgLWUgJ3MvIGMgLyBwdGhyZWFkIGMgLydgCgkgICAgc2hpZnQKCSAgICBs
aWJzd2FudGVkPSIkKiIKCgkgICAgIyBIUC1VWCAxMS5YIHNlZW1zIHRvIGhhdmUgbm8gZWFzeQoJ
ICAgICMgd2F5IG9mIGRldGVjdGluZyB0aGVzZSAqdGltZV9yIHByb3Rvcy4KCSAgICBkX2dtdGlt
ZV9yX3Byb3RvPSdkZWZpbmUnCgkgICAgZ210aW1lX3JfcHJvdG89J1JFRU5UUkFOVF9QUk9UT19T
X1RTJwoJICAgIGRfbG9jYWx0aW1lX3JfcHJvdG89J2RlZmluZScKCSAgICBsb2NhbHRpbWVfcl9w
cm90bz0nUkVFTlRSQU5UX1BST1RPX1NfVFMnCgkgICAgZmkKCTs7CiAgICBlc2FjCkVPQ0JVCgoj
IFRoZXJlIHVzZWQgdG8gYmU6CiMgIFRoZSBteXN0ZXJpb3VzIGlvX3hzIG1lbW9yeSBjb3JydXB0
aW9uIGluIDExLjAwIDMyYml0IHNlZW1zIHRvIGdldAojICBmaXhlZCBieSBub3QgdXNpbmcgUGVy
bCdzIG1hbGxvYy4gIEZsaXAgc2lkZSBpcyBwZXJmb3JtYW5jZSBsb3NzLgojICBTbyB3ZSB3YW50
IG15bWFsbG9jIGZvciBhbGwgc2l0dWF0aW9ucyBwb3NzaWJsZQojIFRoYXQgc2V0IHVzZW15bWFs
bG9jIHRvICduJyBmb3IgdGhyZWFkZWQgYnVpbGRzIGFuZCBub24tZ2NjIDMyYml0CiMgIG5vbi1k
ZWJ1Z2dpbmcgYnVpbGRzIGFuZCAneScgZm9yIGFsbCBvdGhlcnMKCnVzZW15bWFsbG9jPSduJwpj
YXNlICIkdXNlcGVybGlvIiBpbgogICAgJHVuZGVmfGZhbHNlfFtuTl0qKSB1c2VteW1hbGxvYz0n
eScgOzsKICAgIGVzYWMKCiMgbWFsbG9jIHdyYXAgd29ya3MKY2FzZSAiJHVzZW1hbGxvY3dyYXAi
IGluCiAgICAnJykgdXNlbWFsbG9jd3JhcD0nZGVmaW5lJyA7OwogICAgZXNhYwoKIyBjdGltZV9y
ICgpIGFuZCBhc2N0aW1lX3IgKCkgc2VlbSB0byBoYXZlIGlzc3VlcyBmb3IgdmVyc2lvbnMgYmVm
b3JlCiMgSFAtVVggMTEKaWYgWyAkeHhPc1Jldk1ham9yIC1sdCAxMSBdOyB0aGVuCiAgICBkX2N0
aW1lX3I9IiR1bmRlZiIKICAgIGRfYXNjdGltZV9yPSIkdW5kZWYiCiAgICBmaQoKIyBmcGNsYXNz
aWZ5ICgpIGlzIGEgbWFjcm8sIHRoZSBsaWJyYXJ5IGNhbGwgaXMgRnBjbGFzc2lmeQojIFNpbWls
YXJseSB3aXRoIHRoZSBvdGhlcnMgYmVsb3cuCmRfZnBjbGFzc2lmeT0nZGVmaW5lJwpkX2lzbmFu
PSdkZWZpbmUnCmRfaXNpbmY9J2RlZmluZScKZF9pc2Zpbml0ZT0nZGVmaW5lJwpkX3Vub3JkZXJl
ZD0nZGVmaW5lJwojIE5leHQgb25lKHMpIG5lZWQgdGhlIGxlYWRpbmcgdGFiLiAgVGhlc2UgYXJl
IHNwZWNpYWwgJ2hpbnQnIHN5bWJvbHMgdGhhdAojIGFyZSBub3QgdG8gYmUgcHJvcGFnYXRlZCB0
byBjb25maWcuc2gsIGFsbCByZWxhdGVkIHRvIHB0aHJlYWRzIGRyYWZ0IDQKIyBpbnRlcmZhY2Vz
LgpjYXNlICIkZF9vbGRwdGhyZWFkcyIgaW4KICAgICcnfCR1bmRlZikKCWRfY3J5cHRfcl9wcm90
bz0ndW5kZWYnCglkX2dldGdyZW50X3JfcHJvdG89J3VuZGVmJwoJZF9nZXRwd2VudF9yX3Byb3Rv
PSd1bmRlZicKCWRfc3RyZXJyb3Jfcl9wcm90bz0ndW5kZWYnCgk7OwogICAgZXNhYwo=',
);
my %files = (
'freebsd' => 'freebsd.sh',
'netbsd' => 'netbsd.sh',
'openbsd' => 'openbsd.sh',
'linux' => 'linux.sh',
'dragonfly' => 'dragonfly.sh',
'darwin' => 'darwin.sh',
'hpux' => 'hpux.sh',
);
sub hint_file {
my $os = shift;
$os = shift if eval { $os->isa(__PACKAGE__) };
$os = $^O unless $os;
return unless defined $hints{ $os };
my $content = decode_base64( $hints{ $os } );
return $content unless wantarray;
return ( $files{ $os }, $content );
}
qq'nudge nudge wink wink';
__END__
=pod
=head1 NAME
Devel::PatchPerl::Hints - replacement 'hints' files
=head1 VERSION
version 0.52
=head1 SYNOPSIS
use Devel::PatchPerl::Hints;
if ( my $content = Devel::PatchPerl::Hints->hint_file() ) {
chmod 0644, 'hints/netbsd.sh' or die "$!";
open my $hints, '>', 'hints/netbsd.sh' or die "$!";
print $hints $content;
close $hints;
}
=head1 DESCRIPTION
Sometimes there is a problem with Perls C<hints> file for a particular
perl port. This module provides fixed C<hints> files encoded using
C<MIME::Base64>.
=head1 FUNCTION
The function is exported, but has to implicitly imported into the
requesting package.
use Devel::PatchPerl::Hints qw[hint_file];
It may also be called as a class method:
use Devel::PatchPerl::Hints;
my $content = Devel::PatchPerl::Hints->hint_file();
=over
=item C<hint_file>
Takes an optional argument which is the OS name ( as would be returned by C<$^O> ).
By default it will use C<$^O>.
In a scalar context, Will return the decoded content of the C<hints> file suitable for writing straight to a
file handle or undef list if there isn't an applicable C<hints> file for the given or derived
OS.
If called in a list context, will return a list, the first item will be the name of the C<hints> file that
will need to be amended, the second item will be a string with the decoded content of the C<hints> file suitable
for writing straight to a file handle. Otherwise an empty list will be returned.
=back
=head1 AUTHOR
Chris Williams <chris@bingosnet.co.uk>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2011 by Chris Williams and Marcus Holland-Moritz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
DEVEL_PATCHPERL_HINTS
$fatpacked{"ExtUtils/Command/MM.pm"} = <<'EXTUTILS_COMMAND_MM';
package ExtUtils::Command::MM;
require 5.006;
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(test_harness pod2man perllocal_install uninstall
warn_if_old_packlist);
our $VERSION = '6.59';
my $Is_VMS = $^O eq 'VMS';
=head1 NAME
ExtUtils::Command::MM - Commands for the MM's to use in Makefiles
=head1 SYNOPSIS
perl "-MExtUtils::Command::MM" -e "function" "--" arguments...
=head1 DESCRIPTION
B<FOR INTERNAL USE ONLY!> The interface is not stable.
ExtUtils::Command::MM encapsulates code which would otherwise have to
be done with large "one" liners.
Any $(FOO) used in the examples are make variables, not Perl.
=over 4
=item B<test_harness>
test_harness($verbose, @test_libs);
Runs the tests on @ARGV via Test::Harness passing through the $verbose
flag. Any @test_libs will be unshifted onto the test's @INC.
@test_libs are run in alphabetical order.
=cut
sub test_harness {
require Test::Harness;
require File::Spec;
$Test::Harness::verbose = shift;
# Because Windows doesn't do this for us and listing all the *.t files
# out on the command line can blow over its exec limit.
require ExtUtils::Command;
my @argv = ExtUtils::Command::expand_wildcards(@ARGV);
local @INC = @INC;
unshift @INC, map { File::Spec->rel2abs($_) } @_;
Test::Harness::runtests(sort { lc $a cmp lc $b } @argv);
}
=item B<pod2man>
pod2man( '--option=value',
$podfile1 => $manpage1,
$podfile2 => $manpage2,
...
);
# or args on @ARGV
pod2man() is a function performing most of the duties of the pod2man
program. Its arguments are exactly the same as pod2man as of 5.8.0
with the addition of:
--perm_rw octal permission to set the resulting manpage to
And the removal of:
--verbose/-v
--help/-h
If no arguments are given to pod2man it will read from @ARGV.
If Pod::Man is unavailable, this function will warn and return undef.
=cut
sub pod2man {
local @ARGV = @_ ? @_ : @ARGV;
{
local $@;
if( !eval { require Pod::Man } ) {
warn "Pod::Man is not available: $@".
"Man pages will not be generated during this install.\n";
return undef;
}
}
require Getopt::Long;
# We will cheat and just use Getopt::Long. We fool it by putting
# our arguments into @ARGV. Should be safe.
my %options = ();
Getopt::Long::config ('bundling_override');
Getopt::Long::GetOptions (\%options,
'section|s=s', 'release|r=s', 'center|c=s',
'date|d=s', 'fixed=s', 'fixedbold=s', 'fixeditalic=s',
'fixedbolditalic=s', 'official|o', 'quotes|q=s', 'lax|l',
'name|n=s', 'perm_rw=i'
);
# If there's no files, don't bother going further.
return 0 unless @ARGV;
# Official sets --center, but don't override things explicitly set.
if ($options{official} && !defined $options{center}) {
$options{center} = q[Perl Programmer's Reference Guide];
}
# This isn't a valid Pod::Man option and is only accepted for backwards
# compatibility.
delete $options{lax};
do {{ # so 'next' works
my ($pod, $man) = splice(@ARGV, 0, 2);
next if ((-e $man) &&
(-M $man < -M $pod) &&
(-M $man < -M "Makefile"));
print "Manifying $man\n";
my $parser = Pod::Man->new(%options);
$parser->parse_from_file($pod, $man)
or do { warn("Could not install $man\n"); next };
if (exists $options{perm_rw}) {
chmod(oct($options{perm_rw}), $man)
or do { warn("chmod $options{perm_rw} $man: $!\n"); next };
}
}} while @ARGV;
return 1;
}
=item B<warn_if_old_packlist>
perl "-MExtUtils::Command::MM" -e warn_if_old_packlist <somefile>
Displays a warning that an old packlist file was found. Reads the
filename from @ARGV.
=cut
sub warn_if_old_packlist {
my $packlist = $ARGV[0];
return unless -f $packlist;
print <<"PACKLIST_WARNING";
WARNING: I have found an old package in
$packlist.
Please make sure the two installations are not conflicting
PACKLIST_WARNING
}
=item B<perllocal_install>
perl "-MExtUtils::Command::MM" -e perllocal_install
<type> <module name> <key> <value> ...
# VMS only, key|value pairs come on STDIN
perl "-MExtUtils::Command::MM" -e perllocal_install
<type> <module name> < <key>|<value> ...
Prints a fragment of POD suitable for appending to perllocal.pod.
Arguments are read from @ARGV.
'type' is the type of what you're installing. Usually 'Module'.
'module name' is simply the name of your module. (Foo::Bar)
Key/value pairs are extra information about the module. Fields include:
installed into which directory your module was out into
LINKTYPE dynamic or static linking
VERSION module version number
EXE_FILES any executables installed in a space seperated
list
=cut
sub perllocal_install {
my($type, $name) = splice(@ARGV, 0, 2);
# VMS feeds args as a piped file on STDIN since it usually can't
# fit all the args on a single command line.
my @mod_info = $Is_VMS ? split /\|/, <STDIN>
: @ARGV;
my $pod;
$pod = sprintf <<POD, scalar localtime;
=head2 %s: C<$type> L<$name|$name>
=over 4
POD
do {
my($key, $val) = splice(@mod_info, 0, 2);
$pod .= <<POD
=item *
C<$key: $val>
POD
} while(@mod_info);
$pod .= "=back\n\n";
$pod =~ s/^ //mg;
print $pod;
return 1;
}
=item B<uninstall>
perl "-MExtUtils::Command::MM" -e uninstall <packlist>
A wrapper around ExtUtils::Install::uninstall(). Warns that
uninstallation is deprecated and doesn't actually perform the
uninstallation.
=cut
sub uninstall {
my($packlist) = shift @ARGV;
require ExtUtils::Install;
print <<'WARNING';
Uninstall is unsafe and deprecated, the uninstallation was not performed.
We will show what would have been done.
WARNING
ExtUtils::Install::uninstall($packlist, 1, 1);
print <<'WARNING';
Uninstall is unsafe and deprecated, the uninstallation was not performed.
Please check the list above carefully, there may be errors.
Remove the appropriate files manually.
Sorry for the inconvenience.
WARNING
}
=back
=cut
1;
EXTUTILS_COMMAND_MM
$fatpacked{"ExtUtils/Liblist.pm"} = <<'EXTUTILS_LIBLIST';
package ExtUtils::Liblist;
use strict;
our $VERSION = '6.59';
use File::Spec;
require ExtUtils::Liblist::Kid;
our @ISA = qw(ExtUtils::Liblist::Kid File::Spec);
# Backwards compatibility with old interface.
sub ext {
goto &ExtUtils::Liblist::Kid::ext;
}
sub lsdir {
shift;
my $rex = qr/$_[1]/;
opendir DIR, $_[0];
my @out = grep /$rex/, readdir DIR;
closedir DIR;
return @out;
}
__END__
=head1 NAME
ExtUtils::Liblist - determine libraries to use and how to use them
=head1 SYNOPSIS
require ExtUtils::Liblist;
$MM->ext($potential_libs, $verbose, $need_names);
# Usually you can get away with:
ExtUtils::Liblist->ext($potential_libs, $verbose, $need_names)
=head1 DESCRIPTION
This utility takes a list of libraries in the form C<-llib1 -llib2
-llib3> and returns lines suitable for inclusion in an extension
Makefile. Extra library paths may be included with the form
C<-L/another/path> this will affect the searches for all subsequent
libraries.
It returns an array of four or five scalar values: EXTRALIBS,
BSLOADLIBS, LDLOADLIBS, LD_RUN_PATH, and, optionally, a reference to
the array of the filenames of actual libraries. Some of these don't
mean anything unless on Unix. See the details about those platform
specifics below. The list of the filenames is returned only if
$need_names argument is true.
Dependent libraries can be linked in one of three ways:
=over 2
=item * For static extensions
by the ld command when the perl binary is linked with the extension
library. See EXTRALIBS below.
=item * For dynamic extensions at build/link time
by the ld command when the shared object is built/linked. See
LDLOADLIBS below.
=item * For dynamic extensions at load time
by the DynaLoader when the shared object is loaded. See BSLOADLIBS
below.
=back
=head2 EXTRALIBS
List of libraries that need to be linked with when linking a perl
binary which includes this extension. Only those libraries that
actually exist are included. These are written to a file and used
when linking perl.
=head2 LDLOADLIBS and LD_RUN_PATH
List of those libraries which can or must be linked into the shared
library when created using ld. These may be static or dynamic
libraries. LD_RUN_PATH is a colon separated list of the directories
in LDLOADLIBS. It is passed as an environment variable to the process
that links the shared library.
=head2 BSLOADLIBS
List of those libraries that are needed but can be linked in
dynamically at run time on this platform. SunOS/Solaris does not need
this because ld records the information (from LDLOADLIBS) into the
object file. This list is used to create a .bs (bootstrap) file.
=head1 PORTABILITY
This module deals with a lot of system dependencies and has quite a
few architecture specific C<if>s in the code.
=head2 VMS implementation
The version of ext() which is executed under VMS differs from the
Unix-OS/2 version in several respects:
=over 2
=item *
Input library and path specifications are accepted with or without the
C<-l> and C<-L> prefixes used by Unix linkers. If neither prefix is
present, a token is considered a directory to search if it is in fact
a directory, and a library to search for otherwise. Authors who wish
their extensions to be portable to Unix or OS/2 should use the Unix
prefixes, since the Unix-OS/2 version of ext() requires them.
=item *
Wherever possible, shareable images are preferred to object libraries,
and object libraries to plain object files. In accordance with VMS
naming conventions, ext() looks for files named I<lib>shr and I<lib>rtl;
it also looks for I<lib>lib and libI<lib> to accommodate Unix conventions
used in some ported software.
=item *
For each library that is found, an appropriate directive for a linker options
file is generated. The return values are space-separated strings of
these directives, rather than elements used on the linker command line.
=item *
LDLOADLIBS contains both the libraries found based on C<$potential_libs> and
the CRTLs, if any, specified in Config.pm. EXTRALIBS contains just those
libraries found based on C<$potential_libs>. BSLOADLIBS and LD_RUN_PATH
are always empty.
=back
In addition, an attempt is made to recognize several common Unix library
names, and filter them out or convert them to their VMS equivalents, as
appropriate.
In general, the VMS version of ext() should properly handle input from
extensions originally designed for a Unix or VMS environment. If you
encounter problems, or discover cases where the search could be improved,
please let us know.
=head2 Win32 implementation
The version of ext() which is executed under Win32 differs from the
Unix-OS/2 version in several respects:
=over 2
=item *
If C<$potential_libs> is empty, the return value will be empty.
Otherwise, the libraries specified by C<$Config{perllibs}> (see Config.pm)
will be appended to the list of C<$potential_libs>. The libraries
will be searched for in the directories specified in C<$potential_libs>,
C<$Config{libpth}>, and in C<$Config{installarchlib}/CORE>.
For each library that is found, a space-separated list of fully qualified
library pathnames is generated.
=item *
Input library and path specifications are accepted with or without the
C<-l> and C<-L> prefixes used by Unix linkers.
An entry of the form C<-La:\foo> specifies the C<a:\foo> directory to look
for the libraries that follow.
An entry of the form C<-lfoo> specifies the library C<foo>, which may be
spelled differently depending on what kind of compiler you are using. If
you are using GCC, it gets translated to C<libfoo.a>, but for other win32
compilers, it becomes C<foo.lib>. If no files are found by those translated
names, one more attempt is made to find them using either C<foo.a> or
C<libfoo.lib>, depending on whether GCC or some other win32 compiler is
being used, respectively.
If neither the C<-L> or C<-l> prefix is present in an entry, the entry is
considered a directory to search if it is in fact a directory, and a
library to search for otherwise. The C<$Config{lib_ext}> suffix will
be appended to any entries that are not directories and don't already have
the suffix.
Note that the C<-L> and C<-l> prefixes are B<not required>, but authors
who wish their extensions to be portable to Unix or OS/2 should use the
prefixes, since the Unix-OS/2 version of ext() requires them.
=item *
Entries cannot be plain object files, as many Win32 compilers will
not handle object files in the place of libraries.
=item *
Entries in C<$potential_libs> beginning with a colon and followed by
alphanumeric characters are treated as flags. Unknown flags will be ignored.
An entry that matches C</:nodefault/i> disables the appending of default
libraries found in C<$Config{perllibs}> (this should be only needed very rarely).
An entry that matches C</:nosearch/i> disables all searching for
the libraries specified after it. Translation of C<-Lfoo> and
C<-lfoo> still happens as appropriate (depending on compiler being used,
as reflected by C<$Config{cc}>), but the entries are not verified to be
valid files or directories.
An entry that matches C</:search/i> reenables searching for
the libraries specified after it. You can put it at the end to
enable searching for default libraries specified by C<$Config{perllibs}>.
=item *
The libraries specified may be a mixture of static libraries and
import libraries (to link with DLLs). Since both kinds are used
pretty transparently on the Win32 platform, we do not attempt to
distinguish between them.
=item *
LDLOADLIBS and EXTRALIBS are always identical under Win32, and BSLOADLIBS
and LD_RUN_PATH are always empty (this may change in future).
=item *
You must make sure that any paths and path components are properly
surrounded with double-quotes if they contain spaces. For example,
C<$potential_libs> could be (literally):
"-Lc:\Program Files\vc\lib" msvcrt.lib "la test\foo bar.lib"
Note how the first and last entries are protected by quotes in order
to protect the spaces.
=item *
Since this module is most often used only indirectly from extension
C<Makefile.PL> files, here is an example C<Makefile.PL> entry to add
a library to the build process for an extension:
LIBS => ['-lgl']
When using GCC, that entry specifies that MakeMaker should first look
for C<libgl.a> (followed by C<gl.a>) in all the locations specified by
C<$Config{libpth}>.
When using a compiler other than GCC, the above entry will search for
C<gl.lib> (followed by C<libgl.lib>).
If the library happens to be in a location not in C<$Config{libpth}>,
you need:
LIBS => ['-Lc:\gllibs -lgl']
Here is a less often used example:
LIBS => ['-lgl', ':nosearch -Ld:\mesalibs -lmesa -luser32']
This specifies a search for library C<gl> as before. If that search
fails to find the library, it looks at the next item in the list. The
C<:nosearch> flag will prevent searching for the libraries that follow,
so it simply returns the value as C<-Ld:\mesalibs -lmesa -luser32>,
since GCC can use that value as is with its linker.
When using the Visual C compiler, the second item is returned as
C<-libpath:d:\mesalibs mesa.lib user32.lib>.
When using the Borland compiler, the second item is returned as
C<-Ld:\mesalibs mesa.lib user32.lib>, and MakeMaker takes care of
moving the C<-Ld:\mesalibs> to the correct place in the linker
command line.
=back
=head1 SEE ALSO
L<ExtUtils::MakeMaker>
=cut
EXTUTILS_LIBLIST
$fatpacked{"ExtUtils/Liblist/Kid.pm"} = <<'EXTUTILS_LIBLIST_KID';
package ExtUtils::Liblist::Kid;
# XXX Splitting this out into its own .pm is a temporary solution.
# This kid package is to be used by MakeMaker. It will not work if
# $self is not a Makemaker.
use 5.006;
# Broken out of MakeMaker from version 4.11
use strict;
use warnings;
our $VERSION = '6.59';
use ExtUtils::MakeMaker::Config;
use Cwd 'cwd';
use File::Basename;
use File::Spec;
sub ext {
if ( $^O eq 'VMS' ) { return &_vms_ext; }
elsif ( $^O eq 'MSWin32' ) { return &_win32_ext; }
else { return &_unix_os2_ext; }
}
sub _unix_os2_ext {
my ( $self, $potential_libs, $verbose, $give_libs ) = @_;
$verbose ||= 0;
if ( $^O =~ 'os2' and $Config{perllibs} ) {
# Dynamic libraries are not transitive, so we may need including
# the libraries linked against perl.dll again.
$potential_libs .= " " if $potential_libs;
$potential_libs .= $Config{perllibs};
}
return ( "", "", "", "", ( $give_libs ? [] : () ) ) unless $potential_libs;
warn "Potential libraries are '$potential_libs':\n" if $verbose;
my ( $so ) = $Config{so};
my ( $libs ) = defined $Config{perllibs} ? $Config{perllibs} : $Config{libs};
my $Config_libext = $Config{lib_ext} || ".a";
my $Config_dlext = $Config{dlext};
# compute $extralibs, $bsloadlibs and $ldloadlibs from
# $potential_libs
# this is a rewrite of Andy Dougherty's extliblist in perl
my ( @searchpath ); # from "-L/path" entries in $potential_libs
my ( @libpath ) = split " ", $Config{'libpth'};
my ( @ldloadlibs, @bsloadlibs, @extralibs, @ld_run_path, %ld_run_path_seen );
my ( @libs, %libs_seen );
my ( $fullname, @fullname );
my ( $pwd ) = cwd(); # from Cwd.pm
my ( $found ) = 0;
foreach my $thislib ( split ' ', $potential_libs ) {
# Handle possible linker path arguments.
if ( $thislib =~ s/^(-[LR]|-Wl,-R)// ) { # save path flag type
my ( $ptype ) = $1;
unless ( -d $thislib ) {
warn "$ptype$thislib ignored, directory does not exist\n"
if $verbose;
next;
}
my ( $rtype ) = $ptype;
if ( ( $ptype eq '-R' ) or ( $ptype eq '-Wl,-R' ) ) {
if ( $Config{'lddlflags'} =~ /-Wl,-R/ ) {
$rtype = '-Wl,-R';
}
elsif ( $Config{'lddlflags'} =~ /-R/ ) {
$rtype = '-R';
}
}
unless ( File::Spec->file_name_is_absolute( $thislib ) ) {
warn "Warning: $ptype$thislib changed to $ptype$pwd/$thislib\n";
$thislib = $self->catdir( $pwd, $thislib );
}
push( @searchpath, $thislib );
push( @extralibs, "$ptype$thislib" );
push( @ldloadlibs, "$rtype$thislib" );
next;
}
# Handle possible library arguments.
unless ( $thislib =~ s/^-l// ) {
warn "Unrecognized argument in LIBS ignored: '$thislib'\n";
next;
}
my ( $found_lib ) = 0;
foreach my $thispth ( @searchpath, @libpath ) {
# Try to find the full name of the library. We need this to
# determine whether it's a dynamically-loadable library or not.
# This tends to be subject to various os-specific quirks.
# For gcc-2.6.2 on linux (March 1995), DLD can not load
# .sa libraries, with the exception of libm.sa, so we
# deliberately skip them.
if ( @fullname = $self->lsdir( $thispth, "^\Qlib$thislib.$so.\E[0-9]+" ) ) {
# Take care that libfoo.so.10 wins against libfoo.so.9.
# Compare two libraries to find the most recent version
# number. E.g. if you have libfoo.so.9.0.7 and
# libfoo.so.10.1, first convert all digits into two
# decimal places. Then we'll add ".00" to the shorter
# strings so that we're comparing strings of equal length
# Thus we'll compare libfoo.so.09.07.00 with
# libfoo.so.10.01.00. Some libraries might have letters
# in the version. We don't know what they mean, but will
# try to skip them gracefully -- we'll set any letter to
# '0'. Finally, sort in reverse so we can take the
# first element.
#TODO: iterate through the directory instead of sorting
$fullname = "$thispth/" . (
sort {
my ( $ma ) = $a;
my ( $mb ) = $b;
$ma =~ tr/A-Za-z/0/s;
$ma =~ s/\b(\d)\b/0$1/g;
$mb =~ tr/A-Za-z/0/s;
$mb =~ s/\b(\d)\b/0$1/g;
while ( length( $ma ) < length( $mb ) ) { $ma .= ".00"; }
while ( length( $mb ) < length( $ma ) ) { $mb .= ".00"; }
# Comparison deliberately backwards
$mb cmp $ma;
} @fullname
)[0];
}
elsif ( -f ( $fullname = "$thispth/lib$thislib.$so" )
&& ( ( $Config{'dlsrc'} ne "dl_dld.xs" ) || ( $thislib eq "m" ) ) )
{
}
elsif (-f ( $fullname = "$thispth/lib${thislib}_s$Config_libext" )
&& ( $Config{'archname'} !~ /RM\d\d\d-svr4/ )
&& ( $thislib .= "_s" ) )
{ # we must explicitly use _s version
}
elsif ( -f ( $fullname = "$thispth/lib$thislib$Config_libext" ) ) {
}
elsif ( defined( $Config_dlext )
&& -f ( $fullname = "$thispth/lib$thislib.$Config_dlext" ) )
{
}
elsif ( -f ( $fullname = "$thispth/$thislib$Config_libext" ) ) {
}
elsif ( -f ( $fullname = "$thispth/lib$thislib.dll$Config_libext" ) ) {
}
elsif ( -f ( $fullname = "$thispth/Slib$thislib$Config_libext" ) ) {
}
elsif ($^O eq 'dgux'
&& -l ( $fullname = "$thispth/lib$thislib$Config_libext" )
&& readlink( $fullname ) =~ /^elink:/s )
{
# Some of DG's libraries look like misconnected symbolic
# links, but development tools can follow them. (They
# look like this:
#
# libm.a -> elink:${SDE_PATH:-/usr}/sde/\
# ${TARGET_BINARY_INTERFACE:-m88kdgux}/usr/lib/libm.a
#
# , the compilation tools expand the environment variables.)
}
else {
warn "$thislib not found in $thispth\n" if $verbose;
next;
}
warn "'-l$thislib' found at $fullname\n" if $verbose;
push @libs, $fullname unless $libs_seen{$fullname}++;
$found++;
$found_lib++;
# Now update library lists
# what do we know about this library...
my $is_dyna = ( $fullname !~ /\Q$Config_libext\E\z/ );
my $in_perl = ( $libs =~ /\B-l\Q${thislib}\E\b/s );
# include the path to the lib once in the dynamic linker path
# but only if it is a dynamic lib and not in Perl itself
my ( $fullnamedir ) = dirname( $fullname );
push @ld_run_path, $fullnamedir
if $is_dyna
&& !$in_perl
&& !$ld_run_path_seen{$fullnamedir}++;
# Do not add it into the list if it is already linked in
# with the main perl executable.
# We have to special-case the NeXT, because math and ndbm
# are both in libsys_s
unless (
$in_perl
|| ( $Config{'osname'} eq 'next'
&& ( $thislib eq 'm' || $thislib eq 'ndbm' ) )
)
{
push( @extralibs, "-l$thislib" );
}
# We might be able to load this archive file dynamically
if ( ( $Config{'dlsrc'} =~ /dl_next/ && $Config{'osvers'} lt '4_0' )
|| ( $Config{'dlsrc'} =~ /dl_dld/ ) )
{
# We push -l$thislib instead of $fullname because
# it avoids hardwiring a fixed path into the .bs file.
# Mkbootstrap will automatically add dl_findfile() to
# the .bs file if it sees a name in the -l format.
# USE THIS, when dl_findfile() is fixed:
# push(@bsloadlibs, "-l$thislib");
# OLD USE WAS while checking results against old_extliblist
push( @bsloadlibs, "$fullname" );
}
else {
if ( $is_dyna ) {
# For SunOS4, do not add in this shared library if
# it is already linked in the main perl executable
push( @ldloadlibs, "-l$thislib" )
unless ( $in_perl and $^O eq 'sunos' );
}
else {
push( @ldloadlibs, "-l$thislib" );
}
}
last; # found one here so don't bother looking further
}
warn "Note (probably harmless): " . "No library found for -l$thislib\n"
unless $found_lib > 0;
}
unless ( $found ) {
return ( '', '', '', '', ( $give_libs ? \@libs : () ) );
}
else {
return ( "@extralibs", "@bsloadlibs", "@ldloadlibs", join( ":", @ld_run_path ), ( $give_libs ? \@libs : () ) );
}
}
sub _win32_ext {
require Text::ParseWords;
my ( $self, $potential_libs, $verbose, $give_libs ) = @_;
$verbose ||= 0;
# If user did not supply a list, we punt.
# (caller should probably use the list in $Config{libs})
return ( "", "", "", "", ( $give_libs ? [] : () ) ) unless $potential_libs;
# TODO: make this use MM_Win32.pm's compiler detection
my %libs_seen;
my @extralibs;
my $cc = $Config{cc} || '';
my $VC = $cc =~ /\bcl\b/i;
my $GC = $cc =~ /\bgcc\b/i;
my $libext = _win32_lib_extensions();
my @searchpath = ( '' ); # from "-L/path" entries in $potential_libs
my @libpath = _win32_default_search_paths( $VC );
my $pwd = cwd(); # from Cwd.pm
my $search = 1;
# compute @extralibs from $potential_libs
my @lib_search_list = _win32_make_lib_search_list( $potential_libs, $verbose );
for ( @lib_search_list ) {
my $thislib = $_;
# see if entry is a flag
if ( /^:\w+$/ ) {
$search = 0 if lc eq ':nosearch';
$search = 1 if lc eq ':search';
_debug( "Ignoring unknown flag '$thislib'\n", $verbose ) if !/^:(no)?(search|default)$/i;
next;
}
# if searching is disabled, do compiler-specific translations
unless ( $search ) {
s/^-l(.+)$/$1.lib/ unless $GC;
s/^-L/-libpath:/ if $VC;
push( @extralibs, $_ );
next;
}
# handle possible linker path arguments
if ( s/^-L// and not -d ) {
_debug( "$thislib ignored, directory does not exist\n", $verbose );
next;
}
elsif ( -d ) {
unless ( File::Spec->file_name_is_absolute( $_ ) ) {
warn "Warning: '$thislib' changed to '-L$pwd/$_'\n";
$_ = $self->catdir( $pwd, $_ );
}
push( @searchpath, $_ );
next;
}
my @paths = ( @searchpath, @libpath );
my ( $fullname, $path ) = _win32_search_file( $thislib, $libext, \@paths, $verbose, $GC );
if ( !$fullname ) {
warn "Note (probably harmless): No library found for $thislib\n";
next;
}
_debug( "'$thislib' found as '$fullname'\n", $verbose );
push( @extralibs, $fullname );
$libs_seen{$fullname} = 1 if $path; # why is this a special case?
}
my @libs = keys %libs_seen;
return ( '', '', '', '', ( $give_libs ? \@libs : () ) ) unless @extralibs;
# make sure paths with spaces are properly quoted
@extralibs = map { /\s/ ? qq["$_"] : $_ } @extralibs;
@libs = map { /\s/ ? qq["$_"] : $_ } @libs;
my $lib = join( ' ', @extralibs );
# normalize back to backward slashes (to help braindead tools)
# XXX this may break equally braindead GNU tools that don't understand
# backslashes, either. Seems like one can't win here. Cursed be CP/M.
$lib =~ s,/,\\,g;
_debug( "Result: $lib\n", $verbose );
wantarray ? ( $lib, '', $lib, '', ( $give_libs ? \@libs : () ) ) : $lib;
}
sub _win32_make_lib_search_list {
my ( $potential_libs, $verbose ) = @_;
# If Config.pm defines a set of default libs, we always
# tack them on to the user-supplied list, unless the user
# specified :nodefault
my $libs = $Config{'perllibs'};
$potential_libs = join( ' ', $potential_libs, $libs ) if $libs and $potential_libs !~ /:nodefault/i;
_debug( "Potential libraries are '$potential_libs':\n", $verbose );
$potential_libs =~ s,\\,/,g; # normalize to forward slashes
my @list = Text::ParseWords::quotewords( '\s+', 0, $potential_libs );
return @list;
}
sub _win32_default_search_paths {
my ( $VC ) = @_;
my $libpth = $Config{'libpth'} || '';
$libpth =~ s,\\,/,g; # normalize to forward slashes
my @libpath = Text::ParseWords::quotewords( '\s+', 0, $libpth );
push @libpath, "$Config{installarchlib}/CORE"; # add "$Config{installarchlib}/CORE" to default search path
if ( $VC and exists $ENV{LIB} and $ENV{LIB} ) {
push @libpath, split /;/, $ENV{LIB};
}
return @libpath;
}
sub _win32_search_file {
my ( $thislib, $libext, $paths, $verbose, $GC ) = @_;
my @file_list = _win32_build_file_list( $thislib, $GC, $libext );
for my $lib_file ( @file_list ) {
for my $path ( @{$paths} ) {
my $fullname = $lib_file;
$fullname = "$path\\$fullname" if $path;
return ( $fullname, $path ) if -f $fullname;
_debug( "'$thislib' not found as '$fullname'\n", $verbose );
}
}
return;
}
sub _win32_build_file_list {
my ( $lib, $GC, $extensions ) = @_;
my @pre_fixed = _win32_build_prefixed_list( $lib, $GC );
return map _win32_attach_extensions( $_, $extensions ), @pre_fixed;
}
sub _win32_build_prefixed_list {
my ( $lib, $GC ) = @_;
return $lib if $lib !~ s/^-l//;
return $lib if $lib =~ /^lib/ and !$GC;
( my $no_prefix = $lib ) =~ s/^lib//i;
$lib = "lib$lib" if $no_prefix eq $lib;
return ( $lib, $no_prefix ) if $GC;
return ( $no_prefix, $lib );
}
sub _win32_attach_extensions {
my ( $lib, $extensions ) = @_;
return map _win32_try_attach_extension( $lib, $_ ), @{$extensions};
}
sub _win32_try_attach_extension {
my ( $lib, $extension ) = @_;
return $lib if $lib =~ /\Q$extension\E$/i;
return "$lib$extension";
}
sub _win32_lib_extensions {
my %extensions;
$extensions{ $Config{'lib_ext'} } = 1 if $Config{'lib_ext'};
$extensions{".lib"} = 1;
return [ keys %extensions ];
}
sub _debug {
my ( $message, $verbose ) = @_;
return if !$verbose;
warn $message;
return;
}
sub _vms_ext {
my ( $self, $potential_libs, $verbose, $give_libs ) = @_;
$verbose ||= 0;
my ( @crtls, $crtlstr );
@crtls = ( ( $Config{'ldflags'} =~ m-/Debug-i ? $Config{'dbgprefix'} : '' ) . 'PerlShr/Share' );
push( @crtls, grep { not /\(/ } split /\s+/, $Config{'perllibs'} );
push( @crtls, grep { not /\(/ } split /\s+/, $Config{'libc'} );
# In general, we pass through the basic libraries from %Config unchanged.
# The one exception is that if we're building in the Perl source tree, and
# a library spec could be resolved via a logical name, we go to some trouble
# to insure that the copy in the local tree is used, rather than one to
# which a system-wide logical may point.
if ( $self->{PERL_SRC} ) {
my ( $locspec, $type );
foreach my $lib ( @crtls ) {
if ( ( $locspec, $type ) = $lib =~ m{^([\w\$-]+)(/\w+)?} and $locspec =~ /perl/i ) {
if ( lc $type eq '/share' ) { $locspec .= $Config{'exe_ext'}; }
elsif ( lc $type eq '/library' ) { $locspec .= $Config{'lib_ext'}; }
else { $locspec .= $Config{'obj_ext'}; }
$locspec = $self->catfile( $self->{PERL_SRC}, $locspec );
$lib = "$locspec$type" if -e $locspec;
}
}
}
$crtlstr = @crtls ? join( ' ', @crtls ) : '';
unless ( $potential_libs ) {
warn "Result:\n\tEXTRALIBS: \n\tLDLOADLIBS: $crtlstr\n" if $verbose;
return ( '', '', $crtlstr, '', ( $give_libs ? [] : () ) );
}
my ( %found, @fndlibs, $ldlib );
my $cwd = cwd();
my ( $so, $lib_ext, $obj_ext ) = @Config{ 'so', 'lib_ext', 'obj_ext' };
# List of common Unix library names and their VMS equivalents
# (VMS equivalent of '' indicates that the library is automatically
# searched by the linker, and should be skipped here.)
my ( @flibs, %libs_seen );
my %libmap = (
'm' => '',
'f77' => '',
'F77' => '',
'V77' => '',
'c' => '',
'malloc' => '',
'crypt' => '',
'resolv' => '',
'c_s' => '',
'socket' => '',
'X11' => 'DECW$XLIBSHR',
'Xt' => 'DECW$XTSHR',
'Xm' => 'DECW$XMLIBSHR',
'Xmu' => 'DECW$XMULIBSHR'
);
if ( $Config{'vms_cc_type'} ne 'decc' ) { $libmap{'curses'} = 'VAXCCURSE'; }
warn "Potential libraries are '$potential_libs'\n" if $verbose;
# First, sort out directories and library names in the input
my ( @dirs, @libs );
foreach my $lib ( split ' ', $potential_libs ) {
push( @dirs, $1 ), next if $lib =~ /^-L(.*)/;
push( @dirs, $lib ), next if $lib =~ /[:>\]]$/;
push( @dirs, $lib ), next if -d $lib;
push( @libs, $1 ), next if $lib =~ /^-l(.*)/;
push( @libs, $lib );
}
push( @dirs, split( ' ', $Config{'libpth'} ) );
# Now make sure we've got VMS-syntax absolute directory specs
# (We don't, however, check whether someone's hidden a relative
# path in a logical name.)
foreach my $dir ( @dirs ) {
unless ( -d $dir ) {
warn "Skipping nonexistent Directory $dir\n" if $verbose > 1;
$dir = '';
next;
}
warn "Resolving directory $dir\n" if $verbose;
if ( File::Spec->file_name_is_absolute( $dir ) ) {
$dir = $self->fixpath( $dir, 1 );
}
else {
$dir = $self->catdir( $cwd, $dir );
}
}
@dirs = grep { length( $_ ) } @dirs;
unshift( @dirs, '' ); # Check each $lib without additions first
LIB: foreach my $lib ( @libs ) {
if ( exists $libmap{$lib} ) {
next unless length $libmap{$lib};
$lib = $libmap{$lib};
}
my ( @variants, $cand );
my ( $ctype ) = '';
# If we don't have a file type, consider it a possibly abbreviated name and
# check for common variants. We try these first to grab libraries before
# a like-named executable image (e.g. -lperl resolves to perlshr.exe
# before perl.exe).
if ( $lib !~ /\.[^:>\]]*$/ ) {
push( @variants, "${lib}shr", "${lib}rtl", "${lib}lib" );
push( @variants, "lib$lib" ) if $lib !~ /[:>\]]/;
}
push( @variants, $lib );
warn "Looking for $lib\n" if $verbose;
foreach my $variant ( @variants ) {
my ( $fullname, $name );
foreach my $dir ( @dirs ) {
my ( $type );
$name = "$dir$variant";
warn "\tChecking $name\n" if $verbose > 2;
$fullname = VMS::Filespec::rmsexpand( $name );
if ( defined $fullname and -f $fullname ) {
# It's got its own suffix, so we'll have to figure out the type
if ( $fullname =~ /(?:$so|exe)$/i ) { $type = 'SHR'; }
elsif ( $fullname =~ /(?:$lib_ext|olb)$/i ) { $type = 'OLB'; }
elsif ( $fullname =~ /(?:$obj_ext|obj)$/i ) {
warn "Note (probably harmless): " . "Plain object file $fullname found in library list\n";
$type = 'OBJ';
}
else {
warn "Note (probably harmless): " . "Unknown library type for $fullname; assuming shared\n";
$type = 'SHR';
}
}
elsif (-f ( $fullname = VMS::Filespec::rmsexpand( $name, $so ) )
or -f ( $fullname = VMS::Filespec::rmsexpand( $name, '.exe' ) ) )
{
$type = 'SHR';
$name = $fullname unless $fullname =~ /exe;?\d*$/i;
}
elsif (
not length( $ctype ) and # If we've got a lib already,
# don't bother
( -f ( $fullname = VMS::Filespec::rmsexpand( $name, $lib_ext ) ) or -f ( $fullname = VMS::Filespec::rmsexpand( $name, '.olb' ) ) )
)
{
$type = 'OLB';
$name = $fullname unless $fullname =~ /olb;?\d*$/i;
}
elsif (
not length( $ctype ) and # If we've got a lib already,
# don't bother
( -f ( $fullname = VMS::Filespec::rmsexpand( $name, $obj_ext ) ) or -f ( $fullname = VMS::Filespec::rmsexpand( $name, '.obj' ) ) )
)
{
warn "Note (probably harmless): " . "Plain object file $fullname found in library list\n";
$type = 'OBJ';
$name = $fullname unless $fullname =~ /obj;?\d*$/i;
}
if ( defined $type ) {
$ctype = $type;
$cand = $name;
last if $ctype eq 'SHR';
}
}
if ( $ctype ) {
# This has to precede any other CRTLs, so just make it first
if ( $cand eq 'VAXCCURSE' ) { unshift @{ $found{$ctype} }, $cand; }
else { push @{ $found{$ctype} }, $cand; }
warn "\tFound as $cand (really $fullname), type $ctype\n"
if $verbose > 1;
push @flibs, $name unless $libs_seen{$fullname}++;
next LIB;
}
}
warn "Note (probably harmless): " . "No library found for $lib\n";
}
push @fndlibs, @{ $found{OBJ} } if exists $found{OBJ};
push @fndlibs, map { "$_/Library" } @{ $found{OLB} } if exists $found{OLB};
push @fndlibs, map { "$_/Share" } @{ $found{SHR} } if exists $found{SHR};
my $lib = join( ' ', @fndlibs );
$ldlib = $crtlstr ? "$lib $crtlstr" : $lib;
warn "Result:\n\tEXTRALIBS: $lib\n\tLDLOADLIBS: $ldlib\n" if $verbose;
wantarray ? ( $lib, '', $ldlib, '', ( $give_libs ? \@flibs : () ) ) : $lib;
}
1;
EXTUTILS_LIBLIST_KID
$fatpacked{"ExtUtils/MM.pm"} = <<'EXTUTILS_MM';
package ExtUtils::MM;
use strict;
use ExtUtils::MakeMaker::Config;
our $VERSION = '6.59';
require ExtUtils::Liblist;
require ExtUtils::MakeMaker;
our @ISA = qw(ExtUtils::Liblist ExtUtils::MakeMaker);
=head1 NAME
ExtUtils::MM - OS adjusted ExtUtils::MakeMaker subclass
=head1 SYNOPSIS
require ExtUtils::MM;
my $mm = MM->new(...);
=head1 DESCRIPTION
B<FOR INTERNAL USE ONLY>
ExtUtils::MM is a subclass of ExtUtils::MakeMaker which automatically
chooses the appropriate OS specific subclass for you
(ie. ExtUils::MM_Unix, etc...).
It also provides a convenient alias via the MM class (I didn't want
MakeMaker modules outside of ExtUtils/).
This class might turn out to be a temporary solution, but MM won't go
away.
=cut
{
# Convenient alias.
package MM;
our @ISA = qw(ExtUtils::MM);
sub DESTROY {}
}
sub _is_win95 {
# miniperl might not have the Win32 functions available and we need
# to run in miniperl.
my $have_win32 = eval { require Win32 };
return $have_win32 && defined &Win32::IsWin95 ? Win32::IsWin95()
: ! defined $ENV{SYSTEMROOT};
}
my %Is = ();
$Is{VMS} = $^O eq 'VMS';
$Is{OS2} = $^O eq 'os2';
$Is{MacOS} = $^O eq 'MacOS';
if( $^O eq 'MSWin32' ) {
_is_win95() ? $Is{Win95} = 1 : $Is{Win32} = 1;
}
$Is{UWIN} = $^O =~ /^uwin(-nt)?$/;
$Is{Cygwin} = $^O eq 'cygwin';
$Is{NW5} = $Config{osname} eq 'NetWare'; # intentional
$Is{BeOS} = ($^O =~ /beos/i or $^O eq 'haiku');
$Is{DOS} = $^O eq 'dos';
if( $Is{NW5} ) {
$^O = 'NetWare';
delete $Is{Win32};
}
$Is{VOS} = $^O eq 'vos';
$Is{QNX} = $^O eq 'qnx';
$Is{AIX} = $^O eq 'aix';
$Is{Darwin} = $^O eq 'darwin';
$Is{Unix} = !grep { $_ } values %Is;
map { delete $Is{$_} unless $Is{$_} } keys %Is;
_assert( keys %Is == 1 );
my($OS) = keys %Is;
my $class = "ExtUtils::MM_$OS";
eval "require $class" unless $INC{"ExtUtils/MM_$OS.pm"}; ## no critic
die $@ if $@;
unshift @ISA, $class;
sub _assert {
my $sanity = shift;
die sprintf "Assert failed at %s line %d\n", (caller)[1,2] unless $sanity;
return;
}
EXTUTILS_MM
$fatpacked{"ExtUtils/MM_AIX.pm"} = <<'EXTUTILS_MM_AIX';
package ExtUtils::MM_AIX;
use strict;
our $VERSION = '6.59';
require ExtUtils::MM_Unix;
our @ISA = qw(ExtUtils::MM_Unix);
use ExtUtils::MakeMaker qw(neatvalue);
=head1 NAME
ExtUtils::MM_AIX - AIX specific subclass of ExtUtils::MM_Unix
=head1 SYNOPSIS
Don't use this module directly.
Use ExtUtils::MM and let it choose.
=head1 DESCRIPTION
This is a subclass of ExtUtils::MM_Unix which contains functionality for
AIX.
Unless otherwise stated it works just like ExtUtils::MM_Unix
=head2 Overridden methods
=head3 dlsyms
Define DL_FUNCS and DL_VARS and write the *.exp files.
=cut
sub dlsyms {
my($self,%attribs) = @_;
return '' unless $self->needs_linking();
my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || [];
my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
my(@m);
push(@m,"
dynamic :: $self->{BASEEXT}.exp
") unless $self->{SKIPHASH}{'dynamic'}; # dynamic and static are subs, so...
push(@m,"
static :: $self->{BASEEXT}.exp
") unless $self->{SKIPHASH}{'static'}; # we avoid a warning if we tick them
push(@m,"
$self->{BASEEXT}.exp: Makefile.PL
",' $(PERLRUN) -e \'use ExtUtils::Mksymlists; \\
Mksymlists("NAME" => "',$self->{NAME},'", "DL_FUNCS" => ',
neatvalue($funcs), ', "FUNCLIST" => ', neatvalue($funclist),
', "DL_VARS" => ', neatvalue($vars), ');\'
');
join('',@m);
}
=head1 AUTHOR
Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
=head1 SEE ALSO
L<ExtUtils::MakeMaker>
=cut
1;
EXTUTILS_MM_AIX
$fatpacked{"ExtUtils/MM_Any.pm"} = <<'EXTUTILS_MM_ANY';
package ExtUtils::MM_Any;
use strict;
our $VERSION = '6.59';
use Carp;
use File::Spec;
use File::Basename;
BEGIN { our @ISA = qw(File::Spec); }
# We need $Verbose
use ExtUtils::MakeMaker qw($Verbose);
use ExtUtils::MakeMaker::Config;
# So we don't have to keep calling the methods over and over again,
# we have these globals to cache the values. Faster and shrtr.
my $Curdir = __PACKAGE__->curdir;
my $Rootdir = __PACKAGE__->rootdir;
my $Updir = __PACKAGE__->updir;
=head1 NAME
ExtUtils::MM_Any - Platform-agnostic MM methods
=head1 SYNOPSIS
FOR INTERNAL USE ONLY!
package ExtUtils::MM_SomeOS;
# Temporarily, you have to subclass both. Put MM_Any first.
require ExtUtils::MM_Any;
require ExtUtils::MM_Unix;
@ISA = qw(ExtUtils::MM_Any ExtUtils::Unix);
=head1 DESCRIPTION
B<FOR INTERNAL USE ONLY!>
ExtUtils::MM_Any is a superclass for the ExtUtils::MM_* set of
modules. It contains methods which are either inherently
cross-platform or are written in a cross-platform manner.
Subclass off of ExtUtils::MM_Any I<and> ExtUtils::MM_Unix. This is a
temporary solution.
B<THIS MAY BE TEMPORARY!>
=head1 METHODS
Any methods marked I<Abstract> must be implemented by subclasses.
=head2 Cross-platform helper methods
These are methods which help writing cross-platform code.
=head3 os_flavor I<Abstract>
my @os_flavor = $mm->os_flavor;
@os_flavor is the style of operating system this is, usually
corresponding to the MM_*.pm file we're using.
The first element of @os_flavor is the major family (ie. Unix,
Windows, VMS, OS/2, etc...) and the rest are sub families.
Some examples:
Cygwin98 ('Unix', 'Cygwin', 'Cygwin9x')
Windows ('Win32')
Win98 ('Win32', 'Win9x')
Linux ('Unix', 'Linux')
MacOS X ('Unix', 'Darwin', 'MacOS', 'MacOS X')
OS/2 ('OS/2')
This is used to write code for styles of operating system.
See os_flavor_is() for use.
=head3 os_flavor_is
my $is_this_flavor = $mm->os_flavor_is($this_flavor);
my $is_this_flavor = $mm->os_flavor_is(@one_of_these_flavors);
Checks to see if the current operating system is one of the given flavors.
This is useful for code like:
if( $mm->os_flavor_is('Unix') ) {
$out = `foo 2>&1`;
}
else {
$out = `foo`;
}
=cut
sub os_flavor_is {
my $self = shift;
my %flavors = map { ($_ => 1) } $self->os_flavor;
return (grep { $flavors{$_} } @_) ? 1 : 0;
}
=head3 can_load_xs
my $can_load_xs = $self->can_load_xs;
Returns true if we have the ability to load XS.
This is important because miniperl, used to build XS modules in the
core, can not load XS.
=cut
sub can_load_xs {
return defined &DynaLoader::boot_DynaLoader ? 1 : 0;
}
=head3 split_command
my @cmds = $MM->split_command($cmd, @args);
Most OS have a maximum command length they can execute at once. Large
modules can easily generate commands well past that limit. Its
necessary to split long commands up into a series of shorter commands.
C<split_command> will return a series of @cmds each processing part of
the args. Collectively they will process all the arguments. Each
individual line in @cmds will not be longer than the
$self->max_exec_len being careful to take into account macro expansion.
$cmd should include any switches and repeated initial arguments.
If no @args are given, no @cmds will be returned.
Pairs of arguments will always be preserved in a single command, this
is a heuristic for things like pm_to_blib and pod2man which work on
pairs of arguments. This makes things like this safe:
$self->split_command($cmd, %pod2man);
=cut
sub split_command {
my($self, $cmd, @args) = @_;
my @cmds = ();
return(@cmds) unless @args;
# If the command was given as a here-doc, there's probably a trailing
# newline.
chomp $cmd;
# set aside 30% for macro expansion.
my $len_left = int($self->max_exec_len * 0.70);
$len_left -= length $self->_expand_macros($cmd);
do {
my $arg_str = '';
my @next_args;
while( @next_args = splice(@args, 0, 2) ) {
# Two at a time to preserve pairs.
my $next_arg_str = "\t ". join ' ', @next_args, "\n";
if( !length $arg_str ) {
$arg_str .= $next_arg_str
}
elsif( length($arg_str) + length($next_arg_str) > $len_left ) {
unshift @args, @next_args;
last;
}
else {
$arg_str .= $next_arg_str;
}
}
chop $arg_str;
push @cmds, $self->escape_newlines("$cmd \n$arg_str");
} while @args;
return @cmds;
}
sub _expand_macros {
my($self, $cmd) = @_;
$cmd =~ s{\$\((\w+)\)}{
defined $self->{$1} ? $self->{$1} : "\$($1)"
}e;
return $cmd;
}
=head3 echo
my @commands = $MM->echo($text);
my @commands = $MM->echo($text, $file);
my @commands = $MM->echo($text, $file, $appending);
Generates a set of @commands which print the $text to a $file.
If $file is not given, output goes to STDOUT.
If $appending is true the $file will be appended to rather than
overwritten.
=cut
sub echo {
my($self, $text, $file, $appending) = @_;
$appending ||= 0;
my @cmds = map { '$(NOECHO) $(ECHO) '.$self->quote_literal($_) }
split /\n/, $text;
if( $file ) {
my $redirect = $appending ? '>>' : '>';
$cmds[0] .= " $redirect $file";
$_ .= " >> $file" foreach @cmds[1..$#cmds];
}
return @cmds;
}
=head3 wraplist
my $args = $mm->wraplist(@list);
Takes an array of items and turns them into a well-formatted list of
arguments. In most cases this is simply something like:
FOO \
BAR \
BAZ
=cut
sub wraplist {
my $self = shift;
return join " \\\n\t", @_;
}
=head3 maketext_filter
my $filter_make_text = $mm->maketext_filter($make_text);
The text of the Makefile is run through this method before writing to
disk. It allows systems a chance to make portability fixes to the
Makefile.
By default it does nothing.
This method is protected and not intended to be called outside of
MakeMaker.
=cut
sub maketext_filter { return $_[1] }
=head3 cd I<Abstract>
my $subdir_cmd = $MM->cd($subdir, @cmds);
This will generate a make fragment which runs the @cmds in the given
$dir. The rough equivalent to this, except cross platform.
cd $subdir && $cmd
Currently $dir can only go down one level. "foo" is fine. "foo/bar" is
not. "../foo" is right out.
The resulting $subdir_cmd has no leading tab nor trailing newline. This
makes it easier to embed in a make string. For example.
my $make = sprintf <<'CODE', $subdir_cmd;
foo :
$(ECHO) what
%s
$(ECHO) mouche
CODE
=head3 oneliner I<Abstract>
my $oneliner = $MM->oneliner($perl_code);
my $oneliner = $MM->oneliner($perl_code, \@switches);
This will generate a perl one-liner safe for the particular platform
you're on based on the given $perl_code and @switches (a -e is
assumed) suitable for using in a make target. It will use the proper
shell quoting and escapes.
$(PERLRUN) will be used as perl.
Any newlines in $perl_code will be escaped. Leading and trailing
newlines will be stripped. Makes this idiom much easier:
my $code = $MM->oneliner(<<'CODE', [...switches...]);
some code here
another line here
CODE
Usage might be something like:
# an echo emulation
$oneliner = $MM->oneliner('print "Foo\n"');
$make = '$oneliner > somefile';
All dollar signs must be doubled in the $perl_code if you expect them
to be interpreted normally, otherwise it will be considered a make
macro. Also remember to quote make macros else it might be used as a
bareword. For example:
# Assign the value of the $(VERSION_FROM) make macro to $vf.
$oneliner = $MM->oneliner('$$vf = "$(VERSION_FROM)"');
Its currently very simple and may be expanded sometime in the figure
to include more flexible code and switches.
=head3 quote_literal I<Abstract>
my $safe_text = $MM->quote_literal($text);
This will quote $text so it is interpreted literally in the shell.
For example, on Unix this would escape any single-quotes in $text and
put single-quotes around the whole thing.
=head3 escape_newlines I<Abstract>
my $escaped_text = $MM->escape_newlines($text);
Shell escapes newlines in $text.
=head3 max_exec_len I<Abstract>
my $max_exec_len = $MM->max_exec_len;
Calculates the maximum command size the OS can exec. Effectively,
this is the max size of a shell command line.
=for _private
$self->{_MAX_EXEC_LEN} is set by this method, but only for testing purposes.
=head3 make
my $make = $MM->make;
Returns the make variant we're generating the Makefile for. This attempts
to do some normalization on the information from %Config or the user.
=cut
sub make {
my $self = shift;
my $make = lc $self->{MAKE};
# Truncate anything like foomake6 to just foomake.
$make =~ s/^(\w+make).*/$1/;
# Turn gnumake into gmake.
$make =~ s/^gnu/g/;
return $make;
}
=head2 Targets
These are methods which produce make targets.
=head3 all_target
Generate the default target 'all'.
=cut
sub all_target {
my $self = shift;
return <<'MAKE_EXT';
all :: pure_all
$(NOECHO) $(NOOP)
MAKE_EXT
}
=head3 blibdirs_target
my $make_frag = $mm->blibdirs_target;
Creates the blibdirs target which creates all the directories we use
in blib/.
The blibdirs.ts target is deprecated. Depend on blibdirs instead.
=cut
sub blibdirs_target {
my $self = shift;
my @dirs = map { uc "\$(INST_$_)" } qw(libdir archlib
autodir archautodir
bin script
man1dir man3dir
);
my @exists = map { $_.'$(DFSEP).exists' } @dirs;
my $make = sprintf <<'MAKE', join(' ', @exists);
blibdirs : %s
$(NOECHO) $(NOOP)
# Backwards compat with 6.18 through 6.25
blibdirs.ts : blibdirs
$(NOECHO) $(NOOP)
MAKE
$make .= $self->dir_target(@dirs);
return $make;
}
=head3 clean (o)
Defines the clean target.
=cut
sub clean {
# --- Cleanup and Distribution Sections ---
my($self, %attribs) = @_;
my @m;
push(@m, '
# Delete temporary files but do not touch installed files. We don\'t delete
# the Makefile here so a later make realclean still has a makefile to use.
clean :: clean_subdirs
');
my @files = values %{$self->{XS}}; # .c files from *.xs files
my @dirs = qw(blib);
# Normally these are all under blib but they might have been
# redefined.
# XXX normally this would be a good idea, but the Perl core sets
# INST_LIB = ../../lib rather than actually installing the files.
# So a "make clean" in an ext/ directory would blow away lib.
# Until the core is adjusted let's leave this out.
# push @dirs, qw($(INST_ARCHLIB) $(INST_LIB)
# $(INST_BIN) $(INST_SCRIPT)
# $(INST_MAN1DIR) $(INST_MAN3DIR)
# $(INST_LIBDIR) $(INST_ARCHLIBDIR) $(INST_AUTODIR)
# $(INST_STATIC) $(INST_DYNAMIC) $(INST_BOOT)
# );
if( $attribs{FILES} ) {
# Use @dirs because we don't know what's in here.
push @dirs, ref $attribs{FILES} ?
@{$attribs{FILES}} :
split /\s+/, $attribs{FILES} ;
}
push(@files, qw[$(MAKE_APERL_FILE)
MYMETA.json MYMETA.yml perlmain.c tmon.out mon.out so_locations
blibdirs.ts pm_to_blib pm_to_blib.ts
*$(OBJ_EXT) *$(LIB_EXT) perl.exe perl perl$(EXE_EXT)
$(BOOTSTRAP) $(BASEEXT).bso
$(BASEEXT).def lib$(BASEEXT).def
$(BASEEXT).exp $(BASEEXT).x
]);
push(@files, $self->catfile('$(INST_ARCHAUTODIR)','extralibs.all'));
push(@files, $self->catfile('$(INST_ARCHAUTODIR)','extralibs.ld'));
# core files
push(@files, qw[core core.*perl.*.? *perl.core]);
push(@files, map { "core." . "[0-9]"x$_ } (1..5));
# OS specific things to clean up. Use @dirs since we don't know
# what might be in here.
push @dirs, $self->extra_clean_files;
# Occasionally files are repeated several times from different sources
{ my(%f) = map { ($_ => 1) } @files; @files = keys %f; }
{ my(%d) = map { ($_ => 1) } @dirs; @dirs = keys %d; }
push @m, map "\t$_\n", $self->split_command('- $(RM_F)', @files);
push @m, map "\t$_\n", $self->split_command('- $(RM_RF)', @dirs);
# Leave Makefile.old around for realclean
push @m, <<'MAKE';
- $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL)
MAKE
push(@m, "\t$attribs{POSTOP}\n") if $attribs{POSTOP};
join("", @m);
}
=head3 clean_subdirs_target
my $make_frag = $MM->clean_subdirs_target;
Returns the clean_subdirs target. This is used by the clean target to
call clean on any subdirectories which contain Makefiles.
=cut
sub clean_subdirs_target {
my($self) = shift;
# No subdirectories, no cleaning.
return <<'NOOP_FRAG' unless @{$self->{DIR}};
clean_subdirs :
$(NOECHO) $(NOOP)
NOOP_FRAG
my $clean = "clean_subdirs :\n";
for my $dir (@{$self->{DIR}}) {
my $subclean = $self->oneliner(sprintf <<'CODE', $dir);
chdir '%s'; system '$(MAKE) clean' if -f '$(FIRST_MAKEFILE)';
CODE
$clean .= "\t$subclean\n";
}
return $clean;
}
=head3 dir_target
my $make_frag = $mm->dir_target(@directories);
Generates targets to create the specified directories and set its
permission to PERM_DIR.
Because depending on a directory to just ensure it exists doesn't work
too well (the modified time changes too often) dir_target() creates a
.exists file in the created directory. It is this you should depend on.
For portability purposes you should use the $(DIRFILESEP) macro rather
than a '/' to seperate the directory from the file.
yourdirectory$(DIRFILESEP).exists
=cut
sub dir_target {
my($self, @dirs) = @_;
my $make = '';
foreach my $dir (@dirs) {
$make .= sprintf <<'MAKE', ($dir) x 7;
%s$(DFSEP).exists :: Makefile.PL
$(NOECHO) $(MKPATH) %s
$(NOECHO) $(CHMOD) $(PERM_DIR) %s
$(NOECHO) $(TOUCH) %s$(DFSEP).exists
MAKE
}
return $make;
}
=head3 distdir
Defines the scratch directory target that will hold the distribution
before tar-ing (or shar-ing).
=cut
# For backwards compatibility.
*dist_dir = *distdir;
sub distdir {
my($self) = shift;
my $meta_target = $self->{NO_META} ? '' : 'distmeta';
my $sign_target = !$self->{SIGN} ? '' : 'distsignature';
return sprintf <<'MAKE_FRAG', $meta_target, $sign_target;
create_distdir :
$(RM_RF) $(DISTVNAME)
$(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \
-e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');"
distdir : create_distdir %s %s
$(NOECHO) $(NOOP)
MAKE_FRAG
}
=head3 dist_test
Defines a target that produces the distribution in the
scratchdirectory, and runs 'perl Makefile.PL; make ;make test' in that
subdirectory.
=cut
sub dist_test {
my($self) = shift;
my $mpl_args = join " ", map qq["$_"], @ARGV;
my $test = $self->cd('$(DISTVNAME)',
'$(ABSPERLRUN) Makefile.PL '.$mpl_args,
'$(MAKE) $(PASTHRU)',
'$(MAKE) test $(PASTHRU)'
);
return sprintf <<'MAKE_FRAG', $test;
disttest : distdir
%s
MAKE_FRAG
}
=head3 dynamic (o)
Defines the dynamic target.
=cut
sub dynamic {
# --- Dynamic Loading Sections ---
my($self) = shift;
'
dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT)
$(NOECHO) $(NOOP)
';
}
=head3 makemakerdflt_target
my $make_frag = $mm->makemakerdflt_target
Returns a make fragment with the makemakerdeflt_target specified.
This target is the first target in the Makefile, is the default target
and simply points off to 'all' just in case any make variant gets
confused or something gets snuck in before the real 'all' target.
=cut
sub makemakerdflt_target {
return <<'MAKE_FRAG';
makemakerdflt : all
$(NOECHO) $(NOOP)
MAKE_FRAG
}
=head3 manifypods_target
my $manifypods_target = $self->manifypods_target;
Generates the manifypods target. This target generates man pages from
all POD files in MAN1PODS and MAN3PODS.
=cut
sub manifypods_target {
my($self) = shift;
my $man1pods = '';
my $man3pods = '';
my $dependencies = '';
# populate manXpods & dependencies:
foreach my $name (keys %{$self->{MAN1PODS}}, keys %{$self->{MAN3PODS}}) {
$dependencies .= " \\\n\t$name";
}
my $manify = <<END;
manifypods : pure_all $dependencies
END
my @man_cmds;
foreach my $section (qw(1 3)) {
my $pods = $self->{"MAN${section}PODS"};
push @man_cmds, $self->split_command(<<CMD, %$pods);
\$(NOECHO) \$(POD2MAN) --section=$section --perm_rw=\$(PERM_RW)
CMD
}
$manify .= "\t\$(NOECHO) \$(NOOP)\n" unless @man_cmds;
$manify .= join '', map { "$_\n" } @man_cmds;
return $manify;
}
sub _has_cpan_meta {
return eval {
require CPAN::Meta;
CPAN::Meta->VERSION(2.112150);
1;
};
}
=head3 metafile_target
my $target = $mm->metafile_target;
Generate the metafile target.
Writes the file META.yml YAML encoded meta-data about the module in
the distdir. The format follows Module::Build's as closely as
possible.
=cut
sub metafile_target {
my $self = shift;
return <<'MAKE_FRAG' if $self->{NO_META} or ! _has_cpan_meta();
metafile :
$(NOECHO) $(NOOP)
MAKE_FRAG
my %metadata = $self->metafile_data(
$self->{META_ADD} || {},
$self->{META_MERGE} || {},
);
_fix_metadata_before_conversion( \%metadata );
# paper over validation issues, but still complain, necessary because
# there's no guarantee that the above will fix ALL errors
my $meta = eval { CPAN::Meta->create( \%metadata, { lazy_validation => 1 } ) };
warn $@ if $@ and
$@ !~ /encountered CODE.*, but JSON can only represent references to arrays or hashes/;
# use the original metadata straight if the conversion failed
# or if it can't be stringified.
if( !$meta ||
!eval { $meta->as_string( { version => "1.4" } ) } ||
!eval { $meta->as_string }
)
{
$meta = bless \%metadata, 'CPAN::Meta';
}
my @write_metayml = $self->echo(
$meta->as_string({version => "1.4"}), 'META_new.yml'
);
my @write_metajson = $self->echo(
$meta->as_string(), 'META_new.json'
);
my $metayml = join("\n\t", @write_metayml);
my $metajson = join("\n\t", @write_metajson);
return sprintf <<'MAKE_FRAG', $metayml, $metajson;
metafile : create_distdir
$(NOECHO) $(ECHO) Generating META.yml
%s
-$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml
$(NOECHO) $(ECHO) Generating META.json
%s
-$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json
MAKE_FRAG
}
=begin private
=head3 _fix_metadata_before_conversion
_fix_metadata_before_conversion( \%metadata );
Fixes errors in the metadata before it's handed off to CPAN::Meta for
conversion. This hopefully results in something that can be used further
on, no guarantee is made though.
=end private
=cut
sub _fix_metadata_before_conversion {
my ( $metadata ) = @_;
# we should never be called unless this already passed but
# prefer to be defensive in case somebody else calls this
return unless _has_cpan_meta;
my $bad_version = $metadata->{version} &&
!CPAN::Meta::Validator->new->version( 'version', $metadata->{version} );
# just delete all invalid versions
if( $bad_version ) {
warn "Can't parse version '$metadata->{version}'\n";
$metadata->{version} = '';
}
my $validator = CPAN::Meta::Validator->new( $metadata );
return if $validator->is_valid;
# fix non-camelcase custom resource keys (only other trick we know)
for my $error ( $validator->errors ) {
my ( $key ) = ( $error =~ /Custom resource '(.*)' must be in CamelCase./ );
next if !$key;
# first try to remove all non-alphabetic chars
( my $new_key = $key ) =~ s/[^_a-zA-Z]//g;
# if that doesn't work, uppercase first one
$new_key = ucfirst $new_key if !$validator->custom_1( $new_key );
# copy to new key if that worked
$metadata->{resources}{$new_key} = $metadata->{resources}{$key}
if $validator->custom_1( $new_key );
# and delete old one in any case
delete $metadata->{resources}{$key};
}
return;
}
=begin private
=head3 _sort_pairs
my @pairs = _sort_pairs($sort_sub, \%hash);
Sorts the pairs of a hash based on keys ordered according
to C<$sort_sub>.
=end private
=cut
sub _sort_pairs {
my $sort = shift;
my $pairs = shift;
return map { $_ => $pairs->{$_} }
sort $sort
keys %$pairs;
}
# Taken from Module::Build::Base
sub _hash_merge {
my ($self, $h, $k, $v) = @_;
if (ref $h->{$k} eq 'ARRAY') {
push @{$h->{$k}}, ref $v ? @$v : $v;
} elsif (ref $h->{$k} eq 'HASH') {
$self->_hash_merge($h->{$k}, $_, $v->{$_}) foreach keys %$v;
} else {
$h->{$k} = $v;
}
}
=head3 metafile_data
my @metadata_pairs = $mm->metafile_data(\%meta_add, \%meta_merge);
Returns the data which MakeMaker turns into the META.yml file.
Values of %meta_add will overwrite any existing metadata in those
keys. %meta_merge will be merged with them.
=cut
sub metafile_data {
my $self = shift;
my($meta_add, $meta_merge) = @_;
my %meta = (
# required
name => $self->{DISTNAME},
version => _normalize_version($self->{VERSION}),
abstract => $self->{ABSTRACT} || 'unknown',
license => $self->{LICENSE} || 'unknown',
dynamic_config => 1,
# optional
distribution_type => $self->{PM} ? 'module' : 'script',
no_index => {
directory => [qw(t inc)]
},
generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
'meta-spec' => {
url => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
version => 1.4
},
);
# The author key is required and it takes a list.
$meta{author} = defined $self->{AUTHOR} ? $self->{AUTHOR} : [];
# Check the original args so we can tell between the user setting it
# to an empty hash and it just being initialized.
if( $self->{ARGS}{CONFIGURE_REQUIRES} ) {
$meta{configure_requires}
= _normalize_prereqs($self->{CONFIGURE_REQUIRES});
} else {
$meta{configure_requires} = {
'ExtUtils::MakeMaker' => 0,
};
}
%meta = $self->_add_requirements_to_meta( %meta );
while( my($key, $val) = each %$meta_add ) {
$meta{$key} = $val;
}
while( my($key, $val) = each %$meta_merge ) {
$self->_hash_merge(\%meta, $key, $val);
}
return %meta;
}
=begin private
=cut
sub _add_requirements_to_meta {
my ( $self, %meta ) = @_;
# Check the original args so we can tell between the user setting it
# to an empty hash and it just being initialized.
if( $self->{ARGS}{BUILD_REQUIRES} ) {
$meta{build_requires} = _normalize_prereqs($self->{BUILD_REQUIRES});
} else {
$meta{build_requires} = {
'ExtUtils::MakeMaker' => 0,
};
}
$meta{requires} = _normalize_prereqs($self->{PREREQ_PM})
if defined $self->{PREREQ_PM};
$meta{requires}{perl} = _normalize_version($self->{MIN_PERL_VERSION})
if $self->{MIN_PERL_VERSION};
return %meta;
}
sub _normalize_prereqs {
my ($hash) = @_;
my %prereqs;
while ( my ($k,$v) = each %$hash ) {
$prereqs{$k} = _normalize_version($v);
}
return \%prereqs;
}
# Adapted from Module::Build::Base
sub _normalize_version {
my ($version) = @_;
$version = 0 unless defined $version;
if ( ref $version eq 'version' ) { # version objects
$version = $version->is_qv ? $version->normal : $version->stringify;
}
elsif ( $version =~ /^[^v][^.]*\.[^.]+\./ ) { # no leading v, multiple dots
# normalize string tuples without "v": "1.2.3" -> "v1.2.3"
$version = "v$version";
}
else {
# leave alone
}
return $version;
}
=head3 _dump_hash
$yaml = _dump_hash(\%options, %hash);
Implements a fake YAML dumper for a hash given
as a list of pairs. No quoting/escaping is done. Keys
are supposed to be strings. Values are undef, strings,
hash refs or array refs of strings.
Supported options are:
delta => STR - indentation delta
use_header => BOOL - whether to include a YAML header
indent => STR - a string of spaces
default: ''
max_key_length => INT - maximum key length used to align
keys and values of the same hash
default: 20
key_sort => CODE - a sort sub
It may be undef, which means no sorting by keys
default: sub { lc $a cmp lc $b }
customs => HASH - special options for certain keys
(whose values are hashes themselves)
may contain: max_key_length, key_sort, customs
=end private
=cut
sub _dump_hash {
croak "first argument should be a hash ref" unless ref $_[0] eq 'HASH';
my $options = shift;
my %hash = @_;
# Use a list to preserve order.
my @pairs;
my $k_sort
= exists $options->{key_sort} ? $options->{key_sort}
: sub { lc $a cmp lc $b };
if ($k_sort) {
croak "'key_sort' should be a coderef" unless ref $k_sort eq 'CODE';
@pairs = _sort_pairs($k_sort, \%hash);
} else { # list of pairs, no sorting
@pairs = @_;
}
my $yaml = $options->{use_header} ? "--- #YAML:1.0\n" : '';
my $indent = $options->{indent} || '';
my $k_length = min(
($options->{max_key_length} || 20),
max(map { length($_) + 1 } grep { !ref $hash{$_} } keys %hash)
);
my $customs = $options->{customs} || {};
# printf format for key
my $k_format = "%-${k_length}s";
while( @pairs ) {
my($key, $val) = splice @pairs, 0, 2;
$val = '~' unless defined $val;
if(ref $val eq 'HASH') {
if ( keys %$val ) {
my %k_options = ( # options for recursive call
delta => $options->{delta},
use_header => 0,
indent => $indent . $options->{delta},
);
if (exists $customs->{$key}) {
my %k_custom = %{$customs->{$key}};
foreach my $k (qw(key_sort max_key_length customs)) {
$k_options{$k} = $k_custom{$k} if exists $k_custom{$k};
}
}
$yaml .= $indent . "$key:\n"
. _dump_hash(\%k_options, %$val);
}
else {
$yaml .= $indent . "$key: {}\n";
}
}
elsif (ref $val eq 'ARRAY') {
if( @$val ) {
$yaml .= $indent . "$key:\n";
for (@$val) {
croak "only nested arrays of non-refs are supported" if ref $_;
$yaml .= $indent . $options->{delta} . "- $_\n";
}
}
else {
$yaml .= $indent . "$key: []\n";
}
}
elsif( ref $val and !blessed($val) ) {
croak "only nested hashes, arrays and objects are supported";
}
else { # if it's an object, just stringify it
$yaml .= $indent . sprintf "$k_format %s\n", "$key:", $val;
}
};
return $yaml;
}
sub blessed {
return eval { $_[0]->isa("UNIVERSAL"); };
}
sub max {
return (sort { $b <=> $a } @_)[0];
}
sub min {
return (sort { $a <=> $b } @_)[0];
}
=head3 metafile_file
my $meta_yml = $mm->metafile_file(@metadata_pairs);
Turns the @metadata_pairs into YAML.
This method does not implement a complete YAML dumper, being limited
to dump a hash with values which are strings, undef's or nested hashes
and arrays of strings. No quoting/escaping is done.
=cut
sub metafile_file {
my $self = shift;
my %dump_options = (
use_header => 1,
delta => ' ' x 4,
key_sort => undef,
);
return _dump_hash(\%dump_options, @_);
}
=head3 distmeta_target
my $make_frag = $mm->distmeta_target;
Generates the distmeta target to add META.yml to the MANIFEST in the
distdir.
=cut
sub distmeta_target {
my $self = shift;
my @add_meta = (
$self->oneliner(<<'CODE', ['-MExtUtils::Manifest=maniadd']),
exit unless -e q{META.yml};
eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) }
or print "Could not add META.yml to MANIFEST: $${'@'}\n"
CODE
$self->oneliner(<<'CODE', ['-MExtUtils::Manifest=maniadd'])
exit unless -f q{META.json};
eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) }
or print "Could not add META.json to MANIFEST: $${'@'}\n"
CODE
);
my @add_meta_to_distdir = map { $self->cd('$(DISTVNAME)', $_) } @add_meta;
return sprintf <<'MAKE', @add_meta_to_distdir;
distmeta : create_distdir metafile
$(NOECHO) %s
$(NOECHO) %s
MAKE
}
=head3 mymeta
my $mymeta = $mm->mymeta;
Generate MYMETA information as a hash either from an existing META.yml
or from internal data.
=cut
sub mymeta {
my $self = shift;
my $file = shift || ''; # for testing
my $mymeta = $self->_mymeta_from_meta($file);
unless ( $mymeta ) {
my @metadata = $self->metafile_data(
$self->{META_ADD} || {},
$self->{META_MERGE} || {},
);
$mymeta = {@metadata};
}
# Overwrite the non-configure dependency hashes
$mymeta = { $self->_add_requirements_to_meta( %$mymeta ) };
$mymeta->{dynamic_config} = 0;
return $mymeta;
}
sub _mymeta_from_meta {
my $self = shift;
my $metafile = shift || ''; # for testing
return unless _has_cpan_meta();
my $meta;
for my $file ( $metafile, "META.json", "META.yml" ) {
next unless -e $file;
eval {
$meta = CPAN::Meta->load_file($file)->as_struct( {version => "1.4"} );
};
last if $meta;
}
return undef unless $meta;
# META.yml before 6.25_01 cannot be trusted. META.yml lived in the source directory.
# There was a good chance the author accidentally uploaded a stale META.yml if they
# rolled their own tarball rather than using "make dist".
if ($meta->{generated_by} &&
$meta->{generated_by} =~ /ExtUtils::MakeMaker version ([\d\._]+)/) {
my $eummv = do { local $^W = 0; $1+0; };
if ($eummv < 6.2501) {
return undef;
}
}
return $meta;
}
=head3 write_mymeta
$self->write_mymeta( $mymeta );
Write MYMETA information to MYMETA.yml.
This will probably be refactored into a more generic YAML dumping method.
=cut
sub write_mymeta {
my $self = shift;
my $mymeta = shift;
return unless _has_cpan_meta();
_fix_metadata_before_conversion( $mymeta );
# this can still blow up
# not sure if i should just eval this and skip file creation if it
# blows up
my $meta_obj = CPAN::Meta->new( $mymeta, { lazy_validation => 1 } );
$meta_obj->save( 'MYMETA.json' );
$meta_obj->save( 'MYMETA.yml', { version => "1.4" } );
return 1;
}
=head3 realclean (o)
Defines the realclean target.
=cut
sub realclean {
my($self, %attribs) = @_;
my @dirs = qw($(DISTVNAME));
my @files = qw($(FIRST_MAKEFILE) $(MAKEFILE_OLD));
# Special exception for the perl core where INST_* is not in blib.
# This cleans up the files built from the ext/ directory (all XS).
if( $self->{PERL_CORE} ) {
push @dirs, qw($(INST_AUTODIR) $(INST_ARCHAUTODIR));
push @files, values %{$self->{PM}};
}
if( $self->has_link_code ){
push @files, qw($(OBJECT));
}
if( $attribs{FILES} ) {
if( ref $attribs{FILES} ) {
push @dirs, @{ $attribs{FILES} };
}
else {
push @dirs, split /\s+/, $attribs{FILES};
}
}
# Occasionally files are repeated several times from different sources
{ my(%f) = map { ($_ => 1) } @files; @files = keys %f; }
{ my(%d) = map { ($_ => 1) } @dirs; @dirs = keys %d; }
my $rm_cmd = join "\n\t", map { "$_" }
$self->split_command('- $(RM_F)', @files);
my $rmf_cmd = join "\n\t", map { "$_" }
$self->split_command('- $(RM_RF)', @dirs);
my $m = sprintf <<'MAKE', $rm_cmd, $rmf_cmd;
# Delete temporary files (via clean) and also delete dist files
realclean purge :: clean realclean_subdirs
%s
%s
MAKE
$m .= "\t$attribs{POSTOP}\n" if $attribs{POSTOP};
return $m;
}
=head3 realclean_subdirs_target
my $make_frag = $MM->realclean_subdirs_target;
Returns the realclean_subdirs target. This is used by the realclean
target to call realclean on any subdirectories which contain Makefiles.
=cut
sub realclean_subdirs_target {
my $self = shift;
return <<'NOOP_FRAG' unless @{$self->{DIR}};
realclean_subdirs :
$(NOECHO) $(NOOP)
NOOP_FRAG
my $rclean = "realclean_subdirs :\n";
foreach my $dir (@{$self->{DIR}}) {
foreach my $makefile ('$(MAKEFILE_OLD)', '$(FIRST_MAKEFILE)' ) {
my $subrclean .= $self->oneliner(sprintf <<'CODE', $dir, ($makefile) x 2);
chdir '%s'; system '$(MAKE) $(USEMAKEFILE) %s realclean' if -f '%s';
CODE
$rclean .= sprintf <<'RCLEAN', $subrclean;
- %s
RCLEAN
}
}
return $rclean;
}
=head3 signature_target
my $target = $mm->signature_target;
Generate the signature target.
Writes the file SIGNATURE with "cpansign -s".
=cut
sub signature_target {
my $self = shift;
return <<'MAKE_FRAG';
signature :
cpansign -s
MAKE_FRAG
}
=head3 distsignature_target
my $make_frag = $mm->distsignature_target;
Generates the distsignature target to add SIGNATURE to the MANIFEST in the
distdir.
=cut
sub distsignature_target {
my $self = shift;
my $add_sign = $self->oneliner(<<'CODE', ['-MExtUtils::Manifest=maniadd']);
eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) }
or print "Could not add SIGNATURE to MANIFEST: $${'@'}\n"
CODE
my $sign_dist = $self->cd('$(DISTVNAME)' => 'cpansign -s');
# cpansign -s complains if SIGNATURE is in the MANIFEST yet does not
# exist
my $touch_sig = $self->cd('$(DISTVNAME)' => '$(TOUCH) SIGNATURE');
my $add_sign_to_dist = $self->cd('$(DISTVNAME)' => $add_sign );
return sprintf <<'MAKE', $add_sign_to_dist, $touch_sig, $sign_dist
distsignature : create_distdir
$(NOECHO) %s
$(NOECHO) %s
%s
MAKE
}
=head3 special_targets
my $make_frag = $mm->special_targets
Returns a make fragment containing any targets which have special
meaning to make. For example, .SUFFIXES and .PHONY.
=cut
sub special_targets {
my $make_frag = <<'MAKE_FRAG';
.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT)
.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir
MAKE_FRAG
$make_frag .= <<'MAKE_FRAG' if $ENV{CLEARCASE_ROOT};
.NO_CONFIG_REC: Makefile
MAKE_FRAG
return $make_frag;
}
=head2 Init methods
Methods which help initialize the MakeMaker object and macros.
=head3 init_ABSTRACT
$mm->init_ABSTRACT
=cut
sub init_ABSTRACT {
my $self = shift;
if( $self->{ABSTRACT_FROM} and $self->{ABSTRACT} ) {
warn "Both ABSTRACT_FROM and ABSTRACT are set. ".
"Ignoring ABSTRACT_FROM.\n";
return;
}
if ($self->{ABSTRACT_FROM}){
$self->{ABSTRACT} = $self->parse_abstract($self->{ABSTRACT_FROM}) or
carp "WARNING: Setting ABSTRACT via file ".
"'$self->{ABSTRACT_FROM}' failed\n";
}
}
=head3 init_INST
$mm->init_INST;
Called by init_main. Sets up all INST_* variables except those related
to XS code. Those are handled in init_xs.
=cut
sub init_INST {
my($self) = shift;
$self->{INST_ARCHLIB} ||= $self->catdir($Curdir,"blib","arch");
$self->{INST_BIN} ||= $self->catdir($Curdir,'blib','bin');
# INST_LIB typically pre-set if building an extension after
# perl has been built and installed. Setting INST_LIB allows
# you to build directly into, say $Config{privlibexp}.
unless ($self->{INST_LIB}){
if ($self->{PERL_CORE}) {
if (defined $Cross::platform) {
$self->{INST_LIB} = $self->{INST_ARCHLIB} =
$self->catdir($self->{PERL_LIB},"..","xlib",
$Cross::platform);
}
else {
$self->{INST_LIB} = $self->{INST_ARCHLIB} = $self->{PERL_LIB};
}
} else {
$self->{INST_LIB} = $self->catdir($Curdir,"blib","lib");
}
}
my @parentdir = split(/::/, $self->{PARENT_NAME});
$self->{INST_LIBDIR} = $self->catdir('$(INST_LIB)', @parentdir);
$self->{INST_ARCHLIBDIR} = $self->catdir('$(INST_ARCHLIB)', @parentdir);
$self->{INST_AUTODIR} = $self->catdir('$(INST_LIB)', 'auto',
'$(FULLEXT)');
$self->{INST_ARCHAUTODIR} = $self->catdir('$(INST_ARCHLIB)', 'auto',
'$(FULLEXT)');
$self->{INST_SCRIPT} ||= $self->catdir($Curdir,'blib','script');
$self->{INST_MAN1DIR} ||= $self->catdir($Curdir,'blib','man1');
$self->{INST_MAN3DIR} ||= $self->catdir($Curdir,'blib','man3');
return 1;
}
=head3 init_INSTALL
$mm->init_INSTALL;
Called by init_main. Sets up all INSTALL_* variables (except
INSTALLDIRS) and *PREFIX.
=cut
sub init_INSTALL {
my($self) = shift;
if( $self->{ARGS}{INSTALL_BASE} and $self->{ARGS}{PREFIX} ) {
die "Only one of PREFIX or INSTALL_BASE can be given. Not both.\n";
}
if( $self->{ARGS}{INSTALL_BASE} ) {
$self->init_INSTALL_from_INSTALL_BASE;
}
else {
$self->init_INSTALL_from_PREFIX;
}
}
=head3 init_INSTALL_from_PREFIX
$mm->init_INSTALL_from_PREFIX;
=cut
sub init_INSTALL_from_PREFIX {
my $self = shift;
$self->init_lib2arch;
# There are often no Config.pm defaults for these new man variables so
# we fall back to the old behavior which is to use installman*dir
foreach my $num (1, 3) {
my $k = 'installsiteman'.$num.'dir';
$self->{uc $k} ||= uc "\$(installman${num}dir)"
unless $Config{$k};
}
foreach my $num (1, 3) {
my $k = 'installvendorman'.$num.'dir';
unless( $Config{$k} ) {
$self->{uc $k} ||= $Config{usevendorprefix}
? uc "\$(installman${num}dir)"
: '';
}
}
$self->{INSTALLSITEBIN} ||= '$(INSTALLBIN)'
unless $Config{installsitebin};
$self->{INSTALLSITESCRIPT} ||= '$(INSTALLSCRIPT)'
unless $Config{installsitescript};
unless( $Config{installvendorbin} ) {
$self->{INSTALLVENDORBIN} ||= $Config{usevendorprefix}
? $Config{installbin}
: '';
}
unless( $Config{installvendorscript} ) {
$self->{INSTALLVENDORSCRIPT} ||= $Config{usevendorprefix}
? $Config{installscript}
: '';
}
my $iprefix = $Config{installprefixexp} || $Config{installprefix} ||
$Config{prefixexp} || $Config{prefix} || '';
my $vprefix = $Config{usevendorprefix} ? $Config{vendorprefixexp} : '';
my $sprefix = $Config{siteprefixexp} || '';
# 5.005_03 doesn't have a siteprefix.
$sprefix = $iprefix unless $sprefix;
$self->{PREFIX} ||= '';
if( $self->{PREFIX} ) {
@{$self}{qw(PERLPREFIX SITEPREFIX VENDORPREFIX)} =
('$(PREFIX)') x 3;
}
else {
$self->{PERLPREFIX} ||= $iprefix;
$self->{SITEPREFIX} ||= $sprefix;
$self->{VENDORPREFIX} ||= $vprefix;
# Lots of MM extension authors like to use $(PREFIX) so we
# put something sensible in there no matter what.
$self->{PREFIX} = '$('.uc $self->{INSTALLDIRS}.'PREFIX)';
}
my $arch = $Config{archname};
my $version = $Config{version};
# default style
my $libstyle = $Config{installstyle} || 'lib/perl5';
my $manstyle = '';
if( $self->{LIBSTYLE} ) {
$libstyle = $self->{LIBSTYLE};
$manstyle = $self->{LIBSTYLE} eq 'lib/perl5' ? 'lib/perl5' : '';
}
# Some systems, like VOS, set installman*dir to '' if they can't
# read man pages.
for my $num (1, 3) {
$self->{'INSTALLMAN'.$num.'DIR'} ||= 'none'
unless $Config{'installman'.$num.'dir'};
}
my %bin_layouts =
(
bin => { s => $iprefix,
t => 'perl',
d => 'bin' },
vendorbin => { s => $vprefix,
t => 'vendor',
d => 'bin' },
sitebin => { s => $sprefix,
t => 'site',
d => 'bin' },
script => { s => $iprefix,
t => 'perl',
d => 'bin' },
vendorscript=> { s => $vprefix,
t => 'vendor',
d => 'bin' },
sitescript => { s => $sprefix,
t => 'site',
d => 'bin' },
);
my %man_layouts =
(
man1dir => { s => $iprefix,
t => 'perl',
d => 'man/man1',
style => $manstyle, },
siteman1dir => { s => $sprefix,
t => 'site',
d => 'man/man1',
style => $manstyle, },
vendorman1dir => { s => $vprefix,
t => 'vendor',
d => 'man/man1',
style => $manstyle, },
man3dir => { s => $iprefix,
t => 'perl',
d => 'man/man3',
style => $manstyle, },
siteman3dir => { s => $sprefix,
t => 'site',
d => 'man/man3',
style => $manstyle, },
vendorman3dir => { s => $vprefix,
t => 'vendor',
d => 'man/man3',
style => $manstyle, },
);
my %lib_layouts =
(
privlib => { s => $iprefix,
t => 'perl',
d => '',
style => $libstyle, },
vendorlib => { s => $vprefix,
t => 'vendor',
d => '',
style => $libstyle, },
sitelib => { s => $sprefix,
t => 'site',
d => 'site_perl',
style => $libstyle, },
archlib => { s => $iprefix,
t => 'perl',
d => "$version/$arch",
style => $libstyle },
vendorarch => { s => $vprefix,
t => 'vendor',
d => "$version/$arch",
style => $libstyle },
sitearch => { s => $sprefix,
t => 'site',
d => "site_perl/$version/$arch",
style => $libstyle },
);
# Special case for LIB.
if( $self->{LIB} ) {
foreach my $var (keys %lib_layouts) {
my $Installvar = uc "install$var";
if( $var =~ /arch/ ) {
$self->{$Installvar} ||=
$self->catdir($self->{LIB}, $Config{archname});
}
else {
$self->{$Installvar} ||= $self->{LIB};
}
}
}
my %type2prefix = ( perl => 'PERLPREFIX',
site => 'SITEPREFIX',
vendor => 'VENDORPREFIX'
);
my %layouts = (%bin_layouts, %man_layouts, %lib_layouts);
while( my($var, $layout) = each(%layouts) ) {
my($s, $t, $d, $style) = @{$layout}{qw(s t d style)};
my $r = '$('.$type2prefix{$t}.')';
print STDERR "Prefixing $var\n" if $Verbose >= 2;
my $installvar = "install$var";
my $Installvar = uc $installvar;
next if $self->{$Installvar};
$d = "$style/$d" if $style;
$self->prefixify($installvar, $s, $r, $d);
print STDERR " $Installvar == $self->{$Installvar}\n"
if $Verbose >= 2;
}
# Generate these if they weren't figured out.
$self->{VENDORARCHEXP} ||= $self->{INSTALLVENDORARCH};
$self->{VENDORLIBEXP} ||= $self->{INSTALLVENDORLIB};
return 1;
}
=head3 init_from_INSTALL_BASE
$mm->init_from_INSTALL_BASE
=cut
my %map = (
lib => [qw(lib perl5)],
arch => [('lib', 'perl5', $Config{archname})],
bin => [qw(bin)],
man1dir => [qw(man man1)],
man3dir => [qw(man man3)]
);
$map{script} = $map{bin};
sub init_INSTALL_from_INSTALL_BASE {
my $self = shift;
@{$self}{qw(PREFIX VENDORPREFIX SITEPREFIX PERLPREFIX)} =
'$(INSTALL_BASE)';
my %install;
foreach my $thing (keys %map) {
foreach my $dir (('', 'SITE', 'VENDOR')) {
my $uc_thing = uc $thing;
my $key = "INSTALL".$dir.$uc_thing;
$install{$key} ||=
$self->catdir('$(INSTALL_BASE)', @{$map{$thing}});
}
}
# Adjust for variable quirks.
$install{INSTALLARCHLIB} ||= delete $install{INSTALLARCH};
$install{INSTALLPRIVLIB} ||= delete $install{INSTALLLIB};
foreach my $key (keys %install) {
$self->{$key} ||= $install{$key};
}
return 1;
}
=head3 init_VERSION I<Abstract>
$mm->init_VERSION
Initialize macros representing versions of MakeMaker and other tools
MAKEMAKER: path to the MakeMaker module.
MM_VERSION: ExtUtils::MakeMaker Version
MM_REVISION: ExtUtils::MakeMaker version control revision (for backwards
compat)
VERSION: version of your module
VERSION_MACRO: which macro represents the version (usually 'VERSION')
VERSION_SYM: like version but safe for use as an RCS revision number
DEFINE_VERSION: -D line to set the module version when compiling
XS_VERSION: version in your .xs file. Defaults to $(VERSION)
XS_VERSION_MACRO: which macro represents the XS version.
XS_DEFINE_VERSION: -D line to set the xs version when compiling.
Called by init_main.
=cut
sub init_VERSION {
my($self) = shift;
$self->{MAKEMAKER} = $ExtUtils::MakeMaker::Filename;
$self->{MM_VERSION} = $ExtUtils::MakeMaker::VERSION;
$self->{MM_REVISION}= $ExtUtils::MakeMaker::Revision;
$self->{VERSION_FROM} ||= '';
if ($self->{VERSION_FROM}){
$self->{VERSION} = $self->parse_version($self->{VERSION_FROM});
if( $self->{VERSION} eq 'undef' ) {
carp("WARNING: Setting VERSION via file ".
"'$self->{VERSION_FROM}' failed\n");
}
}
# strip blanks
if (defined $self->{VERSION}) {
$self->{VERSION} =~ s/^\s+//;
$self->{VERSION} =~ s/\s+$//;
}
else {
$self->{VERSION} = '';
}
$self->{VERSION_MACRO} = 'VERSION';
($self->{VERSION_SYM} = $self->{VERSION}) =~ s/\W/_/g;
$self->{DEFINE_VERSION} = '-D$(VERSION_MACRO)=\"$(VERSION)\"';
# Graham Barr and Paul Marquess had some ideas how to ensure
# version compatibility between the *.pm file and the
# corresponding *.xs file. The bottomline was, that we need an
# XS_VERSION macro that defaults to VERSION:
$self->{XS_VERSION} ||= $self->{VERSION};
$self->{XS_VERSION_MACRO} = 'XS_VERSION';
$self->{XS_DEFINE_VERSION} = '-D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\"';
}
=head3 init_others
$MM->init_others();
Initializes the macro definitions used by tools_other() and places them
in the $MM object.
If there is no description, its the same as the parameter to
WriteMakefile() documented in ExtUtils::MakeMaker.
Defines at least these macros.
Macro Description
NOOP Do nothing
NOECHO Tell make not to display the command itself
MAKEFILE
FIRST_MAKEFILE
MAKEFILE_OLD
MAKE_APERL_FILE File used by MAKE_APERL
SHELL Program used to run shell commands
ECHO Print text adding a newline on the end
RM_F Remove a file
RM_RF Remove a directory
TOUCH Update a file's timestamp
TEST_F Test for a file's existence
CP Copy a file
MV Move a file
CHMOD Change permissions on a file
FALSE Exit with non-zero
TRUE Exit with zero
UMASK_NULL Nullify umask
DEV_NULL Suppress all command output
=cut
sub init_others {
my $self = shift;
$self->{ECHO} ||= $self->oneliner('print qq{@ARGV}', ['-l']);
$self->{ECHO_N} ||= $self->oneliner('print qq{@ARGV}');
$self->{TOUCH} ||= $self->oneliner('touch', ["-MExtUtils::Command"]);
$self->{CHMOD} ||= $self->oneliner('chmod', ["-MExtUtils::Command"]);
$self->{RM_F} ||= $self->oneliner('rm_f', ["-MExtUtils::Command"]);
$self->{RM_RF} ||= $self->oneliner('rm_rf', ["-MExtUtils::Command"]);
$self->{TEST_F} ||= $self->oneliner('test_f', ["-MExtUtils::Command"]);
$self->{FALSE} ||= $self->oneliner('exit 1');
$self->{TRUE} ||= $self->oneliner('exit 0');
$self->{MKPATH} ||= $self->oneliner('mkpath', ["-MExtUtils::Command"]);
$self->{CP} ||= $self->oneliner('cp', ["-MExtUtils::Command"]);
$self->{MV} ||= $self->oneliner('mv', ["-MExtUtils::Command"]);
$self->{MOD_INSTALL} ||=
$self->oneliner(<<'CODE', ['-MExtUtils::Install']);
install([ from_to => {@ARGV}, verbose => '$(VERBINST)', uninstall_shadows => '$(UNINST)', dir_mode => '$(PERM_DIR)' ]);
CODE
$self->{DOC_INSTALL} ||= $self->oneliner('perllocal_install', ["-MExtUtils::Command::MM"]);
$self->{UNINSTALL} ||= $self->oneliner('uninstall', ["-MExtUtils::Command::MM"]);
$self->{WARN_IF_OLD_PACKLIST} ||=
$self->oneliner('warn_if_old_packlist', ["-MExtUtils::Command::MM"]);
$self->{FIXIN} ||= $self->oneliner('MY->fixin(shift)', ["-MExtUtils::MY"]);
$self->{EQUALIZE_TIMESTAMP} ||= $self->oneliner('eqtime', ["-MExtUtils::Command"]);
$self->{UNINST} ||= 0;
$self->{VERBINST} ||= 0;
$self->{FIRST_MAKEFILE} ||= $self->{MAKEFILE} || 'Makefile';
$self->{MAKEFILE} ||= $self->{FIRST_MAKEFILE};
$self->{MAKEFILE_OLD} ||= $self->{MAKEFILE}.'.old';
$self->{MAKE_APERL_FILE} ||= $self->{MAKEFILE}.'.aperl';
# Not everybody uses -f to indicate "use this Makefile instead"
$self->{USEMAKEFILE} ||= '-f';
# Some makes require a wrapper around macros passed in on the command
# line.
$self->{MACROSTART} ||= '';
$self->{MACROEND} ||= '';
$self->{SHELL} ||= $Config{sh};
# UMASK_NULL is not used by MakeMaker but some CPAN modules
# make use of it.
$self->{UMASK_NULL} ||= "umask 0";
# Not the greatest default, but its something.
$self->{DEV_NULL} ||= "> /dev/null 2>&1";
$self->{NOOP} ||= '$(TRUE)';
$self->{NOECHO} = '@' unless defined $self->{NOECHO};
$self->{LD_RUN_PATH} = "";
$self->{LIBS} = $self->_fix_libs($self->{LIBS});
# Compute EXTRALIBS, BSLOADLIBS and LDLOADLIBS from $self->{LIBS}
foreach my $libs ( @{$self->{LIBS}} ){
$libs =~ s/^\s*(.*\S)\s*$/$1/; # remove leading and trailing whitespace
my(@libs) = $self->extliblist($libs);
if ($libs[0] or $libs[1] or $libs[2]){
# LD_RUN_PATH now computed by ExtUtils::Liblist
($self->{EXTRALIBS}, $self->{BSLOADLIBS},
$self->{LDLOADLIBS}, $self->{LD_RUN_PATH}) = @libs;
last;
}
}
if ( $self->{OBJECT} ) {
$self->{OBJECT} =~ s!\.o(bj)?\b!\$(OBJ_EXT)!g;
} else {
# init_dirscan should have found out, if we have C files
$self->{OBJECT} = "";
$self->{OBJECT} = '$(BASEEXT)$(OBJ_EXT)' if @{$self->{C}||[]};
}
$self->{OBJECT} =~ s/\n+/ \\\n\t/g;
$self->{BOOTDEP} = (-f "$self->{BASEEXT}_BS") ? "$self->{BASEEXT}_BS" : "";
$self->{PERLMAINCC} ||= '$(CC)';
$self->{LDFROM} = '$(OBJECT)' unless $self->{LDFROM};
# Sanity check: don't define LINKTYPE = dynamic if we're skipping
# the 'dynamic' section of MM. We don't have this problem with
# 'static', since we either must use it (%Config says we can't
# use dynamic loading) or the caller asked for it explicitly.
if (!$self->{LINKTYPE}) {
$self->{LINKTYPE} = $self->{SKIPHASH}{'dynamic'}
? 'static'
: ($Config{usedl} ? 'dynamic' : 'static');
}
return 1;
}
# Lets look at $self->{LIBS} carefully: It may be an anon array, a string or
# undefined. In any case we turn it into an anon array
sub _fix_libs {
my($self, $libs) = @_;
return !defined $libs ? [''] :
!ref $libs ? [$libs] :
!defined $libs->[0] ? [''] :
$libs ;
}
=head3 tools_other
my $make_frag = $MM->tools_other;
Returns a make fragment containing definitions for the macros init_others()
initializes.
=cut
sub tools_other {
my($self) = shift;
my @m;
# We set PM_FILTER as late as possible so it can see all the earlier
# on macro-order sensitive makes such as nmake.
for my $tool (qw{ SHELL CHMOD CP MV NOOP NOECHO RM_F RM_RF TEST_F TOUCH
UMASK_NULL DEV_NULL MKPATH EQUALIZE_TIMESTAMP
FALSE TRUE
ECHO ECHO_N
UNINST VERBINST
MOD_INSTALL DOC_INSTALL UNINSTALL
WARN_IF_OLD_PACKLIST
MACROSTART MACROEND
USEMAKEFILE
PM_FILTER
FIXIN
} )
{
next unless defined $self->{$tool};
push @m, "$tool = $self->{$tool}\n";
}
return join "", @m;
}
=head3 init_DIRFILESEP I<Abstract>
$MM->init_DIRFILESEP;
my $dirfilesep = $MM->{DIRFILESEP};
Initializes the DIRFILESEP macro which is the seperator between the
directory and filename in a filepath. ie. / on Unix, \ on Win32 and
nothing on VMS.
For example:
# instead of $(INST_ARCHAUTODIR)/extralibs.ld
$(INST_ARCHAUTODIR)$(DIRFILESEP)extralibs.ld
Something of a hack but it prevents a lot of code duplication between
MM_* variants.
Do not use this as a seperator between directories. Some operating
systems use different seperators between subdirectories as between
directories and filenames (for example: VOLUME:[dir1.dir2]file on VMS).
=head3 init_linker I<Abstract>
$mm->init_linker;
Initialize macros which have to do with linking.
PERL_ARCHIVE: path to libperl.a equivalent to be linked to dynamic
extensions.
PERL_ARCHIVE_AFTER: path to a library which should be put on the
linker command line I<after> the external libraries to be linked to
dynamic extensions. This may be needed if the linker is one-pass, and
Perl includes some overrides for C RTL functions, such as malloc().
EXPORT_LIST: name of a file that is passed to linker to define symbols
to be exported.
Some OSes do not need these in which case leave it blank.
=head3 init_platform
$mm->init_platform
Initialize any macros which are for platform specific use only.
A typical one is the version number of your OS specific mocule.
(ie. MM_Unix_VERSION or MM_VMS_VERSION).
=cut
sub init_platform {
return '';
}
=head3 init_MAKE
$mm->init_MAKE
Initialize MAKE from either a MAKE environment variable or $Config{make}.
=cut
sub init_MAKE {
my $self = shift;
$self->{MAKE} ||= $ENV{MAKE} || $Config{make};
}
=head2 Tools
A grab bag of methods to generate specific macros and commands.
=head3 manifypods
Defines targets and routines to translate the pods into manpages and
put them into the INST_* directories.
=cut
sub manifypods {
my $self = shift;
my $POD2MAN_macro = $self->POD2MAN_macro();
my $manifypods_target = $self->manifypods_target();
return <<END_OF_TARGET;
$POD2MAN_macro
$manifypods_target
END_OF_TARGET
}
=head3 POD2MAN_macro
my $pod2man_macro = $self->POD2MAN_macro
Returns a definition for the POD2MAN macro. This is a program
which emulates the pod2man utility. You can add more switches to the
command by simply appending them on the macro.
Typical usage:
$(POD2MAN) --section=3 --perm_rw=$(PERM_RW) podfile1 man_page1 ...
=cut
sub POD2MAN_macro {
my $self = shift;
# Need the trailing '--' so perl stops gobbling arguments and - happens
# to be an alternative end of line seperator on VMS so we quote it
return <<'END_OF_DEF';
POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--"
POD2MAN = $(POD2MAN_EXE)
END_OF_DEF
}
=head3 test_via_harness
my $command = $mm->test_via_harness($perl, $tests);
Returns a $command line which runs the given set of $tests with
Test::Harness and the given $perl.
Used on the t/*.t files.
=cut
sub test_via_harness {
my($self, $perl, $tests) = @_;
return qq{\t$perl "-MExtUtils::Command::MM" }.
qq{"-e" "test_harness(\$(TEST_VERBOSE), '\$(INST_LIB)', '\$(INST_ARCHLIB)')" $tests\n};
}
=head3 test_via_script
my $command = $mm->test_via_script($perl, $script);
Returns a $command line which just runs a single test without
Test::Harness. No checks are done on the results, they're just
printed.
Used for test.pl, since they don't always follow Test::Harness
formatting.
=cut
sub test_via_script {
my($self, $perl, $script) = @_;
return qq{\t$perl "-I\$(INST_LIB)" "-I\$(INST_ARCHLIB)" $script\n};
}
=head3 tool_autosplit
Defines a simple perl call that runs autosplit. May be deprecated by
pm_to_blib soon.
=cut
sub tool_autosplit {
my($self, %attribs) = @_;
my $maxlen = $attribs{MAXLEN} ? '$$AutoSplit::Maxlen=$attribs{MAXLEN};'
: '';
my $asplit = $self->oneliner(sprintf <<'PERL_CODE', $maxlen);
use AutoSplit; %s autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1)
PERL_CODE
return sprintf <<'MAKE_FRAG', $asplit;
# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
AUTOSPLITFILE = %s
MAKE_FRAG
}
=head3 arch_check
my $arch_ok = $mm->arch_check(
$INC{"Config.pm"},
File::Spec->catfile($Config{archlibexp}, "Config.pm")
);
A sanity check that what Perl thinks the architecture is and what
Config thinks the architecture is are the same. If they're not it
will return false and show a diagnostic message.
When building Perl it will always return true, as nothing is installed
yet.
The interface is a bit odd because this is the result of a
quick refactoring. Don't rely on it.
=cut
sub arch_check {
my $self = shift;
my($pconfig, $cconfig) = @_;
return 1 if $self->{PERL_SRC};
my($pvol, $pthinks) = $self->splitpath($pconfig);
my($cvol, $cthinks) = $self->splitpath($cconfig);
$pthinks = $self->canonpath($pthinks);
$cthinks = $self->canonpath($cthinks);
my $ret = 1;
if ($pthinks ne $cthinks) {
print "Have $pthinks\n";
print "Want $cthinks\n";
$ret = 0;
my $arch = (grep length, $self->splitdir($pthinks))[-1];
print STDOUT <<END unless $self->{UNINSTALLED_PERL};
Your perl and your Config.pm seem to have different ideas about the
architecture they are running on.
Perl thinks: [$arch]
Config says: [$Config{archname}]
This may or may not cause problems. Please check your installation of perl
if you have problems building this extension.
END
}
return $ret;
}
=head2 File::Spec wrappers
ExtUtils::MM_Any is a subclass of File::Spec. The methods noted here
override File::Spec.
=head3 catfile
File::Spec <= 0.83 has a bug where the file part of catfile is not
canonicalized. This override fixes that bug.
=cut
sub catfile {
my $self = shift;
return $self->canonpath($self->SUPER::catfile(@_));
}
=head2 Misc
Methods I can't really figure out where they should go yet.
=head3 find_tests
my $test = $mm->find_tests;
Returns a string suitable for feeding to the shell to return all
tests in t/*.t.
=cut
sub find_tests {
my($self) = shift;
return -d 't' ? 't/*.t' : '';
}
=head3 extra_clean_files
my @files_to_clean = $MM->extra_clean_files;
Returns a list of OS specific files to be removed in the clean target in
addition to the usual set.
=cut
# An empty method here tickled a perl 5.8.1 bug and would return its object.
sub extra_clean_files {
return;
}
=head3 installvars
my @installvars = $mm->installvars;
A list of all the INSTALL* variables without the INSTALL prefix. Useful
for iteration or building related variable sets.
=cut
sub installvars {
return qw(PRIVLIB SITELIB VENDORLIB
ARCHLIB SITEARCH VENDORARCH
BIN SITEBIN VENDORBIN
SCRIPT SITESCRIPT VENDORSCRIPT
MAN1DIR SITEMAN1DIR VENDORMAN1DIR
MAN3DIR SITEMAN3DIR VENDORMAN3DIR
);
}
=head3 libscan
my $wanted = $self->libscan($path);
Takes a path to a file or dir and returns an empty string if we don't
want to include this file in the library. Otherwise it returns the
the $path unchanged.
Mainly used to exclude version control administrative directories from
installation.
=cut
sub libscan {
my($self,$path) = @_;
my($dirs,$file) = ($self->splitpath($path))[1,2];
return '' if grep /^(?:RCS|CVS|SCCS|\.svn|_darcs)$/,
$self->splitdir($dirs), $file;
return $path;
}
=head3 platform_constants
my $make_frag = $mm->platform_constants
Returns a make fragment defining all the macros initialized in
init_platform() rather than put them in constants().
=cut
sub platform_constants {
return '';
}
=begin private
=head3 _PREREQ_PRINT
$self->_PREREQ_PRINT;
Implements PREREQ_PRINT.
Refactored out of MakeMaker->new().
=end private
=cut
sub _PREREQ_PRINT {
my $self = shift;
require Data::Dumper;
my @what = ('PREREQ_PM');
push @what, 'MIN_PERL_VERSION' if $self->{MIN_PERL_VERSION};
push @what, 'BUILD_REQUIRES' if $self->{BUILD_REQUIRES};
print Data::Dumper->Dump([@{$self}{@what}], \@what);
exit 0;
}
=begin private
=head3 _PRINT_PREREQ
$mm->_PRINT_PREREQ;
Implements PRINT_PREREQ, a slightly different version of PREREQ_PRINT
added by Redhat to, I think, support generating RPMs from Perl modules.
Should not include BUILD_REQUIRES as RPMs do not incluide them.
Refactored out of MakeMaker->new().
=end private
=cut
sub _PRINT_PREREQ {
my $self = shift;
my $prereqs= $self->{PREREQ_PM};
my @prereq = map { [$_, $prereqs->{$_}] } keys %$prereqs;
if ( $self->{MIN_PERL_VERSION} ) {
push @prereq, ['perl' => $self->{MIN_PERL_VERSION}];
}
print join(" ", map { "perl($_->[0])>=$_->[1] " }
sort { $a->[0] cmp $b->[0] } @prereq), "\n";
exit 0;
}
=begin private
=head3 _all_prereqs
my $prereqs = $self->_all_prereqs;
Returns a hash ref of both PREREQ_PM and BUILD_REQUIRES.
=end private
=cut
sub _all_prereqs {
my $self = shift;
return { %{$self->{PREREQ_PM}}, %{$self->{BUILD_REQUIRES}} };
}
=head1 AUTHOR
Michael G Schwern <schwern@pobox.com> and the denizens of
makemaker@perl.org with code from ExtUtils::MM_Unix and
ExtUtils::MM_Win32.
=cut
1;
EXTUTILS_MM_ANY
$fatpacked{"ExtUtils/MM_BeOS.pm"} = <<'EXTUTILS_MM_BEOS';
package ExtUtils::MM_BeOS;
use strict;
=head1 NAME
ExtUtils::MM_BeOS - methods to override UN*X behaviour in ExtUtils::MakeMaker
=head1 SYNOPSIS
use ExtUtils::MM_BeOS; # Done internally by ExtUtils::MakeMaker if needed
=head1 DESCRIPTION
See ExtUtils::MM_Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not
the semantics.
=over 4
=cut
use ExtUtils::MakeMaker::Config;
use File::Spec;
require ExtUtils::MM_Any;
require ExtUtils::MM_Unix;
our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
our $VERSION = '6.59';
=item os_flavor
BeOS is BeOS.
=cut
sub os_flavor {
return('BeOS');
}
=item init_linker
libperl.a equivalent to be linked to dynamic extensions.
=cut
sub init_linker {
my($self) = shift;
$self->{PERL_ARCHIVE} ||=
File::Spec->catdir('$(PERL_INC)',$Config{libperl});
$self->{PERL_ARCHIVE_AFTER} ||= '';
$self->{EXPORT_LIST} ||= '';
}
=back
1;
__END__
EXTUTILS_MM_BEOS
$fatpacked{"ExtUtils/MM_Cygwin.pm"} = <<'EXTUTILS_MM_CYGWIN';
package ExtUtils::MM_Cygwin;
use strict;
use ExtUtils::MakeMaker::Config;
use File::Spec;
require ExtUtils::MM_Unix;
require ExtUtils::MM_Win32;
our @ISA = qw( ExtUtils::MM_Unix );
our $VERSION = '6.59';
=head1 NAME
ExtUtils::MM_Cygwin - methods to override UN*X behaviour in ExtUtils::MakeMaker
=head1 SYNOPSIS
use ExtUtils::MM_Cygwin; # Done internally by ExtUtils::MakeMaker if needed
=head1 DESCRIPTION
See ExtUtils::MM_Unix for a documentation of the methods provided there.
=over 4
=item os_flavor
We're Unix and Cygwin.
=cut
sub os_flavor {
return('Unix', 'Cygwin');
}
=item cflags
if configured for dynamic loading, triggers #define EXT in EXTERN.h
=cut
sub cflags {
my($self,$libperl)=@_;
return $self->{CFLAGS} if $self->{CFLAGS};
return '' unless $self->needs_linking();
my $base = $self->SUPER::cflags($libperl);
foreach (split /\n/, $base) {
/^(\S*)\s*=\s*(\S*)$/ and $self->{$1} = $2;
};
$self->{CCFLAGS} .= " -DUSEIMPORTLIB" if ($Config{useshrplib} eq 'true');
return $self->{CFLAGS} = qq{
CCFLAGS = $self->{CCFLAGS}
OPTIMIZE = $self->{OPTIMIZE}
PERLTYPE = $self->{PERLTYPE}
};
}
=item replace_manpage_separator
replaces strings '::' with '.' in MAN*POD man page names
=cut
sub replace_manpage_separator {
my($self, $man) = @_;
$man =~ s{/+}{.}g;
return $man;
}
=item init_linker
points to libperl.a
=cut
sub init_linker {
my $self = shift;
if ($Config{useshrplib} eq 'true') {
my $libperl = '$(PERL_INC)' .'/'. "$Config{libperl}";
if( $] >= 5.006002 ) {
$libperl =~ s/a$/dll.a/;
}
$self->{PERL_ARCHIVE} = $libperl;
} else {
$self->{PERL_ARCHIVE} =
'$(PERL_INC)' .'/'. ("$Config{libperl}" or "libperl.a");
}
$self->{PERL_ARCHIVE_AFTER} ||= '';
$self->{EXPORT_LIST} ||= '';
}
=item maybe_command
If our path begins with F</cygdrive/> then we use C<ExtUtils::MM_Win32>
to determine if it may be a command. Otherwise we use the tests
from C<ExtUtils::MM_Unix>.
=cut
sub maybe_command {
my ($self, $file) = @_;
if ($file =~ m{^/cygdrive/}i) {
return ExtUtils::MM_Win32->maybe_command($file);
}
return $self->SUPER::maybe_command($file);
}
=item dynamic_lib
Use the default to produce the *.dll's.
But for new archdir dll's use the same rebase address if the old exists.
=cut
sub dynamic_lib {
my($self, %attribs) = @_;
my $s = ExtUtils::MM_Unix::dynamic_lib($self, %attribs);
my $ori = "$self->{INSTALLARCHLIB}/auto/$self->{FULLEXT}/$self->{BASEEXT}.$self->{DLEXT}";
if (-e $ori) {
my $imagebase = `/bin/objdump -p $ori | /bin/grep ImageBase | /bin/cut -c12-`;
chomp $imagebase;
if ($imagebase gt "40000000") {
my $LDDLFLAGS = $self->{LDDLFLAGS};
$LDDLFLAGS =~ s/-Wl,--enable-auto-image-base/-Wl,--image-base=0x$imagebase/;
$s =~ s/ \$\(LDDLFLAGS\) / $LDDLFLAGS /m;
}
}
$s;
}
=item all_target
Build man pages, too
=cut
sub all_target {
ExtUtils::MM_Unix::all_target(shift);
}
=back
=cut
1;
EXTUTILS_MM_CYGWIN
$fatpacked{"ExtUtils/MM_DOS.pm"} = <<'EXTUTILS_MM_DOS';
package ExtUtils::MM_DOS;
use strict;
our $VERSION = '6.59';
require ExtUtils::MM_Any;
require ExtUtils::MM_Unix;
our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
=head1 NAME
ExtUtils::MM_DOS - DOS specific subclass of ExtUtils::MM_Unix
=head1 SYNOPSIS
Don't use this module directly.
Use ExtUtils::MM and let it choose.
=head1 DESCRIPTION
This is a subclass of ExtUtils::MM_Unix which contains functionality
for DOS.
Unless otherwise stated, it works just like ExtUtils::MM_Unix
=head2 Overridden methods
=over 4
=item os_flavor
=cut
sub os_flavor {
return('DOS');
}
=item B<replace_manpage_separator>
Generates Foo__Bar.3 style man page names
=cut
sub replace_manpage_separator {
my($self, $man) = @_;
$man =~ s,/+,__,g;
return $man;
}
=back
=head1 AUTHOR
Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
=head1 SEE ALSO
L<ExtUtils::MM_Unix>, L<ExtUtils::MakeMaker>
=cut
1;
EXTUTILS_MM_DOS
$fatpacked{"ExtUtils/MM_Darwin.pm"} = <<'EXTUTILS_MM_DARWIN';
package ExtUtils::MM_Darwin;
use strict;
BEGIN {
require ExtUtils::MM_Unix;
our @ISA = qw( ExtUtils::MM_Unix );
}
our $VERSION = '6.59';
=head1 NAME
ExtUtils::MM_Darwin - special behaviors for OS X
=head1 SYNOPSIS
For internal MakeMaker use only
=head1 DESCRIPTION
See L<ExtUtils::MM_Unix> for L<ExtUtils::MM_Any> for documention on the
methods overridden here.
=head2 Overriden Methods
=head3 init_dist
Turn off Apple tar's tendency to copy resource forks as "._foo" files.
=cut
sub init_dist {
my $self = shift;
# Thank you, Apple, for breaking tar and then breaking the work around.
# 10.4 wants COPY_EXTENDED_ATTRIBUTES_DISABLE while 10.5 wants
# COPYFILE_DISABLE. I'm not going to push my luck and instead just
# set both.
$self->{TAR} ||=
'COPY_EXTENDED_ATTRIBUTES_DISABLE=1 COPYFILE_DISABLE=1 tar';
$self->SUPER::init_dist(@_);
}
1;
EXTUTILS_MM_DARWIN
$fatpacked{"ExtUtils/MM_MacOS.pm"} = <<'EXTUTILS_MM_MACOS';
package ExtUtils::MM_MacOS;
use strict;
our $VERSION = '6.59';
sub new {
die <<'UNSUPPORTED';
MacOS Classic (MacPerl) is no longer supported by MakeMaker.
Please use Module::Build instead.
UNSUPPORTED
}
=head1 NAME
ExtUtils::MM_MacOS - once produced Makefiles for MacOS Classic
=head1 SYNOPSIS
# MM_MacOS no longer contains any code. This is just a stub.
=head1 DESCRIPTION
Once upon a time, MakeMaker could produce an approximation of a correct
Makefile on MacOS Classic (MacPerl). Due to a lack of maintainers, this
fell out of sync with the rest of MakeMaker and hadn't worked in years.
Since there's little chance of it being repaired, MacOS Classic is fading
away, and the code was icky to begin with, the code has been deleted to
make maintenance easier.
Those interested in writing modules for MacPerl should use Module::Build
which works better than MakeMaker ever did.
Anyone interested in resurrecting this file should pull the old version
from the MakeMaker CVS repository and contact makemaker@perl.org, but we
really encourage you to work on Module::Build instead.
=cut
1;
EXTUTILS_MM_MACOS
$fatpacked{"ExtUtils/MM_NW5.pm"} = <<'EXTUTILS_MM_NW5';
package ExtUtils::MM_NW5;
=head1 NAME
ExtUtils::MM_NW5 - methods to override UN*X behaviour in ExtUtils::MakeMaker
=head1 SYNOPSIS
use ExtUtils::MM_NW5; # Done internally by ExtUtils::MakeMaker if needed
=head1 DESCRIPTION
See ExtUtils::MM_Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not
the semantics.
=over
=cut
use strict;
use ExtUtils::MakeMaker::Config;
use File::Basename;
our $VERSION = '6.59';
require ExtUtils::MM_Win32;
our @ISA = qw(ExtUtils::MM_Win32);
use ExtUtils::MakeMaker qw( &neatvalue );
$ENV{EMXSHELL} = 'sh'; # to run `commands`
my $BORLAND = $Config{'cc'} =~ /^bcc/i;
my $GCC = $Config{'cc'} =~ /^gcc/i;
=item os_flavor
We're Netware in addition to being Windows.
=cut
sub os_flavor {
my $self = shift;
return ($self->SUPER::os_flavor, 'Netware');
}
=item init_platform
Add Netware macros.
LIBPTH, BASE_IMPORT, NLM_VERSION, MPKTOOL, TOOLPATH, BOOT_SYMBOL,
NLM_SHORT_NAME, INCLUDE, PATH, MM_NW5_REVISION
=item platform_constants
Add Netware macros initialized above to the Makefile.
=cut
sub init_platform {
my($self) = shift;
# To get Win32's setup.
$self->SUPER::init_platform;
# incpath is copied to makefile var INCLUDE in constants sub, here just
# make it empty
my $libpth = $Config{'libpth'};
$libpth =~ s( )(;);
$self->{'LIBPTH'} = $libpth;
$self->{'BASE_IMPORT'} = $Config{'base_import'};
# Additional import file specified from Makefile.pl
if($self->{'base_import'}) {
$self->{'BASE_IMPORT'} .= ', ' . $self->{'base_import'};
}
$self->{'NLM_VERSION'} = $Config{'nlm_version'};
$self->{'MPKTOOL'} = $Config{'mpktool'};
$self->{'TOOLPATH'} = $Config{'toolpath'};
(my $boot = $self->{'NAME'}) =~ s/:/_/g;
$self->{'BOOT_SYMBOL'}=$boot;
# If the final binary name is greater than 8 chars,
# truncate it here.
if(length($self->{'BASEEXT'}) > 8) {
$self->{'NLM_SHORT_NAME'} = substr($self->{'BASEEXT'},0,8);
}
# Get the include path and replace the spaces with ;
# Copy this to makefile as INCLUDE = d:\...;d:\;
($self->{INCLUDE} = $Config{'incpath'}) =~ s/([ ]*)-I/;/g;
# Set the path to CodeWarrior binaries which might not have been set in
# any other place
$self->{PATH} = '$(PATH);$(TOOLPATH)';
$self->{MM_NW5_VERSION} = $VERSION;
}
sub platform_constants {
my($self) = shift;
my $make_frag = '';
# Setup Win32's constants.
$make_frag .= $self->SUPER::platform_constants;
foreach my $macro (qw(LIBPTH BASE_IMPORT NLM_VERSION MPKTOOL
TOOLPATH BOOT_SYMBOL NLM_SHORT_NAME INCLUDE PATH
MM_NW5_VERSION
))
{
next unless defined $self->{$macro};
$make_frag .= "$macro = $self->{$macro}\n";
}
return $make_frag;
}
=item const_cccmd
=cut
sub const_cccmd {
my($self,$libperl)=@_;
return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
return '' unless $self->needs_linking();
return $self->{CONST_CCCMD} = <<'MAKE_FRAG';
CCCMD = $(CC) $(CCFLAGS) $(INC) $(OPTIMIZE) \
$(PERLTYPE) $(MPOLLUTE) -o $@ \
-DVERSION=\"$(VERSION)\" -DXS_VERSION=\"$(XS_VERSION)\"
MAKE_FRAG
}
=item static_lib
=cut
sub static_lib {
my($self) = @_;
return '' unless $self->has_link_code;
my $m = <<'END';
$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists
$(RM_RF) $@
END
# If this extension has it's own library (eg SDBM_File)
# then copy that to $(INST_STATIC) and add $(OBJECT) into it.
$m .= <<'END' if $self->{MYEXTLIB};
$self->{CP} $(MYEXTLIB) $@
END
my $ar_arg;
if( $BORLAND ) {
$ar_arg = '$@ $(OBJECT:^"+")';
}
elsif( $GCC ) {
$ar_arg = '-ru $@ $(OBJECT)';
}
else {
$ar_arg = '-type library -o $@ $(OBJECT)';
}
$m .= sprintf <<'END', $ar_arg;
$(AR) %s
$(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)\extralibs.ld
$(CHMOD) 755 $@
END
$m .= <<'END' if $self->{PERL_SRC};
$(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)\ext.libs
END
return $m;
}
=item dynamic_lib
Defines how to produce the *.so (or equivalent) files.
=cut
sub dynamic_lib {
my($self, %attribs) = @_;
return '' unless $self->needs_linking(); #might be because of a subdir
return '' unless $self->has_link_code;
my($otherldflags) = $attribs{OTHERLDFLAGS} || ($BORLAND ? 'c0d32.obj': '');
my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
my($ldfrom) = '$(LDFROM)';
(my $boot = $self->{NAME}) =~ s/:/_/g;
my $m = <<'MAKE_FRAG';
# This section creates the dynamically loadable $(INST_DYNAMIC)
# from $(OBJECT) and possibly $(MYEXTLIB).
OTHERLDFLAGS = '.$otherldflags.'
INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
# Create xdc data for an MT safe NLM in case of mpk build
$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists
$(NOECHO) $(ECHO) Export boot_$(BOOT_SYMBOL) > $(BASEEXT).def
$(NOECHO) $(ECHO) $(BASE_IMPORT) >> $(BASEEXT).def
$(NOECHO) $(ECHO) Import @$(PERL_INC)\perl.imp >> $(BASEEXT).def
MAKE_FRAG
if ( $self->{CCFLAGS} =~ m/ -DMPK_ON /) {
$m .= <<'MAKE_FRAG';
$(MPKTOOL) $(XDCFLAGS) $(BASEEXT).xdc
$(NOECHO) $(ECHO) xdcdata $(BASEEXT).xdc >> $(BASEEXT).def
MAKE_FRAG
}
# Reconstruct the X.Y.Z version.
my $version = join '.', map { sprintf "%d", $_ }
$] =~ /(\d)\.(\d{3})(\d{2})/;
$m .= sprintf ' $(LD) $(LDFLAGS) $(OBJECT:.obj=.obj) -desc "Perl %s Extension ($(BASEEXT)) XS_VERSION: $(XS_VERSION)" -nlmversion $(NLM_VERSION)', $version;
# Taking care of long names like FileHandle, ByteLoader, SDBM_File etc
if($self->{NLM_SHORT_NAME}) {
# In case of nlms with names exceeding 8 chars, build nlm in the
# current dir, rename and move to auto\lib.
$m .= q{ -o $(NLM_SHORT_NAME).$(DLEXT)}
} else {
$m .= q{ -o $(INST_AUTODIR)\\$(BASEEXT).$(DLEXT)}
}
# Add additional lib files if any (SDBM_File)
$m .= q{ $(MYEXTLIB) } if $self->{MYEXTLIB};
$m .= q{ $(PERL_INC)\Main.lib -commandfile $(BASEEXT).def}."\n";
if($self->{NLM_SHORT_NAME}) {
$m .= <<'MAKE_FRAG';
if exist $(INST_AUTODIR)\$(NLM_SHORT_NAME).$(DLEXT) del $(INST_AUTODIR)\$(NLM_SHORT_NAME).$(DLEXT)
move $(NLM_SHORT_NAME).$(DLEXT) $(INST_AUTODIR)
MAKE_FRAG
}
$m .= <<'MAKE_FRAG';
$(CHMOD) 755 $@
MAKE_FRAG
return $m;
}
1;
__END__
=back
=cut
EXTUTILS_MM_NW5
$fatpacked{"ExtUtils/MM_OS2.pm"} = <<'EXTUTILS_MM_OS2';
package ExtUtils::MM_OS2;
use strict;
use ExtUtils::MakeMaker qw(neatvalue);
use File::Spec;
our $VERSION = '6.59';
require ExtUtils::MM_Any;
require ExtUtils::MM_Unix;
our @ISA = qw(ExtUtils::MM_Any ExtUtils::MM_Unix);
=pod
=head1 NAME
ExtUtils::MM_OS2 - methods to override UN*X behaviour in ExtUtils::MakeMaker
=head1 SYNOPSIS
use ExtUtils::MM_OS2; # Done internally by ExtUtils::MakeMaker if needed
=head1 DESCRIPTION
See ExtUtils::MM_Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not
the semantics.
=head1 METHODS
=over 4
=item init_dist
Define TO_UNIX to convert OS2 linefeeds to Unix style.
=cut
sub init_dist {
my($self) = @_;
$self->{TO_UNIX} ||= <<'MAKE_TEXT';
$(NOECHO) $(TEST_F) tmp.zip && $(RM_F) tmp.zip; $(ZIP) -ll -mr tmp.zip $(DISTVNAME) && unzip -o tmp.zip && $(RM_F) tmp.zip
MAKE_TEXT
$self->SUPER::init_dist;
}
sub dlsyms {
my($self,%attribs) = @_;
my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || [];
my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
my($imports) = $attribs{IMPORTS} || $self->{IMPORTS} || {};
my(@m);
(my $boot = $self->{NAME}) =~ s/:/_/g;
if (not $self->{SKIPHASH}{'dynamic'}) {
push(@m,"
$self->{BASEEXT}.def: Makefile.PL
",
' $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e \'use ExtUtils::Mksymlists; \\
Mksymlists("NAME" => "$(NAME)", "DLBASE" => "$(DLBASE)", ',
'"VERSION" => "$(VERSION)", "DISTNAME" => "$(DISTNAME)", ',
'"INSTALLDIRS" => "$(INSTALLDIRS)", ',
'"DL_FUNCS" => ',neatvalue($funcs),
', "FUNCLIST" => ',neatvalue($funclist),
', "IMPORTS" => ',neatvalue($imports),
', "DL_VARS" => ', neatvalue($vars), ');\'
');
}
if ($self->{IMPORTS} && %{$self->{IMPORTS}}) {
# Make import files (needed for static build)
-d 'tmp_imp' or mkdir 'tmp_imp', 0777 or die "Can't mkdir tmp_imp";
open my $imp, '>', 'tmpimp.imp' or die "Can't open tmpimp.imp";
while (my($name, $exp) = each %{$self->{IMPORTS}}) {
my ($lib, $id) = ($exp =~ /(.*)\.(.*)/) or die "Malformed IMPORT `$exp'";
print $imp "$name $lib $id ?\n";
}
close $imp or die "Can't close tmpimp.imp";
# print "emximp -o tmpimp$Config::Config{lib_ext} tmpimp.imp\n";
system "emximp -o tmpimp$Config::Config{lib_ext} tmpimp.imp"
and die "Cannot make import library: $!, \$?=$?";
# May be running under miniperl, so have no glob...
eval "unlink <tmp_imp/*>; 1" or system "rm tmp_imp/*";
system "cd tmp_imp; $Config::Config{ar} x ../tmpimp$Config::Config{lib_ext}"
and die "Cannot extract import objects: $!, \$?=$?";
}
join('',@m);
}
sub static_lib {
my($self) = @_;
my $old = $self->ExtUtils::MM_Unix::static_lib();
return $old unless $self->{IMPORTS} && %{$self->{IMPORTS}};
my @chunks = split /\n{2,}/, $old;
shift @chunks unless length $chunks[0]; # Empty lines at the start
$chunks[0] .= <<'EOC';
$(AR) $(AR_STATIC_ARGS) $@ tmp_imp/* && $(RANLIB) $@
EOC
return join "\n\n". '', @chunks;
}
sub replace_manpage_separator {
my($self,$man) = @_;
$man =~ s,/+,.,g;
$man;
}
sub maybe_command {
my($self,$file) = @_;
$file =~ s,[/\\]+,/,g;
return $file if -x $file && ! -d _;
return "$file.exe" if -x "$file.exe" && ! -d _;
return "$file.cmd" if -x "$file.cmd" && ! -d _;
return;
}
=item init_linker
=cut
sub init_linker {
my $self = shift;
$self->{PERL_ARCHIVE} = "\$(PERL_INC)/libperl\$(LIB_EXT)";
$self->{PERL_ARCHIVE_AFTER} = $OS2::is_aout
? ''
: '$(PERL_INC)/libperl_override$(LIB_EXT)';
$self->{EXPORT_LIST} = '$(BASEEXT).def';
}
=item os_flavor
OS/2 is OS/2
=cut
sub os_flavor {
return('OS/2');
}
=back
=cut
1;
EXTUTILS_MM_OS2
$fatpacked{"ExtUtils/MM_QNX.pm"} = <<'EXTUTILS_MM_QNX';
package ExtUtils::MM_QNX;
use strict;
our $VERSION = '6.59';
require ExtUtils::MM_Unix;
our @ISA = qw(ExtUtils::MM_Unix);
=head1 NAME
ExtUtils::MM_QNX - QNX specific subclass of ExtUtils::MM_Unix
=head1 SYNOPSIS
Don't use this module directly.
Use ExtUtils::MM and let it choose.
=head1 DESCRIPTION
This is a subclass of ExtUtils::MM_Unix which contains functionality for
QNX.
Unless otherwise stated it works just like ExtUtils::MM_Unix
=head2 Overridden methods
=head3 extra_clean_files
Add .err files corresponding to each .c file.
=cut
sub extra_clean_files {
my $self = shift;
my @errfiles = @{$self->{C}};
for ( @errfiles ) {
s/.c$/.err/;
}
return( @errfiles, 'perlmain.err' );
}
=head1 AUTHOR
Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
=head1 SEE ALSO
L<ExtUtils::MakeMaker>
=cut
1;
EXTUTILS_MM_QNX
$fatpacked{"ExtUtils/MM_UWIN.pm"} = <<'EXTUTILS_MM_UWIN';
package ExtUtils::MM_UWIN;
use strict;
our $VERSION = '6.59';
require ExtUtils::MM_Unix;
our @ISA = qw(ExtUtils::MM_Unix);
=head1 NAME
ExtUtils::MM_UWIN - U/WIN specific subclass of ExtUtils::MM_Unix
=head1 SYNOPSIS
Don't use this module directly.
Use ExtUtils::MM and let it choose.
=head1 DESCRIPTION
This is a subclass of ExtUtils::MM_Unix which contains functionality for
the AT&T U/WIN UNIX on Windows environment.
Unless otherwise stated it works just like ExtUtils::MM_Unix
=head2 Overridden methods
=over 4
=item os_flavor
In addition to being Unix, we're U/WIN.
=cut
sub os_flavor {
return('Unix', 'U/WIN');
}
=item B<replace_manpage_separator>
=cut
sub replace_manpage_separator {
my($self, $man) = @_;
$man =~ s,/+,.,g;
return $man;
}
=back
=head1 AUTHOR
Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
=head1 SEE ALSO
L<ExtUtils::MM_Win32>, L<ExtUtils::MakeMaker>
=cut
1;
EXTUTILS_MM_UWIN
$fatpacked{"ExtUtils/MM_Unix.pm"} = <<'EXTUTILS_MM_UNIX';
package ExtUtils::MM_Unix;
require 5.006;
use strict;
use Carp;
use ExtUtils::MakeMaker::Config;
use File::Basename qw(basename dirname);
use DirHandle;
our %Config_Override;
use ExtUtils::MakeMaker qw($Verbose neatvalue);
# If we make $VERSION an our variable parse_version() breaks
use vars qw($VERSION);
$VERSION = '6.59';
$VERSION = eval $VERSION;
require ExtUtils::MM_Any;
our @ISA = qw(ExtUtils::MM_Any);
my %Is;
BEGIN {
$Is{OS2} = $^O eq 'os2';
$Is{Win32} = $^O eq 'MSWin32' || $Config{osname} eq 'NetWare';
$Is{Dos} = $^O eq 'dos';
$Is{VMS} = $^O eq 'VMS';
$Is{OSF} = $^O eq 'dec_osf';
$Is{IRIX} = $^O eq 'irix';
$Is{NetBSD} = $^O eq 'netbsd';
$Is{Interix} = $^O eq 'interix';
$Is{SunOS4} = $^O eq 'sunos';
$Is{Solaris} = $^O eq 'solaris';
$Is{SunOS} = $Is{SunOS4} || $Is{Solaris};
$Is{BSD} = ($^O =~ /^(?:free|net|open)bsd$/ or
grep( $^O eq $_, qw(bsdos interix dragonfly) )
);
}
BEGIN {
if( $Is{VMS} ) {
# For things like vmsify()
require VMS::Filespec;
VMS::Filespec->import;
}
}
=head1 NAME
ExtUtils::MM_Unix - methods used by ExtUtils::MakeMaker
=head1 SYNOPSIS
C<require ExtUtils::MM_Unix;>
=head1 DESCRIPTION
The methods provided by this package are designed to be used in
conjunction with ExtUtils::MakeMaker. When MakeMaker writes a
Makefile, it creates one or more objects that inherit their methods
from a package C<MM>. MM itself doesn't provide any methods, but it
ISA ExtUtils::MM_Unix class. The inheritance tree of MM lets operating
specific packages take the responsibility for all the methods provided
by MM_Unix. We are trying to reduce the number of the necessary
overrides by defining rather primitive operations within
ExtUtils::MM_Unix.
If you are going to write a platform specific MM package, please try
to limit the necessary overrides to primitive methods, and if it is not
possible to do so, let's work out how to achieve that gain.
If you are overriding any of these methods in your Makefile.PL (in the
MY class), please report that to the makemaker mailing list. We are
trying to minimize the necessary method overrides and switch to data
driven Makefile.PLs wherever possible. In the long run less methods
will be overridable via the MY class.
=head1 METHODS
The following description of methods is still under
development. Please refer to the code for not suitably documented
sections and complain loudly to the makemaker@perl.org mailing list.
Better yet, provide a patch.
Not all of the methods below are overridable in a
Makefile.PL. Overridable methods are marked as (o). All methods are
overridable by a platform specific MM_*.pm file.
Cross-platform methods are being moved into MM_Any. If you can't find
something that used to be in here, look in MM_Any.
=cut
# So we don't have to keep calling the methods over and over again,
# we have these globals to cache the values. Faster and shrtr.
my $Curdir = __PACKAGE__->curdir;
my $Rootdir = __PACKAGE__->rootdir;
my $Updir = __PACKAGE__->updir;
=head2 Methods
=over 4
=item os_flavor
Simply says that we're Unix.
=cut
sub os_flavor {
return('Unix');
}
=item c_o (o)
Defines the suffix rules to compile different flavors of C files to
object files.
=cut
sub c_o {
# --- Translation Sections ---
my($self) = shift;
return '' unless $self->needs_linking();
my(@m);
my $command = '$(CCCMD)';
my $flags = '$(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE)';
if (my $cpp = $Config{cpprun}) {
my $cpp_cmd = $self->const_cccmd;
$cpp_cmd =~ s/^CCCMD\s*=\s*\$\(CC\)/$cpp/;
push @m, qq{
.c.i:
$cpp_cmd $flags \$*.c > \$*.i
};
}
push @m, qq{
.c.s:
$command -S $flags \$*.c
.c\$(OBJ_EXT):
$command $flags \$*.c
.cpp\$(OBJ_EXT):
$command $flags \$*.cpp
.cxx\$(OBJ_EXT):
$command $flags \$*.cxx
.cc\$(OBJ_EXT):
$command $flags \$*.cc
};
push @m, qq{
.C\$(OBJ_EXT):
$command $flags \$*.C
} if !$Is{OS2} and !$Is{Win32} and !$Is{Dos}; #Case-specific
return join "", @m;
}
=item cflags (o)
Does very much the same as the cflags script in the perl
distribution. It doesn't return the whole compiler command line, but
initializes all of its parts. The const_cccmd method then actually
returns the definition of the CCCMD macro which uses these parts.
=cut
#'
sub cflags {
my($self,$libperl)=@_;
return $self->{CFLAGS} if $self->{CFLAGS};
return '' unless $self->needs_linking();
my($prog, $uc, $perltype, %cflags);
$libperl ||= $self->{LIBPERL_A} || "libperl$self->{LIB_EXT}" ;
$libperl =~ s/\.\$\(A\)$/$self->{LIB_EXT}/;
@cflags{qw(cc ccflags optimize shellflags)}
= @Config{qw(cc ccflags optimize shellflags)};
my($optdebug) = "";
$cflags{shellflags} ||= '';
my(%map) = (
D => '-DDEBUGGING',
E => '-DEMBED',
DE => '-DDEBUGGING -DEMBED',
M => '-DEMBED -DMULTIPLICITY',
DM => '-DDEBUGGING -DEMBED -DMULTIPLICITY',
);
if ($libperl =~ /libperl(\w*)\Q$self->{LIB_EXT}/){
$uc = uc($1);
} else {
$uc = ""; # avoid warning
}
$perltype = $map{$uc} ? $map{$uc} : "";
if ($uc =~ /^D/) {
$optdebug = "-g";
}
my($name);
( $name = $self->{NAME} . "_cflags" ) =~ s/:/_/g ;
if ($prog = $Config{$name}) {
# Expand hints for this extension via the shell
print STDOUT "Processing $name hint:\n" if $Verbose;
my(@o)=`cc=\"$cflags{cc}\"
ccflags=\"$cflags{ccflags}\"
optimize=\"$cflags{optimize}\"
perltype=\"$cflags{perltype}\"
optdebug=\"$cflags{optdebug}\"
eval '$prog'
echo cc=\$cc
echo ccflags=\$ccflags
echo optimize=\$optimize
echo perltype=\$perltype
echo optdebug=\$optdebug
`;
foreach my $line (@o){
chomp $line;
if ($line =~ /(.*?)=\s*(.*)\s*$/){
$cflags{$1} = $2;
print STDOUT " $1 = $2\n" if $Verbose;
} else {
print STDOUT "Unrecognised result from hint: '$line'\n";
}
}
}
if ($optdebug) {
$cflags{optimize} = $optdebug;
}
for (qw(ccflags optimize perltype)) {
$cflags{$_} ||= '';
$cflags{$_} =~ s/^\s+//;
$cflags{$_} =~ s/\s+/ /g;
$cflags{$_} =~ s/\s+$//;
$self->{uc $_} ||= $cflags{$_};
}
if ($self->{POLLUTE}) {
$self->{CCFLAGS} .= ' -DPERL_POLLUTE ';
}
my $pollute = '';
if ($Config{usemymalloc} and not $Config{bincompat5005}
and not $Config{ccflags} =~ /-DPERL_POLLUTE_MALLOC\b/
and $self->{PERL_MALLOC_OK}) {
$pollute = '$(PERL_MALLOC_DEF)';
}
$self->{CCFLAGS} = quote_paren($self->{CCFLAGS});
$self->{OPTIMIZE} = quote_paren($self->{OPTIMIZE});
return $self->{CFLAGS} = qq{
CCFLAGS = $self->{CCFLAGS}
OPTIMIZE = $self->{OPTIMIZE}
PERLTYPE = $self->{PERLTYPE}
MPOLLUTE = $pollute
};
}
=item const_cccmd (o)
Returns the full compiler call for C programs and stores the
definition in CONST_CCCMD.
=cut
sub const_cccmd {
my($self,$libperl)=@_;
return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
return '' unless $self->needs_linking();
return $self->{CONST_CCCMD} =
q{CCCMD = $(CC) -c $(PASTHRU_INC) $(INC) \\
$(CCFLAGS) $(OPTIMIZE) \\
$(PERLTYPE) $(MPOLLUTE) $(DEFINE_VERSION) \\
$(XS_DEFINE_VERSION)};
}
=item const_config (o)
Defines a couple of constants in the Makefile that are imported from
%Config.
=cut
sub const_config {
# --- Constants Sections ---
my($self) = shift;
my @m = <<"END";
# These definitions are from config.sh (via $INC{'Config.pm'}).
# They may have been overridden via Makefile.PL or on the command line.
END
my(%once_only);
foreach my $key (@{$self->{CONFIG}}){
# SITE*EXP macros are defined in &constants; avoid duplicates here
next if $once_only{$key};
$self->{uc $key} = quote_paren($self->{uc $key});
push @m, uc($key) , ' = ' , $self->{uc $key}, "\n";
$once_only{$key} = 1;
}
join('', @m);
}
=item const_loadlibs (o)
Defines EXTRALIBS, LDLOADLIBS, BSLOADLIBS, LD_RUN_PATH. See
L<ExtUtils::Liblist> for details.
=cut
sub const_loadlibs {
my($self) = shift;
return "" unless $self->needs_linking;
my @m;
push @m, qq{
# $self->{NAME} might depend on some other libraries:
# See ExtUtils::Liblist for details
#
};
for my $tmp (qw/
EXTRALIBS LDLOADLIBS BSLOADLIBS
/) {
next unless defined $self->{$tmp};
push @m, "$tmp = $self->{$tmp}\n";
}
# don't set LD_RUN_PATH if empty
for my $tmp (qw/
LD_RUN_PATH
/) {
next unless $self->{$tmp};
push @m, "$tmp = $self->{$tmp}\n";
}
return join "", @m;
}
=item constants (o)
my $make_frag = $mm->constants;
Prints out macros for lots of constants.
=cut
sub constants {
my($self) = @_;
my @m = ();
$self->{DFSEP} = '$(DIRFILESEP)'; # alias for internal use
for my $macro (qw(
AR_STATIC_ARGS DIRFILESEP DFSEP
NAME NAME_SYM
VERSION VERSION_MACRO VERSION_SYM DEFINE_VERSION
XS_VERSION XS_VERSION_MACRO XS_DEFINE_VERSION
INST_ARCHLIB INST_SCRIPT INST_BIN INST_LIB
INST_MAN1DIR INST_MAN3DIR
MAN1EXT MAN3EXT
INSTALLDIRS INSTALL_BASE DESTDIR PREFIX
PERLPREFIX SITEPREFIX VENDORPREFIX
),
(map { ("INSTALL".$_,
"DESTINSTALL".$_)
} $self->installvars),
qw(
PERL_LIB
PERL_ARCHLIB
LIBPERL_A MYEXTLIB
FIRST_MAKEFILE MAKEFILE_OLD MAKE_APERL_FILE
PERLMAINCC PERL_SRC PERL_INC
PERL FULLPERL ABSPERL
PERLRUN FULLPERLRUN ABSPERLRUN
PERLRUNINST FULLPERLRUNINST ABSPERLRUNINST
PERL_CORE
PERM_DIR PERM_RW PERM_RWX
) )
{
next unless defined $self->{$macro};
# pathnames can have sharp signs in them; escape them so
# make doesn't think it is a comment-start character.
$self->{$macro} =~ s/#/\\#/g;
push @m, "$macro = $self->{$macro}\n";
}
push @m, qq{
MAKEMAKER = $self->{MAKEMAKER}
MM_VERSION = $self->{MM_VERSION}
MM_REVISION = $self->{MM_REVISION}
};
push @m, q{
# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle).
# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle)
# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
# DLBASE = Basename part of dynamic library. May be just equal BASEEXT.
};
for my $macro (qw/
MAKE
FULLEXT BASEEXT PARENT_NAME DLBASE VERSION_FROM INC DEFINE OBJECT
LDFROM LINKTYPE BOOTDEP
/ )
{
next unless defined $self->{$macro};
push @m, "$macro = $self->{$macro}\n";
}
push @m, "
# Handy lists of source code files:
XS_FILES = ".$self->wraplist(sort keys %{$self->{XS}})."
C_FILES = ".$self->wraplist(@{$self->{C}})."
O_FILES = ".$self->wraplist(@{$self->{O_FILES}})."
H_FILES = ".$self->wraplist(@{$self->{H}})."
MAN1PODS = ".$self->wraplist(sort keys %{$self->{MAN1PODS}})."
MAN3PODS = ".$self->wraplist(sort keys %{$self->{MAN3PODS}})."
";
push @m, q{
# Where is the Config information that we are using/depend on
CONFIGDEP = $(PERL_ARCHLIB)$(DFSEP)Config.pm $(PERL_INC)$(DFSEP)config.h
};
push @m, qq{
# Where to build things
INST_LIBDIR = $self->{INST_LIBDIR}
INST_ARCHLIBDIR = $self->{INST_ARCHLIBDIR}
INST_AUTODIR = $self->{INST_AUTODIR}
INST_ARCHAUTODIR = $self->{INST_ARCHAUTODIR}
INST_STATIC = $self->{INST_STATIC}
INST_DYNAMIC = $self->{INST_DYNAMIC}
INST_BOOT = $self->{INST_BOOT}
};
push @m, qq{
# Extra linker info
EXPORT_LIST = $self->{EXPORT_LIST}
PERL_ARCHIVE = $self->{PERL_ARCHIVE}
PERL_ARCHIVE_AFTER = $self->{PERL_ARCHIVE_AFTER}
};
push @m, "
TO_INST_PM = ".$self->wraplist(sort keys %{$self->{PM}})."
PM_TO_BLIB = ".$self->wraplist(%{$self->{PM}})."
";
join('',@m);
}
=item depend (o)
Same as macro for the depend attribute.
=cut
sub depend {
my($self,%attribs) = @_;
my(@m,$key,$val);
while (($key,$val) = each %attribs){
last unless defined $key;
push @m, "$key : $val\n";
}
join "", @m;
}
=item init_DEST
$mm->init_DEST
Defines the DESTDIR and DEST* variables paralleling the INSTALL*.
=cut
sub init_DEST {
my $self = shift;
# Initialize DESTDIR
$self->{DESTDIR} ||= '';
# Make DEST variables.
foreach my $var ($self->installvars) {
my $destvar = 'DESTINSTALL'.$var;
$self->{$destvar} ||= '$(DESTDIR)$(INSTALL'.$var.')';
}
}
=item init_dist
$mm->init_dist;
Defines a lot of macros for distribution support.
macro description default
TAR tar command to use tar
TARFLAGS flags to pass to TAR cvf
ZIP zip command to use zip
ZIPFLAGS flags to pass to ZIP -r
COMPRESS compression command to gzip --best
use for tarfiles
SUFFIX suffix to put on .gz
compressed files
SHAR shar command to use shar
PREOP extra commands to run before
making the archive
POSTOP extra commands to run after
making the archive
TO_UNIX a command to convert linefeeds
to Unix style in your archive
CI command to checkin your ci -u
sources to version control
RCS_LABEL command to label your sources rcs -Nv$(VERSION_SYM): -q
just after CI is run
DIST_CP $how argument to manicopy() best
when the distdir is created
DIST_DEFAULT default target to use to tardist
create a distribution
DISTVNAME name of the resulting archive $(DISTNAME)-$(VERSION)
(minus suffixes)
=cut
sub init_dist {
my $self = shift;
$self->{TAR} ||= 'tar';
$self->{TARFLAGS} ||= 'cvf';
$self->{ZIP} ||= 'zip';
$self->{ZIPFLAGS} ||= '-r';
$self->{COMPRESS} ||= 'gzip --best';
$self->{SUFFIX} ||= '.gz';
$self->{SHAR} ||= 'shar';
$self->{PREOP} ||= '$(NOECHO) $(NOOP)'; # eg update MANIFEST
$self->{POSTOP} ||= '$(NOECHO) $(NOOP)'; # eg remove the distdir
$self->{TO_UNIX} ||= '$(NOECHO) $(NOOP)';
$self->{CI} ||= 'ci -u';
$self->{RCS_LABEL}||= 'rcs -Nv$(VERSION_SYM): -q';
$self->{DIST_CP} ||= 'best';
$self->{DIST_DEFAULT} ||= 'tardist';
($self->{DISTNAME} = $self->{NAME}) =~ s{::}{-}g unless $self->{DISTNAME};
$self->{DISTVNAME} ||= $self->{DISTNAME}.'-'.$self->{VERSION};
}
=item dist (o)
my $dist_macros = $mm->dist(%overrides);
Generates a make fragment defining all the macros initialized in
init_dist.
%overrides can be used to override any of the above.
=cut
sub dist {
my($self, %attribs) = @_;
my $make = '';
foreach my $key (qw(
TAR TARFLAGS ZIP ZIPFLAGS COMPRESS SUFFIX SHAR
PREOP POSTOP TO_UNIX
CI RCS_LABEL DIST_CP DIST_DEFAULT
DISTNAME DISTVNAME
))
{
my $value = $attribs{$key} || $self->{$key};
$make .= "$key = $value\n";
}
return $make;
}
=item dist_basics (o)
Defines the targets distclean, distcheck, skipcheck, manifest, veryclean.
=cut
sub dist_basics {
my($self) = shift;
return <<'MAKE_FRAG';
distclean :: realclean distcheck
$(NOECHO) $(NOOP)
distcheck :
$(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck
skipcheck :
$(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck
manifest :
$(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest
veryclean : realclean
$(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old
MAKE_FRAG
}
=item dist_ci (o)
Defines a check in target for RCS.
=cut
sub dist_ci {
my($self) = shift;
return q{
ci :
$(PERLRUN) "-MExtUtils::Manifest=maniread" \\
-e "@all = keys %{ maniread() };" \\
-e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \\
-e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});"
};
}
=item dist_core (o)
my $dist_make_fragment = $MM->dist_core;
Puts the targets necessary for 'make dist' together into one make
fragment.
=cut
sub dist_core {
my($self) = shift;
my $make_frag = '';
foreach my $target (qw(dist tardist uutardist tarfile zipdist zipfile
shdist))
{
my $method = $target.'_target';
$make_frag .= "\n";
$make_frag .= $self->$method();
}
return $make_frag;
}
=item B<dist_target>
my $make_frag = $MM->dist_target;
Returns the 'dist' target to make an archive for distribution. This
target simply checks to make sure the Makefile is up-to-date and
depends on $(DIST_DEFAULT).
=cut
sub dist_target {
my($self) = shift;
my $date_check = $self->oneliner(<<'CODE', ['-l']);
print 'Warning: Makefile possibly out of date with $(VERSION_FROM)'
if -e '$(VERSION_FROM)' and -M '$(VERSION_FROM)' < -M '$(FIRST_MAKEFILE)';
CODE
return sprintf <<'MAKE_FRAG', $date_check;
dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE)
$(NOECHO) %s
MAKE_FRAG
}
=item B<tardist_target>
my $make_frag = $MM->tardist_target;
Returns the 'tardist' target which is simply so 'make tardist' works.
The real work is done by the dynamically named tardistfile_target()
method, tardist should have that as a dependency.
=cut
sub tardist_target {
my($self) = shift;
return <<'MAKE_FRAG';
tardist : $(DISTVNAME).tar$(SUFFIX)
$(NOECHO) $(NOOP)
MAKE_FRAG
}
=item B<zipdist_target>
my $make_frag = $MM->zipdist_target;
Returns the 'zipdist' target which is simply so 'make zipdist' works.
The real work is done by the dynamically named zipdistfile_target()
method, zipdist should have that as a dependency.
=cut
sub zipdist_target {
my($self) = shift;
return <<'MAKE_FRAG';
zipdist : $(DISTVNAME).zip
$(NOECHO) $(NOOP)
MAKE_FRAG
}
=item B<tarfile_target>
my $make_frag = $MM->tarfile_target;
The name of this target is the name of the tarball generated by
tardist. This target does the actual work of turning the distdir into
a tarball.
=cut
sub tarfile_target {
my($self) = shift;
return <<'MAKE_FRAG';
$(DISTVNAME).tar$(SUFFIX) : distdir
$(PREOP)
$(TO_UNIX)
$(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME)
$(RM_RF) $(DISTVNAME)
$(COMPRESS) $(DISTVNAME).tar
$(POSTOP)
MAKE_FRAG
}
=item zipfile_target
my $make_frag = $MM->zipfile_target;
The name of this target is the name of the zip file generated by
zipdist. This target does the actual work of turning the distdir into
a zip file.
=cut
sub zipfile_target {
my($self) = shift;
return <<'MAKE_FRAG';
$(DISTVNAME).zip : distdir
$(PREOP)
$(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME)
$(RM_RF) $(DISTVNAME)
$(POSTOP)
MAKE_FRAG
}
=item uutardist_target
my $make_frag = $MM->uutardist_target;
Converts the tarfile into a uuencoded file
=cut
sub uutardist_target {
my($self) = shift;
return <<'MAKE_FRAG';
uutardist : $(DISTVNAME).tar$(SUFFIX)
uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu
MAKE_FRAG
}
=item shdist_target
my $make_frag = $MM->shdist_target;
Converts the distdir into a shell archive.
=cut
sub shdist_target {
my($self) = shift;
return <<'MAKE_FRAG';
shdist : distdir
$(PREOP)
$(SHAR) $(DISTVNAME) > $(DISTVNAME).shar
$(RM_RF) $(DISTVNAME)
$(POSTOP)
MAKE_FRAG
}
=item dlsyms (o)
Used by some OS' to define DL_FUNCS and DL_VARS and write the *.exp files.
Normally just returns an empty string.
=cut
sub dlsyms {
return '';
}
=item dynamic_bs (o)
Defines targets for bootstrap files.
=cut
sub dynamic_bs {
my($self, %attribs) = @_;
return '
BOOTSTRAP =
' unless $self->has_link_code();
my $target = $Is{VMS} ? '$(MMS$TARGET)' : '$@';
return sprintf <<'MAKE_FRAG', ($target) x 5;
BOOTSTRAP = $(BASEEXT).bs
# As Mkbootstrap might not write a file (if none is required)
# we use touch to prevent make continually trying to remake it.
# The DynaLoader only reads a non-empty file.
$(BOOTSTRAP) : $(FIRST_MAKEFILE) $(BOOTDEP) $(INST_ARCHAUTODIR)$(DFSEP).exists
$(NOECHO) $(ECHO) "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))"
$(NOECHO) $(PERLRUN) \
"-MExtUtils::Mkbootstrap" \
-e "Mkbootstrap('$(BASEEXT)','$(BSLOADLIBS)');"
$(NOECHO) $(TOUCH) %s
$(CHMOD) $(PERM_RW) %s
$(INST_BOOT) : $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists
$(NOECHO) $(RM_RF) %s
- $(CP) $(BOOTSTRAP) %s
$(CHMOD) $(PERM_RW) %s
MAKE_FRAG
}
=item dynamic_lib (o)
Defines how to produce the *.so (or equivalent) files.
=cut
sub dynamic_lib {
my($self, %attribs) = @_;
return '' unless $self->needs_linking(); #might be because of a subdir
return '' unless $self->has_link_code;
my($otherldflags) = $attribs{OTHERLDFLAGS} || "";
my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
my($armaybe) = $attribs{ARMAYBE} || $self->{ARMAYBE} || ":";
my($ldfrom) = '$(LDFROM)';
$armaybe = 'ar' if ($Is{OSF} and $armaybe eq ':');
my(@m);
my $ld_opt = $Is{OS2} ? '$(OPTIMIZE) ' : ''; # Useful on other systems too?
my $ld_fix = $Is{OS2} ? '|| ( $(RM_F) $@ && sh -c false )' : '';
push(@m,'
# This section creates the dynamically loadable $(INST_DYNAMIC)
# from $(OBJECT) and possibly $(MYEXTLIB).
ARMAYBE = '.$armaybe.'
OTHERLDFLAGS = '.$ld_opt.$otherldflags.'
INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
INST_DYNAMIC_FIX = '.$ld_fix.'
$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP)
');
if ($armaybe ne ':'){
$ldfrom = 'tmp$(LIB_EXT)';
push(@m,' $(ARMAYBE) cr '.$ldfrom.' $(OBJECT)'."\n");
push(@m,' $(RANLIB) '."$ldfrom\n");
}
$ldfrom = "-all $ldfrom -none" if $Is{OSF};
# The IRIX linker doesn't use LD_RUN_PATH
my $ldrun = $Is{IRIX} && $self->{LD_RUN_PATH} ?
qq{-rpath "$self->{LD_RUN_PATH}"} : '';
# For example in AIX the shared objects/libraries from previous builds
# linger quite a while in the shared dynalinker cache even when nobody
# is using them. This is painful if one for instance tries to restart
# a failed build because the link command will fail unnecessarily 'cos
# the shared object/library is 'busy'.
push(@m,' $(RM_F) $@
');
my $libs = '$(LDLOADLIBS)';
if (($Is{NetBSD} || $Is{Interix}) && $Config{'useshrplib'} eq 'true') {
# Use nothing on static perl platforms, and to the flags needed
# to link against the shared libperl library on shared perl
# platforms. We peek at lddlflags to see if we need -Wl,-R
# or -R to add paths to the run-time library search path.
if ($Config{'lddlflags'} =~ /-Wl,-R/) {
$libs .= ' -L$(PERL_INC) -Wl,-R$(INSTALLARCHLIB)/CORE -Wl,-R$(PERL_ARCHLIB)/CORE -lperl';
} elsif ($Config{'lddlflags'} =~ /-R/) {
$libs .= ' -L$(PERL_INC) -R$(INSTALLARCHLIB)/CORE -R$(PERL_ARCHLIB)/CORE -lperl';
}
}
my $ld_run_path_shell = "";
if ($self->{LD_RUN_PATH} ne "") {
$ld_run_path_shell = 'LD_RUN_PATH="$(LD_RUN_PATH)" ';
}
push @m, sprintf <<'MAKE', $ld_run_path_shell, $ldrun, $ldfrom, $libs;
%s$(LD) %s $(LDDLFLAGS) %s $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) \
$(PERL_ARCHIVE) %s $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) \
$(INST_DYNAMIC_FIX)
MAKE
push @m, <<'MAKE';
$(CHMOD) $(PERM_RWX) $@
MAKE
return join('',@m);
}
=item exescan
Deprecated method. Use libscan instead.
=cut
sub exescan {
my($self,$path) = @_;
$path;
}
=item extliblist
Called by init_others, and calls ext ExtUtils::Liblist. See
L<ExtUtils::Liblist> for details.
=cut
sub extliblist {
my($self,$libs) = @_;
require ExtUtils::Liblist;
$self->ext($libs, $Verbose);
}
=item find_perl
Finds the executables PERL and FULLPERL
=cut
sub find_perl {
my($self, $ver, $names, $dirs, $trace) = @_;
if ($trace >= 2){
print "Looking for perl $ver by these names:
@$names
in these dirs:
@$dirs
";
}
my $stderr_duped = 0;
local *STDERR_COPY;
unless ($Is{BSD}) {
# >& and lexical filehandles together give 5.6.2 indigestion
if( open(STDERR_COPY, '>&STDERR') ) { ## no critic
$stderr_duped = 1;
}
else {
warn <<WARNING;
find_perl() can't dup STDERR: $!
You might see some garbage while we search for Perl
WARNING
}
}
foreach my $name (@$names){
foreach my $dir (@$dirs){
next unless defined $dir; # $self->{PERL_SRC} may be undefined
my ($abs, $val);
if ($self->file_name_is_absolute($name)) { # /foo/bar
$abs = $name;
} elsif ($self->canonpath($name) eq
$self->canonpath(basename($name))) { # foo
$abs = $self->catfile($dir, $name);
} else { # foo/bar
$abs = $self->catfile($Curdir, $name);
}
print "Checking $abs\n" if ($trace >= 2);
next unless $self->maybe_command($abs);
print "Executing $abs\n" if ($trace >= 2);
my $version_check = qq{$abs -le "require $ver; print qq{VER_OK}"};
$version_check = "$Config{run} $version_check"
if defined $Config{run} and length $Config{run};
# To avoid using the unportable 2>&1 to suppress STDERR,
# we close it before running the command.
# However, thanks to a thread library bug in many BSDs
# ( http://www.freebsd.org/cgi/query-pr.cgi?pr=51535 )
# we cannot use the fancier more portable way in here
# but instead need to use the traditional 2>&1 construct.
if ($Is{BSD}) {
$val = `$version_check 2>&1`;
} else {
close STDERR if $stderr_duped;
$val = `$version_check`;
# 5.6.2's 3-arg open doesn't work with >&
open STDERR, ">&STDERR_COPY" ## no critic
if $stderr_duped;
}
if ($val =~ /^VER_OK/m) {
print "Using PERL=$abs\n" if $trace;
return $abs;
} elsif ($trace >= 2) {
print "Result: '$val' ".($? >> 8)."\n";
}
}
}
print STDOUT "Unable to find a perl $ver (by these names: @$names, in these dirs: @$dirs)\n";
0; # false and not empty
}
=item fixin
$mm->fixin(@files);
Inserts the sharpbang or equivalent magic number to a set of @files.
=cut
sub fixin { # stolen from the pink Camel book, more or less
my ( $self, @files ) = @_;
for my $file (@files) {
my $file_new = "$file.new";
my $file_bak = "$file.bak";
open( my $fixin, '<', $file ) or croak "Can't process '$file': $!";
local $/ = "\n";
chomp( my $line = <$fixin> );
next unless $line =~ s/^\s*\#!\s*//; # Not a shbang file.
my $shb = $self->_fixin_replace_shebang( $file, $line );
next unless defined $shb;
open( my $fixout, ">", "$file_new" ) or do {
warn "Can't create new $file: $!\n";
next;
};
# Print out the new #! line (or equivalent).
local $\;
local $/;
print $fixout $shb, <$fixin>;
close $fixin;
close $fixout;
chmod 0666, $file_bak;
unlink $file_bak;
unless ( _rename( $file, $file_bak ) ) {
warn "Can't rename $file to $file_bak: $!";
next;
}
unless ( _rename( $file_new, $file ) ) {
warn "Can't rename $file_new to $file: $!";
unless ( _rename( $file_bak, $file ) ) {
warn "Can't rename $file_bak back to $file either: $!";
warn "Leaving $file renamed as $file_bak\n";
}
next;
}
unlink $file_bak;
}
continue {
system("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
}
}
sub _rename {
my($old, $new) = @_;
foreach my $file ($old, $new) {
if( $Is{VMS} and basename($file) !~ /\./ ) {
# rename() in 5.8.0 on VMS will not rename a file if it
# does not contain a dot yet it returns success.
$file = "$file.";
}
}
return rename($old, $new);
}
sub _fixin_replace_shebang {
my ( $self, $file, $line ) = @_;
# Now figure out the interpreter name.
my ( $cmd, $arg ) = split ' ', $line, 2;
$cmd =~ s!^.*/!!;
# Now look (in reverse) for interpreter in absolute PATH (unless perl).
my $interpreter;
if ( $cmd =~ m{^perl(?:\z|[^a-z])} ) {
if ( $Config{startperl} =~ m,^\#!.*/perl, ) {
$interpreter = $Config{startperl};
$interpreter =~ s,^\#!,,;
}
else {
$interpreter = $Config{perlpath};
}
}
else {
my (@absdirs)
= reverse grep { $self->file_name_is_absolute($_) } $self->path;
$interpreter = '';
foreach my $dir (@absdirs) {
if ( $self->maybe_command($cmd) ) {
warn "Ignoring $interpreter in $file\n"
if $Verbose && $interpreter;
$interpreter = $self->catfile( $dir, $cmd );
}
}
}
# Figure out how to invoke interpreter on this machine.
my ($does_shbang) = $Config{'sharpbang'} =~ /^\s*\#\!/;
my ($shb) = "";
if ($interpreter) {
print STDOUT "Changing sharpbang in $file to $interpreter"
if $Verbose;
# this is probably value-free on DOSISH platforms
if ($does_shbang) {
$shb .= "$Config{'sharpbang'}$interpreter";
$shb .= ' ' . $arg if defined $arg;
$shb .= "\n";
}
$shb .= qq{
eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}'
if 0; # not running under some shell
} unless $Is{Win32}; # this won't work on win32, so don't
}
else {
warn "Can't find $cmd in PATH, $file unchanged"
if $Verbose;
return undef;
}
return $shb
}
=item force (o)
Writes an empty FORCE: target.
=cut
sub force {
my($self) = shift;
'# Phony target to force checking subdirectories.
FORCE :
$(NOECHO) $(NOOP)
';
}
=item guess_name
Guess the name of this package by examining the working directory's
name. MakeMaker calls this only if the developer has not supplied a
NAME attribute.
=cut
# ';
sub guess_name {
my($self) = @_;
use Cwd 'cwd';
my $name = basename(cwd());
$name =~ s|[\-_][\d\.\-]+\z||; # this is new with MM 5.00, we
# strip minus or underline
# followed by a float or some such
print "Warning: Guessing NAME [$name] from current directory name.\n";
$name;
}
=item has_link_code
Returns true if C, XS, MYEXTLIB or similar objects exist within this
object that need a compiler. Does not descend into subdirectories as
needs_linking() does.
=cut
sub has_link_code {
my($self) = shift;
return $self->{HAS_LINK_CODE} if defined $self->{HAS_LINK_CODE};
if ($self->{OBJECT} or @{$self->{C} || []} or $self->{MYEXTLIB}){
$self->{HAS_LINK_CODE} = 1;
return 1;
}
return $self->{HAS_LINK_CODE} = 0;
}
=item init_dirscan
Scans the directory structure and initializes DIR, XS, XS_FILES,
C, C_FILES, O_FILES, H, H_FILES, PL_FILES, EXE_FILES.
Called by init_main.
=cut
sub init_dirscan { # --- File and Directory Lists (.xs .pm .pod etc)
my($self) = @_;
my(%dir, %xs, %c, %h, %pl_files, %pm);
my %ignore = map {( $_ => 1 )} qw(Makefile.PL Build.PL test.pl t);
# ignore the distdir
$Is{VMS} ? $ignore{"$self->{DISTVNAME}.dir"} = 1
: $ignore{$self->{DISTVNAME}} = 1;
@ignore{map lc, keys %ignore} = values %ignore if $Is{VMS};
foreach my $name ($self->lsdir($Curdir)){
next if $name =~ /\#/;
next if $name eq $Curdir or $name eq $Updir or $ignore{$name};
next unless $self->libscan($name);
if (-d $name){
next if -l $name; # We do not support symlinks at all
next if $self->{NORECURS};
$dir{$name} = $name if (-f $self->catfile($name,"Makefile.PL"));
} elsif ($name =~ /\.xs\z/){
my($c); ($c = $name) =~ s/\.xs\z/.c/;
$xs{$name} = $c;
$c{$c} = 1;
} elsif ($name =~ /\.c(pp|xx|c)?\z/i){ # .c .C .cpp .cxx .cc
$c{$name} = 1
unless $name =~ m/perlmain\.c/; # See MAP_TARGET
} elsif ($name =~ /\.h\z/i){
$h{$name} = 1;
} elsif ($name =~ /\.PL\z/) {
($pl_files{$name} = $name) =~ s/\.PL\z// ;
} elsif (($Is{VMS} || $Is{Dos}) && $name =~ /[._]pl$/i) {
# case-insensitive filesystem, one dot per name, so foo.h.PL
# under Unix appears as foo.h_pl under VMS or fooh.pl on Dos
local($/); open(my $pl, '<', $name); my $txt = <$pl>; close $pl;
if ($txt =~ /Extracting \S+ \(with variable substitutions/) {
($pl_files{$name} = $name) =~ s/[._]pl\z//i ;
}
else {
$pm{$name} = $self->catfile($self->{INST_LIBDIR},$name);
}
} elsif ($name =~ /\.(p[ml]|pod)\z/){
$pm{$name} = $self->catfile($self->{INST_LIBDIR},$name);
}
}
$self->{PL_FILES} ||= \%pl_files;
$self->{DIR} ||= [sort keys %dir];
$self->{XS} ||= \%xs;
$self->{C} ||= [sort keys %c];
$self->{H} ||= [sort keys %h];
$self->{PM} ||= \%pm;
my @o_files = @{$self->{C}};
$self->{O_FILES} = [grep s/\.c(pp|xx|c)?\z/$self->{OBJ_EXT}/i, @o_files];
}
=item init_MANPODS
Determines if man pages should be generated and initializes MAN1PODS
and MAN3PODS as appropriate.
=cut
sub init_MANPODS {
my $self = shift;
# Set up names of manual pages to generate from pods
foreach my $man (qw(MAN1 MAN3)) {
if ( $self->{"${man}PODS"}
or $self->{"INSTALL${man}DIR"} =~ /^(none|\s*)$/
) {
$self->{"${man}PODS"} ||= {};
}
else {
my $init_method = "init_${man}PODS";
$self->$init_method();
}
}
}
sub _has_pod {
my($self, $file) = @_;
my($ispod)=0;
if (open( my $fh, '<', $file )) {
while (<$fh>) {
if (/^=(?:head\d+|item|pod)\b/) {
$ispod=1;
last;
}
}
close $fh;
} else {
# If it doesn't exist yet, we assume, it has pods in it
$ispod = 1;
}
return $ispod;
}
=item init_MAN1PODS
Initializes MAN1PODS from the list of EXE_FILES.
=cut
sub init_MAN1PODS {
my($self) = @_;
if ( exists $self->{EXE_FILES} ) {
foreach my $name (@{$self->{EXE_FILES}}) {
next unless $self->_has_pod($name);
$self->{MAN1PODS}->{$name} =
$self->catfile("\$(INST_MAN1DIR)",
basename($name).".\$(MAN1EXT)");
}
}
}
=item init_MAN3PODS
Initializes MAN3PODS from the list of PM files.
=cut
sub init_MAN3PODS {
my $self = shift;
my %manifypods = (); # we collect the keys first, i.e. the files
# we have to convert to pod
foreach my $name (keys %{$self->{PM}}) {
if ($name =~ /\.pod\z/ ) {
$manifypods{$name} = $self->{PM}{$name};
} elsif ($name =~ /\.p[ml]\z/ ) {
if( $self->_has_pod($name) ) {
$manifypods{$name} = $self->{PM}{$name};
}
}
}
my $parentlibs_re = join '|', @{$self->{PMLIBPARENTDIRS}};
# Remove "Configure.pm" and similar, if it's not the only pod listed
# To force inclusion, just name it "Configure.pod", or override
# MAN3PODS
foreach my $name (keys %manifypods) {
if ($self->{PERL_CORE} and $name =~ /(config|setup).*\.pm/is) {
delete $manifypods{$name};
next;
}
my($manpagename) = $name;
$manpagename =~ s/\.p(od|m|l)\z//;
# everything below lib is ok
unless($manpagename =~ s!^\W*($parentlibs_re)\W+!!s) {
$manpagename = $self->catfile(
split(/::/,$self->{PARENT_NAME}),$manpagename
);
}
$manpagename = $self->replace_manpage_separator($manpagename);
$self->{MAN3PODS}->{$name} =
$self->catfile("\$(INST_MAN3DIR)", "$manpagename.\$(MAN3EXT)");
}
}
=item init_PM
Initializes PMLIBDIRS and PM from PMLIBDIRS.
=cut
sub init_PM {
my $self = shift;
# Some larger extensions often wish to install a number of *.pm/pl
# files into the library in various locations.
# The attribute PMLIBDIRS holds an array reference which lists
# subdirectories which we should search for library files to
# install. PMLIBDIRS defaults to [ 'lib', $self->{BASEEXT} ]. We
# recursively search through the named directories (skipping any
# which don't exist or contain Makefile.PL files).
# For each *.pm or *.pl file found $self->libscan() is called with
# the default installation path in $_[1]. The return value of
# libscan defines the actual installation location. The default
# libscan function simply returns the path. The file is skipped
# if libscan returns false.
# The default installation location passed to libscan in $_[1] is:
#
# ./*.pm => $(INST_LIBDIR)/*.pm
# ./xyz/... => $(INST_LIBDIR)/xyz/...
# ./lib/... => $(INST_LIB)/...
#
# In this way the 'lib' directory is seen as the root of the actual
# perl library whereas the others are relative to INST_LIBDIR
# (which includes PARENT_NAME). This is a subtle distinction but one
# that's important for nested modules.
unless( $self->{PMLIBDIRS} ) {
if( $Is{VMS} ) {
# Avoid logical name vs directory collisions
$self->{PMLIBDIRS} = ['./lib', "./$self->{BASEEXT}"];
}
else {
$self->{PMLIBDIRS} = ['lib', $self->{BASEEXT}];
}
}
#only existing directories that aren't in $dir are allowed
# Avoid $_ wherever possible:
# @{$self->{PMLIBDIRS}} = grep -d && !$dir{$_}, @{$self->{PMLIBDIRS}};
my (@pmlibdirs) = @{$self->{PMLIBDIRS}};
@{$self->{PMLIBDIRS}} = ();
my %dir = map { ($_ => $_) } @{$self->{DIR}};
foreach my $pmlibdir (@pmlibdirs) {
-d $pmlibdir && !$dir{$pmlibdir} && push @{$self->{PMLIBDIRS}}, $pmlibdir;
}
unless( $self->{PMLIBPARENTDIRS} ) {
@{$self->{PMLIBPARENTDIRS}} = ('lib');
}
return if $self->{PM} and $self->{ARGS}{PM};
if (@{$self->{PMLIBDIRS}}){
print "Searching PMLIBDIRS: @{$self->{PMLIBDIRS}}\n"
if ($Verbose >= 2);
require File::Find;
File::Find::find(sub {
if (-d $_){
unless ($self->libscan($_)){
$File::Find::prune = 1;
}
return;
}
return if /\#/;
return if /~$/; # emacs temp files
return if /,v$/; # RCS files
return if m{\.swp$}; # vim swap files
my $path = $File::Find::name;
my $prefix = $self->{INST_LIBDIR};
my $striplibpath;
my $parentlibs_re = join '|', @{$self->{PMLIBPARENTDIRS}};
$prefix = $self->{INST_LIB}
if ($striplibpath = $path) =~ s{^(\W*)($parentlibs_re)\W}
{$1}i;
my($inst) = $self->catfile($prefix,$striplibpath);
local($_) = $inst; # for backwards compatibility
$inst = $self->libscan($inst);
print "libscan($path) => '$inst'\n" if ($Verbose >= 2);
return unless $inst;
$self->{PM}{$path} = $inst;
}, @{$self->{PMLIBDIRS}});
}
}
=item init_DIRFILESEP
Using / for Unix. Called by init_main.
=cut
sub init_DIRFILESEP {
my($self) = shift;
$self->{DIRFILESEP} = '/';
}
=item init_main
Initializes AR, AR_STATIC_ARGS, BASEEXT, CONFIG, DISTNAME, DLBASE,
EXE_EXT, FULLEXT, FULLPERL, FULLPERLRUN, FULLPERLRUNINST, INST_*,
INSTALL*, INSTALLDIRS, LIB_EXT, LIBPERL_A, MAP_TARGET, NAME,
OBJ_EXT, PARENT_NAME, PERL, PERL_ARCHLIB, PERL_INC, PERL_LIB,
PERL_SRC, PERLRUN, PERLRUNINST, PREFIX, VERSION,
VERSION_SYM, XS_VERSION.
=cut
sub init_main {
my($self) = @_;
# --- Initialize Module Name and Paths
# NAME = Foo::Bar::Oracle
# FULLEXT = Foo/Bar/Oracle
# BASEEXT = Oracle
# PARENT_NAME = Foo::Bar
### Only UNIX:
### ($self->{FULLEXT} =
### $self->{NAME}) =~ s!::!/!g ; #eg. BSD/Foo/Socket
$self->{FULLEXT} = $self->catdir(split /::/, $self->{NAME});
# Copied from DynaLoader:
my(@modparts) = split(/::/,$self->{NAME});
my($modfname) = $modparts[-1];
# Some systems have restrictions on files names for DLL's etc.
# mod2fname returns appropriate file base name (typically truncated)
# It may also edit @modparts if required.
if (defined &DynaLoader::mod2fname) {
$modfname = &DynaLoader::mod2fname(\@modparts);
}
($self->{PARENT_NAME}, $self->{BASEEXT}) = $self->{NAME} =~ m!(?:([\w:]+)::)?(\w+)\z! ;
$self->{PARENT_NAME} ||= '';
if (defined &DynaLoader::mod2fname) {
# As of 5.001m, dl_os2 appends '_'
$self->{DLBASE} = $modfname;
} else {
$self->{DLBASE} = '$(BASEEXT)';
}
# --- Initialize PERL_LIB, PERL_SRC
# *Real* information: where did we get these two from? ...
my $inc_config_dir = dirname($INC{'Config.pm'});
my $inc_carp_dir = dirname($INC{'Carp.pm'});
unless ($self->{PERL_SRC}){
foreach my $dir_count (1..8) { # 8 is the VMS limit for nesting
my $dir = $self->catdir(($Updir) x $dir_count);
if (-f $self->catfile($dir,"config_h.SH") &&
-f $self->catfile($dir,"perl.h") &&
-f $self->catfile($dir,"lib","strict.pm")
) {
$self->{PERL_SRC}=$dir ;
last;
}
}
}
warn "PERL_CORE is set but I can't find your PERL_SRC!\n" if
$self->{PERL_CORE} and !$self->{PERL_SRC};
if ($self->{PERL_SRC}){
$self->{PERL_LIB} ||= $self->catdir("$self->{PERL_SRC}","lib");
if (defined $Cross::platform) {
$self->{PERL_ARCHLIB} =
$self->catdir("$self->{PERL_SRC}","xlib",$Cross::platform);
$self->{PERL_INC} =
$self->catdir("$self->{PERL_SRC}","xlib",$Cross::platform,
$Is{Win32}?("CORE"):());
}
else {
$self->{PERL_ARCHLIB} = $self->{PERL_LIB};
$self->{PERL_INC} = ($Is{Win32}) ?
$self->catdir($self->{PERL_LIB},"CORE") : $self->{PERL_SRC};
}
# catch a situation that has occurred a few times in the past:
unless (
-s $self->catfile($self->{PERL_SRC},'cflags')
or
$Is{VMS}
&&
-s $self->catfile($self->{PERL_SRC},'vmsish.h')
or
$Is{Win32}
){
warn qq{
You cannot build extensions below the perl source tree after executing
a 'make clean' in the perl source tree.
To rebuild extensions distributed with the perl source you should
simply Configure (to include those extensions) and then build perl as
normal. After installing perl the source tree can be deleted. It is
not needed for building extensions by running 'perl Makefile.PL'
usually without extra arguments.
It is recommended that you unpack and build additional extensions away
from the perl source tree.
};
}
} else {
# we should also consider $ENV{PERL5LIB} here
my $old = $self->{PERL_LIB} || $self->{PERL_ARCHLIB} || $self->{PERL_INC};
$self->{PERL_LIB} ||= $Config{privlibexp};
$self->{PERL_ARCHLIB} ||= $Config{archlibexp};
$self->{PERL_INC} = $self->catdir("$self->{PERL_ARCHLIB}","CORE"); # wild guess for now
my $perl_h;
if (not -f ($perl_h = $self->catfile($self->{PERL_INC},"perl.h"))
and not $old){
# Maybe somebody tries to build an extension with an
# uninstalled Perl outside of Perl build tree
my $lib;
for my $dir (@INC) {
$lib = $dir, last if -e $self->catfile($dir, "Config.pm");
}
if ($lib) {
# Win32 puts its header files in /perl/src/lib/CORE.
# Unix leaves them in /perl/src.
my $inc = $Is{Win32} ? $self->catdir($lib, "CORE" )
: dirname $lib;
if (-e $self->catfile($inc, "perl.h")) {
$self->{PERL_LIB} = $lib;
$self->{PERL_ARCHLIB} = $lib;
$self->{PERL_INC} = $inc;
$self->{UNINSTALLED_PERL} = 1;
print STDOUT <<EOP;
... Detected uninstalled Perl. Trying to continue.
EOP
}
}
}
}
# We get SITELIBEXP and SITEARCHEXP directly via
# Get_from_Config. When we are running standard modules, these
# won't matter, we will set INSTALLDIRS to "perl". Otherwise we
# set it to "site". I prefer that INSTALLDIRS be set from outside
# MakeMaker.
$self->{INSTALLDIRS} ||= "site";
$self->{MAN1EXT} ||= $Config{man1ext};
$self->{MAN3EXT} ||= $Config{man3ext};
# Get some stuff out of %Config if we haven't yet done so
print STDOUT "CONFIG must be an array ref\n"
if ($self->{CONFIG} and ref $self->{CONFIG} ne 'ARRAY');
$self->{CONFIG} = [] unless (ref $self->{CONFIG});
push(@{$self->{CONFIG}}, @ExtUtils::MakeMaker::Get_from_Config);
push(@{$self->{CONFIG}}, 'shellflags') if $Config{shellflags};
my(%once_only);
foreach my $m (@{$self->{CONFIG}}){
next if $once_only{$m};
print STDOUT "CONFIG key '$m' does not exist in Config.pm\n"
unless exists $Config{$m};
$self->{uc $m} ||= $Config{$m};
$once_only{$m} = 1;
}
# This is too dangerous:
# if ($^O eq "next") {
# $self->{AR} = "libtool";
# $self->{AR_STATIC_ARGS} = "-o";
# }
# But I leave it as a placeholder
$self->{AR_STATIC_ARGS} ||= "cr";
# These should never be needed
$self->{OBJ_EXT} ||= '.o';
$self->{LIB_EXT} ||= '.a';
$self->{MAP_TARGET} ||= "perl";
$self->{LIBPERL_A} ||= "libperl$self->{LIB_EXT}";
# make a simple check if we find strict
warn "Warning: PERL_LIB ($self->{PERL_LIB}) seems not to be a perl library directory
(strict.pm not found)"
unless -f $self->catfile("$self->{PERL_LIB}","strict.pm") ||
$self->{NAME} eq "ExtUtils::MakeMaker";
}
=item init_others
Initializes EXTRALIBS, BSLOADLIBS, LDLOADLIBS, LIBS, LD_RUN_PATH, LD,
OBJECT, BOOTDEP, PERLMAINCC, LDFROM, LINKTYPE, SHELL, NOOP,
FIRST_MAKEFILE, MAKEFILE_OLD, NOECHO, RM_F, RM_RF, TEST_F,
TOUCH, CP, MV, CHMOD, UMASK_NULL, ECHO, ECHO_N
=cut
sub init_others { # --- Initialize Other Attributes
my($self) = shift;
$self->{ECHO} ||= 'echo';
$self->{ECHO_N} ||= 'echo -n';
$self->{RM_F} ||= "rm -f";
$self->{RM_RF} ||= "rm -rf";
$self->{TOUCH} ||= "touch";
$self->{TEST_F} ||= "test -f";
$self->{CP} ||= "cp";
$self->{MV} ||= "mv";
$self->{CHMOD} ||= "chmod";
$self->{FALSE} ||= 'false';
$self->{TRUE} ||= 'true';
$self->{LD} ||= 'ld';
$self->SUPER::init_others(@_);
# After SUPER::init_others so $Config{shell} has a
# chance to get set.
$self->{SHELL} ||= '/bin/sh';
return 1;
}
=item init_linker
Unix has no need of special linker flags.
=cut
sub init_linker {
my($self) = shift;
$self->{PERL_ARCHIVE} ||= '';
$self->{PERL_ARCHIVE_AFTER} ||= '';
$self->{EXPORT_LIST} ||= '';
}
=begin _protected
=item init_lib2arch
$mm->init_lib2arch
=end _protected
=cut
sub init_lib2arch {
my($self) = shift;
# The user who requests an installation directory explicitly
# should not have to tell us an architecture installation directory
# as well. We look if a directory exists that is named after the
# architecture. If not we take it as a sign that it should be the
# same as the requested installation directory. Otherwise we take
# the found one.
for my $libpair ({l=>"privlib", a=>"archlib"},
{l=>"sitelib", a=>"sitearch"},
{l=>"vendorlib", a=>"vendorarch"},
)
{
my $lib = "install$libpair->{l}";
my $Lib = uc $lib;
my $Arch = uc "install$libpair->{a}";
if( $self->{$Lib} && ! $self->{$Arch} ){
my($ilib) = $Config{$lib};
$self->prefixify($Arch,$ilib,$self->{$Lib});
unless (-d $self->{$Arch}) {
print STDOUT "Directory $self->{$Arch} not found\n"
if $Verbose;
$self->{$Arch} = $self->{$Lib};
}
print STDOUT "Defaulting $Arch to $self->{$Arch}\n" if $Verbose;
}
}
}
=item init_PERL
$mm->init_PERL;
Called by init_main. Sets up ABSPERL, PERL, FULLPERL and all the
*PERLRUN* permutations.
PERL is allowed to be miniperl
FULLPERL must be a complete perl
ABSPERL is PERL converted to an absolute path
*PERLRUN contains everything necessary to run perl, find it's
libraries, etc...
*PERLRUNINST is *PERLRUN + everything necessary to find the
modules being built.
=cut
sub init_PERL {
my($self) = shift;
my @defpath = ();
foreach my $component ($self->{PERL_SRC}, $self->path(),
$Config{binexp})
{
push @defpath, $component if defined $component;
}
# Build up a set of file names (not command names).
my $thisperl = $self->canonpath($^X);
$thisperl .= $Config{exe_ext} unless
# VMS might have a file version # at the end
$Is{VMS} ? $thisperl =~ m/$Config{exe_ext}(;\d+)?$/i
: $thisperl =~ m/$Config{exe_ext}$/i;
# We need a relative path to perl when in the core.
$thisperl = $self->abs2rel($thisperl) if $self->{PERL_CORE};
my @perls = ($thisperl);
push @perls, map { "$_$Config{exe_ext}" }
('perl', 'perl5', "perl$Config{version}");
# miniperl has priority over all but the cannonical perl when in the
# core. Otherwise its a last resort.
my $miniperl = "miniperl$Config{exe_ext}";
if( $self->{PERL_CORE} ) {
splice @perls, 1, 0, $miniperl;
}
else {
push @perls, $miniperl;
}
$self->{PERL} ||=
$self->find_perl(5.0, \@perls, \@defpath, $Verbose );
# don't check if perl is executable, maybe they have decided to
# supply switches with perl
# When built for debugging, VMS doesn't create perl.exe but ndbgperl.exe.
my $perl_name = 'perl';
$perl_name = 'ndbgperl' if $Is{VMS} &&
defined $Config{usevmsdebug} && $Config{usevmsdebug} eq 'define';
# XXX This logic is flawed. If "miniperl" is anywhere in the path
# it will get confused. It should be fixed to work only on the filename.
# Define 'FULLPERL' to be a non-miniperl (used in test: target)
($self->{FULLPERL} = $self->{PERL}) =~ s/miniperl/$perl_name/i
unless $self->{FULLPERL};
# Little hack to get around VMS's find_perl putting "MCR" in front
# sometimes.
$self->{ABSPERL} = $self->{PERL};
my $has_mcr = $self->{ABSPERL} =~ s/^MCR\s*//;
if( $self->file_name_is_absolute($self->{ABSPERL}) ) {
$self->{ABSPERL} = '$(PERL)';
}
else {
$self->{ABSPERL} = $self->rel2abs($self->{ABSPERL});
# Quote the perl command if it contains whitespace
$self->{ABSPERL} = $self->quote_literal($self->{ABSPERL})
if $self->{ABSPERL} =~ /\s/;
$self->{ABSPERL} = 'MCR '.$self->{ABSPERL} if $has_mcr;
}
# Are we building the core?
$self->{PERL_CORE} = $ENV{PERL_CORE} unless exists $self->{PERL_CORE};
$self->{PERL_CORE} = 0 unless defined $self->{PERL_CORE};
# How do we run perl?
foreach my $perl (qw(PERL FULLPERL ABSPERL)) {
my $run = $perl.'RUN';
$self->{$run} = "\$($perl)";
# Make sure perl can find itself before it's installed.
$self->{$run} .= q{ "-I$(PERL_LIB)" "-I$(PERL_ARCHLIB)"}
if $self->{UNINSTALLED_PERL} || $self->{PERL_CORE};
$self->{$perl.'RUNINST'} =
sprintf q{$(%sRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"}, $perl;
}
return 1;
}
=item init_platform
=item platform_constants
Add MM_Unix_VERSION.
=cut
sub init_platform {
my($self) = shift;
$self->{MM_Unix_VERSION} = $VERSION;
$self->{PERL_MALLOC_DEF} = '-DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc '.
'-Dfree=Perl_mfree -Drealloc=Perl_realloc '.
'-Dcalloc=Perl_calloc';
}
sub platform_constants {
my($self) = shift;
my $make_frag = '';
foreach my $macro (qw(MM_Unix_VERSION PERL_MALLOC_DEF))
{
next unless defined $self->{$macro};
$make_frag .= "$macro = $self->{$macro}\n";
}
return $make_frag;
}
=item init_PERM
$mm->init_PERM
Called by init_main. Initializes PERL_*
=cut
sub init_PERM {
my($self) = shift;
$self->{PERM_DIR} = 755 unless defined $self->{PERM_DIR};
$self->{PERM_RW} = 644 unless defined $self->{PERM_RW};
$self->{PERM_RWX} = 755 unless defined $self->{PERM_RWX};
return 1;
}
=item init_xs
$mm->init_xs
Sets up macros having to do with XS code. Currently just INST_STATIC,
INST_DYNAMIC and INST_BOOT.
=cut
sub init_xs {
my $self = shift;
if ($self->has_link_code()) {
$self->{INST_STATIC} =
$self->catfile('$(INST_ARCHAUTODIR)', '$(BASEEXT)$(LIB_EXT)');
$self->{INST_DYNAMIC} =
$self->catfile('$(INST_ARCHAUTODIR)', '$(DLBASE).$(DLEXT)');
$self->{INST_BOOT} =
$self->catfile('$(INST_ARCHAUTODIR)', '$(BASEEXT).bs');
} else {
$self->{INST_STATIC} = '';
$self->{INST_DYNAMIC} = '';
$self->{INST_BOOT} = '';
}
}
=item install (o)
Defines the install target.
=cut
sub install {
my($self, %attribs) = @_;
my(@m);
push @m, q{
install :: pure_install doc_install
$(NOECHO) $(NOOP)
install_perl :: pure_perl_install doc_perl_install
$(NOECHO) $(NOOP)
install_site :: pure_site_install doc_site_install
$(NOECHO) $(NOOP)
install_vendor :: pure_vendor_install doc_vendor_install
$(NOECHO) $(NOOP)
pure_install :: pure_$(INSTALLDIRS)_install
$(NOECHO) $(NOOP)
doc_install :: doc_$(INSTALLDIRS)_install
$(NOECHO) $(NOOP)
pure__install : pure_site_install
$(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
doc__install : doc_site_install
$(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
pure_perl_install :: all
$(NOECHO) $(MOD_INSTALL) \
read }.$self->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q{ \
write }.$self->catfile('$(DESTINSTALLARCHLIB)','auto','$(FULLEXT)','.packlist').q{ \
$(INST_LIB) $(DESTINSTALLPRIVLIB) \
$(INST_ARCHLIB) $(DESTINSTALLARCHLIB) \
$(INST_BIN) $(DESTINSTALLBIN) \
$(INST_SCRIPT) $(DESTINSTALLSCRIPT) \
$(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) \
$(INST_MAN3DIR) $(DESTINSTALLMAN3DIR)
$(NOECHO) $(WARN_IF_OLD_PACKLIST) \
}.$self->catdir('$(SITEARCHEXP)','auto','$(FULLEXT)').q{
pure_site_install :: all
$(NOECHO) $(MOD_INSTALL) \
read }.$self->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q{ \
write }.$self->catfile('$(DESTINSTALLSITEARCH)','auto','$(FULLEXT)','.packlist').q{ \
$(INST_LIB) $(DESTINSTALLSITELIB) \
$(INST_ARCHLIB) $(DESTINSTALLSITEARCH) \
$(INST_BIN) $(DESTINSTALLSITEBIN) \
$(INST_SCRIPT) $(DESTINSTALLSITESCRIPT) \
$(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) \
$(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR)
$(NOECHO) $(WARN_IF_OLD_PACKLIST) \
}.$self->catdir('$(PERL_ARCHLIB)','auto','$(FULLEXT)').q{
pure_vendor_install :: all
$(NOECHO) $(MOD_INSTALL) \
read }.$self->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').q{ \
write }.$self->catfile('$(DESTINSTALLVENDORARCH)','auto','$(FULLEXT)','.packlist').q{ \
$(INST_LIB) $(DESTINSTALLVENDORLIB) \
$(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) \
$(INST_BIN) $(DESTINSTALLVENDORBIN) \
$(INST_SCRIPT) $(DESTINSTALLVENDORSCRIPT) \
$(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) \
$(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR)
doc_perl_install :: all
$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
-$(NOECHO) $(DOC_INSTALL) \
"Module" "$(NAME)" \
"installed into" "$(INSTALLPRIVLIB)" \
LINKTYPE "$(LINKTYPE)" \
VERSION "$(VERSION)" \
EXE_FILES "$(EXE_FILES)" \
>> }.$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q{
doc_site_install :: all
$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
-$(NOECHO) $(DOC_INSTALL) \
"Module" "$(NAME)" \
"installed into" "$(INSTALLSITELIB)" \
LINKTYPE "$(LINKTYPE)" \
VERSION "$(VERSION)" \
EXE_FILES "$(EXE_FILES)" \
>> }.$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q{
doc_vendor_install :: all
$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
-$(NOECHO) $(DOC_INSTALL) \
"Module" "$(NAME)" \
"installed into" "$(INSTALLVENDORLIB)" \
LINKTYPE "$(LINKTYPE)" \
VERSION "$(VERSION)" \
EXE_FILES "$(EXE_FILES)" \
>> }.$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q{
};
push @m, q{
uninstall :: uninstall_from_$(INSTALLDIRS)dirs
$(NOECHO) $(NOOP)
uninstall_from_perldirs ::
$(NOECHO) $(UNINSTALL) }.$self->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q{
uninstall_from_sitedirs ::
$(NOECHO) $(UNINSTALL) }.$self->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q{
uninstall_from_vendordirs ::
$(NOECHO) $(UNINSTALL) }.$self->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').q{
};
join("",@m);
}
=item installbin (o)
Defines targets to make and to install EXE_FILES.
=cut
sub installbin {
my($self) = shift;
return "" unless $self->{EXE_FILES} && ref $self->{EXE_FILES} eq "ARRAY";
my @exefiles = @{$self->{EXE_FILES}};
return "" unless @exefiles;
@exefiles = map vmsify($_), @exefiles if $Is{VMS};
my %fromto;
for my $from (@exefiles) {
my($path)= $self->catfile('$(INST_SCRIPT)', basename($from));
local($_) = $path; # for backwards compatibility
my $to = $self->libscan($path);
print "libscan($from) => '$to'\n" if ($Verbose >=2);
$to = vmsify($to) if $Is{VMS};
$fromto{$from} = $to;
}
my @to = values %fromto;
my @m;
push(@m, qq{
EXE_FILES = @exefiles
pure_all :: @to
\$(NOECHO) \$(NOOP)
realclean ::
});
# realclean can get rather large.
push @m, map "\t$_\n", $self->split_command('$(RM_F)', @to);
push @m, "\n";
# A target for each exe file.
while (my($from,$to) = each %fromto) {
last unless defined $from;
push @m, sprintf <<'MAKE', $to, $from, $to, $from, $to, $to, $to;
%s : %s $(FIRST_MAKEFILE) $(INST_SCRIPT)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists
$(NOECHO) $(RM_F) %s
$(CP) %s %s
$(FIXIN) %s
-$(NOECHO) $(CHMOD) $(PERM_RWX) %s
MAKE
}
join "", @m;
}
=item linkext (o)
Defines the linkext target which in turn defines the LINKTYPE.
=cut
sub linkext {
my($self, %attribs) = @_;
# LINKTYPE => static or dynamic or ''
my($linktype) = defined $attribs{LINKTYPE} ?
$attribs{LINKTYPE} : '$(LINKTYPE)';
"
linkext :: $linktype
\$(NOECHO) \$(NOOP)
";
}
=item lsdir
Takes as arguments a directory name and a regular expression. Returns
all entries in the directory that match the regular expression.
=cut
sub lsdir {
my($self) = shift;
my($dir, $regex) = @_;
my(@ls);
my $dh = new DirHandle;
$dh->open($dir || ".") or return ();
@ls = $dh->read;
$dh->close;
@ls = grep(/$regex/, @ls) if $regex;
@ls;
}
=item macro (o)
Simple subroutine to insert the macros defined by the macro attribute
into the Makefile.
=cut
sub macro {
my($self,%attribs) = @_;
my(@m,$key,$val);
while (($key,$val) = each %attribs){
last unless defined $key;
push @m, "$key = $val\n";
}
join "", @m;
}
=item makeaperl (o)
Called by staticmake. Defines how to write the Makefile to produce a
static new perl.
By default the Makefile produced includes all the static extensions in
the perl library. (Purified versions of library files, e.g.,
DynaLoader_pure_p1_c0_032.a are automatically ignored to avoid link errors.)
=cut
sub makeaperl {
my($self, %attribs) = @_;
my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmp, $libperl) =
@attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)};
my(@m);
push @m, "
# --- MakeMaker makeaperl section ---
MAP_TARGET = $target
FULLPERL = $self->{FULLPERL}
";
return join '', @m if $self->{PARENT};
my($dir) = join ":", @{$self->{DIR}};
unless ($self->{MAKEAPERL}) {
push @m, q{
$(MAP_TARGET) :: static $(MAKE_APERL_FILE)
$(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@
$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib
$(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET)
$(NOECHO) $(PERLRUNINST) \
Makefile.PL DIR=}, $dir, q{ \
MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
MAKEAPERL=1 NORECURS=1 CCCDLFLAGS=};
foreach (@ARGV){
if( /\s/ ){
s/=(.*)/='$1'/;
}
push @m, " \\\n\t\t$_";
}
# push @m, map( " \\\n\t\t$_", @ARGV );
push @m, "\n";
return join '', @m;
}
my($cccmd, $linkcmd, $lperl);
$cccmd = $self->const_cccmd($libperl);
$cccmd =~ s/^CCCMD\s*=\s*//;
$cccmd =~ s/\$\(INC\)/ "-I$self->{PERL_INC}" /;
$cccmd .= " $Config{cccdlflags}"
if ($Config{useshrplib} eq 'true');
$cccmd =~ s/\(CC\)/\(PERLMAINCC\)/;
# The front matter of the linkcommand...
$linkcmd = join ' ', "\$(CC)",
grep($_, @Config{qw(ldflags ccdlflags)});
$linkcmd =~ s/\s+/ /g;
$linkcmd =~ s,(perl\.exp),\$(PERL_INC)/$1,;
# Which *.a files could we make use of...
my %static;
require File::Find;
File::Find::find(sub {
return unless m/\Q$self->{LIB_EXT}\E$/;
# Skip perl's libraries.
return if m/^libperl/ or m/^perl\Q$self->{LIB_EXT}\E$/;
# Skip purified versions of libraries
# (e.g., DynaLoader_pure_p1_c0_032.a)
return if m/_pure_\w+_\w+_\w+\.\w+$/ and -f "$File::Find::dir/.pure";
if( exists $self->{INCLUDE_EXT} ){
my $found = 0;
(my $xx = $File::Find::name) =~ s,.*?/auto/,,s;
$xx =~ s,/?$_,,;
$xx =~ s,/,::,g;
# Throw away anything not explicitly marked for inclusion.
# DynaLoader is implied.
foreach my $incl ((@{$self->{INCLUDE_EXT}},'DynaLoader')){
if( $xx eq $incl ){
$found++;
last;
}
}
return unless $found;
}
elsif( exists $self->{EXCLUDE_EXT} ){
(my $xx = $File::Find::name) =~ s,.*?/auto/,,s;
$xx =~ s,/?$_,,;
$xx =~ s,/,::,g;
# Throw away anything explicitly marked for exclusion
foreach my $excl (@{$self->{EXCLUDE_EXT}}){
return if( $xx eq $excl );
}
}
# don't include the installed version of this extension. I
# leave this line here, although it is not necessary anymore:
# I patched minimod.PL instead, so that Miniperl.pm won't
# enclude duplicates
# Once the patch to minimod.PL is in the distribution, I can
# drop it
return if $File::Find::name =~ m:auto/$self->{FULLEXT}/$self->{BASEEXT}$self->{LIB_EXT}\z:;
use Cwd 'cwd';
$static{cwd() . "/" . $_}++;
}, grep( -d $_, @{$searchdirs || []}) );
# We trust that what has been handed in as argument, will be buildable
$static = [] unless $static;
@static{@{$static}} = (1) x @{$static};
$extra = [] unless $extra && ref $extra eq 'ARRAY';
for (sort keys %static) {
next unless /\Q$self->{LIB_EXT}\E\z/;
$_ = dirname($_) . "/extralibs.ld";
push @$extra, $_;
}
s/^(.*)/"-I$1"/ for @{$perlinc || []};
$target ||= "perl";
$tmp ||= ".";
# MAP_STATIC doesn't look into subdirs yet. Once "all" is made and we
# regenerate the Makefiles, MAP_STATIC and the dependencies for
# extralibs.all are computed correctly
push @m, "
MAP_LINKCMD = $linkcmd
MAP_PERLINC = @{$perlinc || []}
MAP_STATIC = ",
join(" \\\n\t", reverse sort keys %static), "
MAP_PRELIBS = $Config{perllibs} $Config{cryptlib}
";
if (defined $libperl) {
($lperl = $libperl) =~ s/\$\(A\)/$self->{LIB_EXT}/;
}
unless ($libperl && -f $lperl) { # Ilya's code...
my $dir = $self->{PERL_SRC} || "$self->{PERL_ARCHLIB}/CORE";
$dir = "$self->{PERL_ARCHLIB}/.." if $self->{UNINSTALLED_PERL};
$libperl ||= "libperl$self->{LIB_EXT}";
$libperl = "$dir/$libperl";
$lperl ||= "libperl$self->{LIB_EXT}";
$lperl = "$dir/$lperl";
if (! -f $libperl and ! -f $lperl) {
# We did not find a static libperl. Maybe there is a shared one?
if ($Is{SunOS}) {
$lperl = $libperl = "$dir/$Config{libperl}";
# SUNOS ld does not take the full path to a shared library
$libperl = '' if $Is{SunOS4};
}
}
print STDOUT "Warning: $libperl not found
If you're going to build a static perl binary, make sure perl is installed
otherwise ignore this warning\n"
unless (-f $lperl || defined($self->{PERL_SRC}));
}
# SUNOS ld does not take the full path to a shared library
my $llibperl = $libperl ? '$(MAP_LIBPERL)' : '-lperl';
push @m, "
MAP_LIBPERL = $libperl
LLIBPERL = $llibperl
";
push @m, '
$(INST_ARCHAUTODIR)/extralibs.all : $(INST_ARCHAUTODIR)$(DFSEP).exists '.join(" \\\n\t", @$extra).'
$(NOECHO) $(RM_F) $@
$(NOECHO) $(TOUCH) $@
';
foreach my $catfile (@$extra){
push @m, "\tcat $catfile >> \$\@\n";
}
push @m, "
\$(MAP_TARGET) :: $tmp/perlmain\$(OBJ_EXT) \$(MAP_LIBPERL) \$(MAP_STATIC) \$(INST_ARCHAUTODIR)/extralibs.all
\$(MAP_LINKCMD) -o \$\@ \$(OPTIMIZE) $tmp/perlmain\$(OBJ_EXT) \$(LDFROM) \$(MAP_STATIC) \$(LLIBPERL) `cat \$(INST_ARCHAUTODIR)/extralibs.all` \$(MAP_PRELIBS)
\$(NOECHO) \$(ECHO) 'To install the new \"\$(MAP_TARGET)\" binary, call'
\$(NOECHO) \$(ECHO) ' \$(MAKE) \$(USEMAKEFILE) $makefilename inst_perl MAP_TARGET=\$(MAP_TARGET)'
\$(NOECHO) \$(ECHO) 'To remove the intermediate files say'
\$(NOECHO) \$(ECHO) ' \$(MAKE) \$(USEMAKEFILE) $makefilename map_clean'
$tmp/perlmain\$(OBJ_EXT): $tmp/perlmain.c
";
push @m, "\t".$self->cd($tmp, qq[$cccmd "-I\$(PERL_INC)" perlmain.c])."\n";
push @m, qq{
$tmp/perlmain.c: $makefilename}, q{
$(NOECHO) $(ECHO) Writing $@
$(NOECHO) $(PERL) $(MAP_PERLINC) "-MExtUtils::Miniperl" \\
-e "writemain(grep s#.*/auto/##s, split(q| |, q|$(MAP_STATIC)|))" > $@t && $(MV) $@t $@
};
push @m, "\t", q{$(NOECHO) $(PERL) $(INSTALLSCRIPT)/fixpmain
} if (defined (&Dos::UseLFN) && Dos::UseLFN()==0);
push @m, q{
doc_inst_perl :
$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
-$(NOECHO) $(DOC_INSTALL) \
"Perl binary" "$(MAP_TARGET)" \
MAP_STATIC "$(MAP_STATIC)" \
MAP_EXTRA "`cat $(INST_ARCHAUTODIR)/extralibs.all`" \
MAP_LIBPERL "$(MAP_LIBPERL)" \
>> }.$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q{
};
push @m, q{
inst_perl : pure_inst_perl doc_inst_perl
pure_inst_perl : $(MAP_TARGET)
}.$self->{CP}.q{ $(MAP_TARGET) }.$self->catfile('$(DESTINSTALLBIN)','$(MAP_TARGET)').q{
clean :: map_clean
map_clean :
}.$self->{RM_F}.qq{ $tmp/perlmain\$(OBJ_EXT) $tmp/perlmain.c \$(MAP_TARGET) $makefilename \$(INST_ARCHAUTODIR)/extralibs.all
};
join '', @m;
}
=item makefile (o)
Defines how to rewrite the Makefile.
=cut
sub makefile {
my($self) = shift;
my $m;
# We do not know what target was originally specified so we
# must force a manual rerun to be sure. But as it should only
# happen very rarely it is not a significant problem.
$m = '
$(OBJECT) : $(FIRST_MAKEFILE)
' if $self->{OBJECT};
my $newer_than_target = $Is{VMS} ? '$(MMS$SOURCE_LIST)' : '$?';
my $mpl_args = join " ", map qq["$_"], @ARGV;
$m .= sprintf <<'MAKE_FRAG', $newer_than_target, $mpl_args;
# We take a very conservative approach here, but it's worth it.
# We move Makefile to Makefile.old here to avoid gnu make looping.
$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP)
$(NOECHO) $(ECHO) "Makefile out-of-date with respect to %s"
$(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..."
-$(NOECHO) $(RM_F) $(MAKEFILE_OLD)
-$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD)
- $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL)
$(PERLRUN) Makefile.PL %s
$(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <=="
$(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <=="
$(FALSE)
MAKE_FRAG
return $m;
}
=item maybe_command
Returns true, if the argument is likely to be a command.
=cut
sub maybe_command {
my($self,$file) = @_;
return $file if -x $file && ! -d $file;
return;
}
=item needs_linking (o)
Does this module need linking? Looks into subdirectory objects (see
also has_link_code())
=cut
sub needs_linking {
my($self) = shift;
my $caller = (caller(0))[3];
confess("needs_linking called too early") if
$caller =~ /^ExtUtils::MakeMaker::/;
return $self->{NEEDS_LINKING} if defined $self->{NEEDS_LINKING};
if ($self->has_link_code or $self->{MAKEAPERL}){
$self->{NEEDS_LINKING} = 1;
return 1;
}
foreach my $child (keys %{$self->{CHILDREN}}) {
if ($self->{CHILDREN}->{$child}->needs_linking) {
$self->{NEEDS_LINKING} = 1;
return 1;
}
}
return $self->{NEEDS_LINKING} = 0;
}
=item parse_abstract
parse a file and return what you think is the ABSTRACT
=cut
sub parse_abstract {
my($self,$parsefile) = @_;
my $result;
local $/ = "\n";
open(my $fh, '<', $parsefile) or die "Could not open '$parsefile': $!";
my $inpod = 0;
my $package = $self->{DISTNAME};
$package =~ s/-/::/g;
while (<$fh>) {
$inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod;
next if !$inpod;
chop;
next unless /^($package(?:\.pm)? \s+ -+ \s+)(.*)/x;
$result = $2;
last;
}
close $fh;
return $result;
}
=item parse_version
my $version = MM->parse_version($file);
Parse a $file and return what $VERSION is set to by the first assignment.
It will return the string "undef" if it can't figure out what $VERSION
is. $VERSION should be for all to see, so C<our $VERSION> or plain $VERSION
are okay, but C<my $VERSION> is not.
C<<package Foo VERSION>> is also checked for. The first version
declaration found is used, but this may change as it differs from how
Perl does it.
parse_version() will try to C<use version> before checking for
C<$VERSION> so the following will work.
$VERSION = qv(1.2.3);
=cut
sub parse_version {
my($self,$parsefile) = @_;
my $result;
local $/ = "\n";
local $_;
open(my $fh, '<', $parsefile) or die "Could not open '$parsefile': $!";
my $inpod = 0;
while (<$fh>) {
$inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod;
next if $inpod || /^\s*#/;
chop;
next if /^\s*(if|unless|elsif)/;
if ( m{^ \s* package \s+ \w[\w\:\']* \s+ (v?[0-9._]+) \s* ; }x ) {
local $^W = 0;
$result = $1;
}
elsif ( m{(?<!\\) ([\$*]) (([\w\:\']*) \bVERSION)\b .* =}x ) {
my $eval = qq{
package ExtUtils::MakeMaker::_version;
no strict;
BEGIN { eval {
# Ensure any version() routine which might have leaked
# into this package has been deleted. Interferes with
# version->import()
undef *version;
require version;
"version"->import;
} }
local $1$2;
\$$2=undef;
do {
$_
};
\$$2;
};
local $^W = 0;
$result = eval($eval); ## no critic
warn "Could not eval '$eval' in $parsefile: $@" if $@;
}
else {
next;
}
last if defined $result;
}
close $fh;
$result = "undef" unless defined $result;
return $result;
}
=item pasthru (o)
Defines the string that is passed to recursive make calls in
subdirectories.
=cut
sub pasthru {
my($self) = shift;
my(@m);
my(@pasthru);
my($sep) = $Is{VMS} ? ',' : '';
$sep .= "\\\n\t";
foreach my $key (qw(LIB LIBPERL_A LINKTYPE OPTIMIZE
PREFIX INSTALL_BASE)
)
{
next unless defined $self->{$key};
push @pasthru, "$key=\"\$($key)\"";
}
foreach my $key (qw(DEFINE INC)) {
next unless defined $self->{$key};
push @pasthru, "PASTHRU_$key=\"\$(PASTHRU_$key)\"";
}
push @m, "\nPASTHRU = ", join ($sep, @pasthru), "\n";
join "", @m;
}
=item perl_script
Takes one argument, a file name, and returns the file name, if the
argument is likely to be a perl script. On MM_Unix this is true for
any ordinary, readable file.
=cut
sub perl_script {
my($self,$file) = @_;
return $file if -r $file && -f _;
return;
}
=item perldepend (o)
Defines the dependency from all *.h files that come with the perl
distribution.
=cut
sub perldepend {
my($self) = shift;
my(@m);
my $make_config = $self->cd('$(PERL_SRC)', '$(MAKE) lib/Config.pm');
push @m, sprintf <<'MAKE_FRAG', $make_config if $self->{PERL_SRC};
# Check for unpropogated config.sh changes. Should never happen.
# We do NOT just update config.h because that is not sufficient.
# An out of date config.h is not fatal but complains loudly!
$(PERL_INC)/config.h: $(PERL_SRC)/config.sh
-$(NOECHO) $(ECHO) "Warning: $(PERL_INC)/config.h out of date with $(PERL_SRC)/config.sh"; $(FALSE)
$(PERL_ARCHLIB)/Config.pm: $(PERL_SRC)/config.sh
$(NOECHO) $(ECHO) "Warning: $(PERL_ARCHLIB)/Config.pm may be out of date with $(PERL_SRC)/config.sh"
%s
MAKE_FRAG
return join "", @m unless $self->needs_linking;
push @m, q{
PERL_HDRS = \
$(PERL_INC)/EXTERN.h \
$(PERL_INC)/INTERN.h \
$(PERL_INC)/XSUB.h \
$(PERL_INC)/av.h \
$(PERL_INC)/config.h \
$(PERL_INC)/cop.h \
$(PERL_INC)/cv.h \
$(PERL_INC)/dosish.h \
$(PERL_INC)/embed.h \
$(PERL_INC)/embedvar.h \
$(PERL_INC)/fakethr.h \
$(PERL_INC)/form.h \
$(PERL_INC)/gv.h \
$(PERL_INC)/handy.h \
$(PERL_INC)/hv.h \
$(PERL_INC)/intrpvar.h \
$(PERL_INC)/iperlsys.h \
$(PERL_INC)/keywords.h \
$(PERL_INC)/mg.h \
$(PERL_INC)/nostdio.h \
$(PERL_INC)/op.h \
$(PERL_INC)/opcode.h \
$(PERL_INC)/patchlevel.h \
$(PERL_INC)/perl.h \
$(PERL_INC)/perlio.h \
$(PERL_INC)/perlsdio.h \
$(PERL_INC)/perlsfio.h \
$(PERL_INC)/perlvars.h \
$(PERL_INC)/perly.h \
$(PERL_INC)/pp.h \
$(PERL_INC)/pp_proto.h \
$(PERL_INC)/proto.h \
$(PERL_INC)/regcomp.h \
$(PERL_INC)/regexp.h \
$(PERL_INC)/regnodes.h \
$(PERL_INC)/scope.h \
$(PERL_INC)/sv.h \
$(PERL_INC)/thread.h \
$(PERL_INC)/unixish.h \
$(PERL_INC)/util.h
$(OBJECT) : $(PERL_HDRS)
} if $self->{OBJECT};
push @m, join(" ", values %{$self->{XS}})." : \$(XSUBPPDEPS)\n" if %{$self->{XS}};
join "\n", @m;
}
=item pm_to_blib
Defines target that copies all files in the hash PM to their
destination and autosplits them. See L<ExtUtils::Install/DESCRIPTION>
=cut
sub pm_to_blib {
my $self = shift;
my($autodir) = $self->catdir('$(INST_LIB)','auto');
my $r = q{
pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM)
};
# VMS will swallow '' and PM_FILTER is often empty. So use q[]
my $pm_to_blib = $self->oneliner(<<CODE, ['-MExtUtils::Install']);
pm_to_blib({\@ARGV}, '$autodir', q[\$(PM_FILTER)], '\$(PERM_DIR)')
CODE
my @cmds = $self->split_command($pm_to_blib, %{$self->{PM}});
$r .= join '', map { "\t\$(NOECHO) $_\n" } @cmds;
$r .= qq{\t\$(NOECHO) \$(TOUCH) pm_to_blib\n};
return $r;
}
=item post_constants (o)
Returns an empty string per default. Dedicated to overrides from
within Makefile.PL after all constants have been defined.
=cut
sub post_constants{
"";
}
=item post_initialize (o)
Returns an empty string per default. Used in Makefile.PLs to add some
chunk of text to the Makefile after the object is initialized.
=cut
sub post_initialize {
"";
}
=item postamble (o)
Returns an empty string. Can be used in Makefile.PLs to write some
text to the Makefile at the end.
=cut
sub postamble {
"";
}
# transform dot-separated version string into comma-separated quadruple
# examples: '1.2.3.4.5' => '1,2,3,4'
# '1.2.3' => '1,2,3,0'
sub _ppd_version {
my ($self, $string) = @_;
return join ',', ((split /\./, $string), (0) x 4)[0..3];
}
=item ppd
Defines target that creates a PPD (Perl Package Description) file
for a binary distribution.
=cut
sub ppd {
my($self) = @_;
my $abstract = $self->{ABSTRACT} || '';
$abstract =~ s/\n/\\n/sg;
$abstract =~ s/</&lt;/g;
$abstract =~ s/>/&gt;/g;
my $author = join(', ',@{$self->{AUTHOR} || []});
$author =~ s/</&lt;/g;
$author =~ s/>/&gt;/g;
my $ppd_xml = sprintf <<'PPD_HTML', $self->{VERSION}, $abstract, $author;
<SOFTPKG NAME="$(DISTNAME)" VERSION="%s">
<ABSTRACT>%s</ABSTRACT>
<AUTHOR>%s</AUTHOR>
PPD_HTML
$ppd_xml .= " <IMPLEMENTATION>\n";
if ( $self->{MIN_PERL_VERSION} ) {
my $min_perl_version = $self->_ppd_version($self->{MIN_PERL_VERSION});
$ppd_xml .= sprintf <<'PPD_PERLVERS', $min_perl_version;
<PERLCORE VERSION="%s" />
PPD_PERLVERS
}
# Don't add "perl" to requires. perl dependencies are
# handles by ARCHITECTURE.
my %prereqs = %{$self->{PREREQ_PM}};
delete $prereqs{perl};
# Build up REQUIRE
foreach my $prereq (sort keys %prereqs) {
my $name = $prereq;
$name .= '::' unless $name =~ /::/;
my $version = $prereqs{$prereq}+0; # force numification
my %attrs = ( NAME => $name );
$attrs{VERSION} = $version if $version;
my $attrs = join " ", map { qq[$_="$attrs{$_}"] } keys %attrs;
$ppd_xml .= qq( <REQUIRE $attrs />\n);
}
my $archname = $Config{archname};
if ($] >= 5.008) {
# archname did not change from 5.6 to 5.8, but those versions may
# not be not binary compatible so now we append the part of the
# version that changes when binary compatibility may change
$archname .= "-$Config{PERL_REVISION}.$Config{PERL_VERSION}";
}
$ppd_xml .= sprintf <<'PPD_OUT', $archname;
<ARCHITECTURE NAME="%s" />
PPD_OUT
if ($self->{PPM_INSTALL_SCRIPT}) {
if ($self->{PPM_INSTALL_EXEC}) {
$ppd_xml .= sprintf qq{ <INSTALL EXEC="%s">%s</INSTALL>\n},
$self->{PPM_INSTALL_EXEC}, $self->{PPM_INSTALL_SCRIPT};
}
else {
$ppd_xml .= sprintf qq{ <INSTALL>%s</INSTALL>\n},
$self->{PPM_INSTALL_SCRIPT};
}
}
my ($bin_location) = $self->{BINARY_LOCATION} || '';
$bin_location =~ s/\\/\\\\/g;
$ppd_xml .= sprintf <<'PPD_XML', $bin_location;
<CODEBASE HREF="%s" />
</IMPLEMENTATION>
</SOFTPKG>
PPD_XML
my @ppd_cmds = $self->echo($ppd_xml, '$(DISTNAME).ppd');
return sprintf <<'PPD_OUT', join "\n\t", @ppd_cmds;
# Creates a PPD (Perl Package Description) for a binary distribution.
ppd :
%s
PPD_OUT
}
=item prefixify
$MM->prefixify($var, $prefix, $new_prefix, $default);
Using either $MM->{uc $var} || $Config{lc $var}, it will attempt to
replace it's $prefix with a $new_prefix.
Should the $prefix fail to match I<AND> a PREFIX was given as an
argument to WriteMakefile() it will set it to the $new_prefix +
$default. This is for systems whose file layouts don't neatly fit into
our ideas of prefixes.
This is for heuristics which attempt to create directory structures
that mirror those of the installed perl.
For example:
$MM->prefixify('installman1dir', '/usr', '/home/foo', 'man/man1');
this will attempt to remove '/usr' from the front of the
$MM->{INSTALLMAN1DIR} path (initializing it to $Config{installman1dir}
if necessary) and replace it with '/home/foo'. If this fails it will
simply use '/home/foo/man/man1'.
=cut
sub prefixify {
my($self,$var,$sprefix,$rprefix,$default) = @_;
my $path = $self->{uc $var} ||
$Config_Override{lc $var} || $Config{lc $var} || '';
$rprefix .= '/' if $sprefix =~ m|/$|;
print STDERR " prefixify $var => $path\n" if $Verbose >= 2;
print STDERR " from $sprefix to $rprefix\n" if $Verbose >= 2;
if( $self->{ARGS}{PREFIX} &&
$path !~ s{^\Q$sprefix\E\b}{$rprefix}s )
{
print STDERR " cannot prefix, using default.\n" if $Verbose >= 2;
print STDERR " no default!\n" if !$default && $Verbose >= 2;
$path = $self->catdir($rprefix, $default) if $default;
}
print " now $path\n" if $Verbose >= 2;
return $self->{uc $var} = $path;
}
=item processPL (o)
Defines targets to run *.PL files.
=cut
sub processPL {
my $self = shift;
my $pl_files = $self->{PL_FILES};
return "" unless $pl_files;
my $m = '';
foreach my $plfile (sort keys %$pl_files) {
my $list = ref($pl_files->{$plfile})
? $pl_files->{$plfile}
: [$pl_files->{$plfile}];
foreach my $target (@$list) {
if( $Is{VMS} ) {
$plfile = vmsify($self->eliminate_macros($plfile));
$target = vmsify($self->eliminate_macros($target));
}
# Normally a .PL file runs AFTER pm_to_blib so it can have
# blib in its @INC and load the just built modules. BUT if
# the generated module is something in $(TO_INST_PM) which
# pm_to_blib depends on then it can't depend on pm_to_blib
# else we have a dependency loop.
my $pm_dep;
my $perlrun;
if( defined $self->{PM}{$target} ) {
$pm_dep = '';
$perlrun = 'PERLRUN';
}
else {
$pm_dep = 'pm_to_blib';
$perlrun = 'PERLRUNINST';
}
$m .= <<MAKE_FRAG;
all :: $target
\$(NOECHO) \$(NOOP)
$target :: $plfile $pm_dep
\$($perlrun) $plfile $target
MAKE_FRAG
}
}
return $m;
}
=item quote_paren
Backslashes parentheses C<()> in command line arguments.
Doesn't handle recursive Makefile C<$(...)> constructs,
but handles simple ones.
=cut
sub quote_paren {
my $arg = shift;
$arg =~ s{\$\((.+?)\)}{\$\\\\($1\\\\)}g; # protect $(...)
$arg =~ s{(?<!\\)([()])}{\\$1}g; # quote unprotected
$arg =~ s{\$\\\\\((.+?)\\\\\)}{\$($1)}g; # unprotect $(...)
return $arg;
}
=item replace_manpage_separator
my $man_name = $MM->replace_manpage_separator($file_path);
Takes the name of a package, which may be a nested package, in the
form 'Foo/Bar.pm' and replaces the slash with C<::> or something else
safe for a man page file name. Returns the replacement.
=cut
sub replace_manpage_separator {
my($self,$man) = @_;
$man =~ s,/+,::,g;
return $man;
}
=item cd
=cut
sub cd {
my($self, $dir, @cmds) = @_;
# No leading tab and no trailing newline makes for easier embedding
my $make_frag = join "\n\t", map { "cd $dir && $_" } @cmds;
return $make_frag;
}
=item oneliner
=cut
sub oneliner {
my($self, $cmd, $switches) = @_;
$switches = [] unless defined $switches;
# Strip leading and trailing newlines
$cmd =~ s{^\n+}{};
$cmd =~ s{\n+$}{};
my @cmds = split /\n/, $cmd;
$cmd = join " \n\t -e ", map $self->quote_literal($_), @cmds;
$cmd = $self->escape_newlines($cmd);
$switches = join ' ', @$switches;
return qq{\$(ABSPERLRUN) $switches -e $cmd --};
}
=item quote_literal
=cut
sub quote_literal {
my($self, $text) = @_;
# I think all we have to quote is single quotes and I think
# this is a safe way to do it.
$text =~ s{'}{'\\''}g;
return "'$text'";
}
=item escape_newlines
=cut
sub escape_newlines {
my($self, $text) = @_;
$text =~ s{\n}{\\\n}g;
return $text;
}
=item max_exec_len
Using POSIX::ARG_MAX. Otherwise falling back to 4096.
=cut
sub max_exec_len {
my $self = shift;
if (!defined $self->{_MAX_EXEC_LEN}) {
if (my $arg_max = eval { require POSIX; &POSIX::ARG_MAX }) {
$self->{_MAX_EXEC_LEN} = $arg_max;
}
else { # POSIX minimum exec size
$self->{_MAX_EXEC_LEN} = 4096;
}
}
return $self->{_MAX_EXEC_LEN};
}
=item static (o)
Defines the static target.
=cut
sub static {
# --- Static Loading Sections ---
my($self) = shift;
'
## $(INST_PM) has been moved to the all: target.
## It remains here for awhile to allow for old usage: "make static"
static :: $(FIRST_MAKEFILE) $(INST_STATIC)
$(NOECHO) $(NOOP)
';
}
=item static_lib (o)
Defines how to produce the *.a (or equivalent) files.
=cut
sub static_lib {
my($self) = @_;
return '' unless $self->has_link_code;
my(@m);
push(@m, <<'END');
$(INST_STATIC) : $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists
$(RM_RF) $@
END
# If this extension has its own library (eg SDBM_File)
# then copy that to $(INST_STATIC) and add $(OBJECT) into it.
push(@m, <<'MAKE_FRAG') if $self->{MYEXTLIB};
$(CP) $(MYEXTLIB) $@
MAKE_FRAG
my $ar;
if (exists $self->{FULL_AR} && -x $self->{FULL_AR}) {
# Prefer the absolute pathed ar if available so that PATH
# doesn't confuse us. Perl itself is built with the full_ar.
$ar = 'FULL_AR';
} else {
$ar = 'AR';
}
push @m, sprintf <<'MAKE_FRAG', $ar;
$(%s) $(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@
$(CHMOD) $(PERM_RWX) $@
$(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)/extralibs.ld
MAKE_FRAG
# Old mechanism - still available:
push @m, <<'MAKE_FRAG' if $self->{PERL_SRC} && $self->{EXTRALIBS};
$(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)/ext.libs
MAKE_FRAG
join('', @m);
}
=item staticmake (o)
Calls makeaperl.
=cut
sub staticmake {
my($self, %attribs) = @_;
my(@static);
my(@searchdirs)=($self->{PERL_ARCHLIB}, $self->{SITEARCHEXP}, $self->{INST_ARCHLIB});
# And as it's not yet built, we add the current extension
# but only if it has some C code (or XS code, which implies C code)
if (@{$self->{C}}) {
@static = $self->catfile($self->{INST_ARCHLIB},
"auto",
$self->{FULLEXT},
"$self->{BASEEXT}$self->{LIB_EXT}"
);
}
# Either we determine now, which libraries we will produce in the
# subdirectories or we do it at runtime of the make.
# We could ask all subdir objects, but I cannot imagine, why it
# would be necessary.
# Instead we determine all libraries for the new perl at
# runtime.
my(@perlinc) = ($self->{INST_ARCHLIB}, $self->{INST_LIB}, $self->{PERL_ARCHLIB}, $self->{PERL_LIB});
$self->makeaperl(MAKE => $self->{MAKEFILE},
DIRS => \@searchdirs,
STAT => \@static,
INCL => \@perlinc,
TARGET => $self->{MAP_TARGET},
TMP => "",
LIBPERL => $self->{LIBPERL_A}
);
}
=item subdir_x (o)
Helper subroutine for subdirs
=cut
sub subdir_x {
my($self, $subdir) = @_;
my $subdir_cmd = $self->cd($subdir,
'$(MAKE) $(USEMAKEFILE) $(FIRST_MAKEFILE) all $(PASTHRU)'
);
return sprintf <<'EOT', $subdir_cmd;
subdirs ::
$(NOECHO) %s
EOT
}
=item subdirs (o)
Defines targets to process subdirectories.
=cut
sub subdirs {
# --- Sub-directory Sections ---
my($self) = shift;
my(@m);
# This method provides a mechanism to automatically deal with
# subdirectories containing further Makefile.PL scripts.
# It calls the subdir_x() method for each subdirectory.
foreach my $dir (@{$self->{DIR}}){
push(@m, $self->subdir_x($dir));
#### print "Including $dir subdirectory\n";
}
if (@m){
unshift(@m, "
# The default clean, realclean and test targets in this Makefile
# have automatically been given entries for each subdir.
");
} else {
push(@m, "\n# none")
}
join('',@m);
}
=item test (o)
Defines the test targets.
=cut
sub test {
# --- Test and Installation Sections ---
my($self, %attribs) = @_;
my $tests = $attribs{TESTS} || '';
if (!$tests && -d 't') {
$tests = $self->find_tests;
}
# note: 'test.pl' name is also hardcoded in init_dirscan()
my(@m);
push(@m,"
TEST_VERBOSE=0
TEST_TYPE=test_\$(LINKTYPE)
TEST_FILE = test.pl
TEST_FILES = $tests
TESTDB_SW = -d
testdb :: testdb_\$(LINKTYPE)
test :: \$(TEST_TYPE) subdirs-test
subdirs-test ::
\$(NOECHO) \$(NOOP)
");
foreach my $dir (@{ $self->{DIR} }) {
my $test = $self->cd($dir, '$(MAKE) test $(PASTHRU)');
push @m, <<END
subdirs-test ::
\$(NOECHO) $test
END
}
push(@m, "\t\$(NOECHO) \$(ECHO) 'No tests defined for \$(NAME) extension.'\n")
unless $tests or -f "test.pl" or @{$self->{DIR}};
push(@m, "\n");
push(@m, "test_dynamic :: pure_all\n");
push(@m, $self->test_via_harness('$(FULLPERLRUN)', '$(TEST_FILES)'))
if $tests;
push(@m, $self->test_via_script('$(FULLPERLRUN)', '$(TEST_FILE)'))
if -f "test.pl";
push(@m, "\n");
push(@m, "testdb_dynamic :: pure_all\n");
push(@m, $self->test_via_script('$(FULLPERLRUN) $(TESTDB_SW)',
'$(TEST_FILE)'));
push(@m, "\n");
# Occasionally we may face this degenerate target:
push @m, "test_ : test_dynamic\n\n";
if ($self->needs_linking()) {
push(@m, "test_static :: pure_all \$(MAP_TARGET)\n");
push(@m, $self->test_via_harness('./$(MAP_TARGET)', '$(TEST_FILES)')) if $tests;
push(@m, $self->test_via_script('./$(MAP_TARGET)', '$(TEST_FILE)')) if -f "test.pl";
push(@m, "\n");
push(@m, "testdb_static :: pure_all \$(MAP_TARGET)\n");
push(@m, $self->test_via_script('./$(MAP_TARGET) $(TESTDB_SW)', '$(TEST_FILE)'));
push(@m, "\n");
} else {
push @m, "test_static :: test_dynamic\n";
push @m, "testdb_static :: testdb_dynamic\n";
}
join("", @m);
}
=item test_via_harness (override)
For some reason which I forget, Unix machines like to have
PERL_DL_NONLAZY set for tests.
=cut
sub test_via_harness {
my($self, $perl, $tests) = @_;
return $self->SUPER::test_via_harness("PERL_DL_NONLAZY=1 $perl", $tests);
}
=item test_via_script (override)
Again, the PERL_DL_NONLAZY thing.
=cut
sub test_via_script {
my($self, $perl, $script) = @_;
return $self->SUPER::test_via_script("PERL_DL_NONLAZY=1 $perl", $script);
}
=item tool_xsubpp (o)
Determines typemaps, xsubpp version, prototype behaviour.
=cut
sub tool_xsubpp {
my($self) = shift;
return "" unless $self->needs_linking;
my $xsdir;
my @xsubpp_dirs = @INC;
# Make sure we pick up the new xsubpp if we're building perl.
unshift @xsubpp_dirs, $self->{PERL_LIB} if $self->{PERL_CORE};
foreach my $dir (@xsubpp_dirs) {
$xsdir = $self->catdir($dir, 'ExtUtils');
if( -r $self->catfile($xsdir, "xsubpp") ) {
last;
}
}
my $tmdir = File::Spec->catdir($self->{PERL_LIB},"ExtUtils");
my(@tmdeps) = $self->catfile($tmdir,'typemap');
if( $self->{TYPEMAPS} ){
foreach my $typemap (@{$self->{TYPEMAPS}}){
if( ! -f $typemap ) {
warn "Typemap $typemap not found.\n";
}
else {
push(@tmdeps, $typemap);
}
}
}
push(@tmdeps, "typemap") if -f "typemap";
my(@tmargs) = map("-typemap $_", @tmdeps);
if( exists $self->{XSOPT} ){
unshift( @tmargs, $self->{XSOPT} );
}
if ($Is{VMS} &&
$Config{'ldflags'} &&
$Config{'ldflags'} =~ m!/Debug!i &&
(!exists($self->{XSOPT}) || $self->{XSOPT} !~ /linenumbers/)
)
{
unshift(@tmargs,'-nolinenumbers');
}
$self->{XSPROTOARG} = "" unless defined $self->{XSPROTOARG};
return qq{
XSUBPPDIR = $xsdir
XSUBPP = \$(XSUBPPDIR)\$(DFSEP)xsubpp
XSUBPPRUN = \$(PERLRUN) \$(XSUBPP)
XSPROTOARG = $self->{XSPROTOARG}
XSUBPPDEPS = @tmdeps \$(XSUBPP)
XSUBPPARGS = @tmargs
XSUBPP_EXTRA_ARGS =
};
};
=item all_target
Build man pages, too
=cut
sub all_target {
my $self = shift;
return <<'MAKE_EXT';
all :: pure_all manifypods
$(NOECHO) $(NOOP)
MAKE_EXT
}
=item top_targets (o)
Defines the targets all, subdirs, config, and O_FILES
=cut
sub top_targets {
# --- Target Sections ---
my($self) = shift;
my(@m);
push @m, $self->all_target, "\n" unless $self->{SKIPHASH}{'all'};
push @m, '
pure_all :: config pm_to_blib subdirs linkext
$(NOECHO) $(NOOP)
subdirs :: $(MYEXTLIB)
$(NOECHO) $(NOOP)
config :: $(FIRST_MAKEFILE) blibdirs
$(NOECHO) $(NOOP)
';
push @m, '
$(O_FILES): $(H_FILES)
' if @{$self->{O_FILES} || []} && @{$self->{H} || []};
push @m, q{
help :
perldoc ExtUtils::MakeMaker
};
join('',@m);
}
=item writedoc
Obsolete, deprecated method. Not used since Version 5.21.
=cut
sub writedoc {
# --- perllocal.pod section ---
my($self,$what,$name,@attribs)=@_;
my $time = localtime;
print "=head2 $time: $what C<$name>\n\n=over 4\n\n=item *\n\n";
print join "\n\n=item *\n\n", map("C<$_>",@attribs);
print "\n\n=back\n\n";
}
=item xs_c (o)
Defines the suffix rules to compile XS files to C.
=cut
sub xs_c {
my($self) = shift;
return '' unless $self->needs_linking();
'
.xs.c:
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c
';
}
=item xs_cpp (o)
Defines the suffix rules to compile XS files to C++.
=cut
sub xs_cpp {
my($self) = shift;
return '' unless $self->needs_linking();
'
.xs.cpp:
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.cpp
';
}
=item xs_o (o)
Defines suffix rules to go from XS to object files directly. This is
only intended for broken make implementations.
=cut
sub xs_o { # many makes are too dumb to use xs_c then c_o
my($self) = shift;
return '' unless $self->needs_linking();
'
.xs$(OBJ_EXT):
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c
$(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c
';
}
1;
=back
=head1 SEE ALSO
L<ExtUtils::MakeMaker>
=cut
__END__
EXTUTILS_MM_UNIX
$fatpacked{"ExtUtils/MM_VMS.pm"} = <<'EXTUTILS_MM_VMS';
package ExtUtils::MM_VMS;
use strict;
use ExtUtils::MakeMaker::Config;
require Exporter;
BEGIN {
# so we can compile the thing on non-VMS platforms.
if( $^O eq 'VMS' ) {
require VMS::Filespec;
VMS::Filespec->import;
}
}
use File::Basename;
our $VERSION = '6.59';
require ExtUtils::MM_Any;
require ExtUtils::MM_Unix;
our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
use ExtUtils::MakeMaker qw($Verbose neatvalue);
our $Revision = $ExtUtils::MakeMaker::Revision;
=head1 NAME
ExtUtils::MM_VMS - methods to override UN*X behaviour in ExtUtils::MakeMaker
=head1 SYNOPSIS
Do not use this directly.
Instead, use ExtUtils::MM and it will figure out which MM_*
class to use for you.
=head1 DESCRIPTION
See ExtUtils::MM_Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not
the semantics.
=head2 Methods always loaded
=over 4
=item wraplist
Converts a list into a string wrapped at approximately 80 columns.
=cut
sub wraplist {
my($self) = shift;
my($line,$hlen) = ('',0);
foreach my $word (@_) {
# Perl bug -- seems to occasionally insert extra elements when
# traversing array (scalar(@array) doesn't show them, but
# foreach(@array) does) (5.00307)
next unless $word =~ /\w/;
$line .= ' ' if length($line);
if ($hlen > 80) { $line .= "\\\n\t"; $hlen = 0; }
$line .= $word;
$hlen += length($word) + 2;
}
$line;
}
# This isn't really an override. It's just here because ExtUtils::MM_VMS
# appears in @MM::ISA before ExtUtils::Liblist::Kid, so if there isn't an ext()
# in MM_VMS, then AUTOLOAD is called, and bad things happen. So, we just
# mimic inheritance here and hand off to ExtUtils::Liblist::Kid.
# XXX This hackery will die soon. --Schwern
sub ext {
require ExtUtils::Liblist::Kid;
goto &ExtUtils::Liblist::Kid::ext;
}
=back
=head2 Methods
Those methods which override default MM_Unix methods are marked
"(override)", while methods unique to MM_VMS are marked "(specific)".
For overridden methods, documentation is limited to an explanation
of why this method overrides the MM_Unix method; see the ExtUtils::MM_Unix
documentation for more details.
=over 4
=item guess_name (override)
Try to determine name of extension being built. We begin with the name
of the current directory. Since VMS filenames are case-insensitive,
however, we look for a F<.pm> file whose name matches that of the current
directory (presumably the 'main' F<.pm> file for this extension), and try
to find a C<package> statement from which to obtain the Mixed::Case
package name.
=cut
sub guess_name {
my($self) = @_;
my($defname,$defpm,@pm,%xs);
local *PM;
$defname = basename(fileify($ENV{'DEFAULT'}));
$defname =~ s![\d\-_]*\.dir.*$!!; # Clip off .dir;1 suffix, and package version
$defpm = $defname;
# Fallback in case for some reason a user has copied the files for an
# extension into a working directory whose name doesn't reflect the
# extension's name. We'll use the name of a unique .pm file, or the
# first .pm file with a matching .xs file.
if (not -e "${defpm}.pm") {
@pm = glob('*.pm');
s/.pm$// for @pm;
if (@pm == 1) { ($defpm = $pm[0]) =~ s/.pm$//; }
elsif (@pm) {
%xs = map { s/.xs$//; ($_,1) } glob('*.xs'); ## no critic
if (keys %xs) {
foreach my $pm (@pm) {
$defpm = $pm, last if exists $xs{$pm};
}
}
}
}
if (open(my $pm, '<', "${defpm}.pm")){
while (<$pm>) {
if (/^\s*package\s+([^;]+)/i) {
$defname = $1;
last;
}
}
print STDOUT "Warning (non-fatal): Couldn't find package name in ${defpm}.pm;\n\t",
"defaulting package name to $defname\n"
if eof($pm);
close $pm;
}
else {
print STDOUT "Warning (non-fatal): Couldn't find ${defpm}.pm;\n\t",
"defaulting package name to $defname\n";
}
$defname =~ s#[\d.\-_]+$##;
$defname;
}
=item find_perl (override)
Use VMS file specification syntax and CLI commands to find and
invoke Perl images.
=cut
sub find_perl {
my($self, $ver, $names, $dirs, $trace) = @_;
my($vmsfile,@sdirs,@snames,@cand);
my($rslt);
my($inabs) = 0;
local *TCF;
if( $self->{PERL_CORE} ) {
# Check in relative directories first, so we pick up the current
# version of Perl if we're running MakeMaker as part of the main build.
@sdirs = sort { my($absa) = $self->file_name_is_absolute($a);
my($absb) = $self->file_name_is_absolute($b);
if ($absa && $absb) { return $a cmp $b }
else { return $absa ? 1 : ($absb ? -1 : ($a cmp $b)); }
} @$dirs;
# Check miniperl before perl, and check names likely to contain
# version numbers before "generic" names, so we pick up an
# executable that's less likely to be from an old installation.
@snames = sort { my($ba) = $a =~ m!([^:>\]/]+)$!; # basename
my($bb) = $b =~ m!([^:>\]/]+)$!;
my($ahasdir) = (length($a) - length($ba) > 0);
my($bhasdir) = (length($b) - length($bb) > 0);
if ($ahasdir and not $bhasdir) { return 1; }
elsif ($bhasdir and not $ahasdir) { return -1; }
else { $bb =~ /\d/ <=> $ba =~ /\d/
or substr($ba,0,1) cmp substr($bb,0,1)
or length($bb) <=> length($ba) } } @$names;
}
else {
@sdirs = @$dirs;
@snames = @$names;
}
# Image names containing Perl version use '_' instead of '.' under VMS
s/\.(\d+)$/_$1/ for @snames;
if ($trace >= 2){
print "Looking for perl $ver by these names:\n";
print "\t@snames,\n";
print "in these dirs:\n";
print "\t@sdirs\n";
}
foreach my $dir (@sdirs){
next unless defined $dir; # $self->{PERL_SRC} may be undefined
$inabs++ if $self->file_name_is_absolute($dir);
if ($inabs == 1) {
# We've covered relative dirs; everything else is an absolute
# dir (probably an installed location). First, we'll try
# potential command names, to see whether we can avoid a long
# MCR expression.
foreach my $name (@snames) {
push(@cand,$name) if $name =~ /^[\w\-\$]+$/;
}
$inabs++; # Should happen above in next $dir, but just in case...
}
foreach my $name (@snames){
push @cand, ($name !~ m![/:>\]]!) ? $self->catfile($dir,$name)
: $self->fixpath($name,0);
}
}
foreach my $name (@cand) {
print "Checking $name\n" if $trace >= 2;
# If it looks like a potential command, try it without the MCR
if ($name =~ /^[\w\-\$]+$/) {
open(my $tcf, ">", "temp_mmvms.com")
or die('unable to open temp file');
print $tcf "\$ set message/nofacil/nosever/noident/notext\n";
print $tcf "\$ $name -e \"require $ver; print \"\"VER_OK\\n\"\"\"\n";
close $tcf;
$rslt = `\@temp_mmvms.com` ;
unlink('temp_mmvms.com');
if ($rslt =~ /VER_OK/) {
print "Using PERL=$name\n" if $trace;
return $name;
}
}
next unless $vmsfile = $self->maybe_command($name);
$vmsfile =~ s/;[\d\-]*$//; # Clip off version number; we can use a newer version as well
print "Executing $vmsfile\n" if ($trace >= 2);
open(my $tcf, '>', "temp_mmvms.com")
or die('unable to open temp file');
print $tcf "\$ set message/nofacil/nosever/noident/notext\n";
print $tcf "\$ mcr $vmsfile -e \"require $ver; print \"\"VER_OK\\n\"\"\" \n";
close $tcf;
$rslt = `\@temp_mmvms.com`;
unlink('temp_mmvms.com');
if ($rslt =~ /VER_OK/) {
print "Using PERL=MCR $vmsfile\n" if $trace;
return "MCR $vmsfile";
}
}
print STDOUT "Unable to find a perl $ver (by these names: @$names, in these dirs: @$dirs)\n";
0; # false and not empty
}
=item _fixin_replace_shebang (override)
Helper routine for MM->fixin(), overridden because there's no such thing as an
actual shebang line that will be intepreted by the shell, so we just prepend
$Config{startperl} and preserve the shebang line argument for any switches it
may contain.
=cut
sub _fixin_replace_shebang {
my ( $self, $file, $line ) = @_;
my ( undef, $arg ) = split ' ', $line, 2;
return $Config{startperl} . "\n" . $Config{sharpbang} . "perl $arg\n";
}
=item maybe_command (override)
Follows VMS naming conventions for executable files.
If the name passed in doesn't exactly match an executable file,
appends F<.Exe> (or equivalent) to check for executable image, and F<.Com>
to check for DCL procedure. If this fails, checks directories in DCL$PATH
and finally F<Sys$System:> for an executable file having the name specified,
with or without the F<.Exe>-equivalent suffix.
=cut
sub maybe_command {
my($self,$file) = @_;
return $file if -x $file && ! -d _;
my(@dirs) = ('');
my(@exts) = ('',$Config{'exe_ext'},'.exe','.com');
if ($file !~ m![/:>\]]!) {
for (my $i = 0; defined $ENV{"DCL\$PATH;$i"}; $i++) {
my $dir = $ENV{"DCL\$PATH;$i"};
$dir .= ':' unless $dir =~ m%[\]:]$%;
push(@dirs,$dir);
}
push(@dirs,'Sys$System:');
foreach my $dir (@dirs) {
my $sysfile = "$dir$file";
foreach my $ext (@exts) {
return $file if -x "$sysfile$ext" && ! -d _;
}
}
}
return 0;
}
=item pasthru (override)
VMS has $(MMSQUALIFIERS) which is a listing of all the original command line
options. This is used in every invocation of make in the VMS Makefile so
PASTHRU should not be necessary. Using PASTHRU tends to blow commands past
the 256 character limit.
=cut
sub pasthru {
return "PASTHRU=\n";
}
=item pm_to_blib (override)
VMS wants a dot in every file so we can't have one called 'pm_to_blib',
it becomes 'pm_to_blib.' and MMS/K isn't smart enough to know that when
you have a target called 'pm_to_blib' it should look for 'pm_to_blib.'.
So in VMS its pm_to_blib.ts.
=cut
sub pm_to_blib {
my $self = shift;
my $make = $self->SUPER::pm_to_blib;
$make =~ s{^pm_to_blib :}{pm_to_blib.ts :}m;
$make =~ s{\$\(TOUCH\) pm_to_blib}{\$(TOUCH) pm_to_blib.ts};
$make = <<'MAKE' . $make;
# Dummy target to match Unix target name; we use pm_to_blib.ts as
# timestamp file to avoid repeated invocations under VMS
pm_to_blib : pm_to_blib.ts
$(NOECHO) $(NOOP)
MAKE
return $make;
}
=item perl_script (override)
If name passed in doesn't specify a readable file, appends F<.com> or
F<.pl> and tries again, since it's customary to have file types on all files
under VMS.
=cut
sub perl_script {
my($self,$file) = @_;
return $file if -r $file && ! -d _;
return "$file.com" if -r "$file.com";
return "$file.pl" if -r "$file.pl";
return '';
}
=item replace_manpage_separator
Use as separator a character which is legal in a VMS-syntax file name.
=cut
sub replace_manpage_separator {
my($self,$man) = @_;
$man = unixify($man);
$man =~ s#/+#__#g;
$man;
}
=item init_DEST
(override) Because of the difficulty concatenating VMS filepaths we
must pre-expand the DEST* variables.
=cut
sub init_DEST {
my $self = shift;
$self->SUPER::init_DEST;
# Expand DEST variables.
foreach my $var ($self->installvars) {
my $destvar = 'DESTINSTALL'.$var;
$self->{$destvar} = $self->eliminate_macros($self->{$destvar});
}
}
=item init_DIRFILESEP
No seperator between a directory path and a filename on VMS.
=cut
sub init_DIRFILESEP {
my($self) = shift;
$self->{DIRFILESEP} = '';
return 1;
}
=item init_main (override)
=cut
sub init_main {
my($self) = shift;
$self->SUPER::init_main;
$self->{DEFINE} ||= '';
if ($self->{DEFINE} ne '') {
my(@terms) = split(/\s+/,$self->{DEFINE});
my(@defs,@udefs);
foreach my $def (@terms) {
next unless $def;
my $targ = \@defs;
if ($def =~ s/^-([DU])//) { # If it was a Unix-style definition
$targ = \@udefs if $1 eq 'U';
$def =~ s/='(.*)'$/=$1/; # then remove shell-protection ''
$def =~ s/^'(.*)'$/$1/; # from entire term or argument
}
if ($def =~ /=/) {
$def =~ s/"/""/g; # Protect existing " from DCL
$def = qq["$def"]; # and quote to prevent parsing of =
}
push @$targ, $def;
}
$self->{DEFINE} = '';
if (@defs) {
$self->{DEFINE} = '/Define=(' . join(',',@defs) . ')';
}
if (@udefs) {
$self->{DEFINE} .= '/Undef=(' . join(',',@udefs) . ')';
}
}
}
=item init_others (override)
Provide VMS-specific forms of various utility commands, then hand
off to the default MM_Unix method.
DEV_NULL should probably be overriden with something.
Also changes EQUALIZE_TIMESTAMP to set revision date of target file to
one second later than source file, since MMK interprets precisely
equal revision dates for a source and target file as a sign that the
target needs to be updated.
=cut
sub init_others {
my($self) = @_;
$self->{NOOP} = 'Continue';
$self->{NOECHO} ||= '@ ';
$self->{MAKEFILE} ||= $self->{FIRST_MAKEFILE} || 'Descrip.MMS';
$self->{FIRST_MAKEFILE} ||= $self->{MAKEFILE};
$self->{MAKE_APERL_FILE} ||= 'Makeaperl.MMS';
$self->{MAKEFILE_OLD} ||= $self->eliminate_macros('$(FIRST_MAKEFILE)_old');
#
# If an extension is not specified, then MMS/MMK assumes an
# an extension of .MMS. If there really is no extension,
# then a trailing "." needs to be appended to specify a
# a null extension.
#
$self->{MAKEFILE} .= '.' unless $self->{MAKEFILE} =~ m/\./;
$self->{FIRST_MAKEFILE} .= '.' unless $self->{FIRST_MAKEFILE} =~ m/\./;
$self->{MAKE_APERL_FILE} .= '.' unless $self->{MAKE_APERL_FILE} =~ m/\./;
$self->{MAKEFILE_OLD} .= '.' unless $self->{MAKEFILE_OLD} =~ m/\./;
$self->{MACROSTART} ||= '/Macro=(';
$self->{MACROEND} ||= ')';
$self->{USEMAKEFILE} ||= '/Descrip=';
$self->{EQUALIZE_TIMESTAMP} ||= '$(ABSPERLRUN) -we "open F,qq{>>$ARGV[1]};close F;utime(0,(stat($ARGV[0]))[9]+1,$ARGV[1])"';
$self->{MOD_INSTALL} ||=
$self->oneliner(<<'CODE', ['-MExtUtils::Install']);
install([ from_to => {split(' ', <STDIN>)}, verbose => '$(VERBINST)', uninstall_shadows => '$(UNINST)', dir_mode => '$(PERM_DIR)' ]);
CODE
$self->SUPER::init_others;
$self->{SHELL} ||= 'Posix';
$self->{UMASK_NULL} = '! ';
# Redirection on VMS goes before the command, not after as on Unix.
# $(DEV_NULL) is used once and its not worth going nuts over making
# it work. However, Unix's DEV_NULL is quite wrong for VMS.
$self->{DEV_NULL} = '';
if ($self->{OBJECT} =~ /\s/) {
$self->{OBJECT} =~ s/(\\)?\n+\s+/ /g;
$self->{OBJECT} = $self->wraplist(
map $self->fixpath($_,0), split /,?\s+/, $self->{OBJECT}
);
}
$self->{LDFROM} = $self->wraplist(
map $self->fixpath($_,0), split /,?\s+/, $self->{LDFROM}
);
}
=item init_platform (override)
Add PERL_VMS, MM_VMS_REVISION and MM_VMS_VERSION.
MM_VMS_REVISION is for backwards compatibility before MM_VMS had a
$VERSION.
=cut
sub init_platform {
my($self) = shift;
$self->{MM_VMS_REVISION} = $Revision;
$self->{MM_VMS_VERSION} = $VERSION;
$self->{PERL_VMS} = $self->catdir($self->{PERL_SRC}, 'VMS')
if $self->{PERL_SRC};
}
=item platform_constants
=cut
sub platform_constants {
my($self) = shift;
my $make_frag = '';
foreach my $macro (qw(PERL_VMS MM_VMS_REVISION MM_VMS_VERSION))
{
next unless defined $self->{$macro};
$make_frag .= "$macro = $self->{$macro}\n";
}
return $make_frag;
}
=item init_VERSION (override)
Override the *DEFINE_VERSION macros with VMS semantics. Translate the
MAKEMAKER filepath to VMS style.
=cut
sub init_VERSION {
my $self = shift;
$self->SUPER::init_VERSION;
$self->{DEFINE_VERSION} = '"$(VERSION_MACRO)=""$(VERSION)"""';
$self->{XS_DEFINE_VERSION} = '"$(XS_VERSION_MACRO)=""$(XS_VERSION)"""';
$self->{MAKEMAKER} = vmsify($INC{'ExtUtils/MakeMaker.pm'});
}
=item constants (override)
Fixes up numerous file and directory macros to insure VMS syntax
regardless of input syntax. Also makes lists of files
comma-separated.
=cut
sub constants {
my($self) = @_;
# Be kind about case for pollution
for (@ARGV) { $_ = uc($_) if /POLLUTE/i; }
# Cleanup paths for directories in MMS macros.
foreach my $macro ( qw [
INST_BIN INST_SCRIPT INST_LIB INST_ARCHLIB
PERL_LIB PERL_ARCHLIB
PERL_INC PERL_SRC ],
(map { 'INSTALL'.$_ } $self->installvars)
)
{
next unless defined $self->{$macro};
next if $macro =~ /MAN/ && $self->{$macro} eq 'none';
$self->{$macro} = $self->fixpath($self->{$macro},1);
}
# Cleanup paths for files in MMS macros.
foreach my $macro ( qw[LIBPERL_A FIRST_MAKEFILE MAKEFILE_OLD
MAKE_APERL_FILE MYEXTLIB] )
{
next unless defined $self->{$macro};
$self->{$macro} = $self->fixpath($self->{$macro},0);
}
# Fixup files for MMS macros
# XXX is this list complete?
for my $macro (qw/
FULLEXT VERSION_FROM OBJECT LDFROM
/ ) {
next unless defined $self->{$macro};
$self->{$macro} = $self->fixpath($self->{$macro},0);
}
for my $macro (qw/ XS MAN1PODS MAN3PODS PM /) {
# Where is the space coming from? --jhi
next unless $self ne " " && defined $self->{$macro};
my %tmp = ();
for my $key (keys %{$self->{$macro}}) {
$tmp{$self->fixpath($key,0)} =
$self->fixpath($self->{$macro}{$key},0);
}
$self->{$macro} = \%tmp;
}
for my $macro (qw/ C O_FILES H /) {
next unless defined $self->{$macro};
my @tmp = ();
for my $val (@{$self->{$macro}}) {
push(@tmp,$self->fixpath($val,0));
}
$self->{$macro} = \@tmp;
}
# mms/k does not define a $(MAKE) macro.
$self->{MAKE} = '$(MMS)$(MMSQUALIFIERS)';
return $self->SUPER::constants;
}
=item special_targets
Clear the default .SUFFIXES and put in our own list.
=cut
sub special_targets {
my $self = shift;
my $make_frag .= <<'MAKE_FRAG';
.SUFFIXES :
.SUFFIXES : $(OBJ_EXT) .c .cpp .cxx .xs
MAKE_FRAG
return $make_frag;
}
=item cflags (override)
Bypass shell script and produce qualifiers for CC directly (but warn
user if a shell script for this extension exists). Fold multiple
/Defines into one, since some C compilers pay attention to only one
instance of this qualifier on the command line.
=cut
sub cflags {
my($self,$libperl) = @_;
my($quals) = $self->{CCFLAGS} || $Config{'ccflags'};
my($definestr,$undefstr,$flagoptstr) = ('','','');
my($incstr) = '/Include=($(PERL_INC)';
my($name,$sys,@m);
( $name = $self->{NAME} . "_cflags" ) =~ s/:/_/g ;
print STDOUT "Unix shell script ".$Config{"$self->{'BASEEXT'}_cflags"}.
" required to modify CC command for $self->{'BASEEXT'}\n"
if ($Config{$name});
if ($quals =~ / -[DIUOg]/) {
while ($quals =~ / -([Og])(\d*)\b/) {
my($type,$lvl) = ($1,$2);
$quals =~ s/ -$type$lvl\b\s*//;
if ($type eq 'g') { $flagoptstr = '/NoOptimize'; }
else { $flagoptstr = '/Optimize' . (defined($lvl) ? "=$lvl" : ''); }
}
while ($quals =~ / -([DIU])(\S+)/) {
my($type,$def) = ($1,$2);
$quals =~ s/ -$type$def\s*//;
$def =~ s/"/""/g;
if ($type eq 'D') { $definestr .= qq["$def",]; }
elsif ($type eq 'I') { $incstr .= ',' . $self->fixpath($def,1); }
else { $undefstr .= qq["$def",]; }
}
}
if (length $quals and $quals !~ m!/!) {
warn "MM_VMS: Ignoring unrecognized CCFLAGS elements \"$quals\"\n";
$quals = '';
}
$definestr .= q["PERL_POLLUTE",] if $self->{POLLUTE};
if (length $definestr) { chop($definestr); $quals .= "/Define=($definestr)"; }
if (length $undefstr) { chop($undefstr); $quals .= "/Undef=($undefstr)"; }
# Deal with $self->{DEFINE} here since some C compilers pay attention
# to only one /Define clause on command line, so we have to
# conflate the ones from $Config{'ccflags'} and $self->{DEFINE}
# ($self->{DEFINE} has already been VMSified in constants() above)
if ($self->{DEFINE}) { $quals .= $self->{DEFINE}; }
for my $type (qw(Def Undef)) {
my(@terms);
while ($quals =~ m:/${type}i?n?e?=([^/]+):ig) {
my $term = $1;
$term =~ s:^\((.+)\)$:$1:;
push @terms, $term;
}
if ($type eq 'Def') {
push @terms, qw[ $(DEFINE_VERSION) $(XS_DEFINE_VERSION) ];
}
if (@terms) {
$quals =~ s:/${type}i?n?e?=[^/]+::ig;
$quals .= "/${type}ine=(" . join(',',@terms) . ')';
}
}
$libperl or $libperl = $self->{LIBPERL_A} || "libperl.olb";
# Likewise with $self->{INC} and /Include
if ($self->{'INC'}) {
my(@includes) = split(/\s+/,$self->{INC});
foreach (@includes) {
s/^-I//;
$incstr .= ','.$self->fixpath($_,1);
}
}
$quals .= "$incstr)";
# $quals =~ s/,,/,/g; $quals =~ s/\(,/(/g;
$self->{CCFLAGS} = $quals;
$self->{PERLTYPE} ||= '';
$self->{OPTIMIZE} ||= $flagoptstr || $Config{'optimize'};
if ($self->{OPTIMIZE} !~ m!/!) {
if ($self->{OPTIMIZE} =~ m!-g!) { $self->{OPTIMIZE} = '/Debug/NoOptimize' }
elsif ($self->{OPTIMIZE} =~ /-O(\d*)/) {
$self->{OPTIMIZE} = '/Optimize' . (defined($1) ? "=$1" : '');
}
else {
warn "MM_VMS: Can't parse OPTIMIZE \"$self->{OPTIMIZE}\"; using default\n" if length $self->{OPTIMIZE};
$self->{OPTIMIZE} = '/Optimize';
}
}
return $self->{CFLAGS} = qq{
CCFLAGS = $self->{CCFLAGS}
OPTIMIZE = $self->{OPTIMIZE}
PERLTYPE = $self->{PERLTYPE}
};
}
=item const_cccmd (override)
Adds directives to point C preprocessor to the right place when
handling #include E<lt>sys/foo.hE<gt> directives. Also constructs CC
command line a bit differently than MM_Unix method.
=cut
sub const_cccmd {
my($self,$libperl) = @_;
my(@m);
return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
return '' unless $self->needs_linking();
if ($Config{'vms_cc_type'} eq 'gcc') {
push @m,'
.FIRST
',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" Then Define/NoLog SYS GNU_CC_Include:[VMS]';
}
elsif ($Config{'vms_cc_type'} eq 'vaxc') {
push @m,'
.FIRST
',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("VAXC$Include").eqs."" Then Define/NoLog SYS Sys$Library
',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("VAXC$Include").nes."" Then Define/NoLog SYS VAXC$Include';
}
else {
push @m,'
.FIRST
',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("DECC$System_Include").eqs."" Then Define/NoLog SYS ',
($Config{'archname'} eq 'VMS_AXP' ? 'Sys$Library' : 'DECC$Library_Include'),'
',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("DECC$System_Include").nes."" Then Define/NoLog SYS DECC$System_Include';
}
push(@m, "\n\nCCCMD = $Config{'cc'} \$(CCFLAGS)\$(OPTIMIZE)\n");
$self->{CONST_CCCMD} = join('',@m);
}
=item tools_other (override)
Throw in some dubious extra macros for Makefile args.
Also keep around the old $(SAY) macro in case somebody's using it.
=cut
sub tools_other {
my($self) = @_;
# XXX Are these necessary? Does anyone override them? They're longer
# than just typing the literal string.
my $extra_tools = <<'EXTRA_TOOLS';
# Just in case anyone is using the old macro.
USEMACROS = $(MACROSTART)
SAY = $(ECHO)
EXTRA_TOOLS
return $self->SUPER::tools_other . $extra_tools;
}
=item init_dist (override)
VMSish defaults for some values.
macro description default
ZIPFLAGS flags to pass to ZIP -Vu
COMPRESS compression command to gzip
use for tarfiles
SUFFIX suffix to put on -gz
compressed files
SHAR shar command to use vms_share
DIST_DEFAULT default target to use to tardist
create a distribution
DISTVNAME Use VERSION_SYM instead of $(DISTNAME)-$(VERSION_SYM)
VERSION for the name
=cut
sub init_dist {
my($self) = @_;
$self->{ZIPFLAGS} ||= '-Vu';
$self->{COMPRESS} ||= 'gzip';
$self->{SUFFIX} ||= '-gz';
$self->{SHAR} ||= 'vms_share';
$self->{DIST_DEFAULT} ||= 'zipdist';
$self->SUPER::init_dist;
$self->{DISTVNAME} = "$self->{DISTNAME}-$self->{VERSION_SYM}"
unless $self->{ARGS}{DISTVNAME};
return;
}
=item c_o (override)
Use VMS syntax on command line. In particular, $(DEFINE) and
$(PERL_INC) have been pulled into $(CCCMD). Also use MM[SK] macros.
=cut
sub c_o {
my($self) = @_;
return '' unless $self->needs_linking();
'
.c$(OBJ_EXT) :
$(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).c
.cpp$(OBJ_EXT) :
$(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).cpp
.cxx$(OBJ_EXT) :
$(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).cxx
';
}
=item xs_c (override)
Use MM[SK] macros.
=cut
sub xs_c {
my($self) = @_;
return '' unless $self->needs_linking();
'
.xs.c :
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET)
';
}
=item xs_o (override)
Use MM[SK] macros, and VMS command line for C compiler.
=cut
sub xs_o { # many makes are too dumb to use xs_c then c_o
my($self) = @_;
return '' unless $self->needs_linking();
'
.xs$(OBJ_EXT) :
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET_NAME).c
$(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).c
';
}
=item dlsyms (override)
Create VMS linker options files specifying universal symbols for this
extension's shareable image, and listing other shareable images or
libraries to which it should be linked.
=cut
sub dlsyms {
my($self,%attribs) = @_;
return '' unless $self->needs_linking();
my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || [];
my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
my(@m);
unless ($self->{SKIPHASH}{'dynamic'}) {
push(@m,'
dynamic :: $(INST_ARCHAUTODIR)$(BASEEXT).opt
$(NOECHO) $(NOOP)
');
}
push(@m,'
static :: $(INST_ARCHAUTODIR)$(BASEEXT).opt
$(NOECHO) $(NOOP)
') unless $self->{SKIPHASH}{'static'};
push @m,'
$(INST_ARCHAUTODIR)$(BASEEXT).opt : $(BASEEXT).opt
$(CP) $(MMS$SOURCE) $(MMS$TARGET)
$(BASEEXT).opt : Makefile.PL
$(PERLRUN) -e "use ExtUtils::Mksymlists;" -
',qq[-e "Mksymlists('NAME' => '$self->{NAME}', 'DL_FUNCS' => ],
neatvalue($funcs),q[, 'DL_VARS' => ],neatvalue($vars),
q[, 'FUNCLIST' => ],neatvalue($funclist),qq[)"\n];
push @m, ' $(PERL) -e "print ""$(INST_STATIC)/Include=';
if ($self->{OBJECT} =~ /\bBASEEXT\b/ or
$self->{OBJECT} =~ /\b$self->{BASEEXT}\b/i) {
push @m, ($Config{d_vms_case_sensitive_symbols}
? uc($self->{BASEEXT}) :'$(BASEEXT)');
}
else { # We don't have a "main" object file, so pull 'em all in
# Upcase module names if linker is being case-sensitive
my($upcase) = $Config{d_vms_case_sensitive_symbols};
my(@omods) = split ' ', $self->eliminate_macros($self->{OBJECT});
for (@omods) {
s/\.[^.]*$//; # Trim off file type
s[\$\(\w+_EXT\)][]; # even as a macro
s/.*[:>\/\]]//; # Trim off dir spec
$_ = uc if $upcase;
};
my(@lines);
my $tmp = shift @omods;
foreach my $elt (@omods) {
$tmp .= ",$elt";
if (length($tmp) > 80) { push @lines, $tmp; $tmp = ''; }
}
push @lines, $tmp;
push @m, '(', join( qq[, -\\n\\t"";" >>\$(MMS\$TARGET)\n\t\$(PERL) -e "print ""], @lines),')';
}
push @m, '\n$(INST_STATIC)/Library\n"";" >>$(MMS$TARGET)',"\n";
if (length $self->{LDLOADLIBS}) {
my($line) = '';
foreach my $lib (split ' ', $self->{LDLOADLIBS}) {
$lib =~ s%\$%\\\$%g; # Escape '$' in VMS filespecs
if (length($line) + length($lib) > 160) {
push @m, "\t\$(PERL) -e \"print qq{$line}\" >>\$(MMS\$TARGET)\n";
$line = $lib . '\n';
}
else { $line .= $lib . '\n'; }
}
push @m, "\t\$(PERL) -e \"print qq{$line}\" >>\$(MMS\$TARGET)\n" if $line;
}
join('',@m);
}
=item dynamic_lib (override)
Use VMS Link command.
=cut
sub dynamic_lib {
my($self, %attribs) = @_;
return '' unless $self->needs_linking(); #might be because of a subdir
return '' unless $self->has_link_code();
my($otherldflags) = $attribs{OTHERLDFLAGS} || "";
my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
my $shr = $Config{'dbgprefix'} . 'PerlShr';
my(@m);
push @m,"
OTHERLDFLAGS = $otherldflags
INST_DYNAMIC_DEP = $inst_dynamic_dep
";
push @m, '
$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
If F$TrnLNm("',$shr,'").eqs."" Then Define/NoLog/User ',"$shr Sys\$Share:$shr.$Config{'dlext'}",'
Link $(LDFLAGS) /Shareable=$(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,$(PERL_INC)perlshr_attr.opt/Option
';
join('',@m);
}
=item static_lib (override)
Use VMS commands to manipulate object library.
=cut
sub static_lib {
my($self) = @_;
return '' unless $self->needs_linking();
return '
$(INST_STATIC) :
$(NOECHO) $(NOOP)
' unless ($self->{OBJECT} or @{$self->{C} || []} or $self->{MYEXTLIB});
my(@m);
push @m,'
# Rely on suffix rule for update action
$(OBJECT) : $(INST_ARCHAUTODIR)$(DFSEP).exists
$(INST_STATIC) : $(OBJECT) $(MYEXTLIB)
';
# If this extension has its own library (eg SDBM_File)
# then copy that to $(INST_STATIC) and add $(OBJECT) into it.
push(@m, "\t",'$(CP) $(MYEXTLIB) $(MMS$TARGET)',"\n") if $self->{MYEXTLIB};
push(@m,"\t",'If F$Search("$(MMS$TARGET)").eqs."" Then Library/Object/Create $(MMS$TARGET)',"\n");
# if there was a library to copy, then we can't use MMS$SOURCE_LIST,
# 'cause it's a library and you can't stick them in other libraries.
# In that case, we use $OBJECT instead and hope for the best
if ($self->{MYEXTLIB}) {
push(@m,"\t",'Library/Object/Replace $(MMS$TARGET) $(OBJECT)',"\n");
} else {
push(@m,"\t",'Library/Object/Replace $(MMS$TARGET) $(MMS$SOURCE_LIST)',"\n");
}
push @m, "\t\$(NOECHO) \$(PERL) -e 1 >\$(INST_ARCHAUTODIR)extralibs.ld\n";
foreach my $lib (split ' ', $self->{EXTRALIBS}) {
push(@m,"\t",'$(NOECHO) $(PERL) -e "print qq{',$lib,'\n}" >>$(INST_ARCHAUTODIR)extralibs.ld',"\n");
}
join('',@m);
}
=item extra_clean_files
Clean up some OS specific files. Plus the temp file used to shorten
a lot of commands. And the name mangler database.
=cut
sub extra_clean_files {
return qw(
*.Map *.Dmp *.Lis *.cpp *.$(DLEXT) *.Opt $(BASEEXT).bso
.MM_Tmp cxx_repository
);
}
=item zipfile_target
=item tarfile_target
=item shdist_target
Syntax for invoking shar, tar and zip differs from that for Unix.
=cut
sub zipfile_target {
my($self) = shift;
return <<'MAKE_FRAG';
$(DISTVNAME).zip : distdir
$(PREOP)
$(ZIP) "$(ZIPFLAGS)" $(MMS$TARGET) [.$(DISTVNAME)...]*.*;
$(RM_RF) $(DISTVNAME)
$(POSTOP)
MAKE_FRAG
}
sub tarfile_target {
my($self) = shift;
return <<'MAKE_FRAG';
$(DISTVNAME).tar$(SUFFIX) : distdir
$(PREOP)
$(TO_UNIX)
$(TAR) "$(TARFLAGS)" $(DISTVNAME).tar [.$(DISTVNAME)...]
$(RM_RF) $(DISTVNAME)
$(COMPRESS) $(DISTVNAME).tar
$(POSTOP)
MAKE_FRAG
}
sub shdist_target {
my($self) = shift;
return <<'MAKE_FRAG';
shdist : distdir
$(PREOP)
$(SHAR) [.$(DISTVNAME)...]*.*; $(DISTVNAME).share
$(RM_RF) $(DISTVNAME)
$(POSTOP)
MAKE_FRAG
}
# --- Test and Installation Sections ---
=item install (override)
Work around DCL's 255 character limit several times,and use
VMS-style command line quoting in a few cases.
=cut
sub install {
my($self, %attribs) = @_;
my(@m);
push @m, q[
install :: all pure_install doc_install
$(NOECHO) $(NOOP)
install_perl :: all pure_perl_install doc_perl_install
$(NOECHO) $(NOOP)
install_site :: all pure_site_install doc_site_install
$(NOECHO) $(NOOP)
pure_install :: pure_$(INSTALLDIRS)_install
$(NOECHO) $(NOOP)
doc_install :: doc_$(INSTALLDIRS)_install
$(NOECHO) $(NOOP)
pure__install : pure_site_install
$(NOECHO) $(ECHO) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
doc__install : doc_site_install
$(NOECHO) $(ECHO) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
# This hack brought to you by DCL's 255-character command line limit
pure_perl_install ::
$(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
$(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(DESTINSTALLARCHLIB)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_LIB) $(DESTINSTALLPRIVLIB) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_ARCHLIB) $(DESTINSTALLARCHLIB) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_BIN) $(DESTINSTALLBIN) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_SCRIPT) $(DESTINSTALLSCRIPT) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_MAN3DIR) $(DESTINSTALLMAN3DIR) " >>.MM_tmp
$(NOECHO) $(MOD_INSTALL) <.MM_tmp
$(NOECHO) $(RM_F) .MM_tmp
$(NOECHO) $(WARN_IF_OLD_PACKLIST) ].$self->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist').q[
# Likewise
pure_site_install ::
$(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
$(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(DESTINSTALLSITEARCH)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_LIB) $(DESTINSTALLSITELIB) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_ARCHLIB) $(DESTINSTALLSITEARCH) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_BIN) $(DESTINSTALLSITEBIN) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_SCRIPT) $(DESTINSTALLSCRIPT) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR) " >>.MM_tmp
$(NOECHO) $(MOD_INSTALL) <.MM_tmp
$(NOECHO) $(RM_F) .MM_tmp
$(NOECHO) $(WARN_IF_OLD_PACKLIST) ].$self->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
pure_vendor_install ::
$(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
$(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(DESTINSTALLVENDORARCH)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_LIB) $(DESTINSTALLVENDORLIB) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_BIN) $(DESTINSTALLVENDORBIN) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_SCRIPT) $(DESTINSTALLSCRIPT) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) " >>.MM_tmp
$(NOECHO) $(ECHO_N) "$(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR) " >>.MM_tmp
$(NOECHO) $(MOD_INSTALL) <.MM_tmp
$(NOECHO) $(RM_F) .MM_tmp
# Ditto
doc_perl_install ::
$(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{DESTINSTALLARCHLIB}, 'perllocal.pod').q["
$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
$(NOECHO) $(ECHO_N) "installed into|$(INSTALLPRIVLIB)|" >.MM_tmp
$(NOECHO) $(ECHO_N) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
$(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{DESTINSTALLARCHLIB},'perllocal.pod').q[
$(NOECHO) $(RM_F) .MM_tmp
# And again
doc_site_install ::
$(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{DESTINSTALLARCHLIB}, 'perllocal.pod').q["
$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
$(NOECHO) $(ECHO_N) "installed into|$(INSTALLSITELIB)|" >.MM_tmp
$(NOECHO) $(ECHO_N) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
$(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{DESTINSTALLARCHLIB},'perllocal.pod').q[
$(NOECHO) $(RM_F) .MM_tmp
doc_vendor_install ::
$(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{DESTINSTALLARCHLIB}, 'perllocal.pod').q["
$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
$(NOECHO) $(ECHO_N) "installed into|$(INSTALLVENDORLIB)|" >.MM_tmp
$(NOECHO) $(ECHO_N) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
$(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{DESTINSTALLARCHLIB},'perllocal.pod').q[
$(NOECHO) $(RM_F) .MM_tmp
];
push @m, q[
uninstall :: uninstall_from_$(INSTALLDIRS)dirs
$(NOECHO) $(NOOP)
uninstall_from_perldirs ::
$(NOECHO) $(UNINSTALL) ].$self->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
$(NOECHO) $(ECHO) "Uninstall is now deprecated and makes no actual changes."
$(NOECHO) $(ECHO) "Please check the list above carefully for errors, and manually remove"
$(NOECHO) $(ECHO) "the appropriate files. Sorry for the inconvenience."
uninstall_from_sitedirs ::
$(NOECHO) $(UNINSTALL) ].$self->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist').q[
$(NOECHO) $(ECHO) "Uninstall is now deprecated and makes no actual changes."
$(NOECHO) $(ECHO) "Please check the list above carefully for errors, and manually remove"
$(NOECHO) $(ECHO) "the appropriate files. Sorry for the inconvenience."
];
join('',@m);
}
=item perldepend (override)
Use VMS-style syntax for files; it's cheaper to just do it directly here
than to have the MM_Unix method call C<catfile> repeatedly. Also, if
we have to rebuild Config.pm, use MM[SK] to do it.
=cut
sub perldepend {
my($self) = @_;
my(@m);
push @m, '
$(OBJECT) : $(PERL_INC)EXTERN.h, $(PERL_INC)INTERN.h, $(PERL_INC)XSUB.h
$(OBJECT) : $(PERL_INC)av.h, $(PERL_INC)config.h
$(OBJECT) : $(PERL_INC)cop.h, $(PERL_INC)cv.h, $(PERL_INC)embed.h
$(OBJECT) : $(PERL_INC)embedvar.h, $(PERL_INC)form.h
$(OBJECT) : $(PERL_INC)gv.h, $(PERL_INC)handy.h, $(PERL_INC)hv.h
$(OBJECT) : $(PERL_INC)intrpvar.h, $(PERL_INC)iperlsys.h, $(PERL_INC)keywords.h
$(OBJECT) : $(PERL_INC)mg.h, $(PERL_INC)nostdio.h, $(PERL_INC)op.h
$(OBJECT) : $(PERL_INC)opcode.h, $(PERL_INC)patchlevel.h
$(OBJECT) : $(PERL_INC)perl.h, $(PERL_INC)perlio.h
$(OBJECT) : $(PERL_INC)perlsdio.h, $(PERL_INC)perlvars.h
$(OBJECT) : $(PERL_INC)perly.h, $(PERL_INC)pp.h, $(PERL_INC)pp_proto.h
$(OBJECT) : $(PERL_INC)proto.h, $(PERL_INC)regcomp.h, $(PERL_INC)regexp.h
$(OBJECT) : $(PERL_INC)regnodes.h, $(PERL_INC)scope.h, $(PERL_INC)sv.h
$(OBJECT) : $(PERL_INC)thread.h, $(PERL_INC)util.h, $(PERL_INC)vmsish.h
' if $self->{OBJECT};
if ($self->{PERL_SRC}) {
my(@macros);
my($mmsquals) = '$(USEMAKEFILE)[.vms]$(FIRST_MAKEFILE)';
push(@macros,'__AXP__=1') if $Config{'archname'} eq 'VMS_AXP';
push(@macros,'DECC=1') if $Config{'vms_cc_type'} eq 'decc';
push(@macros,'GNUC=1') if $Config{'vms_cc_type'} eq 'gcc';
push(@macros,'SOCKET=1') if $Config{'d_has_sockets'};
push(@macros,qq["CC=$Config{'cc'}"]) if $Config{'cc'} =~ m!/!;
$mmsquals .= '$(USEMACROS)' . join(',',@macros) . '$(MACROEND)' if @macros;
push(@m,q[
# Check for unpropagated config.sh changes. Should never happen.
# We do NOT just update config.h because that is not sufficient.
# An out of date config.h is not fatal but complains loudly!
$(PERL_INC)config.h : $(PERL_SRC)config.sh
$(NOOP)
$(PERL_ARCHLIB)Config.pm : $(PERL_SRC)config.sh
$(NOECHO) Write Sys$Error "$(PERL_ARCHLIB)Config.pm may be out of date with config.h or genconfig.pl"
olddef = F$Environment("Default")
Set Default $(PERL_SRC)
$(MMS)],$mmsquals,);
if ($self->{PERL_ARCHLIB} =~ m|\[-| && $self->{PERL_SRC} =~ m|(\[-+)|) {
my($prefix,$target) = ($1,$self->fixpath('$(PERL_ARCHLIB)Config.pm',0));
$target =~ s/\Q$prefix/[/;
push(@m," $target");
}
else { push(@m,' $(MMS$TARGET)'); }
push(@m,q[
Set Default 'olddef'
]);
}
push(@m, join(" ", map($self->fixpath($_,0),values %{$self->{XS}}))." : \$(XSUBPPDEPS)\n")
if %{$self->{XS}};
join('',@m);
}
=item makeaperl (override)
Undertake to build a new set of Perl images using VMS commands. Since
VMS does dynamic loading, it's not necessary to statically link each
extension into the Perl image, so this isn't the normal build path.
Consequently, it hasn't really been tested, and may well be incomplete.
=cut
our %olbs; # needs to be localized
sub makeaperl {
my($self, %attribs) = @_;
my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmpdir, $libperl) =
@attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)};
my(@m);
push @m, "
# --- MakeMaker makeaperl section ---
MAP_TARGET = $target
";
return join '', @m if $self->{PARENT};
my($dir) = join ":", @{$self->{DIR}};
unless ($self->{MAKEAPERL}) {
push @m, q{
$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE)
$(NOECHO) $(ECHO) "Writing ""$(MMS$TARGET)"" for this $(MAP_TARGET)"
$(NOECHO) $(PERLRUNINST) \
Makefile.PL DIR=}, $dir, q{ \
FIRST_MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
MAKEAPERL=1 NORECURS=1 };
push @m, map(q[ \\\n\t\t"$_"], @ARGV),q{
$(MAP_TARGET) :: $(MAKE_APERL_FILE)
$(MAKE)$(USEMAKEFILE)$(MAKE_APERL_FILE) static $(MMS$TARGET)
};
push @m, "\n";
return join '', @m;
}
my($linkcmd,@optlibs,@staticpkgs,$extralist,$targdir,$libperldir,%libseen);
local($_);
# The front matter of the linkcommand...
$linkcmd = join ' ', $Config{'ld'},
grep($_, @Config{qw(large split ldflags ccdlflags)});
$linkcmd =~ s/\s+/ /g;
# Which *.olb files could we make use of...
local(%olbs); # XXX can this be lexical?
$olbs{$self->{INST_ARCHAUTODIR}} = "$self->{BASEEXT}\$(LIB_EXT)";
require File::Find;
File::Find::find(sub {
return unless m/\Q$self->{LIB_EXT}\E$/;
return if m/^libperl/;
if( exists $self->{INCLUDE_EXT} ){
my $found = 0;
(my $xx = $File::Find::name) =~ s,.*?/auto/,,;
$xx =~ s,/?$_,,;
$xx =~ s,/,::,g;
# Throw away anything not explicitly marked for inclusion.
# DynaLoader is implied.
foreach my $incl ((@{$self->{INCLUDE_EXT}},'DynaLoader')){
if( $xx eq $incl ){
$found++;
last;
}
}
return unless $found;
}
elsif( exists $self->{EXCLUDE_EXT} ){
(my $xx = $File::Find::name) =~ s,.*?/auto/,,;
$xx =~ s,/?$_,,;
$xx =~ s,/,::,g;
# Throw away anything explicitly marked for exclusion
foreach my $excl (@{$self->{EXCLUDE_EXT}}){
return if( $xx eq $excl );
}
}
$olbs{$ENV{DEFAULT}} = $_;
}, grep( -d $_, @{$searchdirs || []}));
# We trust that what has been handed in as argument will be buildable
$static = [] unless $static;
@olbs{@{$static}} = (1) x @{$static};
$extra = [] unless $extra && ref $extra eq 'ARRAY';
# Sort the object libraries in inverse order of
# filespec length to try to insure that dependent extensions
# will appear before their parents, so the linker will
# search the parent library to resolve references.
# (e.g. Intuit::DWIM will precede Intuit, so unresolved
# references from [.intuit.dwim]dwim.obj can be found
# in [.intuit]intuit.olb).
for (sort { length($a) <=> length($b) } keys %olbs) {
next unless $olbs{$_} =~ /\Q$self->{LIB_EXT}\E$/;
my($dir) = $self->fixpath($_,1);
my($extralibs) = $dir . "extralibs.ld";
my($extopt) = $dir . $olbs{$_};
$extopt =~ s/$self->{LIB_EXT}$/.opt/;
push @optlibs, "$dir$olbs{$_}";
# Get external libraries this extension will need
if (-f $extralibs ) {
my %seenthis;
open my $list, "<", $extralibs or warn $!,next;
while (<$list>) {
chomp;
# Include a library in the link only once, unless it's mentioned
# multiple times within a single extension's options file, in which
# case we assume the builder needed to search it again later in the
# link.
my $skip = exists($libseen{$_}) && !exists($seenthis{$_});
$libseen{$_}++; $seenthis{$_}++;
next if $skip;
push @$extra,$_;
}
}
# Get full name of extension for ExtUtils::Miniperl
if (-f $extopt) {
open my $opt, '<', $extopt or die $!;
while (<$opt>) {
next unless /(?:UNIVERSAL|VECTOR)=boot_([\w_]+)/;
my $pkg = $1;
$pkg =~ s#__*#::#g;
push @staticpkgs,$pkg;
}
}
}
# Place all of the external libraries after all of the Perl extension
# libraries in the final link, in order to maximize the opportunity
# for XS code from multiple extensions to resolve symbols against the
# same external library while only including that library once.
push @optlibs, @$extra;
$target = "Perl$Config{'exe_ext'}" unless $target;
my $shrtarget;
($shrtarget,$targdir) = fileparse($target);
$shrtarget =~ s/^([^.]*)/$1Shr/;
$shrtarget = $targdir . $shrtarget;
$target = "Perlshr.$Config{'dlext'}" unless $target;
$tmpdir = "[]" unless $tmpdir;
$tmpdir = $self->fixpath($tmpdir,1);
if (@optlibs) { $extralist = join(' ',@optlibs); }
else { $extralist = ''; }
# Let ExtUtils::Liblist find the necessary libs for us (but skip PerlShr)
# that's what we're building here).
push @optlibs, grep { !/PerlShr/i } split ' ', +($self->ext())[2];
if ($libperl) {
unless (-f $libperl || -f ($libperl = $self->catfile($Config{'installarchlib'},'CORE',$libperl))) {
print STDOUT "Warning: $libperl not found\n";
undef $libperl;
}
}
unless ($libperl) {
if (defined $self->{PERL_SRC}) {
$libperl = $self->catfile($self->{PERL_SRC},"libperl$self->{LIB_EXT}");
} elsif (-f ($libperl = $self->catfile($Config{'installarchlib'},'CORE',"libperl$self->{LIB_EXT}")) ) {
} else {
print STDOUT "Warning: $libperl not found
If you're going to build a static perl binary, make sure perl is installed
otherwise ignore this warning\n";
}
}
$libperldir = $self->fixpath((fileparse($libperl))[1],1);
push @m, '
# Fill in the target you want to produce if it\'s not perl
MAP_TARGET = ',$self->fixpath($target,0),'
MAP_SHRTARGET = ',$self->fixpath($shrtarget,0),"
MAP_LINKCMD = $linkcmd
MAP_PERLINC = ", $perlinc ? map('"$_" ',@{$perlinc}) : '',"
MAP_EXTRA = $extralist
MAP_LIBPERL = ",$self->fixpath($libperl,0),'
';
push @m,"\n${tmpdir}Makeaperl.Opt : \$(MAP_EXTRA)\n";
foreach (@optlibs) {
push @m,' $(NOECHO) $(PERL) -e "print q{',$_,'}" >>$(MMS$TARGET)',"\n";
}
push @m,"\n${tmpdir}PerlShr.Opt :\n\t";
push @m,'$(NOECHO) $(PERL) -e "print q{$(MAP_SHRTARGET)}" >$(MMS$TARGET)',"\n";
push @m,'
$(MAP_SHRTARGET) : $(MAP_LIBPERL) Makeaperl.Opt ',"${libperldir}Perlshr_Attr.Opt",'
$(MAP_LINKCMD)/Shareable=$(MMS$TARGET) $(MAP_LIBPERL), Makeaperl.Opt/Option ',"${libperldir}Perlshr_Attr.Opt/Option",'
$(MAP_TARGET) : $(MAP_SHRTARGET) ',"${tmpdir}perlmain\$(OBJ_EXT) ${tmpdir}PerlShr.Opt",'
$(MAP_LINKCMD) ',"${tmpdir}perlmain\$(OBJ_EXT)",', PerlShr.Opt/Option
$(NOECHO) $(ECHO) "To install the new ""$(MAP_TARGET)"" binary, say"
$(NOECHO) $(ECHO) " $(MAKE)$(USEMAKEFILE)$(FIRST_MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)"
$(NOECHO) $(ECHO) "To remove the intermediate files, say
$(NOECHO) $(ECHO) " $(MAKE)$(USEMAKEFILE)$(FIRST_MAKEFILE) map_clean"
';
push @m,"\n${tmpdir}perlmain.c : \$(FIRST_MAKEFILE)\n\t\$(NOECHO) \$(PERL) -e 1 >${tmpdir}Writemain.tmp\n";
push @m, "# More from the 255-char line length limit\n";
foreach (@staticpkgs) {
push @m,' $(NOECHO) $(PERL) -e "print q{',$_,qq[}" >>${tmpdir}Writemain.tmp\n];
}
push @m, sprintf <<'MAKE_FRAG', $tmpdir, $tmpdir;
$(NOECHO) $(PERL) $(MAP_PERLINC) -ane "use ExtUtils::Miniperl; writemain(@F)" %sWritemain.tmp >$(MMS$TARGET)
$(NOECHO) $(RM_F) %sWritemain.tmp
MAKE_FRAG
push @m, q[
# Still more from the 255-char line length limit
doc_inst_perl :
$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
$(NOECHO) $(ECHO) "Perl binary $(MAP_TARGET)|" >.MM_tmp
$(NOECHO) $(ECHO) "MAP_STATIC|$(MAP_STATIC)|" >>.MM_tmp
$(NOECHO) $(PERL) -pl040 -e " " ].$self->catfile('$(INST_ARCHAUTODIR)','extralibs.all'),q[ >>.MM_tmp
$(NOECHO) $(ECHO) -e "MAP_LIBPERL|$(MAP_LIBPERL)|" >>.MM_tmp
$(NOECHO) $(DOC_INSTALL) <.MM_tmp >>].$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q[
$(NOECHO) $(RM_F) .MM_tmp
];
push @m, "
inst_perl : pure_inst_perl doc_inst_perl
\$(NOECHO) \$(NOOP)
pure_inst_perl : \$(MAP_TARGET)
$self->{CP} \$(MAP_SHRTARGET) ",$self->fixpath($Config{'installbin'},1),"
$self->{CP} \$(MAP_TARGET) ",$self->fixpath($Config{'installbin'},1),"
clean :: map_clean
\$(NOECHO) \$(NOOP)
map_clean :
\$(RM_F) ${tmpdir}perlmain\$(OBJ_EXT) ${tmpdir}perlmain.c \$(FIRST_MAKEFILE)
\$(RM_F) ${tmpdir}Makeaperl.Opt ${tmpdir}PerlShr.Opt \$(MAP_TARGET)
";
join '', @m;
}
# --- Output postprocessing section ---
=item maketext_filter (override)
Insure that colons marking targets are preceded by space, in order
to distinguish the target delimiter from a colon appearing as
part of a filespec.
=cut
sub maketext_filter {
my($self, $text) = @_;
$text =~ s/^([^\s:=]+)(:+\s)/$1 $2/mg;
return $text;
}
=item prefixify (override)
prefixifying on VMS is simple. Each should simply be:
perl_root:[some.dir]
which can just be converted to:
volume:[your.prefix.some.dir]
otherwise you get the default layout.
In effect, your search prefix is ignored and $Config{vms_prefix} is
used instead.
=cut
sub prefixify {
my($self, $var, $sprefix, $rprefix, $default) = @_;
# Translate $(PERLPREFIX) to a real path.
$rprefix = $self->eliminate_macros($rprefix);
$rprefix = vmspath($rprefix) if $rprefix;
$sprefix = vmspath($sprefix) if $sprefix;
$default = vmsify($default)
unless $default =~ /\[.*\]/;
(my $var_no_install = $var) =~ s/^install//;
my $path = $self->{uc $var} ||
$ExtUtils::MM_Unix::Config_Override{lc $var} ||
$Config{lc $var} || $Config{lc $var_no_install};
if( !$path ) {
print STDERR " no Config found for $var.\n" if $Verbose >= 2;
$path = $self->_prefixify_default($rprefix, $default);
}
elsif( !$self->{ARGS}{PREFIX} || !$self->file_name_is_absolute($path) ) {
# do nothing if there's no prefix or if its relative
}
elsif( $sprefix eq $rprefix ) {
print STDERR " no new prefix.\n" if $Verbose >= 2;
}
else {
print STDERR " prefixify $var => $path\n" if $Verbose >= 2;
print STDERR " from $sprefix to $rprefix\n" if $Verbose >= 2;
my($path_vol, $path_dirs) = $self->splitpath( $path );
if( $path_vol eq $Config{vms_prefix}.':' ) {
print STDERR " $Config{vms_prefix}: seen\n" if $Verbose >= 2;
$path_dirs =~ s{^\[}{\[.} unless $path_dirs =~ m{^\[\.};
$path = $self->_catprefix($rprefix, $path_dirs);
}
else {
$path = $self->_prefixify_default($rprefix, $default);
}
}
print " now $path\n" if $Verbose >= 2;
return $self->{uc $var} = $path;
}
sub _prefixify_default {
my($self, $rprefix, $default) = @_;
print STDERR " cannot prefix, using default.\n" if $Verbose >= 2;
if( !$default ) {
print STDERR "No default!\n" if $Verbose >= 1;
return;
}
if( !$rprefix ) {
print STDERR "No replacement prefix!\n" if $Verbose >= 1;
return '';
}
return $self->_catprefix($rprefix, $default);
}
sub _catprefix {
my($self, $rprefix, $default) = @_;
my($rvol, $rdirs) = $self->splitpath($rprefix);
if( $rvol ) {
return $self->catpath($rvol,
$self->catdir($rdirs, $default),
''
)
}
else {
return $self->catdir($rdirs, $default);
}
}
=item cd
=cut
sub cd {
my($self, $dir, @cmds) = @_;
$dir = vmspath($dir);
my $cmd = join "\n\t", map "$_", @cmds;
# No leading tab makes it look right when embedded
my $make_frag = sprintf <<'MAKE_FRAG', $dir, $cmd;
startdir = F$Environment("Default")
Set Default %s
%s
Set Default 'startdir'
MAKE_FRAG
# No trailing newline makes this easier to embed
chomp $make_frag;
return $make_frag;
}
=item oneliner
=cut
sub oneliner {
my($self, $cmd, $switches) = @_;
$switches = [] unless defined $switches;
# Strip leading and trailing newlines
$cmd =~ s{^\n+}{};
$cmd =~ s{\n+$}{};
$cmd = $self->quote_literal($cmd);
$cmd = $self->escape_newlines($cmd);
# Switches must be quoted else they will be lowercased.
$switches = join ' ', map { qq{"$_"} } @$switches;
return qq{\$(ABSPERLRUN) $switches -e $cmd "--"};
}
=item B<echo>
perl trips up on "<foo>" thinking it's an input redirect. So we use the
native Write command instead. Besides, its faster.
=cut
sub echo {
my($self, $text, $file, $appending) = @_;
$appending ||= 0;
my $opencmd = $appending ? 'Open/Append' : 'Open/Write';
my @cmds = ("\$(NOECHO) $opencmd MMECHOFILE $file ");
push @cmds, map { '$(NOECHO) Write MMECHOFILE '.$self->quote_literal($_) }
split /\n/, $text;
push @cmds, '$(NOECHO) Close MMECHOFILE';
return @cmds;
}
=item quote_literal
=cut
sub quote_literal {
my($self, $text) = @_;
# I believe this is all we should need.
$text =~ s{"}{""}g;
return qq{"$text"};
}
=item escape_newlines
=cut
sub escape_newlines {
my($self, $text) = @_;
$text =~ s{\n}{-\n}g;
return $text;
}
=item max_exec_len
256 characters.
=cut
sub max_exec_len {
my $self = shift;
return $self->{_MAX_EXEC_LEN} ||= 256;
}
=item init_linker
=cut
sub init_linker {
my $self = shift;
$self->{EXPORT_LIST} ||= '$(BASEEXT).opt';
my $shr = $Config{dbgprefix} . 'PERLSHR';
if ($self->{PERL_SRC}) {
$self->{PERL_ARCHIVE} ||=
$self->catfile($self->{PERL_SRC}, "$shr.$Config{'dlext'}");
}
else {
$self->{PERL_ARCHIVE} ||=
$ENV{$shr} ? $ENV{$shr} : "Sys\$Share:$shr.$Config{'dlext'}";
}
$self->{PERL_ARCHIVE_AFTER} ||= '';
}
=item catdir (override)
=item catfile (override)
Eliminate the macros in the output to the MMS/MMK file.
(File::Spec::VMS used to do this for us, but it's being removed)
=cut
sub catdir {
my $self = shift;
# Process the macros on VMS MMS/MMK
my @args = map { m{\$\(} ? $self->eliminate_macros($_) : $_ } @_;
my $dir = $self->SUPER::catdir(@args);
# Fix up the directory and force it to VMS format.
$dir = $self->fixpath($dir, 1);
return $dir;
}
sub catfile {
my $self = shift;
# Process the macros on VMS MMS/MMK
my @args = map { m{\$\(} ? $self->eliminate_macros($_) : $_ } @_;
my $file = $self->SUPER::catfile(@args);
$file = vmsify($file);
return $file
}
=item eliminate_macros
Expands MM[KS]/Make macros in a text string, using the contents of
identically named elements of C<%$self>, and returns the result
as a file specification in Unix syntax.
NOTE: This is the canonical version of the method. The version in
File::Spec::VMS is deprecated.
=cut
sub eliminate_macros {
my($self,$path) = @_;
return '' unless $path;
$self = {} unless ref $self;
if ($path =~ /\s/) {
return join ' ', map { $self->eliminate_macros($_) } split /\s+/, $path;
}
my($npath) = unixify($path);
# sometimes unixify will return a string with an off-by-one trailing null
$npath =~ s{\0$}{};
my($complex) = 0;
my($head,$macro,$tail);
# perform m##g in scalar context so it acts as an iterator
while ($npath =~ m#(.*?)\$\((\S+?)\)(.*)#gs) {
if (defined $self->{$2}) {
($head,$macro,$tail) = ($1,$2,$3);
if (ref $self->{$macro}) {
if (ref $self->{$macro} eq 'ARRAY') {
$macro = join ' ', @{$self->{$macro}};
}
else {
print "Note: can't expand macro \$($macro) containing ",ref($self->{$macro}),
"\n\t(using MMK-specific deferred substitutuon; MMS will break)\n";
$macro = "\cB$macro\cB";
$complex = 1;
}
}
else { ($macro = unixify($self->{$macro})) =~ s#/\Z(?!\n)##; }
$npath = "$head$macro$tail";
}
}
if ($complex) { $npath =~ s#\cB(.*?)\cB#\${$1}#gs; }
$npath;
}
=item fixpath
my $path = $mm->fixpath($path);
my $path = $mm->fixpath($path, $is_dir);
Catchall routine to clean up problem MM[SK]/Make macros. Expands macros
in any directory specification, in order to avoid juxtaposing two
VMS-syntax directories when MM[SK] is run. Also expands expressions which
are all macro, so that we can tell how long the expansion is, and avoid
overrunning DCL's command buffer when MM[KS] is running.
fixpath() checks to see whether the result matches the name of a
directory in the current default directory and returns a directory or
file specification accordingly. C<$is_dir> can be set to true to
force fixpath() to consider the path to be a directory or false to force
it to be a file.
NOTE: This is the canonical version of the method. The version in
File::Spec::VMS is deprecated.
=cut
sub fixpath {
my($self,$path,$force_path) = @_;
return '' unless $path;
$self = bless {}, $self unless ref $self;
my($fixedpath,$prefix,$name);
if ($path =~ /[ \t]/) {
return join ' ',
map { $self->fixpath($_,$force_path) }
split /[ \t]+/, $path;
}
if ($path =~ m#^\$\([^\)]+\)\Z(?!\n)#s || $path =~ m#[/:>\]]#) {
if ($force_path or $path =~ /(?:DIR\)|\])\Z(?!\n)/) {
$fixedpath = vmspath($self->eliminate_macros($path));
}
else {
$fixedpath = vmsify($self->eliminate_macros($path));
}
}
elsif ((($prefix,$name) = ($path =~ m#^\$\(([^\)]+)\)(.+)#s)) && $self->{$prefix}) {
my($vmspre) = $self->eliminate_macros("\$($prefix)");
# is it a dir or just a name?
$vmspre = ($vmspre =~ m|/| or $prefix =~ /DIR\Z(?!\n)/) ? vmspath($vmspre) : '';
$fixedpath = ($vmspre ? $vmspre : $self->{$prefix}) . $name;
$fixedpath = vmspath($fixedpath) if $force_path;
}
else {
$fixedpath = $path;
$fixedpath = vmspath($fixedpath) if $force_path;
}
# No hints, so we try to guess
if (!defined($force_path) and $fixedpath !~ /[:>(.\]]/) {
$fixedpath = vmspath($fixedpath) if -d $fixedpath;
}
# Trim off root dirname if it's had other dirs inserted in front of it.
$fixedpath =~ s/\.000000([\]>])/$1/;
# Special case for VMS absolute directory specs: these will have had device
# prepended during trip through Unix syntax in eliminate_macros(), since
# Unix syntax has no way to express "absolute from the top of this device's
# directory tree".
if ($path =~ /^[\[>][^.\-]/) { $fixedpath =~ s/^[^\[<]+//; }
return $fixedpath;
}
=item os_flavor
VMS is VMS.
=cut
sub os_flavor {
return('VMS');
}
=back
=head1 AUTHOR
Original author Charles Bailey F<bailey@newman.upenn.edu>
Maintained by Michael G Schwern F<schwern@pobox.com>
See L<ExtUtils::MakeMaker> for patching and contact information.
=cut
1;
EXTUTILS_MM_VMS
$fatpacked{"ExtUtils/MM_VOS.pm"} = <<'EXTUTILS_MM_VOS';
package ExtUtils::MM_VOS;
use strict;
our $VERSION = '6.59';
require ExtUtils::MM_Unix;
our @ISA = qw(ExtUtils::MM_Unix);
=head1 NAME
ExtUtils::MM_VOS - VOS specific subclass of ExtUtils::MM_Unix
=head1 SYNOPSIS
Don't use this module directly.
Use ExtUtils::MM and let it choose.
=head1 DESCRIPTION
This is a subclass of ExtUtils::MM_Unix which contains functionality for
VOS.
Unless otherwise stated it works just like ExtUtils::MM_Unix
=head2 Overridden methods
=head3 extra_clean_files
Cleanup VOS core files
=cut
sub extra_clean_files {
return qw(*.kp);
}
=head1 AUTHOR
Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
=head1 SEE ALSO
L<ExtUtils::MakeMaker>
=cut
1;
EXTUTILS_MM_VOS
$fatpacked{"ExtUtils/MM_Win32.pm"} = <<'EXTUTILS_MM_WIN32';
package ExtUtils::MM_Win32;
use strict;
=head1 NAME
ExtUtils::MM_Win32 - methods to override UN*X behaviour in ExtUtils::MakeMaker
=head1 SYNOPSIS
use ExtUtils::MM_Win32; # Done internally by ExtUtils::MakeMaker if needed
=head1 DESCRIPTION
See ExtUtils::MM_Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not
the semantics.
=cut
use ExtUtils::MakeMaker::Config;
use File::Basename;
use File::Spec;
use ExtUtils::MakeMaker qw( neatvalue );
require ExtUtils::MM_Any;
require ExtUtils::MM_Unix;
our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
our $VERSION = '6.59';
$ENV{EMXSHELL} = 'sh'; # to run `commands`
my ( $BORLAND, $GCC, $DLLTOOL ) = _identify_compiler_environment( \%Config );
sub _identify_compiler_environment {
my ( $config ) = @_;
my $BORLAND = $config->{cc} =~ /^bcc/i ? 1 : 0;
my $GCC = $config->{cc} =~ /\bgcc\b/i ? 1 : 0;
my $DLLTOOL = $config->{dlltool} || 'dlltool';
return ( $BORLAND, $GCC, $DLLTOOL );
}
=head2 Overridden methods
=over 4
=item B<dlsyms>
=cut
sub dlsyms {
my($self,%attribs) = @_;
my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || [];
my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
my($imports) = $attribs{IMPORTS} || $self->{IMPORTS} || {};
my(@m);
if (not $self->{SKIPHASH}{'dynamic'}) {
push(@m,"
$self->{BASEEXT}.def: Makefile.PL
",
q! $(PERLRUN) -MExtUtils::Mksymlists \\
-e "Mksymlists('NAME'=>\"!, $self->{NAME},
q!\", 'DLBASE' => '!,$self->{DLBASE},
# The above two lines quoted differently to work around
# a bug in the 4DOS/4NT command line interpreter. The visible
# result of the bug was files named q('extension_name',) *with the
# single quotes and the comma* in the extension build directories.
q!', 'DL_FUNCS' => !,neatvalue($funcs),
q!, 'FUNCLIST' => !,neatvalue($funclist),
q!, 'IMPORTS' => !,neatvalue($imports),
q!, 'DL_VARS' => !, neatvalue($vars), q!);"
!);
}
join('',@m);
}
=item replace_manpage_separator
Changes the path separator with .
=cut
sub replace_manpage_separator {
my($self,$man) = @_;
$man =~ s,/+,.,g;
$man;
}
=item B<maybe_command>
Since Windows has nothing as simple as an executable bit, we check the
file extension.
The PATHEXT env variable will be used to get a list of extensions that
might indicate a command, otherwise .com, .exe, .bat and .cmd will be
used by default.
=cut
sub maybe_command {
my($self,$file) = @_;
my @e = exists($ENV{'PATHEXT'})
? split(/;/, $ENV{PATHEXT})
: qw(.com .exe .bat .cmd);
my $e = '';
for (@e) { $e .= "\Q$_\E|" }
chop $e;
# see if file ends in one of the known extensions
if ($file =~ /($e)$/i) {
return $file if -e $file;
}
else {
for (@e) {
return "$file$_" if -e "$file$_";
}
}
return;
}
=item B<init_DIRFILESEP>
Using \ for Windows.
=cut
sub init_DIRFILESEP {
my($self) = shift;
# The ^ makes sure its not interpreted as an escape in nmake
$self->{DIRFILESEP} = $self->is_make_type('nmake') ? '^\\' :
$self->is_make_type('dmake') ? '\\\\'
: '\\';
}
=item B<init_others>
Override some of the Unix specific commands with portable
ExtUtils::Command ones.
Also provide defaults for LD and AR in case the %Config values aren't
set.
LDLOADLIBS's default is changed to $Config{libs}.
Adjustments are made for Borland's quirks needing -L to come first.
=cut
sub init_others {
my ($self) = @_;
$self->{NOOP} ||= 'rem';
$self->{DEV_NULL} ||= '> NUL';
$self->{FIXIN} ||= $self->{PERL_CORE} ?
"\$(PERLRUN) $self->{PERL_SRC}/win32/bin/pl2bat.pl" :
'pl2bat.bat';
$self->{LD} ||= 'link';
$self->{AR} ||= 'lib';
$self->SUPER::init_others;
# Setting SHELL from $Config{sh} can break dmake. Its ok without it.
delete $self->{SHELL};
$self->{LDLOADLIBS} ||= $Config{libs};
# -Lfoo must come first for Borland, so we put it in LDDLFLAGS
if ($BORLAND) {
my $libs = $self->{LDLOADLIBS};
my $libpath = '';
while ($libs =~ s/(?:^|\s)(("?)-L.+?\2)(?:\s|$)/ /) {
$libpath .= ' ' if length $libpath;
$libpath .= $1;
}
$self->{LDLOADLIBS} = $libs;
$self->{LDDLFLAGS} ||= $Config{lddlflags};
$self->{LDDLFLAGS} .= " $libpath";
}
return 1;
}
=item init_platform
Add MM_Win32_VERSION.
=item platform_constants
=cut
sub init_platform {
my($self) = shift;
$self->{MM_Win32_VERSION} = $VERSION;
return;
}
sub platform_constants {
my($self) = shift;
my $make_frag = '';
foreach my $macro (qw(MM_Win32_VERSION))
{
next unless defined $self->{$macro};
$make_frag .= "$macro = $self->{$macro}\n";
}
return $make_frag;
}
=item constants
Add MAXLINELENGTH for dmake before all the constants are output.
=cut
sub constants {
my $self = shift;
my $make_text = $self->SUPER::constants;
return $make_text unless $self->is_make_type('dmake');
# dmake won't read any single "line" (even those with escaped newlines)
# larger than a certain size which can be as small as 8k. PM_TO_BLIB
# on large modules like DateTime::TimeZone can create lines over 32k.
# So we'll crank it up to a <ironic>WHOPPING</ironic> 64k.
#
# This has to come here before all the constants and not in
# platform_constants which is after constants.
my $size = $self->{MAXLINELENGTH} || 64 * 1024;
my $prefix = qq{
# Get dmake to read long commands like PM_TO_BLIB
MAXLINELENGTH = $size
};
return $prefix . $make_text;
}
=item special_targets
Add .USESHELL target for dmake.
=cut
sub special_targets {
my($self) = @_;
my $make_frag = $self->SUPER::special_targets;
$make_frag .= <<'MAKE_FRAG' if $self->is_make_type('dmake');
.USESHELL :
MAKE_FRAG
return $make_frag;
}
=item static_lib
Changes how to run the linker.
The rest is duplicate code from MM_Unix. Should move the linker code
to its own method.
=cut
sub static_lib {
my($self) = @_;
return '' unless $self->has_link_code;
my(@m);
push(@m, <<'END');
$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists
$(RM_RF) $@
END
# If this extension has its own library (eg SDBM_File)
# then copy that to $(INST_STATIC) and add $(OBJECT) into it.
push @m, <<'MAKE_FRAG' if $self->{MYEXTLIB};
$(CP) $(MYEXTLIB) $@
MAKE_FRAG
push @m,
q{ $(AR) }.($BORLAND ? '$@ $(OBJECT:^"+")'
: ($GCC ? '-ru $@ $(OBJECT)'
: '-out:$@ $(OBJECT)')).q{
$(CHMOD) $(PERM_RWX) $@
$(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)\extralibs.ld
};
# Old mechanism - still available:
push @m, <<'MAKE_FRAG' if $self->{PERL_SRC} && $self->{EXTRALIBS};
$(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)\ext.libs
MAKE_FRAG
join('', @m);
}
=item dynamic_lib
Complicated stuff for Win32 that I don't understand. :(
=cut
sub dynamic_lib {
my($self, %attribs) = @_;
return '' unless $self->needs_linking(); #might be because of a subdir
return '' unless $self->has_link_code;
my($otherldflags) = $attribs{OTHERLDFLAGS} || ($BORLAND ? 'c0d32.obj': '');
my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
my($ldfrom) = '$(LDFROM)';
my(@m);
push(@m,'
# This section creates the dynamically loadable $(INST_DYNAMIC)
# from $(OBJECT) and possibly $(MYEXTLIB).
OTHERLDFLAGS = '.$otherldflags.'
INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
');
if ($GCC) {
push(@m,
q{ }.$DLLTOOL.q{ --def $(EXPORT_LIST) --output-exp dll.exp
$(LD) -o $@ -Wl,--base-file -Wl,dll.base $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) dll.exp
}.$DLLTOOL.q{ --def $(EXPORT_LIST) --base-file dll.base --output-exp dll.exp
$(LD) -o $@ $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) dll.exp });
} elsif ($BORLAND) {
push(@m,
q{ $(LD) $(LDDLFLAGS) $(OTHERLDFLAGS) }.$ldfrom.q{,$@,,}
.($self->is_make_type('dmake')
? q{$(PERL_ARCHIVE:s,/,\,) $(LDLOADLIBS:s,/,\,) }
.q{$(MYEXTLIB:s,/,\,),$(EXPORT_LIST:s,/,\,)}
: q{$(subst /,\,$(PERL_ARCHIVE)) $(subst /,\,$(LDLOADLIBS)) }
.q{$(subst /,\,$(MYEXTLIB)),$(subst /,\,$(EXPORT_LIST))})
.q{,$(RESFILES)});
} else { # VC
push(@m,
q{ $(LD) -out:$@ $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) }
.q{$(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) -def:$(EXPORT_LIST)});
# Embed the manifest file if it exists
push(@m, q{
if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
if exist $@.manifest del $@.manifest});
}
push @m, '
$(CHMOD) $(PERM_RWX) $@
';
join('',@m);
}
=item extra_clean_files
Clean out some extra dll.{base,exp} files which might be generated by
gcc. Otherwise, take out all *.pdb files.
=cut
sub extra_clean_files {
my $self = shift;
return $GCC ? (qw(dll.base dll.exp)) : ('*.pdb');
}
=item init_linker
=cut
sub init_linker {
my $self = shift;
$self->{PERL_ARCHIVE} = "\$(PERL_INC)\\$Config{libperl}";
$self->{PERL_ARCHIVE_AFTER} = '';
$self->{EXPORT_LIST} = '$(BASEEXT).def';
}
=item perl_script
Checks for the perl program under several common perl extensions.
=cut
sub perl_script {
my($self,$file) = @_;
return $file if -r $file && -f _;
return "$file.pl" if -r "$file.pl" && -f _;
return "$file.plx" if -r "$file.plx" && -f _;
return "$file.bat" if -r "$file.bat" && -f _;
return;
}
=item xs_o
This target is stubbed out. Not sure why.
=cut
sub xs_o {
return ''
}
=item pasthru
All we send is -nologo to nmake to prevent it from printing its damned
banner.
=cut
sub pasthru {
my($self) = shift;
return "PASTHRU = " . ($self->is_make_type('nmake') ? "-nologo" : "");
}
=item arch_check (override)
Normalize all arguments for consistency of comparison.
=cut
sub arch_check {
my $self = shift;
# Win32 is an XS module, minperl won't have it.
# arch_check() is not critical, so just fake it.
return 1 unless $self->can_load_xs;
return $self->SUPER::arch_check( map { $self->_normalize_path_name($_) } @_);
}
sub _normalize_path_name {
my $self = shift;
my $file = shift;
require Win32;
my $short = Win32::GetShortPathName($file);
return defined $short ? lc $short : lc $file;
}
=item oneliner
These are based on what command.com does on Win98. They may be wrong
for other Windows shells, I don't know.
=cut
sub oneliner {
my($self, $cmd, $switches) = @_;
$switches = [] unless defined $switches;
# Strip leading and trailing newlines
$cmd =~ s{^\n+}{};
$cmd =~ s{\n+$}{};
$cmd = $self->quote_literal($cmd);
$cmd = $self->escape_newlines($cmd);
$switches = join ' ', @$switches;
return qq{\$(ABSPERLRUN) $switches -e $cmd --};
}
sub quote_literal {
my($self, $text) = @_;
# DOS batch processing is hilarious:
# Quotes need to be converted into triple quotes.
# Certain special characters need to be escaped with a caret if an odd
# number of quotes came before them.
my @text = split '', $text;
my $quote_count = 0;
my %caret_chars = map { $_ => 1 } qw( < > | );
for my $char ( @text ) {
if ( $char eq '"' ) {
$quote_count++;
$char = '"""';
}
elsif ( $caret_chars{$char} and $quote_count % 2 ) {
$char = "^$char";
}
elsif ( $char eq "\\" ) {
$char = "\\\\";
}
}
$text = join '', @text;
# There is a terribly confusing edge case here, where this will do entirely the wrong thing:
# perl -e "use Data::Dumper; @ARGV = '%PATH%'; print Dumper( \@ARGV );print qq{@ARGV};" --
# I have no idea how to fix this manually, much less programmatically.
# However as it is such a rare edge case i'll just leave this documentation here and hope it never happens.
# dmake eats '{' inside double quotes and leaves alone { outside double
# quotes; however it transforms {{ into { either inside and outside double
# quotes. It also translates }} into }. The escaping below is not
# 100% correct.
if( $self->is_make_type('dmake') ) {
$text =~ s/{/{{/g;
$text =~ s/}}/}}}/g;
}
return qq{"$text"};
}
sub escape_newlines {
my($self, $text) = @_;
# Escape newlines
$text =~ s{\n}{\\\n}g;
return $text;
}
=item cd
dmake can handle Unix style cd'ing but nmake (at least 1.5) cannot. It
wants:
cd dir1\dir2
command
another_command
cd ..\..
=cut
sub cd {
my($self, $dir, @cmds) = @_;
return $self->SUPER::cd($dir, @cmds) unless $self->is_make_type('nmake');
my $cmd = join "\n\t", map "$_", @cmds;
my $updirs = $self->catdir(map { $self->updir } $self->splitdir($dir));
# No leading tab and no trailing newline makes for easier embedding.
my $make_frag = sprintf <<'MAKE_FRAG', $dir, $cmd, $updirs;
cd %s
%s
cd %s
MAKE_FRAG
chomp $make_frag;
return $make_frag;
}
=item max_exec_len
nmake 1.50 limits command length to 2048 characters.
=cut
sub max_exec_len {
my $self = shift;
return $self->{_MAX_EXEC_LEN} ||= 2 * 1024;
}
=item os_flavor
Windows is Win32.
=cut
sub os_flavor {
return('Win32');
}
=item cflags
Defines the PERLDLL symbol if we are configured for static building since all
code destined for the perl5xx.dll must be compiled with the PERLDLL symbol
defined.
=cut
sub cflags {
my($self,$libperl)=@_;
return $self->{CFLAGS} if $self->{CFLAGS};
return '' unless $self->needs_linking();
my $base = $self->SUPER::cflags($libperl);
foreach (split /\n/, $base) {
/^(\S*)\s*=\s*(\S*)$/ and $self->{$1} = $2;
};
$self->{CCFLAGS} .= " -DPERLDLL" if ($self->{LINKTYPE} eq 'static');
return $self->{CFLAGS} = qq{
CCFLAGS = $self->{CCFLAGS}
OPTIMIZE = $self->{OPTIMIZE}
PERLTYPE = $self->{PERLTYPE}
};
}
sub is_make_type {
my($self, $type) = @_;
return !! ($self->make =~ /\b$type(?:\.exe)?$/);
}
1;
__END__
=back
=cut
EXTUTILS_MM_WIN32
$fatpacked{"ExtUtils/MM_Win95.pm"} = <<'EXTUTILS_MM_WIN95';
package ExtUtils::MM_Win95;
use strict;
our $VERSION = '6.59';
require ExtUtils::MM_Win32;
our @ISA = qw(ExtUtils::MM_Win32);
use ExtUtils::MakeMaker::Config;
=head1 NAME
ExtUtils::MM_Win95 - method to customize MakeMaker for Win9X
=head1 SYNOPSIS
You should not be using this module directly.
=head1 DESCRIPTION
This is a subclass of ExtUtils::MM_Win32 containing changes necessary
to get MakeMaker playing nice with command.com and other Win9Xisms.
=head2 Overridden methods
Most of these make up for limitations in the Win9x/nmake command shell.
Mostly its lack of &&.
=over 4
=item xs_c
The && problem.
=cut
sub xs_c {
my($self) = shift;
return '' unless $self->needs_linking();
'
.xs.c:
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.c
'
}
=item xs_cpp
The && problem
=cut
sub xs_cpp {
my($self) = shift;
return '' unless $self->needs_linking();
'
.xs.cpp:
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.cpp
';
}
=item xs_o
The && problem.
=cut
sub xs_o {
my($self) = shift;
return '' unless $self->needs_linking();
'
.xs$(OBJ_EXT):
$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.c
$(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.c
';
}
=item max_exec_len
Win98 chokes on things like Encode if we set the max length to nmake's max
of 2K. So we go for a more conservative value of 1K.
=cut
sub max_exec_len {
my $self = shift;
return $self->{_MAX_EXEC_LEN} ||= 1024;
}
=item os_flavor
Win95 and Win98 and WinME are collectively Win9x and Win32
=cut
sub os_flavor {
my $self = shift;
return ($self->SUPER::os_flavor, 'Win9x');
}
=back
=head1 AUTHOR
Code originally inside MM_Win32. Original author unknown.
Currently maintained by Michael G Schwern C<schwern@pobox.com>.
Send patches and ideas to C<makemaker@perl.org>.
See http://www.makemaker.org.
=cut
1;
EXTUTILS_MM_WIN95
$fatpacked{"ExtUtils/MY.pm"} = <<'EXTUTILS_MY';
package ExtUtils::MY;
use strict;
require ExtUtils::MM;
our $VERSION = '6.59';
our @ISA = qw(ExtUtils::MM);
{
package MY;
our @ISA = qw(ExtUtils::MY);
}
sub DESTROY {}
=head1 NAME
ExtUtils::MY - ExtUtils::MakeMaker subclass for customization
=head1 SYNOPSIS
# in your Makefile.PL
sub MY::whatever {
...
}
=head1 DESCRIPTION
B<FOR INTERNAL USE ONLY>
ExtUtils::MY is a subclass of ExtUtils::MM. Its provided in your
Makefile.PL for you to add and override MakeMaker functionality.
It also provides a convenient alias via the MY class.
ExtUtils::MY might turn out to be a temporary solution, but MY won't
go away.
=cut
EXTUTILS_MY
$fatpacked{"ExtUtils/MakeMaker.pm"} = <<'EXTUTILS_MAKEMAKER';
# $Id$
package ExtUtils::MakeMaker;
use strict;
BEGIN {require 5.006;}
require Exporter;
use ExtUtils::MakeMaker::Config;
use Carp;
use File::Path;
our $Verbose = 0; # exported
our @Parent; # needs to be localized
our @Get_from_Config; # referenced by MM_Unix
our @MM_Sections;
our @Overridable;
my @Prepend_parent;
my %Recognized_Att_Keys;
our $VERSION = '6.59';
$VERSION = eval $VERSION;
# Emulate something resembling CVS $Revision$
(our $Revision = $VERSION) =~ s{_}{};
$Revision = int $Revision * 10000;
our $Filename = __FILE__; # referenced outside MakeMaker
our @ISA = qw(Exporter);
our @EXPORT = qw(&WriteMakefile &writeMakefile $Verbose &prompt);
our @EXPORT_OK = qw($VERSION &neatvalue &mkbootstrap &mksymlists
&WriteEmptyMakefile);
# These will go away once the last of the Win32 & VMS specific code is
# purged.
my $Is_VMS = $^O eq 'VMS';
my $Is_Win32 = $^O eq 'MSWin32';
full_setup();
require ExtUtils::MM; # Things like CPAN assume loading ExtUtils::MakeMaker
# will give them MM.
require ExtUtils::MY; # XXX pre-5.8 versions of ExtUtils::Embed expect
# loading ExtUtils::MakeMaker will give them MY.
# This will go when Embed is its own CPAN module.
sub WriteMakefile {
croak "WriteMakefile: Need even number of args" if @_ % 2;
require ExtUtils::MY;
my %att = @_;
_convert_compat_attrs(\%att);
_verify_att(\%att);
my $mm = MM->new(\%att);
$mm->flush;
return $mm;
}
# Basic signatures of the attributes WriteMakefile takes. Each is the
# reference type. Empty value indicate it takes a non-reference
# scalar.
my %Att_Sigs;
my %Special_Sigs = (
AUTHOR => 'ARRAY',
C => 'ARRAY',
CONFIG => 'ARRAY',
CONFIGURE => 'CODE',
DIR => 'ARRAY',
DL_FUNCS => 'HASH',
DL_VARS => 'ARRAY',
EXCLUDE_EXT => 'ARRAY',
EXE_FILES => 'ARRAY',
FUNCLIST => 'ARRAY',
H => 'ARRAY',
IMPORTS => 'HASH',
INCLUDE_EXT => 'ARRAY',
LIBS => ['ARRAY',''],
MAN1PODS => 'HASH',
MAN3PODS => 'HASH',
META_ADD => 'HASH',
META_MERGE => 'HASH',
PL_FILES => 'HASH',
PM => 'HASH',
PMLIBDIRS => 'ARRAY',
PMLIBPARENTDIRS => 'ARRAY',
PREREQ_PM => 'HASH',
BUILD_REQUIRES => 'HASH',
CONFIGURE_REQUIRES => 'HASH',
SKIP => 'ARRAY',
TYPEMAPS => 'ARRAY',
XS => 'HASH',
VERSION => ['version',''],
_KEEP_AFTER_FLUSH => '',
clean => 'HASH',
depend => 'HASH',
dist => 'HASH',
dynamic_lib=> 'HASH',
linkext => 'HASH',
macro => 'HASH',
postamble => 'HASH',
realclean => 'HASH',
test => 'HASH',
tool_autosplit => 'HASH',
);
@Att_Sigs{keys %Recognized_Att_Keys} = ('') x keys %Recognized_Att_Keys;
@Att_Sigs{keys %Special_Sigs} = values %Special_Sigs;
sub _convert_compat_attrs { #result of running several times should be same
my($att) = @_;
if (exists $att->{AUTHOR}) {
if ($att->{AUTHOR}) {
if (!ref($att->{AUTHOR})) {
my $t = $att->{AUTHOR};
$att->{AUTHOR} = [$t];
}
} else {
$att->{AUTHOR} = [];
}
}
}
sub _verify_att {
my($att) = @_;
while( my($key, $val) = each %$att ) {
my $sig = $Att_Sigs{$key};
unless( defined $sig ) {
warn "WARNING: $key is not a known parameter.\n";
next;
}
my @sigs = ref $sig ? @$sig : $sig;
my $given = ref $val;
unless( grep { _is_of_type($val, $_) } @sigs ) {
my $takes = join " or ", map { _format_att($_) } @sigs;
my $has = _format_att($given);
warn "WARNING: $key takes a $takes not a $has.\n".
" Please inform the author.\n";
}
}
}
# Check if a given thing is a reference or instance of $type
sub _is_of_type {
my($thing, $type) = @_;
return 1 if ref $thing eq $type;
local $SIG{__DIE__};
return 1 if eval{ $thing->isa($type) };
return 0;
}
sub _format_att {
my $given = shift;
return $given eq '' ? "string/number"
: uc $given eq $given ? "$given reference"
: "$given object"
;
}
sub prompt ($;$) { ## no critic
my($mess, $def) = @_;
confess("prompt function called without an argument")
unless defined $mess;
my $isa_tty = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ;
my $dispdef = defined $def ? "[$def] " : " ";
$def = defined $def ? $def : "";
local $|=1;
local $\;
print "$mess $dispdef";
my $ans;
if ($ENV{PERL_MM_USE_DEFAULT} || (!$isa_tty && eof STDIN)) {
print "$def\n";
}
else {
$ans = <STDIN>;
if( defined $ans ) {
chomp $ans;
}
else { # user hit ctrl-D
print "\n";
}
}
return (!defined $ans || $ans eq '') ? $def : $ans;
}
sub eval_in_subdirs {
my($self) = @_;
use Cwd qw(cwd abs_path);
my $pwd = cwd() || die "Can't figure out your cwd!";
local @INC = map eval {abs_path($_) if -e} || $_, @INC;
push @INC, '.'; # '.' has to always be at the end of @INC
foreach my $dir (@{$self->{DIR}}){
my($abs) = $self->catdir($pwd,$dir);
eval { $self->eval_in_x($abs); };
last if $@;
}
chdir $pwd;
die $@ if $@;
}
sub eval_in_x {
my($self,$dir) = @_;
chdir $dir or carp("Couldn't change to directory $dir: $!");
{
package main;
do './Makefile.PL';
};
if ($@) {
# if ($@ =~ /prerequisites/) {
# die "MakeMaker WARNING: $@";
# } else {
# warn "WARNING from evaluation of $dir/Makefile.PL: $@";
# }
die "ERROR from evaluation of $dir/Makefile.PL: $@";
}
}
# package name for the classes into which the first object will be blessed
my $PACKNAME = 'PACK000';
sub full_setup {
$Verbose ||= 0;
my @attrib_help = qw/
AUTHOR ABSTRACT ABSTRACT_FROM BINARY_LOCATION
C CAPI CCFLAGS CONFIG CONFIGURE DEFINE DIR DISTNAME DISTVNAME
DL_FUNCS DL_VARS
EXCLUDE_EXT EXE_FILES FIRST_MAKEFILE
FULLPERL FULLPERLRUN FULLPERLRUNINST
FUNCLIST H IMPORTS
INST_ARCHLIB INST_SCRIPT INST_BIN INST_LIB INST_MAN1DIR INST_MAN3DIR
INSTALLDIRS
DESTDIR PREFIX INSTALL_BASE
PERLPREFIX SITEPREFIX VENDORPREFIX
INSTALLPRIVLIB INSTALLSITELIB INSTALLVENDORLIB
INSTALLARCHLIB INSTALLSITEARCH INSTALLVENDORARCH
INSTALLBIN INSTALLSITEBIN INSTALLVENDORBIN
INSTALLMAN1DIR INSTALLMAN3DIR
INSTALLSITEMAN1DIR INSTALLSITEMAN3DIR
INSTALLVENDORMAN1DIR INSTALLVENDORMAN3DIR
INSTALLSCRIPT INSTALLSITESCRIPT INSTALLVENDORSCRIPT
PERL_LIB PERL_ARCHLIB
SITELIBEXP SITEARCHEXP
INC INCLUDE_EXT LDFROM LIB LIBPERL_A LIBS LICENSE
LINKTYPE MAKE MAKEAPERL MAKEFILE MAKEFILE_OLD MAN1PODS MAN3PODS MAP_TARGET
META_ADD META_MERGE MIN_PERL_VERSION BUILD_REQUIRES CONFIGURE_REQUIRES
MYEXTLIB NAME NEEDS_LINKING NOECHO NO_META NO_MYMETA NORECURS NO_VC OBJECT
OPTIMIZE PERL_MALLOC_OK PERL PERLMAINCC PERLRUN PERLRUNINST PERL_CORE
PERL_SRC PERM_DIR PERM_RW PERM_RWX
PL_FILES PM PM_FILTER PMLIBDIRS PMLIBPARENTDIRS POLLUTE PPM_INSTALL_EXEC
PPM_INSTALL_SCRIPT PREREQ_FATAL PREREQ_PM PREREQ_PRINT PRINT_PREREQ
SIGN SKIP TYPEMAPS VERSION VERSION_FROM XS XSOPT XSPROTOARG
XS_VERSION clean depend dist dynamic_lib linkext macro realclean
tool_autosplit
MACPERL_SRC MACPERL_LIB MACLIBS_68K MACLIBS_PPC MACLIBS_SC MACLIBS_MRC
MACLIBS_ALL_68K MACLIBS_ALL_PPC MACLIBS_SHARED
/;
# IMPORTS is used under OS/2 and Win32
# @Overridable is close to @MM_Sections but not identical. The
# order is important. Many subroutines declare macros. These
# depend on each other. Let's try to collect the macros up front,
# then pasthru, then the rules.
# MM_Sections are the sections we have to call explicitly
# in Overridable we have subroutines that are used indirectly
@MM_Sections =
qw(
post_initialize const_config constants platform_constants
tool_autosplit tool_xsubpp tools_other
makemakerdflt
dist macro depend cflags const_loadlibs const_cccmd
post_constants
pasthru
special_targets
c_o xs_c xs_o
top_targets blibdirs linkext dlsyms dynamic dynamic_bs
dynamic_lib static static_lib manifypods processPL
installbin subdirs
clean_subdirs clean realclean_subdirs realclean
metafile signature
dist_basics dist_core distdir dist_test dist_ci distmeta distsignature
install force perldepend makefile staticmake test ppd
); # loses section ordering
@Overridable = @MM_Sections;
push @Overridable, qw[
libscan makeaperl needs_linking
subdir_x test_via_harness test_via_script
init_VERSION init_dist init_INST init_INSTALL init_DEST init_dirscan
init_PM init_MANPODS init_xs init_PERL init_DIRFILESEP init_linker
];
push @MM_Sections, qw[
pm_to_blib selfdocument
];
# Postamble needs to be the last that was always the case
push @MM_Sections, "postamble";
push @Overridable, "postamble";
# All sections are valid keys.
@Recognized_Att_Keys{@MM_Sections} = (1) x @MM_Sections;
# we will use all these variables in the Makefile
@Get_from_Config =
qw(
ar cc cccdlflags ccdlflags dlext dlsrc exe_ext full_ar ld
lddlflags ldflags libc lib_ext obj_ext osname osvers ranlib
sitelibexp sitearchexp so
);
# 5.5.3 doesn't have any concept of vendor libs
push @Get_from_Config, qw( vendorarchexp vendorlibexp ) if $] >= 5.006;
foreach my $item (@attrib_help){
$Recognized_Att_Keys{$item} = 1;
}
foreach my $item (@Get_from_Config) {
$Recognized_Att_Keys{uc $item} = $Config{$item};
print "Attribute '\U$item\E' => '$Config{$item}'\n"
if ($Verbose >= 2);
}
#
# When we eval a Makefile.PL in a subdirectory, that one will ask
# us (the parent) for the values and will prepend "..", so that
# all files to be installed end up below OUR ./blib
#
@Prepend_parent = qw(
INST_BIN INST_LIB INST_ARCHLIB INST_SCRIPT
MAP_TARGET INST_MAN1DIR INST_MAN3DIR PERL_SRC
PERL FULLPERL
);
}
sub writeMakefile {
die <<END;
The extension you are trying to build apparently is rather old and
most probably outdated. We detect that from the fact, that a
subroutine "writeMakefile" is called, and this subroutine is not
supported anymore since about October 1994.
Please contact the author or look into CPAN (details about CPAN can be
found in the FAQ and at http:/www.perl.com) for a more recent version
of the extension. If you're really desperate, you can try to change
the subroutine name from writeMakefile to WriteMakefile and rerun
'perl Makefile.PL', but you're most probably left alone, when you do
so.
The MakeMaker team
END
}
sub new {
my($class,$self) = @_;
my($key);
_convert_compat_attrs($self) if defined $self && $self;
# Store the original args passed to WriteMakefile()
foreach my $k (keys %$self) {
$self->{ARGS}{$k} = $self->{$k};
}
$self = {} unless defined $self;
# Temporarily bless it into MM so it can be used as an
# object. It will be blessed into a temp package later.
bless $self, "MM";
# Cleanup all the module requirement bits
for my $key (qw(PREREQ_PM BUILD_REQUIRES CONFIGURE_REQUIRES)) {
$self->{$key} ||= {};
$self->clean_versions( $key );
}
if ("@ARGV" =~ /\bPREREQ_PRINT\b/) {
$self->_PREREQ_PRINT;
}
# PRINT_PREREQ is RedHatism.
if ("@ARGV" =~ /\bPRINT_PREREQ\b/) {
$self->_PRINT_PREREQ;
}
print STDOUT "MakeMaker (v$VERSION)\n" if $Verbose;
if (-f "MANIFEST" && ! -f "Makefile" && ! $ENV{PERL_CORE}){
check_manifest();
}
check_hints($self);
# Translate X.Y.Z to X.00Y00Z
if( defined $self->{MIN_PERL_VERSION} ) {
$self->{MIN_PERL_VERSION} =~ s{ ^ (\d+) \. (\d+) \. (\d+) $ }
{sprintf "%d.%03d%03d", $1, $2, $3}ex;
}
my $perl_version_ok = eval {
local $SIG{__WARN__} = sub {
# simulate "use warnings FATAL => 'all'" for vintage perls
die @_;
};
!$self->{MIN_PERL_VERSION} or $self->{MIN_PERL_VERSION} <= $]
};
if (!$perl_version_ok) {
if (!defined $perl_version_ok) {
die <<'END';
Warning: MIN_PERL_VERSION is not in a recognized format.
Recommended is a quoted numerical value like '5.005' or '5.008001'.
END
}
elsif ($self->{PREREQ_FATAL}) {
die sprintf <<"END", $self->{MIN_PERL_VERSION}, $];
MakeMaker FATAL: perl version too low for this distribution.
Required is %s. We run %s.
END
}
else {
warn sprintf
"Warning: Perl version %s or higher required. We run %s.\n",
$self->{MIN_PERL_VERSION}, $];
}
}
my %configure_att; # record &{$self->{CONFIGURE}} attributes
my(%initial_att) = %$self; # record initial attributes
my(%unsatisfied) = ();
my $prereqs = $self->_all_prereqs;
foreach my $prereq (sort keys %$prereqs) {
my $required_version = $prereqs->{$prereq};
my $installed_file = MM->_installed_file_for_module($prereq);
my $pr_version = 0;
$pr_version = MM->parse_version($installed_file) if $installed_file;
$pr_version = 0 if $pr_version eq 'undef';
# convert X.Y_Z alpha version #s to X.YZ for easier comparisons
$pr_version =~ s/(\d+)\.(\d+)_(\d+)/$1.$2$3/;
if (!$installed_file) {
warn sprintf "Warning: prerequisite %s %s not found.\n",
$prereq, $required_version
unless $self->{PREREQ_FATAL}
or $ENV{PERL_CORE};
$unsatisfied{$prereq} = 'not installed';
}
elsif ($pr_version < $required_version ){
warn sprintf "Warning: prerequisite %s %s not found. We have %s.\n",
$prereq, $required_version, ($pr_version || 'unknown version')
unless $self->{PREREQ_FATAL}
or $ENV{PERL_CORE};
$unsatisfied{$prereq} = $required_version ? $required_version : 'unknown version' ;
}
}
if (%unsatisfied && $self->{PREREQ_FATAL}){
my $failedprereqs = join "\n", map {" $_ $unsatisfied{$_}"}
sort { $a cmp $b } keys %unsatisfied;
die <<"END";
MakeMaker FATAL: prerequisites not found.
$failedprereqs
Please install these modules first and rerun 'perl Makefile.PL'.
END
}
if (defined $self->{CONFIGURE}) {
if (ref $self->{CONFIGURE} eq 'CODE') {
%configure_att = %{&{$self->{CONFIGURE}}};
_convert_compat_attrs(\%configure_att);
$self = { %$self, %configure_att };
} else {
croak "Attribute 'CONFIGURE' to WriteMakefile() not a code reference\n";
}
}
# This is for old Makefiles written pre 5.00, will go away
if ( Carp::longmess("") =~ /runsubdirpl/s ){
carp("WARNING: Please rerun 'perl Makefile.PL' to regenerate your Makefiles\n");
}
my $newclass = ++$PACKNAME;
local @Parent = @Parent; # Protect against non-local exits
{
print "Blessing Object into class [$newclass]\n" if $Verbose>=2;
mv_all_methods("MY",$newclass);
bless $self, $newclass;
push @Parent, $self;
require ExtUtils::MY;
no strict 'refs'; ## no critic;
@{"$newclass\:\:ISA"} = 'MM';
}
if (defined $Parent[-2]){
$self->{PARENT} = $Parent[-2];
for my $key (@Prepend_parent) {
next unless defined $self->{PARENT}{$key};
# Don't stomp on WriteMakefile() args.
next if defined $self->{ARGS}{$key} and
$self->{ARGS}{$key} eq $self->{$key};
$self->{$key} = $self->{PARENT}{$key};
unless ($Is_VMS && $key =~ /PERL$/) {
$self->{$key} = $self->catdir("..",$self->{$key})
unless $self->file_name_is_absolute($self->{$key});
} else {
# PERL or FULLPERL will be a command verb or even a
# command with an argument instead of a full file
# specification under VMS. So, don't turn the command
# into a filespec, but do add a level to the path of
# the argument if not already absolute.
my @cmd = split /\s+/, $self->{$key};
$cmd[1] = $self->catfile('[-]',$cmd[1])
unless (@cmd < 2) || $self->file_name_is_absolute($cmd[1]);
$self->{$key} = join(' ', @cmd);
}
}
if ($self->{PARENT}) {
$self->{PARENT}->{CHILDREN}->{$newclass} = $self;
foreach my $opt (qw(POLLUTE PERL_CORE LINKTYPE)) {
if (exists $self->{PARENT}->{$opt}
and not exists $self->{$opt})
{
# inherit, but only if already unspecified
$self->{$opt} = $self->{PARENT}->{$opt};
}
}
}
my @fm = grep /^FIRST_MAKEFILE=/, @ARGV;
parse_args($self,@fm) if @fm;
} else {
parse_args($self,split(' ', $ENV{PERL_MM_OPT} || ''),@ARGV);
}
$self->{NAME} ||= $self->guess_name;
($self->{NAME_SYM} = $self->{NAME}) =~ s/\W+/_/g;
$self->init_MAKE;
$self->init_main;
$self->init_VERSION;
$self->init_dist;
$self->init_INST;
$self->init_INSTALL;
$self->init_DEST;
$self->init_dirscan;
$self->init_PM;
$self->init_MANPODS;
$self->init_xs;
$self->init_PERL;
$self->init_DIRFILESEP;
$self->init_linker;
$self->init_ABSTRACT;
$self->arch_check(
$INC{'Config.pm'},
$self->catfile($Config{'archlibexp'}, "Config.pm")
);
$self->init_others();
$self->init_platform();
$self->init_PERM();
my($argv) = neatvalue(\@ARGV);
$argv =~ s/^\[/(/;
$argv =~ s/\]$/)/;
push @{$self->{RESULT}}, <<END;
# This Makefile is for the $self->{NAME} extension to perl.
#
# It was generated automatically by MakeMaker version
# $VERSION (Revision: $Revision) from the contents of
# Makefile.PL. Don't edit this file, edit Makefile.PL instead.
#
# ANY CHANGES MADE HERE WILL BE LOST!
#
# MakeMaker ARGV: $argv
#
END
push @{$self->{RESULT}}, $self->_MakeMaker_Parameters_section(\%initial_att);
if (defined $self->{CONFIGURE}) {
push @{$self->{RESULT}}, <<END;
# MakeMaker 'CONFIGURE' Parameters:
END
if (scalar(keys %configure_att) > 0) {
foreach my $key (sort keys %configure_att){
next if $key eq 'ARGS';
my($v) = neatvalue($configure_att{$key});
$v =~ s/(CODE|HASH|ARRAY|SCALAR)\([\dxa-f]+\)/$1\(...\)/;
$v =~ tr/\n/ /s;
push @{$self->{RESULT}}, "# $key => $v";
}
}
else
{
push @{$self->{RESULT}}, "# no values returned";
}
undef %configure_att; # free memory
}
# turn the SKIP array into a SKIPHASH hash
for my $skip (@{$self->{SKIP} || []}) {
$self->{SKIPHASH}{$skip} = 1;
}
delete $self->{SKIP}; # free memory
if ($self->{PARENT}) {
for (qw/install dist dist_basics dist_core distdir dist_test dist_ci/) {
$self->{SKIPHASH}{$_} = 1;
}
}
# We run all the subdirectories now. They don't have much to query
# from the parent, but the parent has to query them: if they need linking!
unless ($self->{NORECURS}) {
$self->eval_in_subdirs if @{$self->{DIR}};
}
foreach my $section ( @MM_Sections ){
# Support for new foo_target() methods.
my $method = $section;
$method .= '_target' unless $self->can($method);
print "Processing Makefile '$section' section\n" if ($Verbose >= 2);
my($skipit) = $self->skipcheck($section);
if ($skipit){
push @{$self->{RESULT}}, "\n# --- MakeMaker $section section $skipit.";
} else {
my(%a) = %{$self->{$section} || {}};
push @{$self->{RESULT}}, "\n# --- MakeMaker $section section:";
push @{$self->{RESULT}}, "# " . join ", ", %a if $Verbose && %a;
push @{$self->{RESULT}}, $self->maketext_filter(
$self->$method( %a )
);
}
}
push @{$self->{RESULT}}, "\n# End.";
$self;
}
sub WriteEmptyMakefile {
croak "WriteEmptyMakefile: Need an even number of args" if @_ % 2;
my %att = @_;
my $self = MM->new(\%att);
my $new = $self->{MAKEFILE};
my $old = $self->{MAKEFILE_OLD};
if (-f $old) {
_unlink($old) or warn "unlink $old: $!";
}
if ( -f $new ) {
_rename($new, $old) or warn "rename $new => $old: $!"
}
open my $mfh, '>', $new or die "open $new for write: $!";
print $mfh <<'EOP';
all :
clean :
install :
makemakerdflt :
test :
EOP
close $mfh or die "close $new for write: $!";
}
=begin private
=head3 _installed_file_for_module
my $file = MM->_installed_file_for_module($module);
Return the first installed .pm $file associated with the $module. The
one which will show up when you C<use $module>.
$module is something like "strict" or "Test::More".
=end private
=cut
sub _installed_file_for_module {
my $class = shift;
my $prereq = shift;
my $file = "$prereq.pm";
$file =~ s{::}{/}g;
my $path;
for my $dir (@INC) {
my $tmp = File::Spec->catfile($dir, $file);
if ( -r $tmp ) {
$path = $tmp;
last;
}
}
return $path;
}
# Extracted from MakeMaker->new so we can test it
sub _MakeMaker_Parameters_section {
my $self = shift;
my $att = shift;
my @result = <<'END';
# MakeMaker Parameters:
END
foreach my $key (sort keys %$att){
next if $key eq 'ARGS';
my ($v) = neatvalue($att->{$key});
if ($key eq 'PREREQ_PM') {
# CPAN.pm takes prereqs from this field in 'Makefile'
# and does not know about BUILD_REQUIRES
$v = neatvalue({ %{ $att->{PREREQ_PM} || {} }, %{ $att->{BUILD_REQUIRES} || {} } });
} else {
$v = neatvalue($att->{$key});
}
$v =~ s/(CODE|HASH|ARRAY|SCALAR)\([\dxa-f]+\)/$1\(...\)/;
$v =~ tr/\n/ /s;
push @result, "# $key => $v";
}
return @result;
}
sub check_manifest {
print STDOUT "Checking if your kit is complete...\n";
require ExtUtils::Manifest;
# avoid warning
$ExtUtils::Manifest::Quiet = $ExtUtils::Manifest::Quiet = 1;
my(@missed) = ExtUtils::Manifest::manicheck();
if (@missed) {
print STDOUT "Warning: the following files are missing in your kit:\n";
print "\t", join "\n\t", @missed;
print STDOUT "\n";
print STDOUT "Please inform the author.\n";
} else {
print STDOUT "Looks good\n";
}
}
sub parse_args{
my($self, @args) = @_;
foreach (@args) {
unless (m/(.*?)=(.*)/) {
++$Verbose if m/^verb/;
next;
}
my($name, $value) = ($1, $2);
if ($value =~ m/^~(\w+)?/) { # tilde with optional username
$value =~ s [^~(\w*)]
[$1 ?
((getpwnam($1))[7] || "~$1") :
(getpwuid($>))[7]
]ex;
}
# Remember the original args passed it. It will be useful later.
$self->{ARGS}{uc $name} = $self->{uc $name} = $value;
}
# catch old-style 'potential_libs' and inform user how to 'upgrade'
if (defined $self->{potential_libs}){
my($msg)="'potential_libs' => '$self->{potential_libs}' should be";
if ($self->{potential_libs}){
print STDOUT "$msg changed to:\n\t'LIBS' => ['$self->{potential_libs}']\n";
} else {
print STDOUT "$msg deleted.\n";
}
$self->{LIBS} = [$self->{potential_libs}];
delete $self->{potential_libs};
}
# catch old-style 'ARMAYBE' and inform user how to 'upgrade'
if (defined $self->{ARMAYBE}){
my($armaybe) = $self->{ARMAYBE};
print STDOUT "ARMAYBE => '$armaybe' should be changed to:\n",
"\t'dynamic_lib' => {ARMAYBE => '$armaybe'}\n";
my(%dl) = %{$self->{dynamic_lib} || {}};
$self->{dynamic_lib} = { %dl, ARMAYBE => $armaybe};
delete $self->{ARMAYBE};
}
if (defined $self->{LDTARGET}){
print STDOUT "LDTARGET should be changed to LDFROM\n";
$self->{LDFROM} = $self->{LDTARGET};
delete $self->{LDTARGET};
}
# Turn a DIR argument on the command line into an array
if (defined $self->{DIR} && ref \$self->{DIR} eq 'SCALAR') {
# So they can choose from the command line, which extensions they want
# the grep enables them to have some colons too much in case they
# have to build a list with the shell
$self->{DIR} = [grep $_, split ":", $self->{DIR}];
}
# Turn a INCLUDE_EXT argument on the command line into an array
if (defined $self->{INCLUDE_EXT} && ref \$self->{INCLUDE_EXT} eq 'SCALAR') {
$self->{INCLUDE_EXT} = [grep $_, split '\s+', $self->{INCLUDE_EXT}];
}
# Turn a EXCLUDE_EXT argument on the command line into an array
if (defined $self->{EXCLUDE_EXT} && ref \$self->{EXCLUDE_EXT} eq 'SCALAR') {
$self->{EXCLUDE_EXT} = [grep $_, split '\s+', $self->{EXCLUDE_EXT}];
}
foreach my $mmkey (sort keys %$self){
next if $mmkey eq 'ARGS';
print STDOUT " $mmkey => ", neatvalue($self->{$mmkey}), "\n" if $Verbose;
print STDOUT "'$mmkey' is not a known MakeMaker parameter name.\n"
unless exists $Recognized_Att_Keys{$mmkey};
}
$| = 1 if $Verbose;
}
sub check_hints {
my($self) = @_;
# We allow extension-specific hints files.
require File::Spec;
my $curdir = File::Spec->curdir;
my $hint_dir = File::Spec->catdir($curdir, "hints");
return unless -d $hint_dir;
# First we look for the best hintsfile we have
my($hint)="${^O}_$Config{osvers}";
$hint =~ s/\./_/g;
$hint =~ s/_$//;
return unless $hint;
# Also try without trailing minor version numbers.
while (1) {
last if -f File::Spec->catfile($hint_dir, "$hint.pl"); # found
} continue {
last unless $hint =~ s/_[^_]*$//; # nothing to cut off
}
my $hint_file = File::Spec->catfile($hint_dir, "$hint.pl");
return unless -f $hint_file; # really there
_run_hintfile($self, $hint_file);
}
sub _run_hintfile {
our $self;
local($self) = shift; # make $self available to the hint file.
my($hint_file) = shift;
local($@, $!);
print STDERR "Processing hints file $hint_file\n";
# Just in case the ./ isn't on the hint file, which File::Spec can
# often strip off, we bung the curdir into @INC
local @INC = (File::Spec->curdir, @INC);
my $ret = do $hint_file;
if( !defined $ret ) {
my $error = $@ || $!;
print STDERR $error;
}
}
sub mv_all_methods {
my($from,$to) = @_;
# Here you see the *current* list of methods that are overridable
# from Makefile.PL via MY:: subroutines. As of VERSION 5.07 I'm
# still trying to reduce the list to some reasonable minimum --
# because I want to make it easier for the user. A.K.
local $SIG{__WARN__} = sub {
# can't use 'no warnings redefined', 5.6 only
warn @_ unless $_[0] =~ /^Subroutine .* redefined/
};
foreach my $method (@Overridable) {
# We cannot say "next" here. Nick might call MY->makeaperl
# which isn't defined right now
# Above statement was written at 4.23 time when Tk-b8 was
# around. As Tk-b9 only builds with 5.002something and MM 5 is
# standard, we try to enable the next line again. It was
# commented out until MM 5.23
next unless defined &{"${from}::$method"};
{
no strict 'refs'; ## no critic
*{"${to}::$method"} = \&{"${from}::$method"};
# If we delete a method, then it will be undefined and cannot
# be called. But as long as we have Makefile.PLs that rely on
# %MY:: being intact, we have to fill the hole with an
# inheriting method:
{
package MY;
my $super = "SUPER::".$method;
*{$method} = sub {
shift->$super(@_);
};
}
}
}
# We have to clean out %INC also, because the current directory is
# changed frequently and Graham Barr prefers to get his version
# out of a History.pl file which is "required" so woudn't get
# loaded again in another extension requiring a History.pl
# With perl5.002_01 the deletion of entries in %INC caused Tk-b11
# to core dump in the middle of a require statement. The required
# file was Tk/MMutil.pm. The consequence is, we have to be
# extremely careful when we try to give perl a reason to reload a
# library with same name. The workaround prefers to drop nothing
# from %INC and teach the writers not to use such libraries.
# my $inc;
# foreach $inc (keys %INC) {
# #warn "***$inc*** deleted";
# delete $INC{$inc};
# }
}
sub skipcheck {
my($self) = shift;
my($section) = @_;
if ($section eq 'dynamic') {
print STDOUT "Warning (non-fatal): Target 'dynamic' depends on targets ",
"in skipped section 'dynamic_bs'\n"
if $self->{SKIPHASH}{dynamic_bs} && $Verbose;
print STDOUT "Warning (non-fatal): Target 'dynamic' depends on targets ",
"in skipped section 'dynamic_lib'\n"
if $self->{SKIPHASH}{dynamic_lib} && $Verbose;
}
if ($section eq 'dynamic_lib') {
print STDOUT "Warning (non-fatal): Target '\$(INST_DYNAMIC)' depends on ",
"targets in skipped section 'dynamic_bs'\n"
if $self->{SKIPHASH}{dynamic_bs} && $Verbose;
}
if ($section eq 'static') {
print STDOUT "Warning (non-fatal): Target 'static' depends on targets ",
"in skipped section 'static_lib'\n"
if $self->{SKIPHASH}{static_lib} && $Verbose;
}
return 'skipped' if $self->{SKIPHASH}{$section};
return '';
}
sub flush {
my $self = shift;
my $finalname = $self->{MAKEFILE};
print STDOUT "Writing $finalname for $self->{NAME}\n";
unlink($finalname, "MakeMaker.tmp", $Is_VMS ? 'Descrip.MMS' : ());
open(my $fh,">", "MakeMaker.tmp")
or die "Unable to open MakeMaker.tmp: $!";
for my $chunk (@{$self->{RESULT}}) {
print $fh "$chunk\n"
or die "Can't write to MakeMaker.tmp: $!";
}
close $fh
or die "Can't write to MakeMaker.tmp: $!";
_rename("MakeMaker.tmp", $finalname) or
warn "rename MakeMaker.tmp => $finalname: $!";
chmod 0644, $finalname unless $Is_VMS;
unless ($self->{NO_MYMETA}) {
# Write MYMETA.yml to communicate metadata up to the CPAN clients
if ( $self->write_mymeta( $self->mymeta ) ) {;
print STDOUT "Writing MYMETA.yml and MYMETA.json\n";
}
}
my %keep = map { ($_ => 1) } qw(NEEDS_LINKING HAS_LINK_CODE);
if ($self->{PARENT} && !$self->{_KEEP_AFTER_FLUSH}) {
foreach (keys %$self) { # safe memory
delete $self->{$_} unless $keep{$_};
}
}
system("$Config::Config{eunicefix} $finalname") unless $Config::Config{eunicefix} eq ":";
}
# This is a rename for OS's where the target must be unlinked first.
sub _rename {
my($src, $dest) = @_;
chmod 0666, $dest;
unlink $dest;
return rename $src, $dest;
}
# This is an unlink for OS's where the target must be writable first.
sub _unlink {
my @files = @_;
chmod 0666, @files;
return unlink @files;
}
# The following mkbootstrap() is only for installations that are calling
# the pre-4.1 mkbootstrap() from their old Makefiles. This MakeMaker
# writes Makefiles, that use ExtUtils::Mkbootstrap directly.
sub mkbootstrap {
die <<END;
!!! Your Makefile has been built such a long time ago, !!!
!!! that is unlikely to work with current MakeMaker. !!!
!!! Please rebuild your Makefile !!!
END
}
# Ditto for mksymlists() as of MakeMaker 5.17
sub mksymlists {
die <<END;
!!! Your Makefile has been built such a long time ago, !!!
!!! that is unlikely to work with current MakeMaker. !!!
!!! Please rebuild your Makefile !!!
END
}
sub neatvalue {
my($v) = @_;
return "undef" unless defined $v;
my($t) = ref $v;
return "q[$v]" unless $t;
if ($t eq 'ARRAY') {
my(@m, @neat);
push @m, "[";
foreach my $elem (@$v) {
push @neat, "q[$elem]";
}
push @m, join ", ", @neat;
push @m, "]";
return join "", @m;
}
return "$v" unless $t eq 'HASH';
my(@m, $key, $val);
while (($key,$val) = each %$v){
last unless defined $key; # cautious programming in case (undef,undef) is true
push(@m,"$key=>".neatvalue($val)) ;
}
return "{ ".join(', ',@m)." }";
}
# Look for weird version numbers, warn about them and set them to 0
# before CPAN::Meta chokes.
sub clean_versions {
my($self, $key) = @_;
my $reqs = $self->{$key};
for my $module (keys %$reqs) {
my $version = $reqs->{$module};
if( !defined $version or $version !~ /^[\d_\.]+$/ ) {
carp "Unparsable version '$version' for prerequisite $module";
$reqs->{$module} = 0;
}
}
}
sub selfdocument {
my($self) = @_;
my(@m);
if ($Verbose){
push @m, "\n# Full list of MakeMaker attribute values:";
foreach my $key (sort keys %$self){
next if $key eq 'RESULT' || $key =~ /^[A-Z][a-z]/;
my($v) = neatvalue($self->{$key});
$v =~ s/(CODE|HASH|ARRAY|SCALAR)\([\dxa-f]+\)/$1\(...\)/;
$v =~ tr/\n/ /s;
push @m, "# $key => $v";
}
}
join "\n", @m;
}
1;
__END__
=head1 NAME
ExtUtils::MakeMaker - Create a module Makefile
=head1 SYNOPSIS
use ExtUtils::MakeMaker;
WriteMakefile( ATTRIBUTE => VALUE [, ...] );
=head1 DESCRIPTION
This utility is designed to write a Makefile for an extension module
from a Makefile.PL. It is based on the Makefile.SH model provided by
Andy Dougherty and the perl5-porters.
It splits the task of generating the Makefile into several subroutines
that can be individually overridden. Each subroutine returns the text
it wishes to have written to the Makefile.
MakeMaker is object oriented. Each directory below the current
directory that contains a Makefile.PL is treated as a separate
object. This makes it possible to write an unlimited number of
Makefiles with a single invocation of WriteMakefile().
=head2 How To Write A Makefile.PL
See ExtUtils::MakeMaker::Tutorial.
The long answer is the rest of the manpage :-)
=head2 Default Makefile Behaviour
The generated Makefile enables the user of the extension to invoke
perl Makefile.PL # optionally "perl Makefile.PL verbose"
make
make test # optionally set TEST_VERBOSE=1
make install # See below
The Makefile to be produced may be altered by adding arguments of the
form C<KEY=VALUE>. E.g.
perl Makefile.PL INSTALL_BASE=~
Other interesting targets in the generated Makefile are
make config # to check if the Makefile is up-to-date
make clean # delete local temp files (Makefile gets renamed)
make realclean # delete derived files (including ./blib)
make ci # check in all the files in the MANIFEST file
make dist # see below the Distribution Support section
=head2 make test
MakeMaker checks for the existence of a file named F<test.pl> in the
current directory and if it exists it execute the script with the
proper set of perl C<-I> options.
MakeMaker also checks for any files matching glob("t/*.t"). It will
execute all matching files in alphabetical order via the
L<Test::Harness> module with the C<-I> switches set correctly.
If you'd like to see the raw output of your tests, set the
C<TEST_VERBOSE> variable to true.
make test TEST_VERBOSE=1
=head2 make testdb
A useful variation of the above is the target C<testdb>. It runs the
test under the Perl debugger (see L<perldebug>). If the file
F<test.pl> exists in the current directory, it is used for the test.
If you want to debug some other testfile, set the C<TEST_FILE> variable
thusly:
make testdb TEST_FILE=t/mytest.t
By default the debugger is called using C<-d> option to perl. If you
want to specify some other option, set the C<TESTDB_SW> variable:
make testdb TESTDB_SW=-Dx
=head2 make install
make alone puts all relevant files into directories that are named by
the macros INST_LIB, INST_ARCHLIB, INST_SCRIPT, INST_MAN1DIR and
INST_MAN3DIR. All these default to something below ./blib if you are
I<not> building below the perl source directory. If you I<are>
building below the perl source, INST_LIB and INST_ARCHLIB default to
../../lib, and INST_SCRIPT is not defined.
The I<install> target of the generated Makefile copies the files found
below each of the INST_* directories to their INSTALL*
counterparts. Which counterparts are chosen depends on the setting of
INSTALLDIRS according to the following table:
INSTALLDIRS set to
perl site vendor
PERLPREFIX SITEPREFIX VENDORPREFIX
INST_ARCHLIB INSTALLARCHLIB INSTALLSITEARCH INSTALLVENDORARCH
INST_LIB INSTALLPRIVLIB INSTALLSITELIB INSTALLVENDORLIB
INST_BIN INSTALLBIN INSTALLSITEBIN INSTALLVENDORBIN
INST_SCRIPT INSTALLSCRIPT INSTALLSITESCRIPT INSTALLVENDORSCRIPT
INST_MAN1DIR INSTALLMAN1DIR INSTALLSITEMAN1DIR INSTALLVENDORMAN1DIR
INST_MAN3DIR INSTALLMAN3DIR INSTALLSITEMAN3DIR INSTALLVENDORMAN3DIR
The INSTALL... macros in turn default to their %Config
($Config{installprivlib}, $Config{installarchlib}, etc.) counterparts.
You can check the values of these variables on your system with
perl '-V:install.*'
And to check the sequence in which the library directories are
searched by perl, run
perl -le 'print join $/, @INC'
Sometimes older versions of the module you're installing live in other
directories in @INC. Because Perl loads the first version of a module it
finds, not the newest, you might accidentally get one of these older
versions even after installing a brand new version. To delete I<all other
versions of the module you're installing> (not simply older ones) set the
C<UNINST> variable.
make install UNINST=1
=head2 INSTALL_BASE
INSTALL_BASE can be passed into Makefile.PL to change where your
module will be installed. INSTALL_BASE is more like what everyone
else calls "prefix" than PREFIX is.
To have everything installed in your home directory, do the following.
# Unix users, INSTALL_BASE=~ works fine
perl Makefile.PL INSTALL_BASE=/path/to/your/home/dir
Like PREFIX, it sets several INSTALL* attributes at once. Unlike
PREFIX it is easy to predict where the module will end up. The
installation pattern looks like this:
INSTALLARCHLIB INSTALL_BASE/lib/perl5/$Config{archname}
INSTALLPRIVLIB INSTALL_BASE/lib/perl5
INSTALLBIN INSTALL_BASE/bin
INSTALLSCRIPT INSTALL_BASE/bin
INSTALLMAN1DIR INSTALL_BASE/man/man1
INSTALLMAN3DIR INSTALL_BASE/man/man3
INSTALL_BASE in MakeMaker and C<--install_base> in Module::Build (as
of 0.28) install to the same location. If you want MakeMaker and
Module::Build to install to the same location simply set INSTALL_BASE
and C<--install_base> to the same location.
INSTALL_BASE was added in 6.31.
=head2 PREFIX and LIB attribute
PREFIX and LIB can be used to set several INSTALL* attributes in one
go. Here's an example for installing into your home directory.
# Unix users, PREFIX=~ works fine
perl Makefile.PL PREFIX=/path/to/your/home/dir
This will install all files in the module under your home directory,
with man pages and libraries going into an appropriate place (usually
~/man and ~/lib). How the exact location is determined is complicated
and depends on how your Perl was configured. INSTALL_BASE works more
like what other build systems call "prefix" than PREFIX and we
recommend you use that instead.
Another way to specify many INSTALL directories with a single
parameter is LIB.
perl Makefile.PL LIB=~/lib
This will install the module's architecture-independent files into
~/lib, the architecture-dependent files into ~/lib/$archname.
Note, that in both cases the tilde expansion is done by MakeMaker, not
by perl by default, nor by make.
Conflicts between parameters LIB, PREFIX and the various INSTALL*
arguments are resolved so that:
=over 4
=item *
setting LIB overrides any setting of INSTALLPRIVLIB, INSTALLARCHLIB,
INSTALLSITELIB, INSTALLSITEARCH (and they are not affected by PREFIX);
=item *
without LIB, setting PREFIX replaces the initial C<$Config{prefix}>
part of those INSTALL* arguments, even if the latter are explicitly
set (but are set to still start with C<$Config{prefix}>).
=back
If the user has superuser privileges, and is not working on AFS or
relatives, then the defaults for INSTALLPRIVLIB, INSTALLARCHLIB,
INSTALLSCRIPT, etc. will be appropriate, and this incantation will be
the best:
perl Makefile.PL;
make;
make test
make install
make install per default writes some documentation of what has been
done into the file C<$(INSTALLARCHLIB)/perllocal.pod>. This feature
can be bypassed by calling make pure_install.
=head2 AFS users
will have to specify the installation directories as these most
probably have changed since perl itself has been installed. They will
have to do this by calling
perl Makefile.PL INSTALLSITELIB=/afs/here/today \
INSTALLSCRIPT=/afs/there/now INSTALLMAN3DIR=/afs/for/manpages
make
Be careful to repeat this procedure every time you recompile an
extension, unless you are sure the AFS installation directories are
still valid.
=head2 Static Linking of a new Perl Binary
An extension that is built with the above steps is ready to use on
systems supporting dynamic loading. On systems that do not support
dynamic loading, any newly created extension has to be linked together
with the available resources. MakeMaker supports the linking process
by creating appropriate targets in the Makefile whenever an extension
is built. You can invoke the corresponding section of the makefile with
make perl
That produces a new perl binary in the current directory with all
extensions linked in that can be found in INST_ARCHLIB, SITELIBEXP,
and PERL_ARCHLIB. To do that, MakeMaker writes a new Makefile, on
UNIX, this is called Makefile.aperl (may be system dependent). If you
want to force the creation of a new perl, it is recommended, that you
delete this Makefile.aperl, so the directories are searched-through
for linkable libraries again.
The binary can be installed into the directory where perl normally
resides on your machine with
make inst_perl
To produce a perl binary with a different name than C<perl>, either say
perl Makefile.PL MAP_TARGET=myperl
make myperl
make inst_perl
or say
perl Makefile.PL
make myperl MAP_TARGET=myperl
make inst_perl MAP_TARGET=myperl
In any case you will be prompted with the correct invocation of the
C<inst_perl> target that installs the new binary into INSTALLBIN.
make inst_perl per default writes some documentation of what has been
done into the file C<$(INSTALLARCHLIB)/perllocal.pod>. This
can be bypassed by calling make pure_inst_perl.
Warning: the inst_perl: target will most probably overwrite your
existing perl binary. Use with care!
Sometimes you might want to build a statically linked perl although
your system supports dynamic loading. In this case you may explicitly
set the linktype with the invocation of the Makefile.PL or make:
perl Makefile.PL LINKTYPE=static # recommended
or
make LINKTYPE=static # works on most systems
=head2 Determination of Perl Library and Installation Locations
MakeMaker needs to know, or to guess, where certain things are
located. Especially INST_LIB and INST_ARCHLIB (where to put the files
during the make(1) run), PERL_LIB and PERL_ARCHLIB (where to read
existing modules from), and PERL_INC (header files and C<libperl*.*>).
Extensions may be built either using the contents of the perl source
directory tree or from the installed perl library. The recommended way
is to build extensions after you have run 'make install' on perl
itself. You can do that in any directory on your hard disk that is not
below the perl source tree. The support for extensions below the ext
directory of the perl distribution is only good for the standard
extensions that come with perl.
If an extension is being built below the C<ext/> directory of the perl
source then MakeMaker will set PERL_SRC automatically (e.g.,
C<../..>). If PERL_SRC is defined and the extension is recognized as
a standard extension, then other variables default to the following:
PERL_INC = PERL_SRC
PERL_LIB = PERL_SRC/lib
PERL_ARCHLIB = PERL_SRC/lib
INST_LIB = PERL_LIB
INST_ARCHLIB = PERL_ARCHLIB
If an extension is being built away from the perl source then MakeMaker
will leave PERL_SRC undefined and default to using the installed copy
of the perl library. The other variables default to the following:
PERL_INC = $archlibexp/CORE
PERL_LIB = $privlibexp
PERL_ARCHLIB = $archlibexp
INST_LIB = ./blib/lib
INST_ARCHLIB = ./blib/arch
If perl has not yet been installed then PERL_SRC can be defined on the
command line as shown in the previous section.
=head2 Which architecture dependent directory?
If you don't want to keep the defaults for the INSTALL* macros,
MakeMaker helps you to minimize the typing needed: the usual
relationship between INSTALLPRIVLIB and INSTALLARCHLIB is determined
by Configure at perl compilation time. MakeMaker supports the user who
sets INSTALLPRIVLIB. If INSTALLPRIVLIB is set, but INSTALLARCHLIB not,
then MakeMaker defaults the latter to be the same subdirectory of
INSTALLPRIVLIB as Configure decided for the counterparts in %Config ,
otherwise it defaults to INSTALLPRIVLIB. The same relationship holds
for INSTALLSITELIB and INSTALLSITEARCH.
MakeMaker gives you much more freedom than needed to configure
internal variables and get different results. It is worth to mention,
that make(1) also lets you configure most of the variables that are
used in the Makefile. But in the majority of situations this will not
be necessary, and should only be done if the author of a package
recommends it (or you know what you're doing).
=head2 Using Attributes and Parameters
The following attributes may be specified as arguments to WriteMakefile()
or as NAME=VALUE pairs on the command line.
=over 2
=item ABSTRACT
One line description of the module. Will be included in PPD file.
=item ABSTRACT_FROM
Name of the file that contains the package description. MakeMaker looks
for a line in the POD matching /^($package\s-\s)(.*)/. This is typically
the first line in the "=head1 NAME" section. $2 becomes the abstract.
=item AUTHOR
Array of strings containing name (and email address) of package author(s).
Is used in CPAN Meta files (META.yml or META.json) and PPD
(Perl Package Description) files for PPM (Perl Package Manager).
=item BINARY_LOCATION
Used when creating PPD files for binary packages. It can be set to a
full or relative path or URL to the binary archive for a particular
architecture. For example:
perl Makefile.PL BINARY_LOCATION=x86/Agent.tar.gz
builds a PPD package that references a binary of the C<Agent> package,
located in the C<x86> directory relative to the PPD itself.
=item BUILD_REQUIRES
A hash of modules that are needed to build your module but not run it.
This will go into the C<build_requires> field of your CPAN Meta file.
(F<META.yml> or F<META.json>).
The format is the same as PREREQ_PM.
=item C
Ref to array of *.c file names. Initialised from a directory scan
and the values portion of the XS attribute hash. This is not
currently used by MakeMaker but may be handy in Makefile.PLs.
=item CCFLAGS
String that will be included in the compiler call command line between
the arguments INC and OPTIMIZE.
=item CONFIG
Arrayref. E.g. [qw(archname manext)] defines ARCHNAME & MANEXT from
config.sh. MakeMaker will add to CONFIG the following values anyway:
ar
cc
cccdlflags
ccdlflags
dlext
dlsrc
ld
lddlflags
ldflags
libc
lib_ext
obj_ext
ranlib
sitelibexp
sitearchexp
so
=item CONFIGURE
CODE reference. The subroutine should return a hash reference. The
hash may contain further attributes, e.g. {LIBS =E<gt> ...}, that have to
be determined by some evaluation method.
=item CONFIGURE_REQUIRES
A hash of modules that are required to run Makefile.PL itself, but not
to run your distribution.
This will go into the C<configure_requires> field of your CPAN Meta file
(F<META.yml> or F<META.json>)
Defaults to C<<< { "ExtUtils::MakeMaker" => 0 } >>>
The format is the same as PREREQ_PM.
=item DEFINE
Something like C<"-DHAVE_UNISTD_H">
=item DESTDIR
This is the root directory into which the code will be installed. It
I<prepends itself to the normal prefix>. For example, if your code
would normally go into F</usr/local/lib/perl> you could set DESTDIR=~/tmp/
and installation would go into F<~/tmp/usr/local/lib/perl>.
This is primarily of use for people who repackage Perl modules.
NOTE: Due to the nature of make, it is important that you put the trailing
slash on your DESTDIR. F<~/tmp/> not F<~/tmp>.
=item DIR
Ref to array of subdirectories containing Makefile.PLs e.g. ['sdbm']
in ext/SDBM_File
=item DISTNAME
A safe filename for the package.
Defaults to NAME above but with :: replaced with -.
For example, Foo::Bar becomes Foo-Bar.
=item DISTVNAME
Your name for distributing the package with the version number
included. This is used by 'make dist' to name the resulting archive
file.
Defaults to DISTNAME-VERSION.
For example, version 1.04 of Foo::Bar becomes Foo-Bar-1.04.
On some OS's where . has special meaning VERSION_SYM may be used in
place of VERSION.
=item DL_FUNCS
Hashref of symbol names for routines to be made available as universal
symbols. Each key/value pair consists of the package name and an
array of routine names in that package. Used only under AIX, OS/2,
VMS and Win32 at present. The routine names supplied will be expanded
in the same way as XSUB names are expanded by the XS() macro.
Defaults to
{"$(NAME)" => ["boot_$(NAME)" ] }
e.g.
{"RPC" => [qw( boot_rpcb rpcb_gettime getnetconfigent )],
"NetconfigPtr" => [ 'DESTROY'] }
Please see the L<ExtUtils::Mksymlists> documentation for more information
about the DL_FUNCS, DL_VARS and FUNCLIST attributes.
=item DL_VARS
Array of symbol names for variables to be made available as universal symbols.
Used only under AIX, OS/2, VMS and Win32 at present. Defaults to [].
(e.g. [ qw(Foo_version Foo_numstreams Foo_tree ) ])
=item EXCLUDE_EXT
Array of extension names to exclude when doing a static build. This
is ignored if INCLUDE_EXT is present. Consult INCLUDE_EXT for more
details. (e.g. [ qw( Socket POSIX ) ] )
This attribute may be most useful when specified as a string on the
command line: perl Makefile.PL EXCLUDE_EXT='Socket Safe'
=item EXE_FILES
Ref to array of executable files. The files will be copied to the
INST_SCRIPT directory. Make realclean will delete them from there
again.
If your executables start with something like #!perl or
#!/usr/bin/perl MakeMaker will change this to the path of the perl
'Makefile.PL' was invoked with so the programs will be sure to run
properly even if perl is not in /usr/bin/perl.
=item FIRST_MAKEFILE
The name of the Makefile to be produced. This is used for the second
Makefile that will be produced for the MAP_TARGET.
Defaults to 'Makefile' or 'Descrip.MMS' on VMS.
(Note: we couldn't use MAKEFILE because dmake uses this for something
else).
=item FULLPERL
Perl binary able to run this extension, load XS modules, etc...
=item FULLPERLRUN
Like PERLRUN, except it uses FULLPERL.
=item FULLPERLRUNINST
Like PERLRUNINST, except it uses FULLPERL.
=item FUNCLIST
This provides an alternate means to specify function names to be
exported from the extension. Its value is a reference to an
array of function names to be exported by the extension. These
names are passed through unaltered to the linker options file.
=item H
Ref to array of *.h file names. Similar to C.
=item IMPORTS
This attribute is used to specify names to be imported into the
extension. Takes a hash ref.
It is only used on OS/2 and Win32.
=item INC
Include file dirs eg: C<"-I/usr/5include -I/path/to/inc">
=item INCLUDE_EXT
Array of extension names to be included when doing a static build.
MakeMaker will normally build with all of the installed extensions when
doing a static build, and that is usually the desired behavior. If
INCLUDE_EXT is present then MakeMaker will build only with those extensions
which are explicitly mentioned. (e.g. [ qw( Socket POSIX ) ])
It is not necessary to mention DynaLoader or the current extension when
filling in INCLUDE_EXT. If the INCLUDE_EXT is mentioned but is empty then
only DynaLoader and the current extension will be included in the build.
This attribute may be most useful when specified as a string on the
command line: perl Makefile.PL INCLUDE_EXT='POSIX Socket Devel::Peek'
=item INSTALLARCHLIB
Used by 'make install', which copies files from INST_ARCHLIB to this
directory if INSTALLDIRS is set to perl.
=item INSTALLBIN
Directory to install binary files (e.g. tkperl) into if
INSTALLDIRS=perl.
=item INSTALLDIRS
Determines which of the sets of installation directories to choose:
perl, site or vendor. Defaults to site.
=item INSTALLMAN1DIR
=item INSTALLMAN3DIR
These directories get the man pages at 'make install' time if
INSTALLDIRS=perl. Defaults to $Config{installman*dir}.
If set to 'none', no man pages will be installed.
=item INSTALLPRIVLIB
Used by 'make install', which copies files from INST_LIB to this
directory if INSTALLDIRS is set to perl.
Defaults to $Config{installprivlib}.
=item INSTALLSCRIPT
Used by 'make install' which copies files from INST_SCRIPT to this
directory if INSTALLDIRS=perl.
=item INSTALLSITEARCH
Used by 'make install', which copies files from INST_ARCHLIB to this
directory if INSTALLDIRS is set to site (default).
=item INSTALLSITEBIN
Used by 'make install', which copies files from INST_BIN to this
directory if INSTALLDIRS is set to site (default).
=item INSTALLSITELIB
Used by 'make install', which copies files from INST_LIB to this
directory if INSTALLDIRS is set to site (default).
=item INSTALLSITEMAN1DIR
=item INSTALLSITEMAN3DIR
These directories get the man pages at 'make install' time if
INSTALLDIRS=site (default). Defaults to
$(SITEPREFIX)/man/man$(MAN*EXT).
If set to 'none', no man pages will be installed.
=item INSTALLSITESCRIPT
Used by 'make install' which copies files from INST_SCRIPT to this
directory if INSTALLDIRS is set to site (default).
=item INSTALLVENDORARCH
Used by 'make install', which copies files from INST_ARCHLIB to this
directory if INSTALLDIRS is set to vendor.
=item INSTALLVENDORBIN
Used by 'make install', which copies files from INST_BIN to this
directory if INSTALLDIRS is set to vendor.
=item INSTALLVENDORLIB
Used by 'make install', which copies files from INST_LIB to this
directory if INSTALLDIRS is set to vendor.
=item INSTALLVENDORMAN1DIR
=item INSTALLVENDORMAN3DIR
These directories get the man pages at 'make install' time if
INSTALLDIRS=vendor. Defaults to $(VENDORPREFIX)/man/man$(MAN*EXT).
If set to 'none', no man pages will be installed.
=item INSTALLVENDORSCRIPT
Used by 'make install' which copies files from INST_SCRIPT to this
directory if INSTALLDIRS is set to vendor.
=item INST_ARCHLIB
Same as INST_LIB for architecture dependent files.
=item INST_BIN
Directory to put real binary files during 'make'. These will be copied
to INSTALLBIN during 'make install'
=item INST_LIB
Directory where we put library files of this extension while building
it.
=item INST_MAN1DIR
Directory to hold the man pages at 'make' time
=item INST_MAN3DIR
Directory to hold the man pages at 'make' time
=item INST_SCRIPT
Directory, where executable files should be installed during
'make'. Defaults to "./blib/script", just to have a dummy location during
testing. make install will copy the files in INST_SCRIPT to
INSTALLSCRIPT.
=item LD
Program to be used to link libraries for dynamic loading.
Defaults to $Config{ld}.
=item LDDLFLAGS
Any special flags that might need to be passed to ld to create a
shared library suitable for dynamic loading. It is up to the makefile
to use it. (See L<Config/lddlflags>)
Defaults to $Config{lddlflags}.
=item LDFROM
Defaults to "$(OBJECT)" and is used in the ld command to specify
what files to link/load from (also see dynamic_lib below for how to
specify ld flags)
=item LIB
LIB should only be set at C<perl Makefile.PL> time but is allowed as a
MakeMaker argument. It has the effect of setting both INSTALLPRIVLIB
and INSTALLSITELIB to that value regardless any explicit setting of
those arguments (or of PREFIX). INSTALLARCHLIB and INSTALLSITEARCH
are set to the corresponding architecture subdirectory.
=item LIBPERL_A
The filename of the perllibrary that will be used together with this
extension. Defaults to libperl.a.
=item LIBS
An anonymous array of alternative library
specifications to be searched for (in order) until
at least one library is found. E.g.
'LIBS' => ["-lgdbm", "-ldbm -lfoo", "-L/path -ldbm.nfs"]
Mind, that any element of the array
contains a complete set of arguments for the ld
command. So do not specify
'LIBS' => ["-ltcl", "-ltk", "-lX11"]
See ODBM_File/Makefile.PL for an example, where an array is needed. If
you specify a scalar as in
'LIBS' => "-ltcl -ltk -lX11"
MakeMaker will turn it into an array with one element.
=item LICENSE
The licensing terms of your distribution. Generally its "perl" for the
same license as Perl itself.
See L<Module::Build::API> for the list of options.
Defaults to "unknown".
=item LINKTYPE
'static' or 'dynamic' (default unless usedl=undef in
config.sh). Should only be used to force static linking (also see
linkext below).
=item MAKE
Variant of make you intend to run the generated Makefile with. This
parameter lets Makefile.PL know what make quirks to account for when
generating the Makefile.
MakeMaker also honors the MAKE environment variable. This parameter
takes precedent.
Currently the only significant values are 'dmake' and 'nmake' for Windows
users.
Defaults to $Config{make}.
=item MAKEAPERL
Boolean which tells MakeMaker, that it should include the rules to
make a perl. This is handled automatically as a switch by
MakeMaker. The user normally does not need it.
=item MAKEFILE_OLD
When 'make clean' or similar is run, the $(FIRST_MAKEFILE) will be
backed up at this location.
Defaults to $(FIRST_MAKEFILE).old or $(FIRST_MAKEFILE)_old on VMS.
=item MAN1PODS
Hashref of pod-containing files. MakeMaker will default this to all
EXE_FILES files that include POD directives. The files listed
here will be converted to man pages and installed as was requested
at Configure time.
This hash should map POD files (or scripts containing POD) to the
man file names under the C<blib/man1/> directory, as in the following
example:
MAN1PODS => {
'doc/command.pod' => 'blib/man1/command.1',
'scripts/script.pl' => 'blib/man1/script.1',
}
=item MAN3PODS
Hashref that assigns to *.pm and *.pod files the files into which the
manpages are to be written. MakeMaker parses all *.pod and *.pm files
for POD directives. Files that contain POD will be the default keys of
the MAN3PODS hashref. These will then be converted to man pages during
C<make> and will be installed during C<make install>.
Example similar to MAN1PODS.
=item MAP_TARGET
If it is intended, that a new perl binary be produced, this variable
may hold a name for that binary. Defaults to perl
=item META_ADD
=item META_MERGE
A hashrefs of items to add to the CPAN Meta file (F<META.yml> or
F<META.json>).
They differ in how they behave if they have the same key as the
default metadata. META_ADD will override the default value with its
own. META_MERGE will merge its value with the default.
Unless you want to override the defaults, prefer META_MERGE so as to
get the advantage of any future defaults.
=item MIN_PERL_VERSION
The minimum required version of Perl for this distribution.
Either 5.006001 or 5.6.1 format is acceptable.
=item MYEXTLIB
If the extension links to a library that it builds set this to the
name of the library (see SDBM_File)
=item NAME
Perl module name for this extension (DBD::Oracle). This will default
to the directory name but should be explicitly defined in the
Makefile.PL.
=item NEEDS_LINKING
MakeMaker will figure out if an extension contains linkable code
anywhere down the directory tree, and will set this variable
accordingly, but you can speed it up a very little bit if you define
this boolean variable yourself.
=item NOECHO
Command so make does not print the literal commands its running.
By setting it to an empty string you can generate a Makefile that
prints all commands. Mainly used in debugging MakeMaker itself.
Defaults to C<@>.
=item NORECURS
Boolean. Attribute to inhibit descending into subdirectories.
=item NO_META
When true, suppresses the generation and addition to the MANIFEST of
the META.yml and META.json module meta-data files during 'make distdir'.
Defaults to false.
=item NO_MYMETA
When true, suppresses the generation of MYMETA.yml and MYMETA.json module
meta-data files during 'perl Makefile.PL'.
Defaults to false.
=item NO_VC
In general, any generated Makefile checks for the current version of
MakeMaker and the version the Makefile was built under. If NO_VC is
set, the version check is neglected. Do not write this into your
Makefile.PL, use it interactively instead.
=item OBJECT
List of object files, defaults to '$(BASEEXT)$(OBJ_EXT)', but can be a long
string containing all object files, e.g. "tkpBind.o
tkpButton.o tkpCanvas.o"
(Where BASEEXT is the last component of NAME, and OBJ_EXT is $Config{obj_ext}.)
=item OPTIMIZE
Defaults to C<-O>. Set it to C<-g> to turn debugging on. The flag is
passed to subdirectory makes.
=item PERL
Perl binary for tasks that can be done by miniperl
=item PERL_CORE
Set only when MakeMaker is building the extensions of the Perl core
distribution.
=item PERLMAINCC
The call to the program that is able to compile perlmain.c. Defaults
to $(CC).
=item PERL_ARCHLIB
Same as for PERL_LIB, but for architecture dependent files.
Used only when MakeMaker is building the extensions of the Perl core
distribution (because normally $(PERL_ARCHLIB) is automatically in @INC,
and adding it would get in the way of PERL5LIB).
=item PERL_LIB
Directory containing the Perl library to use.
Used only when MakeMaker is building the extensions of the Perl core
distribution (because normally $(PERL_LIB) is automatically in @INC,
and adding it would get in the way of PERL5LIB).
=item PERL_MALLOC_OK
defaults to 0. Should be set to TRUE if the extension can work with
the memory allocation routines substituted by the Perl malloc() subsystem.
This should be applicable to most extensions with exceptions of those
=over 4
=item *
with bugs in memory allocations which are caught by Perl's malloc();
=item *
which interact with the memory allocator in other ways than via
malloc(), realloc(), free(), calloc(), sbrk() and brk();
=item *
which rely on special alignment which is not provided by Perl's malloc().
=back
B<NOTE.> Negligence to set this flag in I<any one> of loaded extension
nullifies many advantages of Perl's malloc(), such as better usage of
system resources, error detection, memory usage reporting, catchable failure
of memory allocations, etc.
=item PERLPREFIX
Directory under which core modules are to be installed.
Defaults to $Config{installprefixexp} falling back to
$Config{installprefix}, $Config{prefixexp} or $Config{prefix} should
$Config{installprefixexp} not exist.
Overridden by PREFIX.
=item PERLRUN
Use this instead of $(PERL) when you wish to run perl. It will set up
extra necessary flags for you.
=item PERLRUNINST
Use this instead of $(PERL) when you wish to run perl to work with
modules. It will add things like -I$(INST_ARCH) and other necessary
flags so perl can see the modules you're about to install.
=item PERL_SRC
Directory containing the Perl source code (use of this should be
avoided, it may be undefined)
=item PERM_DIR
Desired permission for directories. Defaults to C<755>.
=item PERM_RW
Desired permission for read/writable files. Defaults to C<644>.
=item PERM_RWX
Desired permission for executable files. Defaults to C<755>.
=item PL_FILES
MakeMaker can run programs to generate files for you at build time.
By default any file named *.PL (except Makefile.PL and Build.PL) in
the top level directory will be assumed to be a Perl program and run
passing its own basename in as an argument. For example...
perl foo.PL foo
This behavior can be overridden by supplying your own set of files to
search. PL_FILES accepts a hash ref, the key being the file to run
and the value is passed in as the first argument when the PL file is run.
PL_FILES => {'bin/foobar.PL' => 'bin/foobar'}
Would run bin/foobar.PL like this:
perl bin/foobar.PL bin/foobar
If multiple files from one program are desired an array ref can be used.
PL_FILES => {'bin/foobar.PL' => [qw(bin/foobar1 bin/foobar2)]}
In this case the program will be run multiple times using each target file.
perl bin/foobar.PL bin/foobar1
perl bin/foobar.PL bin/foobar2
PL files are normally run B<after> pm_to_blib and include INST_LIB and
INST_ARCH in its C<@INC> so the just built modules can be
accessed... unless the PL file is making a module (or anything else in
PM) in which case it is run B<before> pm_to_blib and does not include
INST_LIB and INST_ARCH in its C<@INC>. This apparently odd behavior
is there for backwards compatibility (and its somewhat DWIM).
=item PM
Hashref of .pm files and *.pl files to be installed. e.g.
{'name_of_file.pm' => '$(INST_LIBDIR)/install_as.pm'}
By default this will include *.pm and *.pl and the files found in
the PMLIBDIRS directories. Defining PM in the
Makefile.PL will override PMLIBDIRS.
=item PMLIBDIRS
Ref to array of subdirectories containing library files. Defaults to
[ 'lib', $(BASEEXT) ]. The directories will be scanned and I<any> files
they contain will be installed in the corresponding location in the
library. A libscan() method can be used to alter the behaviour.
Defining PM in the Makefile.PL will override PMLIBDIRS.
(Where BASEEXT is the last component of NAME.)
=item PM_FILTER
A filter program, in the traditional Unix sense (input from stdin, output
to stdout) that is passed on each .pm file during the build (in the
pm_to_blib() phase). It is empty by default, meaning no filtering is done.
Great care is necessary when defining the command if quoting needs to be
done. For instance, you would need to say:
{'PM_FILTER' => 'grep -v \\"^\\#\\"'}
to remove all the leading comments on the fly during the build. The
extra \\ are necessary, unfortunately, because this variable is interpolated
within the context of a Perl program built on the command line, and double
quotes are what is used with the -e switch to build that command line. The
# is escaped for the Makefile, since what is going to be generated will then
be:
PM_FILTER = grep -v \"^\#\"
Without the \\ before the #, we'd have the start of a Makefile comment,
and the macro would be incorrectly defined.
=item POLLUTE
Release 5.005 grandfathered old global symbol names by providing preprocessor
macros for extension source compatibility. As of release 5.6, these
preprocessor definitions are not available by default. The POLLUTE flag
specifies that the old names should still be defined:
perl Makefile.PL POLLUTE=1
Please inform the module author if this is necessary to successfully install
a module under 5.6 or later.
=item PPM_INSTALL_EXEC
Name of the executable used to run C<PPM_INSTALL_SCRIPT> below. (e.g. perl)
=item PPM_INSTALL_SCRIPT
Name of the script that gets executed by the Perl Package Manager after
the installation of a package.
=item PREFIX
This overrides all the default install locations. Man pages,
libraries, scripts, etc... MakeMaker will try to make an educated
guess about where to place things under the new PREFIX based on your
Config defaults. Failing that, it will fall back to a structure
which should be sensible for your platform.
If you specify LIB or any INSTALL* variables they will not be effected
by the PREFIX.
=item PREREQ_FATAL
Bool. If this parameter is true, failing to have the required modules
(or the right versions thereof) will be fatal. C<perl Makefile.PL>
will C<die> instead of simply informing the user of the missing dependencies.
It is I<extremely> rare to have to use C<PREREQ_FATAL>. Its use by module
authors is I<strongly discouraged> and should never be used lightly.
Module installation tools have ways of resolving umet dependencies but
to do that they need a F<Makefile>. Using C<PREREQ_FATAL> breaks this.
That's bad.
Assuming you have good test coverage, your tests should fail with
missing dependencies informing the user more strongly that something
is wrong. You can write a F<t/00compile.t> test which will simply
check that your code compiles and stop "make test" prematurely if it
doesn't. See L<Test::More/BAIL_OUT> for more details.
=item PREREQ_PM
A hash of modules that are needed to run your module. The keys are
the module names ie. Test::More, and the minimum version is the
value. If the required version number is 0 any version will do.
This will go into the C<requires> field of your CPAN Meta file
(F<META.yml> or F<META.json>).
PREREQ_PM => {
# Require Test::More at least 0.47
"Test::More" => "0.47",
# Require any version of Acme::Buffy
"Acme::Buffy" => 0,
}
=item PREREQ_PRINT
Bool. If this parameter is true, the prerequisites will be printed to
stdout and MakeMaker will exit. The output format is an evalable hash
ref.
$PREREQ_PM = {
'A::B' => Vers1,
'C::D' => Vers2,
...
};
If a distribution defines a minimal required perl version, this is
added to the output as an additional line of the form:
$MIN_PERL_VERSION = '5.008001';
If BUILD_REQUIRES is not empty, it will be dumped as $BUILD_REQUIRES hasref.
=item PRINT_PREREQ
RedHatism for C<PREREQ_PRINT>. The output format is different, though:
perl(A::B)>=Vers1 perl(C::D)>=Vers2 ...
A minimal required perl version, if present, will look like this:
perl(perl)>=5.008001
=item SITEPREFIX
Like PERLPREFIX, but only for the site install locations.
Defaults to $Config{siteprefixexp}. Perls prior to 5.6.0 didn't have
an explicit siteprefix in the Config. In those cases
$Config{installprefix} will be used.
Overridable by PREFIX
=item SIGN
When true, perform the generation and addition to the MANIFEST of the
SIGNATURE file in the distdir during 'make distdir', via 'cpansign
-s'.
Note that you need to install the Module::Signature module to
perform this operation.
Defaults to false.
=item SKIP
Arrayref. E.g. [qw(name1 name2)] skip (do not write) sections of the
Makefile. Caution! Do not use the SKIP attribute for the negligible
speedup. It may seriously damage the resulting Makefile. Only use it
if you really need it.
=item TYPEMAPS
Ref to array of typemap file names. Use this when the typemaps are
in some directory other than the current directory or when they are
not named B<typemap>. The last typemap in the list takes
precedence. A typemap in the current directory has highest
precedence, even if it isn't listed in TYPEMAPS. The default system
typemap has lowest precedence.
=item VENDORPREFIX
Like PERLPREFIX, but only for the vendor install locations.
Defaults to $Config{vendorprefixexp}.
Overridable by PREFIX
=item VERBINST
If true, make install will be verbose
=item VERSION
Your version number for distributing the package. This defaults to
0.1.
=item VERSION_FROM
Instead of specifying the VERSION in the Makefile.PL you can let
MakeMaker parse a file to determine the version number. The parsing
routine requires that the file named by VERSION_FROM contains one
single line to compute the version number. The first line in the file
that contains something like a $VERSION assignment or C<package Name
VERSION> will be used. The following lines will be parsed o.k.:
# Good
package Foo::Bar 1.23; # 1.23
$VERSION = '1.00'; # 1.00
*VERSION = \'1.01'; # 1.01
($VERSION) = q$Revision$ =~ /(\d+)/g; # The digits in $Revision$
$FOO::VERSION = '1.10'; # 1.10
*FOO::VERSION = \'1.11'; # 1.11
but these will fail:
# Bad
my $VERSION = '1.01';
local $VERSION = '1.02';
local $FOO::VERSION = '1.30';
"Version strings" are incompatible should not be used.
# Bad
$VERSION = 1.2.3;
$VERSION = v1.2.3;
L<version> objects are fine. As of MakeMaker 6.35 version.pm will be
automatically loaded, but you must declare the dependency on version.pm.
For compatibility with older MakeMaker you should load on the same line
as $VERSION is declared.
# All on one line
use version; our $VERSION = qv(1.2.3);
(Putting C<my> or C<local> on the preceding line will work o.k.)
The file named in VERSION_FROM is not added as a dependency to
Makefile. This is not really correct, but it would be a major pain
during development to have to rewrite the Makefile for any smallish
change in that file. If you want to make sure that the Makefile
contains the correct VERSION macro after any change of the file, you
would have to do something like
depend => { Makefile => '$(VERSION_FROM)' }
See attribute C<depend> below.
=item VERSION_SYM
A sanitized VERSION with . replaced by _. For places where . has
special meaning (some filesystems, RCS labels, etc...)
=item XS
Hashref of .xs files. MakeMaker will default this. e.g.
{'name_of_file.xs' => 'name_of_file.c'}
The .c files will automatically be included in the list of files
deleted by a make clean.
=item XSOPT
String of options to pass to xsubpp. This might include C<-C++> or
C<-extern>. Do not include typemaps here; the TYPEMAP parameter exists for
that purpose.
=item XSPROTOARG
May be set to an empty string, which is identical to C<-prototypes>, or
C<-noprototypes>. See the xsubpp documentation for details. MakeMaker
defaults to the empty string.
=item XS_VERSION
Your version number for the .xs file of this package. This defaults
to the value of the VERSION attribute.
=back
=head2 Additional lowercase attributes
can be used to pass parameters to the methods which implement that
part of the Makefile. Parameters are specified as a hash ref but are
passed to the method as a hash.
=over 2
=item clean
{FILES => "*.xyz foo"}
=item depend
{ANY_TARGET => ANY_DEPENDENCY, ...}
(ANY_TARGET must not be given a double-colon rule by MakeMaker.)
=item dist
{TARFLAGS => 'cvfF', COMPRESS => 'gzip', SUFFIX => '.gz',
SHAR => 'shar -m', DIST_CP => 'ln', ZIP => '/bin/zip',
ZIPFLAGS => '-rl', DIST_DEFAULT => 'private tardist' }
If you specify COMPRESS, then SUFFIX should also be altered, as it is
needed to tell make the target file of the compression. Setting
DIST_CP to ln can be useful, if you need to preserve the timestamps on
your files. DIST_CP can take the values 'cp', which copies the file,
'ln', which links the file, and 'best' which copies symbolic links and
links the rest. Default is 'best'.
=item dynamic_lib
{ARMAYBE => 'ar', OTHERLDFLAGS => '...', INST_DYNAMIC_DEP => '...'}
=item linkext
{LINKTYPE => 'static', 'dynamic' or ''}
NB: Extensions that have nothing but *.pm files had to say
{LINKTYPE => ''}
with Pre-5.0 MakeMakers. Since version 5.00 of MakeMaker such a line
can be deleted safely. MakeMaker recognizes when there's nothing to
be linked.
=item macro
{ANY_MACRO => ANY_VALUE, ...}
=item postamble
Anything put here will be passed to MY::postamble() if you have one.
=item realclean
{FILES => '$(INST_ARCHAUTODIR)/*.xyz'}
=item test
{TESTS => 't/*.t'}
=item tool_autosplit
{MAXLEN => 8}
=back
=head2 Overriding MakeMaker Methods
If you cannot achieve the desired Makefile behaviour by specifying
attributes you may define private subroutines in the Makefile.PL.
Each subroutine returns the text it wishes to have written to
the Makefile. To override a section of the Makefile you can
either say:
sub MY::c_o { "new literal text" }
or you can edit the default by saying something like:
package MY; # so that "SUPER" works right
sub c_o {
my $inherited = shift->SUPER::c_o(@_);
$inherited =~ s/old text/new text/;
$inherited;
}
If you are running experiments with embedding perl as a library into
other applications, you might find MakeMaker is not sufficient. You'd
better have a look at ExtUtils::Embed which is a collection of utilities
for embedding.
If you still need a different solution, try to develop another
subroutine that fits your needs and submit the diffs to
C<makemaker@perl.org>
For a complete description of all MakeMaker methods see
L<ExtUtils::MM_Unix>.
Here is a simple example of how to add a new target to the generated
Makefile:
sub MY::postamble {
return <<'MAKE_FRAG';
$(MYEXTLIB): sdbm/Makefile
cd sdbm && $(MAKE) all
MAKE_FRAG
}
=head2 The End Of Cargo Cult Programming
WriteMakefile() now does some basic sanity checks on its parameters to
protect against typos and malformatted values. This means some things
which happened to work in the past will now throw warnings and
possibly produce internal errors.
Some of the most common mistakes:
=over 2
=item C<< MAN3PODS => ' ' >>
This is commonly used to suppress the creation of man pages. MAN3PODS
takes a hash ref not a string, but the above worked by accident in old
versions of MakeMaker.
The correct code is C<< MAN3PODS => { } >>.
=back
=head2 Hintsfile support
MakeMaker.pm uses the architecture specific information from
Config.pm. In addition it evaluates architecture specific hints files
in a C<hints/> directory. The hints files are expected to be named
like their counterparts in C<PERL_SRC/hints>, but with an C<.pl> file
name extension (eg. C<next_3_2.pl>). They are simply C<eval>ed by
MakeMaker within the WriteMakefile() subroutine, and can be used to
execute commands as well as to include special variables. The rules
which hintsfile is chosen are the same as in Configure.
The hintsfile is eval()ed immediately after the arguments given to
WriteMakefile are stuffed into a hash reference $self but before this
reference becomes blessed. So if you want to do the equivalent to
override or create an attribute you would say something like
$self->{LIBS} = ['-ldbm -lucb -lc'];
=head2 Distribution Support
For authors of extensions MakeMaker provides several Makefile
targets. Most of the support comes from the ExtUtils::Manifest module,
where additional documentation can be found.
=over 4
=item make distcheck
reports which files are below the build directory but not in the
MANIFEST file and vice versa. (See ExtUtils::Manifest::fullcheck() for
details)
=item make skipcheck
reports which files are skipped due to the entries in the
C<MANIFEST.SKIP> file (See ExtUtils::Manifest::skipcheck() for
details)
=item make distclean
does a realclean first and then the distcheck. Note that this is not
needed to build a new distribution as long as you are sure that the
MANIFEST file is ok.
=item make manifest
rewrites the MANIFEST file, adding all remaining files found (See
ExtUtils::Manifest::mkmanifest() for details)
=item make distdir
Copies all the files that are in the MANIFEST file to a newly created
directory with the name C<$(DISTNAME)-$(VERSION)>. If that directory
exists, it will be removed first.
Additionally, it will create META.yml and META.json module meta-data file
in the distdir and add this to the distdir's MANIFEST. You can shut this
behavior off with the NO_META flag.
=item make disttest
Makes a distdir first, and runs a C<perl Makefile.PL>, a make, and
a make test in that directory.
=item make tardist
First does a distdir. Then a command $(PREOP) which defaults to a null
command, followed by $(TO_UNIX), which defaults to a null command under
UNIX, and will convert files in distribution directory to UNIX format
otherwise. Next it runs C<tar> on that directory into a tarfile and
deletes the directory. Finishes with a command $(POSTOP) which
defaults to a null command.
=item make dist
Defaults to $(DIST_DEFAULT) which in turn defaults to tardist.
=item make uutardist
Runs a tardist first and uuencodes the tarfile.
=item make shdist
First does a distdir. Then a command $(PREOP) which defaults to a null
command. Next it runs C<shar> on that directory into a sharfile and
deletes the intermediate directory again. Finishes with a command
$(POSTOP) which defaults to a null command. Note: For shdist to work
properly a C<shar> program that can handle directories is mandatory.
=item make zipdist
First does a distdir. Then a command $(PREOP) which defaults to a null
command. Runs C<$(ZIP) $(ZIPFLAGS)> on that directory into a
zipfile. Then deletes that directory. Finishes with a command
$(POSTOP) which defaults to a null command.
=item make ci
Does a $(CI) and a $(RCS_LABEL) on all files in the MANIFEST file.
=back
Customization of the dist targets can be done by specifying a hash
reference to the dist attribute of the WriteMakefile call. The
following parameters are recognized:
CI ('ci -u')
COMPRESS ('gzip --best')
POSTOP ('@ :')
PREOP ('@ :')
TO_UNIX (depends on the system)
RCS_LABEL ('rcs -q -Nv$(VERSION_SYM):')
SHAR ('shar')
SUFFIX ('.gz')
TAR ('tar')
TARFLAGS ('cvf')
ZIP ('zip')
ZIPFLAGS ('-r')
An example:
WriteMakefile(
...other options...
dist => {
COMPRESS => "bzip2",
SUFFIX => ".bz2"
}
);
=head2 Module Meta-Data (META and MYMETA)
Long plaguing users of MakeMaker based modules has been the problem of
getting basic information about the module out of the sources
I<without> running the F<Makefile.PL> and doing a bunch of messy
heuristics on the resulting F<Makefile>. Over the years, it has become
standard to keep this information in one or more CPAN Meta files
distributed with each distribution.
The original format of CPAN Meta files was L<YAML> and the corresponding
file was called F<META.yml>. In 2010, version 2 of the L<CPAN::Meta::Spec>
was released, which mandates JSON format for the metadata in order to
overcome certain compatibility issues between YAML serializers and to
avoid breaking older clients unable to handle a new version of the spec.
The L<CPAN::Meta> library is now standard for accessing old and new-style
Meta files.
If L<CPAN::Meta> is installed, MakeMaker will automatically generate
F<META.json> and F<META.yml> files for you and add them to your F<MANIFEST> as
part of the 'distdir' target (and thus the 'dist' target). This is intended to
seamlessly and rapidly populate CPAN with module meta-data. If you wish to
shut this feature off, set the C<NO_META> C<WriteMakefile()> flag to true.
At the 2008 QA Hackathon in Oslo, Perl module toolchain maintainers agrees
to use the CPAN Meta format to communicate post-configuration requirements
between toolchain components. These files, F<MYMETA.json> and F<MYMETA.yml>,
are generated when F<Makefile.PL> generates a F<Makefile> (if L<CPAN::Meta>
is installed). Clients like L<CPAN> or L<CPANPLUS> will read this
files to see what prerequisites must be fulfilled before building or testing
the distribution. If you with to shut this feature off, set the C<NO_MYMETA>
C<WriteMakeFile()> flag to true.
=head2 Disabling an extension
If some events detected in F<Makefile.PL> imply that there is no way
to create the Module, but this is a normal state of things, then you
can create a F<Makefile> which does nothing, but succeeds on all the
"usual" build targets. To do so, use
use ExtUtils::MakeMaker qw(WriteEmptyMakefile);
WriteEmptyMakefile();
instead of WriteMakefile().
This may be useful if other modules expect this module to be I<built>
OK, as opposed to I<work> OK (say, this system-dependent module builds
in a subdirectory of some other distribution, or is listed as a
dependency in a CPAN::Bundle, but the functionality is supported by
different means on the current architecture).
=head2 Other Handy Functions
=over 4
=item prompt
my $value = prompt($message);
my $value = prompt($message, $default);
The C<prompt()> function provides an easy way to request user input
used to write a makefile. It displays the $message as a prompt for
input. If a $default is provided it will be used as a default. The
function returns the $value selected by the user.
If C<prompt()> detects that it is not running interactively and there
is nothing on STDIN or if the PERL_MM_USE_DEFAULT environment variable
is set to true, the $default will be used without prompting. This
prevents automated processes from blocking on user input.
If no $default is provided an empty string will be used instead.
=back
=head1 ENVIRONMENT
=over 4
=item PERL_MM_OPT
Command line options used by C<MakeMaker-E<gt>new()>, and thus by
C<WriteMakefile()>. The string is split on whitespace, and the result
is processed before any actual command line arguments are processed.
=item PERL_MM_USE_DEFAULT
If set to a true value then MakeMaker's prompt function will
always return the default without waiting for user input.
=item PERL_CORE
Same as the PERL_CORE parameter. The parameter overrides this.
=back
=head1 SEE ALSO
L<Module::Build> is a pure-Perl alternative to MakeMaker which does
not rely on make or any other external utility. It is easier to
extend to suit your needs.
L<Module::Install> is a wrapper around MakeMaker which adds features
not normally available.
L<ExtUtils::ModuleMaker> and L<Module::Starter> are both modules to
help you setup your distribution.
L<CPAN::Meta> and L<CPAN::Meta::Spec> explain CPAN Meta files in detail.
=head1 AUTHORS
Andy Dougherty C<doughera@lafayette.edu>, Andreas KE<ouml>nig
C<andreas.koenig@mind.de>, Tim Bunce C<timb@cpan.org>. VMS
support by Charles Bailey C<bailey@newman.upenn.edu>. OS/2 support
by Ilya Zakharevich C<ilya@math.ohio-state.edu>.
Currently maintained by Michael G Schwern C<schwern@pobox.com>
Send patches and ideas to C<makemaker@perl.org>.
Send bug reports via http://rt.cpan.org/. Please send your
generated Makefile along with your report.
For more up-to-date information, see L<http://www.makemaker.org>.
Repository available at L<https://github.com/Perl-Toolchain-Gang/ExtUtils-MakeMaker>.
=head1 LICENSE
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
See L<http://www.perl.com/perl/misc/Artistic.html>
=cut
EXTUTILS_MAKEMAKER
$fatpacked{"ExtUtils/MakeMaker/Config.pm"} = <<'EXTUTILS_MAKEMAKER_CONFIG';
package ExtUtils::MakeMaker::Config;
use strict;
our $VERSION = '6.59';
use Config ();
# Give us an overridable config.
our %Config = %Config::Config;
sub import {
my $caller = caller;
no strict 'refs'; ## no critic
*{$caller.'::Config'} = \%Config;
}
1;
=head1 NAME
ExtUtils::MakeMaker::Config - Wrapper around Config.pm
=head1 SYNOPSIS
use ExtUtils::MakeMaker::Config;
print $Config{installbin}; # or whatever
=head1 DESCRIPTION
B<FOR INTERNAL USE ONLY>
A very thin wrapper around Config.pm so MakeMaker is easier to test.
=cut
EXTUTILS_MAKEMAKER_CONFIG
$fatpacked{"ExtUtils/Mkbootstrap.pm"} = <<'EXTUTILS_MKBOOTSTRAP';
package ExtUtils::Mkbootstrap;
# There's just too much Dynaloader incest here to turn on strict vars.
use strict 'refs';
our $VERSION = '6.59';
require Exporter;
our @ISA = ('Exporter');
our @EXPORT = ('&Mkbootstrap');
use Config;
our $Verbose = 0;
sub Mkbootstrap {
my($baseext, @bsloadlibs)=@_;
@bsloadlibs = grep($_, @bsloadlibs); # strip empty libs
print STDOUT " bsloadlibs=@bsloadlibs\n" if $Verbose;
# We need DynaLoader here because we and/or the *_BS file may
# call dl_findfile(). We don't say `use' here because when
# first building perl extensions the DynaLoader will not have
# been built when MakeMaker gets first used.
require DynaLoader;
rename "$baseext.bs", "$baseext.bso"
if -s "$baseext.bs";
if (-f "${baseext}_BS"){
$_ = "${baseext}_BS";
package DynaLoader; # execute code as if in DynaLoader
local($osname, $dlsrc) = (); # avoid warnings
($osname, $dlsrc) = @Config::Config{qw(osname dlsrc)};
$bscode = "";
unshift @INC, ".";
require $_;
shift @INC;
}
if ($Config{'dlsrc'} =~ /^dl_dld/){
package DynaLoader;
push(@dl_resolve_using, dl_findfile('-lc'));
}
my(@all) = (@bsloadlibs, @DynaLoader::dl_resolve_using);
my($method) = '';
if (@all){
open my $bs, ">", "$baseext.bs"
or die "Unable to open $baseext.bs: $!";
print STDOUT "Writing $baseext.bs\n";
print STDOUT " containing: @all" if $Verbose;
print $bs "# $baseext DynaLoader bootstrap file for $^O architecture.\n";
print $bs "# Do not edit this file, changes will be lost.\n";
print $bs "# This file was automatically generated by the\n";
print $bs "# Mkbootstrap routine in ExtUtils::Mkbootstrap (v$VERSION).\n";
print $bs "\@DynaLoader::dl_resolve_using = ";
# If @all contains names in the form -lxxx or -Lxxx then it's asking for
# runtime library location so we automatically add a call to dl_findfile()
if (" @all" =~ m/ -[lLR]/){
print $bs " dl_findfile(qw(\n @all\n ));\n";
}else{
print $bs " qw(@all);\n";
}
# write extra code if *_BS says so
print $bs $DynaLoader::bscode if $DynaLoader::bscode;
print $bs "\n1;\n";
close $bs;
}
}
1;
__END__
=head1 NAME
ExtUtils::Mkbootstrap - make a bootstrap file for use by DynaLoader
=head1 SYNOPSIS
C<Mkbootstrap>
=head1 DESCRIPTION
Mkbootstrap typically gets called from an extension Makefile.
There is no C<*.bs> file supplied with the extension. Instead, there may
be a C<*_BS> file which has code for the special cases, like posix for
berkeley db on the NeXT.
This file will get parsed, and produce a maybe empty
C<@DynaLoader::dl_resolve_using> array for the current architecture.
That will be extended by $BSLOADLIBS, which was computed by
ExtUtils::Liblist::ext(). If this array still is empty, we do nothing,
else we write a .bs file with an C<@DynaLoader::dl_resolve_using>
array.
The C<*_BS> file can put some code into the generated C<*.bs> file by
placing it in C<$bscode>. This is a handy 'escape' mechanism that may
prove useful in complex situations.
If @DynaLoader::dl_resolve_using contains C<-L*> or C<-l*> entries then
Mkbootstrap will automatically add a dl_findfile() call to the
generated C<*.bs> file.
=cut
EXTUTILS_MKBOOTSTRAP
$fatpacked{"ExtUtils/Mksymlists.pm"} = <<'EXTUTILS_MKSYMLISTS';
package ExtUtils::Mksymlists;
use 5.006;
use strict qw[ subs refs ];
# no strict 'vars'; # until filehandles are exempted
use Carp;
use Exporter;
use Config;
our @ISA = qw(Exporter);
our @EXPORT = qw(&Mksymlists);
our $VERSION = '6.59';
sub Mksymlists {
my(%spec) = @_;
my($osname) = $^O;
croak("Insufficient information specified to Mksymlists")
unless ( $spec{NAME} or
($spec{FILE} and ($spec{DL_FUNCS} or $spec{FUNCLIST})) );
$spec{DL_VARS} = [] unless $spec{DL_VARS};
($spec{FILE} = $spec{NAME}) =~ s/.*::// unless $spec{FILE};
$spec{FUNCLIST} = [] unless $spec{FUNCLIST};
$spec{DL_FUNCS} = { $spec{NAME} => [] }
unless ( ($spec{DL_FUNCS} and keys %{$spec{DL_FUNCS}}) or
@{$spec{FUNCLIST}});
if (defined $spec{DL_FUNCS}) {
foreach my $package (keys %{$spec{DL_FUNCS}}) {
my($packprefix,$bootseen);
($packprefix = $package) =~ s/\W/_/g;
foreach my $sym (@{$spec{DL_FUNCS}->{$package}}) {
if ($sym =~ /^boot_/) {
push(@{$spec{FUNCLIST}},$sym);
$bootseen++;
}
else {
push(@{$spec{FUNCLIST}},"XS_${packprefix}_$sym");
}
}
push(@{$spec{FUNCLIST}},"boot_$packprefix") unless $bootseen;
}
}
# We'll need this if we ever add any OS which uses mod2fname
# not as pseudo-builtin.
# require DynaLoader;
if (defined &DynaLoader::mod2fname and not $spec{DLBASE}) {
$spec{DLBASE} = DynaLoader::mod2fname([ split(/::/,$spec{NAME}) ]);
}
if ($osname eq 'aix') { _write_aix(\%spec); }
elsif ($osname eq 'MacOS'){ _write_aix(\%spec) }
elsif ($osname eq 'VMS') { _write_vms(\%spec) }
elsif ($osname eq 'os2') { _write_os2(\%spec) }
elsif ($osname eq 'MSWin32') { _write_win32(\%spec) }
else {
croak("Don't know how to create linker option file for $osname\n");
}
}
sub _write_aix {
my($data) = @_;
rename "$data->{FILE}.exp", "$data->{FILE}.exp_old";
open( my $exp, ">", "$data->{FILE}.exp")
or croak("Can't create $data->{FILE}.exp: $!\n");
print $exp join("\n",@{$data->{DL_VARS}}, "\n") if @{$data->{DL_VARS}};
print $exp join("\n",@{$data->{FUNCLIST}}, "\n") if @{$data->{FUNCLIST}};
close $exp;
}
sub _write_os2 {
my($data) = @_;
require Config;
my $threaded = ($Config::Config{archname} =~ /-thread/ ? " threaded" : "");
if (not $data->{DLBASE}) {
($data->{DLBASE} = $data->{NAME}) =~ s/.*:://;
$data->{DLBASE} = substr($data->{DLBASE},0,7) . '_';
}
my $distname = $data->{DISTNAME} || $data->{NAME};
$distname = "Distribution $distname";
my $patchlevel = " pl$Config{perl_patchlevel}" || '';
my $comment = sprintf "Perl (v%s%s%s) module %s",
$Config::Config{version}, $threaded, $patchlevel, $data->{NAME};
chomp $comment;
if ($data->{INSTALLDIRS} and $data->{INSTALLDIRS} eq 'perl') {
$distname = 'perl5-porters@perl.org';
$comment = "Core $comment";
}
$comment = "$comment (Perl-config: $Config{config_args})";
$comment = substr($comment, 0, 200) . "...)" if length $comment > 203;
rename "$data->{FILE}.def", "$data->{FILE}_def.old";
open(my $def, ">", "$data->{FILE}.def")
or croak("Can't create $data->{FILE}.def: $!\n");
print $def "LIBRARY '$data->{DLBASE}' INITINSTANCE TERMINSTANCE\n";
print $def "DESCRIPTION '\@#$distname:$data->{VERSION}#\@ $comment'\n";
print $def "CODE LOADONCALL\n";
print $def "DATA LOADONCALL NONSHARED MULTIPLE\n";
print $def "EXPORTS\n ";
print $def join("\n ",@{$data->{DL_VARS}}, "\n") if @{$data->{DL_VARS}};
print $def join("\n ",@{$data->{FUNCLIST}}, "\n") if @{$data->{FUNCLIST}};
if (%{$data->{IMPORTS}}) {
print $def "IMPORTS\n";
my ($name, $exp);
while (($name, $exp)= each %{$data->{IMPORTS}}) {
print $def " $name=$exp\n";
}
}
close $def;
}
sub _write_win32 {
my($data) = @_;
require Config;
if (not $data->{DLBASE}) {
($data->{DLBASE} = $data->{NAME}) =~ s/.*:://;
$data->{DLBASE} = substr($data->{DLBASE},0,7) . '_';
}
rename "$data->{FILE}.def", "$data->{FILE}_def.old";
open( my $def, ">", "$data->{FILE}.def" )
or croak("Can't create $data->{FILE}.def: $!\n");
# put library name in quotes (it could be a keyword, like 'Alias')
if ($Config::Config{'cc'} !~ /^gcc/i) {
print $def "LIBRARY \"$data->{DLBASE}\"\n";
}
print $def "EXPORTS\n ";
my @syms;
# Export public symbols both with and without underscores to
# ensure compatibility between DLLs from different compilers
# NOTE: DynaLoader itself only uses the names without underscores,
# so this is only to cover the case when the extension DLL may be
# linked to directly from C. GSAR 97-07-10
if ($Config::Config{'cc'} =~ /^bcc/i) {
for (@{$data->{DL_VARS}}, @{$data->{FUNCLIST}}) {
push @syms, "_$_", "$_ = _$_";
}
}
else {
for (@{$data->{DL_VARS}}, @{$data->{FUNCLIST}}) {
push @syms, "$_", "_$_ = $_";
}
}
print $def join("\n ",@syms, "\n") if @syms;
if (%{$data->{IMPORTS}}) {
print $def "IMPORTS\n";
my ($name, $exp);
while (($name, $exp)= each %{$data->{IMPORTS}}) {
print $def " $name=$exp\n";
}
}
close $def;
}
sub _write_vms {
my($data) = @_;
require Config; # a reminder for once we do $^O
require ExtUtils::XSSymSet;
my($isvax) = $Config::Config{'archname'} =~ /VAX/i;
my($set) = new ExtUtils::XSSymSet;
rename "$data->{FILE}.opt", "$data->{FILE}.opt_old";
open(my $opt,">", "$data->{FILE}.opt")
or croak("Can't create $data->{FILE}.opt: $!\n");
# Options file declaring universal symbols
# Used when linking shareable image for dynamic extension,
# or when linking PerlShr into which we've added this package
# as a static extension
# We don't do anything to preserve order, so we won't relax
# the GSMATCH criteria for a dynamic extension
print $opt "case_sensitive=yes\n"
if $Config::Config{d_vms_case_sensitive_symbols};
foreach my $sym (@{$data->{FUNCLIST}}) {
my $safe = $set->addsym($sym);
if ($isvax) { print $opt "UNIVERSAL=$safe\n" }
else { print $opt "SYMBOL_VECTOR=($safe=PROCEDURE)\n"; }
}
foreach my $sym (@{$data->{DL_VARS}}) {
my $safe = $set->addsym($sym);
print $opt "PSECT_ATTR=${sym},PIC,OVR,RD,NOEXE,WRT,NOSHR\n";
if ($isvax) { print $opt "UNIVERSAL=$safe\n" }
else { print $opt "SYMBOL_VECTOR=($safe=DATA)\n"; }
}
close $opt;
}
1;
__END__
=head1 NAME
ExtUtils::Mksymlists - write linker options files for dynamic extension
=head1 SYNOPSIS
use ExtUtils::Mksymlists;
Mksymlists({ NAME => $name ,
DL_VARS => [ $var1, $var2, $var3 ],
DL_FUNCS => { $pkg1 => [ $func1, $func2 ],
$pkg2 => [ $func3 ] });
=head1 DESCRIPTION
C<ExtUtils::Mksymlists> produces files used by the linker under some OSs
during the creation of shared libraries for dynamic extensions. It is
normally called from a MakeMaker-generated Makefile when the extension
is built. The linker option file is generated by calling the function
C<Mksymlists>, which is exported by default from C<ExtUtils::Mksymlists>.
It takes one argument, a list of key-value pairs, in which the following
keys are recognized:
=over 4
=item DLBASE
This item specifies the name by which the linker knows the
extension, which may be different from the name of the
extension itself (for instance, some linkers add an '_' to the
name of the extension). If it is not specified, it is derived
from the NAME attribute. It is presently used only by OS2 and Win32.
=item DL_FUNCS
This is identical to the DL_FUNCS attribute available via MakeMaker,
from which it is usually taken. Its value is a reference to an
associative array, in which each key is the name of a package, and
each value is an a reference to an array of function names which
should be exported by the extension. For instance, one might say
C<DL_FUNCS =E<gt> { Homer::Iliad =E<gt> [ qw(trojans greeks) ],
Homer::Odyssey =E<gt> [ qw(travellers family suitors) ] }>. The
function names should be identical to those in the XSUB code;
C<Mksymlists> will alter the names written to the linker option
file to match the changes made by F<xsubpp>. In addition, if
none of the functions in a list begin with the string B<boot_>,
C<Mksymlists> will add a bootstrap function for that package,
just as xsubpp does. (If a B<boot_E<lt>pkgE<gt>> function is
present in the list, it is passed through unchanged.) If
DL_FUNCS is not specified, it defaults to the bootstrap
function for the extension specified in NAME.
=item DL_VARS
This is identical to the DL_VARS attribute available via MakeMaker,
and, like DL_FUNCS, it is usually specified via MakeMaker. Its
value is a reference to an array of variable names which should
be exported by the extension.
=item FILE
This key can be used to specify the name of the linker option file
(minus the OS-specific extension), if for some reason you do not
want to use the default value, which is the last word of the NAME
attribute (I<e.g.> for C<Tk::Canvas>, FILE defaults to C<Canvas>).
=item FUNCLIST
This provides an alternate means to specify function names to be
exported from the extension. Its value is a reference to an
array of function names to be exported by the extension. These
names are passed through unaltered to the linker options file.
Specifying a value for the FUNCLIST attribute suppresses automatic
generation of the bootstrap function for the package. To still create
the bootstrap name you have to specify the package name in the
DL_FUNCS hash:
Mksymlists({ NAME => $name ,
FUNCLIST => [ $func1, $func2 ],
DL_FUNCS => { $pkg => [] } });
=item IMPORTS
This attribute is used to specify names to be imported into the
extension. It is currently only used by OS/2 and Win32.
=item NAME
This gives the name of the extension (I<e.g.> C<Tk::Canvas>) for which
the linker option file will be produced.
=back
When calling C<Mksymlists>, one should always specify the NAME
attribute. In most cases, this is all that's necessary. In
the case of unusual extensions, however, the other attributes
can be used to provide additional information to the linker.
=head1 AUTHOR
Charles Bailey I<E<lt>bailey@newman.upenn.eduE<gt>>
=head1 REVISION
Last revised 14-Feb-1996, for Perl 5.002.
EXTUTILS_MKSYMLISTS
$fatpacked{"ExtUtils/testlib.pm"} = <<'EXTUTILS_TESTLIB';
package ExtUtils::testlib;
use strict;
use warnings;
our $VERSION = '6.59';
use Cwd;
use File::Spec;
# So the tests can chdir around and not break @INC.
# We use getcwd() because otherwise rel2abs will blow up under taint
# mode pre-5.8. We detaint is so @INC won't be tainted. This is
# no worse, and probably better, than just shoving an untainted,
# relative "blib/lib" onto @INC.
my $cwd;
BEGIN {
($cwd) = getcwd() =~ /(.*)/;
}
use lib map { File::Spec->rel2abs($_, $cwd) } qw(blib/arch blib/lib);
1;
__END__
=head1 NAME
ExtUtils::testlib - add blib/* directories to @INC
=head1 SYNOPSIS
use ExtUtils::testlib;
=head1 DESCRIPTION
After an extension has been built and before it is installed it may be
desirable to test it bypassing C<make test>. By adding
use ExtUtils::testlib;
to a test program the intermediate directories used by C<make> are
added to @INC.
EXTUTILS_TESTLIB
$fatpacked{"File/pushd.pm"} = <<'FILE_PUSHD';
package File::pushd;
$VERSION = '1.00';
@EXPORT = qw( pushd tempd );
@ISA = qw( Exporter );
use 5.004;
use strict;
#use warnings;
use Exporter;
use Carp;
use Cwd qw( cwd abs_path );
use File::Path qw( rmtree );
use File::Temp qw();
use File::Spec;
use overload
q{""} => sub { File::Spec->canonpath( $_[0]->{_pushd} ) },
fallback => 1;
#--------------------------------------------------------------------------#
# pushd()
#--------------------------------------------------------------------------#
sub pushd {
my ($target_dir) = @_;
my $orig = cwd;
my $dest;
eval { $dest = $target_dir ? abs_path( $target_dir ) : $orig };
croak "Can't locate directory $target_dir: $@" if $@;
if ($dest ne $orig) {
chdir $dest or croak "Can't chdir to $dest\: $!";
}
my $self = bless {
_pushd => $dest,
_original => $orig
}, __PACKAGE__;
return $self;
}
#--------------------------------------------------------------------------#
# tempd()
#--------------------------------------------------------------------------#
sub tempd {
my $dir = pushd( File::Temp::tempdir( CLEANUP => 0 ) );
$dir->{_tempd} = 1;
return $dir;
}
#--------------------------------------------------------------------------#
# preserve()
#--------------------------------------------------------------------------#
sub preserve {
my $self = shift;
return 1 if ! $self->{"_tempd"};
if ( @_ == 0 ) {
return $self->{_preserve} = 1;
}
else {
return $self->{_preserve} = $_[0] ? 1 : 0;
}
}
#--------------------------------------------------------------------------#
# DESTROY()
# Revert to original directory as object is destroyed and cleanup
# if necessary
#--------------------------------------------------------------------------#
sub DESTROY {
my ($self) = @_;
my $orig = $self->{_original};
chdir $orig if $orig; # should always be so, but just in case...
if ( $self->{_tempd} &&
!$self->{_preserve} ) {
eval { rmtree( $self->{_pushd} ) };
carp $@ if $@;
}
}
1; #this line is important and will help the module return a true value
__END__
=begin wikidoc
= NAME
File::pushd - change directory temporarily for a limited scope
= VERSION
This documentation describes version %%VERSION%%.
= SYNOPSIS
use File::pushd;
chdir $ENV{HOME};
# change directory again for a limited scope
{
my $dir = pushd( '/tmp' );
# working directory changed to /tmp
}
# working directory has reverted to $ENV{HOME}
# tempd() is equivalent to pushd( File::Temp::tempdir )
{
my $dir = tempd();
}
# object stringifies naturally as an absolute path
{
my $dir = pushd( '/tmp' );
my $filename = File::Spec->catfile( $dir, "somefile.txt" );
# gives /tmp/somefile.txt
}
= DESCRIPTION
File::pushd does a temporary {chdir} that is easily and automatically
reverted, similar to {pushd} in some Unix command shells. It works by
creating an object that caches the original working directory. When the object
is destroyed, the destructor calls {chdir} to revert to the original working
directory. By storing the object in a lexical variable with a limited scope,
this happens automatically at the end of the scope.
This is very handy when working with temporary directories for tasks like
testing; a function is provided to streamline getting a temporary
directory from [File::Temp].
For convenience, the object stringifies as the canonical form of the absolute
pathname of the directory entered.
= USAGE
use File::pushd;
Using File::pushd automatically imports the {pushd} and {tempd} functions.
== pushd
{
my $dir = pushd( $target_directory );
}
Caches the current working directory, calls {chdir} to change to the target
directory, and returns a File::pushd object. When the object is
destroyed, the working directory reverts to the original directory.
The provided target directory can be a relative or absolute path. If
called with no arguments, it uses the current directory as its target and
returns to the current directory when the object is destroyed.
== tempd
{
my $dir = tempd();
}
This function is like {pushd} but automatically creates and calls {chdir} to
a temporary directory created by [File::Temp]. Unlike normal [File::Temp]
cleanup which happens at the end of the program, this temporary directory is
removed when the object is destroyed. (But also see {preserve}.) A warning
will be issued if the directory cannot be removed.
== preserve
{
my $dir = tempd();
$dir->preserve; # mark to preserve at end of scope
$dir->preserve(0); # mark to delete at end of scope
}
Controls whether a temporary directory will be cleaned up when the object is
destroyed. With no arguments, {preserve} sets the directory to be preserved.
With an argument, the directory will be preserved if the argument is true, or
marked for cleanup if the argument is false. Only {tempd} objects may be
marked for cleanup. (Target directories to {pushd} are always preserved.)
{preserve} returns true if the directory will be preserved, and false
otherwise.
= SEE ALSO
* [File::chdir]
= BUGS
Please report any bugs or feature using the CPAN Request Tracker.
Bugs can be submitted through the web interface at
[http://rt.cpan.org/Dist/Display.html?Queue=File-pushd]
When submitting a bug or request, please include a test-file or a patch to an
existing test-file that illustrates the bug or desired feature.
= AUTHOR
David A. Golden (DAGOLDEN)
= COPYRIGHT AND LICENSE
Copyright (c) 2005, 2006, 2007 by David A. Golden
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
[http://www.apache.org/licenses/LICENSE-2.0]
Files produced as output though the use of this software, including
generated copies of boilerplate templates provided with this software,
shall not be considered Derivative Works, but shall be considered the
original work of the Licensor.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=end wikidoc
FILE_PUSHD
$fatpacked{"IPC/Cmd.pm"} = <<'IPC_CMD';
package IPC::Cmd;
use strict;
BEGIN {
use constant IS_VMS => $^O eq 'VMS' ? 1 : 0;
use constant IS_WIN32 => $^O eq 'MSWin32' ? 1 : 0;
use constant IS_WIN98 => (IS_WIN32 and !Win32::IsWinNT()) ? 1 : 0;
use constant ALARM_CLASS => __PACKAGE__ . '::TimeOut';
use constant SPECIAL_CHARS => qw[< > | &];
use constant QUOTE => do { IS_WIN32 ? q["] : q['] };
use Exporter ();
use vars qw[ @ISA $VERSION @EXPORT_OK $VERBOSE $DEBUG
$USE_IPC_RUN $USE_IPC_OPEN3 $CAN_USE_RUN_FORKED $WARN
$INSTANCES
];
$VERSION = '0.72';
$VERBOSE = 0;
$DEBUG = 0;
$WARN = 1;
$USE_IPC_RUN = IS_WIN32 && !IS_WIN98;
$USE_IPC_OPEN3 = not IS_VMS;
$CAN_USE_RUN_FORKED = 0;
eval {
require POSIX; POSIX->import();
require IPC::Open3; IPC::Open3->import();
require IO::Select; IO::Select->import();
require IO::Handle; IO::Handle->import();
require FileHandle; FileHandle->import();
require Socket; Socket->import();
require Time::HiRes; Time::HiRes->import();
require Win32 if IS_WIN32;
};
$CAN_USE_RUN_FORKED = $@ || !IS_VMS && !IS_WIN32;
@ISA = qw[Exporter];
@EXPORT_OK = qw[can_run run run_forked QUOTE];
}
require Carp;
use File::Spec;
use Params::Check qw[check];
use Text::ParseWords (); # import ONLY if needed!
use Module::Load::Conditional qw[can_load];
use Locale::Maketext::Simple Style => 'gettext';
=pod
=head1 NAME
IPC::Cmd - finding and running system commands made easy
=head1 SYNOPSIS
use IPC::Cmd qw[can_run run run_forked];
my $full_path = can_run('wget') or warn 'wget is not installed!';
### commands can be arrayrefs or strings ###
my $cmd = "$full_path -b theregister.co.uk";
my $cmd = [$full_path, '-b', 'theregister.co.uk'];
### in scalar context ###
my $buffer;
if( scalar run( command => $cmd,
verbose => 0,
buffer => \$buffer,
timeout => 20 )
) {
print "fetched webpage successfully: $buffer\n";
}
### in list context ###
my( $success, $error_message, $full_buf, $stdout_buf, $stderr_buf ) =
run( command => $cmd, verbose => 0 );
if( $success ) {
print "this is what the command printed:\n";
print join "", @$full_buf;
}
### check for features
print "IPC::Open3 available: " . IPC::Cmd->can_use_ipc_open3;
print "IPC::Run available: " . IPC::Cmd->can_use_ipc_run;
print "Can capture buffer: " . IPC::Cmd->can_capture_buffer;
### don't have IPC::Cmd be verbose, ie don't print to stdout or
### stderr when running commands -- default is '0'
$IPC::Cmd::VERBOSE = 0;
=head1 DESCRIPTION
IPC::Cmd allows you to run commands platform independently,
interactively if desired, but have them still work.
The C<can_run> function can tell you if a certain binary is installed
and if so where, whereas the C<run> function can actually execute any
of the commands you give it and give you a clear return value, as well
as adhere to your verbosity settings.
=head1 CLASS METHODS
=head2 $ipc_run_version = IPC::Cmd->can_use_ipc_run( [VERBOSE] )
Utility function that tells you if C<IPC::Run> is available.
If the C<verbose> flag is passed, it will print diagnostic messages
if L<IPC::Run> can not be found or loaded.
=cut
sub can_use_ipc_run {
my $self = shift;
my $verbose = shift || 0;
### IPC::Run doesn't run on win98
return if IS_WIN98;
### if we dont have ipc::run, we obviously can't use it.
return unless can_load(
modules => { 'IPC::Run' => '0.55' },
verbose => ($WARN && $verbose),
);
### otherwise, we're good to go
return $IPC::Run::VERSION;
}
=head2 $ipc_open3_version = IPC::Cmd->can_use_ipc_open3( [VERBOSE] )
Utility function that tells you if C<IPC::Open3> is available.
If the verbose flag is passed, it will print diagnostic messages
if C<IPC::Open3> can not be found or loaded.
=cut
sub can_use_ipc_open3 {
my $self = shift;
my $verbose = shift || 0;
### IPC::Open3 is not working on VMS because of a lack of fork.
return if IS_VMS;
### IPC::Open3 works on every non-VMS platform platform, but it can't
### capture buffers on win32 :(
return unless can_load(
modules => { map {$_ => '0.0'} qw|IPC::Open3 IO::Select Symbol| },
verbose => ($WARN && $verbose),
);
return $IPC::Open3::VERSION;
}
=head2 $bool = IPC::Cmd->can_capture_buffer
Utility function that tells you if C<IPC::Cmd> is capable of
capturing buffers in it's current configuration.
=cut
sub can_capture_buffer {
my $self = shift;
return 1 if $USE_IPC_RUN && $self->can_use_ipc_run;
return 1 if $USE_IPC_OPEN3 && $self->can_use_ipc_open3;
return;
}
=head2 $bool = IPC::Cmd->can_use_run_forked
Utility function that tells you if C<IPC::Cmd> is capable of
providing C<run_forked> on the current platform.
=head1 FUNCTIONS
=head2 $path = can_run( PROGRAM );
C<can_run> takes only one argument: the name of a binary you wish
to locate. C<can_run> works much like the unix binary C<which> or the bash
command C<type>, which scans through your path, looking for the requested
binary.
Unlike C<which> and C<type>, this function is platform independent and
will also work on, for example, Win32.
If called in a scalar context it will return the full path to the binary
you asked for if it was found, or C<undef> if it was not.
If called in a list context and the global variable C<$INSTANCES> is a true
value, it will return a list of the full paths to instances
of the binary where found in C<PATH>, or an empty list if it was not found.
=cut
sub can_run {
my $command = shift;
# a lot of VMS executables have a symbol defined
# check those first
if ( $^O eq 'VMS' ) {
require VMS::DCLsym;
my $syms = VMS::DCLsym->new;
return $command if scalar $syms->getsym( uc $command );
}
require Config;
require File::Spec;
require ExtUtils::MakeMaker;
my @possibles;
if( File::Spec->file_name_is_absolute($command) ) {
return MM->maybe_command($command);
} else {
for my $dir (
(split /\Q$Config::Config{path_sep}\E/, $ENV{PATH}),
File::Spec->curdir
) {
next if ! $dir || ! -d $dir;
my $abs = File::Spec->catfile( IS_WIN32 ? Win32::GetShortPathName( $dir ) : $dir, $command);
push @possibles, $abs if $abs = MM->maybe_command($abs);
}
}
return @possibles if wantarray and $INSTANCES;
return shift @possibles;
}
=head2 $ok | ($ok, $err, $full_buf, $stdout_buff, $stderr_buff) = run( command => COMMAND, [verbose => BOOL, buffer => \$SCALAR, timeout => DIGIT] );
C<run> takes 4 arguments:
=over 4
=item command
This is the command to execute. It may be either a string or an array
reference.
This is a required argument.
See L<"Caveats"> for remarks on how commands are parsed and their
limitations.
=item verbose
This controls whether all output of a command should also be printed
to STDOUT/STDERR or should only be trapped in buffers (NOTE: buffers
require L<IPC::Run> to be installed, or your system able to work with
L<IPC::Open3>).
It will default to the global setting of C<$IPC::Cmd::VERBOSE>,
which by default is 0.
=item buffer
This will hold all the output of a command. It needs to be a reference
to a scalar.
Note that this will hold both the STDOUT and STDERR messages, and you
have no way of telling which is which.
If you require this distinction, run the C<run> command in list context
and inspect the individual buffers.
Of course, this requires that the underlying call supports buffers. See
the note on buffers above.
=item timeout
Sets the maximum time the command is allowed to run before aborting,
using the built-in C<alarm()> call. If the timeout is triggered, the
C<errorcode> in the return value will be set to an object of the
C<IPC::Cmd::TimeOut> class. See the L<"error message"> section below for
details.
Defaults to C<0>, meaning no timeout is set.
=back
C<run> will return a simple C<true> or C<false> when called in scalar
context.
In list context, you will be returned a list of the following items:
=over 4
=item success
A simple boolean indicating if the command executed without errors or
not.
=item error message
If the first element of the return value (C<success>) was 0, then some
error occurred. This second element is the error message the command
you requested exited with, if available. This is generally a pretty
printed value of C<$?> or C<$@>. See C<perldoc perlvar> for details on
what they can contain.
If the error was a timeout, the C<error message> will be prefixed with
the string C<IPC::Cmd::TimeOut>, the timeout class.
=item full_buffer
This is an array reference containing all the output the command
generated.
Note that buffers are only available if you have L<IPC::Run> installed,
or if your system is able to work with L<IPC::Open3> -- see below).
Otherwise, this element will be C<undef>.
=item out_buffer
This is an array reference containing all the output sent to STDOUT the
command generated. The notes from L<"full_buffer"> apply.
=item error_buffer
This is an arrayreference containing all the output sent to STDERR the
command generated. The notes from L<"full_buffer"> apply.
=back
See the L<"HOW IT WORKS"> section below to see how C<IPC::Cmd> decides
what modules or function calls to use when issuing a command.
=cut
{ my @acc = qw[ok error _fds];
### autogenerate accessors ###
for my $key ( @acc ) {
no strict 'refs';
*{__PACKAGE__."::$key"} = sub {
$_[0]->{$key} = $_[1] if @_ > 1;
return $_[0]->{$key};
}
}
}
sub can_use_run_forked {
return $CAN_USE_RUN_FORKED eq "1";
}
# incompatible with POSIX::SigAction
#
sub install_layered_signal {
my ($s, $handler_code) = @_;
my %available_signals = map {$_ => 1} keys %SIG;
die("install_layered_signal got nonexistent signal name [$s]")
unless defined($available_signals{$s});
die("install_layered_signal expects coderef")
if !ref($handler_code) || ref($handler_code) ne 'CODE';
my $previous_handler = $SIG{$s};
my $sig_handler = sub {
my ($called_sig_name, @sig_param) = @_;
# $s is a closure referring to real signal name
# for which this handler is being installed.
# it is used to distinguish between
# real signal handlers and aliased signal handlers
my $signal_name = $s;
# $called_sig_name is a signal name which
# was passed to this signal handler;
# it doesn't equal $signal_name in case
# some signal handlers in %SIG point
# to other signal handler (CHLD and CLD,
# ABRT and IOT)
#
# initial signal handler for aliased signal
# calls some other signal handler which
# should not execute the same handler_code again
if ($called_sig_name eq $signal_name) {
$handler_code->($signal_name);
}
# run original signal handler if any (including aliased)
#
if (ref($previous_handler)) {
$previous_handler->($called_sig_name, @sig_param);
}
};
$SIG{$s} = $sig_handler;
}
# give process a chance sending TERM,
# waiting for a while (2 seconds)
# and killing it with KILL
sub kill_gently {
my ($pid, $opts) = @_;
$opts = {} unless $opts;
$opts->{'wait_time'} = 2 unless defined($opts->{'wait_time'});
$opts->{'first_kill_type'} = 'just_process' unless $opts->{'first_kill_type'};
$opts->{'final_kill_type'} = 'just_process' unless $opts->{'final_kill_type'};
if ($opts->{'first_kill_type'} eq 'just_process') {
kill(15, $pid);
}
elsif ($opts->{'first_kill_type'} eq 'process_group') {
kill(-15, $pid);
}
my $child_finished = 0;
my $wait_start_time = time();
while (!$child_finished && $wait_start_time + $opts->{'wait_time'} > time()) {
my $waitpid = waitpid($pid, WNOHANG);
if ($waitpid eq -1) {
$child_finished = 1;
}
Time::HiRes::usleep(250000); # quarter of a second
}
if (!$child_finished) {
if ($opts->{'final_kill_type'} eq 'just_process') {
kill(9, $pid);
}
elsif ($opts->{'final_kill_type'} eq 'process_group') {
kill(-9, $pid);
}
}
}
sub open3_run {
my ($cmd, $opts) = @_;
$opts = {} unless $opts;
my $child_in = FileHandle->new;
my $child_out = FileHandle->new;
my $child_err = FileHandle->new;
$child_out->autoflush(1);
$child_err->autoflush(1);
my $pid = open3($child_in, $child_out, $child_err, $cmd);
# push my child's pid to our parent
# so in case i am killed parent
# could stop my child (search for
# child_child_pid in parent code)
if ($opts->{'parent_info'}) {
my $ps = $opts->{'parent_info'};
print $ps "spawned $pid\n";
}
if ($child_in && $child_out->opened && $opts->{'child_stdin'}) {
# If the child process dies for any reason,
# the next write to CHLD_IN is likely to generate
# a SIGPIPE in the parent, which is fatal by default.
# So you may wish to handle this signal.
#
# from http://perldoc.perl.org/IPC/Open3.html,
# absolutely needed to catch piped commands errors.
#
local $SIG{'PIPE'} = sub { 1; };
print $child_in $opts->{'child_stdin'};
}
close($child_in);
my $child_output = {
'out' => $child_out->fileno,
'err' => $child_err->fileno,
$child_out->fileno => {
'parent_socket' => $opts->{'parent_stdout'},
'scalar_buffer' => "",
'child_handle' => $child_out,
'block_size' => ($child_out->stat)[11] || 1024,
},
$child_err->fileno => {
'parent_socket' => $opts->{'parent_stderr'},
'scalar_buffer' => "",
'child_handle' => $child_err,
'block_size' => ($child_err->stat)[11] || 1024,
},
};
my $select = IO::Select->new();
$select->add($child_out, $child_err);
# pass any signal to the child
# effectively creating process
# strongly attached to the child:
# it will terminate only after child
# has terminated (except for SIGKILL,
# which is specially handled)
foreach my $s (keys %SIG) {
my $sig_handler;
$sig_handler = sub {
kill("$s", $pid);
$SIG{$s} = $sig_handler;
};
$SIG{$s} = $sig_handler;
}
my $child_finished = 0;
my $got_sig_child = 0;
$SIG{'CHLD'} = sub { $got_sig_child = time(); };
while(!$child_finished && ($child_out->opened || $child_err->opened)) {
# parent was killed otherwise we would have got
# the same signal as parent and process it same way
if (getppid() eq "1") {
# end my process group with all the children
# (i am the process group leader, so my pid
# equals to the process group id)
#
# same thing which is done
# with $opts->{'clean_up_children'}
# in run_forked
#
kill(-9, $$);
exit 1;
}
if ($got_sig_child) {
if (time() - $got_sig_child > 1) {
# select->can_read doesn't return 0 after SIG_CHLD
#
# "On POSIX-compliant platforms, SIGCHLD is the signal
# sent to a process when a child process terminates."
# http://en.wikipedia.org/wiki/SIGCHLD
#
# nevertheless kill KILL wouldn't break anything here
#
kill (9, $pid);
$child_finished = 1;
}
}
Time::HiRes::usleep(1);
foreach my $fd ($select->can_read(1/100)) {
my $str = $child_output->{$fd->fileno};
psSnake::die("child stream not found: $fd") unless $str;
my $data;
my $count = $fd->sysread($data, $str->{'block_size'});
if ($count) {
if ($str->{'parent_socket'}) {
my $ph = $str->{'parent_socket'};
print $ph $data;
}
else {
$str->{'scalar_buffer'} .= $data;
}
}
elsif ($count eq 0) {
$select->remove($fd);
$fd->close();
}
else {
psSnake::die("error during sysread: " . $!);
}
}
}
my $waitpid_ret = waitpid($pid, 0);
my $real_exit = $?;
my $exit_value = $real_exit >> 8;
# since we've successfully reaped the child,
# let our parent know about this.
#
if ($opts->{'parent_info'}) {
my $ps = $opts->{'parent_info'};
# child was killed, inform parent
if ($real_exit & 127) {
print $ps "$pid killed with " . ($real_exit & 127) . "\n";
}
print $ps "reaped $pid\n";
}
if ($opts->{'parent_stdout'} || $opts->{'parent_stderr'}) {
return $exit_value;
}
else {
return {
'stdout' => $child_output->{$child_output->{'out'}}->{'scalar_buffer'},
'stderr' => $child_output->{$child_output->{'err'}}->{'scalar_buffer'},
'exit_code' => $exit_value,
};
}
}
=head2 $hashref = run_forked( COMMAND, { child_stdin => SCALAR, timeout => DIGIT, stdout_handler => CODEREF, stderr_handler => CODEREF} );
C<run_forked> is used to execute some program or a coderef,
optionally feed it with some input, get its return code
and output (both stdout and stderr into separate buffers).
In addition, it allows to terminate the program
if it takes too long to finish.
The important and distinguishing feature of run_forked
is execution timeout which at first seems to be
quite a simple task but if you think
that the program which you're spawning
might spawn some children itself (which
in their turn could do the same and so on)
it turns out to be not a simple issue.
C<run_forked> is designed to survive and
successfully terminate almost any long running task,
even a fork bomb in case your system has the resources
to survive during given timeout.
This is achieved by creating separate watchdog process
which spawns the specified program in a separate
process session and supervises it: optionally
feeds it with input, stores its exit code,
stdout and stderr, terminates it in case
it runs longer than specified.
Invocation requires the command to be executed or a coderef and optionally a hashref of options:
=over
=item C<timeout>
Specify in seconds how long to run the command before it is killed with with SIG_KILL (9),
which effectively terminates it and all of its children (direct or indirect).
=item C<child_stdin>
Specify some text that will be passed into the C<STDIN> of the executed program.
=item C<stdout_handler>
Coderef of a subroutine to call when a portion of data is received on
STDOUT from the executing program.
=item C<stderr_handler>
Coderef of a subroutine to call when a portion of data is received on
STDERR from the executing program.
=item C<discard_output>
Discards the buffering of the standard output and standard errors for return by run_forked().
With this option you have to use the std*_handlers to read what the command outputs.
Useful for commands that send a lot of output.
=item C<terminate_on_parent_sudden_death>
Enable this option if you wish all spawned processes to be killed if the initially spawned
process (the parent) is killed or dies without waiting for child processes.
=back
C<run_forked> will return a HASHREF with the following keys:
=over
=item C<exit_code>
The exit code of the executed program.
=item C<timeout>
The number of seconds the program ran for before being terminated, or 0 if no timeout occurred.
=item C<stdout>
Holds the standard output of the executed command (or empty string if
there was no STDOUT output or if C<discard_output> was used; it's always defined!)
=item C<stderr>
Holds the standard error of the executed command (or empty string if
there was no STDERR output or if C<discard_output> was used; it's always defined!)
=item C<merged>
Holds the standard output and error of the executed command merged into one stream
(or empty string if there was no output at all or if C<discard_output> was used; it's always defined!)
=item C<err_msg>
Holds some explanation in the case of an error.
=back
=cut
sub run_forked {
### container to store things in
my $self = bless {}, __PACKAGE__;
if (!can_use_run_forked()) {
Carp::carp("run_forked is not available: $CAN_USE_RUN_FORKED");
return;
}
my ($cmd, $opts) = @_;
if (!$cmd) {
Carp::carp("run_forked expects command to run");
return;
}
$opts = {} unless $opts;
$opts->{'timeout'} = 0 unless $opts->{'timeout'};
$opts->{'terminate_wait_time'} = 2 unless defined($opts->{'terminate_wait_time'});
# turned on by default
$opts->{'clean_up_children'} = 1 unless defined($opts->{'clean_up_children'});
# sockets to pass child stdout to parent
my $child_stdout_socket;
my $parent_stdout_socket;
# sockets to pass child stderr to parent
my $child_stderr_socket;
my $parent_stderr_socket;
# sockets for child -> parent internal communication
my $child_info_socket;
my $parent_info_socket;
socketpair($child_stdout_socket, $parent_stdout_socket, AF_UNIX, SOCK_STREAM, PF_UNSPEC) ||
die ("socketpair: $!");
socketpair($child_stderr_socket, $parent_stderr_socket, AF_UNIX, SOCK_STREAM, PF_UNSPEC) ||
die ("socketpair: $!");
socketpair($child_info_socket, $parent_info_socket, AF_UNIX, SOCK_STREAM, PF_UNSPEC) ||
die ("socketpair: $!");
$child_stdout_socket->autoflush(1);
$parent_stdout_socket->autoflush(1);
$child_stderr_socket->autoflush(1);
$parent_stderr_socket->autoflush(1);
$child_info_socket->autoflush(1);
$parent_info_socket->autoflush(1);
my $start_time = time();
my $pid;
if ($pid = fork) {
# we are a parent
close($parent_stdout_socket);
close($parent_stderr_socket);
close($parent_info_socket);
my $flags;
# prepare sockets to read from child
$flags = 0;
fcntl($child_stdout_socket, F_GETFL, $flags) || die "can't fnctl F_GETFL: $!";
$flags |= O_NONBLOCK;
fcntl($child_stdout_socket, F_SETFL, $flags) || die "can't fnctl F_SETFL: $!";
$flags = 0;
fcntl($child_stderr_socket, F_GETFL, $flags) || die "can't fnctl F_GETFL: $!";
$flags |= O_NONBLOCK;
fcntl($child_stderr_socket, F_SETFL, $flags) || die "can't fnctl F_SETFL: $!";
$flags = 0;
fcntl($child_info_socket, F_GETFL, $flags) || die "can't fnctl F_GETFL: $!";
$flags |= O_NONBLOCK;
fcntl($child_info_socket, F_SETFL, $flags) || die "can't fnctl F_SETFL: $!";
# print "child $pid started\n";
my $child_timedout = 0;
my $child_finished = 0;
my $child_stdout = '';
my $child_stderr = '';
my $child_merged = '';
my $child_exit_code = 0;
my $child_killed_by_signal = 0;
my $parent_died = 0;
my $got_sig_child = 0;
my $got_sig_quit = 0;
my $orig_sig_child = $SIG{'CHLD'};
$SIG{'CHLD'} = sub { $got_sig_child = time(); };
if ($opts->{'terminate_on_signal'}) {
install_layered_signal($opts->{'terminate_on_signal'}, sub { $got_sig_quit = time(); });
}
my $child_child_pid;
while (!$child_finished) {
my $now = time();
if ($opts->{'terminate_on_parent_sudden_death'}) {
$opts->{'runtime'}->{'last_parent_check'} = 0
unless defined($opts->{'runtime'}->{'last_parent_check'});
# check for parent once each five seconds
if ($now - $opts->{'runtime'}->{'last_parent_check'} > 5) {
if (getppid() eq "1") {
kill_gently ($pid, {
'first_kill_type' => 'process_group',
'final_kill_type' => 'process_group',
'wait_time' => $opts->{'terminate_wait_time'}
});
$parent_died = 1;
}
$opts->{'runtime'}->{'last_parent_check'} = $now;
}
}
# user specified timeout
if ($opts->{'timeout'}) {
if ($now - $start_time > $opts->{'timeout'}) {
kill_gently ($pid, {
'first_kill_type' => 'process_group',
'final_kill_type' => 'process_group',
'wait_time' => $opts->{'terminate_wait_time'}
});
$child_timedout = 1;
}
}
# give OS 10 seconds for correct return of waitpid,
# kill process after that and finish wait loop;
# shouldn't ever happen -- remove this code?
if ($got_sig_child) {
if ($now - $got_sig_child > 10) {
print STDERR "waitpid did not return -1 for 10 seconds after SIG_CHLD, killing [$pid]\n";
kill (-9, $pid);
$child_finished = 1;
}
}
if ($got_sig_quit) {
kill_gently ($pid, {
'first_kill_type' => 'process_group',
'final_kill_type' => 'process_group',
'wait_time' => $opts->{'terminate_wait_time'}
});
$child_finished = 1;
}
my $waitpid = waitpid($pid, WNOHANG);
# child finished, catch it's exit status
if ($waitpid ne 0 && $waitpid ne -1) {
$child_exit_code = $? >> 8;
}
if ($waitpid eq -1) {
$child_finished = 1;
next;
}
# child -> parent simple internal communication protocol
while (my $l = <$child_info_socket>) {
if ($l =~ /^spawned ([0-9]+?)\n(.*?)/so) {
$child_child_pid = $1;
$l = $2;
}
if ($l =~ /^reaped ([0-9]+?)\n(.*?)/so) {
$child_child_pid = undef;
$l = $2;
}
if ($l =~ /^[\d]+ killed with ([0-9]+?)\n(.*?)/so) {
$child_killed_by_signal = $1;
$l = $2;
}
}
while (my $l = <$child_stdout_socket>) {
if (!$opts->{'discard_output'}) {
$child_stdout .= $l;
$child_merged .= $l;
}
if ($opts->{'stdout_handler'} && ref($opts->{'stdout_handler'}) eq 'CODE') {
$opts->{'stdout_handler'}->($l);
}
}
while (my $l = <$child_stderr_socket>) {
if (!$opts->{'discard_output'}) {
$child_stderr .= $l;
$child_merged .= $l;
}
if ($opts->{'stderr_handler'} && ref($opts->{'stderr_handler'}) eq 'CODE') {
$opts->{'stderr_handler'}->($l);
}
}
Time::HiRes::usleep(1);
}
# $child_pid_pid is not defined in two cases:
# * when our child was killed before
# it had chance to tell us the pid
# of the child it spawned. we can do
# nothing in this case :(
# * our child successfully reaped its child,
# we have nothing left to do in this case
#
# defined $child_pid_pid means child's child
# has not died but nobody is waiting for it,
# killing it brutally.
#
if ($child_child_pid) {
kill_gently($child_child_pid);
}
# in case there are forks in child which
# do not forward or process signals (TERM) correctly
# kill whole child process group, effectively trying
# not to return with some children or their parts still running
#
# to be more accurate -- we need to be sure
# that this is process group created by our child
# (and not some other process group with the same pgid,
# created just after death of our child) -- fortunately
# this might happen only when process group ids
# are reused quickly (there are lots of processes
# spawning new process groups for example)
#
if ($opts->{'clean_up_children'}) {
kill(-9, $pid);
}
# print "child $pid finished\n";
close($child_stdout_socket);
close($child_stderr_socket);
close($child_info_socket);
my $o = {
'stdout' => $child_stdout,
'stderr' => $child_stderr,
'merged' => $child_merged,
'timeout' => $child_timedout ? $opts->{'timeout'} : 0,
'exit_code' => $child_exit_code,
'parent_died' => $parent_died,
'killed_by_signal' => $child_killed_by_signal,
'child_pgid' => $pid,
};
my $err_msg = '';
if ($o->{'exit_code'}) {
$err_msg .= "exited with code [$o->{'exit_code'}]\n";
}
if ($o->{'timeout'}) {
$err_msg .= "ran more than [$o->{'timeout'}] seconds\n";
}
if ($o->{'parent_died'}) {
$err_msg .= "parent died\n";
}
if ($o->{'stdout'}) {
$err_msg .= "stdout:\n" . $o->{'stdout'} . "\n";
}
if ($o->{'stderr'}) {
$err_msg .= "stderr:\n" . $o->{'stderr'} . "\n";
}
if ($o->{'killed_by_signal'}) {
$err_msg .= "killed by signal [" . $o->{'killed_by_signal'} . "]\n";
}
$o->{'err_msg'} = $err_msg;
if ($orig_sig_child) {
$SIG{'CHLD'} = $orig_sig_child;
}
else {
delete($SIG{'CHLD'});
}
return $o;
}
else {
die("cannot fork: $!") unless defined($pid);
# create new process session for open3 call,
# so we hopefully can kill all the subprocesses
# which might be spawned in it (except for those
# which do setsid theirselves -- can't do anything
# with those)
POSIX::setsid() || die("Error running setsid: " . $!);
if ($opts->{'child_BEGIN'} && ref($opts->{'child_BEGIN'}) eq 'CODE') {
$opts->{'child_BEGIN'}->();
}
close($child_stdout_socket);
close($child_stderr_socket);
close($child_info_socket);
my $child_exit_code;
# allow both external programs
# and internal perl calls
if (!ref($cmd)) {
$child_exit_code = open3_run($cmd, {
'parent_info' => $parent_info_socket,
'parent_stdout' => $parent_stdout_socket,
'parent_stderr' => $parent_stderr_socket,
'child_stdin' => $opts->{'child_stdin'},
});
}
elsif (ref($cmd) eq 'CODE') {
$child_exit_code = $cmd->({
'opts' => $opts,
'parent_info' => $parent_info_socket,
'parent_stdout' => $parent_stdout_socket,
'parent_stderr' => $parent_stderr_socket,
'child_stdin' => $opts->{'child_stdin'},
});
}
else {
print $parent_stderr_socket "Invalid command reference: " . ref($cmd) . "\n";
$child_exit_code = 1;
}
close($parent_stdout_socket);
close($parent_stderr_socket);
close($parent_info_socket);
if ($opts->{'child_END'} && ref($opts->{'child_END'}) eq 'CODE') {
$opts->{'child_END'}->();
}
exit $child_exit_code;
}
}
sub run {
### container to store things in
my $self = bless {}, __PACKAGE__;
my %hash = @_;
### if the user didn't provide a buffer, we'll store it here.
my $def_buf = '';
my($verbose,$cmd,$buffer,$timeout);
my $tmpl = {
verbose => { default => $VERBOSE, store => \$verbose },
buffer => { default => \$def_buf, store => \$buffer },
command => { required => 1, store => \$cmd,
allow => sub { !ref($_[0]) or ref($_[0]) eq 'ARRAY' },
},
timeout => { default => 0, store => \$timeout },
};
unless( check( $tmpl, \%hash, $VERBOSE ) ) {
Carp::carp( loc( "Could not validate input: %1",
Params::Check->last_error ) );
return;
};
$cmd = _quote_args_vms( $cmd ) if IS_VMS;
### strip any empty elements from $cmd if present
$cmd = [ grep { defined && length } @$cmd ] if ref $cmd;
my $pp_cmd = (ref $cmd ? "@$cmd" : $cmd);
print loc("Running [%1]...\n", $pp_cmd ) if $verbose;
### did the user pass us a buffer to fill or not? if so, set this
### flag so we know what is expected of us
### XXX this is now being ignored. in the future, we could add diagnostic
### messages based on this logic
#my $user_provided_buffer = $buffer == \$def_buf ? 0 : 1;
### buffers that are to be captured
my( @buffer, @buff_err, @buff_out );
### capture STDOUT
my $_out_handler = sub {
my $buf = shift;
return unless defined $buf;
print STDOUT $buf if $verbose;
push @buffer, $buf;
push @buff_out, $buf;
};
### capture STDERR
my $_err_handler = sub {
my $buf = shift;
return unless defined $buf;
print STDERR $buf if $verbose;
push @buffer, $buf;
push @buff_err, $buf;
};
### flag to indicate we have a buffer captured
my $have_buffer = $self->can_capture_buffer ? 1 : 0;
### flag indicating if the subcall went ok
my $ok;
### dont look at previous errors:
local $?;
local $@;
local $!;
### we might be having a timeout set
eval {
local $SIG{ALRM} = sub { die bless sub {
ALARM_CLASS .
qq[: Command '$pp_cmd' aborted by alarm after $timeout seconds]
}, ALARM_CLASS } if $timeout;
alarm $timeout || 0;
### IPC::Run is first choice if $USE_IPC_RUN is set.
if( !IS_WIN32 and $USE_IPC_RUN and $self->can_use_ipc_run( 1 ) ) {
### ipc::run handlers needs the command as a string or an array ref
$self->_debug( "# Using IPC::Run. Have buffer: $have_buffer" )
if $DEBUG;
$ok = $self->_ipc_run( $cmd, $_out_handler, $_err_handler );
### since IPC::Open3 works on all platforms, and just fails on
### win32 for capturing buffers, do that ideally
} elsif ( $USE_IPC_OPEN3 and $self->can_use_ipc_open3( 1 ) ) {
$self->_debug("# Using IPC::Open3. Have buffer: $have_buffer")
if $DEBUG;
### in case there are pipes in there;
### IPC::Open3 will call exec and exec will do the right thing
my $method = IS_WIN32 ? '_open3_run_win32' : '_open3_run';
$ok = $self->$method(
$cmd, $_out_handler, $_err_handler, $verbose
);
### if we are allowed to run verbose, just dispatch the system command
} else {
$self->_debug( "# Using system(). Have buffer: $have_buffer" )
if $DEBUG;
$ok = $self->_system_run( $cmd, $verbose );
}
alarm 0;
};
### restore STDIN after duping, or STDIN will be closed for
### this current perl process!
$self->__reopen_fds( @{ $self->_fds} ) if $self->_fds;
my $err;
unless( $ok ) {
### alarm happened
if ( $@ and ref $@ and $@->isa( ALARM_CLASS ) ) {
$err = $@->(); # the error code is an expired alarm
### another error happened, set by the dispatchub
} else {
$err = $self->error;
}
}
### fill the buffer;
$$buffer = join '', @buffer if @buffer;
### return a list of flags and buffers (if available) in list
### context, or just a simple 'ok' in scalar
return wantarray
? $have_buffer
? ($ok, $err, \@buffer, \@buff_out, \@buff_err)
: ($ok, $err )
: $ok
}
sub _open3_run_win32 {
my $self = shift;
my $cmd = shift;
my $outhand = shift;
my $errhand = shift;
my $pipe = sub {
socketpair($_[0], $_[1], AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or return undef;
shutdown($_[0], 1); # No more writing for reader
shutdown($_[1], 0); # No more reading for writer
return 1;
};
my $open3 = sub {
local (*TO_CHLD_R, *TO_CHLD_W);
local (*FR_CHLD_R, *FR_CHLD_W);
local (*FR_CHLD_ERR_R, *FR_CHLD_ERR_W);
$pipe->(*TO_CHLD_R, *TO_CHLD_W ) or die $^E;
$pipe->(*FR_CHLD_R, *FR_CHLD_W ) or die $^E;
$pipe->(*FR_CHLD_ERR_R, *FR_CHLD_ERR_W) or die $^E;
my $pid = IPC::Open3::open3('>&TO_CHLD_R', '<&FR_CHLD_W', '<&FR_CHLD_ERR_W', @_);
return ( $pid, *TO_CHLD_W, *FR_CHLD_R, *FR_CHLD_ERR_R );
};
$cmd = [ grep { defined && length } @$cmd ] if ref $cmd;
$cmd = $self->__fix_cmd_whitespace_and_special_chars( $cmd );
my ($pid, $to_chld, $fr_chld, $fr_chld_err) =
$open3->( ( ref $cmd ? @$cmd : $cmd ) );
my $in_sel = IO::Select->new();
my $out_sel = IO::Select->new();
my %objs;
$objs{ fileno( $fr_chld ) } = $outhand;
$objs{ fileno( $fr_chld_err ) } = $errhand;
$in_sel->add( $fr_chld );
$in_sel->add( $fr_chld_err );
close($to_chld);
while ($in_sel->count() + $out_sel->count()) {
my ($ins, $outs) = IO::Select::select($in_sel, $out_sel, undef);
for my $fh (@$ins) {
my $obj = $objs{ fileno($fh) };
my $buf;
my $bytes_read = sysread($fh, $buf, 64*1024 ); #, length($buf));
if (!$bytes_read) {
$in_sel->remove($fh);
}
else {
$obj->( "$buf" );
}
}
for my $fh (@$outs) {
}
}
waitpid($pid, 0);
### some error occurred
if( $? ) {
$self->error( $self->_pp_child_error( $cmd, $? ) );
$self->ok( 0 );
return;
} else {
return $self->ok( 1 );
}
}
sub _open3_run {
my $self = shift;
my $cmd = shift;
my $_out_handler = shift;
my $_err_handler = shift;
my $verbose = shift || 0;
### Following code are adapted from Friar 'abstracts' in the
### Perl Monastery (http://www.perlmonks.org/index.pl?node_id=151886).
### XXX that code didn't work.
### we now use the following code, thanks to theorbtwo
### define them beforehand, so we always have defined FH's
### to read from.
use Symbol;
my $kidout = Symbol::gensym();
my $kiderror = Symbol::gensym();
### Dup the filehandle so we can pass 'our' STDIN to the
### child process. This stops us from having to pump input
### from ourselves to the childprocess. However, we will need
### to revive the FH afterwards, as IPC::Open3 closes it.
### We'll do the same for STDOUT and STDERR. It works without
### duping them on non-unix derivatives, but not on win32.
my @fds_to_dup = ( IS_WIN32 && !$verbose
? qw[STDIN STDOUT STDERR]
: qw[STDIN]
);
$self->_fds( \@fds_to_dup );
$self->__dup_fds( @fds_to_dup );
### pipes have to come in a quoted string, and that clashes with
### whitespace. This sub fixes up such commands so they run properly
$cmd = $self->__fix_cmd_whitespace_and_special_chars( $cmd );
### dont stringify @$cmd, so spaces in filenames/paths are
### treated properly
my $pid = eval {
IPC::Open3::open3(
'<&STDIN',
(IS_WIN32 ? '>&STDOUT' : $kidout),
(IS_WIN32 ? '>&STDERR' : $kiderror),
( ref $cmd ? @$cmd : $cmd ),
);
};
### open3 error occurred
if( $@ and $@ =~ /^open3:/ ) {
$self->ok( 0 );
$self->error( $@ );
return;
};
### use OUR stdin, not $kidin. Somehow,
### we never get the input.. so jump through
### some hoops to do it :(
my $selector = IO::Select->new(
(IS_WIN32 ? \*STDERR : $kiderror),
\*STDIN,
(IS_WIN32 ? \*STDOUT : $kidout)
);
STDOUT->autoflush(1); STDERR->autoflush(1); STDIN->autoflush(1);
$kidout->autoflush(1) if UNIVERSAL::can($kidout, 'autoflush');
$kiderror->autoflush(1) if UNIVERSAL::can($kiderror, 'autoflush');
### add an explicit break statement
### code courtesy of theorbtwo from #london.pm
my $stdout_done = 0;
my $stderr_done = 0;
OUTER: while ( my @ready = $selector->can_read ) {
for my $h ( @ready ) {
my $buf;
### $len is the amount of bytes read
my $len = sysread( $h, $buf, 4096 ); # try to read 4096 bytes
### see perldoc -f sysread: it returns undef on error,
### so bail out.
if( not defined $len ) {
warn(loc("Error reading from process: %1", $!));
last OUTER;
}
### check for $len. it may be 0, at which point we're
### done reading, so don't try to process it.
### if we would print anyway, we'd provide bogus information
$_out_handler->( "$buf" ) if $len && $h == $kidout;
$_err_handler->( "$buf" ) if $len && $h == $kiderror;
### Wait till child process is done printing to both
### stdout and stderr.
$stdout_done = 1 if $h == $kidout and $len == 0;
$stderr_done = 1 if $h == $kiderror and $len == 0;
last OUTER if ($stdout_done && $stderr_done);
}
}
waitpid $pid, 0; # wait for it to die
### restore STDIN after duping, or STDIN will be closed for
### this current perl process!
### done in the parent call now
# $self->__reopen_fds( @fds_to_dup );
### some error occurred
if( $? ) {
$self->error( $self->_pp_child_error( $cmd, $? ) );
$self->ok( 0 );
return;
} else {
return $self->ok( 1 );
}
}
### Text::ParseWords::shellwords() uses unix semantics. that will break
### on win32
{ my $parse_sub = IS_WIN32
? __PACKAGE__->can('_split_like_shell_win32')
: Text::ParseWords->can('shellwords');
sub _ipc_run {
my $self = shift;
my $cmd = shift;
my $_out_handler = shift;
my $_err_handler = shift;
STDOUT->autoflush(1); STDERR->autoflush(1);
### a command like:
# [
# '/usr/bin/gzip',
# '-cdf',
# '/Users/kane/sources/p4/other/archive-extract/t/src/x.tgz',
# '|',
# '/usr/bin/tar',
# '-tf -'
# ]
### needs to become:
# [
# ['/usr/bin/gzip', '-cdf',
# '/Users/kane/sources/p4/other/archive-extract/t/src/x.tgz']
# '|',
# ['/usr/bin/tar', '-tf -']
# ]
my @command;
my $special_chars;
my $re = do { my $x = join '', SPECIAL_CHARS; qr/([$x])/ };
if( ref $cmd ) {
my $aref = [];
for my $item (@$cmd) {
if( $item =~ $re ) {
push @command, $aref, $item;
$aref = [];
$special_chars .= $1;
} else {
push @$aref, $item;
}
}
push @command, $aref;
} else {
@command = map { if( $_ =~ $re ) {
$special_chars .= $1; $_;
} else {
# [ split /\s+/ ]
[ map { m/[ ]/ ? qq{'$_'} : $_ } $parse_sub->($_) ]
}
} split( /\s*$re\s*/, $cmd );
}
### if there's a pipe in the command, *STDIN needs to
### be inserted *BEFORE* the pipe, to work on win32
### this also works on *nix, so we should do it when possible
### this should *also* work on multiple pipes in the command
### if there's no pipe in the command, append STDIN to the back
### of the command instead.
### XXX seems IPC::Run works it out for itself if you just
### dont pass STDIN at all.
# if( $special_chars and $special_chars =~ /\|/ ) {
# ### only add STDIN the first time..
# my $i;
# @command = map { ($_ eq '|' && not $i++)
# ? ( \*STDIN, $_ )
# : $_
# } @command;
# } else {
# push @command, \*STDIN;
# }
# \*STDIN is already included in the @command, see a few lines up
my $ok = eval { IPC::Run::run( @command,
fileno(STDOUT).'>',
$_out_handler,
fileno(STDERR).'>',
$_err_handler
)
};
### all is well
if( $ok ) {
return $self->ok( $ok );
### some error occurred
} else {
$self->ok( 0 );
### if the eval fails due to an exception, deal with it
### unless it's an alarm
if( $@ and not UNIVERSAL::isa( $@, ALARM_CLASS ) ) {
$self->error( $@ );
### if it *is* an alarm, propagate
} elsif( $@ ) {
die $@;
### some error in the sub command
} else {
$self->error( $self->_pp_child_error( $cmd, $? ) );
}
return;
}
}
}
sub _system_run {
my $self = shift;
my $cmd = shift;
my $verbose = shift || 0;
### pipes have to come in a quoted string, and that clashes with
### whitespace. This sub fixes up such commands so they run properly
$cmd = $self->__fix_cmd_whitespace_and_special_chars( $cmd );
my @fds_to_dup = $verbose ? () : qw[STDOUT STDERR];
$self->_fds( \@fds_to_dup );
$self->__dup_fds( @fds_to_dup );
### system returns 'true' on failure -- the exit code of the cmd
$self->ok( 1 );
system( ref $cmd ? @$cmd : $cmd ) == 0 or do {
$self->error( $self->_pp_child_error( $cmd, $? ) );
$self->ok( 0 );
};
### done in the parent call now
#$self->__reopen_fds( @fds_to_dup );
return unless $self->ok;
return $self->ok;
}
{ my %sc_lookup = map { $_ => $_ } SPECIAL_CHARS;
sub __fix_cmd_whitespace_and_special_chars {
my $self = shift;
my $cmd = shift;
### command has a special char in it
if( ref $cmd and grep { $sc_lookup{$_} } @$cmd ) {
### since we have special chars, we have to quote white space
### this *may* conflict with the parsing :(
my $fixed;
my @cmd = map { / / ? do { $fixed++; QUOTE.$_.QUOTE } : $_ } @$cmd;
$self->_debug( "# Quoted $fixed arguments containing whitespace" )
if $DEBUG && $fixed;
### stringify it, so the special char isn't escaped as argument
### to the program
$cmd = join ' ', @cmd;
}
return $cmd;
}
}
### Command-line arguments (but not the command itself) must be quoted
### to ensure case preservation. Borrowed from Module::Build with adaptations.
### Patch for this supplied by Craig Berry, see RT #46288: [PATCH] Add argument
### quoting for run() on VMS
sub _quote_args_vms {
### Returns a command string with proper quoting so that the subprocess
### sees this same list of args, or if we get a single arg that is an
### array reference, quote the elements of it (except for the first)
### and return the reference.
my @args = @_;
my $got_arrayref = (scalar(@args) == 1
&& UNIVERSAL::isa($args[0], 'ARRAY'))
? 1
: 0;
@args = split(/\s+/, $args[0]) unless $got_arrayref || scalar(@args) > 1;
my $cmd = $got_arrayref ? shift @{$args[0]} : shift @args;
### Do not quote qualifiers that begin with '/' or previously quoted args.
map { if (/^[^\/\"]/) {
$_ =~ s/\"/""/g; # escape C<"> by doubling
$_ = q(").$_.q(");
}
}
($got_arrayref ? @{$args[0]}
: @args
);
$got_arrayref ? unshift(@{$args[0]}, $cmd) : unshift(@args, $cmd);
return $got_arrayref ? $args[0]
: join(' ', @args);
}
### XXX this is cribbed STRAIGHT from M::B 0.30 here:
### http://search.cpan.org/src/KWILLIAMS/Module-Build-0.30/lib/Module/Build/Platform/Windows.pm:split_like_shell
### XXX this *should* be integrated into text::parsewords
sub _split_like_shell_win32 {
# As it turns out, Windows command-parsing is very different from
# Unix command-parsing. Double-quotes mean different things,
# backslashes don't necessarily mean escapes, and so on. So we
# can't use Text::ParseWords::shellwords() to break a command string
# into words. The algorithm below was bashed out by Randy and Ken
# (mostly Randy), and there are a lot of regression tests, so we
# should feel free to adjust if desired.
local $_ = shift;
my @argv;
return @argv unless defined() && length();
my $arg = '';
my( $i, $quote_mode ) = ( 0, 0 );
while ( $i < length() ) {
my $ch = substr( $_, $i , 1 );
my $next_ch = substr( $_, $i+1, 1 );
if ( $ch eq '\\' && $next_ch eq '"' ) {
$arg .= '"';
$i++;
} elsif ( $ch eq '\\' && $next_ch eq '\\' ) {
$arg .= '\\';
$i++;
} elsif ( $ch eq '"' && $next_ch eq '"' && $quote_mode ) {
$quote_mode = !$quote_mode;
$arg .= '"';
$i++;
} elsif ( $ch eq '"' && $next_ch eq '"' && !$quote_mode &&
( $i + 2 == length() ||
substr( $_, $i + 2, 1 ) eq ' ' )
) { # for cases like: a"" => [ 'a' ]
push( @argv, $arg );
$arg = '';
$i += 2;
} elsif ( $ch eq '"' ) {
$quote_mode = !$quote_mode;
} elsif ( $ch eq ' ' && !$quote_mode ) {
push( @argv, $arg ) if defined( $arg ) && length( $arg );
$arg = '';
++$i while substr( $_, $i + 1, 1 ) eq ' ';
} else {
$arg .= $ch;
}
$i++;
}
push( @argv, $arg ) if defined( $arg ) && length( $arg );
return @argv;
}
{ use File::Spec;
use Symbol;
my %Map = (
STDOUT => [qw|>&|, \*STDOUT, Symbol::gensym() ],
STDERR => [qw|>&|, \*STDERR, Symbol::gensym() ],
STDIN => [qw|<&|, \*STDIN, Symbol::gensym() ],
);
### dups FDs and stores them in a cache
sub __dup_fds {
my $self = shift;
my @fds = @_;
__PACKAGE__->_debug( "# Closing the following fds: @fds" ) if $DEBUG;
for my $name ( @fds ) {
my($redir, $fh, $glob) = @{$Map{$name}} or (
Carp::carp(loc("No such FD: '%1'", $name)), next );
### MUST use the 2-arg version of open for dup'ing for
### 5.6.x compatibility. 5.8.x can use 3-arg open
### see perldoc5.6.2 -f open for details
open $glob, $redir . fileno($fh) or (
Carp::carp(loc("Could not dup '$name': %1", $!)),
return
);
### we should re-open this filehandle right now, not
### just dup it
### Use 2-arg version of open, as 5.5.x doesn't support
### 3-arg version =/
if( $redir eq '>&' ) {
open( $fh, '>' . File::Spec->devnull ) or (
Carp::carp(loc("Could not reopen '$name': %1", $!)),
return
);
}
}
return 1;
}
### reopens FDs from the cache
sub __reopen_fds {
my $self = shift;
my @fds = @_;
__PACKAGE__->_debug( "# Reopening the following fds: @fds" ) if $DEBUG;
for my $name ( @fds ) {
my($redir, $fh, $glob) = @{$Map{$name}} or (
Carp::carp(loc("No such FD: '%1'", $name)), next );
### MUST use the 2-arg version of open for dup'ing for
### 5.6.x compatibility. 5.8.x can use 3-arg open
### see perldoc5.6.2 -f open for details
open( $fh, $redir . fileno($glob) ) or (
Carp::carp(loc("Could not restore '$name': %1", $!)),
return
);
### close this FD, we're not using it anymore
close $glob;
}
return 1;
}
}
sub _debug {
my $self = shift;
my $msg = shift or return;
my $level = shift || 0;
local $Carp::CarpLevel += $level;
Carp::carp($msg);
return 1;
}
sub _pp_child_error {
my $self = shift;
my $cmd = shift or return;
my $ce = shift or return;
my $pp_cmd = ref $cmd ? "@$cmd" : $cmd;
my $str;
if( $ce == -1 ) {
### Include $! in the error message, so that the user can
### see 'No such file or directory' versus 'Permission denied'
### versus 'Cannot fork' or whatever the cause was.
$str = "Failed to execute '$pp_cmd': $!";
} elsif ( $ce & 127 ) {
### some signal
$str = loc( "'%1' died with signal %d, %s coredump\n",
$pp_cmd, ($ce & 127), ($ce & 128) ? 'with' : 'without');
} else {
### Otherwise, the command run but gave error status.
$str = "'$pp_cmd' exited with value " . ($ce >> 8);
}
$self->_debug( "# Child error '$ce' translated to: $str" ) if $DEBUG;
return $str;
}
1;
=head2 $q = QUOTE
Returns the character used for quoting strings on this platform. This is
usually a C<'> (single quote) on most systems, but some systems use different
quotes. For example, C<Win32> uses C<"> (double quote).
You can use it as follows:
use IPC::Cmd qw[run QUOTE];
my $cmd = q[echo ] . QUOTE . q[foo bar] . QUOTE;
This makes sure that C<foo bar> is treated as a string, rather than two
separate arguments to the C<echo> function.
__END__
=head1 HOW IT WORKS
C<run> will try to execute your command using the following logic:
=over 4
=item *
If you have C<IPC::Run> installed, and the variable C<$IPC::Cmd::USE_IPC_RUN>
is set to true (See the L<"Global Variables"> section) use that to execute
the command. You will have the full output available in buffers, interactive commands
are sure to work and you are guaranteed to have your verbosity
settings honored cleanly.
=item *
Otherwise, if the variable C<$IPC::Cmd::USE_IPC_OPEN3> is set to true
(See the L<"Global Variables"> section), try to execute the command using
L<IPC::Open3>. Buffers will be available on all platforms,
interactive commands will still execute cleanly, and also your verbosity
settings will be adhered to nicely;
=item *
Otherwise, if you have the C<verbose> argument set to true, we fall back
to a simple C<system()> call. We cannot capture any buffers, but
interactive commands will still work.
=item *
Otherwise we will try and temporarily redirect STDERR and STDOUT, do a
C<system()> call with your command and then re-open STDERR and STDOUT.
This is the method of last resort and will still allow you to execute
your commands cleanly. However, no buffers will be available.
=back
=head1 Global Variables
The behaviour of IPC::Cmd can be altered by changing the following
global variables:
=head2 $IPC::Cmd::VERBOSE
This controls whether IPC::Cmd will print any output from the
commands to the screen or not. The default is 0.
=head2 $IPC::Cmd::USE_IPC_RUN
This variable controls whether IPC::Cmd will try to use L<IPC::Run>
when available and suitable.
=head2 $IPC::Cmd::USE_IPC_OPEN3
This variable controls whether IPC::Cmd will try to use L<IPC::Open3>
when available and suitable. Defaults to true.
=head2 $IPC::Cmd::WARN
This variable controls whether run-time warnings should be issued, like
the failure to load an C<IPC::*> module you explicitly requested.
Defaults to true. Turn this off at your own risk.
=head2 $IPC::Cmd::INSTANCES
This variable controls whether C<can_run> will return all instances of
the binary it finds in the C<PATH> when called in a list context.
Defaults to false, set to true to enable the described behaviour.
=head1 Caveats
=over 4
=item Whitespace and IPC::Open3 / system()
When using C<IPC::Open3> or C<system>, if you provide a string as the
C<command> argument, it is assumed to be appropriately escaped. You can
use the C<QUOTE> constant to use as a portable quote character (see above).
However, if you provide an array reference, special rules apply:
If your command contains B<special characters> (< > | &), it will
be internally stringified before executing the command, to avoid that these
special characters are escaped and passed as arguments instead of retaining
their special meaning.
However, if the command contained arguments that contained whitespace,
stringifying the command would loose the significance of the whitespace.
Therefore, C<IPC::Cmd> will quote any arguments containing whitespace in your
command if the command is passed as an arrayref and contains special characters.
=item Whitespace and IPC::Run
When using C<IPC::Run>, if you provide a string as the C<command> argument,
the string will be split on whitespace to determine the individual elements
of your command. Although this will usually just Do What You Mean, it may
break if you have files or commands with whitespace in them.
If you do not wish this to happen, you should provide an array
reference, where all parts of your command are already separated out.
Note however, if there are extra or spurious whitespaces in these parts,
the parser or underlying code may not interpret it correctly, and
cause an error.
Example:
The following code
gzip -cdf foo.tar.gz | tar -xf -
should either be passed as
"gzip -cdf foo.tar.gz | tar -xf -"
or as
['gzip', '-cdf', 'foo.tar.gz', '|', 'tar', '-xf', '-']
But take care not to pass it as, for example
['gzip -cdf foo.tar.gz', '|', 'tar -xf -']
Since this will lead to issues as described above.
=item IO Redirect
Currently it is too complicated to parse your command for IO
redirections. For capturing STDOUT or STDERR there is a work around
however, since you can just inspect your buffers for the contents.
=item Interleaving STDOUT/STDERR
Neither IPC::Run nor IPC::Open3 can interleave STDOUT and STDERR. For short
bursts of output from a program, e.g. this sample,
for ( 1..4 ) {
$_ % 2 ? print STDOUT $_ : print STDERR $_;
}
IPC::[Run|Open3] will first read all of STDOUT, then all of STDERR, meaning
the output looks like '13' on STDOUT and '24' on STDERR, instead of
1
2
3
4
This has been recorded in L<rt.cpan.org> as bug #37532: Unable to interleave
STDOUT and STDERR.
=back
=head1 See Also
L<IPC::Run>, L<IPC::Open3>
=head1 ACKNOWLEDGEMENTS
Thanks to James Mastros and Martijn van der Streek for their
help in getting L<IPC::Open3> to behave nicely.
Thanks to Petya Kohts for the C<run_forked> code.
=head1 BUG REPORTS
Please report bugs or other issues to E<lt>bug-ipc-cmd@rt.cpan.orgE<gt>.
=head1 AUTHOR
Original author: Jos Boumans E<lt>kane@cpan.orgE<gt>.
Current maintainer: Chris Williams E<lt>bingos@cpan.orgE<gt>.
=head1 COPYRIGHT
This library is free software; you may redistribute and/or modify it
under the same terms as Perl itself.
=cut
IPC_CMD
$fatpacked{"JSON/PP/Compat5006.pm"} = <<'JSON_PP_COMPAT5006';
package JSON::PP::Compat5006;
use 5.006;
use strict;
BEGIN {
if ( $] >= 5.008 ) {
require Carp;
die( "JSON::PP::Compat5006 is for Perl 5.6" );
}
}
my @properties;
$JSON::PP::Compat5006::VERSION = '1.09';
BEGIN {
sub utf8::is_utf8 {
my $len = length $_[0]; # char length
{
use bytes; # byte length;
return $len != length $_[0]; # if !=, UTF8-flagged on.
}
}
sub utf8::upgrade {
; # noop;
}
sub utf8::downgrade ($;$) {
return 1 unless ( utf8::is_utf8( $_[0] ) );
if ( _is_valid_utf8( $_[0] ) ) {
my $downgrade;
for my $c ( unpack( "U*", $_[0] ) ) {
if ( $c < 256 ) {
$downgrade .= pack("C", $c);
}
else {
$downgrade .= pack("U", $c);
}
}
$_[0] = $downgrade;
return 1;
}
else {
Carp::croak("Wide character in subroutine entry") unless ( $_[1] );
0;
}
}
sub utf8::encode ($) { # UTF8 flag off
if ( utf8::is_utf8( $_[0] ) ) {
$_[0] = pack( "C*", unpack( "C*", $_[0] ) );
}
else {
$_[0] = pack( "U*", unpack( "C*", $_[0] ) );
$_[0] = pack( "C*", unpack( "C*", $_[0] ) );
}
}
sub utf8::decode ($) { # UTF8 flag on
if ( _is_valid_utf8( $_[0] ) ) {
utf8::downgrade( $_[0] );
$_[0] = pack( "U*", unpack( "U*", $_[0] ) );
}
}
*JSON::PP::JSON_PP_encode_ascii = \&_encode_ascii;
*JSON::PP::JSON_PP_encode_latin1 = \&_encode_latin1;
*JSON::PP::JSON_PP_decode_surrogates = \&JSON::PP::_decode_surrogates;
*JSON::PP::JSON_PP_decode_unicode = \&JSON::PP::_decode_unicode;
unless ( defined &B::SVp_NOK ) { # missing in B module.
eval q{ sub B::SVp_NOK () { 0x02000000; } };
}
}
sub _encode_ascii {
join('',
map {
$_ <= 127 ?
chr($_) :
$_ <= 65535 ?
sprintf('\u%04x', $_) : sprintf('\u%x\u%x', JSON::PP::_encode_surrogates($_));
} _unpack_emu($_[0])
);
}
sub _encode_latin1 {
join('',
map {
$_ <= 255 ?
chr($_) :
$_ <= 65535 ?
sprintf('\u%04x', $_) : sprintf('\u%x\u%x', JSON::PP::_encode_surrogates($_));
} _unpack_emu($_[0])
);
}
sub _unpack_emu { # for Perl 5.6 unpack warnings
return !utf8::is_utf8($_[0]) ? unpack('C*', $_[0])
: _is_valid_utf8($_[0]) ? unpack('U*', $_[0])
: unpack('C*', $_[0]);
}
sub _is_valid_utf8 {
my $str = $_[0];
my $is_utf8;
while ($str =~ /(?:
(
[\x00-\x7F]
|[\xC2-\xDF][\x80-\xBF]
|[\xE0][\xA0-\xBF][\x80-\xBF]
|[\xE1-\xEC][\x80-\xBF][\x80-\xBF]
|[\xED][\x80-\x9F][\x80-\xBF]
|[\xEE-\xEF][\x80-\xBF][\x80-\xBF]
|[\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF]
|[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]
|[\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF]
)
| (.)
)/xg)
{
if (defined $1) {
$is_utf8 = 1 if (!defined $is_utf8);
}
else {
$is_utf8 = 0 if (!defined $is_utf8);
if ($is_utf8) { # eventually, not utf8
return;
}
}
}
return $is_utf8;
}
1;
__END__
=pod
=head1 NAME
JSON::PP::Compat5006 - Helper module in using JSON::PP in Perl 5.6
=head1 DESCRIPTION
JSON::PP calls internally.
=head1 AUTHOR
Makamaka Hannyaharamitu, E<lt>makamaka[at]cpan.orgE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright 2007-2010 by Makamaka Hannyaharamitu
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
JSON_PP_COMPAT5006
$fatpacked{"Locale/Maketext.pm"} = <<'LOCALE_MAKETEXT';
package Locale::Maketext;
use strict;
use vars qw( @ISA $VERSION $MATCH_SUPERS $USING_LANGUAGE_TAGS
$USE_LITERALS $MATCH_SUPERS_TIGHTLY);
use Carp ();
use I18N::LangTags ();
use I18N::LangTags::Detect ();
#--------------------------------------------------------------------------
BEGIN { unless(defined &DEBUG) { *DEBUG = sub () {0} } }
# define the constant 'DEBUG' at compile-time
# turn on utf8 if we have it (this is what GutsLoader.pm used to do essentially )
# use if (exists $INC{'utf8.pm'} || eval 'use utf8'), 'utf8';
BEGIN {
# if we have it || we can load it
if ( exists $INC{'utf8.pm'} || eval { local $SIG{'__DIE__'};require utf8; } ) {
utf8->import();
DEBUG and warn " utf8 on for _compile()\n";
}
else {
DEBUG and warn " utf8 not available for _compile() ($INC{'utf8.pm'})\n$@\n";
}
}
$VERSION = '1.19';
@ISA = ();
$MATCH_SUPERS = 1;
$MATCH_SUPERS_TIGHTLY = 1;
$USING_LANGUAGE_TAGS = 1;
# Turning this off is somewhat of a security risk in that little or no
# checking will be done on the legality of tokens passed to the
# eval("use $module_name") in _try_use. If you turn this off, you have
# to do your own taint checking.
$USE_LITERALS = 1 unless defined $USE_LITERALS;
# a hint for compiling bracket-notation things.
my %isa_scan = ();
###########################################################################
sub quant {
my($handle, $num, @forms) = @_;
return $num if @forms == 0; # what should this mean?
return $forms[2] if @forms > 2 and $num == 0; # special zeroth case
# Normal case:
# Note that the formatting of $num is preserved.
return( $handle->numf($num) . ' ' . $handle->numerate($num, @forms) );
# Most human languages put the number phrase before the qualified phrase.
}
sub numerate {
# return this lexical item in a form appropriate to this number
my($handle, $num, @forms) = @_;
my $s = ($num == 1);
return '' unless @forms;
if(@forms == 1) { # only the headword form specified
return $s ? $forms[0] : ($forms[0] . 's'); # very cheap hack.
}
else { # sing and plural were specified
return $s ? $forms[0] : $forms[1];
}
}
#--------------------------------------------------------------------------
sub numf {
my($handle, $num) = @_[0,1];
if($num < 10_000_000_000 and $num > -10_000_000_000 and $num == int($num)) {
$num += 0; # Just use normal integer stringification.
# Specifically, don't let %G turn ten million into 1E+007
}
else {
$num = CORE::sprintf('%G', $num);
# "CORE::" is there to avoid confusion with the above sub sprintf.
}
while( $num =~ s/^([-+]?\d+)(\d{3})/$1,$2/s ) {1} # right from perlfaq5
# The initial \d+ gobbles as many digits as it can, and then we
# backtrack so it un-eats the rightmost three, and then we
# insert the comma there.
$num =~ tr<.,><,.> if ref($handle) and $handle->{'numf_comma'};
# This is just a lame hack instead of using Number::Format
return $num;
}
sub sprintf {
no integer;
my($handle, $format, @params) = @_;
return CORE::sprintf($format, @params);
# "CORE::" is there to avoid confusion with myself!
}
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
use integer; # vroom vroom... applies to the whole rest of the module
sub language_tag {
my $it = ref($_[0]) || $_[0];
return undef unless $it =~ m/([^':]+)(?:::)?$/s;
$it = lc($1);
$it =~ tr<_><->;
return $it;
}
sub encoding {
my $it = $_[0];
return(
(ref($it) && $it->{'encoding'})
|| 'iso-8859-1' # Latin-1
);
}
#--------------------------------------------------------------------------
sub fallback_languages { return('i-default', 'en', 'en-US') }
sub fallback_language_classes { return () }
#--------------------------------------------------------------------------
sub fail_with { # an actual attribute method!
my($handle, @params) = @_;
return unless ref($handle);
$handle->{'fail'} = $params[0] if @params;
return $handle->{'fail'};
}
#--------------------------------------------------------------------------
sub failure_handler_auto {
# Meant to be used like:
# $handle->fail_with('failure_handler_auto')
my $handle = shift;
my $phrase = shift;
$handle->{'failure_lex'} ||= {};
my $lex = $handle->{'failure_lex'};
my $value ||= ($lex->{$phrase} ||= $handle->_compile($phrase));
# Dumbly copied from sub maketext:
return ${$value} if ref($value) eq 'SCALAR';
return $value if ref($value) ne 'CODE';
{
local $SIG{'__DIE__'};
eval { $value = &$value($handle, @_) };
}
# If we make it here, there was an exception thrown in the
# call to $value, and so scream:
if($@) {
# pretty up the error message
$@ =~ s{\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?}
{\n in bracket code [compiled line $1],}s;
#$err =~ s/\n?$/\n/s;
Carp::croak "Error in maketexting \"$phrase\":\n$@ as used";
# Rather unexpected, but suppose that the sub tried calling
# a method that didn't exist.
}
else {
return $value;
}
}
#==========================================================================
sub new {
# Nothing fancy!
my $class = ref($_[0]) || $_[0];
my $handle = bless {}, $class;
$handle->init;
return $handle;
}
sub init { return } # no-op
###########################################################################
sub maketext {
# Remember, this can fail. Failure is controllable many ways.
Carp::croak 'maketext requires at least one parameter' unless @_ > 1;
my($handle, $phrase) = splice(@_,0,2);
Carp::confess('No handle/phrase') unless (defined($handle) && defined($phrase));
# backup $@ in case it it's still being used in the calling code.
# If no failures, we'll re-set it back to what it was later.
my $at = $@;
# Copy @_ case one of its elements is $@.
@_ = @_;
# Look up the value:
my $value;
if (exists $handle->{'_external_lex_cache'}{$phrase}) {
DEBUG and warn "* Using external lex cache version of \"$phrase\"\n";
$value = $handle->{'_external_lex_cache'}{$phrase};
}
else {
foreach my $h_r (
@{ $isa_scan{ref($handle) || $handle} || $handle->_lex_refs }
) {
DEBUG and warn "* Looking up \"$phrase\" in $h_r\n";
if(exists $h_r->{$phrase}) {
DEBUG and warn " Found \"$phrase\" in $h_r\n";
unless(ref($value = $h_r->{$phrase})) {
# Nonref means it's not yet compiled. Compile and replace.
if ($handle->{'use_external_lex_cache'}) {
$value = $handle->{'_external_lex_cache'}{$phrase} = $handle->_compile($value);
}
else {
$value = $h_r->{$phrase} = $handle->_compile($value);
}
}
last;
}
# extending packages need to be able to localize _AUTO and if readonly can't "local $h_r->{'_AUTO'} = 1;"
# but they can "local $handle->{'_external_lex_cache'}{'_AUTO'} = 1;"
elsif($phrase !~ m/^_/s and ($handle->{'use_external_lex_cache'} ? ( exists $handle->{'_external_lex_cache'}{'_AUTO'} ? $handle->{'_external_lex_cache'}{'_AUTO'} : $h_r->{'_AUTO'} ) : $h_r->{'_AUTO'})) {
# it's an auto lex, and this is an autoable key!
DEBUG and warn " Automaking \"$phrase\" into $h_r\n";
if ($handle->{'use_external_lex_cache'}) {
$value = $handle->{'_external_lex_cache'}{$phrase} = $handle->_compile($phrase);
}
else {
$value = $h_r->{$phrase} = $handle->_compile($phrase);
}
last;
}
DEBUG>1 and print " Not found in $h_r, nor automakable\n";
# else keep looking
}
}
unless(defined($value)) {
DEBUG and warn "! Lookup of \"$phrase\" in/under ", ref($handle) || $handle, " fails.\n";
if(ref($handle) and $handle->{'fail'}) {
DEBUG and warn "WARNING0: maketext fails looking for <$phrase>\n";
my $fail;
if(ref($fail = $handle->{'fail'}) eq 'CODE') { # it's a sub reference
$@ = $at; # Put $@ back in case we altered it along the way.
return &{$fail}($handle, $phrase, @_);
# If it ever returns, it should return a good value.
}
else { # It's a method name
$@ = $at; # Put $@ back in case we altered it along the way.
return $handle->$fail($phrase, @_);
# If it ever returns, it should return a good value.
}
}
else {
# All we know how to do is this;
Carp::croak("maketext doesn't know how to say:\n$phrase\nas needed");
}
}
if(ref($value) eq 'SCALAR'){
$@ = $at; # Put $@ back in case we altered it along the way.
return $$value ;
}
if(ref($value) ne 'CODE'){
$@ = $at; # Put $@ back in case we altered it along the way.
return $value ;
}
{
local $SIG{'__DIE__'};
eval { $value = &$value($handle, @_) };
}
# If we make it here, there was an exception thrown in the
# call to $value, and so scream:
if ($@) {
# pretty up the error message
$@ =~ s{\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?}
{\n in bracket code [compiled line $1],}s;
#$err =~ s/\n?$/\n/s;
Carp::croak "Error in maketexting \"$phrase\":\n$@ as used";
# Rather unexpected, but suppose that the sub tried calling
# a method that didn't exist.
}
else {
$@ = $at; # Put $@ back in case we altered it along the way.
return $value;
}
$@ = $at; # Put $@ back in case we altered it along the way.
}
###########################################################################
sub get_handle { # This is a constructor and, yes, it CAN FAIL.
# Its class argument has to be the base class for the current
# application's l10n files.
my($base_class, @languages) = @_;
$base_class = ref($base_class) || $base_class;
# Complain if they use __PACKAGE__ as a project base class?
if( @languages ) {
DEBUG and warn 'Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
if($USING_LANGUAGE_TAGS) { # An explicit language-list was given!
@languages =
map {; $_, I18N::LangTags::alternate_language_tags($_) }
# Catch alternation
map I18N::LangTags::locale2language_tag($_),
# If it's a lg tag, fine, pass thru (untainted)
# If it's a locale ID, try converting to a lg tag (untainted),
# otherwise nix it.
@languages;
DEBUG and warn 'Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
}
}
else {
@languages = $base_class->_ambient_langprefs;
}
@languages = $base_class->_langtag_munging(@languages);
my %seen;
foreach my $module_name ( map { $base_class . '::' . $_ } @languages ) {
next unless length $module_name; # sanity
next if $seen{$module_name}++ # Already been here, and it was no-go
|| !&_try_use($module_name); # Try to use() it, but can't it.
return($module_name->new); # Make it!
}
return undef; # Fail!
}
###########################################################################
sub _langtag_munging {
my($base_class, @languages) = @_;
# We have all these DEBUG statements because otherwise it's hard as hell
# to diagnose ifwhen something goes wrong.
DEBUG and warn 'Lgs1: ', map("<$_>", @languages), "\n";
if($USING_LANGUAGE_TAGS) {
DEBUG and warn 'Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
@languages = $base_class->_add_supers( @languages );
push @languages, I18N::LangTags::panic_languages(@languages);
DEBUG and warn "After adding panic languages:\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
push @languages, $base_class->fallback_languages;
# You are free to override fallback_languages to return empty-list!
DEBUG and warn 'Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
@languages = # final bit of processing to turn them into classname things
map {
my $it = $_; # copy
$it =~ tr<-A-Z><_a-z>; # lc, and turn - to _
$it =~ tr<_a-z0-9><>cd; # remove all but a-z0-9_
$it;
} @languages
;
DEBUG and warn "Nearing end of munging:\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
}
else {
DEBUG and warn "Bypassing language-tags.\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
}
DEBUG and warn "Before adding fallback classes:\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
push @languages, $base_class->fallback_language_classes;
# You are free to override that to return whatever.
DEBUG and warn "Finally:\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
return @languages;
}
###########################################################################
sub _ambient_langprefs {
return I18N::LangTags::Detect::detect();
}
###########################################################################
sub _add_supers {
my($base_class, @languages) = @_;
if (!$MATCH_SUPERS) {
# Nothing
DEBUG and warn "Bypassing any super-matching.\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
}
elsif( $MATCH_SUPERS_TIGHTLY ) {
DEBUG and warn "Before adding new supers tightly:\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
@languages = I18N::LangTags::implicate_supers( @languages );
DEBUG and warn "After adding new supers tightly:\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
}
else {
DEBUG and warn "Before adding supers to end:\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
@languages = I18N::LangTags::implicate_supers_strictly( @languages );
DEBUG and warn "After adding supers to end:\n",
' Lgs@', __LINE__, ': ', map("<$_>", @languages), "\n";
}
return @languages;
}
###########################################################################
#
# This is where most people should stop reading.
#
###########################################################################
my %tried = ();
# memoization of whether we've used this module, or found it unusable.
sub _try_use { # Basically a wrapper around "require Modulename"
# "Many men have tried..." "They tried and failed?" "They tried and died."
return $tried{$_[0]} if exists $tried{$_[0]}; # memoization
my $module = $_[0]; # ASSUME sane module name!
{ no strict 'refs';
no warnings 'once';
return($tried{$module} = 1)
if %{$module . '::Lexicon'} or @{$module . '::ISA'};
# weird case: we never use'd it, but there it is!
}
DEBUG and warn " About to use $module ...\n";
local $SIG{'__DIE__'};
local $@;
eval "require $module"; # used to be "use $module", but no point in that.
if($@) {
DEBUG and warn "Error using $module \: $@\n";
return $tried{$module} = 0;
}
else {
DEBUG and warn " OK, $module is used\n";
return $tried{$module} = 1;
}
}
#--------------------------------------------------------------------------
sub _lex_refs { # report the lexicon references for this handle's class
# returns an arrayREF!
no strict 'refs';
no warnings 'once';
my $class = ref($_[0]) || $_[0];
DEBUG and warn "Lex refs lookup on $class\n";
return $isa_scan{$class} if exists $isa_scan{$class}; # memoization!
my @lex_refs;
my $seen_r = ref($_[1]) ? $_[1] : {};
if( defined( *{$class . '::Lexicon'}{'HASH'} )) {
push @lex_refs, *{$class . '::Lexicon'}{'HASH'};
DEBUG and warn '%' . $class . '::Lexicon contains ',
scalar(keys %{$class . '::Lexicon'}), " entries\n";
}
# Implements depth(height?)-first recursive searching of superclasses.
# In hindsight, I suppose I could have just used Class::ISA!
foreach my $superclass (@{$class . '::ISA'}) {
DEBUG and warn " Super-class search into $superclass\n";
next if $seen_r->{$superclass}++;
push @lex_refs, @{&_lex_refs($superclass, $seen_r)}; # call myself
}
$isa_scan{$class} = \@lex_refs; # save for next time
return \@lex_refs;
}
sub clear_isa_scan { %isa_scan = (); return; } # end on a note of simplicity!
#--------------------------------------------------------------------------
sub _compile {
# This big scary routine compiles an entry.
# It returns either a coderef if there's brackety bits in this, or
# otherwise a ref to a scalar.
my $string_to_compile = $_[1]; # There are taint issues using regex on @_ - perlbug 60378,27344
# The while() regex is more expensive than this check on strings that don't need a compile.
# this op causes a ~2% speed hit for strings that need compile and a 250% speed improvement
# on strings that don't need compiling.
return \"$string_to_compile" if($string_to_compile !~ m/[\[~\]]/ms); # return a string ref if chars [~] are not in the string
my $target = ref($_[0]) || $_[0];
my(@code);
my(@c) = (''); # "chunks" -- scratch.
my $call_count = 0;
my $big_pile = '';
{
my $in_group = 0; # start out outside a group
my($m, @params); # scratch
while($string_to_compile =~ # Iterate over chunks.
m/(
[^\~\[\]]+ # non-~[] stuff (Capture everything else here)
|
~. # ~[, ~], ~~, ~other
|
\[ # [ presumably opening a group
|
\] # ] presumably closing a group
|
~ # terminal ~ ?
|
$
)/xgs
) {
DEBUG>2 and warn qq{ "$1"\n};
if($1 eq '[' or $1 eq '') { # "[" or end
# Whether this is "[" or end, force processing of any
# preceding literal.
if($in_group) {
if($1 eq '') {
$target->_die_pointing($string_to_compile, 'Unterminated bracket group');
}
else {
$target->_die_pointing($string_to_compile, 'You can\'t nest bracket groups');
}
}
else {
if ($1 eq '') {
DEBUG>2 and warn " [end-string]\n";
}
else {
$in_group = 1;
}
die "How come \@c is empty?? in <$string_to_compile>" unless @c; # sanity
if(length $c[-1]) {
# Now actually processing the preceding literal
$big_pile .= $c[-1];
if($USE_LITERALS and (
(ord('A') == 65)
? $c[-1] !~ m/[^\x20-\x7E]/s
# ASCII very safe chars
: $c[-1] !~ m/[^ !"\#\$%&'()*+,\-.\/0-9:;<=>?\@A-Z[\\\]^_`a-z{|}~\x07]/s
# EBCDIC very safe chars
)) {
# normal case -- all very safe chars
$c[-1] =~ s/'/\\'/g;
push @code, q{ '} . $c[-1] . "',\n";
$c[-1] = ''; # reuse this slot
}
else {
push @code, ' $c[' . $#c . "],\n";
push @c, ''; # new chunk
}
}
# else just ignore the empty string.
}
}
elsif($1 eq ']') { # "]"
# close group -- go back in-band
if($in_group) {
$in_group = 0;
DEBUG>2 and warn " --Closing group [$c[-1]]\n";
# And now process the group...
if(!length($c[-1]) or $c[-1] =~ m/^\s+$/s) {
DEBUG>2 and warn " -- (Ignoring)\n";
$c[-1] = ''; # reset out chink
next;
}
#$c[-1] =~ s/^\s+//s;
#$c[-1] =~ s/\s+$//s;
($m,@params) = split(/,/, $c[-1], -1); # was /\s*,\s*/
# A bit of a hack -- we've turned "~,"'s into DELs, so turn
# 'em into real commas here.
if (ord('A') == 65) { # ASCII, etc
foreach($m, @params) { tr/\x7F/,/ }
}
else { # EBCDIC (1047, 0037, POSIX-BC)
# Thanks to Peter Prymmer for the EBCDIC handling
foreach($m, @params) { tr/\x07/,/ }
}
# Special-case handling of some method names:
if($m eq '_*' or $m =~ m/^_(-?\d+)$/s) {
# Treat [_1,...] as [,_1,...], etc.
unshift @params, $m;
$m = '';
}
elsif($m eq '*') {
$m = 'quant'; # "*" for "times": "4 cars" is 4 times "cars"
}
elsif($m eq '#') {
$m = 'numf'; # "#" for "number": [#,_1] for "the number _1"
}
# Most common case: a simple, legal-looking method name
if($m eq '') {
# 0-length method name means to just interpolate:
push @code, ' (';
}
elsif($m =~ /^\w+(?:\:\:\w+)*$/s
and $m !~ m/(?:^|\:)\d/s
# exclude starting a (sub)package or symbol with a digit
) {
# Yes, it even supports the demented (and undocumented?)
# $obj->Foo::bar(...) syntax.
$target->_die_pointing(
$string_to_compile, q{Can't use "SUPER::" in a bracket-group method},
2 + length($c[-1])
)
if $m =~ m/^SUPER::/s;
# Because for SUPER:: to work, we'd have to compile this into
# the right package, and that seems just not worth the bother,
# unless someone convinces me otherwise.
push @code, ' $_[0]->' . $m . '(';
}
else {
# TODO: implement something? or just too icky to consider?
$target->_die_pointing(
$string_to_compile,
"Can't use \"$m\" as a method name in bracket group",
2 + length($c[-1])
);
}
pop @c; # we don't need that chunk anymore
++$call_count;
foreach my $p (@params) {
if($p eq '_*') {
# Meaning: all parameters except $_[0]
$code[-1] .= ' @_[1 .. $#_], ';
# and yes, that does the right thing for all @_ < 3
}
elsif($p =~ m/^_(-?\d+)$/s) {
# _3 meaning $_[3]
$code[-1] .= '$_[' . (0 + $1) . '], ';
}
elsif($USE_LITERALS and (
(ord('A') == 65)
? $p !~ m/[^\x20-\x7E]/s
# ASCII very safe chars
: $p !~ m/[^ !"\#\$%&'()*+,\-.\/0-9:;<=>?\@A-Z[\\\]^_`a-z{|}~\x07]/s
# EBCDIC very safe chars
)) {
# Normal case: a literal containing only safe characters
$p =~ s/'/\\'/g;
$code[-1] .= q{'} . $p . q{', };
}
else {
# Stow it on the chunk-stack, and just refer to that.
push @c, $p;
push @code, ' $c[' . $#c . '], ';
}
}
$code[-1] .= "),\n";
push @c, '';
}
else {
$target->_die_pointing($string_to_compile, q{Unbalanced ']'});
}
}
elsif(substr($1,0,1) ne '~') {
# it's stuff not containing "~" or "[" or "]"
# i.e., a literal blob
$c[-1] .= $1;
}
elsif($1 eq '~~') { # "~~"
$c[-1] .= '~';
}
elsif($1 eq '~[') { # "~["
$c[-1] .= '[';
}
elsif($1 eq '~]') { # "~]"
$c[-1] .= ']';
}
elsif($1 eq '~,') { # "~,"
if($in_group) {
# This is a hack, based on the assumption that no-one will actually
# want a DEL inside a bracket group. Let's hope that's it's true.
if (ord('A') == 65) { # ASCII etc
$c[-1] .= "\x7F";
}
else { # EBCDIC (cp 1047, 0037, POSIX-BC)
$c[-1] .= "\x07";
}
}
else {
$c[-1] .= '~,';
}
}
elsif($1 eq '~') { # possible only at string-end, it seems.
$c[-1] .= '~';
}
else {
# It's a "~X" where X is not a special character.
# Consider it a literal ~ and X.
$c[-1] .= $1;
}
}
}
if($call_count) {
undef $big_pile; # Well, nevermind that.
}
else {
# It's all literals! Ahwell, that can happen.
# So don't bother with the eval. Return a SCALAR reference.
return \$big_pile;
}
die q{Last chunk isn't null??} if @c and length $c[-1]; # sanity
DEBUG and warn scalar(@c), " chunks under closure\n";
if(@code == 0) { # not possible?
DEBUG and warn "Empty code\n";
return \'';
}
elsif(@code > 1) { # most cases, presumably!
unshift @code, "join '',\n";
}
unshift @code, "use strict; sub {\n";
push @code, "}\n";
DEBUG and warn @code;
my $sub = eval(join '', @code);
die "$@ while evalling" . join('', @code) if $@; # Should be impossible.
return $sub;
}
#--------------------------------------------------------------------------
sub _die_pointing {
# This is used by _compile to throw a fatal error
my $target = shift; # class name
# ...leaving $_[0] the error-causing text, and $_[1] the error message
my $i = index($_[0], "\n");
my $pointy;
my $pos = pos($_[0]) - (defined($_[2]) ? $_[2] : 0) - 1;
if($pos < 1) {
$pointy = "^=== near there\n";
}
else { # we need to space over
my $first_tab = index($_[0], "\t");
if($pos > 2 and ( -1 == $first_tab or $first_tab > pos($_[0]))) {
# No tabs, or the first tab is harmlessly after where we will point to,
# AND we're far enough from the margin that we can draw a proper arrow.
$pointy = ('=' x $pos) . "^ near there\n";
}
else {
# tabs screw everything up!
$pointy = substr($_[0],0,$pos);
$pointy =~ tr/\t //cd;
# make everything into whitespace, but preserving tabs
$pointy .= "^=== near there\n";
}
}
my $errmsg = "$_[1], in\:\n$_[0]";
if($i == -1) {
# No newline.
$errmsg .= "\n" . $pointy;
}
elsif($i == (length($_[0]) - 1) ) {
# Already has a newline at end.
$errmsg .= $pointy;
}
else {
# don't bother with the pointy bit, I guess.
}
Carp::croak( "$errmsg via $target, as used" );
}
1;
LOCALE_MAKETEXT
$fatpacked{"Locale/Maketext/Extract.pm"} = <<'LOCALE_MAKETEXT_EXTRACT';
package Locale::Maketext::Extract;
$Locale::Maketext::Extract::VERSION = '0.38';
use strict;
use Locale::Maketext::Lexicon();
=head1 NAME
Locale::Maketext::Extract - Extract translatable strings from source
=head1 SYNOPSIS
my $Ext = Locale::Maketext::Extract->new;
$Ext->read_po('messages.po');
$Ext->extract_file($_) for <*.pl>;
# Set $entries_are_in_gettext_format if the .pl files above use
# loc('%1') instead of loc('[_1]')
$Ext->compile($entries_are_in_gettext_format);
$Ext->write_po('messages.po');
-----------------------------------
### Specifying parser plugins ###
my $Ext = Locale::Maketext::Extract->new(
# Specify which parser plugins to use
plugins => {
# Use Perl parser, process files with extension .pl .pm .cgi
perl => [],
# Use YAML parser, process all files
yaml => ['*'],
# Use TT2 parser, process files with extension .tt2 .tt .html
# or which match the regex
tt2 => [
'tt2',
'tt',
'html',
qr/\.tt2?\./
],
# Use My::Module as a parser for all files
'My::Module' => ['*'],
},
# Warn if a parser can't process a file or problems loading a plugin
warnings => 1,
# List processed files
verbose => 1,
);
=head1 DESCRIPTION
This module can extract translatable strings from files, and write
them back to PO files. It can also parse existing PO files and merge
their contents with newly extracted strings.
A command-line utility, L<xgettext.pl>, is installed with this module
as well.
The format parsers are loaded as plugins, so it is possible to define
your own parsers.
Following formats of input files are supported:
=over 4
=item Perl source files (plugin: perl)
Valid localization function names are: C<translate>, C<maketext>,
C<gettext>, C<loc>, C<x>, C<_> and C<__>.
For a slightly more accurate, but much slower Perl parser, you can use the PPI
plugin. This does not have a short name (like C<perl>), but must be specified
in full.
=item HTML::Mason (Mason 1) and Mason (Mason 2) (plugin: mason)
HTML::Mason (aka Mason 1)
Strings inside <&|/l>...</&> and <&|/loc>...</&> are extracted.
Mason (aka Mason 2)
Strings inside <% $.floc { %>...</%> or <% $.fl { %>...</%> or
<% $self->floc { %>...</%> or <% $self->fl { %>...</%> are extracted.
=item Template Toolkit (plugin: tt2)
Valid forms are:
[% | l(arg1,argn) %]string[% END %]
[% 'string' | l(arg1,argn) %]
[% l('string',arg1,argn) %]
FILTER and | are interchangeable
l and loc are interchangeable
args are optional
=item Text::Template (plugin: text)
Sentences between C<STARTxxx> and C<ENDxxx> are extracted individually.
=item YAML (plugin: yaml)
Valid forms are _"string" or _'string', eg:
title: _"My title"
desc: _'My "quoted" string'
Quotes do not have to be escaped, so you could also do:
desc: _"My "quoted" string"
=item HTML::FormFu (plugin: formfu)
HTML::FormFu uses a config-file to generate forms, with built in
support for localizing errors, labels etc.
We extract the text after C<_loc: >:
content_loc: this is the string
message_loc: ['Max string length: [_1]', 10]
=item Generic Template (plugin: generic)
Strings inside {{...}} are extracted.
=back
=head1 METHODS
=head2 Constructor
new()
new(
plugins => {...},
warnings => 1 | 0,
verbose => 0 | 1 | 2 | 3,
)
See L</"Plugins">, L</"Warnings"> and L</"Verbose"> for details
=head2 Plugins
$ext->plugins({...});
Locale::Maketext::Extract uses plugins (see below for the list)
to parse different formats.
Each plugin can also specify which file types it can parse.
# use only the YAML plugin
# only parse files with the default extension list defined in the plugin
# ie .yaml .yml .conf
$ext->plugins({
yaml => [],
})
# use only the Perl plugin
# parse all file types
$ext->plugins({
perl => '*'
})
$ext->plugins({
tt2 => [
'tt', # matches base filename against /\.tt$/
qr/\.tt2?\./, # matches base filename against regex
\&my_filter, # codref called
]
})
sub my_filter {
my ($base_filename,$path_to_file) = @_;
return 1 | 0;
}
# Specify your own parser
# only parse files with the default extension list defined in the plugin
$ext->plugins({
'My::Extract::Parser' => []
})
By default, if no plugins are specified, then it uses all of the builtin
plugins, and overrides the file types specified in each plugin
- instead, each plugin is tried for every file.
=head3 Available plugins
=over 4
=item C<perl> : L<Locale::Maketext::Extract::Plugin::Perl>
For a slightly more accurate but much slower Perl parser, you can use
the PPI plugin. This does not have a short name, but must be specified in
full, ie: L<Locale::Maketext::Extract::Plugin::PPI>
=item C<tt2> : L<Locale::Maketext::Extract::Plugin::TT2>
=item C<yaml> : L<Locale::Maketext::Extract::Plugin::YAML>
=item C<formfu> : L<Locale::Maketext::Extract::Plugin::FormFu>
=item C<mason> : L<Locale::Maketext::Extract::Plugin::Mason>
=item C<text> : L<Locale::Maketext::Extract::Plugin::TextTemplate>
=item C<generic> : L<Locale::Maketext::Extract::Plugin::Generic>
=back
Also, see L<Locale::Maketext::Extract::Plugin::Base> for details of how to
write your own plugin.
=head2 Warnings
Because the YAML and TT2 plugins use proper parsers, rather than just regexes,
if a source file is not valid and it is unable to parse the file, then the
parser will throw an error and abort parsing.
The next enabled plugin will be tried.
By default, you will not see these errors. If you would like to see them,
then enable warnings via new(). All parse errors will be printed to STDERR.
Also, if developing your own plugin, turn on warnings to see any errors that
result from loading your plugin.
=head2 Verbose
If you would like to see which files have been processed, which plugins were
used, and which strings were extracted, then enable C<verbose>. If no
acceptable plugin was found, or no strings were extracted, then the file
is not listed:
$ext = Locale::Extract->new( verbose => 1 | 2 | 3);
OR
xgettext.pl ... -v # files reported
xgettext.pl ... -v -v # files and plugins reported
xgettext.pl ... -v -v -v # files, plugins and strings reported
=cut
our %Known_Plugins = (
perl => 'Locale::Maketext::Extract::Plugin::Perl',
yaml => 'Locale::Maketext::Extract::Plugin::YAML',
tt2 => 'Locale::Maketext::Extract::Plugin::TT2',
text => 'Locale::Maketext::Extract::Plugin::TextTemplate',
mason => 'Locale::Maketext::Extract::Plugin::Mason',
generic => 'Locale::Maketext::Extract::Plugin::Generic',
formfu => 'Locale::Maketext::Extract::Plugin::FormFu',
);
sub new {
my $class = shift;
my %params = @_;
my $plugins = delete $params{plugins}
|| { map { $_ => '*' } keys %Known_Plugins };
Locale::Maketext::Lexicon::set_option( 'keep_fuzzy' => 1 );
my $self = bless( { header => '',
entries => {},
compiled_entries => {},
lexicon => {},
warnings => 0,
verbose => 0,
wrap => 0,
%params,
},
$class
);
$self->{verbose} ||= 0;
die "No plugins defined in new()"
unless $plugins;
$self->plugins($plugins);
return $self;
}
=head2 Accessors
header, set_header
lexicon, set_lexicon, msgstr, set_msgstr
entries, set_entries, entry, add_entry, del_entry
compiled_entries, set_compiled_entries, compiled_entry,
add_compiled_entry, del_compiled_entry
clear
=cut
sub header { $_[0]{header} || _default_header() }
sub set_header { $_[0]{header} = $_[1] }
sub lexicon { $_[0]{lexicon} }
sub set_lexicon { $_[0]{lexicon} = $_[1] || {}; delete $_[0]{lexicon}{''}; }
sub msgstr { $_[0]{lexicon}{ $_[1] } }
sub set_msgstr { $_[0]{lexicon}{ $_[1] } = $_[2] }
sub entries { $_[0]{entries} }
sub set_entries { $_[0]{entries} = $_[1] || {} }
sub compiled_entries { $_[0]{compiled_entries} }
sub set_compiled_entries { $_[0]{compiled_entries} = $_[1] || {} }
sub entry { @{ $_[0]->entries->{ $_[1] } || [] } }
sub add_entry { push @{ $_[0]->entries->{ $_[1] } }, $_[2] }
sub del_entry { delete $_[0]->entries->{ $_[1] } }
sub compiled_entry { @{ $_[0]->compiled_entries->{ $_[1] } || [] } }
sub add_compiled_entry { push @{ $_[0]->compiled_entries->{ $_[1] } }, $_[2] }
sub del_compiled_entry { delete $_[0]->compiled_entries->{ $_[1] } }
sub plugins {
my $self = shift;
if (@_) {
my @plugins;
my %params = %{ shift @_ };
foreach my $name ( keys %params ) {
my $plugin_class = $Known_Plugins{$name} || $name;
my $filename = $plugin_class . '.pm';
$filename =~ s/::/\//g;
local $@;
eval {
require $filename && 1;
1;
} or do {
my $error = $@ || 'Unknown';
print STDERR "Error loading $plugin_class: $error\n"
if $self->{warnings};
next;
};
push @plugins, $plugin_class->new( $params{$name} );
}
$self->{plugins} = \@plugins;
}
return $self->{plugins} || [];
}
sub clear {
$_[0]->set_header;
$_[0]->set_lexicon;
$_[0]->set_comments;
$_[0]->set_fuzzy;
$_[0]->set_entries;
$_[0]->set_compiled_entries;
}
=head2 PO File manipulation
=head3 method read_po ($file)
=cut
sub read_po {
my ( $self, $file ) = @_;
print STDERR "READING PO FILE : $file\n"
if $self->{verbose};
my $header = '';
local ( *LEXICON, $_ );
open LEXICON, $file or die $!;
while (<LEXICON>) {
( 1 .. /^$/ ) or last;
$header .= $_;
}
1 while chomp $header;
$self->set_header("$header\n");
require Locale::Maketext::Lexicon::Gettext;
my $lexicon = {};
my $comments = {};
my $fuzzy = {};
$self->set_compiled_entries( {} );
if ( defined($_) ) {
( $lexicon, $comments, $fuzzy )
= Locale::Maketext::Lexicon::Gettext->parse( $_, <LEXICON> );
}
# Internally the lexicon is in gettext format already.
$self->set_lexicon( { map _maketext_to_gettext($_), %$lexicon } );
$self->set_comments($comments);
$self->set_fuzzy($fuzzy);
close LEXICON;
}
sub msg_comment {
my $self = shift;
my $msgid = shift;
my $comment = $self->{comments}->{$msgid};
return $comment;
}
sub msg_fuzzy {
return $_[0]->{fuzzy}{$_[1]} ? ', fuzzy' : '';
}
sub set_comments {
$_[0]->{comments} = $_[1];
}
sub set_fuzzy {
$_[0]->{fuzzy} = $_[1];
}
=head3 method write_po ($file, $add_format_marker?)
=cut
sub write_po {
my ( $self, $file, $add_format_marker ) = @_;
print STDERR "WRITING PO FILE : $file\n"
if $self->{verbose};
local *LEXICON;
open LEXICON, ">$file" or die "Can't write to $file$!\n";
print LEXICON $self->header;
foreach my $msgid ( $self->msgids ) {
$self->normalize_space($msgid);
print LEXICON "\n";
if ( my $comment = $self->msg_comment($msgid) ) {
my @lines = split "\n", $comment;
print LEXICON map {"# $_\n"} @lines;
}
print LEXICON $self->msg_variables($msgid);
print LEXICON $self->msg_positions($msgid);
my $flags = $self->msg_fuzzy($msgid);
$flags.= $self->msg_format($msgid) if $add_format_marker;
print LEXICON "#$flags\n" if $flags;
print LEXICON $self->msg_out($msgid);
}
print STDERR "DONE\n\n"
if $self->{verbose};
}
=head2 Extraction
extract
extract_file
=cut
sub extract {
my $self = shift;
my $file = shift;
my $content = shift;
local $@;
my ( @messages, $total, $error_found );
$total = 0;
my $verbose = $self->{verbose};
foreach my $plugin ( @{ $self->plugins } ) {
if ( $plugin->known_file_type($file) ) {
pos($content) = 0;
my $success = eval { $plugin->extract($content); 1; };
if ($success) {
my $entries = $plugin->entries;
if ( $verbose > 1 && @$entries ) {
push @messages,
" - "
. ref($plugin)
. ' - Strings extracted : '
. ( scalar @$entries );
}
for my $entry (@$entries) {
my ( $string, $line, $vars ) = @$entry;
$self->add_entry( $string => [ $file, $line, $vars ] );
if ( $verbose > 2 ) {
$vars = '' if !defined $vars;
# pad string
$string =~ s/\n/\n /g;
push @messages,
sprintf( qq[ - %-8s "%s" (%s)],
$line . ':',
$string, $vars
),
;
}
}
$total += @$entries;
}
else {
$error_found++;
if ( $self->{warnings} ) {
push @messages,
"Error parsing '$file' with plugin "
. ( ref $plugin )
. ": \n $@\n";
}
}
$plugin->clear;
}
}
print STDERR " * $file\n - Total strings extracted : $total"
. ( $error_found ? ' [ERROR ] ' : '' ) . "\n"
if $verbose
&& ( $total || $error_found );
print STDERR join( "\n", @messages ) . "\n"
if @messages;
}
sub extract_file {
my ( $self, $file ) = @_;
local ( $/, *FH );
open FH, $file or die "Error reading from file '$file' : $!";
my $content = scalar <FH>;
$self->extract( $file => $content );
close FH;
}
=head2 Compilation
=head3 compile($entries_are_in_gettext_style?)
Merges the C<entries> into C<compiled_entries>.
If C<$entries_are_in_gettext_style> is true, the previously extracted entries
are assumed to be in the B<Gettext> style (e.g. C<%1>).
Otherwise they are assumed to be in B<Maketext> style (e.g. C<[_1]>) and are
converted into B<Gettext> style before merging into C<compiled_entries>.
The C<entries> are I<not> cleared after each compilation; use
C<->set_entries()> to clear them if you need to extract from sources with
varying styles.
=cut
sub compile {
my ( $self, $entries_are_in_gettext_style ) = @_;
my $entries = $self->entries;
my $lexicon = $self->lexicon;
my $comp = $self->compiled_entries;
while ( my ( $k, $v ) = each %$entries ) {
my $compiled_key = ( ($entries_are_in_gettext_style)
? $k
: _maketext_to_gettext($k)
);
$comp->{$compiled_key} = $v;
$lexicon->{$compiled_key} = ''
unless exists $lexicon->{$compiled_key};
}
return %$lexicon;
}
=head3 normalize_space
=cut
my %Escapes = map { ( "\\$_" => eval("qq(\\$_)") ) } qw(t r f b a e);
sub normalize_space {
my ( $self, $msgid ) = @_;
my $nospace = $msgid;
$nospace =~ s/ +$//;
return
unless ( !$self->has_msgid($msgid) and $self->has_msgid($nospace) );
$self->set_msgstr( $msgid => $self->msgstr($nospace)
. ( ' ' x ( length($msgid) - length($nospace) ) ) );
}
=head2 Lexicon accessors
msgids, has_msgid,
msgstr, set_msgstr
msg_positions, msg_variables, msg_format, msg_out
=cut
sub msgids { sort keys %{ $_[0]{lexicon} } }
sub has_msgid {
my $msg_str = $_[0]->msgstr( $_[1] );
return defined $msg_str ? length $msg_str : 0;
}
sub msg_positions {
my ( $self, $msgid ) = @_;
my %files = ( map { ( " $_->[0]:$_->[1]" => 1 ) }
$self->compiled_entry($msgid) );
return $self->{wrap}
? join( "\n", ( map { '#:' . $_ } sort( keys %files ) ), '' )
: join( '', '#:', sort( keys %files ), "\n" );
}
sub msg_variables {
my ( $self, $msgid ) = @_;
my $out = '';
my %seen;
foreach my $entry ( grep { $_->[2] } $self->compiled_entry($msgid) ) {
my ( $file, $line, $var ) = @$entry;
$var =~ s/^\s*,\s*//;
$var =~ s/\s*$//;
$out .= "#. ($var)\n" unless !length($var) or $seen{$var}++;
}
return $out;
}
sub msg_format {
my ( $self, $msgid ) = @_;
return ", perl-maketext-format"
if $msgid =~ /%(?:[1-9]\d*|\w+\([^\)]*\))/;
return '';
}
sub msg_out {
my ( $self, $msgid ) = @_;
my $msgstr = $self->msgstr($msgid);
return "msgid " . _format($msgid) . "msgstr " . _format($msgstr);
}
=head2 Internal utilities
_default_header
_maketext_to_gettext
_escape
_format
=cut
sub _default_header {
return << '.';
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
.
}
sub _maketext_to_gettext {
my $text = shift;
return '' unless defined $text;
$text =~ s{((?<!~)(?:~~)*)\[_([1-9]\d*|\*)\]}
{$1%$2}g;
$text =~ s{((?<!~)(?:~~)*)\[([A-Za-z#*]\w*),([^\]]+)\]}
{"$1%$2(" . _escape($3) . ')'}eg;
$text =~ s/~([\~\[\]])/$1/g;
return $text;
}
sub _escape {
my $text = shift;
$text =~ s/\b_([1-9]\d*)/%$1/g;
return $text;
}
sub _format {
my $str = shift;
$str =~ s/(?=[\\"])/\\/g;
while ( my ( $char, $esc ) = each %Escapes ) {
$str =~ s/$esc/$char/g;
}
return "\"$str\"\n" unless $str =~ /\n/;
my $multi_line = ( $str =~ /\n(?!\z)/ );
$str =~ s/\n/\\n"\n"/g;
if ( $str =~ /\n"$/ ) {
chop $str;
}
else {
$str .= "\"\n";
}
return $multi_line ? qq(""\n"$str) : qq("$str);
}
1;
=head1 ACKNOWLEDGMENTS
Thanks to Jesse Vincent for contributing to an early version of this
module.
Also to Alain Barbet, who effectively re-wrote the source parser with a
flex-like algorithm.
=head1 SEE ALSO
L<xgettext.pl>, L<Locale::Maketext>, L<Locale::Maketext::Lexicon>
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2003-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
LOCALE_MAKETEXT_EXTRACT
$fatpacked{"Locale/Maketext/Extract/Plugin/Base.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_PLUGIN_BASE';
package Locale::Maketext::Extract::Plugin::Base;
use strict;
use File::Basename qw(fileparse);
=head1 NAME
Locale::Maketext::Extract::Plugin::Base - Base module for format parser plugins
=head1 SYNOPSIS
package My::Parser::Plugin;
use base qw(Locale::Maketext::Extract::Plugin::Base);
sub file_types {
return [qw( ext ext2 )]
}
sub extract {
my $self = shift;
local $_ = shift;
my $line = 1;
while (my $found = $self->routine_to_extract_strings) {
$self->add_entry($str,[$filename,$line,$vars])
}
return;
}
=head1 DESCRIPTION
All format parser plugins in Locale::Maketext::Extract inherit from
Locale::Maketext::Extract::Plugin::Base.
If you want to write your own custom parser plugin, you will need to inherit
from this module, and provide C<file_types()> and C<extract()> methods,
as shown above.
=head1 METHODS
=over 4
=item new()
$plugin = My::Parser->new(
@file_types # Optionally specify a list of recognised file types
)
=cut
sub new {
my $class = shift;
my $self = bless {
entries => [],
}, $class;
$self->_compile_file_types(@_);
return $self;
}
=item add_entry()
$plugin->add_entry($str,$line,$vars)
=cut
sub add_entry {
my $self = shift;
push @{$self->{entries}},[@_];
}
=item C<entries()>
$entries = $plugin->entries;
=cut
#===================================
sub entries {
#===================================
my $self = shift;
return $self->{entries};
}
=item C<clear()>
$plugin->clear
Clears all stored entries.
=cut
#===================================
sub clear {
#===================================
my $self = shift;
$self->{entries}=[];
}
=item file_types()
@default_file_types = $plugin->file_types
Returns a list of recognised file types that your module knows how to parse.
Each file type can be one of:
=over 4
=item * A plain string
'pl' => base filename is matched against qr/\.pl$/
'*' => all files are accepted
=item * A regex
qr/\.tt2?\./ => base filename is matched against this regex
=item * A codref
sub {} => this codref is called as $coderef->($base_filename,$path_to_file)
It should return true or false
=back
=cut
sub file_types {
die "Please override sub file_types() to return "
. "a list of recognised file extensions, or regexes";
}
=item extract()
$plugin->extract($filecontents);
extract() is the method that will be called to process the contents of the
current file.
When it finds a string that should be extracted, it should call
$self->add_entry($string,$line,$vars])
where C<$vars> refers to any arguments that are being passed to the localise
function. For instance:
l("You found [quant,_1,file,files]",files_found)
string: "You found [quant,_1,file,files]"
vars : (files_found)
IMPORTANT: a single plugin instance is used for all files, so if you plan
on storing state information in the C<$plugin> object, this should be cleared
out at the beginning of C<extract()>
=cut
sub extract {
die "Please override sub extract()";
}
sub _compile_file_types {
my $self = shift;
my @file_types
= ref $_[0] eq 'ARRAY'
? @{ shift @_ }
: @_;
@file_types = $self->file_types
unless @file_types;
my @checks;
if ( grep { $_ eq '*' } @file_types ) {
$self->{file_checks} = [ sub {1} ];
return;
}
foreach my $type (@file_types) {
if ( ref $type eq 'CODE' ) {
push @checks, $type;
next;
}
else {
my $regex
= ref $type
? $type
: qr/^.*\.\Q$type\E$/;
push @checks, sub { $_[0] =~ m/$regex/ };
}
}
$self->{file_checks} = \@checks;
}
=item known_file_type()
if ($plugin->known_file_type($filename_with_path)) {
....
}
Determines whether the current file should be handled by this parser, based
either on the list of file_types specified when this object was created,
or the default file_types specified in the module.
=cut
sub known_file_type {
my $self = shift;
my ( $name, $path ) = fileparse( shift @_ );
foreach my $check ( @{ $self->{file_checks} } ) {
return 1 if $check->( $name, $path );
}
return 0;
}
=back
=head1 SEE ALSO
=over 4
=item L<xgettext.pl>
for extracting translatable strings from common template
systems and perl source files.
=item L<Locale::Maketext::Lexicon>
=item L<Locale::Maketext::Extract::Plugin::Perl>
=item L<Locale::Maketext::Extract::Plugin::PPI>
=item L<Locale::Maketext::Extract::Plugin::TT2>
=item L<Locale::Maketext::Extract::Plugin::YAML>
=item L<Locale::Maketext::Extract::Plugin::FormFu>
=item L<Locale::Maketext::Extract::Plugin::Mason>
=item L<Locale::Maketext::Extract::Plugin::TextTemplate>
=item L<Locale::Maketext::Extract::Plugin::Generic>
=back
=head1 AUTHORS
Clinton Gormley [DRTECH] E<lt>clinton@traveljury.comE<gt>
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
1;
LOCALE_MAKETEXT_EXTRACT_PLUGIN_BASE
$fatpacked{"Locale/Maketext/Extract/Plugin/FormFu.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_PLUGIN_FORMFU';
package Locale::Maketext::Extract::Plugin::FormFu;
use strict;
use base qw(Locale::Maketext::Extract::Plugin::Base);
=head1 NAME
Locale::Maketext::Extract::Plugin::FormFu - FormFu format parser
=head1 SYNOPSIS
$plugin = Locale::Maketext::Extract::Plugin::FormFu->new(
$lexicon # A Locale::Maketext::Extract object
@file_types # Optionally specify a list of recognised file types
)
$plugin->extract($filename,$filecontents);
=head1 DESCRIPTION
HTML::FormFu uses a config-file to generate forms, with built in support
for localizing errors, labels etc.
=head1 SHORT PLUGIN NAME
formfu
=head1 VALID FORMATS
We extract the text after any key which ends in C<_loc>:
content_loc: this is the string
message_loc: ['Max length [_1]', 10]
=head1 KNOWN FILE TYPES
=over 4
=item .yaml
=item .yml
=item .conf
=back
=head1 REQUIRES
L<YAML>
=head1 NOTES
The docs for the YAML module describes it as alpha code. It is not as tolerant
of errors as L<YAML::Syck>. However, because it is pure Perl, it is easy
to hook into.
I have seen it enter endless loops, so if xgettext.pl hangs, try running it
again with C<--verbose --verbose> (twice) enabled, so that you can see if
the fault lies with YAML. If it does, either correct the YAML source file,
or use the file_types to exclude that file.
=cut
sub file_types {
return qw( yaml yml conf );
}
sub extract {
my $self = shift;
my $data = shift;
my $y = Locale::Maketext::Extract::Plugin::FormFu::Extractor->new();
$y->load($data);
foreach my $entry ( @{ $y->found } ) {
$self->add_entry(@$entry);
}
}
package Locale::Maketext::Extract::Plugin::FormFu::Extractor;
use base qw(YAML::Loader);
#===================================
sub new {
#===================================
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{found} = [];
return $self;
}
#===================================
sub _check_key {
#===================================
my $self = shift;
my ( $key, $value, $line ) = @_;
my ( $str, $vars );
if ( ref $value ) {
return if ref $value ne 'ARRAY';
$str = shift @$value;
$vars = join( ', ', @$value );
}
else {
$str = $value;
}
return
unless $key
&& $key =~ /_loc$/
&& defined $str;
push @{ $self->{found} }, [ $str, $line, $vars ];
}
#===================================
sub _parse_mapping {
#===================================
my $self = shift;
my ($anchor) = @_;
my $mapping = {};
$self->anchor2node->{$anchor} = $mapping;
my $key;
while ( not $self->done
and $self->indent == $self->offset->[ $self->level ] )
{
# If structured key:
if ( $self->{content} =~ s/^\?\s*// ) {
$self->preface( $self->content );
$self->_parse_next_line(YAML::Loader::COLLECTION);
$key = $self->_parse_node();
$key = "$key";
}
# If "default" key (equals sign)
elsif ( $self->{content} =~ s/^\=\s*// ) {
$key = YAML::Loader::VALUE;
}
# If "comment" key (slash slash)
elsif ( $self->{content} =~ s/^\=\s*// ) {
$key = YAML::Loader::COMMENT;
}
# Regular scalar key:
else {
$self->inline( $self->content );
$key = $self->_parse_inline();
$key = "$key";
$self->content( $self->inline );
$self->inline('');
}
unless ( $self->{content} =~ s/^:\s*// ) {
$self->die('YAML_LOAD_ERR_BAD_MAP_ELEMENT');
}
$self->preface( $self->content );
my $line = $self->line;
$self->_parse_next_line(YAML::Loader::COLLECTION);
my $value = $self->_parse_node();
if ( exists $mapping->{$key} ) {
$self->warn('YAML_LOAD_WARN_DUPLICATE_KEY');
}
else {
$mapping->{$key} = $value;
$self->_check_key( $key, $value, $line );
}
}
return $mapping;
}
#===================================
sub _parse_inline_mapping {
#===================================
my $self = shift;
my ($anchor) = @_;
my $node = {};
my $start_line = $self->{_start_line};
$self->anchor2node->{$anchor} = $node;
$self->die('YAML_PARSE_ERR_INLINE_MAP')
unless $self->{inline} =~ s/^\{\s*//;
while ( not $self->{inline} =~ s/^\s*\}// ) {
my $key = $self->_parse_inline();
$self->die('YAML_PARSE_ERR_INLINE_MAP')
unless $self->{inline} =~ s/^\: \s*//;
my $value = $self->_parse_inline();
if ( exists $node->{$key} ) {
$self->warn('YAML_LOAD_WARN_DUPLICATE_KEY');
}
else {
$node->{$key} = $value;
$self->_check_key( $key, $value, $start_line );
}
next if $self->inline =~ /^\s*\}/;
$self->die('YAML_PARSE_ERR_INLINE_MAP')
unless $self->{inline} =~ s/^\,\s*//;
}
return $node;
}
#===================================
sub _parse_next_line {
#===================================
my $self = shift;
$self->{_start_line} = $self->line;
$self->SUPER::_parse_next_line(@_);
}
#===================================
sub found {
#===================================
my $self = shift;
return $self->{found};
}
=head1 SEE ALSO
=over 4
=item L<xgettext.pl>
for extracting translatable strings from common template
systems and perl source files.
=item L<YAML>
=item L<HTML::FormFu>
=item L<Locale::Maketext::Lexicon>
=item L<Locale::Maketext::Extract::Plugin::Base>
=item L<Locale::Maketext::Extract::Plugin::Perl>
=item L<Locale::Maketext::Extract::Plugin::TT2>
=item L<Locale::Maketext::Extract::Plugin::YAML>
=item L<Locale::Maketext::Extract::Plugin::Mason>
=item L<Locale::Maketext::Extract::Plugin::TextTemplate>
=item L<Locale::Maketext::Extract::Plugin::Generic>
=back
=head1 AUTHORS
Clinton Gormley E<lt>clint@traveljury.comE<gt>
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
1;
LOCALE_MAKETEXT_EXTRACT_PLUGIN_FORMFU
$fatpacked{"Locale/Maketext/Extract/Plugin/Generic.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_PLUGIN_GENERIC';
package Locale::Maketext::Extract::Plugin::Generic;
use strict;
use base qw(Locale::Maketext::Extract::Plugin::Base);
=head1 NAME
Locale::Maketext::Extract::Plugin::Generic - Generic template parser
=head1 SYNOPSIS
$plugin = Locale::Maketext::Extract::Plugin::Generic->new(
$lexicon # A Locale::Maketext::Extract object
@file_types # Optionally specify a list of recognised file types
)
$plugin->extract($filename,$filecontents);
=head1 DESCRIPTION
Extracts strings to localise from generic templates.
=head1 SHORT PLUGIN NAME
generic
=head1 VALID FORMATS
Strings inside {{...}} are extracted.
=head1 KNOWN FILE TYPES
=over 4
=item All file types
=back
=cut
sub file_types {
return qw( * );
}
sub extract {
my $self = shift;
local $_ = shift;
my $line = 1;
# Generic Template:
$line = 1; pos($_) = 0;
while (m/\G(.*?(?<!\{)\{\{(?!\{)(.*?)\}\})/sg) {
my ($vars, $str) = ('', $2);
$line += ( () = ($1 =~ /\n/g) ); # cryptocontext!
$self->add_entry($str, $line, $vars );
}
my $quoted = '(\')([^\\\']*(?:\\.[^\\\']*)*)(\')|(\")([^\\\"]*(?:\\.[^\\\"]*)*)(\")';
# Comment-based mark: "..." # loc
$line = 1; pos($_) = 0;
while (m/\G(.*?($quoted)[\}\)\],;]*\s*\#\s*loc\s*$)/smog) {
my $str = substr($2, 1, -1);
$line += ( () = ( $1 =~ /\n/g ) ); # cryptocontext!
$str =~ s/\\(["'])/$1/g;
$self->add_entry($str, $line, '' );
}
# Comment-based pair mark: "..." => "..." # loc_pair
$line = 1; pos($_) = 0;
while (m/\G(.*?(\w+)\s*=>\s*($quoted)[\}\)\],;]*\s*\#\s*loc_pair\s*$)/smg) {
my $key = $2;
my $val = substr($3, 1, -1);
$line += ( () = ( $1 =~ /\n/g ) ); # cryptocontext!
$key =~ s/\\(["'])/$1/g;
$val =~ s/\\(["'])/$1/g;
$self->add_entry($val, $line, '' );
}
}
=head1 SEE ALSO
=over 4
=item L<xgettext.pl>
for extracting translatable strings from common template
systems and perl source files.
=item L<Locale::Maketext::Lexicon>
=item L<Locale::Maketext::Extract::Plugin::Base>
=item L<Locale::Maketext::Extract::Plugin::FormFu>
=item L<Locale::Maketext::Extract::Plugin::Perl>
=item L<Locale::Maketext::Extract::Plugin::TT2>
=item L<Locale::Maketext::Extract::Plugin::YAML>
=item L<Locale::Maketext::Extract::Plugin::Mason>
=item L<Locale::Maketext::Extract::Plugin::TextTemplate>
=back
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
1;
LOCALE_MAKETEXT_EXTRACT_PLUGIN_GENERIC
$fatpacked{"Locale/Maketext/Extract/Plugin/Mason.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_PLUGIN_MASON';
package Locale::Maketext::Extract::Plugin::Mason;
use strict;
use base qw(Locale::Maketext::Extract::Plugin::Base);
=head1 NAME
Locale::Maketext::Extract::Plugin::Mason - HTML::Mason (aka Mason 1) and Mason
(aka Mason 2) format parser
=head1 SYNOPSIS
$plugin = Locale::Maketext::Extract::Plugin::Mason->new(
$lexicon # A Locale::Maketext::Extract object
@file_types # Optionally specify a list of recognised file types
)
$plugin->extract($filename,$filecontents);
=head1 DESCRIPTION
Extracts strings to localise from Mason files.
=head1 SHORT PLUGIN NAME
mason
=head1 VALID FORMATS
HTML::Mason (aka Mason 1)
Strings inside <&|/l>...</&> and <&|/loc>...</&> are extracted.
Mason (aka Mason 2)
Strings inside <% $.floc { %>...</%> or <% $.fl { %>...</%> or
<% $self->floc { %>...</%> or <% $self->fl { %>...</%> are extracted.
=head1 KNOWN FILE TYPES
=over 4
=item All file types
=back
=cut
sub file_types {
return qw( * );
}
sub extract {
my $self = shift;
local $_ = shift;
my $line = 1;
# HTML::Mason (aka Mason 1)
while (m!\G(.*?<&\|[ ]*/l(?:oc)?(?:[ ]*,[ ]*(.*?))?[ ]*&>(.*?)</&>)!sg) {
my ( $vars, $str ) = ( $2, $3 );
$line += ( () = ( $1 =~ /\n/g ) ); # cryptocontext!
$self->add_entry( $str, $line, $vars );
}
# Mason (aka Mason 2)
while (
m!\G(.*?<%[ ]*(?:\$(?:\.|self->))fl(?:oc)?(?:[ ]*\((.*?)\))?[ ]*{[ ]*%>(.*?)</%>)!sg
)
{
my ( $vars, $str ) = ( $2, $3 );
$line += ( () = ( $1 =~ /\n/g ) ); # cryptocontext!
$self->add_entry( $str, $line, $vars );
}
}
=head1 SEE ALSO
=over 4
=item L<xgettext.pl>
for extracting translatable strings from common template
systems and perl source files.
=item L<Locale::Maketext::Lexicon>
=item L<Locale::Maketext::Extract::Plugin::Base>
=item L<Locale::Maketext::Extract::Plugin::FormFu>
=item L<Locale::Maketext::Extract::Plugin::Perl>
=item L<Locale::Maketext::Extract::Plugin::TT2>
=item L<Locale::Maketext::Extract::Plugin::YAML>
=item L<Locale::Maketext::Extract::Plugin::TextTemplate>
=item L<Locale::Maketext::Extract::Plugin::Generic>
=back
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
1;
LOCALE_MAKETEXT_EXTRACT_PLUGIN_MASON
$fatpacked{"Locale/Maketext/Extract/Plugin/PPI.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_PLUGIN_PPI';
package Locale::Maketext::Extract::Plugin::PPI;
use strict;
use base qw(Locale::Maketext::Extract::Plugin::Base);
use PPI();
=head1 NAME
Locale::Maketext::Extract::Plugin::PPI - Perl format parser
=head1 SYNOPSIS
$plugin = Locale::Maketext::Extract::Plugin::PPI->new(
$lexicon # A Locale::Maketext::Extract object
@file_types # Optionally specify a list of recognised file types
)
$plugin->extract($filename,$filecontents);
=head1 DESCRIPTION
Does exactly the same thing as the L<Locale::Maketext::Extract::Plugin::Perl>
parser, but more accurately, and more slowly. Considerably more slowly! For this
reason it isn't a built-in plugin.
=head1 SHORT PLUGIN NAME
none - the module must be specified in full
=head1 VALID FORMATS
Valid localization function names are:
=over 4
=item translate
=item maketext
=item gettext
=item loc
=item x
=item _
=item __
=back
=head1 KNOWN FILE TYPES
=over 4
=item .pm
=item .pl
=item .cgi
=back
=cut
sub file_types {
return qw( pm pl cgi );
}
my %subnames = map { $_ => 1 } qw (translate maketext gettext loc x __);
#===================================
sub extract {
#===================================
my $self = shift;
my $text = shift;
my $doc = PPI::Document->new( \$text, index_locations => 1 );
foreach my $statement ( @{ $doc->find('PPI::Statement') } ) {
my @children = $statement->schildren;
while ( my $child = shift @children ) {
next
unless @children
&& ( $child->isa('PPI::Token::Word')
&& $subnames{ $child->content }
|| $child->isa('PPI::Token::Magic')
&& $child->content eq '_' );
my $list = shift @children;
next
unless $list->isa('PPI::Structure::List')
&& $list->schildren;
$self->_check_arg_list($list);
}
}
}
#===================================
sub _check_arg_list {
#===================================
my $self = shift;
my $list = shift;
my @args = ( $list->schildren )[0]->schildren;
my $final_string = '';
my ( $line, $mode );
while ( my $string_el = shift @args ) {
return
unless $string_el->isa('PPI::Token::Quote')
|| $string_el->isa('PPI::Token::HereDoc');
$line ||= $string_el->location->[0];
my $string;
if ( $string_el->isa('PPI::Token::HereDoc') ) {
$string = join( '', $string_el->heredoc );
$mode
= $string_el->{_mode} eq 'interpolate'
? 'double'
: 'literal';
}
else {
$string = $string_el->string;
$mode
= $string_el->isa('PPI::Token::Quote::Literal') ? 'literal'
: ( $string_el->isa('PPI::Token::Quote::Double')
|| $string_el->isa('PPI::Token::Quote::Interpolate') )
? 'double'
: 'single';
}
if ( $mode eq 'double' ) {
return
if !!( $string =~ /(?<!\\)(?:\\\\)*[\$\@]/ );
$string = eval qq("$string");
}
elsif ( $mode eq 'single' ) {
$string =~ s/\\'/'/g;
}
# $string =~ s/(?<!\\)\\//g;
$string =~ s/\\\\/\\/g;
# unless $mode eq 'literal';
$final_string .= $string;
my $next_op = shift @args;
last
unless $next_op
&& $next_op->isa('PPI::Token::Operator')
&& $next_op->content eq '.';
}
return unless $final_string;
my $vars = join( '', map { $_->content } @args );
$self->add_entry( $final_string, $line, $vars );
}
=head1 SEE ALSO
=over 4
=item L<xgettext.pl>
for extracting translatable strings from common template
systems and perl source files.
=item L<Locale::Maketext::Lexicon>
=item L<Locale::Maketext::Extract::Plugin::Base>
=item L<Locale::Maketext::Extract::Plugin::Perl>
=item L<Locale::Maketext::Extract::Plugin::FormFu>
=item L<Locale::Maketext::Extract::Plugin::Perl>
=item L<Locale::Maketext::Extract::Plugin::TT2>
=item L<Locale::Maketext::Extract::Plugin::YAML>
=item L<Locale::Maketext::Extract::Plugin::TextTemplate>
=item L<Locale::Maketext::Extract::Plugin::Generic>
=back
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
1;
LOCALE_MAKETEXT_EXTRACT_PLUGIN_PPI
$fatpacked{"Locale/Maketext/Extract/Plugin/Perl.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_PLUGIN_PERL';
package Locale::Maketext::Extract::Plugin::Perl;
use strict;
use base qw(Locale::Maketext::Extract::Plugin::Base);
=head1 NAME
Locale::Maketext::Extract::Plugin::Perl - Perl format parser
=head1 SYNOPSIS
$plugin = Locale::Maketext::Extract::Plugin::Perl->new(
$lexicon # A Locale::Maketext::Extract object
@file_types # Optionally specify a list of recognised file types
)
$plugin->extract($filename,$filecontents);
=head1 DESCRIPTION
Extracts strings to localise (including HEREDOCS and
concatenated strings) from Perl code.
This Perl parser is very fast and very good, but not perfect - it does make
mistakes. The PPI parser (L<Locale::Maketext::Extract::Plugin::PPI>) is more
accurate, but a lot slower, and so is not enabled by default.
=head1 SHORT PLUGIN NAME
perl
=head1 VALID FORMATS
Valid localization function names are:
=over 4
=item translate
=item maketext
=item gettext
=item loc
=item x
=item _
=item __
=back
=head1 KNOWN FILE TYPES
=over 4
=item .pm
=item .pl
=item .cgi
=back
=cut
use constant NUL => 0;
use constant BEG => 1;
use constant PAR => 2;
use constant HERE => 10;
use constant QUO1 => 3;
use constant QUO2 => 4;
use constant QUO3 => 5;
use constant QUO4 => 6;
use constant QUO5 => 7;
use constant QUO6 => 8;
use constant QUO7 => 9;
sub file_types {
return qw( pm pl cgi );
}
sub extract {
my $self = shift;
local $_ = shift;
local $SIG{__WARN__} = sub { die @_ };
# Perl code:
my ( $state, $line_offset, $str, $str_part, $vars, $quo, $heredoc )
= ( 0, 0 );
my $orig = 1 + ( () = ( ( my $__ = $_ ) =~ /\n/g ) );
PARSER: {
$_ = substr( $_, pos($_) ) if ( pos($_) );
my $line = $orig - ( () = ( ( my $__ = $_ ) =~ /\n/g ) );
# various ways to spell the localization function
$state == NUL
&& m/\b(translate|maketext|gettext|__?|loc(?:ali[sz]e)?|x)/gc
&& do { $state = BEG; redo };
$state == BEG && m/^([\s\t\n]*)/gc && redo;
# begin ()
$state == BEG
&& m/^([\S\(])\s*/gc
&& do { $state = ( ( $1 eq '(' ) ? PAR : NUL ); redo };
# concat
$state == PAR
&& defined($str)
&& m/^(\s*\.\s*)/gc
&& do { $line_offset += ( () = ( ( my $__ = $1 ) =~ /\n/g ) ); redo };
# str_part
$state == PAR && defined($str_part) && do {
if ( ( $quo == QUO1 ) || ( $quo == QUO5 ) ) {
$str_part =~ s/\\([\\'])/$1/g
if ($str_part); # normalize q strings
}
elsif ( $quo != QUO6 ) {
$str_part =~ s/(\\(?:[0x]..|c?.))/"qq($1)"/eeg
if ($str_part); # normalize qq / qx strings
}
$str .= $str_part;
undef $str_part;
undef $quo;
redo;
};
# begin or end of string
$state == PAR && m/^(\')/gc && do { $state = $quo = QUO1; redo };
$state == QUO1 && m/^([^'\\]+)/gc && do { $str_part .= $1; redo };
$state == QUO1 && m/^((?:\\.)+)/gcs && do { $str_part .= $1; redo };
$state == QUO1 && m/^\'/gc && do { $state = PAR; redo };
$state == PAR && m/^\"/gc && do { $state = $quo = QUO2; redo };
$state == QUO2 && m/^([^"\\]+)/gc && do { $str_part .= $1; redo };
$state == QUO2 && m/^((?:\\.)+)/gcs && do { $str_part .= $1; redo };
$state == QUO2 && m/^\"/gc && do { $state = PAR; redo };
$state == PAR && m/^\`/gc && do { $state = $quo = QUO3; redo };
$state == QUO3 && m/^([^\`]*)/gc && do { $str_part .= $1; redo };
$state == QUO3 && m/^\`/gc && do { $state = PAR; redo };
$state == PAR && m/^qq\{/gc && do { $state = $quo = QUO4; redo };
$state == QUO4 && m/^([^\}]*)/gc && do { $str_part .= $1; redo };
$state == QUO4 && m/^\}/gc && do { $state = PAR; redo };
$state == PAR && m/^q\{/gc && do { $state = $quo = QUO5; redo };
$state == QUO5 && m/^([^\}]*)/gc && do { $str_part .= $1; redo };
$state == QUO5 && m/^\}/gc && do { $state = PAR; redo };
# find heredoc terminator, then get the
#heredoc and go back to current position
$state == PAR
&& m/^<<\s*\'/gc
&& do { $state = $quo = QUO6; $heredoc = ''; redo };
$state == QUO6 && m/^([^'\\\n]+)/gc && do { $heredoc .= $1; redo };
$state == QUO6 && m/^((?:\\.)+)/gc && do { $heredoc .= $1; redo };
$state == QUO6
&& m/^\'/gc
&& do { $state = HERE; $heredoc =~ s/\\\'/\'/g; redo };
$state == PAR
&& m/^<<\s*\"/gc
&& do { $state = $quo = QUO7; $heredoc = ''; redo };
$state == QUO7 && m/^([^"\\\n]+)/gc && do { $heredoc .= $1; redo };
$state == QUO7 && m/^((?:\\.)+)/gc && do { $heredoc .= $1; redo };
$state == QUO7
&& m/^\"/gc
&& do { $state = HERE; $heredoc =~ s/\\\"/\"/g; redo };
$state == PAR
&& m/^<<(\w*)/gc
&& do { $state = HERE; $quo = QUO7; $heredoc = $1; redo };
# jump ahaid and get the heredoc, then s/// also
# resets the pos and we are back at the current pos
$state == HERE
&& m/^.*\r?\n/gc
&& s/\G(.*?\r?\n)$heredoc(\r?\n)//s
&& do { $state = PAR; $str_part .= $1; $line_offset++; redo };
# end ()
#
$state == PAR && m/^\s*[\)]/gc && do {
$state = NUL;
$vars =~ s/[\n\r]//g if ($vars);
$self->add_entry( $str,
$line - ( () = $str =~ /\n/g ) - $line_offset,
$vars )
if $str;
undef $str;
undef $vars;
undef $heredoc;
$line_offset = 0;
redo;
};
# a line of vars
$state == PAR && m/^([^\)]*)/gc && do { $vars .= "$1\n"; redo };
}
}
=head1 SEE ALSO
=over 4
=item L<xgettext.pl>
for extracting translatable strings from common template
systems and perl source files.
=item L<Locale::Maketext::Lexicon>
=item L<Locale::Maketext::Extract::Plugin::Base>
=item L<Locale::Maketext::Extract::Plugin::PPI>
=item L<Locale::Maketext::Extract::Plugin::FormFu>
=item L<Locale::Maketext::Extract::Plugin::TT2>
=item L<Locale::Maketext::Extract::Plugin::YAML>
=item L<Locale::Maketext::Extract::Plugin::Mason>
=item L<Locale::Maketext::Extract::Plugin::TextTemplate>
=item L<Locale::Maketext::Extract::Plugin::Generic>
=back
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
1;
LOCALE_MAKETEXT_EXTRACT_PLUGIN_PERL
$fatpacked{"Locale/Maketext/Extract/Plugin/TT2.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_PLUGIN_TT2';
package Locale::Maketext::Extract::Plugin::TT2;
use strict;
use base qw(Locale::Maketext::Extract::Plugin::Base);
use Template::Constants qw( :debug );
use Template::Parser;
=head1 NAME
Locale::Maketext::Extract::Plugin::TT2 - Template Toolkit format parser
=head1 SYNOPSIS
$plugin = Locale::Maketext::Extract::Plugin::TT2->new(
$lexicon # A Locale::Maketext::Extract object
@file_types # Optionally specify a list of recognised file types
)
$plugin->extract($filename,$filecontents);
=head1 DESCRIPTION
Extracts strings to localise from Template Toolkit templates.
=head1 SHORT PLUGIN NAME
tt2
=head1 VALID FORMATS
Valid formats are:
=over 4
=item [% |l(args) %]string[% END %]
=item [% 'string' | l(args) %]
=item [% l('string',args) %]
=item [% c.l('string') %]
Also all the above combinations with C<c.> prepended should work
correctly. This is the default syntax when using TT templates
with L<Mojolicious>.
=back
l and loc are interchangeable.
| and FILTER are interchangeable.
=head1 KNOWN FILE TYPES
=over 4
=item .tt
=item .tt2
=item .html
=item .tt.*
=item .tt2.*
=back
=head1 REQUIRES
L<Template>
=head1 NOTES
=over 4
=item *
B<BEWARE> Using the C<loc> form can give false positives if you use the Perl parser
plugin on TT files. If you want to use the C<loc> form, then you should
specify the file types that you want to the Perl plugin to parse, or enable
the default file types, eg:
xgetext.pl -P perl .... # default file types
xgettext.pl -P perl=pl,pm ... # specified file types
=item *
The string-to-be-localised must be a string, not a variable. We try not
to extract calls to your localise function which contain variables eg:
l('string',arg) # extracted
l(var,arg) # not extracted
This doesn't work for block filters, so don't do that. Eg:
[% FILTER l %]
string [% var %] # BAD!
[% END %]
=item *
Getting the right line number is difficult in TT. Often it'll be a range
of lines, or it may be thrown out by the use of PRE_CHOMP or POST_CHOMP. It will
always be within a few lines of the correct location.
=item *
If you have PRE/POST_CHOMP enabled by default in your templates, then you should
extract the strings using the same values. In order to set them, you can
use the following wrapper script:
#!/usr/bin/perl
use Locale::Maketext::Extract::Run qw(xgettext);
use Locale::Maketext::Extract::Plugin::TT2();
%Locale::Maketext::Extract::Plugin::TT2::PARSER_OPTIONS = (
PRE_CHOMP => 1, # or 2
POST_CHOMP => 1, # or 2
# Also START/END_TAG, ANYCASE, INTERPOLATE, V1DOLLAR, EVAL_PERL
);
xgettext(@ARGV);
=back
=cut
# import strip_quotes
*strip_quotes
= \&Locale::Maketext::Extract::Plugin::TT2::Directive::strip_quotes;
our %PARSER_OPTIONS;
#===================================
sub file_types {
#===================================
return ( qw( tt tt2 html ), qr/\.tt2?\./ );
}
my %Escapes = map { ( "\\$_" => eval("qq(\\$_)") ) } qw(t n r f b a e);
#===================================
sub extract {
#===================================
my $self = shift;
my $data = shift;
$Template::Directive::PRETTY = 1;
my $parser =
Locale::Maketext::Extract::Plugin::TT2::Parser->new(
%PARSER_OPTIONS,
FACTORY => 'Locale::Maketext::Extract::Plugin::TT2::Directive',
FILE_INFO => 0,
);
_init_overrides($parser);
$parser->{extracted} = [];
$Locale::Maketext::Extract::Plugin::TT2::Directive::PARSER
= $parser; # hack
$parser->parse($data)
|| die $parser->error;
foreach my $entry ( @{ $parser->{extracted} } ) {
$entry->[2] =~ s/^\((.*)\)$/$1/s; # Remove () from vars
$_ =~ s/\\'/'/gs # Unescape \'
for @{$entry}[ 0, 2 ];
$entry->[2] =~ s/\\(?!")/\\\\/gs; # Escape all \ not followed by "
# Escape argument lists correctly
while ( my ( $char, $esc ) = each %Escapes ) {
$entry->[2] =~ s/$esc/$char/g;
}
$entry->[1] =~ s/\D+.*$//;
$self->add_entry(@$entry);
}
}
#===================================
sub _init_overrides {
#===================================
my $parser = shift;
# Override the concatenation sub to return _ instead of .
my $states = $parser->{STATES};
foreach my $state ( @{$states} ) {
if ( my $CAT_no = $state->{ACTIONS}{CAT} ) {
my $CAT_rule_no
= $states->[ $states->[$CAT_no]{GOTOS}{expr} ]->{DEFAULT};
# override the TT::Grammar sub which cats two args
$parser->{RULES}[ -$CAT_rule_no ][2] = sub {
my $first = ( $_[1] );
my $second = ( $_[3] );
if ( strip_quotes($first) && strip_quotes($second) ) {
# both are literal
return "'${first}${second}'";
}
else {
# at least one is an ident
return "$_[1] _ $_[3]";
}
};
last;
}
}
}
#===================================
#===================================
package Locale::Maketext::Extract::Plugin::TT2::Parser;
#===================================
#===================================
use base 'Template::Parser';
# disabled location() because it was adding unneccessary text
# to filter blocks
#===================================
sub location {''}
#===================================
# Custom TT parser for Locale::Maketext::Lexicon
#
# Written by Andy Wardley http://wardley.org/
#
# 18 September 2008
#
#-----------------------------------------------------------------------
# custom directive generator to capture filters, variables and
# massage a few other elements to make life easy.
#-----------------------------------------------------------------------
#===================================
#===================================
package Locale::Maketext::Extract::Plugin::TT2::Directive;
#===================================
#===================================
use base 'Template::Directive';
our $PARSER;
#===================================
sub textblock {
#===================================
my ( $class, $text ) = @_;
$text =~ s/([\\'])/\\$1/g;
return "'$text'";
}
#===================================
sub ident {
#===================================
my ( $class, $ident ) = @_;
return "NULL" unless @$ident;
if ( scalar @$ident <= 2 && !$ident->[1] ) {
my $var = $ident->[0];
$var =~ s/^'(.+)'$/$1/;
return $var;
}
else {
my @source = @$ident;
my @dotted;
my $first = 1;
my $first_literal;
while (@source) {
my ( $name, $args ) = splice( @source, 0, 2 );
if ($first) {
strip_quotes($name);
my $first_arg = $args && @$args ? $args->[0] : '';
$first_literal = strip_quotes($first_arg);
$first--;
}
elsif ( !strip_quotes($name) && $name =~ /\D/ ) {
$name = '$' . $name;
}
$name .= join_args($args);
push( @dotted, $name );
}
my $got_i18n = 0;
# Classic TT syntax [% l('...') %] or [% loc('....') %]
if ( $first_literal
&& ( $ident->[0] eq "'l'" or $ident->[0] eq "'loc'" ) )
{
$got_i18n = 1;
}
# Mojolicious TT syntax [% c.l('...') %]
elsif ($ident->[0] eq "'c'" && $ident->[2] eq "'l'")
{
$got_i18n = 1;
splice(@$ident, 0, 2);
}
if ($got_i18n) {
my $string = shift @{ $ident->[1] };
strip_quotes($string);
$string =~ s/\\\\/\\/g;
my $args = join_args( $ident->[1] );
push @{ $PARSER->{extracted} },
[ $string, ${ $PARSER->{LINE} }, $args ];
}
return join( '.', @dotted );
}
}
#===================================
sub text {
#===================================
my ( $class, $text ) = @_;
$text =~ s/\\/\\\\/g;
return "'$text'";
}
#===================================
sub quoted {
#===================================
my ( $class, $items ) = @_;
return '' unless @$items;
return ( $items->[0] ) if scalar @$items == 1;
return '(' . join( ' _ ', @$items ) . ')';
}
#===================================
sub args {
#===================================
my ( $class, $args ) = @_;
my $hash = shift @$args;
push( @$args, '{ ' . join( ', ', @$hash ) . ' }' ) # named params
if @$hash;
return $args;
}
#===================================
sub get {
#===================================
my ( $class, $expr ) = @_;
return $expr;
}
#===================================
sub filter {
#===================================
my ( $class, $lnameargs, $block ) = @_;
my ( $name, $args, $alias ) = @$lnameargs;
$name = $name->[0];
return ''
unless $name eq "'l'"
or $name eq "'loc'"
or $name eq "'c.l'";
if ( strip_quotes($block) ) {
$block =~ s/\\\\/\\/g;
$args = join_args( $class->args($args) );
# NOTE: line number is at end of block, and can be a range
my ($end) = ( ${ $PARSER->{LINE} } =~ /^(\d+)/ );
my $start = $end;
# rewind line count for newlines
$start -= $block =~ tr/\n//;
my $line = $start == $end ? $start : "$start-$end";
push @{ $PARSER->{extracted} }, [ $block, $line, $args ];
}
return '';
}
# strips outer single quotes from a string (modifies original string)
# returns true if stripped, or false
#===================================
sub strip_quotes {
#===================================
return scalar $_[0] =~ s/^'(.*)'$/$1/s;
}
#===================================
sub join_args {
#===================================
my $args = shift;
return '' unless $args && @$args;
my @new_args = (@$args);
for (@new_args) {
s/\\\\/\\/g;
if ( strip_quotes($_) ) {
s/"/\\"/g;
$_ = qq{"$_"};
}
}
return '(' . join( ', ', @new_args ) . ')';
}
=head1 ACKNOWLEDGEMENTS
Thanks to Andy Wardley for writing the Template::Directive subclass which
made this possible.
=head1 SEE ALSO
=over 4
=item L<xgettext.pl>
for extracting translatable strings from common template
systems and perl source files.
=item L<Locale::Maketext::Lexicon>
=item L<Locale::Maketext::Extract::Plugin::Base>
=item L<Locale::Maketext::Extract::Plugin::FormFu>
=item L<Locale::Maketext::Extract::Plugin::Perl>
=item L<Locale::Maketext::Extract::Plugin::YAML>
=item L<Locale::Maketext::Extract::Plugin::Mason>
=item L<Locale::Maketext::Extract::Plugin::TextTemplate>
=item L<Locale::Maketext::Extract::Plugin::Generic>
=item L<Template::Toolkit>
=back
=head1 AUTHORS
Clinton Gormley E<lt>clint@traveljury.comE<gt>
Andy Wardley http://wardley.org
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
1;
LOCALE_MAKETEXT_EXTRACT_PLUGIN_TT2
$fatpacked{"Locale/Maketext/Extract/Plugin/TextTemplate.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_PLUGIN_TEXTTEMPLATE';
package Locale::Maketext::Extract::Plugin::TextTemplate;
use strict;
use base qw(Locale::Maketext::Extract::Plugin::Base);
use vars qw($VERSION);
$VERSION = '0.31';
=head1 NAME
Locale::Maketext::Extract::Plugin::TextTemplate - Text::Template format parser
=head1 SYNOPSIS
$plugin = Locale::Maketext::Extract::Plugin::TextTemplate->new(
$lexicon # A Locale::Maketext::Extract object
@file_types # Optionally specify a list of recognised file types
)
$plugin->extract($filename,$filecontents);
=head1 DESCRIPTION
Extracts strings to localise from Text::Template files
=head1 SHORT PLUGIN NAME
text
=head1 VALID FORMATS
Sentences between STARTxxx and ENDxxx are extracted individually.
=head1 KNOWN FILE TYPES
=over 4
=item All file types
=back
=cut
sub file_types {
return qw( * );
}
sub extract {
my $self = shift;
local $_ = shift;
my $line = 1; pos($_) = 0;
# Text::Template
if ($_=~/^STARTTEXT$/m and $_=~ /^ENDTEXT$/m) {
require HTML::Parser;
require Lingua::EN::Sentence;
{
package Locale::Maketext::Extract::Plugin::TextTemplate::Parser;
our @ISA = 'HTML::Parser';
*{'text'} = sub {
my ($self, $str, $is_cdata) = @_;
my $sentences = Lingua::EN::Sentence::get_sentences($str) or return;
$str =~ s/\n/ /g; $str =~ s/^\s+//; $str =~ s/\s+$//;
$self->add_entry($str , $line);
};
}
my $p = Locale::Maketext::Extract::Plugin::TextTemplate::Parser->new;
while (m/\G((.*?)^(?:START|END)[A-Z]+$)/smg) {
my ($str) = ($2);
$line += ( () = ($1 =~ /\n/g) ); # cryptocontext!
$p->parse($str); $p->eof;
}
$_ = '';
}
}
=head1 SEE ALSO
=over 4
=item L<xgettext.pl>
for extracting translatable strings from common template
systems and perl source files.
=item L<Locale::Maketext::Lexicon>
=item L<Locale::Maketext::Extract::Plugin::Base>
=item L<Locale::Maketext::Extract::Plugin::FormFu>
=item L<Locale::Maketext::Extract::Plugin::Perl>
=item L<Locale::Maketext::Extract::Plugin::TT2>
=item L<Locale::Maketext::Extract::Plugin::YAML>
=item L<Locale::Maketext::Extract::Plugin::Mason>
=item L<Locale::Maketext::Extract::Plugin::Generic>
=back
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
1;
LOCALE_MAKETEXT_EXTRACT_PLUGIN_TEXTTEMPLATE
$fatpacked{"Locale/Maketext/Extract/Plugin/YAML.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_PLUGIN_YAML';
package Locale::Maketext::Extract::Plugin::YAML;
use strict;
use base qw(Locale::Maketext::Extract::Plugin::Base);
=head1 NAME
Locale::Maketext::Extract::Plugin::YAML - YAML format parser
=head1 SYNOPSIS
$plugin = Locale::Maketext::Extract::Plugin::YAML->new(
$lexicon # A Locale::Maketext::Extract object
@file_types # Optionally specify a list of recognised file types
)
$plugin->extract($filename,$filecontents);
=head1 DESCRIPTION
Extracts strings to localise from YAML files.
=head1 SHORT PLUGIN NAME
yaml
=head1 VALID FORMATS
Valid formats are:
=over 4
=item *
key: _"string"
=item *
key: _'string'
=item *
key: _'string with embedded 'quotes''
=item *
key: |-
_'my folded
string
to translate'
Note, the left hand side of the folded string must line up with the C<_>,
otherwise YAML adds spaces at the beginning of each line.
=item *
key: |-
_'my block
string
to translate
'
Note, you must use the trailing C<-> so that YAMl doesn't add a carriage
return after your final quote.
=back
=head1 KNOWN FILE TYPES
=over 4
=item .yaml
=item .yml
=item .conf
=back
=head1 REQUIRES
L<YAML>
=head1 NOTES
The docs for the YAML module describes it as alpha code. It is not as tolerant
of errors as L<YAML::Syck>. However, because it is pure Perl, it is easy
to hook into.
I have seen it enter endless loops, so if xgettext.pl hangs, try running it
again with C<--verbose --verbose> (twice) enabled, so that you can see if
the fault lies with YAML. If it does, either correct the YAML source file,
or use the file_types to exclude that file.
=cut
sub file_types {
return qw( yaml yml conf );
}
sub extract {
my $self = shift;
my $data = shift;
my $y = Locale::Maketext::Extract::Plugin::YAML::Extractor->new();
$y->load($data);
foreach my $entry (@{$y->found}) {
$self->add_entry(@$entry)
}
}
package Locale::Maketext::Extract::Plugin::YAML::Extractor;
use base qw(YAML::Loader);
#===================================
sub new {
#===================================
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{found} = [];
return $self;
}
#===================================
sub check_scalar {
#===================================
my $self = shift;
my $node = $_[0];
if ( defined $node && !ref $node && $node =~ /^__?(["'])(.+)\1$/s ) {
my $string = $2;
my $line = $_[1];
push @{ $self->{found} }, [ $string, $line ];
}
return $node;
}
sub _parse_node {
my $self = shift;
my $line = $self->{_start_line}||=length($self->preface) ? $self->line - 1 : $self->line;
my $node = $self->SUPER::_parse_node(@_);
$self->{start_line} = 0;
return $self->check_scalar($node,$line);
}
sub _parse_inline_seq {
my $self = shift;
my $line = $self->{_start_line}||=$self->line;
my $node = $self->SUPER::_parse_inline_seq(@_);
foreach (@$node) {
$self->check_scalar( $_, $line );
}
$self->{start_line} = 0;
return $node;
}
sub _parse_inline_mapping {
my $self = shift;
my $line = $self->{_start_line}||=$self->line;
my $node = $self->SUPER::_parse_inline_mapping(@_);
foreach ( values %$node ) {
$self->check_scalar( $_, $line );
}
$self->{start_line} = 0;
return $node;
}
#===================================
sub _parse_next_line {
#===================================
my $self = shift;
$self->{_start_line} = $self->line
if $_[0] == YAML::Loader::COLLECTION;
$self->SUPER::_parse_next_line(@_);
}
sub found {
my $self = shift;
return $self->{found};
}
=head1 SEE ALSO
=over 4
=item L<xgettext.pl>
for extracting translatable strings from common template
systems and perl source files.
=item L<YAML>
=item L<Locale::Maketext::Lexicon>
=item L<Locale::Maketext::Extract::Plugin::Base>
=item L<Locale::Maketext::Extract::Plugin::FormFu>
=item L<Locale::Maketext::Extract::Plugin::Perl>
=item L<Locale::Maketext::Extract::Plugin::TT2>
=item L<Locale::Maketext::Extract::Plugin::Mason>
=item L<Locale::Maketext::Extract::Plugin::TextTemplate>
=item L<Locale::Maketext::Extract::Plugin::Generic>
=back
=head1 AUTHORS
Clinton Gormley E<lt>clint@traveljury.comE<gt>
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
1;
LOCALE_MAKETEXT_EXTRACT_PLUGIN_YAML
$fatpacked{"Locale/Maketext/Extract/Run.pm"} = <<'LOCALE_MAKETEXT_EXTRACT_RUN';
package Locale::Maketext::Extract::Run;
$Locale::Maketext::Lexicon::Extract::Run::VERSION = '0.35';
use strict;
use vars qw( @ISA @EXPORT_OK );
use File::Spec::Functions qw(catfile);
=head1 NAME
Locale::Maketext::Extract::Run - Module interface to xgettext.pl
=head1 SYNOPSIS
use Locale::Maketext::Extract::Run 'xgettext';
xgettext(@ARGV);
=cut
use Cwd;
use Config ();
use File::Find;
use Getopt::Long;
use Locale::Maketext::Extract;
use Exporter;
use constant HAS_SYMLINK => ( $Config::Config{d_symlink} ? 1 : 0 );
@ISA = 'Exporter';
@EXPORT_OK = 'xgettext';
sub xgettext { __PACKAGE__->run(@_) }
sub run {
my $self = shift;
local @ARGV = @_;
my %opts;
Getopt::Long::Configure("no_ignore_case");
Getopt::Long::GetOptions( \%opts,
'f|files-from:s@',
'D|directory:s@',
'u|use-gettext-style|unescaped',
'g|gnu-gettext',
'o|output:s@',
'd|default-domain:s',
'p|output-dir:s@',
'P|plugin:s@',
'W|wrap!',
'w|warnings!',
'v|verbose+',
'h|help',
) or help();
help() if $opts{h};
my %extract_options = %{ $self->_parse_extract_options( \%opts ) };
my @po = @{ $opts{o} || [ ( $opts{d} || 'messages' ) . '.po' ] };
foreach my $file ( @{ $opts{f} || [] } ) {
open FILE, $file or die "Cannot open $file: $!";
while (<FILE>) {
chomp;
push @ARGV, $_ if -r and !-d;
}
}
foreach my $dir ( @{ $opts{D} || [] } ) {
File::Find::find( {
wanted => sub {
if (-d) {
$File::Find::prune
= /^(\.svn|blib|autogen|var|m4|local|CVS|\.git)$/;
return;
}
# Only extract from non-binary, normal files
return unless (-f or -s) and -T;
return
if (/\.po$|\.bak$|~|,D|,B$/i)
|| (/^[\.#]/);
push @ARGV, $File::Find::name;
},
follow => HAS_SYMLINK,
},
$dir
);
}
@ARGV = ('-') unless @ARGV;
s!^\.[/\\]!! for @ARGV;
my $cwd = getcwd();
my $Ext = Locale::Maketext::Extract->new(%extract_options);
foreach my $dir ( @{ $opts{p} || ['.'] } ) {
$Ext->extract_file($_) for grep !/\.po$/i, @ARGV;
foreach my $po (@po) {
$Ext->read_po($po) if -r $po and -s _;
$Ext->compile( $opts{u} ) or next;
$Ext->write_po( catfile( $dir, $po ), $opts{g} );
}
}
}
sub _parse_extract_options {
my $self = shift;
my $opts = shift;
# If a list of plugins is specified, then we use those modules
# plus their default list of file extensionse
# and warnings enabled by default
my %extract_options
= ( verbose => $opts->{v}, wrap => $opts->{W} || 0 );
if ( my $plugin_args = $opts->{P} ) {
# file extension with potentially multiple dots eg .tt.html
my %plugins;
foreach my $param (@$plugin_args) {
my ( $plugin, $args )
= ( $param =~ /^([a-z_]\w+(?:::\w+)*)(?:=(.+))?$/i );
die "Couldn't understand plugin option '$param'"
unless $plugin;
my @extensions;
if ($args) {
foreach my $arg ( split /,/, $args ) {
if ( $arg eq '*' ) {
@extensions = ('*');
last;
}
my ($extension) = ( $arg =~ /^\.?(\w+(?:\.\w+)*)$/ );
die "Couldn't understand '$arg' in plugin '$param'"
unless defined $extension;
push @extensions, $extension;
}
}
$plugins{$plugin} = \@extensions;
}
$extract_options{plugins} = \%plugins;
$extract_options{warnings} = exists $opts->{w} ? $opts->{w} : 1;
}
# otherwise we default to the original xgettext.pl modules
# with warnings disabled by default
else {
$extract_options{warnings} = $opts->{w};
}
return \%extract_options;
}
sub help {
local $SIG{__WARN__} = sub { };
{ exec "perldoc $0"; }
{ exec "pod2text $0"; }
}
1;
=head1 COPYRIGHT
Copyright 2003-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
LOCALE_MAKETEXT_EXTRACT_RUN
$fatpacked{"Locale/Maketext/Guts.pm"} = <<'LOCALE_MAKETEXT_GUTS';
package Locale::Maketext::Guts;
use Locale::Maketext;
our $VERSION = '1.19';
=head1 NAME
Locale::Maketext::Guts - Deprecated module to load Locale::Maketext utf8 code
=head1 SYNOPSIS
# Do this instead please
use Locale::Maketext
=head1 DESCRIPTION
Previously Local::Maketext::GutsLoader performed some magic to load
Locale::Maketext when utf8 was unavailable. The subs this module provided
were merged back into Locale::Maketext
=cut
1;
LOCALE_MAKETEXT_GUTS
$fatpacked{"Locale/Maketext/GutsLoader.pm"} = <<'LOCALE_MAKETEXT_GUTSLOADER';
package Locale::Maketext::GutsLoader;
use Locale::Maketext;
our $VERSION = '1.19';
sub zorp { return scalar @_ }
=head1 NAME
Locale::Maketext::GutsLoader - Deprecated module to load Locale::Maketext utf8 code
=head1 SYNOPSIS
# Do this instead please
use Locale::Maketext
=head1 DESCRIPTION
Previously Locale::Maketext::Guts performed some magic to load
Locale::Maketext when utf8 was unavailable. The subs this module provided
were merged back into Locale::Maketext.
=cut
1;
LOCALE_MAKETEXT_GUTSLOADER
$fatpacked{"Locale/Maketext/Lexicon.pm"} = <<'LOCALE_MAKETEXT_LEXICON';
package Locale::Maketext::Lexicon;
$Locale::Maketext::Lexicon::VERSION = '0.91';
use 5.004;
use strict;
=head1 NAME
Locale::Maketext::Lexicon - Use other catalog formats in Maketext
=head1 VERSION
This document describes version 0.91 of Locale::Maketext::Lexicon.
=head1 SYNOPSIS
As part of a localization class, automatically glob for available
lexicons:
package Hello::I18N;
use base 'Locale::Maketext';
use Locale::Maketext::Lexicon {
'*' => [Gettext => '/usr/local/share/locale/*/LC_MESSAGES/hello.mo'],
### Uncomment to fallback when a key is missing from lexicons
# _auto => 1,
### Uncomment to decode lexicon entries into Unicode strings
# _decode => 1,
### Uncomment to load and parse everything right away
# _preload => 1,
### Uncomment to use %1 / %quant(%1) instead of [_1] / [quant, _1]
# _style => 'gettext',
};
Explicitly specify languages, during compile- or run-time:
package Hello::I18N;
use base 'Locale::Maketext';
use Locale::Maketext::Lexicon {
de => [Gettext => 'hello_de.po'],
fr => [
Gettext => 'hello_fr.po',
Gettext => 'local/hello/fr.po',
],
};
# ... incrementally add new lexicons
Locale::Maketext::Lexicon->import({
de => [Gettext => 'local/hello/de.po'],
})
Alternatively, as part of a localization subclass:
package Hello::I18N::de;
use base 'Hello::I18N';
use Locale::Maketext::Lexicon (Gettext => \*DATA);
__DATA__
# Some sample data
msgid ""
msgstr ""
"Project-Id-Version: Hello 1.3.22.1\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
#: Hello.pm:10
msgid "Hello, World!"
msgstr "Hallo, Welt!"
#: Hello.pm:11
msgid "You have %quant(%1,piece) of mail."
msgstr "Sie haben %quant(%1,Poststueck,Poststuecken)."
=head1 DESCRIPTION
This module provides lexicon-handling modules to read from other
localization formats, such as I<Gettext>, I<Msgcat>, and so on.
If you are unfamiliar with the concept of lexicon modules, please
consult L<Locale::Maketext> and the C<webl10n> HTML files in the C<docs/>
directory of this module.
A command-line utility L<xgettext.pl> is also installed with this
module, for extracting translatable strings from source files.
=head2 The C<import> function
The C<import()> function accepts two forms of arguments:
=over 4
=item (I<format> => I<source> ... )
This form takes any number of argument pairs (usually one);
I<source> may be a file name, a filehandle, or an array reference.
For each such pair, it pass the contents specified by the second
argument to B<Locale::Maketext::Lexicon::I<format>>->parse as a
plain list, and export its return value as the C<%Lexicon> hash
in the calling package.
In the case that there are multiple such pairs, the lexicon
defined by latter ones overrides earlier ones.
=item { I<language> => [ I<format>, I<source> ... ] ... }
This form accepts a hash reference. It will export a C<%Lexicon>
into the subclasses specified by each I<language>, using the process
described above. It is designed to alleviate the need to set up a
separate subclass for each localized language, and just use the catalog
files.
This module will convert the I<language> arguments into lowercase,
and replace all C<-> with C<_>, so C<zh_TW> and C<zh-tw> will both
map to the C<zh_tw> subclass.
If I<language> begins with C<_>, it is taken as an option that
controls how lexicons are parsed. See L</Options> for a list
of available options.
The C<*> is a special I<language>; it must be used in conjunction
with a filename that also contains C<*>; all matched files with
a valid language code in the place of C<*> will be automatically
prepared as a lexicon subclass. If there is multiple C<*> in
the filename, the last one is used as the language name.
=back
=head2 Options
=over 4
=item C<_auto>
If set to a true value, missing lookups on lexicons are handled
silently, as if an C<Auto> lexicon has been appended on all
language lexicons.
=item C<_decode>
If set to a true value, source entries will be converted into
utf8-strings (available in Perl 5.6.1 or later). This feature
needs the B<Encode> or B<Encode::compat> module.
Currently, only the C<Gettext> backend supports this option.
=item C<_encoding>
This option only has effect when C<_decode> is set to true.
It specifies an encoding to store lexicon entries, instead of
utf8-strings.
If C<_encoding> is set to C<locale>, the encoding from the
current locale setting is used.
=item C<_preload>
By default parsing is delayed until first use of the lexicon,
set this option to true value to parse it asap. Increment
adding lexicons forces parsing.
=back
=head2 Subclassing format handlers
If you wish to override how sources specified in different data types
are handled, please use a subclass that overrides C<lexicon_get_I<TYPE>>.
XXX: not documented well enough yet. Patches welcome.
=head1 NOTES
When you attempt to localize an entry missing in the lexicon, Maketext
will throw an exception by default. To inhibit this behaviour, override
the C<_AUTO> key in your language subclasses, for example:
$Hello::I18N::en::Lexicon{_AUTO} = 1; # autocreate missing keys
If you want to implement a new C<Lexicon::*> backend module, please note
that C<parse()> takes an array containing the B<source strings> from the
specified filehandle or filename, which are I<not> C<chomp>ed. Although
if the source is an array reference, its elements will probably not contain
any newline characters anyway.
The C<parse()> function should return a hash reference, which will be
assigned to the I<typeglob> (C<*Lexicon>) of the language module. All
it amounts to is that if the returned reference points to a tied hash,
the C<%Lexicon> will be aliased to the same tied hash if it was not
initialized previously.
=cut
our %Opts;
sub option { shift if ref( $_[0] ); $Opts{ lc $_[0] } }
sub set_option { shift if ref( $_[0] ); $Opts{ lc $_[0] } = $_[1] }
sub encoding {
my $encoding = option( @_, 'encoding' ) or return;
return $encoding unless lc($encoding) eq 'locale';
local $^W; # no warnings 'uninitialized', really.
my ( $country_language, $locale_encoding );
local $@;
eval {
require I18N::Langinfo;
$locale_encoding
= I18N::Langinfo::langinfo( I18N::Langinfo::CODESET() );
}
or eval {
require Win32::Console;
$locale_encoding = 'cp' . Win32::Console::OutputCP();
};
if ( !$locale_encoding ) {
foreach my $key (qw( LANGUAGE LC_ALL LC_MESSAGES LANG )) {
$ENV{$key} =~ /^([^.]+)\.([^.:]+)/ or next;
( $country_language, $locale_encoding ) = ( $1, $2 );
last;
}
}
if ( defined $locale_encoding
&& lc($locale_encoding) eq 'euc'
&& defined $country_language )
{
if ( $country_language =~ /^ja_JP|japan(?:ese)?$/i ) {
$locale_encoding = 'euc-jp';
}
elsif ( $country_language =~ /^ko_KR|korean?$/i ) {
$locale_encoding = 'euc-kr';
}
elsif ( $country_language =~ /^zh_CN|chin(?:a|ese)?$/i ) {
$locale_encoding = 'euc-cn';
}
elsif ( $country_language =~ /^zh_TW|taiwan(?:ese)?$/i ) {
$locale_encoding = 'euc-tw';
}
}
return $locale_encoding;
}
sub import {
my $class = shift;
return unless @_;
my %entries;
if ( UNIVERSAL::isa( $_[0], 'HASH' ) ) {
# a hashref with $lang as keys, [$format, $src ...] as values
%entries = %{ $_[0] };
}
elsif ( @_ % 2 == 0 ) {
%entries = ( '' => [ splice @_, 0, 2 ], @_ );
}
# expand the wildcard entry
if ( my $wild_entry = delete $entries{'*'} ) {
while ( my ( $format, $src ) = splice( @$wild_entry, 0, 2 ) ) {
next if ref($src); # XXX: implement globbing for the 'Tie' backend
my $pattern = quotemeta($src);
$pattern =~ s/\\\*(?=[^*]+$)/\([-\\w]+\)/g or next;
$pattern =~ s/\\\*/.*?/g;
$pattern =~ s/\\\?/./g;
$pattern =~ s/\\\[/[/g;
$pattern =~ s/\\\]/]/g;
$pattern =~ s[\\\{(.*?)\\\\}][
'(?:'.join('|', split(/,/, $1)).')'
]eg;
require File::Glob;
foreach my $file ( File::Glob::bsd_glob($src) ) {
$file =~ /$pattern/ or next;
push @{ $entries{$1} }, ( $format => $file ) if $1;
}
delete $entries{$1}
unless !defined($1)
or exists $entries{$1} and @{ $entries{$1} };
}
}
%Opts = ();
foreach my $key ( grep /^_/, keys %entries ) {
set_option( lc( substr( $key, 1 ) ) => delete( $entries{$key} ) );
}
my $OptsRef = {%Opts};
while ( my ( $lang, $entry ) = each %entries ) {
my $export = caller;
if ( length $lang ) {
# normalize language tag to Maketext's subclass convention
$lang = lc($lang);
$lang =~ s/-/_/g;
$export .= "::$lang";
}
my @pairs = @{ $entry || [] } or die "no format specified";
while ( my ( $format, $src ) = splice( @pairs, 0, 2 ) ) {
if ( defined($src) and !ref($src) and $src =~ /\*/ ) {
unshift( @pairs, $format => $_ )
for File::Glob::bsd_glob($src);
next;
}
my @content
= eval { $class->lexicon_get( $src, scalar caller(1), $lang ); };
next if $@ and $@ =~ /^next\b/;
die $@ if $@;
no strict 'refs';
eval "use $class\::$format; 1" or die $@;
if ( %{"$export\::Lexicon"} ) {
my $lexicon = \%{"$export\::Lexicon"};
if ( my $obj = tied %$lexicon ) {
# if it's our tied hash then force loading
# otherwise late load will rewrite
$obj->_force if $obj->isa(__PACKAGE__);
}
# clear the memoized cache for old entries:
Locale::Maketext->clear_isa_scan;
my $new = "$class\::$format"->parse(@content);
# avoid hash rebuild, on big sets
@{$lexicon}{ keys %$new } = values %$new;
}
else {
local $^W if $] >= 5.009; # no warnings 'once', really.
tie %{"$export\::Lexicon"}, __PACKAGE__,
{
Opts => $OptsRef,
Export => "$export\::Lexicon",
Class => "$class\::$format",
Content => \@content,
};
tied( %{"$export\::Lexicon"} )->_force
if $OptsRef->{'preload'};
}
length $lang or next;
# Avoid re-entry
my $caller = caller();
next if $export->isa($caller);
push( @{"$export\::ISA"}, scalar caller );
if ( my $style = option('style') ) {
my $cref
= $class->can( lc("_style_$style") )
->( $class, $export->can('maketext') )
or die "Unknown style: $style";
# Avoid redefinition warnings
local $SIG{__WARN__} = sub {1};
*{"$export\::maketext"} = $cref;
}
}
}
}
sub _style_gettext {
my ( $self, $orig ) = @_;
require Locale::Maketext::Lexicon::Gettext;
sub {
my $lh = shift;
my $str = shift;
return $orig->(
$lh,
Locale::Maketext::Lexicon::Gettext::_gettext_to_maketext($str), @_
);
}
}
sub TIEHASH {
my ( $class, $args ) = @_;
return bless( $args, $class );
}
{
no strict 'refs';
sub _force {
my $args = shift;
unless ( $args->{'Done'} ) {
$args->{'Done'} = 1;
local *Opts = $args->{Opts};
*{ $args->{Export} }
= $args->{Class}->parse( @{ $args->{Content} } );
$args->{'Export'}{'_AUTO'} = 1
if option('auto');
}
return $args->{'Export'};
}
sub FETCH { _force( $_[0] )->{ $_[1] } }
sub EXISTS { _force( $_[0] )->{ $_[1] } }
sub DELETE { delete _force( $_[0] )->{ $_[1] } }
sub SCALAR { scalar %{ _force( $_[0] ) } }
sub STORE { _force( $_[0] )->{ $_[1] } = $_[2] }
sub CLEAR { %{ _force( $_[0] )->{ $_[1] } } = () }
sub NEXTKEY { each %{ _force( $_[0] ) } }
sub FIRSTKEY {
my $hash = _force( $_[0] );
my $a = scalar keys %$hash;
each %$hash;
}
}
sub lexicon_get {
my ( $class, $src, $caller, $lang ) = @_;
return unless defined $src;
foreach my $type ( qw(ARRAY HASH SCALAR GLOB), ref($src) ) {
next unless UNIVERSAL::isa( $src, $type );
my $method = 'lexicon_get_' . lc($type);
die "cannot handle source $type for $src: no $method defined"
unless $class->can($method);
return $class->$method( $src, $caller, $lang );
}
# default handler
return $class->lexicon_get_( $src, $caller, $lang );
}
# for scalarrefs and arrayrefs we just dereference the $src
sub lexicon_get_scalar { ${ $_[1] } }
sub lexicon_get_array { @{ $_[1] } }
sub lexicon_get_hash {
my ( $class, $src, $caller, $lang ) = @_;
return map { $_ => $src->{$_} } sort keys %$src;
}
sub lexicon_get_glob {
my ( $class, $src, $caller, $lang ) = @_;
no strict 'refs';
local $^W if $] >= 5.009; # no warnings 'once', really.
# be extra magical and check for DATA section
if ( eof($src) and $src eq \*{"$caller\::DATA"}
or $src eq \*{"main\::DATA"} )
{
# okay, the *DATA isn't initiated yet. let's read.
#
require FileHandle;
my $fh = FileHandle->new;
my $package = ( ( $src eq \*{"main\::DATA"} ) ? 'main' : $caller );
if ( $package eq 'main' and -e $0 ) {
$fh->open($0) or die "Can't open $0: $!";
}
else {
my $level = 1;
while ( my ( $pkg, $filename ) = caller( $level++ ) ) {
next unless $pkg eq $package;
next unless -e $filename;
next;
$fh->open($filename) or die "Can't open $filename: $!";
last;
}
}
while (<$fh>) {
# okay, this isn't foolproof, but good enough
last if /^__DATA__$/;
}
return <$fh>;
}
# fh containing the lines
my $pos = tell($src);
my @lines = <$src>;
seek( $src, $pos, 0 );
return @lines;
}
# assume filename - search path, open and return its contents
sub lexicon_get_ {
my ( $class, $src, $caller, $lang ) = @_;
$src = $class->lexicon_find( $src, $caller, $lang );
defined $src or die 'next';
require FileHandle;
my $fh = FileHandle->new;
$fh->open($src) or die "Cannot read $src (called by $caller): $!";
binmode($fh);
return <$fh>;
}
sub lexicon_find {
my ( $class, $src, $caller, $lang ) = @_;
return $src if -e $src;
require File::Spec;
my @path = split '::', $caller;
push @path, $lang if length $lang;
while (@path) {
foreach (@INC) {
my $file = File::Spec->catfile( $_, @path, $src );
return $file if -e $file;
}
pop @path;
}
return undef;
}
1;
=head1 ACKNOWLEDGMENTS
Thanks to Jesse Vincent for suggesting this module to be written.
Thanks also to Sean M. Burke for coming up with B<Locale::Maketext>
in the first place, and encouraging me to experiment with alternative
Lexicon syntaxes.
Thanks also to Yi Ma Mao for providing the MO file parsing subroutine,
as well as inspiring me to implement file globbing and transcoding
support.
See the F<AUTHORS> file in the distribution for a list of people who
have sent helpful patches, ideas or comments.
=head1 SEE ALSO
L<xgettext.pl> for extracting translatable strings from common template
systems and perl source files.
L<Locale::Maketext>, L<Locale::Maketext::Lexicon::Auto>,
L<Locale::Maketext::Lexicon::Gettext>, L<Locale::Maketext::Lexicon::Msgcat>,
L<Locale::Maketext::Lexicon::Tie>
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002-2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
LOCALE_MAKETEXT_LEXICON
$fatpacked{"Locale/Maketext/Lexicon/Auto.pm"} = <<'LOCALE_MAKETEXT_LEXICON_AUTO';
package Locale::Maketext::Lexicon::Auto;
$Locale::Maketext::Lexicon::Auto::VERSION = '0.10';
use strict;
=head1 NAME
Locale::Maketext::Lexicon::Auto - Auto fallback lexicon for Maketext
=head1 SYNOPSIS
package Hello::I18N;
use base 'Locale::Maketext';
use Locale::Maketext::Lexicon {
en => ['Auto'],
# ... other languages
};
=head1 DESCRIPTION
This module builds a simple Lexicon hash that contains nothing but
C<( '_AUTO' =E<gt> 1)>, which tells C<Locale::Maketext> that no
localizing is needed -- just use the lookup key as the returned string.
It is especially useful if you're starting to prototype a program, and
do not want to deal with the localization files yet.
=head1 CAVEATS
If the key to C<-E<gt>maketext> begins with a C<_>, C<Locale::Maketext>
will still throw an exception. See L<Locale::Maketext/CONTROLLING LOOKUP
FAILURE> for how to prevent it.
=cut
sub parse {
+{ _AUTO => 1 };
}
1;
=head1 SEE ALSO
L<Locale::Maketext>, L<Locale::Maketext::Lexicon>
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002, 2003, 2004, 2007 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
LOCALE_MAKETEXT_LEXICON_AUTO
$fatpacked{"Locale/Maketext/Lexicon/Gettext.pm"} = <<'LOCALE_MAKETEXT_LEXICON_GETTEXT';
package Locale::Maketext::Lexicon::Gettext;
$Locale::Maketext::Lexicon::Gettext::VERSION = '0.17';
use strict;
=head1 NAME
Locale::Maketext::Lexicon::Gettext - PO and MO file parser for Maketext
=head1 SYNOPSIS
Called via B<Locale::Maketext::Lexicon>:
package Hello::I18N;
use base 'Locale::Maketext';
use Locale::Maketext::Lexicon {
de => [Gettext => 'hello/de.mo'],
};
Directly calling C<parse()>:
use Locale::Maketext::Lexicon::Gettext;
my %Lexicon = %{ Locale::Maketext::Lexicon::Gettext->parse(<DATA>) };
__DATA__
#: Hello.pm:10
msgid "Hello, World!"
msgstr "Hallo, Welt!"
#: Hello.pm:11
msgid "You have %quant(%1,piece) of mail."
msgstr "Sie haben %quant(%1,Poststueck,Poststuecken)."
=head1 DESCRIPTION
This module implements a perl-based C<Gettext> parser for
B<Locale::Maketext>. It transforms all C<%1>, C<%2>, <%*>... sequences
to C<[_1]>, C<[_2]>, C<[_*]>, and so on. It accepts either plain PO
file, or a MO file which will be handled with a pure-perl parser
adapted from Imacat's C<Locale::Maketext::Gettext>.
Since version 0.03, this module also looks for C<%I<function>(I<args...>)>
in the lexicon strings, and transform it to C<[I<function>,I<args...>]>.
Any C<%1>, C<%2>... sequences inside the I<args> will have their percent
signs (C<%>) replaced by underscores (C<_>).
The name of I<function> above should begin with a letter or underscore,
followed by any number of alphanumeric characters and/or underscores.
As an exception, the function name may also consist of a single asterisk
(C<*>) or pound sign (C<#>), which are C<Locale::Maketext>'s shorthands
for C<quant> and C<numf>, respectively.
As an additional feature, this module also parses MIME-header style
metadata specified in the null msgstr (C<"">), and add them to the
C<%Lexicon> with a C<__> prefix. For example, the example above will
set C<__Content-Type> to C<text/plain; charset=iso8859-1>, without
the newline or the colon.
Any normal entry that duplicates a metadata entry takes precedence.
Hence, a C<msgid "__Content-Type"> line occurs anywhere should override
the above value.
=head1 OPTIONS
=head2 use_fuzzy
When parsing PO files, fuzzy entries (entries marked with C<#, fuzzy>)
are silently ignored. If you wish to use fuzzy entries, specify a true
value to the C<_use_fuzzy> option:
use Locale::Maketext::Lexicon {
de => [Gettext => 'hello/de.mo'],
_use_fuzzy => 1,
};
=head2 allow_empty
When parsing PO files, empty entries (entries with C<msgstr "">) are
silently ignored. If you wish to allow empty entries, specify a true
value to the C<_allow_empty> option:
use Locale::Maketext::Lexicon {
de => [Gettext => 'hello/de.mo'],
_allow_empty => 1,
};
=cut
my ( $InputEncoding, $OutputEncoding, $DoEncoding );
sub input_encoding {$InputEncoding}
sub output_encoding {$OutputEncoding}
sub parse {
my $self = shift;
my ( %var, $key, @ret );
my @metadata;
my @comments;
my @fuzzy;
$InputEncoding = $OutputEncoding = $DoEncoding = undef;
use Carp;
Carp::cluck "Undefined source called\n" unless defined $_[0];
# Check for magic string of MO files
return parse_mo( join( '', @_ ) )
if ( $_[0] =~ /^\x95\x04\x12\xde/ or $_[0] =~ /^\xde\x12\x04\x95/ );
local $^W; # no 'uninitialized' warnings, please.
require Locale::Maketext::Lexicon;
my $KeepFuzzy = Locale::Maketext::Lexicon::option('keep_fuzzy');
my $UseFuzzy = $KeepFuzzy
|| Locale::Maketext::Lexicon::option('use_fuzzy');
my $AllowEmpty = Locale::Maketext::Lexicon::option('allow_empty');
my $process = sub {
if ( length( $var{msgstr} ) and ( $UseFuzzy or !$var{fuzzy} ) ) {
push @ret, ( map transform($_), @var{ 'msgid', 'msgstr' } );
}
elsif ($AllowEmpty) {
push @ret, ( transform( $var{msgid} ), '' );
}
if ( $var{msgid} eq '' ) {
push @metadata, parse_metadata( $var{msgstr} );
}
else {
push @comments, $var{msgid}, $var{msgcomment};
}
if ( $KeepFuzzy && $var{fuzzy} ) {
push @fuzzy, $var{msgid}, 1;
}
%var = ();
};
# Parse PO files
foreach (@_) {
s/[\015\012]*\z//; # fix CRLF issues
/^(msgid|msgstr) +"(.*)" *$/
? do { # leading strings
$var{$1} = $2;
$key = $1;
}
:
/^"(.*)" *$/
? do { # continued strings
$var{$key} .= $1;
}
:
/^# (.*)$/
? do { # user comments
$var{msgcomment} .= $1 . "\n";
}
:
/^#, +(.*) *$/
? do { # control variables
$var{$_} = 1 for split( /,\s+/, $1 );
}
:
/^ *$/ && %var
? do { # interpolate string escapes
$process->($_);
}
: ();
}
# do not silently skip last entry
$process->() if keys %var != 0;
push @ret, map { transform($_) } @var{ 'msgid', 'msgstr' }
if length $var{msgstr};
push @metadata, parse_metadata( $var{msgstr} )
if $var{msgid} eq '';
return wantarray
? ( { @metadata, @ret }, {@comments}, {@fuzzy} )
: ( { @metadata, @ret } );
}
sub parse_metadata {
return map {
(/^([^\x00-\x1f\x80-\xff :=]+):\s*(.*)$/)
? ( $1 eq 'Content-Type' )
? do {
my $enc = $2;
if ( $enc =~ /\bcharset=\s*([-\w]+)/i ) {
$InputEncoding = $1 || '';
$OutputEncoding
= Locale::Maketext::Lexicon::encoding()
|| '';
$InputEncoding = 'utf8'
if $InputEncoding =~ /^utf-?8$/i;
$OutputEncoding = 'utf8'
if $OutputEncoding =~ /^utf-?8$/i;
if ( Locale::Maketext::Lexicon::option('decode')
and ( !$OutputEncoding
or $InputEncoding ne $OutputEncoding )
)
{
require Encode::compat if $] < 5.007001;
require Encode;
$DoEncoding = 1;
}
}
( "__Content-Type", $enc );
}
: ( "__$1", $2 )
: ();
} split( /\r*\n+\r*/, transform(pop) );
}
sub transform {
my $str = shift;
if ( $DoEncoding and $InputEncoding ) {
$str
= ( $InputEncoding eq 'utf8' )
? Encode::decode_utf8($str)
: Encode::decode( $InputEncoding, $str );
}
$str =~ s/\\([0x]..|c?.)/qq{"\\$1"}/eeg;
if ( $DoEncoding and $OutputEncoding ) {
$str
= ( $OutputEncoding eq 'utf8' )
? Encode::encode_utf8($str)
: Encode::encode( $OutputEncoding, $str );
}
return _gettext_to_maketext($str);
}
sub _gettext_to_maketext {
my $str = shift;
$str =~ s{([\~\[\]])}{~$1}g;
$str =~ s{
([%\\]%) # 1 - escaped sequence
|
% (?:
([A-Za-z#*]\w*) # 2 - function call
\(([^\)]*)\) # 3 - arguments
|
([1-9]\d*|\*) # 4 - variable
)
}{
$1 ? $1
: $2 ? "\[$2,"._unescape($3)."]"
: "[_$4]"
}egx;
$str;
}
sub _unescape {
join( ',',
map { /\A(\s*)%([1-9]\d*|\*)(\s*)\z/ ? "$1_$2$3" : $_ }
split( /,/, $_[0] ) );
}
# This subroutine was derived from Locale::Maketext::Gettext::readmo()
# under the Perl License; the original author is Yi Ma Mao (IMACAT).
sub parse_mo {
my $content = shift;
my $tmpl = ( substr( $content, 0, 4 ) eq "\xde\x12\x04\x95" ) ? 'V' : 'N';
# Check the MO format revision number
# There is only one revision now: revision 0.
return if unpack( $tmpl, substr( $content, 4, 4 ) ) > 0;
my ( $num, $offo, $offt );
# Number of strings
$num = unpack $tmpl, substr( $content, 8, 4 );
# Offset to the beginning of the original strings
$offo = unpack $tmpl, substr( $content, 12, 4 );
# Offset to the beginning of the translated strings
$offt = unpack $tmpl, substr( $content, 16, 4 );
my ( @metadata, @ret );
for ( 0 .. $num - 1 ) {
my ( $len, $off, $stro, $strt );
# The first word is the length of the string
$len = unpack $tmpl, substr( $content, $offo + $_ * 8, 4 );
# The second word is the offset of the string
$off = unpack $tmpl, substr( $content, $offo + $_ * 8 + 4, 4 );
# Original string
$stro = substr( $content, $off, $len );
# The first word is the length of the string
$len = unpack $tmpl, substr( $content, $offt + $_ * 8, 4 );
# The second word is the offset of the string
$off = unpack $tmpl, substr( $content, $offt + $_ * 8 + 4, 4 );
# Translated string
$strt = substr( $content, $off, $len );
# Hash it
push @metadata, parse_metadata($strt) if $stro eq '';
push @ret, ( map transform($_), $stro, $strt ) if length $strt;
}
return { @metadata, @ret };
}
1;
=head1 SEE ALSO
L<Locale::Maketext>, L<Locale::Maketext::Lexicon>
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002, 2003, 2004, 2007 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
LOCALE_MAKETEXT_LEXICON_GETTEXT
$fatpacked{"Locale/Maketext/Lexicon/Msgcat.pm"} = <<'LOCALE_MAKETEXT_LEXICON_MSGCAT';
package Locale::Maketext::Lexicon::Msgcat;
$Locale::Maketext::Lexicon::Msgcat::VERSION = '0.03';
use strict;
=head1 NAME
Locale::Maketext::Lexicon::Msgcat - Msgcat catalog parser Maketext
=head1 SYNOPSIS
package Hello::I18N;
use base 'Locale::Maketext';
use Locale::Maketext::Lexicon {
en => ['Msgcat', 'en_US/hello.pl.m'],
};
package main;
my $lh = Hello::I18N->get_handle('en');
print $lh->maketext(1,2); # set 1, msg 2
print $lh->maketext("1,2"); # same thing
=head1 DESCRIPTION
This module parses one or more Msgcat catalogs in plain text format,
and returns a Lexicon hash, which may be looked up either with a
two-argument form (C<$set_id, $msg_id>) or as a single string
(C<"$set_id,$msg_id">).
=head1 NOTES
All special characters (C<[>, C<]> and C<~>) in catalogs will be
escaped so they lose their magic meanings. That means C<-E<gt>maketext>
calls to this lexicon will I<not> take any additional arguments.
=cut
sub parse {
my $set = 0;
my $msg = undef;
my ($qr, $qq, $qc) = (qr//, '', '');
my @out;
# Set up the msgcat handler
{
no strict 'refs';
no warnings 'once';
*{Locale::Maketext::msgcat} = \&_msgcat;
}
# Parse *.m files; Locale::Msgcat objects and *.cat are not yet supported.
foreach (@_) {
s/[\015\012]*\z//; # fix CRLF issues
/^\$set (\d+)/
? do { # set_id
$set = int($1);
push @out, $1, "[msgcat,$1,_1]";
}
:
/^\$quote (.)/
? do { # quote character
$qc = $1;
$qq = quotemeta($1);
$qr = qr/$qq?/;
}
:
/^(\d+) ($qr)(.*?)\2(\\?)$/
? do { # msg_id and msg_str
local $^W;
push @out, "$set," . int($1);
if ($4) {
$msg = $3;
}
else {
push @out, unescape($qq, $qc, $3);
undef $msg;
}
}
:
(defined $msg and /^($qr)(.*?)\1(\\?)$/)
? do { # continued string
local $^W;
if ($3) {
$msg .= $2;
}
else {
push @out, unescape($qq, $qc, $msg . $2);
undef $msg;
}
}
: ();
}
push @out, '' if defined $msg;
return {@out};
}
sub _msgcat {
my ($self, $set_id, $msg_id, @args) = @_;
return $self->maketext(int($set_id) . ',' . int($msg_id), @args);
}
sub unescape {
my ($qq, $qc, $str) = @_;
$str =~ s/(\\([ntvbrf\\$qq]))/($2 eq $qc) ? $qc : eval qq("$1")/e;
$str =~ s/([\~\[\]])/~$1/g;
return $str;
}
1;
=head1 SEE ALSO
L<Locale::Maketext>, L<Locale::Maketext::Lexicon>
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002, 2003, 2004, 2007 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
LOCALE_MAKETEXT_LEXICON_MSGCAT
$fatpacked{"Locale/Maketext/Lexicon/Tie.pm"} = <<'LOCALE_MAKETEXT_LEXICON_TIE';
package Locale::Maketext::Lexicon::Tie;
$Locale::Maketext::Lexicon::Tie::VERSION = '0.05';
use strict;
use Symbol ();
=head1 NAME
Locale::Maketext::Lexicon::Tie - Use tied hashes as lexicons for Maketext
=head1 SYNOPSIS
package Hello::I18N;
use base 'Locale::Maketext';
use Locale::Maketext::Lexicon {
en => [ Tie => [ DB_File => 'en.db' ] ],
};
=head1 DESCRIPTION
This module lets you easily C<tie> the C<%Lexicon> hash to a database
or other data sources. It takes an array reference of arguments, and
passes them directly to C<tie()>.
Entries will then be fetched whenever it is used; this module does not
cache them.
=cut
sub parse {
my $self = shift;
my $mod = shift;
my $sym = Symbol::gensym();
# Load the target module into memory
{
no strict 'refs';
eval "use $mod; 1" or die $@ unless %{"$mod\::"};
}
# Perform the actual tie
tie %{*$sym}, $mod, @_;
# Returns the GLOB reference, so %Lexicon will be tied too
return $sym;
}
1;
=head1 SEE ALSO
L<Locale::Maketext>, L<Locale::Maketext::Lexicon>
=head1 AUTHORS
Audrey Tang E<lt>cpan@audreyt.orgE<gt>
=head1 COPYRIGHT
Copyright 2002, 2003, 2004, 2007 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
This software is released under the MIT license cited below.
=head2 The "MIT" License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
=cut
LOCALE_MAKETEXT_LEXICON_TIE
$fatpacked{"Module/Load.pm"} = <<'MODULE_LOAD';
package Module::Load;
$VERSION = '0.20';
use strict;
use File::Spec ();
sub import {
my $who = _who();
{ no strict 'refs';
*{"${who}::load"} = *load;
}
}
sub load (*;@) {
my $mod = shift or return;
my $who = _who();
if( _is_file( $mod ) ) {
require $mod;
} else {
LOAD: {
my $err;
for my $flag ( qw[1 0] ) {
my $file = _to_file( $mod, $flag);
eval { require $file };
$@ ? $err .= $@ : last LOAD;
}
die $err if $err;
}
}
### This addresses #41883: Module::Load cannot import
### non-Exporter module. ->import() routines weren't
### properly called when load() was used.
{ no strict 'refs';
my $import;
if (@_ and $import = $mod->can('import')) {
unshift @_, $mod;
goto &$import;
}
}
}
sub _to_file{
local $_ = shift;
my $pm = shift || '';
## trailing blanks ignored by default. [rt #69886]
my @parts = split /::/, $_, -1;
### because of [perl #19213], see caveats ###
my $file = $^O eq 'MSWin32'
? join "/", @parts
: File::Spec->catfile( @parts );
$file .= '.pm' if $pm;
### on perl's before 5.10 (5.9.5@31746) if you require
### a file in VMS format, it's stored in %INC in VMS
### format. Therefor, better unixify it first
### Patch in reply to John Malmbergs patch (as mentioned
### above) on p5p Tue 21 Aug 2007 04:55:07
$file = VMS::Filespec::unixify($file) if $^O eq 'VMS';
return $file;
}
sub _who { (caller(1))[0] }
sub _is_file {
local $_ = shift;
return /^\./ ? 1 :
/[^\w:']/ ? 1 :
undef
#' silly bbedit..
}
1;
__END__
=pod
=head1 NAME
Module::Load - runtime require of both modules and files
=head1 SYNOPSIS
use Module::Load;
my $module = 'Data:Dumper';
load Data::Dumper; # loads that module
load 'Data::Dumper'; # ditto
load $module # tritto
my $script = 'some/script.pl'
load $script;
load 'some/script.pl'; # use quotes because of punctuations
load thing; # try 'thing' first, then 'thing.pm'
load CGI, ':standard' # like 'use CGI qw[:standard]'
=head1 DESCRIPTION
C<load> eliminates the need to know whether you are trying to require
either a file or a module.
If you consult C<perldoc -f require> you will see that C<require> will
behave differently when given a bareword or a string.
In the case of a string, C<require> assumes you are wanting to load a
file. But in the case of a bareword, it assumes you mean a module.
This gives nasty overhead when you are trying to dynamically require
modules at runtime, since you will need to change the module notation
(C<Acme::Comment>) to a file notation fitting the particular platform
you are on.
C<load> eliminates the need for this overhead and will just DWYM.
=head1 Rules
C<load> has the following rules to decide what it thinks you want:
=over 4
=item *
If the argument has any characters in it other than those matching
C<\w>, C<:> or C<'>, it must be a file
=item *
If the argument matches only C<[\w:']>, it must be a module
=item *
If the argument matches only C<\w>, it could either be a module or a
file. We will try to find C<file.pm> first in C<@INC> and if that
fails, we will try to find C<file> in @INC. If both fail, we die with
the respective error messages.
=back
=head1 Caveats
Because of a bug in perl (#19213), at least in version 5.6.1, we have
to hardcode the path separator for a require on Win32 to be C</>, like
on Unix rather than the Win32 C<\>. Otherwise perl will not read its
own %INC accurately double load files if they are required again, or
in the worst case, core dump.
C<Module::Load> cannot do implicit imports, only explicit imports.
(in other words, you always have to specify explicitly what you wish
to import from a module, even if the functions are in that modules'
C<@EXPORT>)
=head1 ACKNOWLEDGEMENTS
Thanks to Jonas B. Nielsen for making explicit imports work.
=head1 BUG REPORTS
Please report bugs or other issues to E<lt>bug-module-load@rt.cpan.org<gt>.
=head1 AUTHOR
This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
=head1 COPYRIGHT
This library is free software; you may redistribute and/or modify it
under the same terms as Perl itself.
=cut
MODULE_LOAD
$fatpacked{"Params/Check.pm"} = <<'PARAMS_CHECK';
package Params::Check;
use strict;
use Carp qw[carp croak];
use Locale::Maketext::Simple Style => 'gettext';
BEGIN {
use Exporter ();
use vars qw[ @ISA $VERSION @EXPORT_OK $VERBOSE $ALLOW_UNKNOWN
$STRICT_TYPE $STRIP_LEADING_DASHES $NO_DUPLICATES
$PRESERVE_CASE $ONLY_ALLOW_DEFINED $WARNINGS_FATAL
$SANITY_CHECK_TEMPLATE $CALLER_DEPTH $_ERROR_STRING
];
@ISA = qw[ Exporter ];
@EXPORT_OK = qw[check allow last_error];
$VERSION = '0.32';
$VERBOSE = $^W ? 1 : 0;
$NO_DUPLICATES = 0;
$STRIP_LEADING_DASHES = 0;
$STRICT_TYPE = 0;
$ALLOW_UNKNOWN = 0;
$PRESERVE_CASE = 0;
$ONLY_ALLOW_DEFINED = 0;
$SANITY_CHECK_TEMPLATE = 1;
$WARNINGS_FATAL = 0;
$CALLER_DEPTH = 0;
}
my %known_keys = map { $_ => 1 }
qw| required allow default strict_type no_override
store defined |;
=pod
=head1 NAME
Params::Check - A generic input parsing/checking mechanism.
=head1 SYNOPSIS
use Params::Check qw[check allow last_error];
sub fill_personal_info {
my %hash = @_;
my $x;
my $tmpl = {
firstname => { required => 1, defined => 1 },
lastname => { required => 1, store => \$x },
gender => { required => 1,
allow => [qr/M/i, qr/F/i],
},
married => { allow => [0,1] },
age => { default => 21,
allow => qr/^\d+$/,
},
phone => { allow => [ sub { return 1 if /$valid_re/ },
'1-800-PERL' ]
},
id_list => { default => [],
strict_type => 1
},
employer => { default => 'NSA', no_override => 1 },
};
### check() returns a hashref of parsed args on success ###
my $parsed_args = check( $tmpl, \%hash, $VERBOSE )
or die qw[Could not parse arguments!];
... other code here ...
}
my $ok = allow( $colour, [qw|blue green yellow|] );
my $error = Params::Check::last_error();
=head1 DESCRIPTION
Params::Check is a generic input parsing/checking mechanism.
It allows you to validate input via a template. The only requirement
is that the arguments must be named.
Params::Check can do the following things for you:
=over 4
=item *
Convert all keys to lowercase
=item *
Check if all required arguments have been provided
=item *
Set arguments that have not been provided to the default
=item *
Weed out arguments that are not supported and warn about them to the
user
=item *
Validate the arguments given by the user based on strings, regexes,
lists or even subroutines
=item *
Enforce type integrity if required
=back
Most of Params::Check's power comes from its template, which we'll
discuss below:
=head1 Template
As you can see in the synopsis, based on your template, the arguments
provided will be validated.
The template can take a different set of rules per key that is used.
The following rules are available:
=over 4
=item default
This is the default value if none was provided by the user.
This is also the type C<strict_type> will look at when checking type
integrity (see below).
=item required
A boolean flag that indicates if this argument was a required
argument. If marked as required and not provided, check() will fail.
=item strict_type
This does a C<ref()> check on the argument provided. The C<ref> of the
argument must be the same as the C<ref> of the default value for this
check to pass.
This is very useful if you insist on taking an array reference as
argument for example.
=item defined
If this template key is true, enforces that if this key is provided by
user input, its value is C<defined>. This just means that the user is
not allowed to pass C<undef> as a value for this key and is equivalent
to:
allow => sub { defined $_[0] && OTHER TESTS }
=item no_override
This allows you to specify C<constants> in your template. ie, they
keys that are not allowed to be altered by the user. It pretty much
allows you to keep all your C<configurable> data in one place; the
C<Params::Check> template.
=item store
This allows you to pass a reference to a scalar, in which the data
will be stored:
my $x;
my $args = check(foo => { default => 1, store => \$x }, $input);
This is basically shorthand for saying:
my $args = check( { foo => { default => 1 }, $input );
my $x = $args->{foo};
You can alter the global variable $Params::Check::NO_DUPLICATES to
control whether the C<store>'d key will still be present in your
result set. See the L<Global Variables> section below.
=item allow
A set of criteria used to validate a particular piece of data if it
has to adhere to particular rules.
See the C<allow()> function for details.
=back
=head1 Functions
=head2 check( \%tmpl, \%args, [$verbose] );
This function is not exported by default, so you'll have to ask for it
via:
use Params::Check qw[check];
or use its fully qualified name instead.
C<check> takes a list of arguments, as follows:
=over 4
=item Template
This is a hashreference which contains a template as explained in the
C<SYNOPSIS> and C<Template> section.
=item Arguments
This is a reference to a hash of named arguments which need checking.
=item Verbose
A boolean to indicate whether C<check> should be verbose and warn
about what went wrong in a check or not.
You can enable this program wide by setting the package variable
C<$Params::Check::VERBOSE> to a true value. For details, see the
section on C<Global Variables> below.
=back
C<check> will return when it fails, or a hashref with lowercase
keys of parsed arguments when it succeeds.
So a typical call to check would look like this:
my $parsed = check( \%template, \%arguments, $VERBOSE )
or warn q[Arguments could not be parsed!];
A lot of the behaviour of C<check()> can be altered by setting
package variables. See the section on C<Global Variables> for details
on this.
=cut
sub check {
my ($utmpl, $href, $verbose) = @_;
### clear the current error string ###
_clear_error();
### did we get the arguments we need? ###
if ( !$utmpl or !$href ) {
_store_error(loc('check() expects two arguments'));
return unless $WARNINGS_FATAL;
croak(__PACKAGE__->last_error);
}
### sensible defaults ###
$verbose ||= $VERBOSE || 0;
### XXX what type of template is it? ###
### { key => { } } ?
#if (ref $args eq 'HASH') {
# 1;
#}
### clean up the template ###
my $args = _clean_up_args( $href ) or return;
### sanity check + defaults + required keys set? ###
my $defs = _sanity_check_and_defaults( $utmpl, $args, $verbose )
or return;
### deref only once ###
my %utmpl = %$utmpl;
my %args = %$args;
my %defs = %$defs;
### flag to see if anything went wrong ###
my $wrong;
### flag to see if we warned for anything, needed for warnings_fatal
my $warned;
for my $key (keys %args) {
### you gave us this key, but it's not in the template ###
unless( $utmpl{$key} ) {
### but we'll allow it anyway ###
if( $ALLOW_UNKNOWN ) {
$defs{$key} = $args{$key};
### warn about the error ###
} else {
_store_error(
loc("Key '%1' is not a valid key for %2 provided by %3",
$key, _who_was_it(), _who_was_it(1)), $verbose);
$warned ||= 1;
}
next;
}
### check if you're even allowed to override this key ###
if( $utmpl{$key}->{'no_override'} ) {
_store_error(
loc(q[You are not allowed to override key '%1'].
q[for %2 from %3], $key, _who_was_it(), _who_was_it(1)),
$verbose
);
$warned ||= 1;
next;
}
### copy of this keys template instructions, to save derefs ###
my %tmpl = %{$utmpl{$key}};
### check if you were supposed to provide defined() values ###
if( ($tmpl{'defined'} || $ONLY_ALLOW_DEFINED) and
not defined $args{$key}
) {
_store_error(loc(q|Key '%1' must be defined when passed|, $key),
$verbose );
$wrong ||= 1;
next;
}
### check if they should be of a strict type, and if it is ###
if( ($tmpl{'strict_type'} || $STRICT_TYPE) and
(ref $args{$key} ne ref $tmpl{'default'})
) {
_store_error(loc(q|Key '%1' needs to be of type '%2'|,
$key, ref $tmpl{'default'} || 'SCALAR'), $verbose );
$wrong ||= 1;
next;
}
### check if we have an allow handler, to validate against ###
### allow() will report its own errors ###
if( exists $tmpl{'allow'} and not do {
local $_ERROR_STRING;
allow( $args{$key}, $tmpl{'allow'} )
}
) {
### stringify the value in the error report -- we don't want dumps
### of objects, but we do want to see *roughly* what we passed
_store_error(loc(q|Key '%1' (%2) is of invalid type for '%3' |.
q|provided by %4|,
$key, "$args{$key}", _who_was_it(),
_who_was_it(1)), $verbose);
$wrong ||= 1;
next;
}
### we got here, then all must be OK ###
$defs{$key} = $args{$key};
}
### croak with the collected errors if there were errors and
### we have the fatal flag toggled.
croak(__PACKAGE__->last_error) if ($wrong || $warned) && $WARNINGS_FATAL;
### done with our loop... if $wrong is set, something went wrong
### and the user is already informed, just return...
return if $wrong;
### check if we need to store any of the keys ###
### can't do it before, because something may go wrong later,
### leaving the user with a few set variables
for my $key (keys %defs) {
if( my $ref = $utmpl{$key}->{'store'} ) {
$$ref = $NO_DUPLICATES ? delete $defs{$key} : $defs{$key};
}
}
return \%defs;
}
=head2 allow( $test_me, \@criteria );
The function that handles the C<allow> key in the template is also
available for independent use.
The function takes as first argument a key to test against, and
as second argument any form of criteria that are also allowed by
the C<allow> key in the template.
You can use the following types of values for allow:
=over 4
=item string
The provided argument MUST be equal to the string for the validation
to pass.
=item regexp
The provided argument MUST match the regular expression for the
validation to pass.
=item subroutine
The provided subroutine MUST return true in order for the validation
to pass and the argument accepted.
(This is particularly useful for more complicated data).
=item array ref
The provided argument MUST equal one of the elements of the array
ref for the validation to pass. An array ref can hold all the above
values.
=back
It returns true if the key matched the criteria, or false otherwise.
=cut
sub allow {
### use $_[0] and $_[1] since this is hot code... ###
#my ($val, $ref) = @_;
### it's a regexp ###
if( ref $_[1] eq 'Regexp' ) {
local $^W; # silence warnings if $val is undef #
return if $_[0] !~ /$_[1]/;
### it's a sub ###
} elsif ( ref $_[1] eq 'CODE' ) {
return unless $_[1]->( $_[0] );
### it's an array ###
} elsif ( ref $_[1] eq 'ARRAY' ) {
### loop over the elements, see if one of them says the
### value is OK
### also, short-circuit when possible
for ( @{$_[1]} ) {
return 1 if allow( $_[0], $_ );
}
return;
### fall back to a simple, but safe 'eq' ###
} else {
return unless _safe_eq( $_[0], $_[1] );
}
### we got here, no failures ###
return 1;
}
### helper functions ###
### clean up the template ###
sub _clean_up_args {
### don't even bother to loop, if there's nothing to clean up ###
return $_[0] if $PRESERVE_CASE and !$STRIP_LEADING_DASHES;
my %args = %{$_[0]};
### keys are note aliased ###
for my $key (keys %args) {
my $org = $key;
$key = lc $key unless $PRESERVE_CASE;
$key =~ s/^-// if $STRIP_LEADING_DASHES;
$args{$key} = delete $args{$org} if $key ne $org;
}
### return references so we always return 'true', even on empty
### arguments
return \%args;
}
sub _sanity_check_and_defaults {
my %utmpl = %{$_[0]};
my %args = %{$_[1]};
my $verbose = $_[2];
my %defs; my $fail;
for my $key (keys %utmpl) {
### check if required keys are provided
### keys are now lower cased, unless preserve case was enabled
### at which point, the utmpl keys must match, but that's the users
### problem.
if( $utmpl{$key}->{'required'} and not exists $args{$key} ) {
_store_error(
loc(q|Required option '%1' is not provided for %2 by %3|,
$key, _who_was_it(1), _who_was_it(2)), $verbose );
### mark the error ###
$fail++;
next;
}
### next, set the default, make sure the key exists in %defs ###
$defs{$key} = $utmpl{$key}->{'default'}
if exists $utmpl{$key}->{'default'};
if( $SANITY_CHECK_TEMPLATE ) {
### last, check if they provided any weird template keys
### -- do this last so we don't always execute this code.
### just a small optimization.
map { _store_error(
loc(q|Template type '%1' not supported [at key '%2']|,
$_, $key), 1, 1 );
} grep {
not $known_keys{$_}
} keys %{$utmpl{$key}};
### make sure you passed a ref, otherwise, complain about it!
if ( exists $utmpl{$key}->{'store'} ) {
_store_error( loc(
q|Store variable for '%1' is not a reference!|, $key
), 1, 1 ) unless ref $utmpl{$key}->{'store'};
}
}
}
### errors found ###
return if $fail;
### return references so we always return 'true', even on empty
### defaults
return \%defs;
}
sub _safe_eq {
### only do a straight 'eq' if they're both defined ###
return defined($_[0]) && defined($_[1])
? $_[0] eq $_[1]
: defined($_[0]) eq defined($_[1]);
}
sub _who_was_it {
my $level = $_[0] || 0;
return (caller(2 + $CALLER_DEPTH + $level))[3] || 'ANON'
}
=head2 last_error()
Returns a string containing all warnings and errors reported during
the last time C<check> was called.
This is useful if you want to report then some other way than
C<carp>'ing when the verbose flag is on.
It is exported upon request.
=cut
{ $_ERROR_STRING = '';
sub _store_error {
my($err, $verbose, $offset) = @_[0..2];
$verbose ||= 0;
$offset ||= 0;
my $level = 1 + $offset;
local $Carp::CarpLevel = $level;
carp $err if $verbose;
$_ERROR_STRING .= $err . "\n";
}
sub _clear_error {
$_ERROR_STRING = '';
}
sub last_error { $_ERROR_STRING }
}
1;
=head1 Global Variables
The behaviour of Params::Check can be altered by changing the
following global variables:
=head2 $Params::Check::VERBOSE
This controls whether Params::Check will issue warnings and
explanations as to why certain things may have failed.
If you set it to 0, Params::Check will not output any warnings.
The default is 1 when L<warnings> are enabled, 0 otherwise;
=head2 $Params::Check::STRICT_TYPE
This works like the C<strict_type> option you can pass to C<check>,
which will turn on C<strict_type> globally for all calls to C<check>.
The default is 0;
=head2 $Params::Check::ALLOW_UNKNOWN
If you set this flag, unknown options will still be present in the
return value, rather than filtered out. This is useful if your
subroutine is only interested in a few arguments, and wants to pass
the rest on blindly to perhaps another subroutine.
The default is 0;
=head2 $Params::Check::STRIP_LEADING_DASHES
If you set this flag, all keys passed in the following manner:
function( -key => 'val' );
will have their leading dashes stripped.
=head2 $Params::Check::NO_DUPLICATES
If set to true, all keys in the template that are marked as to be
stored in a scalar, will also be removed from the result set.
Default is false, meaning that when you use C<store> as a template
key, C<check> will put it both in the scalar you supplied, as well as
in the hashref it returns.
=head2 $Params::Check::PRESERVE_CASE
If set to true, L<Params::Check> will no longer convert all keys from
the user input to lowercase, but instead expect them to be in the
case the template provided. This is useful when you want to use
similar keys with different casing in your templates.
Understand that this removes the case-insensitivity feature of this
module.
Default is 0;
=head2 $Params::Check::ONLY_ALLOW_DEFINED
If set to true, L<Params::Check> will require all values passed to be
C<defined>. If you wish to enable this on a 'per key' basis, use the
template option C<defined> instead.
Default is 0;
=head2 $Params::Check::SANITY_CHECK_TEMPLATE
If set to true, L<Params::Check> will sanity check templates, validating
for errors and unknown keys. Although very useful for debugging, this
can be somewhat slow in hot-code and large loops.
To disable this check, set this variable to C<false>.
Default is 1;
=head2 $Params::Check::WARNINGS_FATAL
If set to true, L<Params::Check> will C<croak> when an error during
template validation occurs, rather than return C<false>.
Default is 0;
=head2 $Params::Check::CALLER_DEPTH
This global modifies the argument given to C<caller()> by
C<Params::Check::check()> and is useful if you have a custom wrapper
function around C<Params::Check::check()>. The value must be an
integer, indicating the number of wrapper functions inserted between
the real function call and C<Params::Check::check()>.
Example wrapper function, using a custom stacktrace:
sub check {
my ($template, $args_in) = @_;
local $Params::Check::WARNINGS_FATAL = 1;
local $Params::Check::CALLER_DEPTH = $Params::Check::CALLER_DEPTH + 1;
my $args_out = Params::Check::check($template, $args_in);
my_stacktrace(Params::Check::last_error) unless $args_out;
return $args_out;
}
Default is 0;
=head1 Acknowledgements
Thanks to Richard Soderberg for his performance improvements.
=head1 BUG REPORTS
Please report bugs or other issues to E<lt>bug-params-check@rt.cpan.orgE<gt>.
=head1 AUTHOR
This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
=head1 COPYRIGHT
This library is free software; you may redistribute and/or modify it
under the same terms as Perl itself.
=cut
# Local variables:
# c-indentation-style: bsd
# c-basic-offset: 4
# indent-tabs-mode: nil
# End:
# vim: expandtab shiftwidth=4:
PARAMS_CHECK
$fatpacked{"darwin-2level/Time/HiRes.pm"} = <<'DARWIN-2LEVEL_TIME_HIRES';
package Time::HiRes;
{ use 5.006; }
use strict;
require Exporter;
require DynaLoader;
our @ISA = qw(Exporter DynaLoader);
our @EXPORT = qw( );
our @EXPORT_OK = qw (usleep sleep ualarm alarm gettimeofday time tv_interval
getitimer setitimer nanosleep clock_gettime clock_getres
clock clock_nanosleep
CLOCK_HIGHRES CLOCK_MONOTONIC CLOCK_PROCESS_CPUTIME_ID
CLOCK_REALTIME CLOCK_SOFTTIME CLOCK_THREAD_CPUTIME_ID
CLOCK_TIMEOFDAY CLOCKS_PER_SEC
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF
TIMER_ABSTIME
d_usleep d_ualarm d_gettimeofday d_getitimer d_setitimer
d_nanosleep d_clock_gettime d_clock_getres
d_clock d_clock_nanosleep
stat
);
our $VERSION = '1.9724';
our $XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
our $AUTOLOAD;
sub AUTOLOAD {
my $constname;
($constname = $AUTOLOAD) =~ s/.*:://;
# print "AUTOLOAD: constname = $constname ($AUTOLOAD)\n";
die "&Time::HiRes::constant not defined" if $constname eq 'constant';
my ($error, $val) = constant($constname);
# print "AUTOLOAD: error = $error, val = $val\n";
if ($error) {
my (undef,$file,$line) = caller;
die "$error at $file line $line.\n";
}
{
no strict 'refs';
*$AUTOLOAD = sub { $val };
}
goto &$AUTOLOAD;
}
sub import {
my $this = shift;
for my $i (@_) {
if (($i eq 'clock_getres' && !&d_clock_getres) ||
($i eq 'clock_gettime' && !&d_clock_gettime) ||
($i eq 'clock_nanosleep' && !&d_clock_nanosleep) ||
($i eq 'clock' && !&d_clock) ||
($i eq 'nanosleep' && !&d_nanosleep) ||
($i eq 'usleep' && !&d_usleep) ||
($i eq 'ualarm' && !&d_ualarm)) {
require Carp;
Carp::croak("Time::HiRes::$i(): unimplemented in this platform");
}
}
Time::HiRes->export_to_level(1, $this, @_);
}
bootstrap Time::HiRes;
# Preloaded methods go here.
sub tv_interval {
# probably could have been done in C
my ($a, $b) = @_;
$b = [gettimeofday()] unless defined($b);
(${$b}[0] - ${$a}[0]) + ((${$b}[1] - ${$a}[1]) / 1_000_000);
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
=head1 NAME
Time::HiRes - High resolution alarm, sleep, gettimeofday, interval timers
=head1 SYNOPSIS
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval nanosleep
clock_gettime clock_getres clock_nanosleep clock
stat );
usleep ($microseconds);
nanosleep ($nanoseconds);
ualarm ($microseconds);
ualarm ($microseconds, $interval_microseconds);
$t0 = [gettimeofday];
($seconds, $microseconds) = gettimeofday;
$elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
$elapsed = tv_interval ( $t0, [gettimeofday]);
$elapsed = tv_interval ( $t0 );
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep ($floating_seconds);
alarm ($floating_seconds);
alarm ($floating_seconds, $floating_interval);
use Time::HiRes qw( setitimer getitimer );
setitimer ($which, $floating_seconds, $floating_interval );
getitimer ($which);
use Time::HiRes qw( clock_gettime clock_getres clock_nanosleep
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF );
$realtime = clock_gettime(CLOCK_REALTIME);
$resolution = clock_getres(CLOCK_REALTIME);
clock_nanosleep(CLOCK_REALTIME, 1.5e9);
clock_nanosleep(CLOCK_REALTIME, time()*1e9 + 10e9, TIMER_ABSTIME);
my $ticktock = clock();
use Time::HiRes qw( stat );
my @stat = stat("file");
my @stat = stat(FH);
=head1 DESCRIPTION
The C<Time::HiRes> module implements a Perl interface to the
C<usleep>, C<nanosleep>, C<ualarm>, C<gettimeofday>, and
C<setitimer>/C<getitimer> system calls, in other words, high
resolution time and timers. See the L</EXAMPLES> section below and the
test scripts for usage; see your system documentation for the
description of the underlying C<nanosleep> or C<usleep>, C<ualarm>,
C<gettimeofday>, and C<setitimer>/C<getitimer> calls.
If your system lacks C<gettimeofday()> or an emulation of it you don't
get C<gettimeofday()> or the one-argument form of C<tv_interval()>.
If your system lacks all of C<nanosleep()>, C<usleep()>,
C<select()>, and C<poll>, you don't get C<Time::HiRes::usleep()>,
C<Time::HiRes::nanosleep()>, or C<Time::HiRes::sleep()>.
If your system lacks both C<ualarm()> and C<setitimer()> you don't get
C<Time::HiRes::ualarm()> or C<Time::HiRes::alarm()>.
If you try to import an unimplemented function in the C<use> statement
it will fail at compile time.
If your subsecond sleeping is implemented with C<nanosleep()> instead
of C<usleep()>, you can mix subsecond sleeping with signals since
C<nanosleep()> does not use signals. This, however, is not portable,
and you should first check for the truth value of
C<&Time::HiRes::d_nanosleep> to see whether you have nanosleep, and
then carefully read your C<nanosleep()> C API documentation for any
peculiarities.
If you are using C<nanosleep> for something else than mixing sleeping
with signals, give some thought to whether Perl is the tool you should
be using for work requiring nanosecond accuracies.
Remember that unless you are working on a I<hard realtime> system,
any clocks and timers will be imprecise, especially so if you are working
in a pre-emptive multiuser system. Understand the difference between
I<wallclock time> and process time (in UNIX-like systems the sum of
I<user> and I<system> times). Any attempt to sleep for X seconds will
most probably end up sleeping B<more> than that, but don't be surpised
if you end up sleeping slightly B<less>.
The following functions can be imported from this module.
No functions are exported by default.
=over 4
=item gettimeofday ()
In array context returns a two-element array with the seconds and
microseconds since the epoch. In scalar context returns floating
seconds like C<Time::HiRes::time()> (see below).
=item usleep ( $useconds )
Sleeps for the number of microseconds (millionths of a second)
specified. Returns the number of microseconds actually slept.
Can sleep for more than one second, unlike the C<usleep> system call.
Can also sleep for zero seconds, which often works like a I<thread yield>.
See also C<Time::HiRes::usleep()>, C<Time::HiRes::sleep()>, and
C<Time::HiRes::clock_nanosleep()>.
Do not expect usleep() to be exact down to one microsecond.
=item nanosleep ( $nanoseconds )
Sleeps for the number of nanoseconds (1e9ths of a second) specified.
Returns the number of nanoseconds actually slept (accurate only to
microseconds, the nearest thousand of them). Can sleep for more than
one second. Can also sleep for zero seconds, which often works like
a I<thread yield>. See also C<Time::HiRes::sleep()>,
C<Time::HiRes::usleep()>, and C<Time::HiRes::clock_nanosleep()>.
Do not expect nanosleep() to be exact down to one nanosecond.
Getting even accuracy of one thousand nanoseconds is good.
=item ualarm ( $useconds [, $interval_useconds ] )
Issues a C<ualarm> call; the C<$interval_useconds> is optional and
will be zero if unspecified, resulting in C<alarm>-like behaviour.
Returns the remaining time in the alarm in microseconds, or C<undef>
if an error occurred.
ualarm(0) will cancel an outstanding ualarm().
Note that the interaction between alarms and sleeps is unspecified.
=item tv_interval
tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
Returns the floating seconds between the two times, which should have
been returned by C<gettimeofday()>. If the second argument is omitted,
then the current time is used.
=item time ()
Returns a floating seconds since the epoch. This function can be
imported, resulting in a nice drop-in replacement for the C<time>
provided with core Perl; see the L</EXAMPLES> below.
B<NOTE 1>: This higher resolution timer can return values either less
or more than the core C<time()>, depending on whether your platform
rounds the higher resolution timer values up, down, or to the nearest second
to get the core C<time()>, but naturally the difference should be never
more than half a second. See also L</clock_getres>, if available
in your system.
B<NOTE 2>: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT, when
the C<time()> seconds since epoch rolled over to 1_000_000_000, the
default floating point format of Perl and the seconds since epoch have
conspired to produce an apparent bug: if you print the value of
C<Time::HiRes::time()> you seem to be getting only five decimals, not
six as promised (microseconds). Not to worry, the microseconds are
there (assuming your platform supports such granularity in the first
place). What is going on is that the default floating point format of
Perl only outputs 15 digits. In this case that means ten digits
before the decimal separator and five after. To see the microseconds
you can use either C<printf>/C<sprintf> with C<"%.6f">, or the
C<gettimeofday()> function in list context, which will give you the
seconds and microseconds as two separate values.
=item sleep ( $floating_seconds )
Sleeps for the specified amount of seconds. Returns the number of
seconds actually slept (a floating point value). This function can
be imported, resulting in a nice drop-in replacement for the C<sleep>
provided with perl, see the L</EXAMPLES> below.
Note that the interaction between alarms and sleeps is unspecified.
=item alarm ( $floating_seconds [, $interval_floating_seconds ] )
The C<SIGALRM> signal is sent after the specified number of seconds.
Implemented using C<setitimer()> if available, C<ualarm()> if not.
The C<$interval_floating_seconds> argument is optional and will be
zero if unspecified, resulting in C<alarm()>-like behaviour. This
function can be imported, resulting in a nice drop-in replacement for
the C<alarm> provided with perl, see the L</EXAMPLES> below.
Returns the remaining time in the alarm in seconds, or C<undef>
if an error occurred.
B<NOTE 1>: With some combinations of operating systems and Perl
releases C<SIGALRM> restarts C<select()>, instead of interrupting it.
This means that an C<alarm()> followed by a C<select()> may together
take the sum of the times specified for the the C<alarm()> and the
C<select()>, not just the time of the C<alarm()>.
Note that the interaction between alarms and sleeps is unspecified.
=item setitimer ( $which, $floating_seconds [, $interval_floating_seconds ] )
Start up an interval timer: after a certain time, a signal ($which) arrives,
and more signals may keep arriving at certain intervals. To disable
an "itimer", use C<$floating_seconds> of zero. If the
C<$interval_floating_seconds> is set to zero (or unspecified), the
timer is disabled B<after> the next delivered signal.
Use of interval timers may interfere with C<alarm()>, C<sleep()>,
and C<usleep()>. In standard-speak the "interaction is unspecified",
which means that I<anything> may happen: it may work, it may not.
In scalar context, the remaining time in the timer is returned.
In list context, both the remaining time and the interval are returned.
There are usually three or four interval timers (signals) available: the
C<$which> can be C<ITIMER_REAL>, C<ITIMER_VIRTUAL>, C<ITIMER_PROF>, or
C<ITIMER_REALPROF>. Note that which ones are available depends: true
UNIX platforms usually have the first three, but only Solaris seems to
have C<ITIMER_REALPROF> (which is used to profile multithreaded programs).
Win32 unfortunately does not haveinterval timers.
C<ITIMER_REAL> results in C<alarm()>-like behaviour. Time is counted in
I<real time>; that is, wallclock time. C<SIGALRM> is delivered when
the timer expires.
C<ITIMER_VIRTUAL> counts time in (process) I<virtual time>; that is,
only when the process is running. In multiprocessor/user/CPU systems
this may be more or less than real or wallclock time. (This time is
also known as the I<user time>.) C<SIGVTALRM> is delivered when the
timer expires.
C<ITIMER_PROF> counts time when either the process virtual time or when
the operating system is running on behalf of the process (such as I/O).
(This time is also known as the I<system time>.) (The sum of user
time and system time is known as the I<CPU time>.) C<SIGPROF> is
delivered when the timer expires. C<SIGPROF> can interrupt system calls.
The semantics of interval timers for multithreaded programs are
system-specific, and some systems may support additional interval
timers. For example, it is unspecified which thread gets the signals.
See your C<setitimer()> documentation.
=item getitimer ( $which )
Return the remaining time in the interval timer specified by C<$which>.
In scalar context, the remaining time is returned.
In list context, both the remaining time and the interval are returned.
The interval is always what you put in using C<setitimer()>.
=item clock_gettime ( $which )
Return as seconds the current value of the POSIX high resolution timer
specified by C<$which>. All implementations that support POSIX high
resolution timers are supposed to support at least the C<$which> value
of C<CLOCK_REALTIME>, which is supposed to return results close to the
results of C<gettimeofday>, or the number of seconds since 00:00:00:00
January 1, 1970 Greenwich Mean Time (GMT). Do not assume that
CLOCK_REALTIME is zero, it might be one, or something else.
Another potentially useful (but not available everywhere) value is
C<CLOCK_MONOTONIC>, which guarantees a monotonically increasing time
value (unlike time() or gettimeofday(), which can be adjusted).
See your system documentation for other possibly supported values.
=item clock_getres ( $which )
Return as seconds the resolution of the POSIX high resolution timer
specified by C<$which>. All implementations that support POSIX high
resolution timers are supposed to support at least the C<$which> value
of C<CLOCK_REALTIME>, see L</clock_gettime>.
=item clock_nanosleep ( $which, $nanoseconds, $flags = 0)
Sleeps for the number of nanoseconds (1e9ths of a second) specified.
Returns the number of nanoseconds actually slept. The $which is the
"clock id", as with clock_gettime() and clock_getres(). The flags
default to zero but C<TIMER_ABSTIME> can specified (must be exported
explicitly) which means that C<$nanoseconds> is not a time interval
(as is the default) but instead an absolute time. Can sleep for more
than one second. Can also sleep for zero seconds, which often works
like a I<thread yield>. See also C<Time::HiRes::sleep()>,
C<Time::HiRes::usleep()>, and C<Time::HiRes::nanosleep()>.
Do not expect clock_nanosleep() to be exact down to one nanosecond.
Getting even accuracy of one thousand nanoseconds is good.
=item clock()
Return as seconds the I<process time> (user + system time) spent by
the process since the first call to clock() (the definition is B<not>
"since the start of the process", though if you are lucky these times
may be quite close to each other, depending on the system). What this
means is that you probably need to store the result of your first call
to clock(), and subtract that value from the following results of clock().
The time returned also includes the process times of the terminated
child processes for which wait() has been executed. This value is
somewhat like the second value returned by the times() of core Perl,
but not necessarily identical. Note that due to backward
compatibility limitations the returned value may wrap around at about
2147 seconds or at about 36 minutes.
=item stat
=item stat FH
=item stat EXPR
As L<perlfunc/stat> but with the access/modify/change file timestamps
in subsecond resolution, if the operating system and the filesystem
both support such timestamps. To override the standard stat():
use Time::HiRes qw(stat);
Test for the value of &Time::HiRes::d_hires_stat to find out whether
the operating system supports subsecond file timestamps: a value
larger than zero means yes. There are unfortunately no easy
ways to find out whether the filesystem supports such timestamps.
UNIX filesystems often do; NTFS does; FAT doesn't (FAT timestamp
granularity is B<two> seconds).
A zero return value of &Time::HiRes::d_hires_stat means that
Time::HiRes::stat is a no-op passthrough for CORE::stat(),
and therefore the timestamps will stay integers. The same
thing will happen if the filesystem does not do subsecond timestamps,
even if the &Time::HiRes::d_hires_stat is non-zero.
In any case do not expect nanosecond resolution, or even a microsecond
resolution. Also note that the modify/access timestamps might have
different resolutions, and that they need not be synchronized, e.g.
if the operations are
write
stat # t1
read
stat # t2
the access time stamp from t2 need not be greater-than the modify
time stamp from t1: it may be equal or I<less>.
=back
=head1 EXAMPLES
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
$microseconds = 750_000;
usleep($microseconds);
# signal alarm in 2.5s & every .1s thereafter
ualarm(2_500_000, 100_000);
# cancel that ualarm
ualarm(0);
# get seconds and microseconds since the epoch
($s, $usec) = gettimeofday();
# measure elapsed time
# (could also do by subtracting 2 gettimeofday return values)
$t0 = [gettimeofday];
# do bunch of stuff here
$t1 = [gettimeofday];
# do more stuff here
$t0_t1 = tv_interval $t0, $t1;
$elapsed = tv_interval ($t0, [gettimeofday]);
$elapsed = tv_interval ($t0); # equivalent code
#
# replacements for time, alarm and sleep that know about
# floating seconds
#
use Time::HiRes;
$now_fractions = Time::HiRes::time;
Time::HiRes::sleep (2.5);
Time::HiRes::alarm (10.6666666);
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep (2.5);
alarm (10.6666666);
# Arm an interval timer to go off first at 10 seconds and
# after that every 2.5 seconds, in process virtual time
use Time::HiRes qw ( setitimer ITIMER_VIRTUAL time );
$SIG{VTALRM} = sub { print time, "\n" };
setitimer(ITIMER_VIRTUAL, 10, 2.5);
use Time::HiRes qw( clock_gettime clock_getres CLOCK_REALTIME );
# Read the POSIX high resolution timer.
my $high = clock_getres(CLOCK_REALTIME);
# But how accurate we can be, really?
my $reso = clock_getres(CLOCK_REALTIME);
use Time::HiRes qw( clock_nanosleep TIMER_ABSTIME );
clock_nanosleep(CLOCK_REALTIME, 1e6);
clock_nanosleep(CLOCK_REALTIME, 2e9, TIMER_ABSTIME);
use Time::HiRes qw( clock );
my $clock0 = clock();
... # Do something.
my $clock1 = clock();
my $clockd = $clock1 - $clock0;
use Time::HiRes qw( stat );
my ($atime, $mtime, $ctime) = (stat("istics"))[8, 9, 10];
=head1 C API
In addition to the perl API described above, a C API is available for
extension writers. The following C functions are available in the
modglobal hash:
name C prototype
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(pTHX_ UV ret[2])
Both functions return equivalent information (like C<gettimeofday>)
but with different representations. The names C<NVtime> and C<U2time>
were selected mainly because they are operating system independent.
(C<gettimeofday> is Unix-centric, though some platforms like Win32 and
VMS have emulations for it.)
Here is an example of using C<NVtime> from C:
double (*myNVtime)(); /* Returns -1 on failure. */
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
=head1 DIAGNOSTICS
=head2 useconds or interval more than ...
In ualarm() you tried to use number of microseconds or interval (also
in microseconds) more than 1_000_000 and setitimer() is not available
in your system to emulate that case.
=head2 negative time not invented yet
You tried to use a negative time argument.
=head2 internal error: useconds < 0 (unsigned ... signed ...)
Something went horribly wrong-- the number of microseconds that cannot
become negative just became negative. Maybe your compiler is broken?
=head2 useconds or uinterval equal to or more than 1000000
In some platforms it is not possible to get an alarm with subsecond
resolution and later than one second.
=head2 unimplemented in this platform
Some calls simply aren't available, real or emulated, on every platform.
=head1 CAVEATS
Notice that the core C<time()> maybe rounding rather than truncating.
What this means is that the core C<time()> may be reporting the time
as one second later than C<gettimeofday()> and C<Time::HiRes::time()>.
Adjusting the system clock (either manually or by services like ntp)
may cause problems, especially for long running programs that assume
a monotonously increasing time (note that all platforms do not adjust
time as gracefully as UNIX ntp does). For example in Win32 (and derived
platforms like Cygwin and MinGW) the Time::HiRes::time() may temporarily
drift off from the system clock (and the original time()) by up to 0.5
seconds. Time::HiRes will notice this eventually and recalibrate.
Note that since Time::HiRes 1.77 the clock_gettime(CLOCK_MONOTONIC)
might help in this (in case your system supports CLOCK_MONOTONIC).
Some systems have APIs but not implementations: for example QNX and Haiku
have the interval timer APIs but not the functionality.
=head1 SEE ALSO
Perl modules L<BSD::Resource>, L<Time::TAI64>.
Your system documentation for C<clock>, C<clock_gettime>,
C<clock_getres>, C<clock_nanosleep>, C<clock_settime>, C<getitimer>,
C<gettimeofday>, C<setitimer>, C<sleep>, C<stat>, C<ualarm>.
=head1 AUTHORS
D. Wegscheid <wegscd@whirlpool.com>
R. Schertler <roderick@argon.org>
J. Hietaniemi <jhi@iki.fi>
G. Aas <gisle@aas.no>
=head1 COPYRIGHT AND LICENSE
Copyright (c) 1996-2002 Douglas E. Wegscheid. All rights reserved.
Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Jarkko Hietaniemi.
All rights reserved.
Copyright (C) 2011 Andrew Main (Zefram) <zefram@fysh.org>
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
DARWIN-2LEVEL_TIME_HIRES
$fatpacked{"darwin-2level/version.pm"} = <<'DARWIN-2LEVEL_VERSION';
#!perl -w
package version;
use 5.005_04;
use strict;
use vars qw(@ISA $VERSION $CLASS $STRICT $LAX *declare *qv);
$VERSION = 0.94;
$CLASS = 'version';
#--------------------------------------------------------------------------#
# Version regexp components
#--------------------------------------------------------------------------#
# Fraction part of a decimal version number. This is a common part of
# both strict and lax decimal versions
my $FRACTION_PART = qr/\.[0-9]+/;
# First part of either decimal or dotted-decimal strict version number.
# Unsigned integer with no leading zeroes (except for zero itself) to
# avoid confusion with octal.
my $STRICT_INTEGER_PART = qr/0|[1-9][0-9]*/;
# First part of either decimal or dotted-decimal lax version number.
# Unsigned integer, but allowing leading zeros. Always interpreted
# as decimal. However, some forms of the resulting syntax give odd
# results if used as ordinary Perl expressions, due to how perl treats
# octals. E.g.
# version->new("010" ) == 10
# version->new( 010 ) == 8
# version->new( 010.2) == 82 # "8" . "2"
my $LAX_INTEGER_PART = qr/[0-9]+/;
# Second and subsequent part of a strict dotted-decimal version number.
# Leading zeroes are permitted, and the number is always decimal.
# Limited to three digits to avoid overflow when converting to decimal
# form and also avoid problematic style with excessive leading zeroes.
my $STRICT_DOTTED_DECIMAL_PART = qr/\.[0-9]{1,3}/;
# Second and subsequent part of a lax dotted-decimal version number.
# Leading zeroes are permitted, and the number is always decimal. No
# limit on the numerical value or number of digits, so there is the
# possibility of overflow when converting to decimal form.
my $LAX_DOTTED_DECIMAL_PART = qr/\.[0-9]+/;
# Alpha suffix part of lax version number syntax. Acts like a
# dotted-decimal part.
my $LAX_ALPHA_PART = qr/_[0-9]+/;
#--------------------------------------------------------------------------#
# Strict version regexp definitions
#--------------------------------------------------------------------------#
# Strict decimal version number.
my $STRICT_DECIMAL_VERSION =
qr/ $STRICT_INTEGER_PART $FRACTION_PART? /x;
# Strict dotted-decimal version number. Must have both leading "v" and
# at least three parts, to avoid confusion with decimal syntax.
my $STRICT_DOTTED_DECIMAL_VERSION =
qr/ v $STRICT_INTEGER_PART $STRICT_DOTTED_DECIMAL_PART{2,} /x;
# Complete strict version number syntax -- should generally be used
# anchored: qr/ \A $STRICT \z /x
$STRICT =
qr/ $STRICT_DECIMAL_VERSION | $STRICT_DOTTED_DECIMAL_VERSION /x;
#--------------------------------------------------------------------------#
# Lax version regexp definitions
#--------------------------------------------------------------------------#
# Lax decimal version number. Just like the strict one except for
# allowing an alpha suffix or allowing a leading or trailing
# decimal-point
my $LAX_DECIMAL_VERSION =
qr/ $LAX_INTEGER_PART (?: \. | $FRACTION_PART $LAX_ALPHA_PART? )?
|
$FRACTION_PART $LAX_ALPHA_PART?
/x;
# Lax dotted-decimal version number. Distinguished by having either
# leading "v" or at least three non-alpha parts. Alpha part is only
# permitted if there are at least two non-alpha parts. Strangely
# enough, without the leading "v", Perl takes .1.2 to mean v0.1.2,
# so when there is no "v", the leading part is optional
my $LAX_DOTTED_DECIMAL_VERSION =
qr/
v $LAX_INTEGER_PART (?: $LAX_DOTTED_DECIMAL_PART+ $LAX_ALPHA_PART? )?
|
$LAX_INTEGER_PART? $LAX_DOTTED_DECIMAL_PART{2,} $LAX_ALPHA_PART?
/x;
# Complete lax version number syntax -- should generally be used
# anchored: qr/ \A $LAX \z /x
#
# The string 'undef' is a special case to make for easier handling
# of return values from ExtUtils::MM->parse_version
$LAX =
qr/ undef | $LAX_DECIMAL_VERSION | $LAX_DOTTED_DECIMAL_VERSION /x;
#--------------------------------------------------------------------------#
{
local $SIG{'__DIE__'};
eval "use version::vxs $VERSION";
if ( $@ ) { # don't have the XS version installed
eval "use version::vpp $VERSION"; # don't tempt fate
die "$@" if ( $@ );
push @ISA, "version::vpp";
local $^W;
*version::qv = \&version::vpp::qv;
*version::declare = \&version::vpp::declare;
*version::_VERSION = \&version::vpp::_VERSION;
if ($] >= 5.009000) {
no strict 'refs';
*version::stringify = \&version::vpp::stringify;
*{'version::(""'} = \&version::vpp::stringify;
*version::new = \&version::vpp::new;
*version::parse = \&version::vpp::parse;
}
}
else { # use XS module
push @ISA, "version::vxs";
local $^W;
*version::declare = \&version::vxs::declare;
*version::qv = \&version::vxs::qv;
*version::_VERSION = \&version::vxs::_VERSION;
*version::vcmp = \&version::vxs::VCMP;
if ($] >= 5.009000) {
no strict 'refs';
*version::stringify = \&version::vxs::stringify;
*{'version::(""'} = \&version::vxs::stringify;
*version::new = \&version::vxs::new;
*version::parse = \&version::vxs::parse;
}
}
}
# Preloaded methods go here.
sub import {
no strict 'refs';
my ($class) = shift;
# Set up any derived class
unless ($class eq 'version') {
local $^W;
*{$class.'::declare'} = \&version::declare;
*{$class.'::qv'} = \&version::qv;
}
my %args;
if (@_) { # any remaining terms are arguments
map { $args{$_} = 1 } @_
}
else { # no parameters at all on use line
%args =
(
qv => 1,
'UNIVERSAL::VERSION' => 1,
);
}
my $callpkg = caller();
if (exists($args{declare})) {
*{$callpkg.'::declare'} =
sub {return $class->declare(shift) }
unless defined(&{$callpkg.'::declare'});
}
if (exists($args{qv})) {
*{$callpkg.'::qv'} =
sub {return $class->qv(shift) }
unless defined(&{$callpkg.'::qv'});
}
if (exists($args{'UNIVERSAL::VERSION'})) {
local $^W;
*UNIVERSAL::VERSION
= \&version::_VERSION;
}
if (exists($args{'VERSION'})) {
*{$callpkg.'::VERSION'} = \&version::_VERSION;
}
if (exists($args{'is_strict'})) {
*{$callpkg.'::is_strict'} = \&version::is_strict
unless defined(&{$callpkg.'::is_strict'});
}
if (exists($args{'is_lax'})) {
*{$callpkg.'::is_lax'} = \&version::is_lax
unless defined(&{$callpkg.'::is_lax'});
}
}
sub is_strict { defined $_[0] && $_[0] =~ qr/ \A $STRICT \z /x }
sub is_lax { defined $_[0] && $_[0] =~ qr/ \A $LAX \z /x }
1;
DARWIN-2LEVEL_VERSION
$fatpacked{"darwin-2level/version/vxs.pm"} = <<'DARWIN-2LEVEL_VERSION_VXS';
#!perl -w
package version::vxs;
use 5.005_03;
use strict;
use vars qw(@ISA $VERSION $CLASS );
$VERSION = 0.94;
$CLASS = 'version::vxs';
eval {
require XSLoader;
local $^W; # shut up the 'redefined' warning for UNIVERSAL::VERSION
XSLoader::load('version::vxs', $VERSION);
1;
} or do {
require DynaLoader;
push @ISA, 'DynaLoader';
local $^W; # shut up the 'redefined' warning for UNIVERSAL::VERSION
bootstrap version::vxs $VERSION;
};
# Preloaded methods go here.
1;
DARWIN-2LEVEL_VERSION_VXS
s/^ //mg for values %fatpacked;
unshift @INC, sub {
if (my $fat = $fatpacked{$_[1]}) {
open my $fh, '<', \$fat
or die "FatPacker error loading $_[1] (could be a perl installation issue?)";
return $fh;
}
return
};
} # END OF FATPACK CODE
#!/Users/gugod/perl5/perlbrew/perls/perl-5.14.1/bin/perl
eval 'exec /Users/gugod/perl5/perlbrew/perls/perl-5.14.1/bin/perl -S $0 ${1+"$@"}'
if 0; # not running under some shell
package
patchperl;
# ABSTRACT: patch a perl source tree
use strict;
use warnings;
use Devel::PatchPerl;
Devel::PatchPerl->patch_source($ARGV[1], $ARGV[0]);
__END__
=pod
=head1 NAME
patchperl - patch a perl source tree
=head1 VERSION
version 0.52
=head1 AUTHOR
Chris Williams <chris@bingosnet.co.uk>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2011 by Chris Williams and Marcus Holland-Moritz.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment