--- /dev/null
+#!/usr/bin/perl -w
+
+BEGIN { our $NO_INIT = 1 }
+
+use strict;
+use lib "lib", "inc";
+use My::Build;
+
+our( $TYPE, $URL );
+
+my %VERSIONS =
+ ( '2.8.10' => 'patches/data-2.8.10',
+ '2.9.0' => 'patches/data-2.9.0',
+ );
+my $DEFAULT_VERSION = '2.8.10';
+
+# new_from_context is broken: it does not restore
+# @INC set in Build.PL before trying to load a base class not
+# defined using ->subclass...
+my $class = Module::Build->subclass
+ ( class => 'My::Build::new_from_context_is_broken',
+ code => <<'EOC' );
+use lib qw(lib inc);
+@ISA = qw(My::Build Module::Build);
+require My::Build;
+EOC
+my $build = $class->new
+ ( module_name => 'Alien::wxWidgets',
+ license => 'perl',
+ author => 'Mattia Barbon <mbarbon@cpan.org>',
+ requires => { perl => '5.006',
+ 'Module::Pluggable' => '2.6',
+ },
+ build_requires => { 'Module::Build' => '0.28',
+ 'ExtUtils::CBuilder' => '0.24',
+ },
+ configure_requires => { 'Module::Build' => '0.28',
+ },
+ get_options => { 'wxWidgets-debug' => { type => '!' },
+ 'wxWidgets-unicode' => { type => '!' },
+ 'wxWidgets-mslu' => { type => '!' },
+ 'wxWidgets-static' => { type => '!' },
+ 'wxWidgets-monolithic' => { type => '!' },
+ 'wxWidgets-universal' => { type => '!' },
+ 'wxWidgets-build' => { type => '!' },
+ 'wxWidgets-portable' => { type => '!',
+ default => $^O eq 'MSWin32' },
+ 'wxWidgets-build-opengl' => { type => '!' },
+ 'wxWidgets-source' => { type => '=s' },
+ 'wxWidgets-version' => { type => '=s' },
+ },
+ create_makefile_pl => 'passthrough',
+ meta_merge =>
+ { resources =>
+ { 'license' => 'http://dev.perl.org/licenses/',
+ 'homepage' => 'http://wxperl.eu/',
+ 'bugtracker' => 'http://rt.cpan.org/NoAuth/Bugs.html?Dist=Alien-wxWidgets',
+ 'repository' => 'https://wxperl.svn.sourceforge.net/svnroot/wxperl/Alien-wxWidgets',
+ 'MailingList' => 'http://lists.perl.org/list/wxperl-users.html',
+ },
+ },
+ );
+
+my $accept_defaults = $ENV{PERL5_CPANPLUS_IS_RUNNING}
+ || $ENV{CPAN_SHELL_LEVEL};
+my $build_wx_dflt = 'yes';
+my $build_wx_opengl_dflt = 'yes';
+my $build_prompt = 'Do you want to fetch and build wxWidgets from sources?';
+my $have_alien_configuration = 0;
+
+# try to detect if wxWidgets has been installed using Alien::wxWidgets and if
+# it is the latest version; the rule is:
+#
+# if there is any any wxWidgets installation registered with Alien::wxWidgets
+# it will only get upgraded if it was compiled using Alien::wxWidgets itself and
+# it is older than $DEFAULT_VERSION
+my $ok = eval {
+ require Alien::wxWidgets;
+ require File::Basename;
+ require File::Spec;
+ require Cwd;
+
+ $DEFAULT_VERSION =~ m/^(\d+)\.(\d+)\.(\d+)$/ or die "Wrong default version";
+ my $install_version = $1 + $2 / 1000 + $3 / 1000000;
+ my @configs = Alien::wxWidgets->get_configurations;
+
+ $build_wx_dflt = 'no' if @configs;
+ $have_alien_configuration = @configs;
+
+ foreach my $config ( @configs ) {
+ last if $config->{version} >= $install_version;
+
+ # installed version is older than $DEFAULT_VERSION, check if it
+ # has been installed using Alien::wxWidgets
+ my %values = $config->{package}->values;
+ ( my $pm_filename = $config->{package} . '.pm' ) =~ s{::}{/}g;
+ my $pm_file = $INC{$pm_filename};
+ my $pm_path = File::Spec->catdir( File::Basename::dirname( $pm_file ),
+ File::Spec->updir );
+ my $prefix = File::Spec->catdir( $values{prefix}, File::Spec->updir );
+
+ if( Cwd::realpath( $pm_path ) eq Cwd::realpath( $prefix ) ) {
+ $build_wx_dflt = 'yes';
+ }
+ }
+
+ 1;
+};
+# if anything went wrong in the autodetection, revert to the correct
+# default
+if( !$ok ) {
+ $build_wx_dflt = 'yes';
+}
+
+# detect wxWidgets using WXDIR/WXWIN environment variables on Win32
+# and wx-config on other platforms
+if( $^O eq 'MSWin32' && ( $ENV{WXWIN} || $ENV{WXDIR} ) ) {
+ $build_wx_dflt = 'no';
+ $build_prompt = sprintf <<EOP, ( $ENV{WXWIN} || $ENV{WXDIR} );
+A wxWidgets build seems to be in '%s', so it should be safe to answer
+'no' to the following question
+
+$build_prompt
+EOP
+} else {
+ require My::Build::Base;
+ my $wx_config = My::Build::Base->awx_path_search( 'wx-config' );
+ if( $wx_config ) {
+ my $ans = `wx-config --version`;
+ if( $ans =~ /^2\./ ) {
+ my $prefix = `wx-config --prefix`;
+ chomp foreach $ans, $prefix;
+ $build_wx_dflt = 'no' ;
+ $build_prompt = sprintf <<EOP, $ans, $prefix;
+wxWidgets %s seems to be installed in '%s', so it should be safe to
+answer 'no' to the following question:
+
+$build_prompt
+EOP
+ }
+ }
+}
+if( $^O ne 'darwin' && $^O ne 'MSWin32' ) {
+ $build_wx_opengl_dflt = 'no';
+}
+if( $ENV{AWX_URL} ) {
+ $build_wx_dflt = 'yes';
+}
+if( $ENV{AUTOMATED_TESTING} ) {
+ if( $^O ne 'darwin' && $^O ne 'MSWin32' ) {
+ my $pkg_config = $ENV{PKG_CONFIG} || 'pkg-config';
+ my $ans = `$pkg_config --modversion gtk+-2.0 2>&1`;
+ unless( $ans =~ /^2\./ ) {
+ print <<EOT;
+Could not detect GTK+ 2 by running '$pkg_config': aborting
+
+== pkg-config output: ====================================
+$ans==========================================================
+EOT
+ exit 0;
+ }
+ }
+ if( $^O eq 'solaris' )
+ {
+ my $ans = `gmake -v`;
+ unless( $ans =~ /gnu make/i ) {
+ print <<EOT;
+Could not find GNU Make as 'gmake': aborting
+EOT
+ exit 0;
+ }
+ }
+}
+chomp $build_prompt;
+my $build_wx = _askyn( $build, 'wxWidgets-build',
+ $build_prompt, $build_wx_dflt );
+my $wx_version;
+$build->notes( 'build_wx' => $build_wx );
+$build->notes( 'mk_portable' => $build->args('wxWidgets-portable') );
+$build->notes( 'install_only' => $have_alien_configuration && !$build_wx && $accept_defaults );
+if( $build_wx ) {
+ $wx_version = _askmulti( $build, 'wxWidgets-version',
+ 'Which wxWidgets version?',
+ [ sort keys %VERSIONS ], $DEFAULT_VERSION );
+ $TYPE = _ask( $build, 'wxWidgets-source', 'Which archive type?', 'tar.gz' );
+ $URL = $ENV{AWX_URL};
+ $build->notes( 'build_data' => do $VERSIONS{$wx_version} );
+}
+if( $build_wx && $wx_version !~ /^2\.9/ ) {
+ my $build_wx_unicode = _askyn( $build, 'wxWidgets-unicode',
+ 'Do you want to enable Unicode support',
+ 'yes' );
+ $build->notes( 'build_wx_unicode' => $build_wx_unicode );
+} elsif( $build_wx ) {
+ # Unicode-only for 2.9.x and higher
+ $build->notes( 'build_wx_unicode' => 1 );
+}
+if( $build_wx ) {
+ my $build_wx_opengl = _askyn( $build, 'wxWidgets-build-opengl',
+ 'Do you want to include OpenGL support',
+ $build_wx_opengl_dflt );
+ $build->notes( 'build_wx_opengl' => $build_wx_opengl );
+}
+
+$build->create_build_script;
+
+sub _is_yes {
+ return lc( $_[0] ) eq 'y' || lc( $_[0] ) eq 'yes';
+}
+
+sub _askyn {
+ my( $build, $arg, $question, $default ) = @_;
+ my $res =
+ defined $build->args( $arg ) ? _is_yes( $build->args( $arg ) ) :
+ exists $ENV{"AWX_\U$arg"} ? _is_yes( $ENV{"AWX_\U$arg"} ) :
+ $accept_defaults ? _is_yes( $default ) :
+ $build->y_n( $question, $default );
+
+ return $res
+}
+
+sub _askmulti {
+ my( $build, $arg, $question, $options, $default ) = @_;
+ $question .= " (" . join( ', ', @$options ) . ")";
+ my $res =
+ defined $build->args( $arg ) ? $build->args( $arg ) :
+ exists $ENV{"AWX_\U$arg"} ? $ENV{"AWX_\U$arg"} :
+ $accept_defaults ? $default :
+ $build->prompt( $question, $default );
+
+ die "Invalid value '$res' for option '$arg': must be one of ",
+ join( ', ', map "'$_'", @$options ), "\n"
+ unless grep $_ eq $res, @$options;
+
+ return $res
+}
+
+sub _ask {
+ my( $build, $arg, $question, $default ) = @_;
+ my $res =
+ defined $build->args( $arg ) ? $build->args( $arg ) :
+ exists $ENV{"AWX_\U$arg"} ? $ENV{"AWX_\U$arg"} :
+ $accept_defaults ? $default :
+ $build->prompt( $question, $default );
+
+ return $res
+}
--- /dev/null
+Revision history for Perl extension Alien::wxWidgets.
+
+0.50 Sun Jan 10 16:16:44 CET 2010
+ - When compiling on Windows with MSVC 9, make the generated
+ wxWidgets DLL load correctly by adding a manifest to them
+ (suggested by IKEGAMI).
+ - Add a missing file to the distribution.
+
+0.49 Sat Jan 9 10:39:02 CET 2010
+ - Support GCC 4 and 64 bit GCC builds on Windows (patch by KMX).
+ - Fix monolithic build handling for wxWidgets' 2.8.x.
+
+0.48 Fri Dec 25 18:23:56 CET 2009
+ - Fix the compiler check for Visual C++.
+
+0.47 Sat Dec 5 16:16:05 CET 2009
+ - Released 0.46_01 as 0.47.
+
+0.46_01 Tue Nov 24 20:34:25 CET 2009
+ - Do not give a warning when installed using WiX
+ (patch by Curtis Jewell).
+ - Tentative patch to correctly detect wxWidgets under OpenBSD,
+ based on RT ticket 41678.
+ - Under Solaris, use GNU Make to build wxWidgets, and fail if it
+ is not present or can't be detected.
+ - Detect wxWidgets versions that have been installed using
+ Alien::wxWidgets itself and avoid needlessly recompiling/reinstalling
+ it.
+
+0.46 Sun Nov 8 16:25:02 CET 2009
+ - Allow choosing the wxWidgets version to build (defaults to
+ the latest stable release when building from the CPAN shell).
+ - Add a build configuration for wxWidgets 2.9.0.
+ - On Snow Leopard, build wxCocoa when building wxWidgets 2.9.0
+ with a 64 bit Perl.
+ - On Windows, enable the 'portable' option by default (finds the
+ wxWidgets libraries relative to the Alien::wxWidgets installation
+ directory).
+
+0.45 Wed Oct 14 22:54:35 CEST 2009
+ - On Snow Leopard, abort wxWidgets build if Perl is 64 bit.
+ - On Snow Leopard, force wxWidgets build to be 32 bit.
+
+0.44 Sun Aug 9 12:56:05 CEST 2009
+ - Rename all command line options to avoid clashing with
+ Module::Build options.
+
+0.43 Sun May 10 09:46:05 CEST 2009
+ - Fix building under recent FreeBSD versions (patch by Cezary Morga).
+ - Correctly handle monolithic build on wxWidgets' 2.9.x.
+ - Support Cocoa builds for wxWidgets 2.9.x.
+ - Fix building wxWidgets when the build path contains spaces.
+ - Patch and build wxWidgets 2.8.10.
+
+0.42 Sat Nov 8 00:51:18 CET 2008
+ - Add an option for building with Unicode support in interactive
+ configuration (defaults to yes).
+ - Use ExtUtils::CBuilder to try to detect non-working
+ (or non-installed) compilers.
+
+0.41 Mon Oct 27 22:22:25 CET 2008
+ - Rewrite show_configurations to display a pretty-printed version of
+ the available wxWidgets builds.
+ - When load() fails to find a compatible configuration, display a
+ the selection criteria and a list of available configurations.
+
+0.40 Wed Oct 15 20:23:15 CEST 2008
+ - Always use Archive::Extract to extract the wxWidgets archive
+ since it now handles .bz2 files correctly on all platforms.
+ - Add a manifest to the bundled patch.exe to avoid triggering
+ an UAC prompt under Windows Vista.
+
+0.39 Mon Sep 8 20:56:44 CEST 2008
+ - Add missing file to MANIFEST.
+
+0.38 Sun Aug 24 11:17:37 CEST 2008
+ - Patch and build wxWidgets 2.8.8.
+ - When running with AUTOMATED_TESTING try to detect GTK+2
+ presence and abort early if it can't be found.
+
+0.37 Sun Jun 29 21:40:16 CEST 2008
+ - Always use binary programs to extract archives, unless
+ under Win32.
+
+0.36 Mon May 19 22:35:46 CEST 2008
+ - Renamed 0.35_01 to 0.36.
+
+0.35_01 Mon May 12 23:43:02 CEST 2008
+ - Handle --install_base correctly when building wxWidgets
+ during Alien::wxWidgets build.
+
+0.35 Thu May 1 16:25:04 CEST 2008
+ - Correctly handle monolithic build on Win32. (patch by Mark Dootson)
+ - Add mk_portable (Win32-only) build option to create a self-contained
+ wxWidgets+Alien::wxWidgets installation even when not building
+ wxWidgets together with Alien::wxWidgets. (patch by Mark Dootson)
+
+0.34 Sun Apr 13 12:40:08 CEST 2008
+ - Correctly detect GCC 4.3. (patch by Roberto C. Sánchez)
+
+0.33 Sat Jan 19 17:35:57 CET 2008
+ - Patch and build wxWidgets 2.8.7.
+
+0.32 Thu Aug 16 00:11:40 CEST 2007
+ - Patch and build wxWidgets 2.8.4.
+ - Correctly handle flags for wxWidgets Universal Mac builds.
+ - Allow building a monolithic wxWidgets.
+ - Allow building Mac Universal binaries for wxWidgets.
+ - Updated bundled Archive::Extract to the latest version.
+
+0.31 Sat Mar 24 17:25:25 CET 2007
+ - Patch and build wxWidgets 2.8.3.
+ - Automatically link in C++ runtime for MSVC 7.0 and above.
+
+0.30 Sun Mar 18 16:47:23 CET 2007
+ - Fetch and build wxWidgets 2.8.2.
+
+0.29 Fri Mar 16 20:11:31 CET 2007
+ - Must require Perl 5.006, not 5.6.
+
+0.28 Sat Mar 10 21:41:32 CET 2007
+ - Release 0.27_51 as the new stable version.
+
+0.27_51 Sun Feb 25 22:54:07 CET 2007
+ - Fetch and build wxWidgets 2.8.1.
+
+0.27_50 Sun Feb 25 22:39:43 CET 2007
+ - Fetch and build wxWidgets 2.8.0.
+ - Update bundled modules to the latest version.
+
+0.27 Tue Dec 19 23:04:41 CET 2006
+ - Support monolithic wxWidgets builds.
+
+0.26 Sat Dec 16 19:42:57 CET 2006
+ - Improve error reporting for missing libraries.
+
+0.25 Sun Nov 5 18:39:22 CET 2006
+ - Add aui and richtest to the wxWidgets libraries
+ searched with wx-config.
+
+0.24 Fri Oct 20 21:27:57 CEST 2006
+ - Add an option for disabling OpenGL support when building
+ wxWidgets.
+
+0.23 Thu Oct 19 21:41:16 CEST 2006
+ - Use a smart default for the "Do you want to build
+ wxWidgets?" question.
+
+0.22 Tue Oct 3 20:30:48 CEST 2006
+ - Fixed a bug in detecting an installed wxWidgets in /usr/lib64 in
+ x86_64 systems. (patch by Jose Pedro Oliveira)
+ - When fetching wxWidgets, print the download URL.
+
+0.21 Sun Aug 27 17:17:56 CEST 2006
+ - Check that the build environment is sane under Win32.
+
+0.20 Tue Aug 15 17:45:12 CEST 2006
+ - Bundle and use the patch implementation from GNU under Windows;
+ the PPT implementation is way too fragile.
+
+0.19 Sun Jul 16 15:46:11 CEST 2006
+ - Fixes for when the compiler user for building is not in
+ the PATH when installing.
+
+0.18 Sun Jul 9 12:31:44 CEST 2006
+ - Restored compatibility with wxWidgets 2.4 where it uses
+ configure/wx-config.
+
+0.17 Fri Jul 7 22:14:13 CEST 2006
+ - Do not test POD for bundled libraries.
+
+0.16 Wed Jul 5 21:58:33 CEST 2006
+ - Fixed extraction error when using Archive::Extract.
+
+0.15 Wed Jul 5 20:26:32 CEST 2006
+ - Bundled missing Archive::Extract.
+
+0.14 Sun Jun 25 13:00:37 CEST 2006
+ - Make the wxWidgets archive type configurable when building
+ wxWidgets, defaulting to .tar.gz instead of .tar.bz2.
+
+0.13 Sun Jun 18 17:52:44 CEST 2006
+ - Removed (unused) Module::Install from inc.
+
+0.12 Mon Jun 5 21:59:58 CEST 2006
+ - Work with old versions of Test::Pod.
+ - Added a 'passthrough' Makefile.PL.
+ - Take GCC ABI compatibility into account when comparing
+ compiler versions.
+ - Clearly signal that we need bzip2 to extract wxWidgets.
+
+0.11 Thu May 25 22:27:05 CEST 2006
+ - Bundle and use the patch implementation from PPT.
+ - Rediffed all the patches against wxWidgets 2.6.3.
+
+0.10 Sun May 21 19:19:39 CEST 2006
+ - Prefer $CXX to $CC if both are set.
+ - Download and build wxWidgets 2.6.3.
+
+0.09 Tue May 2 21:27:03 CEST 2006
+ - Use mingw32-make as an alternative to make
+ under Win32/MinGW.
+
+0.08 Sun Apr 30 12:33:01 CEST 2006
+ - Fix the build process with CPANPLUS.
+
+0.07 Mon Apr 24 23:16:30 CEST 2006
+ - Fix the download URL for wxWidgets 2.6.2.
+ - Fix the build process under Windows.
+
+0.06 Sun Apr 23 14:35:47 CEST 2006
+ - Cache the absolute path of the wx-config used, and always
+ use it during the build even if PATH changes.
+
+0.05 Fri Apr 21 22:40:38 CEST 2006
+ - Work around a Module::Build handling of @INC when
+ building from CPAN.
+
+0.04 Sun Apr 16 17:01:07 CEST 2006
+ - Optionally build wxWidgets from sources.
+ - Allow some actions (like 'dist') to be executed without
+ an installed wxWidgets.
+ - Detect when some wxWidgets contrib libraries are not built
+ on wx-config platforms.
+ - Check for a recent 'nmake' for Win32+MSVC+Bakefile.
+
+0.03 Wed Aug 17 20:57:49 CEST 2005
+ - Allow multiple configurations to be installed at the
+ same time.
+
+0.02 Wed Aug 17 00:53:40 CEST 2005
+ - Added support for wxWidgets 2.4.x.
+ - Fixed option handling.
+ - Small corrections to the existing code.
+ - Added documentation.
+
+0.01 Tue Aug 16 00:00:12 CEST 2005
+ - First release. Only supports detecting
+ an already-installed wxWidgets. Works for
+ wxWidgets 2.5.x/2.6.x under Mac OS X, Windows,
+ Linux (and probably other Unices).
--- /dev/null
+Build.PL
+Changes
+MANIFEST
+MANIFEST.SKIP
+META.yml
+Makefile.PL
+README.txt
+inc/Archive/Extract.pm
+inc/File/Fetch.pm
+inc/File/Spec/Unix.pm
+inc/IPC/Cmd.pm
+inc/Locale/Maketext/Simple.pm
+inc/Module/Load.pm
+inc/Module/Load/Conditional.pm
+inc/My/Build.pm
+inc/My/Build/Any_wx_config.pm
+inc/My/Build/Any_wx_config_Bakefile.pm
+inc/My/Build/Base.pm
+inc/My/Build/MacOSX_wx_config.pm
+inc/My/Build/Utility.pm
+inc/My/Build/Win32.pm
+inc/My/Build/Win32_MSVC.pm
+inc/My/Build/Win32_MSVC_Bakefile.pm
+inc/My/Build/Win32_MinGW.pm
+inc/My/Build/Win32_MinGW_Bakefile.pm
+inc/My/Build/gmake.mak
+inc/My/Build/nmake.mak
+inc/Params/Check.pm
+inc/Text/Patch.pm
+inc/bin/patch
+inc/version.pm
+inc/version/vpp.pm
+lib/Alien/wxWidgets.pm
+lib/Alien/wxWidgets/Utility.pm
+patches/data-2.8.10
+patches/data-2.9.0
+patches/wxMSW-2.8.0-makefiles.patch
+patches/wxMSW-2.8.0-setup.patch
+patches/wxMSW-2.8.0-setup_u.patch
+patches/wxMSW-2.8.10-config.patch
+patches/wxMSW-2.8.10-mingw64.patch
+patches/wxMSW-2.8.10-version.patch
+patches/wxMSW-2.9.0-config.patch
+patches/wxMSW-2.9.0-makefiles.patch
+patches/wxMSW-2.9.0-setup.patch
+patches/wxMSW-2.9.0-version.patch
+patches/wxMac-2.8.3-brokengcc.patch
+patches/wxMac-2.9.0-textctrl.patch
+patches/wxWidgets-2.8.0-magic.patch
+patches/wxWidgets-2.8.10-gsocket.patch
+patches/wxWidgets-2.9.0-magic.patch
+patches/wxWidgets-2.9.0-msgdlg.patch
+script/make_ppm.pl
+t/01_load.t
+t/zy_pod_coverage.t
+t/zz_pod.t
--- /dev/null
+# Avoid wxWidgets temp directory and archive
+^wxWidgets
+
+# Avoid version control files.
+\bRCS\b
+\bCVS\b
+,v$
+\B\.svn\b
+
+# Avoid Makemaker generated and utility files.
+\bMakefile$
+\bblib
+\bMakeMaker-\d
+\bpm_to_blib$
+\bblibdirs$
+^MANIFEST\.SKIP$
+
+# Avoid Module::Build generated and utility files.
+\bBuild$
+\b_build
+
+# Avoid temp and backup files.
+~$
+\.tmp$
+\.old$
+\.bak$
+\#$
+\b\.#
--- /dev/null
+---
+name: Alien-wxWidgets
+version: 0.50
+author:
+ - 'Mattia Barbon <mbarbon@cpan.org>'
+abstract: 'building, finding and using wxWidgets binaries'
+license: perl
+resources:
+ MailingList: http://lists.perl.org/list/wxperl-users.html
+ bugtracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Alien-wxWidgets
+ homepage: http://wxperl.eu/
+ license: http://dev.perl.org/licenses/
+ repository: https://wxperl.svn.sourceforge.net/svnroot/wxperl/Alien-wxWidgets
+build_requires:
+ ExtUtils::CBuilder: 0.24
+ Module::Build: 0.28
+requires:
+ Module::Pluggable: 2.6
+ perl: 5.006
+configure_requires:
+ Module::Build: 0.28
+provides:
+ Alien::wxWidgets:
+ file: lib/Alien/wxWidgets.pm
+ version: 0.50
+ Alien::wxWidgets::Utility:
+ file: lib/Alien/wxWidgets/Utility.pm
+generated_by: Module::Build version 0.35
+meta-spec:
+ url: http://module-build.sourceforge.net/META-spec-v1.4.html
+ version: 1.4
--- /dev/null
+# Note: this file was auto-generated by Module::Build::Compat version 0.35
+require 5.006;
+
+ unless (eval "use Module::Build::Compat 0.02; 1" ) {
+ print "This module requires Module::Build to install itself.\n";
+
+ require ExtUtils::MakeMaker;
+ my $yn = ExtUtils::MakeMaker::prompt
+ (' Install Module::Build now from CPAN?', 'y');
+
+ unless ($yn =~ /^y/i) {
+ die " *** Cannot install without Module::Build. Exiting ...\n";
+ }
+
+ require Cwd;
+ require File::Spec;
+ require CPAN;
+
+ # Save this 'cause CPAN will chdir all over the place.
+ my $cwd = Cwd::cwd();
+
+ CPAN::Shell->install('Module::Build::Compat');
+ CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate
+ or die "Couldn't install Module::Build, giving up.\n";
+
+ chdir $cwd or die "Cannot chdir() back to $cwd: $!";
+ }
+ eval "use Module::Build::Compat 0.02; 1" or die $@;
+ use lib '_build/lib';
+ Module::Build::Compat->run_build_pl(args => \@ARGV);
+ my $build_script = 'Build';
+ $build_script .= '.com' if $^O eq 'VMS';
+ exit(0) unless(-e $build_script); # cpantesters convention
+ require My::Build::new_from_context_is_broken;
+ Module::Build::Compat->write_makefile(build_class => 'My::Build::new_from_context_is_broken');
--- /dev/null
+=head1 NAME
+
+README.txt - build and installation instructions
+
+=head1 DESCRIPTION
+
+Alien::wxWidgets allows wxPerl to easily find information about
+your wxWidgets installation. It can store this information for multiple
+wxWidgets versions or configurations (debug, Unicode, etc.). It can also
+build and install a private copy of wxWidgets as part of the build process.
+
+=head1 Installing wxWidgets
+
+If yo do not know how to do it, please answer 'yes' to the question 'Do you
+want to build wxWidgets?'; Alien::wxWidgets will build and install a
+copy of wxWidgets for you.
+
+=head1 Installing Alien::wxWidgets
+
+Please note that the steps below can be repeated multiple times in order
+install multiple configurations (differing for the wxWidgets version,
+compiler, compiler version, debug/unicode settings).
+
+=head2 Unices and Mac OS X
+
+Important: either wx-config must be in the PATH or the WX_CONFIG
+environment variable must be set to the full path to wx-config. The
+environment WX_CONFIG variable can also be used to specify a different
+wx-config.
+
+ perl Build.PL
+ perl Build
+ perl Build test
+ perl Build install
+
+=head2 Windows
+
+ <add your compiler to the path>
+ <build wxWidgets>
+ set WXDIR=C:\Path\to\wxWidgets
+ perl Build.PL [--wxWidgets-debug] [--wxWidgets-unicode] [--wxWidgets-mslu]
+ perl Build
+ perl Build test
+ perl Build install
+
+Important: the command line options to Build.PL must match the build
+settings used to build wxWidgets.
+
+=cut
--- /dev/null
+libalien-wxwidgets-perl for Debian
+----------------------------------
+
+This package is, for the most part useless. That is, it is not useful on its
+own. It is a dependency of libwx-perl. I imagine that other packages which
+need to determine information about the installed wxWidgets could also use it.
+However, there are no others of which I am aware.
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Sat, 24 Nov 2007 10:38:49 -0500
--- /dev/null
+
+Upstream sources are repackaged
+===============================
+
+debian/repack.sh script is provided to automate the repackaging. The most
+convenient way is to run `uscan --force', which will download the upstream
+.tar.gz and pass it to debian/repack.sh
+
+Patches
+=======
+
+This package uses quilt to manage all modifications to the upstream
+source. Changes are stored in the source package as diffs in
+debian/patches and applied during the build.
+
+See /usr/share/doc/quilt/README.source for a detailed explanation.
--- /dev/null
+libalien-wxwidgets-perl (0.50-1maemo1) fremantle; urgency=low
+
+ * New Maemo packaging
+
+ -- Nito Martinez <Nito@Qindel.ES> Fri, 16 Apr 2010 06:53:44 +0100
+
+
+libalien-wxwidgets-perl (0.50+dfsg-1) unstable; urgency=low
+
+ [ Jonathan Yu ]
+ * New upstream release
+ * Add a patch to fix POD spelling
+
+ [ Ryan Niebur ]
+ * require wxwidgets 2.8.10.1
+ * Add myself to Uploaders
+ * New upstream release
+
+ -- Jonathan Yu <jawnsy@cpan.org> Sun, 17 Jan 2010 19:04:57 -0500
+
+libalien-wxwidgets-perl (0.46+dfsg-1) unstable; urgency=low
+
+ [ Jonathan Yu ]
+ * New upstream release
+
+ [ Roberto C. Sanchez ]
+ * Tighten up Build-Depends:
+ + change 'perl-modules (>= 5.10) | libmodule-build-perl,
+ libextutils-cbuilder-perl' to 'perl-modules (>= 5.10.1)' since
+ libalien-wxwidgets-perl now requires ExtUtils::CBuilder: 0.24
+
+ [ gregor herrmann ]
+ * debian/control: Changed: (build-)depend on perl instead of perl-
+ modules.
+
+ -- Jonathan Yu <jawnsy@cpan.org> Sun, 08 Nov 2009 16:23:57 -0500
+
+libalien-wxwidgets-perl (0.44+dfsg-1) unstable; urgency=low
+
+ [ Jonathan Yu ]
+ * New upstream release
+ + Rename command-line options to avoid clashing with
+ Module::Build options (closes: #546225)
+ * Added myself to Uploaders and copyright
+ * Standards-Version 3.8.3
+ * Move lintian-overrides to libalien-wxwidgets-perl.XXX
+ * Update copyright information to machine-readable version
+ * Rewrote control file description
+ * Remove README.txt from installation, it's not useful
+
+ [ Ryan Niebur ]
+ * debhelper 7
+
+ [ Roberto C. Sanchez ]
+ * Tighten up Build-Depends on debhelper since debian/rules uses overrides
+
+ -- Jonathan Yu <jawnsy@cpan.org> Thu, 03 Sep 2009 16:04:26 -0400
+
+libalien-wxwidgets-perl (0.42+dfsg-1) unstable; urgency=low
+
+ * drop version from libextutils-cbuilder-perl. The version provided by
+ perl-modules is sufficient.
+ (see http://lists.debian.org/debian-perl/2009/04/msg00072.html)
+ * Standards-Version: 3.8.1 (no changes needed)
+ * add module name to long description
+ * copyright:
+ + use dist-based upstream URL
+ + add "Copyright" in addition to "(C)" in debian/* part
+ + complete copyright/licensing information for all files in inc/
+ * watch: do not limit upstream source location to its current author
+ * add debian/repack.sh for repackaging upstream sources
+ + this is due to unlicensed source files in inc/src as well as the
+ resulting inc/bin/patch.exe
+ + hook debian/repack.sh to debian/watch
+ + rules: provide a get-orig-source target
+ * add README.source documenting repackaging, mention it in debian/copyright
+ too
+
+ -- Damyan Ivanov <dmn@debian.org> Wed, 29 Apr 2009 23:22:05 +0300
+
+libalien-wxwidgets-perl (0.42-1) unstable; urgency=low
+
+ [ Roberto C. Sanchez ]
+ * New upstream release
+ * Add a Build-Depends on libextutils-cbuilder-perl (>= 0.24)
+
+ [ gregor herrmann ]
+ * debian/control: Changed: Switched Vcs-Browser field to ViewSVN
+ (source stanza).
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Tue, 18 Nov 2008 19:47:29 -0500
+
+libalien-wxwidgets-perl (0.41-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Wed, 29 Oct 2008 23:04:03 -0400
+
+libalien-wxwidgets-perl (0.39-1) unstable; urgency=low
+
+ * New upstream release
+ * rules: fir target dependencies for parallel builds
+ * upload to unstable
+
+ -- Damyan Ivanov <dmn@debian.org> Mon, 15 Sep 2008 10:01:55 +0300
+
+libalien-wxwidgets-perl (0.37-2) experimental; urgency=low
+
+ * Bump (build-)dependencies on Wx to 2.8.
+ * Upload to experimental
+
+ -- Damyan Ivanov <dmn@debian.org> Thu, 31 Jul 2008 09:24:24 +0300
+
+libalien-wxwidgets-perl (0.37-1) unstable; urgency=low
+
+ * New upstream release
+ * Update to Standards-Version 3.8.0 (no changes)
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Mon, 30 Jun 2008 18:08:09 -0400
+
+libalien-wxwidgets-perl (0.36-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Tue, 20 May 2008 16:11:33 -0400
+
+libalien-wxwidgets-perl (0.35-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Sun, 04 May 2008 16:53:20 -0400
+
+libalien-wxwidgets-perl (0.34-1) unstable; urgency=low
+
+ * New upstream release.
+ * recognize_g++_compiler.patch: Removed, included upstream, removed quilt
+ framework.
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Sun, 13 Apr 2008 09:15:53 -0400
+
+libalien-wxwidgets-perl (0.33-3) unstable; urgency=low
+
+ * More intelligent check for compiler name and version (Closes: #475776)
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Sat, 12 Apr 2008 23:31:47 -0400
+
+libalien-wxwidgets-perl (0.33-2) unstable; urgency=low
+
+ * Make Alien::wxWidgets->config able to see g++ >= 4.3 (Closes: #474404)
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Sat, 12 Apr 2008 13:59:20 -0400
+
+libalien-wxwidgets-perl (0.33-1) unstable; urgency=low
+
+ * debian/rules: Fix so package builds when run as 'debian/rules binary-arch'
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Mon, 21 Jan 2008 20:33:30 -0500
+
+libalien-wxwidgets-perl (0.32-3) unstable; urgency=low
+
+ [ Roberto C. Sanchez ]
+ * fill README.Debian
+
+ [ Damyan Ivanov ]
+ * Move test suite to build-stamp target
+ * Instead of hunting down .packlist files with find, give 'Build install' a
+ create_packlist=0 parameter
+ * Add libtest-pod-perl and libtest-pod-coverage-perl to Build-Depends
+ * Stop removing usr/lib/perl5/auto/Alien/wxWidgets/ as it is not
+ created
+ * debian/rules: delete /usr/share/perl5 only if it exists.
+ * add ${perl:Depends} to Depends:
+ * add myself to Uploaders
+
+ -- Damyan Ivanov <dmn@debian.org> Tue, 08 Jan 2008 16:58:40 +0200
+
+libalien-wxwidgets-perl (0.32-2) unstable; urgency=low
+
+ * Add missing dependency.
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Sat, 5 Jan 2008 14:55:35 -0500
+
+libalien-wxwidgets-perl (0.32-1) unstable; urgency=low
+
+ * Initial release (Closes: #459256)
+
+ -- Roberto C. Sanchez <roberto@connexer.com> Fri, 4 Jan 2008 10:38:49 -0500
+
--- /dev/null
+Source: libalien-wxwidgets-perl
+Section: perl
+Priority: optional
+Build-Depends: debhelper7, quilt, perl (>= 5.8.3),
+ libmodule-pluggable-perl, libwxgtk2.8-dev (>= 2.8.10.1), libtest-pod-perl,
+ libtest-pod-coverage-perl
+Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
+Uploaders: Roberto C. Sanchez <roberto@connexer.com>,
+ Damyan Ivanov <dmn@debian.org>, Jonathan Yu <jawnsy@cpan.org>,
+ Ryan Niebur <ryan@debian.org>
+Standards-Version: 3.8.3
+Homepage: http://search.cpan.org/dist/Alien-wxWidgets/
+Vcs-Svn: svn://svn.debian.org/pkg-perl/trunk/libalien-wxwidgets-perl/
+Vcs-Browser: http://svn.debian.org/viewsvn/pkg-perl/trunk/libalien-wxwidgets-perl/
+
+Package: libalien-wxwidgets-perl
+Architecture: any
+Depends: ${perl:Depends}, ${misc:Depends}, libwxgtk2.8-dev (>= ${wx:current}),
+ libwxgtk2.8-dev (<< ${wx:next}), libmodule-pluggable-perl
+Description: Perl module for locating wxWidgets binaries
+ Alien::WxWidgets is a simple Perl module that detects configuration settings
+ of an installed wxWidgets. It is useful to assist in the building of modules
+ that require wxWidgets, providing indispensible compile-related information
+ like relevant linker and compiler flags.
--- /dev/null
+Format-Specification:
+ http://wiki.debian.org/Proposals/CopyrightFormat?action=recall&rev=196
+Upstream-Maintainer: Mattia Barbon <mbarbon@cpan.org>
+Upstream-Source: http://search.cpan.org/dist/Alien-wxWidgets/
+Upstream-Name: Alien-wxWidgets
+X-Comment: Since upstream-provided tarball contains files without license, it has to be
+ repackaged. The following items are removed:
+ .
+ + inc/src/: contains files without a license
+ + inc/bin/patch.exe: supposedly the result of compiling the above sources.
+ removed as it becomes sourceless after inc/src removal
+
+Files: *
+Copyright: 2005-2009, Mattia Barbon <mbarbon@cpan.org>
+License-Alias: Perl
+License: Artistic | GPL-1+
+
+Files: debian/*
+Copyright: 2009, Jonathan Yu <jawnsy@cpan.org>
+ 2008-2009, Damyan Ivanov <dmn@debian.org>
+ 2008-2009, Roberto C. Sanchez <roberto@connexer.com>
+License: GPL-2+
+
+Files: inc/bin/patch
+Copyright: 1999, Moogle Stuffy Software <tgy@chocobo.org>
+License-Alias: Perl
+License: Artistic | GPL-1+
+
+Files: inc/Archive/Extract.pm
+Copyright: 2002, Jos Boumans <kane@cpan.org>
+License-Alias: Perl
+License: Artistic | GPL-1+
+
+Files: inc/File/Spec/Unix.pm
+Copyright: 2004, Perl 5 Porters. All rights reserved.
+License-Alias: Perl
+License: Artistic | GPL-1+
+
+Files: inc/File/Fetch.pm
+Copyright: 2003-2007, Jos Boumans <kane@cpan.org>
+License-Alias: Perl
+License: Artistic | GPL-1+
+
+Files: inc/IPC/Cmd.pm
+Copyright: 2002-2006, Jos Boumans <kane@cpan.org>
+License-Alias: Perl
+License: Artistic | GPL-1+
+
+Files: inc/Locale/Maketext/Simple.pm
+Copyright: 2003-2006, Audrey Tang <cpan@audreyt.org>
+License: MIT
+
+Files: inc/Module/Load.pm, inc/Module/Load/Conditional.pm
+Copyright: 2002-2007, Jos Boumans <kane@cpan.org>
+License-Alias: Perl
+License: Artistic | GPL-1+
+
+Files: inc/Params/Check.pm
+Copyright: 2003-2004, Jos Boumans <kane@cpan.org>
+License-Alias: Perl
+License: Artistic | GPL-1+
+
+Files: inc/Text/Patch.pm
+Copyright: 2004, Vladi Belperchinov-Shabanski <cade@datamax.bg>
+License: GPL-2+
+
+Files: inc/version.pm, inc/version/vpp.pm
+Copyright: 2004-2009, John Peacock <jpeacock@cpan.org>
+License-Alias: Perl
+License: Artistic | GPL-1+
+
+License: Artistic
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the Artistic License, which comes with Perl.
+ On Debian GNU/Linux systems, the complete text of the Artistic License
+ can be found in `/usr/share/common-licenses/Artistic'
+
+License: GPL-1+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+ On Debian GNU/Linux systems, the complete text of the GNU General
+ Public License can be found in `/usr/share/common-licenses/GPL'
+
+License: GPL-2+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+ On Debian GNU/Linux systems, the complete text of the GNU General
+ Public License can be found in `/usr/share/common-licenses/GPL-2'
+
+License: MIT
+ 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.
--- /dev/null
+# While the files are non-binary, they depend on binary info about wxWidgets
+# so, they have the potential to differ from architecture to architecture
+libalien-wxwidgets-perl: package-installs-nonbinary-perl-in-usr-lib-perl5
+
--- /dev/null
+Description: fix POD spelling
+Author: Jonathan Yu <jawnsy@cpan.org>
+Origin: vendor
+Forwarded: no
+--- a/lib/Alien/wxWidgets.pm
++++ b/lib/Alien/wxWidgets.pm
+@@ -236,7 +236,7 @@
+
+ my $config = Alien::wxWidgets->config;
+
+-Returns some miscellaneous configuration informations for wxWidgets
++Returns some miscellaneous configuration information for wxWidgets
+ in the form
+
+ { toolkit => 'msw' | 'gtk' | 'motif' | 'x11' | 'cocoa' | 'mac',
--- /dev/null
+fix-pod-spelling.patch
--- /dev/null
+MANIFEST=1
+rm inc/bin/patch.exe inc/src/
+
--- /dev/null
+#!/bin/sh
+
+: <<=cut
+=pod
+
+=head1 NAME
+
+repack.stub - script to repack upstream tarballs from uscan
+
+=head1 INSTRUCTIONS
+
+put this in debian/repack.stub and add "debian sh debian/repack.stub" to
+the end of the line in debian/watch. you will also need to add a version
+mangle to debian/watch.
+
+then create a debian/repack.local. this is a shell script that is
+sources under "set -e", so be careful to check returns codes.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item rm
+
+rm is replaced by a function that does some magic ("rm -rv" by default), but also changes MANIFEST if $MANIFEST is 1
+
+=item mv
+
+mv is replaced by a function that just does mv (by default), but also changes MANIFEST if $MANIFEST is 1
+
+=item requires_version
+
+requires_version is there for future usage for requiring certain versions of the script
+
+=back
+
+=head1 VARIABLES
+
+=over 4
+
+=item SUFFIX
+
+defaults to +dfsg
+
+what to append to the upstream version
+
+=item RM_OPTS
+
+defaults to -vrf
+
+options to pass to rm
+
+=item MANIFEST
+
+defaults to 0, set to 1 to turn on.
+
+this will manipulate MANIFEST files in CPAN tarballs.
+
+=item UP_BASE
+
+this is the directory where the upstream source is.
+
+=back
+
+=cut
+
+if [ -z "$REPACK_SH" ]; then
+ if [ -f ../../scripts/repack.sh ]; then
+ REPACK_SH=../../scripts/repack.sh
+ fi
+ if [ -z "$REPACK_SH" ] && which repack.sh > /dev/null; then
+ REPACK_SH=$(which repack.sh)
+ fi
+fi
+
+if [ ! -f "$REPACK_SH" ]; then
+ echo "Couldn't find a repack.sh. please put it in your PATH, put it at ../../scripts/repack.sh, or put it somewhere else and set the REPACK_SH variable"
+ echo "You can get it from http://svn.debian.org/viewsvn/pkg-perl/scripts/repack.sh"
+ exit 1
+fi
+
+exec "$REPACK_SH" "$@"
--- /dev/null
+#!/usr/bin/make -f
+
+# wxWidgets version
+export V=`dpkg -s libwxgtk2.8-dev | grep ^Version |cut -f2 -d' '`
+VMAJOR:=$(shell echo $(V) |cut -f 1 -d .)
+VMINOR:=$(shell echo $(V) |cut -f 2 -d .)
+VPATCH:=$(shell echo $(V) |cut -f 3 -d .)
+NEXTPATCH:=$(shell expr $(VPATCH) + 1 2>/dev/null || expr `echo $(VPATCH) | cut -f 1 -d - ` + 1)
+
+%:
+ dh --with quilt $@
+
+override_dh_gencontrol:
+ echo 'wx:current=$(VMAJOR).$(VMINOR).$(VPATCH)~' \
+ >> debian/libalien-wxwidgets-perl.substvars
+ echo 'wx:next=$(VMAJOR).$(VMINOR).$(NEXTPATCH)~' \
+ >> debian/libalien-wxwidgets-perl.substvars
+ dh_gencontrol
--- /dev/null
+# Example watch control file for uscan
+# Rename this file to "watch" and then you can run the "uscan" command
+# to check for upstream updates and more.
+# See uscan(1) for format
+
+# Compulsory line, this is a version 3 file
+version=3
+
+# <Webpage URL> <string match>
+opts=dversionmangle=s/\+dfsg[.\d]*// \
+http://search.cpan.org/dist/Alien-wxWidgets/ .*/Alien-wxWidgets-(.*)\.tar\.gz \
+ debian debian/repack.stub
+
--- /dev/null
+package Archive::Extract;
+
+use strict;
+
+use Cwd qw[cwd];
+use Carp qw[carp];
+use IPC::Cmd qw[run can_run];
+use FileHandle;
+use File::Path qw[mkpath];
+use File::Spec;
+use File::Basename qw[dirname basename];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load check_install];
+use Locale::Maketext::Simple Style => 'gettext';
+
+### solaris has silly /bin/tar output ###
+use constant ON_SOLARIS => $^O eq 'solaris' ? 1 : 0;
+use constant FILE_EXISTS => sub { -e $_[0] ? 1 : 0 };
+
+### If these are changed, update @TYPES and the new() POD
+use constant TGZ => 'tgz';
+use constant TAR => 'tar';
+use constant GZ => 'gz';
+use constant ZIP => 'zip';
+use constant BZ2 => 'bz2';
+use constant TBZ => 'tbz';
+use constant Z => 'Z';
+
+use vars qw[$VERSION $PREFER_BIN $PROGRAMS $WARN $DEBUG];
+
+$VERSION = '0.22';
+$PREFER_BIN = 0;
+$WARN = 1;
+$DEBUG = 0;
+my @Types = ( TGZ, TAR, GZ, ZIP, BZ2, TBZ, Z ); # same as all constants
+
+local $Params::Check::VERBOSE = $Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+Archive::Extract - A generic archive extracting mechanism
+
+=head1 SYNOPSIS
+
+ use Archive::Extract;
+
+ ### build an Archive::Extract object ###
+ my $ae = Archive::Extract->new( archive => 'foo.tgz' );
+
+ ### extract to cwd() ###
+ my $ok = $ae->extract;
+
+ ### extract to /tmp ###
+ my $ok = $ae->extract( to => '/tmp' );
+
+ ### what if something went wrong?
+ my $ok = $ae->extract or die $ae->error;
+
+ ### files from the archive ###
+ my $files = $ae->files;
+
+ ### dir that was extracted to ###
+ my $outdir = $ae->extract_path;
+
+
+ ### quick check methods ###
+ $ae->is_tar # is it a .tar file?
+ $ae->is_tgz # is it a .tar.gz or .tgz file?
+ $ae->is_gz; # is it a .gz file?
+ $ae->is_zip; # is it a .zip file?
+ $ae->is_bz2; # is it a .bz2 file?
+ $ae->is_tbz; # is it a .tar.bz2 or .tbz file?
+
+ ### absolute path to the archive you provided ###
+ $ae->archive;
+
+ ### commandline tools, if found ###
+ $ae->bin_tar # path to /bin/tar, if found
+ $ae->bin_gzip # path to /bin/gzip, if found
+ $ae->bin_unzip # path to /bin/unzip, if found
+ $ae->bin_bunzip2 # path to /bin/bunzip2 if found
+
+=head1 DESCRIPTION
+
+Archive::Extract is a generic archive extraction mechanism.
+
+It allows you to extract any archive file of the type .tar, .tar.gz,
+.gz, .Z, tar.bz2, .tbz, .bz2 or .zip without having to worry how it
+does so, or use different interfaces for each type by using either
+perl modules, or commandline tools on your system.
+
+See the C<HOW IT WORKS> section further down for details.
+
+=cut
+
+
+### see what /bin/programs are available ###
+$PROGRAMS = {};
+for my $pgm (qw[tar unzip gzip bunzip2 uncompress]) {
+ $PROGRAMS->{$pgm} = can_run($pgm);
+}
+
+### mapping from types to extractor methods ###
+my $Mapping = {
+ is_tgz => '_untar',
+ is_tar => '_untar',
+ is_gz => '_gunzip',
+ is_zip => '_unzip',
+ is_tbz => '_untar',
+ is_bz2 => '_bunzip2',
+ is_Z => '_uncompress',
+};
+
+{
+ my $tmpl = {
+ archive => { required => 1, allow => FILE_EXISTS },
+ type => { default => '', allow => [ @Types ] },
+ };
+
+ ### build accesssors ###
+ for my $method( keys %$tmpl,
+ qw[_extractor _gunzip_to files extract_path],
+ qw[_error_msg _error_msg_long]
+ ) {
+ no strict 'refs';
+ *$method = sub {
+ my $self = shift;
+ $self->{$method} = $_[0] if @_;
+ return $self->{$method};
+ }
+ }
+
+=head1 METHODS
+
+=head2 $ae = Archive::Extract->new(archive => '/path/to/archive',[type => TYPE])
+
+Creates a new C<Archive::Extract> object based on the archive file you
+passed it. Automatically determines the type of archive based on the
+extension, but you can override that by explicitly providing the
+C<type> argument.
+
+Valid values for C<type> are:
+
+=over 4
+
+=item tar
+
+Standard tar files, as produced by, for example, C</bin/tar>.
+Corresponds to a C<.tar> suffix.
+
+=item tgz
+
+Gzip compressed tar files, as produced by, for example C</bin/tar -z>.
+Corresponds to a C<.tgz> or C<.tar.gz> suffix.
+
+=item gz
+
+Gzip compressed file, as produced by, for example C</bin/gzip>.
+Corresponds to a C<.gz> suffix.
+
+=item Z
+
+Lempel-Ziv compressed file, as produced by, for example C</bin/compress>.
+Corresponds to a C<.Z> suffix.
+
+=item zip
+
+Zip compressed file, as produced by, for example C</bin/zip>.
+Corresponds to a C<.zip>, C<.jar> or C<.par> suffix.
+
+=item bz2
+
+Bzip2 compressed file, as produced by, for example, C</bin/bzip2>.
+Corresponds to a C<.bz2> suffix.
+
+=item tbz
+
+Bzip2 compressed tar file, as produced by, for exmample C</bin/tar -j>.
+Corresponds to a C<.tbz> or C<.tar.bz2> suffix.
+
+=back
+
+Returns a C<Archive::Extract> object on success, or false on failure.
+
+=cut
+
+ ### constructor ###
+ sub new {
+ my $class = shift;
+ my %hash = @_;
+
+ my $parsed = check( $tmpl, \%hash ) or return;
+
+ ### make sure we have an absolute path ###
+ my $ar = $parsed->{archive} = File::Spec->rel2abs( $parsed->{archive} );
+
+ ### figure out the type, if it wasn't already specified ###
+ unless ( $parsed->{type} ) {
+ $parsed->{type} =
+ $ar =~ /.+?\.(?:tar\.gz|tgz)$/i ? TGZ :
+ $ar =~ /.+?\.gz$/i ? GZ :
+ $ar =~ /.+?\.tar$/i ? TAR :
+ $ar =~ /.+?\.(zip|jar|par)$/i ? ZIP :
+ $ar =~ /.+?\.(?:tbz|tar\.bz2?)$/i ? TBZ :
+ $ar =~ /.+?\.bz2$/i ? BZ2 :
+ $ar =~ /.+?\.Z$/ ? Z :
+ '';
+
+ }
+
+ ### don't know what type of file it is ###
+ return __PACKAGE__->_error(loc("Cannot determine file type for '%1'",
+ $parsed->{archive} )) unless $parsed->{type};
+
+ return bless $parsed, $class;
+ }
+}
+
+=head2 $ae->extract( [to => '/output/path'] )
+
+Extracts the archive represented by the C<Archive::Extract> object to
+the path of your choice as specified by the C<to> argument. Defaults to
+C<cwd()>.
+
+Since C<.gz> files never hold a directory, but only a single file; if
+the C<to> argument is an existing directory, the file is extracted
+there, with it's C<.gz> suffix stripped.
+If the C<to> argument is not an existing directory, the C<to> argument
+is understood to be a filename, if the archive type is C<gz>.
+In the case that you did not specify a C<to> argument, the output
+file will be the name of the archive file, stripped from it's C<.gz>
+suffix, in the current working directory.
+
+C<extract> will try a pure perl solution first, and then fall back to
+commandline tools if they are available. See the C<GLOBAL VARIABLES>
+section below on how to alter this behaviour.
+
+It will return true on success, and false on failure.
+
+On success, it will also set the follow attributes in the object:
+
+=over 4
+
+=item $ae->extract_path
+
+This is the directory that the files where extracted to.
+
+=item $ae->files
+
+This is an array ref with the paths of all the files in the archive,
+relative to the C<to> argument you specified.
+To get the full path to an extracted file, you would use:
+
+ File::Spec->catfile( $to, $ae->files->[0] );
+
+Note that all files from a tar archive will be in unix format, as per
+the tar specification.
+
+=back
+
+=cut
+
+sub extract {
+ my $self = shift;
+ my %hash = @_;
+
+ my $to;
+ my $tmpl = {
+ to => { default => '.', store => \$to }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### so 'to' could be a file or a dir, depending on whether it's a .gz
+ ### file, or basically anything else.
+ ### so, check that, then act accordingly.
+ ### set an accessor specifically so _gunzip can know what file to extract
+ ### to.
+ my $dir;
+ { ### a foo.gz file
+ if( $self->is_gz or $self->is_bz2 or $self->is_Z) {
+
+ my $cp = $self->archive; $cp =~ s/\.(?:gz|bz2|Z)$//i;
+
+ ### to is a dir?
+ if ( -d $to ) {
+ $dir = $to;
+ $self->_gunzip_to( basename($cp) );
+
+ ### then it's a filename
+ } else {
+ $dir = dirname($to);
+ $self->_gunzip_to( basename($to) );
+ }
+
+ ### not a foo.gz file
+ } else {
+ $dir = $to;
+ }
+ }
+
+ ### make the dir if it doesn't exist ###
+ unless( -d $dir ) {
+ eval { mkpath( $dir ) };
+
+ return $self->_error(loc("Could not create path '%1': %2", $dir, $@))
+ if $@;
+ }
+
+ ### get the current dir, to restore later ###
+ my $cwd = cwd();
+
+ my $ok = 1;
+ EXTRACT: {
+
+ ### chdir to the target dir ###
+ unless( chdir $dir ) {
+ $self->_error(loc("Could not chdir to '%1': %2", $dir, $!));
+ $ok = 0; last EXTRACT;
+ }
+
+ ### set files to an empty array ref, so there's always an array
+ ### ref IN the accessor, to avoid errors like:
+ ### Can't use an undefined value as an ARRAY reference at
+ ### ../lib/Archive/Extract.pm line 742. (rt #19815)
+ $self->files( [] );
+
+ ### find what extractor method to use ###
+ while( my($type,$method) = each %$Mapping ) {
+
+ ### call the corresponding method if the type is OK ###
+ if( $self->$type) {
+ $ok = $self->$method();
+ }
+ }
+
+ ### warn something went wrong if we didn't get an OK ###
+ $self->_error(loc("Extract failed, no extractor found"))
+ unless $ok;
+
+ }
+
+ ### and chdir back ###
+ unless( chdir $cwd ) {
+ $self->_error(loc("Could not chdir back to start dir '%1': %2'",
+ $cwd, $!));
+ }
+
+ return $ok;
+}
+
+=pod
+
+=head1 ACCESSORS
+
+=head2 $ae->error([BOOL])
+
+Returns the last encountered error as string.
+Pass it a true value to get the C<Carp::longmess()> output instead.
+
+=head2 $ae->extract_path
+
+This is the directory the archive got extracted to.
+See C<extract()> for details.
+
+=head2 $ae->files
+
+This is an array ref holding all the paths from the archive.
+See C<extract()> for details.
+
+=head2 $ae->archive
+
+This is the full path to the archive file represented by this
+C<Archive::Extract> object.
+
+=head2 $ae->type
+
+This is the type of archive represented by this C<Archive::Extract>
+object. See accessors below for an easier way to use this.
+See the C<new()> method for details.
+
+=head2 $ae->types
+
+Returns a list of all known C<types> for C<Archive::Extract>'s
+C<new> method.
+
+=cut
+
+sub types { return @Types }
+
+=head2 $ae->is_tgz
+
+Returns true if the file is of type C<.tar.gz>.
+See the C<new()> method for details.
+
+=head2 $ae->is_tar
+
+Returns true if the file is of type C<.tar>.
+See the C<new()> method for details.
+
+=head2 $ae->is_gz
+
+Returns true if the file is of type C<.gz>.
+See the C<new()> method for details.
+
+=head2 $ae->is_Z
+
+Returns true if the file is of type C<.Z>.
+See the C<new()> method for details.
+
+=head2 $ae->is_zip
+
+Returns true if the file is of type C<.zip>.
+See the C<new()> method for details.
+
+=cut
+
+### quick check methods ###
+sub is_tgz { return $_[0]->type eq TGZ }
+sub is_tar { return $_[0]->type eq TAR }
+sub is_gz { return $_[0]->type eq GZ }
+sub is_zip { return $_[0]->type eq ZIP }
+sub is_tbz { return $_[0]->type eq TBZ }
+sub is_bz2 { return $_[0]->type eq BZ2 }
+sub is_Z { return $_[0]->type eq Z }
+
+=pod
+
+=head2 $ae->bin_tar
+
+Returns the full path to your tar binary, if found.
+
+=head2 $ae->bin_gzip
+
+Returns the full path to your gzip binary, if found
+
+=head2 $ae->bin_unzip
+
+Returns the full path to your unzip binary, if found
+
+=cut
+
+### paths to commandline tools ###
+sub bin_gzip { return $PROGRAMS->{'gzip'} if $PROGRAMS->{'gzip'} }
+sub bin_unzip { return $PROGRAMS->{'unzip'} if $PROGRAMS->{'unzip'} }
+sub bin_tar { return $PROGRAMS->{'tar'} if $PROGRAMS->{'tar'} }
+sub bin_bunzip2 { return $PROGRAMS->{'bunzip2'} if $PROGRAMS->{'bunzip2'} }
+sub bin_uncompress { return $PROGRAMS->{'uncompress'}
+ if $PROGRAMS->{'uncompress'} }
+
+#################################
+#
+# Untar code
+#
+#################################
+
+
+### untar wrapper... goes to either Archive::Tar or /bin/tar
+### depending on $PREFER_BIN
+sub _untar {
+ my $self = shift;
+
+ ### bzip2 support in A::T via IO::Uncompress::Bzip2
+ my @methods = qw[_untar_at _untar_bin];
+ @methods = reverse @methods if $PREFER_BIN;
+
+ for my $method (@methods) {
+ $self->_extractor($method) && return 1 if $self->$method();
+ }
+
+ return $self->_error(loc("Unable to untar file '%1'", $self->archive));
+}
+
+### use /bin/tar to extract ###
+sub _untar_bin {
+ my $self = shift;
+
+ ### check for /bin/tar ###
+ return $self->_error(loc("No '%1' program found", '/bin/tar'))
+ unless $self->bin_tar;
+
+ ### check for /bin/gzip if we need it ###
+ return $self->_error(loc("No '%1' program found", '/bin/gzip'))
+ if $self->is_tgz && !$self->bin_gzip;
+
+ return $self->_error(loc("No '%1' program found", '/bin/bunzip2'))
+ if $self->is_tbz && !$self->bin_bunzip2;
+
+ ### XXX figure out how to make IPC::Run do this in one call --
+ ### currently i don't know how to get output of a command after a pipe
+ ### trapped in a scalar. Mailed barries about this 5th of june 2004.
+
+
+
+ ### see what command we should run, based on whether
+ ### it's a .tgz or .tar
+
+ ### XXX solaris tar and bsdtar are having different outputs
+ ### depending whether you run with -x or -t
+ ### compensate for this insanity by running -t first, then -x
+ { my $cmd =
+ $self->is_tgz ? [$self->bin_gzip, '-cdf', $self->archive, '|',
+ $self->bin_tar, '-tf', '-'] :
+ $self->is_tbz ? [$self->bin_bunzip2, '-c', $self->archive, '|',
+ $self->bin_tar, '-tf', '-'] :
+ [$self->bin_tar, '-tf', $self->archive];
+
+ ### run the command ###
+ my $buffer = '';
+ unless( scalar run( command => $cmd,
+ buffer => \$buffer,
+ verbose => $DEBUG )
+ ) {
+ return $self->_error(loc(
+ "Error listing contents of archive '%1': %2",
+ $self->archive, $buffer ));
+ }
+
+ ### no buffers available?
+ if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
+ $self->_error( $self->_no_buffer_files( $self->archive ) );
+
+ } else {
+ ### if we're on solaris we /might/ be using /bin/tar, which has
+ ### a weird output format... we might also be using
+ ### /usr/local/bin/tar, which is gnu tar, which is perfectly
+ ### fine... so we have to do some guessing here =/
+ my @files = map { chomp;
+ !ON_SOLARIS ? $_
+ : (m|^ x \s+ # 'xtract' -- sigh
+ (.+?), # the actual file name
+ \s+ [\d,.]+ \s bytes,
+ \s+ [\d,.]+ \s tape \s blocks
+ |x ? $1 : $_);
+
+ } split $/, $buffer;
+
+ ### store the files that are in the archive ###
+ $self->files(\@files);
+ }
+ }
+
+ ### now actually extract it ###
+ { my $cmd =
+ $self->is_tgz ? [$self->bin_gzip, '-cdf', $self->archive, '|',
+ $self->bin_tar, '-xf', '-'] :
+ $self->is_tbz ? [$self->bin_bunzip2, '-c', $self->archive, '|',
+ $self->bin_tar, '-xf', '-'] :
+ [$self->bin_tar, '-xf', $self->archive];
+
+ my $buffer = '';
+ unless( scalar run( command => $cmd,
+ buffer => \$buffer,
+ verbose => $DEBUG )
+ ) {
+ return $self->_error(loc("Error extracting archive '%1': %2",
+ $self->archive, $buffer ));
+ }
+
+ ### we might not have them, due to lack of buffers
+ if( $self->files ) {
+ ### now that we've extracted, figure out where we extracted to
+ my $dir = $self->__get_extract_dir( $self->files );
+
+ ### store the extraction dir ###
+ $self->extract_path( $dir );
+ }
+ }
+
+ ### we got here, no error happened
+ return 1;
+}
+
+### use archive::tar to extract ###
+sub _untar_at {
+ my $self = shift;
+
+ ### we definitely need A::T, so load that first
+ { my $use_list = { 'Archive::Tar' => '0.0' };
+
+ unless( can_load( modules => $use_list ) ) {
+
+ return $self->_error(loc("You do not have '%1' installed - " .
+ "Please install it as soon as possible.",
+ 'Archive::Tar'));
+ }
+ }
+
+ ### we might pass it a filehandle if it's a .tbz file..
+ my $fh_to_read = $self->archive;
+
+ ### we will need Compress::Zlib too, if it's a tgz... and IO::Zlib
+ ### if A::T's version is 0.99 or higher
+ if( $self->is_tgz ) {
+ my $use_list = { 'Compress::Zlib' => '0.0' };
+ $use_list->{ 'IO::Zlib' } = '0.0'
+ if $Archive::Tar::VERSION >= '0.99';
+
+ unless( can_load( modules => $use_list ) ) {
+ my $which = join '/', sort keys %$use_list;
+
+ return $self->_error(loc(
+ "You do not have '%1' installed - Please ".
+ "install it as soon as possible.", $which));
+
+ }
+ } elsif ( $self->is_tbz ) {
+ my $use_list = { 'IO::Uncompress::Bunzip2' => '0.0' };
+ unless( can_load( modules => $use_list ) ) {
+ return $self->_error(loc(
+ "You do not have '%1' installed - Please " .
+ "install it as soon as possible.",
+ 'IO::Uncompress::Bunzip2'));
+ }
+
+ my $bz = IO::Uncompress::Bunzip2->new( $self->archive ) or
+ return $self->_error(loc("Unable to open '%1': %2",
+ $self->archive,
+ $IO::Uncompress::Bunzip2::Bunzip2Error));
+
+ $fh_to_read = $bz;
+ }
+
+ my $tar = Archive::Tar->new();
+
+ ### only tell it it's compressed if it's a .tgz, as we give it a file
+ ### handle if it's a .tbz
+ unless( $tar->read( $fh_to_read, ( $self->is_tgz ? 1 : 0 ) ) ) {
+ return $self->_error(loc("Unable to read '%1': %2", $self->archive,
+ $Archive::Tar::error));
+ }
+
+ ### workaround to prevent Archive::Tar from setting uid, which
+ ### is a potential security hole. -autrijus
+ ### have to do it here, since A::T needs to be /loaded/ first ###
+ { no strict 'refs'; local $^W;
+
+ ### older versions of archive::tar <= 0.23
+ *Archive::Tar::chown = sub {};
+ }
+
+ ### for version of archive::tar > 1.04
+ local $Archive::Tar::Constant::CHOWN = 0;
+
+ { local $^W; # quell 'splice() offset past end of array' warnings
+ # on older versions of A::T
+
+ ### older archive::tar always returns $self, return value slightly
+ ### fux0r3d because of it.
+ $tar->extract()
+ or return $self->_error(loc("Unable to extract '%1': %2",
+ $self->archive, $Archive::Tar::error ));
+ }
+
+ my @files = $tar->list_files;
+ my $dir = $self->__get_extract_dir( \@files );
+
+ ### store the files that are in the archive ###
+ $self->files(\@files);
+
+ ### store the extraction dir ###
+ $self->extract_path( $dir );
+
+ ### check if the dir actually appeared ###
+ return 1 if -d $self->extract_path;
+
+ ### no dir, we failed ###
+ return $self->_error(loc("Unable to extract '%1': %2",
+ $self->archive, $Archive::Tar::error ));
+}
+
+#################################
+#
+# Gunzip code
+#
+#################################
+
+### gunzip wrapper... goes to either Compress::Zlib or /bin/gzip
+### depending on $PREFER_BIN
+sub _gunzip {
+ my $self = shift;
+
+ my @methods = qw[_gunzip_cz _gunzip_bin];
+ @methods = reverse @methods if $PREFER_BIN;
+
+ for my $method (@methods) {
+ $self->_extractor($method) && return 1 if $self->$method();
+ }
+
+ return $self->_error(loc("Unable to gunzip file '%1'", $self->archive));
+}
+
+sub _gunzip_bin {
+ my $self = shift;
+
+ ### check for /bin/gzip -- we need it ###
+ return $self->_error(loc("No '%1' program found", '/bin/gzip'))
+ unless $self->bin_gzip;
+
+
+ my $fh = FileHandle->new('>'. $self->_gunzip_to) or
+ return $self->_error(loc("Could not open '%1' for writing: %2",
+ $self->_gunzip_to, $! ));
+
+ my $cmd = [ $self->bin_gzip, '-cdf', $self->archive ];
+
+ my $buffer;
+ unless( scalar run( command => $cmd,
+ verbose => $DEBUG,
+ buffer => \$buffer )
+ ) {
+ return $self->_error(loc("Unable to gunzip '%1': %2",
+ $self->archive, $buffer));
+ }
+
+ ### no buffers available?
+ if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
+ $self->_error( $self->_no_buffer_content( $self->archive ) );
+ }
+
+ print $fh $buffer if defined $buffer;
+
+ close $fh;
+
+ ### set what files where extract, and where they went ###
+ $self->files( [$self->_gunzip_to] );
+ $self->extract_path( File::Spec->rel2abs(cwd()) );
+
+ return 1;
+}
+
+sub _gunzip_cz {
+ my $self = shift;
+
+ my $use_list = { 'Compress::Zlib' => '0.0' };
+ unless( can_load( modules => $use_list ) ) {
+ return $self->_error(loc("You do not have '%1' installed - Please " .
+ "install it as soon as possible.", 'Compress::Zlib'));
+ }
+
+ my $gz = Compress::Zlib::gzopen( $self->archive, "rb" ) or
+ return $self->_error(loc("Unable to open '%1': %2",
+ $self->archive, $Compress::Zlib::gzerrno));
+
+ my $fh = FileHandle->new('>'. $self->_gunzip_to) or
+ return $self->_error(loc("Could not open '%1' for writing: %2",
+ $self->_gunzip_to, $! ));
+
+ my $buffer;
+ $fh->print($buffer) while $gz->gzread($buffer) > 0;
+ $fh->close;
+
+ ### set what files where extract, and where they went ###
+ $self->files( [$self->_gunzip_to] );
+ $self->extract_path( File::Spec->rel2abs(cwd()) );
+
+ return 1;
+}
+
+#################################
+#
+# Uncompress code
+#
+#################################
+
+
+### untar wrapper... goes to either Archive::Tar or /bin/tar
+### depending on $PREFER_BIN
+sub _uncompress {
+ my $self = shift;
+
+ my @methods = qw[_gunzip_cz _uncompress_bin];
+ @methods = reverse @methods if $PREFER_BIN;
+
+ for my $method (@methods) {
+ $self->_extractor($method) && return 1 if $self->$method();
+ }
+
+ return $self->_error(loc("Unable to untar file '%1'", $self->archive));
+}
+
+sub _uncompress_bin {
+ my $self = shift;
+
+ ### check for /bin/gzip -- we need it ###
+ return $self->_error(loc("No '%1' program found", '/bin/uncompress'))
+ unless $self->bin_uncompress;
+
+
+ my $fh = FileHandle->new('>'. $self->_gunzip_to) or
+ return $self->_error(loc("Could not open '%1' for writing: %2",
+ $self->_gunzip_to, $! ));
+
+ my $cmd = [ $self->bin_uncompress, '-c', $self->archive ];
+
+ my $buffer;
+ unless( scalar run( command => $cmd,
+ verbose => $DEBUG,
+ buffer => \$buffer )
+ ) {
+ return $self->_error(loc("Unable to uncompress '%1': %2",
+ $self->archive, $buffer));
+ }
+
+ ### no buffers available?
+ if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
+ $self->_error( $self->_no_buffer_content( $self->archive ) );
+ }
+
+ print $fh $buffer if defined $buffer;
+
+ close $fh;
+
+ ### set what files where extract, and where they went ###
+ $self->files( [$self->_gunzip_to] );
+ $self->extract_path( File::Spec->rel2abs(cwd()) );
+
+ return 1;
+}
+
+
+#################################
+#
+# Unzip code
+#
+#################################
+
+### unzip wrapper... goes to either Archive::Zip or /bin/unzip
+### depending on $PREFER_BIN
+sub _unzip {
+ my $self = shift;
+
+ my @methods = qw[_unzip_az _unzip_bin];
+ @methods = reverse @methods if $PREFER_BIN;
+
+ for my $method (@methods) {
+ $self->_extractor($method) && return 1 if $self->$method();
+ }
+
+ return $self->_error(loc("Unable to gunzip file '%1'", $self->archive));
+}
+
+sub _unzip_bin {
+ my $self = shift;
+
+ ### check for /bin/gzip if we need it ###
+ return $self->_error(loc("No '%1' program found", '/bin/unzip'))
+ unless $self->bin_unzip;
+
+
+ ### first, get the files.. it must be 2 different commands with 'unzip' :(
+ { my $cmd = [ $self->bin_unzip, '-Z', '-1', $self->archive ];
+
+ my $buffer = '';
+ unless( scalar run( command => $cmd,
+ verbose => $DEBUG,
+ buffer => \$buffer )
+ ) {
+ return $self->_error(loc("Unable to unzip '%1': %2",
+ $self->archive, $buffer));
+ }
+
+ ### no buffers available?
+ if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
+ $self->_error( $self->_no_buffer_files( $self->archive ) );
+
+ } else {
+ $self->files( [split $/, $buffer] );
+ }
+ }
+
+ ### now, extract the archive ###
+ { my $cmd = [ $self->bin_unzip, '-qq', '-o', $self->archive ];
+
+ my $buffer;
+ unless( scalar run( command => $cmd,
+ verbose => $DEBUG,
+ buffer => \$buffer )
+ ) {
+ return $self->_error(loc("Unable to unzip '%1': %2",
+ $self->archive, $buffer));
+ }
+
+ if( scalar @{$self->files} ) {
+ my $files = $self->files;
+ my $dir = $self->__get_extract_dir( $files );
+
+ $self->extract_path( $dir );
+ }
+ }
+
+ return 1;
+}
+
+sub _unzip_az {
+ my $self = shift;
+
+ my $use_list = { 'Archive::Zip' => '0.0' };
+ unless( can_load( modules => $use_list ) ) {
+ return $self->_error(loc("You do not have '%1' installed - Please " .
+ "install it as soon as possible.", 'Archive::Zip'));
+ }
+
+ my $zip = Archive::Zip->new();
+
+ unless( $zip->read( $self->archive ) == &Archive::Zip::AZ_OK ) {
+ return $self->_error(loc("Unable to read '%1'", $self->archive));
+ }
+
+ my @files;
+ ### have to extract every memeber individually ###
+ for my $member ($zip->members) {
+ push @files, $member->{fileName};
+
+ unless( $zip->extractMember($member) == &Archive::Zip::AZ_OK ) {
+ return $self->_error(loc("Extraction of '%1' from '%2' failed",
+ $member->{fileName}, $self->archive ));
+ }
+ }
+
+ my $dir = $self->__get_extract_dir( \@files );
+
+ ### set what files where extract, and where they went ###
+ $self->files( \@files );
+ $self->extract_path( File::Spec->rel2abs($dir) );
+
+ return 1;
+}
+
+sub __get_extract_dir {
+ my $self = shift;
+ my $files = shift || [];
+
+ return unless scalar @$files;
+
+ my($dir1, $dir2);
+ for my $aref ( [ \$dir1, 0 ], [ \$dir2, -1 ] ) {
+ my($dir,$pos) = @$aref;
+
+ ### add a catdir(), so that any trailing slashes get
+ ### take care of (removed)
+ ### also, a catdir() normalises './dir/foo' to 'dir/foo';
+ ### which was the problem in bug #23999
+ my $res = -d $files->[$pos]
+ ? File::Spec->catdir( $files->[$pos], '' )
+ : File::Spec->catdir( dirname( $files->[$pos] ) );
+
+ $$dir = $res;
+ }
+
+ ### if the first and last dir don't match, make sure the
+ ### dirname is not set wrongly
+ my $dir;
+
+ ### dirs are the same, so we know for sure what the extract dir is
+ if( $dir1 eq $dir2 ) {
+ $dir = $dir1;
+
+ ### dirs are different.. do they share the base dir?
+ ### if so, use that, if not, fall back to '.'
+ } else {
+ my $base1 = [ File::Spec->splitdir( $dir1 ) ]->[0];
+ my $base2 = [ File::Spec->splitdir( $dir2 ) ]->[0];
+
+ $dir = File::Spec->rel2abs( $base1 eq $base2 ? $base1 : '.' );
+ }
+
+ return File::Spec->rel2abs( $dir );
+}
+
+#################################
+#
+# Bunzip2 code
+#
+#################################
+
+### bunzip2 wrapper...
+sub _bunzip2 {
+ my $self = shift;
+
+ my @methods = qw[_bunzip2_cz2 _bunzip2_bin];
+ @methods = reverse @methods if $PREFER_BIN;
+
+ for my $method (@methods) {
+ $self->_extractor($method) && return 1 if $self->$method();
+ }
+
+ return $self->_error(loc("Unable to bunzip2 file '%1'", $self->archive));
+}
+
+sub _bunzip2_bin {
+ my $self = shift;
+
+ ### check for /bin/gzip -- we need it ###
+ return $self->_error(loc("No '%1' program found", '/bin/bunzip2'))
+ unless $self->bin_bunzip2;
+
+
+ my $fh = FileHandle->new('>'. $self->_gunzip_to) or
+ return $self->_error(loc("Could not open '%1' for writing: %2",
+ $self->_gunzip_to, $! ));
+
+ my $cmd = [ $self->bin_bunzip2, '-c', $self->archive ];
+
+ my $buffer;
+ unless( scalar run( command => $cmd,
+ verbose => $DEBUG,
+ buffer => \$buffer )
+ ) {
+ return $self->_error(loc("Unable to bunzip2 '%1': %2",
+ $self->archive, $buffer));
+ }
+
+ ### no buffers available?
+ if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
+ $self->_error( $self->_no_buffer_content( $self->archive ) );
+ }
+
+ print $fh $buffer if defined $buffer;
+
+ close $fh;
+
+ ### set what files where extract, and where they went ###
+ $self->files( [$self->_gunzip_to] );
+ $self->extract_path( File::Spec->rel2abs(cwd()) );
+
+ return 1;
+}
+
+### using cz2, the compact versions... this we use mainly in archive::tar
+### extractor..
+# sub _bunzip2_cz1 {
+# my $self = shift;
+#
+# my $use_list = { 'IO::Uncompress::Bunzip2' => '0.0' };
+# unless( can_load( modules => $use_list ) ) {
+# return $self->_error(loc("You do not have '%1' installed - Please " .
+# "install it as soon as possible.",
+# 'IO::Uncompress::Bunzip2'));
+# }
+#
+# my $bz = IO::Uncompress::Bunzip2->new( $self->archive ) or
+# return $self->_error(loc("Unable to open '%1': %2",
+# $self->archive,
+# $IO::Uncompress::Bunzip2::Bunzip2Error));
+#
+# my $fh = FileHandle->new('>'. $self->_gunzip_to) or
+# return $self->_error(loc("Could not open '%1' for writing: %2",
+# $self->_gunzip_to, $! ));
+#
+# my $buffer;
+# $fh->print($buffer) while $bz->read($buffer) > 0;
+# $fh->close;
+#
+# ### set what files where extract, and where they went ###
+# $self->files( [$self->_gunzip_to] );
+# $self->extract_path( File::Spec->rel2abs(cwd()) );
+#
+# return 1;
+# }
+
+sub _bunzip2_cz2 {
+ my $self = shift;
+
+ my $use_list = { 'IO::Uncompress::Bunzip2' => '0.0' };
+ unless( can_load( modules => $use_list ) ) {
+ return $self->_error(loc("You do not have '%1' installed - Please " .
+ "install it as soon as possible.",
+ 'IO::Uncompress::Bunzip2'));
+ }
+
+ IO::Uncompress::Bunzip2::bunzip2($self->archive => $self->_gunzip_to)
+ or return $self->_error(loc("Unable to uncompress '%1': %2",
+ $self->archive,
+ $IO::Uncompress::Bunzip2::Bunzip2Error));
+
+ ### set what files where extract, and where they went ###
+ $self->files( [$self->_gunzip_to] );
+ $self->extract_path( File::Spec->rel2abs(cwd()) );
+
+ return 1;
+}
+
+
+#################################
+#
+# Error code
+#
+#################################
+
+sub _error {
+ my $self = shift;
+ my $error = shift;
+
+ $self->_error_msg( $error );
+ $self->_error_msg_long( Carp::longmess($error) );
+
+ ### set $Archive::Extract::WARN to 0 to disable printing
+ ### of errors
+ if( $WARN ) {
+ carp $DEBUG ? $self->_error_msg_long : $self->_error_msg;
+ }
+
+ return;
+}
+
+sub error {
+ my $self = shift;
+ return shift() ? $self->_error_msg_long : $self->_error_msg;
+}
+
+sub _no_buffer_files {
+ my $self = shift;
+ my $file = shift or return;
+ return loc("No buffer captured, unable to tell ".
+ "extracted files or extraction dir for '%1'", $file);
+}
+
+sub _no_buffer_content {
+ my $self = shift;
+ my $file = shift or return;
+ return loc("No buffer captured, unable to get content for '%1'", $file);
+}
+1;
+
+=pod
+
+=head1 HOW IT WORKS
+
+C<Archive::Extract> tries first to determine what type of archive you
+are passing it, by inspecting its suffix. It does not do this by using
+Mime magic, or something related. See C<CAVEATS> below.
+
+Once it has determined the file type, it knows which extraction methods
+it can use on the archive. It will try a perl solution first, then fall
+back to a commandline tool if that fails. If that also fails, it will
+return false, indicating it was unable to extract the archive.
+See the section on C<GLOBAL VARIABLES> to see how to alter this order.
+
+=head1 CAVEATS
+
+=head2 File Extensions
+
+C<Archive::Extract> trusts on the extension of the archive to determine
+what type it is, and what extractor methods therefore can be used. If
+your archives do not have any of the extensions as described in the
+C<new()> method, you will have to specify the type explicitly, or
+C<Archive::Extract> will not be able to extract the archive for you.
+
+=head2 Bzip2 Support
+
+There's currently no very reliable pure perl Bzip2 implementation
+available, so C<Archive::Extract> can only extract C<bzip2>
+compressed archives if you have a C</bin/bunzip2> program.
+
+=head1 GLOBAL VARIABLES
+
+=head2 $Archive::Extract::DEBUG
+
+Set this variable to C<true> to have all calls to command line tools
+be printed out, including all their output.
+This also enables C<Carp::longmess> errors, instead of the regular
+C<carp> errors.
+
+Good for tracking down why things don't work with your particular
+setup.
+
+Defaults to C<false>.
+
+=head2 $Archive::Extract::WARN
+
+This variable controls whether errors encountered internally by
+C<Archive::Extract> should be C<carp>'d or not.
+
+Set to false to silence warnings. Inspect the output of the C<error()>
+method manually to see what went wrong.
+
+Defaults to C<true>.
+
+=head2 $Archive::Extract::PREFER_BIN
+
+This variables controls whether C<Archive::Extract> should prefer the
+use of perl modules, or commandline tools to extract archives.
+
+Set to C<true> to have C<Archive::Extract> prefer commandline tools.
+
+Defaults to C<false>.
+
+=head1 TODO
+
+=over 4
+
+=item Mime magic support
+
+Maybe this module should use something like C<File::Type> to determine
+the type, rather than blindly trust the suffix.
+
+=back
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-archive-extract@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
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
--- /dev/null
+package File::Fetch;
+
+use strict;
+use FileHandle;
+use File::Copy;
+use File::Spec;
+use File::Spec::Unix;
+use File::Basename qw[dirname];
+
+use Cwd qw[cwd];
+use Carp qw[carp];
+use IPC::Cmd qw[can_run run];
+use File::Path qw[mkpath];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+use Locale::Maketext::Simple Style => 'gettext';
+
+use vars qw[ $VERBOSE $PREFER_BIN $FROM_EMAIL $USER_AGENT
+ $BLACKLIST $METHOD_FAIL $VERSION $METHODS
+ $FTP_PASSIVE $TIMEOUT $DEBUG $WARN
+ ];
+
+use constant QUOTE => do { $^O eq 'MSWin32' ? q["] : q['] };
+
+
+$VERSION = '0.10';
+$PREFER_BIN = 0; # XXX TODO implement
+$FROM_EMAIL = 'File-Fetch@example.com';
+$USER_AGENT = 'File::Fetch/$VERSION';
+$BLACKLIST = [qw|ftp|];
+$METHOD_FAIL = { };
+$FTP_PASSIVE = 1;
+$TIMEOUT = 0;
+$DEBUG = 0;
+$WARN = 1;
+
+### methods available to fetch the file depending on the scheme
+$METHODS = {
+ http => [ qw|lwp wget curl lynx| ],
+ ftp => [ qw|lwp netftp wget curl ncftp ftp| ],
+ file => [ qw|lwp file| ],
+ rsync => [ qw|rsync| ]
+};
+
+### silly warnings ###
+local $Params::Check::VERBOSE = 1;
+local $Params::Check::VERBOSE = 1;
+local $Module::Load::Conditional::VERBOSE = 0;
+local $Module::Load::Conditional::VERBOSE = 0;
+
+### see what OS we are on, important for file:// uris ###
+use constant ON_UNIX => ($^O ne 'MSWin32' and
+ $^O ne 'MacOS' and
+ $^O ne 'VMS');
+
+=pod
+
+=head1 NAME
+
+File::Fetch - A generic file fetching mechanism
+
+=head1 SYNOPSIS
+
+ use File::Fetch;
+
+ ### build a File::Fetch object ###
+ my $ff = File::Fetch->new(uri => 'http://some.where.com/dir/a.txt');
+
+ ### fetch the uri to cwd() ###
+ my $where = $ff->fetch() or die $ff->error;
+
+ ### fetch the uri to /tmp ###
+ my $where = $ff->fetch( to => '/tmp' );
+
+ ### parsed bits from the uri ###
+ $ff->uri;
+ $ff->scheme;
+ $ff->host;
+ $ff->path;
+ $ff->file;
+
+=head1 DESCRIPTION
+
+File::Fetch is a generic file fetching mechanism.
+
+It allows you to fetch any file pointed to by a C<ftp>, C<http>,
+C<file>, or C<rsync> uri by a number of different means.
+
+See the C<HOW IT WORKS> section further down for details.
+
+=head1 ACCESSORS
+
+A C<File::Fetch> object has the following accessors
+
+=over 4
+
+=item $ff->uri
+
+The uri you passed to the constructor
+
+=item $ff->scheme
+
+The scheme from the uri (like 'file', 'http', etc)
+
+=item $ff->host
+
+The hostname in the uri, will be empty for a 'file' scheme.
+
+=item $ff->path
+
+The path from the uri, will be at least a single '/'.
+
+=item $ff->file
+
+The name of the remote file. For the local file name, the
+result of $ff->output_file will be used.
+
+=cut
+
+
+##########################
+### Object & Accessors ###
+##########################
+
+{
+ ### template for new() and autogenerated accessors ###
+ my $Tmpl = {
+ scheme => { default => 'http' },
+ host => { default => 'localhost' },
+ path => { default => '/' },
+ file => { required => 1 },
+ uri => { required => 1 },
+ _error_msg => { no_override => 1 },
+ _error_msg_long => { no_override => 1 },
+ };
+
+ for my $method ( keys %$Tmpl ) {
+ no strict 'refs';
+ *$method = sub {
+ my $self = shift;
+ $self->{$method} = $_[0] if @_;
+ return $self->{$method};
+ }
+ }
+
+ sub _create {
+ my $class = shift;
+ my %hash = @_;
+
+ my $args = check( $Tmpl, \%hash ) or return;
+
+ bless $args, $class;
+
+ if( lc($args->scheme) ne 'file' and not $args->host ) {
+ return File::Fetch->_error(loc(
+ "Hostname required when fetching from '%1'",$args->scheme));
+ }
+
+ for (qw[path file]) {
+ unless( $args->$_ ) {
+ return File::Fetch->_error(loc("No '%1' specified",$_));
+ }
+ }
+
+ return $args;
+ }
+}
+
+=item $ff->output_file
+
+The name of the output file. This is the same as $ff->file,
+but any query parameters are stripped off. For example:
+
+ http://example.com/index.html?x=y
+
+would make the output file be C<index.html> rather than
+C<index.html?x=y>.
+
+=back
+
+=cut
+
+sub output_file {
+ my $self = shift;
+ my $file = $self->file;
+
+ $file =~ s/\?.*$//g;
+
+ return $file;
+}
+
+### XXX do this or just point to URI::Escape?
+# =head2 $esc_uri = $ff->escaped_uri
+#
+# =cut
+#
+# ### most of this is stolen straight from URI::escape
+# { ### Build a char->hex map
+# my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255;
+#
+# sub escaped_uri {
+# my $self = shift;
+# my $uri = $self->uri;
+#
+# ### Default unsafe characters. RFC 2732 ^(uric - reserved)
+# $uri =~ s/([^A-Za-z0-9\-_.!~*'()])/
+# $escapes{$1} || $self->_fail_hi($1)/ge;
+#
+# return $uri;
+# }
+#
+# sub _fail_hi {
+# my $self = shift;
+# my $char = shift;
+#
+# $self->_error(loc(
+# "Can't escape '%1', try using the '%2' module instead",
+# sprintf("\\x{%04X}", ord($char)), 'URI::Escape'
+# ));
+# }
+#
+# sub output_file {
+#
+# }
+#
+#
+# }
+
+=head1 METHODS
+
+=head2 $ff = File::Fetch->new( uri => 'http://some.where.com/dir/file.txt' );
+
+Parses the uri and creates a corresponding File::Fetch::Item object,
+that is ready to be C<fetch>ed and returns it.
+
+Returns false on failure.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my %hash = @_;
+
+ my ($uri);
+ my $tmpl = {
+ uri => { required => 1, store => \$uri },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### parse the uri to usable parts ###
+ my $href = __PACKAGE__->_parse_uri( $uri ) or return;
+
+ ### make it into a FFI object ###
+ my $ff = File::Fetch->_create( %$href ) or return;
+
+
+ ### return the object ###
+ return $ff;
+}
+
+### parses an uri to a hash structure:
+###
+### $class->_parse_uri( 'ftp://ftp.cpan.org/pub/mirror/index.txt' )
+###
+### becomes:
+###
+### $href = {
+### scheme => 'ftp',
+### host => 'ftp.cpan.org',
+### path => '/pub/mirror',
+### file => 'index.html'
+### };
+###
+sub _parse_uri {
+ my $self = shift;
+ my $uri = shift or return;
+
+ my $href = { uri => $uri };
+
+ ### find the scheme ###
+ $uri =~ s|^(\w+)://||;
+ $href->{scheme} = $1;
+
+ ### file:// paths have no host ###
+ if( $href->{scheme} eq 'file' ) {
+ $href->{path} = $uri;
+ $href->{host} = '';
+
+ } else {
+ @{$href}{qw|host path|} = $uri =~ m|([^/]*)(/.*)$|s;
+ }
+
+ ### split the path into file + dir ###
+ { my @parts = File::Spec::Unix->splitpath( delete $href->{path} );
+ $href->{path} = $parts[1];
+ $href->{file} = $parts[2];
+ }
+
+
+ return $href;
+}
+
+=head2 $ff->fetch( [to => /my/output/dir/] )
+
+Fetches the file you requested. By default it writes to C<cwd()>,
+but you can override that by specifying the C<to> argument.
+
+Returns the full path to the downloaded file on success, and false
+on failure.
+
+=cut
+
+sub fetch {
+ my $self = shift or return;
+ my %hash = @_;
+
+ my $to;
+ my $tmpl = {
+ to => { default => cwd(), store => \$to },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### create the path if it doesn't exist yet ###
+ unless( -d $to ) {
+ eval { mkpath( $to ) };
+
+ return $self->_error(loc("Could not create path '%1'",$to)) if $@;
+ }
+
+ ### set passive ftp if required ###
+ local $ENV{FTP_PASSIVE} = $FTP_PASSIVE;
+
+ ###
+ for my $method ( @{ $METHODS->{$self->scheme} } ) {
+ my $sub = '_'.$method.'_fetch';
+
+ unless( __PACKAGE__->can($sub) ) {
+ $self->_error(loc("Cannot call method for '%1' -- WEIRD!",
+ $method));
+ next;
+ }
+
+ ### method is blacklisted ###
+ next if grep { lc $_ eq $method } @$BLACKLIST;
+
+ ### method is known to fail ###
+ next if $METHOD_FAIL->{$method};
+
+ ### there's serious issues with IPC::Run and quoting of command
+ ### line arguments. using quotes in the wrong place breaks things,
+ ### and in the case of say,
+ ### C:\cygwin\bin\wget.EXE --quiet --passive-ftp --output-document
+ ### "index.html" "http://www.cpan.org/index.html?q=1&y=2"
+ ### it doesn't matter how you quote, it always fails.
+ local $IPC::Cmd::USE_IPC_RUN = 0;
+
+ if( my $file = $self->$sub(
+ to => File::Spec->catfile( $to, $self->output_file )
+ )){
+
+ unless( -e $file && -s _ ) {
+ $self->_error(loc("'%1' said it fetched '%2', ".
+ "but it was not created",$method,$file));
+
+ ### mark the failure ###
+ $METHOD_FAIL->{$method} = 1;
+
+ next;
+
+ } else {
+
+ my $abs = File::Spec->rel2abs( $file );
+ return $abs;
+ }
+ }
+ }
+
+
+ ### if we got here, we looped over all methods, but we weren't able
+ ### to fetch it.
+ return;
+}
+
+########################
+### _*_fetch methods ###
+########################
+
+### LWP fetching ###
+sub _lwp_fetch {
+ my $self = shift;
+ my %hash = @_;
+
+ my ($to);
+ my $tmpl = {
+ to => { required => 1, store => \$to }
+ };
+ check( $tmpl, \%hash ) or return;
+
+ ### modules required to download with lwp ###
+ my $use_list = {
+ LWP => '0.0',
+ 'LWP::UserAgent' => '0.0',
+ 'HTTP::Request' => '0.0',
+ 'HTTP::Status' => '0.0',
+ URI => '0.0',
+
+ };
+
+ if( can_load(modules => $use_list) ) {
+
+ ### setup the uri object
+ my $uri = URI->new( File::Spec::Unix->catfile(
+ $self->path, $self->file
+ ) );
+
+ ### special rules apply for file:// uris ###
+ $uri->scheme( $self->scheme );
+ $uri->host( $self->scheme eq 'file' ? '' : $self->host );
+ $uri->userinfo("anonymous:$FROM_EMAIL") if $self->scheme ne 'file';
+
+ ### set up the useragent object
+ my $ua = LWP::UserAgent->new();
+ $ua->timeout( $TIMEOUT ) if $TIMEOUT;
+ $ua->agent( $USER_AGENT );
+ $ua->from( $FROM_EMAIL );
+ $ua->env_proxy;
+
+ my $res = $ua->mirror($uri, $to) or return;
+
+ ### uptodate or fetched ok ###
+ if ( $res->code == 304 or $res->code == 200 ) {
+ return $to;
+
+ } else {
+ return $self->_error(loc("Fetch failed! HTTP response: %1 %2 [%3]",
+ $res->code, HTTP::Status::status_message($res->code),
+ $res->status_line));
+ }
+
+ } else {
+ $METHOD_FAIL->{'lwp'} = 1;
+ return;
+ }
+}
+
+### Net::FTP fetching
+sub _netftp_fetch {
+ my $self = shift;
+ my %hash = @_;
+
+ my ($to);
+ my $tmpl = {
+ to => { required => 1, store => \$to }
+ };
+ check( $tmpl, \%hash ) or return;
+
+ ### required modules ###
+ my $use_list = { 'Net::FTP' => 0 };
+
+ if( can_load( modules => $use_list ) ) {
+
+ ### make connection ###
+ my $ftp;
+ my @options = ($self->host);
+ push(@options, Timeout => $TIMEOUT) if $TIMEOUT;
+ unless( $ftp = Net::FTP->new( @options ) ) {
+ return $self->_error(loc("Ftp creation failed: %1",$@));
+ }
+
+ ### login ###
+ unless( $ftp->login( anonymous => $FROM_EMAIL ) ) {
+ return $self->_error(loc("Could not login to '%1'",$self->host));
+ }
+
+ ### set binary mode, just in case ###
+ $ftp->binary;
+
+ ### create the remote path
+ ### remember remote paths are unix paths! [#11483]
+ my $remote = File::Spec::Unix->catfile( $self->path, $self->file );
+
+ ### fetch the file ###
+ my $target;
+ unless( $target = $ftp->get( $remote, $to ) ) {
+ return $self->_error(loc("Could not fetch '%1' from '%2'",
+ $remote, $self->host));
+ }
+
+ ### log out ###
+ $ftp->quit;
+
+ return $target;
+
+ } else {
+ $METHOD_FAIL->{'netftp'} = 1;
+ return;
+ }
+}
+
+### /bin/wget fetch ###
+sub _wget_fetch {
+ my $self = shift;
+ my %hash = @_;
+
+ my ($to);
+ my $tmpl = {
+ to => { required => 1, store => \$to }
+ };
+ check( $tmpl, \%hash ) or return;
+
+ ### see if we have a wget binary ###
+ if( my $wget = can_run('wget') ) {
+
+ ### no verboseness, thanks ###
+ my $cmd = [ $wget, '--quiet' ];
+
+ ### if a timeout is set, add it ###
+ push(@$cmd, '--timeout=' . $TIMEOUT) if $TIMEOUT;
+
+ ### run passive if specified ###
+ push @$cmd, '--passive-ftp' if $FTP_PASSIVE;
+
+ ### set the output document, add the uri ###
+ push @$cmd, '--output-document',
+ ### DO NOT quote things for IPC::Run, it breaks stuff.
+ $IPC::Cmd::USE_IPC_RUN
+ ? ($to, $self->uri)
+ : (QUOTE. $to .QUOTE, QUOTE. $self->uri .QUOTE);
+
+ ### shell out ###
+ my $captured;
+ unless(run( command => $cmd,
+ buffer => \$captured,
+ verbose => $DEBUG
+ )) {
+ ### wget creates the output document always, even if the fetch
+ ### fails.. so unlink it in that case
+ 1 while unlink $to;
+
+ return $self->_error(loc( "Command failed: %1", $captured || '' ));
+ }
+
+ return $to;
+
+ } else {
+ $METHOD_FAIL->{'wget'} = 1;
+ return;
+ }
+}
+
+
+### /bin/ftp fetch ###
+sub _ftp_fetch {
+ my $self = shift;
+ my %hash = @_;
+
+ my ($to);
+ my $tmpl = {
+ to => { required => 1, store => \$to }
+ };
+ check( $tmpl, \%hash ) or return;
+
+ ### see if we have a ftp binary ###
+ if( my $ftp = can_run('ftp') ) {
+
+ my $fh = FileHandle->new;
+
+ local $SIG{CHLD} = 'IGNORE';
+
+ unless ($fh->open("|$ftp -n")) {
+ return $self->_error(loc("%1 creation failed: %2", $ftp, $!));
+ }
+
+ my @dialog = (
+ "lcd " . dirname($to),
+ "open " . $self->host,
+ "user anonymous $FROM_EMAIL",
+ "cd /",
+ "cd " . $self->path,
+ "binary",
+ "get " . $self->file . " " . $self->output_file,
+ "quit",
+ );
+
+ foreach (@dialog) { $fh->print($_, "\n") }
+ $fh->close or return;
+
+ return $to;
+ }
+}
+
+### lynx is stupid - it decompresses any .gz file it finds to be text
+### use /bin/lynx to fetch files
+sub _lynx_fetch {
+ my $self = shift;
+ my %hash = @_;
+
+ my ($to);
+ my $tmpl = {
+ to => { required => 1, store => \$to }
+ };
+ check( $tmpl, \%hash ) or return;
+
+ ### see if we have a lynx binary ###
+ if( my $lynx = can_run('lynx') ) {
+
+ unless( IPC::Cmd->can_capture_buffer ) {
+ $METHOD_FAIL->{'lynx'} = 1;
+
+ return $self->_error(loc(
+ "Can not capture buffers. Can not use '%1' to fetch files",
+ 'lynx' ));
+ }
+
+ ### write to the output file ourselves, since lynx ass_u_mes to much
+ my $local = FileHandle->new(">$to")
+ or return $self->_error(loc(
+ "Could not open '%1' for writing: %2",$to,$!));
+
+ ### dump to stdout ###
+ my $cmd = [
+ $lynx,
+ '-source',
+ "-auth=anonymous:$FROM_EMAIL",
+ ];
+
+ push @$cmd, "-connect_timeout=$TIMEOUT" if $TIMEOUT;
+
+ ### DO NOT quote things for IPC::Run, it breaks stuff.
+ push @$cmd, $IPC::Cmd::USE_IPC_RUN
+ ? $self->uri
+ : QUOTE. $self->uri .QUOTE;
+
+
+ ### shell out ###
+ my $captured;
+ unless(run( command => $cmd,
+ buffer => \$captured,
+ verbose => $DEBUG )
+ ) {
+ return $self->_error(loc("Command failed: %1", $captured || ''));
+ }
+
+ ### print to local file ###
+ ### XXX on a 404 with a special error page, $captured will actually
+ ### hold the contents of that page, and make it *appear* like the
+ ### request was a success, when really it wasn't :(
+ ### there doesn't seem to be an option for lynx to change the exit
+ ### code based on a 4XX status or so.
+ ### the closest we can come is using --error_file and parsing that,
+ ### which is very unreliable ;(
+ $local->print( $captured );
+ $local->close or return;
+
+ return $to;
+
+ } else {
+ $METHOD_FAIL->{'lynx'} = 1;
+ return;
+ }
+}
+
+### use /bin/ncftp to fetch files
+sub _ncftp_fetch {
+ my $self = shift;
+ my %hash = @_;
+
+ my ($to);
+ my $tmpl = {
+ to => { required => 1, store => \$to }
+ };
+ check( $tmpl, \%hash ) or return;
+
+ ### we can only set passive mode in interactive sesssions, so bail out
+ ### if $FTP_PASSIVE is set
+ return if $FTP_PASSIVE;
+
+ ### see if we have a ncftp binary ###
+ if( my $ncftp = can_run('ncftp') ) {
+
+ my $cmd = [
+ $ncftp,
+ '-V', # do not be verbose
+ '-p', $FROM_EMAIL, # email as password
+ $self->host, # hostname
+ dirname($to), # local dir for the file
+ # remote path to the file
+ ### DO NOT quote things for IPC::Run, it breaks stuff.
+ $IPC::Cmd::USE_IPC_RUN
+ ? File::Spec::Unix->catdir( $self->path, $self->file )
+ : QUOTE. File::Spec::Unix->catdir(
+ $self->path, $self->file ) .QUOTE
+
+ ];
+
+ ### shell out ###
+ my $captured;
+ unless(run( command => $cmd,
+ buffer => \$captured,
+ verbose => $DEBUG )
+ ) {
+ return $self->_error(loc("Command failed: %1", $captured || ''));
+ }
+
+ return $to;
+
+ } else {
+ $METHOD_FAIL->{'ncftp'} = 1;
+ return;
+ }
+}
+
+### use /bin/curl to fetch files
+sub _curl_fetch {
+ my $self = shift;
+ my %hash = @_;
+
+ my ($to);
+ my $tmpl = {
+ to => { required => 1, store => \$to }
+ };
+ check( $tmpl, \%hash ) or return;
+
+ if (my $curl = can_run('curl')) {
+
+ ### these long opts are self explanatory - I like that -jmb
+ my $cmd = [ $curl ];
+
+ push(@$cmd, '--connect-timeout', $TIMEOUT) if $TIMEOUT;
+
+ push(@$cmd, '--silent') unless $DEBUG;
+
+ ### curl does the right thing with passive, regardless ###
+ if ($self->scheme eq 'ftp') {
+ push(@$cmd, '--user', "anonymous:$FROM_EMAIL");
+ }
+
+ ### curl doesn't follow 302 (temporarily moved) etc automatically
+ ### so we add --location to enable that.
+ push @$cmd, '--fail', '--location', '--output',
+ ### DO NOT quote things for IPC::Run, it breaks stuff.
+ $IPC::Cmd::USE_IPC_RUN
+ ? ($to, $self->uri)
+ : (QUOTE. $to .QUOTE, QUOTE. $self->uri .QUOTE);
+
+ my $captured;
+ unless(run( command => $cmd,
+ buffer => \$captured,
+ verbose => $DEBUG )
+ ) {
+
+ return $self->_error(loc("Command failed: %1", $captured || ''));
+ }
+
+ return $to;
+
+ } else {
+ $METHOD_FAIL->{'curl'} = 1;
+ return;
+ }
+}
+
+
+### use File::Copy for fetching file:// urls ###
+### XXX file:// uri to local path conversion is just too weird...
+### depend on LWP to do it for us
+sub _file_fetch {
+ my $self = shift;
+ my %hash = @_;
+
+ my ($to);
+ my $tmpl = {
+ to => { required => 1, store => \$to }
+ };
+ check( $tmpl, \%hash ) or return;
+
+ ### prefix a / on unix systems with a file uri, since it would
+ ### look somewhat like this:
+ ### file://home/kane/file
+ ### wheras windows file uris might look like:
+ ### file://C:/home/kane/file
+ my $path = ON_UNIX ? '/'. $self->path : $self->path;
+
+ my $remote = File::Spec->catfile( $path, $self->file );
+
+ ### File::Copy is littered with 'die' statements :( ###
+ my $rv = eval { File::Copy::copy( $remote, $to ) };
+
+ ### something went wrong ###
+ if( !$rv or $@ ) {
+ return $self->_error(loc("Could not copy '%1' to '%2': %3 %4",
+ $remote, $to, $!, $@));
+ }
+
+ return $to;
+}
+
+### use /usr/bin/rsync to fetch files
+sub _rsync_fetch {
+ my $self = shift;
+ my %hash = @_;
+
+ my ($to);
+ my $tmpl = {
+ to => { required => 1, store => \$to }
+ };
+ check( $tmpl, \%hash ) or return;
+
+ if (my $rsync = can_run('rsync')) {
+
+ my $cmd = [ $rsync ];
+
+ ### XXX: rsync has no I/O timeouts at all, by default
+ push(@$cmd, '--timeout=' . $TIMEOUT) if $TIMEOUT;
+
+ push(@$cmd, '--quiet') unless $DEBUG;
+
+ ### DO NOT quote things for IPC::Run, it breaks stuff.
+ push @$cmd, $IPC::Cmd::USE_IPC_RUN
+ ? ($self->uri, $to)
+ : (QUOTE. $self->uri .QUOTE, QUOTE. $to .QUOTE);
+
+ my $captured;
+ unless(run( command => $cmd,
+ buffer => \$captured,
+ verbose => $DEBUG )
+ ) {
+
+ return $self->_error(loc("Command failed: %1", $captured || ''));
+ }
+
+ return $to;
+
+ } else {
+ $METHOD_FAIL->{'rsync'} = 1;
+ return;
+ }
+}
+
+#################################
+#
+# Error code
+#
+#################################
+
+=pod
+
+=head2 $ff->error([BOOL])
+
+Returns the last encountered error as string.
+Pass it a true value to get the C<Carp::longmess()> output instead.
+
+=cut
+
+### error handling the way Archive::Extract does it
+sub _error {
+ my $self = shift;
+ my $error = shift;
+
+ $self->_error_msg( $error );
+ $self->_error_msg_long( Carp::longmess($error) );
+
+ if( $WARN ) {
+ carp $DEBUG ? $self->_error_msg_long : $self->_error_msg;
+ }
+
+ return;
+}
+
+sub error {
+ my $self = shift;
+ return shift() ? $self->_error_msg_long : $self->_error_msg;
+}
+
+
+1;
+
+=pod
+
+=head1 HOW IT WORKS
+
+File::Fetch is able to fetch a variety of uris, by using several
+external programs and modules.
+
+Below is a mapping of what utilities will be used in what order
+for what schemes, if available:
+
+ file => LWP, file
+ http => LWP, wget, curl, lynx
+ ftp => LWP, Net::FTP, wget, curl, ncftp, ftp
+ rsync => rsync
+
+If you'd like to disable the use of one or more of these utilities
+and/or modules, see the C<$BLACKLIST> variable further down.
+
+If a utility or module isn't available, it will be marked in a cache
+(see the C<$METHOD_FAIL> variable further down), so it will not be
+tried again. The C<fetch> method will only fail when all options are
+exhausted, and it was not able to retrieve the file.
+
+A special note about fetching files from an ftp uri:
+
+By default, all ftp connections are done in passive mode. To change
+that, see the C<$FTP_PASSIVE> variable further down.
+
+Furthermore, ftp uris only support anonymous connections, so no
+named user/password pair can be passed along.
+
+C</bin/ftp> is blacklisted by default; see the C<$BLACKLIST> variable
+further down.
+
+=head1 GLOBAL VARIABLES
+
+The behaviour of File::Fetch can be altered by changing the following
+global variables:
+
+=head2 $File::Fetch::FROM_EMAIL
+
+This is the email address that will be sent as your anonymous ftp
+password.
+
+Default is C<File-Fetch@example.com>.
+
+=head2 $File::Fetch::USER_AGENT
+
+This is the useragent as C<LWP> will report it.
+
+Default is C<File::Fetch/$VERSION>.
+
+=head2 $File::Fetch::FTP_PASSIVE
+
+This variable controls whether the environment variable C<FTP_PASSIVE>
+and any passive switches to commandline tools will be set to true.
+
+Default value is 1.
+
+Note: When $FTP_PASSIVE is true, C<ncftp> will not be used to fetch
+files, since passive mode can only be set interactively for this binary
+
+=head2 $File::Fetch::TIMEOUT
+
+When set, controls the network timeout (counted in seconds).
+
+Default value is 0.
+
+=head2 $File::Fetch::WARN
+
+This variable controls whether errors encountered internally by
+C<File::Fetch> should be C<carp>'d or not.
+
+Set to false to silence warnings. Inspect the output of the C<error()>
+method manually to see what went wrong.
+
+Defaults to C<true>.
+
+=head2 $File::Fetch::DEBUG
+
+This enables debugging output when calling commandline utilities to
+fetch files.
+This also enables C<Carp::longmess> errors, instead of the regular
+C<carp> errors.
+
+Good for tracking down why things don't work with your particular
+setup.
+
+Default is 0.
+
+=head2 $File::Fetch::BLACKLIST
+
+This is an array ref holding blacklisted modules/utilities for fetching
+files with.
+
+To disallow the use of, for example, C<LWP> and C<Net::FTP>, you could
+set $File::Fetch::BLACKLIST to:
+
+ $File::Fetch::BLACKLIST = [qw|lwp netftp|]
+
+The default blacklist is [qw|ftp|], as C</bin/ftp> is rather unreliable.
+
+See the note on C<MAPPING> below.
+
+=head2 $File::Fetch::METHOD_FAIL
+
+This is a hashref registering what modules/utilities were known to fail
+for fetching files (mostly because they weren't installed).
+
+You can reset this cache by assigning an empty hashref to it, or
+individually remove keys.
+
+See the note on C<MAPPING> below.
+
+=head1 MAPPING
+
+
+Here's a quick mapping for the utilities/modules, and their names for
+the $BLACKLIST, $METHOD_FAIL and other internal functions.
+
+ LWP => lwp
+ Net::FTP => netftp
+ wget => wget
+ lynx => lynx
+ ncftp => ncftp
+ ftp => ftp
+ curl => curl
+ rsync => rsync
+
+=head1 FREQUENTLY ASKED QUESTIONS
+
+=head2 So how do I use a proxy with File::Fetch?
+
+C<File::Fetch> currently only supports proxies with LWP::UserAgent.
+You will need to set your environment variables accordingly. For
+example, to use an ftp proxy:
+
+ $ENV{ftp_proxy} = 'foo.com';
+
+Refer to the LWP::UserAgent manpage for more details.
+
+=head2 I used 'lynx' to fetch a file, but its contents is all wrong!
+
+C<lynx> can only fetch remote files by dumping its contents to C<STDOUT>,
+which we in turn capture. If that content is a 'custom' error file
+(like, say, a C<404 handler>), you will get that contents instead.
+
+Sadly, C<lynx> doesn't support any options to return a different exit
+code on non-C<200 OK> status, giving us no way to tell the difference
+between a 'successfull' fetch and a custom error page.
+
+Therefor, we recommend to only use C<lynx> as a last resort. This is
+why it is at the back of our list of methods to try as well.
+
+=head2 Files I'm trying to fetch have reserved characters or non-ASCII characters in them. What do I do?
+
+C<File::Fetch> is relatively smart about things. When trying to write
+a file to disk, it removes the C<query parameters> (see the
+C<output_file> method for details) from the file name before creating
+it. In most cases this suffices.
+
+If you have any other characters you need to escape, please install
+the C<URI::Escape> module from CPAN, and pre-encode your URI before
+passing it to C<File::Fetch>. You can read about the details of URIs
+and URI encoding here:
+
+ http://www.faqs.org/rfcs/rfc2396.html
+
+=head1 TODO
+
+=over 4
+
+=item Implement $PREFER_BIN
+
+To indicate to rather use commandline tools than modules
+
+=head1 AUTHORS
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+This module is copyright (c) 2003-2007 Jos Boumans
+E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+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:
+
+
+
+
--- /dev/null
+package File::Spec::Unix;
+
+use strict;
+use vars qw($VERSION);
+
+$VERSION = '1.5';
+
+=head1 NAME
+
+File::Spec::Unix - File::Spec for Unix, base for other File::Spec modules
+
+=head1 SYNOPSIS
+
+ require File::Spec::Unix; # Done automatically by File::Spec
+
+=head1 DESCRIPTION
+
+Methods for manipulating file specifications. Other File::Spec
+modules, such as File::Spec::Mac, inherit from File::Spec::Unix and
+override specific methods.
+
+=head1 METHODS
+
+=over 2
+
+=item canonpath()
+
+No physical check on the filesystem, but a logical cleanup of a
+path. On UNIX eliminates successive slashes and successive "/.".
+
+ $cpath = File::Spec->canonpath( $path ) ;
+
+Note that this does *not* collapse F<x/../y> sections into F<y>. This
+is by design. If F</foo> on your system is a symlink to F</bar/baz>,
+then F</foo/../quux> is actually F</bar/quux>, not F</quux> as a naive
+F<../>-removal would give you. If you want to do this kind of
+processing, you probably want C<Cwd>'s C<realpath()> function to
+actually traverse the filesystem cleaning up paths like this.
+
+=cut
+
+sub canonpath {
+ my ($self,$path) = @_;
+
+ # Handle POSIX-style node names beginning with double slash (qnx, nto)
+ # (POSIX says: "a pathname that begins with two successive slashes
+ # may be interpreted in an implementation-defined manner, although
+ # more than two leading slashes shall be treated as a single slash.")
+ my $node = '';
+ my $double_slashes_special = $^O eq 'qnx' || $^O eq 'nto';
+ if ( $double_slashes_special && $path =~ s{^(//[^/]+)(?:/|\z)}{/}s ) {
+ $node = $1;
+ }
+ # This used to be
+ # $path =~ s|/+|/|g unless ($^O eq 'cygwin');
+ # but that made tests 29, 30, 35, 46, and 213 (as of #13272) to fail
+ # (Mainly because trailing "" directories didn't get stripped).
+ # Why would cygwin avoid collapsing multiple slashes into one? --jhi
+ $path =~ s|/{2,}|/|g; # xx////xx -> xx/xx
+ $path =~ s{(?:/\.)+(?:/|\z)}{/}g; # xx/././xx -> xx/xx
+ $path =~ s|^(?:\./)+||s unless $path eq "./"; # ./xx -> xx
+ $path =~ s|^/(?:\.\./)+|/|; # /../../xx -> xx
+ $path =~ s|^/\.\.$|/|; # /.. -> /
+ $path =~ s|/\z|| unless $path eq "/"; # xx/ -> xx
+ return "$node$path";
+}
+
+=item catdir()
+
+Concatenate two or more directory names to form a complete path ending
+with a directory. But remove the trailing slash from the resulting
+string, because it doesn't look good, isn't necessary and confuses
+OS2. Of course, if this is the root directory, don't cut off the
+trailing slash :-)
+
+=cut
+
+sub catdir {
+ my $self = shift;
+
+ $self->canonpath(join('/', @_, '')); # '' because need a trailing '/'
+}
+
+=item catfile
+
+Concatenate one or more directory names and a filename to form a
+complete path ending with a filename
+
+=cut
+
+sub catfile {
+ my $self = shift;
+ my $file = $self->canonpath(pop @_);
+ return $file unless @_;
+ my $dir = $self->catdir(@_);
+ $dir .= "/" unless substr($dir,-1) eq "/";
+ return $dir.$file;
+}
+
+=item curdir
+
+Returns a string representation of the current directory. "." on UNIX.
+
+=cut
+
+sub curdir () { '.' }
+
+=item devnull
+
+Returns a string representation of the null device. "/dev/null" on UNIX.
+
+=cut
+
+sub devnull () { '/dev/null' }
+
+=item rootdir
+
+Returns a string representation of the root directory. "/" on UNIX.
+
+=cut
+
+sub rootdir () { '/' }
+
+=item tmpdir
+
+Returns a string representation of the first writable directory from
+the following list or the current directory if none from the list are
+writable:
+
+ $ENV{TMPDIR}
+ /tmp
+
+Since perl 5.8.0, if running under taint mode, and if $ENV{TMPDIR}
+is tainted, it is not used.
+
+=cut
+
+my $tmpdir;
+sub _tmpdir {
+ return $tmpdir if defined $tmpdir;
+ my $self = shift;
+ my @dirlist = @_;
+ {
+ no strict 'refs';
+ if (${"\cTAINT"}) { # Check for taint mode on perl >= 5.8.0
+ require Scalar::Util;
+ @dirlist = grep { ! Scalar::Util::tainted($_) } @dirlist;
+ }
+ }
+ foreach (@dirlist) {
+ next unless defined && -d && -w _;
+ $tmpdir = $_;
+ last;
+ }
+ $tmpdir = $self->curdir unless defined $tmpdir;
+ $tmpdir = defined $tmpdir && $self->canonpath($tmpdir);
+ return $tmpdir;
+}
+
+sub tmpdir {
+ return $tmpdir if defined $tmpdir;
+ $tmpdir = $_[0]->_tmpdir( $ENV{TMPDIR}, "/tmp" );
+}
+
+=item updir
+
+Returns a string representation of the parent directory. ".." on UNIX.
+
+=cut
+
+sub updir () { '..' }
+
+=item no_upwards
+
+Given a list of file names, strip out those that refer to a parent
+directory. (Does not strip symlinks, only '.', '..', and equivalents.)
+
+=cut
+
+sub no_upwards {
+ my $self = shift;
+ return grep(!/^\.{1,2}\z/s, @_);
+}
+
+=item case_tolerant
+
+Returns a true or false value indicating, respectively, that alphabetic
+is not or is significant when comparing file specifications.
+
+=cut
+
+sub case_tolerant () { 0 }
+
+=item file_name_is_absolute
+
+Takes as argument a path and returns true if it is an absolute path.
+
+This does not consult the local filesystem on Unix, Win32, OS/2 or Mac
+OS (Classic). It does consult the working environment for VMS (see
+L<File::Spec::VMS/file_name_is_absolute>).
+
+=cut
+
+sub file_name_is_absolute {
+ my ($self,$file) = @_;
+ return scalar($file =~ m:^/:s);
+}
+
+=item path
+
+Takes no argument, returns the environment variable PATH as an array.
+
+=cut
+
+sub path {
+ return () unless exists $ENV{PATH};
+ my @path = split(':', $ENV{PATH});
+ foreach (@path) { $_ = '.' if $_ eq '' }
+ return @path;
+}
+
+=item join
+
+join is the same as catfile.
+
+=cut
+
+sub join {
+ my $self = shift;
+ return $self->catfile(@_);
+}
+
+=item splitpath
+
+ ($volume,$directories,$file) = File::Spec->splitpath( $path );
+ ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
+
+Splits a path into volume, directory, and filename portions. On systems
+with no concept of volume, returns '' for volume.
+
+For systems with no syntax differentiating filenames from directories,
+assumes that the last file is a path unless $no_file is true or a
+trailing separator or /. or /.. is present. On Unix this means that $no_file
+true makes this return ( '', $path, '' ).
+
+The directory portion may or may not be returned with a trailing '/'.
+
+The results can be passed to L</catpath()> to get back a path equivalent to
+(usually identical to) the original path.
+
+=cut
+
+sub splitpath {
+ my ($self,$path, $nofile) = @_;
+
+ my ($volume,$directory,$file) = ('','','');
+
+ if ( $nofile ) {
+ $directory = $path;
+ }
+ else {
+ $path =~ m|^ ( (?: .* / (?: \.\.?\z )? )? ) ([^/]*) |xs;
+ $directory = $1;
+ $file = $2;
+ }
+
+ return ($volume,$directory,$file);
+}
+
+
+=item splitdir
+
+The opposite of L</catdir()>.
+
+ @dirs = File::Spec->splitdir( $directories );
+
+$directories must be only the directory portion of the path on systems
+that have the concept of a volume or that have path syntax that differentiates
+files from directories.
+
+Unlike just splitting the directories on the separator, empty
+directory names (C<''>) can be returned, because these are significant
+on some OSs.
+
+On Unix,
+
+ File::Spec->splitdir( "/a/b//c/" );
+
+Yields:
+
+ ( '', 'a', 'b', '', 'c', '' )
+
+=cut
+
+sub splitdir {
+ return split m|/|, $_[1], -1; # Preserve trailing fields
+}
+
+
+=item catpath()
+
+Takes volume, directory and file portions and returns an entire path. Under
+Unix, $volume is ignored, and directory and file are concatenated. A '/' is
+inserted if needed (though if the directory portion doesn't start with
+'/' it is not added). On other OSs, $volume is significant.
+
+=cut
+
+sub catpath {
+ my ($self,$volume,$directory,$file) = @_;
+
+ if ( $directory ne '' &&
+ $file ne '' &&
+ substr( $directory, -1 ) ne '/' &&
+ substr( $file, 0, 1 ) ne '/'
+ ) {
+ $directory .= "/$file" ;
+ }
+ else {
+ $directory .= $file ;
+ }
+
+ return $directory ;
+}
+
+=item abs2rel
+
+Takes a destination path and an optional base path returns a relative path
+from the base path to the destination path:
+
+ $rel_path = File::Spec->abs2rel( $path ) ;
+ $rel_path = File::Spec->abs2rel( $path, $base ) ;
+
+If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
+relative, then it is converted to absolute form using
+L</rel2abs()>. This means that it is taken to be relative to
+L<cwd()|Cwd>.
+
+On systems that have a grammar that indicates filenames, this ignores the
+$base filename. Otherwise all path components are assumed to be
+directories.
+
+If $path is relative, it is converted to absolute form using L</rel2abs()>.
+This means that it is taken to be relative to L<cwd()|Cwd>.
+
+No checks against the filesystem are made. On VMS, there is
+interaction with the working environment, as logicals and
+macros are expanded.
+
+Based on code written by Shigio Yamaguchi.
+
+=cut
+
+sub abs2rel {
+ my($self,$path,$base) = @_;
+ $base = $self->_cwd() unless defined $base and length $base;
+
+ ($path, $base) = map $self->canonpath($_), $path, $base;
+
+ if (grep $self->file_name_is_absolute($_), $path, $base) {
+ ($path, $base) = map $self->rel2abs($_), $path, $base;
+ }
+ else {
+ # save a couple of cwd()s if both paths are relative
+ ($path, $base) = map $self->catdir('/', $_), $path, $base;
+ }
+
+ my ($path_volume) = $self->splitpath($path, 1);
+ my ($base_volume) = $self->splitpath($base, 1);
+
+ # Can't relativize across volumes
+ return $path unless $path_volume eq $base_volume;
+
+ my $path_directories = ($self->splitpath($path, 1))[1];
+ my $base_directories = ($self->splitpath($base, 1))[1];
+
+ # For UNC paths, the user might give a volume like //foo/bar that
+ # strictly speaking has no directory portion. Treat it as if it
+ # had the root directory for that volume.
+ if (!length($base_directories) and $self->file_name_is_absolute($base)) {
+ $base_directories = $self->rootdir;
+ }
+
+ # Now, remove all leading components that are the same
+ my @pathchunks = $self->splitdir( $path_directories );
+ my @basechunks = $self->splitdir( $base_directories );
+
+ if ($base_directories eq $self->rootdir) {
+ shift @pathchunks;
+ return $self->canonpath( $self->catpath('', $self->catdir( @pathchunks ), '') );
+ }
+
+ while (@pathchunks && @basechunks && $self->_same($pathchunks[0], $basechunks[0])) {
+ shift @pathchunks ;
+ shift @basechunks ;
+ }
+ return $self->curdir unless @pathchunks || @basechunks;
+
+ # $base now contains the directories the resulting relative path
+ # must ascend out of before it can descend to $path_directory.
+ my $result_dirs = $self->catdir( ($self->updir) x @basechunks, @pathchunks );
+ return $self->canonpath( $self->catpath('', $result_dirs, '') );
+}
+
+sub _same {
+ $_[1] eq $_[2];
+}
+
+=item rel2abs()
+
+Converts a relative path to an absolute path.
+
+ $abs_path = File::Spec->rel2abs( $path ) ;
+ $abs_path = File::Spec->rel2abs( $path, $base ) ;
+
+If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
+relative, then it is converted to absolute form using
+L</rel2abs()>. This means that it is taken to be relative to
+L<cwd()|Cwd>.
+
+On systems that have a grammar that indicates filenames, this ignores
+the $base filename. Otherwise all path components are assumed to be
+directories.
+
+If $path is absolute, it is cleaned up and returned using L</canonpath()>.
+
+No checks against the filesystem are made. On VMS, there is
+interaction with the working environment, as logicals and
+macros are expanded.
+
+Based on code written by Shigio Yamaguchi.
+
+=cut
+
+sub rel2abs {
+ my ($self,$path,$base ) = @_;
+
+ # Clean up $path
+ if ( ! $self->file_name_is_absolute( $path ) ) {
+ # Figure out the effective $base and clean it up.
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = $self->_cwd();
+ }
+ elsif ( ! $self->file_name_is_absolute( $base ) ) {
+ $base = $self->rel2abs( $base ) ;
+ }
+ else {
+ $base = $self->canonpath( $base ) ;
+ }
+
+ # Glom them together
+ $path = $self->catdir( $base, $path ) ;
+ }
+
+ return $self->canonpath( $path ) ;
+}
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright (c) 2004 by the Perl 5 Porters. All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<File::Spec>
+
+=cut
+
+# Internal routine to File::Spec, no point in making this public since
+# it is the standard Cwd interface. Most of the platform-specific
+# File::Spec subclasses use this.
+sub _cwd {
+ require Cwd;
+ Cwd::cwd();
+}
+
+
+# Internal method to reduce xx\..\yy -> yy
+sub _collapse {
+ my($fs, $path) = @_;
+
+ my $updir = $fs->updir;
+ my $curdir = $fs->curdir;
+
+ my($vol, $dirs, $file) = $fs->splitpath($path);
+ my @dirs = $fs->splitdir($dirs);
+ pop @dirs if @dirs && $dirs[-1] eq '';
+
+ my @collapsed;
+ foreach my $dir (@dirs) {
+ if( $dir eq $updir and # if we have an updir
+ @collapsed and # and something to collapse
+ length $collapsed[-1] and # and its not the rootdir
+ $collapsed[-1] ne $updir and # nor another updir
+ $collapsed[-1] ne $curdir # nor the curdir
+ )
+ { # then
+ pop @collapsed; # collapse
+ }
+ else { # else
+ push @collapsed, $dir; # just hang onto it
+ }
+ }
+
+ return $fs->catpath($vol,
+ $fs->catdir(@collapsed),
+ $file
+ );
+}
+
+
+1;
--- /dev/null
+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 Exporter ();
+ use vars qw[ @ISA $VERSION @EXPORT_OK $VERBOSE $DEBUG
+ $USE_IPC_RUN $USE_IPC_OPEN3 $WARN
+ ];
+
+ $VERSION = '0.36';
+ $VERBOSE = 0;
+ $DEBUG = 0;
+ $WARN = 1;
+ $USE_IPC_RUN = IS_WIN32 && !IS_WIN98;
+ $USE_IPC_OPEN3 = not IS_VMS;
+
+ @ISA = qw[Exporter];
+ @EXPORT_OK = qw[can_run run];
+}
+
+require Carp;
+use Params::Check qw[check];
+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];
+
+ 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 )
+ ) {
+ print "fetched webpage successfully: $buffer\n";
+ }
+
+
+ ### in list context ###
+ my( $success, $error_code, $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, interactively if desired,
+platform independent 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 $bool = IPC::Cmd->can_use_ipc_run( [VERBOSE] )
+
+Utility function that tells you if C<IPC::Run> is available.
+If the verbose flag is passed, it will print diagnostic messages
+if C<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 1;
+}
+
+=head2 $bool = 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 works on every 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 1;
+}
+
+=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 && !IS_WIN32;
+ return;
+}
+
+
+=head1 FUNCTIONS
+
+=head2 $path = can_run( PROGRAM );
+
+C<can_run> takes but a single 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.
+
+It will return the full path to the binary you asked for if it was
+found, or C<undef> if it was not.
+
+=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;
+
+ 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}) {
+ my $abs = File::Spec->catfile($dir, $command);
+ return $abs if $abs = MM->maybe_command($abs);
+ }
+ }
+}
+
+=head2 $ok | ($ok, $err, $full_buf, $stdout_buff, $stderr_buff) = run( command => COMMAND, [verbose => BOOL, buffer => \$SCALAR] );
+
+C<run> takes 3 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 C<IPC::Run> to be installed or your system able to work with
+C<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 right above.
+
+=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 errorcode
+
+If the first element of the return value (success) was 0, then some
+error occurred. This second element is the error code the command
+you requested exited with, if available.
+
+=item full_buffer
+
+This is an arrayreference containing all the output the command
+generated.
+Note that buffers are only available if you have C<IPC::Run> installed,
+or if your system is able to work with C<IPC::Open3> -- See below).
+This element will be C<undef> if this is not the case.
+
+=item out_buffer
+
+This is an arrayreference containing all the output sent to STDOUT the
+command generated.
+Note that buffers are only available if you have C<IPC::Run> installed,
+or if your system is able to work with C<IPC::Open3> -- See below).
+This element will be C<undef> if this is not the case.
+
+=item error_buffer
+
+This is an arrayreference containing all the output sent to STDERR the
+command generated.
+Note that buffers are only available if you have C<IPC::Run> installed,
+or if your system is able to work with C<IPC::Open3> -- See below).
+This element will be C<undef> if this is not the case.
+
+=back
+
+See the C<HOW IT WORKS> Section below to see how C<IPC::Cmd> decides
+what modules or function calls to use when issuing a command.
+
+=cut
+
+sub run {
+ my %hash = @_;
+
+ ### if the user didn't provide a buffer, we'll store it here.
+ my $def_buf = '';
+
+ my($verbose,$cmd,$buffer);
+ 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' }
+ },
+ };
+
+ unless( check( $tmpl, \%hash, $VERBOSE ) ) {
+ Carp::carp(loc("Could not validate input: %1", Params::Check->last_error));
+ return;
+ };
+
+ print loc("Running [%1]...\n", (ref $cmd ? "@$cmd" : $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 = __PACKAGE__->can_capture_buffer ? 1 : 0;
+
+ ### flag indicating if the subcall went ok
+ my $ok;
+
+ ### IPC::Run is first choice if $USE_IPC_RUN is set.
+ if( $USE_IPC_RUN and __PACKAGE__->can_use_ipc_run( 1 ) ) {
+ ### ipc::run handlers needs the command as a string or an array ref
+
+ __PACKAGE__->_debug( "# Using IPC::Run. Have buffer: $have_buffer" )
+ if $DEBUG;
+
+ $ok = __PACKAGE__->_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 __PACKAGE__->can_use_ipc_open3( 1 ) ) {
+
+ __PACKAGE__->_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
+ $ok = __PACKAGE__->_open3_run(
+ ( ref $cmd ? "@$cmd" : $cmd ),
+ $_out_handler, $_err_handler, $verbose
+ );
+
+ ### if we are allowed to run verbose, just dispatch the system command
+ } else {
+ __PACKAGE__->_debug( "# Using system(). Have buffer: $have_buffer" )
+ if $DEBUG;
+ $ok = __PACKAGE__->_system_run( (ref $cmd ? "@$cmd" : $cmd), $verbose );
+ }
+
+ ### 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, $?, \@buffer, \@buff_out, \@buff_err)
+ : ($ok, $? )
+ : $ok
+
+
+}
+
+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]
+ );
+ __PACKAGE__->__dup_fds( @fds_to_dup );
+
+
+ my $pid = IPC::Open3::open3(
+ '<&STDIN',
+ (IS_WIN32 ? '>&STDOUT' : $kidout),
+ (IS_WIN32 ? '>&STDERR' : $kiderror),
+ $cmd
+ );
+
+ ### 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 epxlicit break statement
+ ### code courtesy of theorbtwo from #london.pm
+ 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;
+
+ ### child process is done printing.
+ last OUTER if $h == $kidout and $len == 0
+ }
+ }
+
+ waitpid $pid, 0; # wait for it to die
+
+ ### restore STDIN after duping, or STDIN will be closed for
+ ### this current perl process!
+ __PACKAGE__->__reopen_fds( @fds_to_dup );
+
+ return if $?; # some error occurred
+ return 1;
+}
+
+
+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;
+ if( ref $cmd ) {
+ my $aref = [];
+ for my $item (@$cmd) {
+ if( $item =~ /([<>|&])/ ) {
+ push @command, $aref, $item;
+ $aref = [];
+ $special_chars .= $1;
+ } else {
+ push @$aref, $item;
+ }
+ }
+ push @command, $aref;
+ } else {
+ @command = map { if( /([<>|&])/ ) {
+ $special_chars .= $1; $_;
+ } else {
+ [ split / +/ ]
+ }
+ } split( /\s*([<>|&])\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
+ return IPC::Run::run( @command,
+ fileno(STDOUT).'>',
+ $_out_handler,
+ fileno(STDERR).'>',
+ $_err_handler
+ );
+}
+
+sub _system_run {
+ my $self = shift;
+ my $cmd = shift;
+ my $verbose = shift || 0;
+
+ my @fds_to_dup = $verbose ? () : qw[STDOUT STDERR];
+ __PACKAGE__->__dup_fds( @fds_to_dup );
+
+ ### system returns 'true' on failure -- the exit code of the cmd
+ system( $cmd );
+
+ __PACKAGE__->__reopen_fds( @fds_to_dup );
+
+ return if $?;
+ return 1;
+}
+
+{ 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 compatibilty. 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
+ 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 compatibilty. 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;
+}
+
+
+1;
+
+
+__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 C<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 C<GLOBAL VARIABLES> Section), try to execute the command using
+C<IPC::Open3>. Buffers will be available on all platforms except C<Win32>,
+interactive commands will still execute cleanly, and also your verbosity
+settings will be adhered to nicely;
+
+=item *
+
+Otherwise, if you have the verbose argument set to true, we fall back
+to a simple 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
+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. Defaults to true if you are on C<Win32>.
+
+=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.
+
+=head1 Caveats
+
+=over 4
+
+=item Whitespace
+
+When you provide a string as this 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's extra or spurious whitespace 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.
+
+=back
+
+=head1 See Also
+
+C<IPC::Run>, C<IPC::Open3>
+
+=head1 AUTHOR
+
+This module by
+Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 ACKNOWLEDGEMENTS
+
+Thanks to James Mastros and Martijn van der Streek for their
+help in getting IPC::Open3 to behave nicely.
+
+=head1 COPYRIGHT
+
+This module is
+copyright (c) 2002 - 2006 Jos Boumans E<lt>kane@cpan.orgE<gt>.
+All rights reserved.
+
+This library is free software;
+you may redistribute and/or modify it under the same
+terms as Perl itself.
--- /dev/null
+package Locale::Maketext::Simple;
+$Locale::Maketext::Simple::VERSION = '0.18';
+
+use strict;
+use 5.004;
+
+=head1 NAME
+
+Locale::Maketext::Simple - Simple interface to Locale::Maketext::Lexicon
+
+=head1 VERSION
+
+This document describes version 0.18 of Locale::Maketext::Simple,
+released Septermber 8, 2006.
+
+=head1 SYNOPSIS
+
+Minimal setup (looks for F<auto/Foo/*.po> and F<auto/Foo/*.mo>):
+
+ package Foo;
+ use Locale::Maketext::Simple; # exports 'loc'
+ loc_lang('fr'); # set language to French
+ sub hello {
+ print loc("Hello, [_1]!", "World");
+ }
+
+More sophisticated example:
+
+ package Foo::Bar;
+ use Locale::Maketext::Simple (
+ Class => 'Foo', # search in auto/Foo/
+ Style => 'gettext', # %1 instead of [_1]
+ Export => 'maketext', # maketext() instead of loc()
+ Subclass => 'L10N', # Foo::L10N instead of Foo::I18N
+ Decode => 1, # decode entries to unicode-strings
+ Encoding => 'locale', # but encode lexicons in current locale
+ # (needs Locale::Maketext::Lexicon 0.36)
+ );
+ sub japh {
+ print maketext("Just another %1 hacker", "Perl");
+ }
+
+=head1 DESCRIPTION
+
+This module is a simple wrapper around B<Locale::Maketext::Lexicon>,
+designed to alleviate the need of creating I<Language Classes> for
+module authors.
+
+If B<Locale::Maketext::Lexicon> is not present, it implements a
+minimal localization function by simply interpolating C<[_1]> with
+the first argument, C<[_2]> with the second, etc. Interpolated
+function like C<[quant,_1]> are treated as C<[_1]>, with the sole
+exception of C<[tense,_1,X]>, which will append C<ing> to C<_1> when
+X is C<present>, or appending C<ed> to <_1> otherwise.
+
+=head1 OPTIONS
+
+All options are passed either via the C<use> statement, or via an
+explicit C<import>.
+
+=head2 Class
+
+By default, B<Locale::Maketext::Simple> draws its source from the
+calling package's F<auto/> directory; you can override this behaviour
+by explicitly specifying another package as C<Class>.
+
+=head2 Path
+
+If your PO and MO files are under a path elsewhere than C<auto/>,
+you may specify it using the C<Path> option.
+
+=head2 Style
+
+By default, this module uses the C<maketext> style of C<[_1]> and
+C<[quant,_1]> for interpolation. Alternatively, you can specify the
+C<gettext> style, which uses C<%1> and C<%quant(%1)> for interpolation.
+
+This option is case-insensitive.
+
+=head2 Export
+
+By default, this module exports a single function, C<loc>, into its
+caller's namespace. You can set it to another name, or set it to
+an empty string to disable exporting.
+
+=head2 Subclass
+
+By default, this module creates an C<::I18N> subclass under the
+caller's package (or the package specified by C<Class>), and stores
+lexicon data in its subclasses. You can assign a name other than
+C<I18N> via this option.
+
+=head2 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.
+
+=head2 Encoding
+
+Specifies an encoding to store lexicon entries, instead of
+utf8-strings. If set to C<locale>, the encoding from the current
+locale setting is used. Implies a true value for C<Decode>.
+
+=cut
+
+sub import {
+ my ($class, %args) = @_;
+
+ $args{Class} ||= caller;
+ $args{Style} ||= 'maketext';
+ $args{Export} ||= 'loc';
+ $args{Subclass} ||= 'I18N';
+
+ my ($loc, $loc_lang) = $class->load_loc(%args);
+ $loc ||= $class->default_loc(%args);
+
+ no strict 'refs';
+ *{caller(0) . "::$args{Export}"} = $loc if $args{Export};
+ *{caller(0) . "::$args{Export}_lang"} = $loc_lang || sub { 1 };
+}
+
+my %Loc;
+
+sub reload_loc { %Loc = () }
+
+sub load_loc {
+ my ($class, %args) = @_;
+
+ my $pkg = join('::', grep { defined and length } $args{Class}, $args{Subclass});
+ return $Loc{$pkg} if exists $Loc{$pkg};
+
+ eval { require Locale::Maketext::Lexicon; 1 } or return;
+ $Locale::Maketext::Lexicon::VERSION > 0.20 or return;
+ eval { require File::Spec; 1 } or return;
+
+ my $path = $args{Path} || $class->auto_path($args{Class}) or return;
+ my $pattern = File::Spec->catfile($path, '*.[pm]o');
+ my $decode = $args{Decode} || 0;
+ my $encoding = $args{Encoding} || undef;
+
+ $decode = 1 if $encoding;
+
+ $pattern =~ s{\\}{/}g; # to counter win32 paths
+
+ eval "
+ package $pkg;
+ use base 'Locale::Maketext';
+ %${pkg}::Lexicon = ( '_AUTO' => 1 );
+ Locale::Maketext::Lexicon->import({
+ 'i-default' => [ 'Auto' ],
+ '*' => [ Gettext => \$pattern ],
+ _decode => \$decode,
+ _encoding => \$encoding,
+ });
+ *tense = sub { \$_[1] . ((\$_[2] eq 'present') ? 'ing' : 'ed') }
+ unless defined &tense;
+
+ 1;
+ " or die $@;
+
+ my $lh = eval { $pkg->get_handle } or return;
+ my $style = lc($args{Style});
+ if ($style eq 'maketext') {
+ $Loc{$pkg} = sub {
+ $lh->maketext(@_)
+ };
+ }
+ elsif ($style eq 'gettext') {
+ $Loc{$pkg} = sub {
+ 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;
+ return $lh->maketext($str, @_);
+ };
+ }
+ else {
+ die "Unknown Style: $style";
+ }
+
+ return $Loc{$pkg}, sub {
+ $lh = $pkg->get_handle(@_);
+ $lh = $pkg->get_handle(@_);
+ };
+}
+
+sub default_loc {
+ my ($self, %args) = @_;
+ my $style = lc($args{Style});
+ if ($style eq 'maketext') {
+ return sub {
+ my $str = shift;
+ $str =~ s{((?<!~)(?:~~)*)\[_([1-9]\d*|\*)\]}
+ {$1%$2}g;
+ $str =~ s{((?<!~)(?:~~)*)\[([A-Za-z#*]\w*),([^\]]+)\]}
+ {"$1%$2(" . _escape($3) . ')'}eg;
+ _default_gettext($str, @_);
+ };
+ }
+ elsif ($style eq 'gettext') {
+ return \&_default_gettext;
+ }
+ else {
+ die "Unknown Style: $style";
+ }
+}
+
+sub _default_gettext {
+ my $str = shift;
+ $str =~ s{
+ % # leading symbol
+ (?: # either one of
+ \d+ # a digit, like %1
+ | # or
+ (\w+)\( # a function call -- 1
+ (?: # either
+ %\d+ # an interpolation
+ | # or
+ ([^,]*) # some string -- 2
+ ) # end either
+ (?: # maybe followed
+ , # by a comma
+ ([^),]*) # and a param -- 3
+ )? # end maybe
+ (?: # maybe followed
+ , # by another comma
+ ([^),]*) # and a param -- 4
+ )? # end maybe
+ [^)]* # and other ignorable params
+ \) # closing function call
+ ) # closing either one of
+ }{
+ my $digit = $2 || shift;
+ $digit . (
+ $1 ? (
+ ($1 eq 'tense') ? (($3 eq 'present') ? 'ing' : 'ed') :
+ ($1 eq 'quant') ? ' ' . (($digit > 1) ? ($4 || "$3s") : $3) :
+ ''
+ ) : ''
+ );
+ }egx;
+ return $str;
+};
+
+sub _escape {
+ my $text = shift;
+ $text =~ s/\b_([1-9]\d*)/%$1/g;
+ return $text;
+}
+
+sub _unescape {
+ join(',', map {
+ /\A(\s*)%([1-9]\d*|\*)(\s*)\z/ ? "$1_$2$3" : $_
+ } split(/,/, $_[0]));
+}
+
+sub auto_path {
+ my ($self, $calldir) = @_;
+ $calldir =~ s#::#/#g;
+ my $path = $INC{$calldir . '.pm'} or return;
+
+ # Try absolute path name.
+ if ($^O eq 'MacOS') {
+ (my $malldir = $calldir) =~ tr#/#:#;
+ $path =~ s#^(.*)$malldir\.pm\z#$1auto:$malldir:#s;
+ } else {
+ $path =~ s#^(.*)$calldir\.pm\z#$1auto/$calldir/#;
+ }
+
+ return $path if -d $path;
+
+ # If that failed, try relative path with normal @INC searching.
+ $path = "auto/$calldir/";
+ foreach my $inc (@INC) {
+ return "$inc/$path" if -d "$inc/$path";
+ }
+
+ return;
+}
+
+1;
+
+=head1 ACKNOWLEDGMENTS
+
+Thanks to Jos I. Boumans for suggesting this module to be written.
+
+Thanks to Chia-Liang Kao for suggesting C<Path> and C<loc_lang>.
+
+=head1 SEE ALSO
+
+L<Locale::Maketext>, L<Locale::Maketext::Lexicon>
+
+=head1 AUTHORS
+
+Audrey Tang E<lt>cpan@audreyt.orgE<gt>
+
+=head1 COPYRIGHT
+
+Copyright 2003, 2004, 2005, 2006 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
+
+This software is released under the MIT license cited below. Additionally,
+when this software is distributed with B<Perl Kit, Version 5>, you may also
+redistribute it and/or modify it under the same terms as Perl itself.
+
+=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
--- /dev/null
+package Module::Load;\r
+\r
+$VERSION = '0.10';\r
+\r
+use strict;\r
+use File::Spec ();\r
+\r
+sub import {\r
+ my $who = _who();\r
+\r
+ { no strict 'refs';\r
+ *{"${who}::load"} = *load;\r
+ }\r
+}\r
+\r
+sub load (*;@) {\r
+ my $mod = shift or return;\r
+ my $who = _who();\r
+\r
+ if( _is_file( $mod ) ) {\r
+ require $mod;\r
+ } else {\r
+ LOAD: {\r
+ my $err;\r
+ for my $flag ( qw[1 0] ) {\r
+ my $file = _to_file( $mod, $flag);\r
+ eval { require $file };\r
+ $@ ? $err .= $@ : last LOAD;\r
+ }\r
+ die $err if $err;\r
+ }\r
+ }\r
+ __PACKAGE__->_export_to_level(1, $mod, @_) if @_;\r
+}\r
+\r
+### 5.004's Exporter doesn't have export_to_level.\r
+### Taken from Michael Schwerns Test::More and slightly modified\r
+sub _export_to_level {\r
+ my $pkg = shift;\r
+ my $level = shift;\r
+ my $mod = shift;\r
+ my $callpkg = caller($level);\r
+\r
+ $mod->export($callpkg, @_);\r
+}\r
+\r
+sub _to_file{\r
+ local $_ = shift;\r
+ my $pm = shift || '';\r
+\r
+ my @parts = split /::/;\r
+\r
+ ### because of [perl #19213], see caveats ###\r
+ my $file = $^O eq 'MSWin32'\r
+ ? join "/", @parts\r
+ : File::Spec->catfile( @parts );\r
+\r
+ $file .= '.pm' if $pm;\r
+\r
+ return $file;\r
+}\r
+\r
+sub _who { (caller(1))[0] }\r
+\r
+sub _is_file {\r
+ local $_ = shift;\r
+ return /^\./ ? 1 :\r
+ /[^\w:']/ ? 1 :\r
+ undef\r
+ #' silly bbedit..\r
+}\r
+\r
+\r
+1;\r
+\r
+__END__\r
+\r
+=pod\r
+\r
+=head1 NAME\r
+\r
+Module::Load - runtime require of both modules and files\r
+\r
+=head1 SYNOPSIS\r
+\r
+ use Module::Load;\r
+\r
+ my $module = 'Data:Dumper';\r
+ load Data::Dumper; # loads that module\r
+ load 'Data::Dumper'; # ditto\r
+ load $module # tritto\r
+ \r
+ my $script = 'some/script.pl'\r
+ load $script;\r
+ load 'some/script.pl'; # use quotes because of punctuations\r
+ \r
+ load thing; # try 'thing' first, then 'thing.pm'\r
+\r
+ load CGI, ':standard' # like 'use CGI qw[:standard]'\r
+ \r
+\r
+=head1 DESCRIPTION\r
+\r
+C<load> eliminates the need to know whether you are trying to require\r
+either a file or a module.\r
+\r
+If you consult C<perldoc -f require> you will see that C<require> will\r
+behave differently when given a bareword or a string.\r
+\r
+In the case of a string, C<require> assumes you are wanting to load a\r
+file. But in the case of a bareword, it assumes you mean a module.\r
+\r
+This gives nasty overhead when you are trying to dynamically require\r
+modules at runtime, since you will need to change the module notation\r
+(C<Acme::Comment>) to a file notation fitting the particular platform\r
+you are on.\r
+\r
+C<load> elimates the need for this overhead and will just DWYM.\r
+\r
+=head1 Rules\r
+\r
+C<load> has the following rules to decide what it thinks you want:\r
+\r
+=over 4\r
+\r
+=item *\r
+\r
+If the argument has any characters in it other than those matching\r
+C<\w>, C<:> or C<'>, it must be a file\r
+\r
+=item *\r
+\r
+If the argument matches only C<[\w:']>, it must be a module\r
+\r
+=item *\r
+\r
+If the argument matches only C<\w>, it could either be a module or a\r
+file. We will try to find C<file> first in C<@INC> and if that fails,\r
+we will try to find C<file.pm> in @INC.\r
+If both fail, we die with the respective error messages.\r
+\r
+=back\r
+\r
+=head1 Caveats\r
+\r
+Because of a bug in perl (#19213), at least in version 5.6.1, we have\r
+to hardcode the path seperator for a require on Win32 to be C</>, like\r
+on Unix rather than the Win32 C<\>. Otherwise perl will not read it's\r
+own %INC accurately double load files if they are required again, or\r
+in the worst case, core dump.\r
+\r
+C<Module::Load> can not do implicit imports, only explicit imports.\r
+(in other words, you always have to specify expliclity what you wish\r
+to import from a module, even if the functions are in that modules'\r
+C<@EXPORT>)\r
+\r
+=head1 AUTHOR\r
+\r
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.\r
+\r
+Thanks to Jonas B. Nielsen for making explicit imports work.\r
+\r
+=head1 COPYRIGHT\r
+\r
+This module is\r
+copyright (c) 2002 Jos Boumans E<lt>kane@cpan.orgE<gt>.\r
+All rights reserved.\r
+\r
+This library is free software;\r
+you may redistribute and/or modify it under the same\r
+terms as Perl itself.\r
+\r
+=cut \r
--- /dev/null
+package Module::Load::Conditional;
+
+use strict;
+
+use Module::Load;
+use Params::Check qw[check];
+use Locale::Maketext::Simple Style => 'gettext';
+
+use Carp ();
+use File::Spec ();
+use FileHandle ();
+use version qw[qv];
+
+BEGIN {
+ use vars qw[ $VERSION @ISA $VERBOSE $CACHE @EXPORT_OK
+ $FIND_VERSION $ERROR $CHECK_INC_HASH];
+ use Exporter;
+ @ISA = qw[Exporter];
+ $VERSION = '0.16';
+ $VERBOSE = 0;
+ $FIND_VERSION = 1;
+ $CHECK_INC_HASH = 0;
+ @EXPORT_OK = qw[check_install can_load requires];
+}
+
+=pod
+
+=head1 NAME
+
+Module::Load::Conditional - Looking up module information / loading at runtime
+
+=head1 SYNOPSIS
+
+ use Module::Load::Conditional qw[can_load check_install requires];
+
+
+ my $use_list = {
+ CPANPLUS => 0.05,
+ LWP => 5.60,
+ 'Test::More' => undef,
+ };
+
+ print can_load( modules => $use_list )
+ ? 'all modules loaded successfully'
+ : 'failed to load required modules';
+
+
+ my $rv = check_install( module => 'LWP', version => 5.60 )
+ or print 'LWP is not installed!';
+
+ print 'LWP up to date' if $rv->{uptodate};
+ print "LWP version is $rv->{version}\n";
+ print "LWP is installed as file $rv->{file}\n";
+
+
+ print "LWP requires the following modules to be installed:\n";
+ print join "\n", requires('LWP');
+
+ ### allow M::L::C to peek in your %INC rather than just
+ ### scanning @INC
+ $Module::Load::Conditional::CHECK_INC_HASH = 1;
+
+ ### reset the 'can_load' cache
+ undef $Module::Load::Conditional::CACHE;
+
+ ### don't have Module::Load::Conditional issue warnings --
+ ### default is '1'
+ $Module::Load::Conditional::VERBOSE = 0;
+
+ ### The last error that happened during a call to 'can_load'
+ my $err = $Module::Load::Conditional::ERROR;
+
+
+=head1 DESCRIPTION
+
+Module::Load::Conditional provides simple ways to query and possibly load any of
+the modules you have installed on your system during runtime.
+
+It is able to load multiple modules at once or none at all if one of
+them was not able to load. It also takes care of any error checking
+and so forth.
+
+=head1 Methods
+
+=head1 $href = check_install( module => NAME [, version => VERSION, verbose => BOOL ] );
+
+C<check_install> allows you to verify if a certain module is installed
+or not. You may call it with the following arguments:
+
+=over 4
+
+=item module
+
+The name of the module you wish to verify -- this is a required key
+
+=item version
+
+The version this module needs to be -- this is optional
+
+=item verbose
+
+Whether or not to be verbose about what it is doing -- it will default
+to $Module::Load::Conditional::VERBOSE
+
+=back
+
+It will return undef if it was not able to find where the module was
+installed, or a hash reference with the following keys if it was able
+to find the file:
+
+=over 4
+
+=item file
+
+Full path to the file that contains the module
+
+=item version
+
+The version number of the installed module - this will be C<undef> if
+the module had no (or unparsable) version number, or if the variable
+C<$Module::Load::Conditional::FIND_VERSION> was set to true.
+(See the C<GLOBAL VARIABLES> section below for details)
+
+=item uptodate
+
+A boolean value indicating whether or not the module was found to be
+at least the version you specified. If you did not specify a version,
+uptodate will always be true if the module was found.
+If no parsable version was found in the module, uptodate will also be
+true, since C<check_install> had no way to verify clearly.
+
+=back
+
+=cut
+
+### this checks if a certain module is installed already ###
+### if it returns true, the module in question is already installed
+### or we found the file, but couldn't open it, OR there was no version
+### to be found in the module
+### it will return 0 if the version in the module is LOWER then the one
+### we are looking for, or if we couldn't find the desired module to begin with
+### if the installed version is higher or equal to the one we want, it will return
+### a hashref with he module name and version in it.. so 'true' as well.
+sub check_install {
+ my %hash = @_;
+
+ my $tmpl = {
+ version => { default => '0.0' },
+ module => { required => 1 },
+ verbose => { default => $VERBOSE },
+ };
+
+ my $args;
+ unless( $args = check( $tmpl, \%hash, $VERBOSE ) ) {
+ warn loc( q[A problem occurred checking arguments] ) if $VERBOSE;
+ return;
+ }
+
+ my $file = File::Spec->catfile( split /::/, $args->{module} ) . '.pm';
+ my $file_inc = File::Spec::Unix->catfile(
+ split /::/, $args->{module}
+ ) . '.pm';
+
+ ### where we store the return value ###
+ my $href = {
+ file => undef,
+ version => undef,
+ uptodate => undef,
+ };
+
+ my $filename;
+
+ ### check the inc hash if we're allowed to
+ if( $CHECK_INC_HASH ) {
+ $filename = $href->{'file'} =
+ $INC{ $file_inc } if defined $INC{ $file_inc };
+
+ ### find the version by inspecting the package
+ if( defined $filename && $FIND_VERSION ) {
+ no strict 'refs';
+ $href->{version} = ${ "$args->{module}"."::VERSION" };
+ }
+ }
+
+ ### we didnt find the filename yet by looking in %INC,
+ ### so scan the dirs
+ unless( $filename ) {
+
+ DIR: for my $dir ( @INC ) {
+
+ my $fh;
+
+ if ( ref $dir ) {
+ ### @INC hook -- we invoke it and get the filehandle back
+ ### this is actually documented behaviour as of 5.8 ;)
+
+ if (UNIVERSAL::isa($dir, 'CODE')) {
+ ($fh) = $dir->($dir, $file);
+
+ } elsif (UNIVERSAL::isa($dir, 'ARRAY')) {
+ ($fh) = $dir->[0]->($dir, $file, @{$dir}{1..$#{$dir}})
+
+ } elsif (UNIVERSAL::can($dir, 'INC')) {
+ ($fh) = $dir->INC->($dir, $file);
+ }
+
+ if (!UNIVERSAL::isa($fh, 'GLOB')) {
+ warn loc(q[Cannot open file '%1': %2], $file, $!)
+ if $args->{verbose};
+ next;
+ }
+
+ $filename = $INC{$file_inc} || $file;
+
+ } else {
+ $filename = File::Spec->catfile($dir, $file);
+ next unless -e $filename;
+
+ $fh = new FileHandle;
+ if (!$fh->open($filename)) {
+ warn loc(q[Cannot open file '%1': %2], $file, $!)
+ if $args->{verbose};
+ next;
+ }
+ }
+
+ $href->{file} = $filename;
+
+ ### user wants us to find the version from files
+ if( $FIND_VERSION ) {
+
+ my $in_pod = 0;
+ while (local $_ = <$fh> ) {
+
+ ### stolen from EU::MM_Unix->parse_version to address
+ ### #24062: "Problem with CPANPLUS 0.076 misidentifying
+ ### versions after installing Text::NSP 1.03" where a
+ ### VERSION mentioned in the POD was found before
+ ### the real $VERSION declaration.
+ $in_pod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $in_pod;
+ next if $in_pod;
+
+ ### try to find a version declaration in this string.
+ my $ver = __PACKAGE__->_parse_version( $_ );
+
+ if( defined $ver ) {
+ $href->{version} = $ver;
+
+ last DIR;
+ }
+ }
+ }
+ }
+ }
+
+ ### if we couldn't find the file, return undef ###
+ return unless defined $href->{file};
+
+ ### only complain if we expected fo find a version higher than 0.0 anyway
+ if( $FIND_VERSION and not defined $href->{version} ) {
+ { ### don't warn about the 'not numeric' stuff ###
+ local $^W;
+
+ ### if we got here, we didn't find the version
+ warn loc(q[Could not check version on '%1'], $args->{module} )
+ if $args->{verbose} and $args->{version} > 0;
+ }
+ $href->{uptodate} = 1;
+
+ } else {
+ ### don't warn about the 'not numeric' stuff ###
+ local $^W;
+ $href->{uptodate} = $args->{version} <= $href->{version} ? 1 : 0;
+ }
+
+ return $href;
+}
+
+sub _parse_version {
+ my $self = shift;
+ my $str = shift or return;
+ my $verbose = shift or 0;
+
+ ### skip commented out lines, they won't eval to anything.
+ return if $str =~ /^\s*#/;
+
+ ### the following regexp & eval statement comes from the
+ ### ExtUtils::MakeMaker source (EU::MM_Unix->parse_version)
+ ### Following #18892, which tells us the original
+ ### regex breaks under -T, we must modifiy it so
+ ### it captures the entire expression, and eval /that/
+ ### rather than $_, which is insecure.
+
+ if( $str =~ /(?<!\\)([\$*])(([\w\:\']*)\bVERSION)\b.*\=/ ) {
+
+ print "Evaluating: $str\n" if $verbose;
+
+ ### this creates a string to be eval'd, like:
+ # package Module::Load::Conditional::_version;
+ # no strict;
+ #
+ # local $VERSION;
+ # $VERSION=undef; do {
+ # use version; $VERSION = qv('0.0.3');
+ # }; $VERSION
+
+ my $eval = qq{
+ package Module::Load::Conditional::_version;
+ no strict;
+
+ local $1$2;
+ \$$2=undef; do {
+ $str
+ }; \$$2
+ };
+
+ print "Evaltext: $eval\n" if $verbose;
+
+ my $result = do {
+ local $^W = 0;
+ eval($eval);
+ };
+
+
+ my $rv = defined $result ? $result : '0.0';
+
+ print( $@ ? "Error: $@\n" : "Result: $rv\n" ) if $verbose;
+
+ return $rv;
+ }
+
+ ### unable to find a version in this string
+ return;
+}
+
+=head2 $bool = can_load( modules => { NAME => VERSION [,NAME => VERSION] }, [verbose => BOOL, nocache => BOOL] )
+
+C<can_load> will take a list of modules, optionally with version
+numbers and determine if it is able to load them. If it can load *ALL*
+of them, it will. If one or more are unloadable, none will be loaded.
+
+This is particularly useful if you have More Than One Way (tm) to
+solve a problem in a program, and only wish to continue down a path
+if all modules could be loaded, and not load them if they couldn't.
+
+This function uses the C<load> function from Module::Load under the
+hood.
+
+C<can_load> takes the following arguments:
+
+=over 4
+
+=item modules
+
+This is a hashref of module/version pairs. The version indicates the
+minimum version to load. If no version is provided, any version is
+assumed to be good enough.
+
+=item verbose
+
+This controls whether warnings should be printed if a module failed
+to load.
+The default is to use the value of $Module::Load::Conditional::VERBOSE.
+
+=item nocache
+
+C<can_load> keeps its results in a cache, so it will not load the
+same module twice, nor will it attempt to load a module that has
+already failed to load before. By default, C<can_load> will check its
+cache, but you can override that by setting C<nocache> to true.
+
+=cut
+
+sub can_load {
+ my %hash = @_;
+
+ my $tmpl = {
+ modules => { default => {}, strict_type => 1 },
+ verbose => { default => $VERBOSE },
+ nocache => { default => 0 },
+ };
+
+ my $args;
+
+ unless( $args = check( $tmpl, \%hash, $VERBOSE ) ) {
+ $ERROR = loc(q[Problem validating arguments!]);
+ warn $ERROR if $VERBOSE;
+ return;
+ }
+
+ ### layout of $CACHE:
+ ### $CACHE = {
+ ### $ module => {
+ ### usable => BOOL,
+ ### version => \d,
+ ### file => /path/to/file,
+ ### },
+ ### };
+
+ $CACHE ||= {}; # in case it was undef'd
+
+ my $error;
+ BLOCK: {
+ my $href = $args->{modules};
+
+ my @load;
+ for my $mod ( keys %$href ) {
+
+ next if $CACHE->{$mod}->{usable} && !$args->{nocache};
+
+ ### else, check if the hash key is defined already,
+ ### meaning $mod => 0,
+ ### indicating UNSUCCESSFUL prior attempt of usage
+ if ( !$args->{nocache}
+ && defined $CACHE->{$mod}->{usable}
+ && (($CACHE->{$mod}->{version}||0) >= $href->{$mod})
+ ) {
+ $error = loc( q[Already tried to use '%1', which was unsuccessful], $mod);
+ last BLOCK;
+ }
+
+ my $mod_data = check_install(
+ module => $mod,
+ version => $href->{$mod}
+ );
+
+ if( !$mod_data or !defined $mod_data->{file} ) {
+ $error = loc(q[Could not find or check module '%1'], $mod);
+ $CACHE->{$mod}->{usable} = 0;
+ last BLOCK;
+ }
+
+ map {
+ $CACHE->{$mod}->{$_} = $mod_data->{$_}
+ } qw[version file uptodate];
+
+ push @load, $mod;
+ }
+
+ for my $mod ( @load ) {
+
+ if ( $CACHE->{$mod}->{uptodate} ) {
+
+ eval { load $mod };
+
+ ### in case anything goes wrong, log the error, the fact
+ ### we tried to use this module and return 0;
+ if( $@ ) {
+ $error = $@;
+ $CACHE->{$mod}->{usable} = 0;
+ last BLOCK;
+ } else {
+ $CACHE->{$mod}->{usable} = 1;
+ }
+
+ ### module not found in @INC, store the result in
+ ### $CACHE and return 0
+ } else {
+
+ $error = loc(q[Module '%1' is not uptodate!], $mod);
+ $CACHE->{$mod}->{usable} = 0;
+ last BLOCK;
+ }
+ }
+
+ } # BLOCK
+
+ if( defined $error ) {
+ $ERROR = $error;
+ Carp::carp( loc(q|%1 [THIS MAY BE A PROBLEM!]|,$error) ) if $args->{verbose};
+ return undef;
+ } else {
+ return 1;
+ }
+}
+
+=head2 @list = requires( MODULE );
+
+C<requires> can tell you what other modules a particular module
+requires. This is particularly useful when you're intending to write
+a module for public release and are listing its prerequisites.
+
+C<requires> takes but one argument: the name of a module.
+It will then first check if it can actually load this module, and
+return undef if it can't.
+Otherwise, it will return a list of modules and pragmas that would
+have been loaded on the module's behalf.
+
+Note: The list C<require> returns has originated from your current
+perl and your current install.
+
+=cut
+
+sub requires {
+ my $who = shift;
+
+ unless( check_install( module => $who ) ) {
+ warn loc(q[You do not have module '%1' installed], $who) if $VERBOSE;
+ return undef;
+ }
+
+ my $lib = join " ", map { qq["-I$_"] } @INC;
+ my $cmd = qq[$^X $lib -M$who -e"print(join(qq[\\n],keys(%INC)))"];
+
+ return sort
+ grep { !/^$who$/ }
+ map { chomp; s|/|::|g; $_ }
+ grep { s|\.pm$||i; }
+ `$cmd`;
+}
+
+1;
+
+__END__
+
+=head1 Global Variables
+
+The behaviour of Module::Load::Conditional can be altered by changing the
+following global variables:
+
+=head2 $Module::Load::Conditional::VERBOSE
+
+This controls whether Module::Load::Conditional will issue warnings and
+explanations as to why certain things may have failed. If you set it
+to 0, Module::Load::Conditional will not output any warnings.
+The default is 0;
+
+=head2 $Module::Load::Conditional::FIND_VERSION
+
+This controls whether Module::Load::Conditional will try to parse
+(and eval) the version from the module you're trying to load.
+
+If you don't wish to do this, set this variable to C<false>. Understand
+then that version comparisons are not possible, and Module::Load::Conditional
+can not tell you what module version you have installed.
+This may be desirable from a security or performance point of view.
+Note that C<$FIND_VERSION> code runs safely under C<taint mode>.
+
+The default is 1;
+
+=head2 $Module::Load::Conditional::CHECK_INC_HASH
+
+This controls whether C<Module::Load::Conditional> checks your
+C<%INC> hash to see if a module is available. By default, only
+C<@INC> is scanned to see if a module is physically on your
+filesystem, or avialable via an C<@INC-hook>. Setting this variable
+to C<true> will trust any entries in C<%INC> and return them for
+you.
+
+The default is 0;
+
+=head2 $Module::Load::Conditional::CACHE
+
+This holds the cache of the C<can_load> function. If you explicitly
+want to remove the current cache, you can set this variable to
+C<undef>
+
+=head2 $Module::Load::Conditional::ERROR
+
+This holds a string of the last error that happened during a call to
+C<can_load>. It is useful to inspect this when C<can_load> returns
+C<undef>.
+
+=head1 See Also
+
+C<Module::Load>
+
+=head1 AUTHOR
+
+This module by
+Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+This module is copyright (c) 2002-2007 Jos Boumans
+E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify
+it under the same terms as Perl itself.
--- /dev/null
+package My::Build;
+
+use strict;
+use base qw(Module::Build);
+use Config;
+use File::Spec;
+
+our @ISA;
+$main::NO_INIT = $main::NO_INIT; # no warnings...
+
+sub awx_get_package {
+ local $_ = $Config{osname};
+
+ # Win32
+ /MSWin32/ and return 'Win32';
+ # MacOS X is slightly different...
+ /darwin/ and return 'MacOSX_wx_config';
+ # default
+ return 'Any_wx_config';
+}
+
+BEGIN {
+ my $package = 'My::Build';
+
+ # iterate until fixed point
+ for( ; !$main::NO_INIT; ) {
+ my $full_package = 'My::Build::' . $package->awx_get_package;
+ last if $package eq $full_package;
+
+ my $file = $full_package . '.pm'; $file =~ s{::}{/}g;
+
+ require $file;
+ @ISA = ( $full_package );
+ $package = $full_package;
+ }
+}
+
+1;
--- /dev/null
+package My::Build::Any_wx_config;
+
+use strict;
+use base qw(My::Build::Any_wx_config_Bakefile);
+use My::Build::Utility qw(awx_arch_dir awx_install_arch_dir);
+
+our $WX_CONFIG_LIBSEP;
+our @LIBRARIES = qw(base net xml adv animate aui core fl gizmos
+ gl html media qa richtext stc xrc);
+our @MONO_LIBRARIES_2_9 = qw(core gl);
+our @MONO_LIBRARIES_2_8 = qw(core stc gl);
+our @CONTRIB_LIBRARIES = qw(gizmos_xrc ogl plot svg);
+our @CRITICAL = qw(base core);
+our @IMPORTANT = qw(net xml adv aui gl html media richtext stc xrc);
+
+my $initialized;
+my( $wx_debug, $wx_unicode, $wx_monolithic );
+
+sub _find {
+ my( $name ) = @_;
+
+ return $name if File::Spec->file_name_is_absolute( $name );
+ foreach my $dir ( File::Spec->path ) {
+ my $abs = File::Spec->catfile( $dir, $name );
+ return $abs if -x $abs;
+ }
+
+ return $name;
+}
+
+sub _init {
+ my $build = shift;
+
+ return if $initialized;
+ $initialized = 1;
+
+ lib->import( qw(lib inc) );
+
+ my $wx_config = ( $build && $build->notes( 'wx_config' ) )
+ || $ENV{WX_CONFIG} || 'wx-config';
+ my $ver = `$wx_config --version` or die "Can't execute '$wx_config': $!";
+
+ $build->notes( 'wx_config' => _find( $wx_config ) )
+ if $build && !$build->notes( 'wx_config' );
+ $ver = __PACKAGE__->_version_2_dec( $ver );
+
+ my $base = `$wx_config --basename`;
+ $wx_debug = $base =~ m/d$/ ? 1 : 0;
+ $wx_unicode = $base =~ m/ud?$/ ? 1 : 0;
+
+ $WX_CONFIG_LIBSEP = `$wx_config --libs base > /dev/null 2>&1 || echo 'X'` eq "X\n" ? '=' : ' ';
+ $wx_monolithic = `$wx_config --libs${WX_CONFIG_LIBSEP}adv` eq
+ `$wx_config --libs${WX_CONFIG_LIBSEP}core`;
+
+ sub awx_is_debug {
+ $_[0]->notes( 'build_wx' )
+ ? $_[0]->SUPER::awx_is_debug
+ : $wx_debug;
+ }
+ sub awx_is_unicode {
+ $_[0]->notes( 'build_wx' )
+ ? $_[0]->SUPER::awx_is_unicode
+ : $wx_unicode;
+ }
+ sub awx_is_monolithic {
+ $_[0]->notes( 'build_wx' )
+ ? $_[0]->SUPER::awx_is_monolithic
+ : $wx_monolithic;
+ }
+}
+
+package My::Build::Any_wx_config::Base;
+
+use strict;
+use base qw(My::Build::Base);
+use Fatal qw(chdir mkdir);
+use Cwd ();
+use Config;
+use My::Build::Utility qw(awx_arch_dir awx_install_arch_dir);
+
+sub awx_configure {
+ My::Build::Any_wx_config::_init( $_[0] );
+
+ my $self = shift;
+ my %config = $self->SUPER::awx_configure;
+ my $cf = $self->wx_config( 'cxxflags' );
+
+ $config{prefix} = $self->wx_config( 'prefix' );
+ $cf =~ m/__WX(x11|msw|motif|gtk|mac|osx_carbon|osx_cocoa)__/i or
+ die "Unable to determine toolkit!";
+ $config{config}{toolkit} = lc $1;
+ $config{config}{build} = $self->awx_is_monolithic ? 'mono' : 'multi';
+
+ if( $config{config}{toolkit} eq 'gtk' ) {
+ $self->wx_config( 'basename' ) =~ m/(gtk2?)/i or
+ die 'PANIC: ', $self->wx_config( 'basename' );
+ $config{config}{toolkit} = lc $1;
+ }
+
+ $config{compiler} = $ENV{CXX} || $self->wx_config( 'cxx' );
+ if( $self->awx_debug ) {
+ $config{c_flags} .= ' -g ';
+ }
+
+ my $cccflags = $self->wx_config( 'cxxflags' );
+ my $libs = $self->wx_config( 'libs' );
+
+ foreach ( split /\s+/, $cccflags ) {
+ m(^[-/]I) && do { $config{include_path} .= "$_ "; next; };
+ m(^[-/]D) && do { $config{defines} .= "$_ "; next; };
+ $config{c_flags} .= "$_ ";
+ }
+
+ my @paths = ( ( map { s/^-L//; $_ } grep { /^-L/ } split ' ', $libs ),
+ qw(/usr/local/lib /usr/lib /usr/lib64) );
+
+ foreach ( split /\s+/, $libs ) {
+ m{^-[lL]|/} && do { $config{link_libraries} .= " $_"; next; };
+ if( $_ eq '-pthread' && $^O =~ m/(?:linux|freebsd)/i ) {
+ $config{link_libraries} .= " -lpthread";
+ next;
+ }
+ $config{link_libraries} .= " $_";
+ }
+
+ my %dlls = %{$self->wx_config( 'dlls' )};
+ $config{_libraries} = {};
+
+ while( my( $k, $v ) = each %dlls ) {
+ if( @paths ) {
+ my $found = 0;
+ foreach my $path ( @paths ) {
+ $found = 1 if -f File::Spec->catfile( $path, $v->{dll} );
+ }
+ unless( $found || $self->notes( 'build_wx' ) ) {
+ if( grep $_ eq $k, @My::Build::Any_wx_config::CRITICAL ) {
+ warn "'$k' library not found: can't use wxWidgets\n";
+ } elsif( grep $_ eq $k, @My::Build::Any_wx_config::IMPORTANT ) {
+ warn "'$k' library not found: some functionality will be missing\n";
+ }
+ next;
+ }
+ }
+
+ $config{_libraries}{$k} = $v;
+ }
+
+ return %config;
+}
+
+sub _call_wx_config {
+ My::Build::Any_wx_config::_init( $_[0] );
+
+ my $self = shift;
+ my $options = join ' ', map { "--$_" } @_;
+ my $wx_config = $self->notes( 'wx_config' )
+ || $ENV{WX_CONFIG} || 'wx-config';
+
+ # not completely correct, but close
+ $options = "--static $options" if $self->awx_static;
+
+ my $t = qx($wx_config $options);
+ chomp $t;
+
+ return $t;
+}
+
+sub awx_compiler_kind {
+ My::Build::Any_wx_config::_init( $_[0] );
+
+ return Alien::wxWidgets::Utility::awx_compiler_kind( $_[1] )
+}
+
+sub awx_dlext { $Config{dlext} }
+
+sub _key {
+ my $self = shift;
+ my $compiler = $ENV{CXX} || $Config{ccname} || $Config{cc};
+ my $key = $self->awx_get_name
+ ( toolkit => $self->awx_build_toolkit,
+ version => $self->_version_2_dec
+ ( $self->notes( 'build_data' )->{data}{version} ),
+ debug => $self->awx_is_debug,
+ unicode => $self->awx_is_unicode,
+ mslu => $self->awx_is_mslu,
+ # it is unlikely it will ever be required under *nix
+ $self->notes( 'build_wx' ) ? () :
+ ( compiler => $self->awx_compiler_kind( $compiler ),
+ compiler_version => $self->awx_compiler_version( $compiler )
+ ),
+ );
+
+ return $key;
+}
+
+sub wxwidgets_configure_extra_flags { '' }
+
+sub awx_make {
+ my( $self ) = @_;
+ my $make = 'make';
+ if( $^O eq 'solaris' ) {
+ $make = $self->awx_path_search( 'gmake' );
+ die "GNU make required under Solaris"
+ unless $make;
+ }
+
+ return $make;
+}
+
+sub build_wxwidgets {
+ my $self = shift;
+
+ my $extra_flags = $self->wxwidgets_configure_extra_flags;
+ my $prefix_dir = $self->_key;
+ my $prefix = awx_install_arch_dir( $self, $prefix_dir );
+ my $opengl = $self->notes( 'build_wx_opengl' );
+ my $args = sprintf '--with-%s %s--disable-compat24',
+ $self->awx_build_toolkit,
+ $opengl ? '--with-opengl ' : '';
+ my $unicode = $self->awx_is_unicode ? 'enable' : 'disable';
+ my $debug = $self->awx_is_debug ? 'enable' : 'disable';
+ my $monolithic = $self->awx_is_monolithic ? 'enable' : 'disable';
+ my $universal = $self->awx_is_universal ? 'enable' : 'disable';
+ my $dir = $self->notes( 'build_data' )->{data}{directory};
+ my $cmd = "echo exit | " . # for OS X 10.3...
+ "sh ../configure --prefix=$prefix $args --$unicode-unicode"
+ . " --$debug-debug --$monolithic-monolithic"
+ . " --$universal-universal_binary $extra_flags";
+ my $old_dir = Cwd::cwd;
+
+ chdir $dir;
+
+ # do not reconfigure unless necessary
+ mkdir 'bld' unless -d 'bld';
+ chdir 'bld';
+ # print $cmd, "\n";
+ $self->_system( $cmd ) unless -f 'Makefile';
+ my $make = $self->awx_make;
+ $self->_system( "$make all" );
+ if( $self->notes( 'build_data' )->{data}{version} !~ /^2.9/ ) {
+ chdir 'contrib/src/stc';
+ $self->_system( "$make all" );
+ }
+
+ chdir $old_dir;
+}
+
+sub massage_environment {
+ my( $self ) = shift;
+
+ if( $self->notes( 'build_wx' ) ) {
+ my $wxc = File::Spec->rel2abs
+ ( File::Spec->catfile
+ ( $self->notes( 'build_data' )->{data}{directory},
+ 'bld', 'wx-config' ) );
+ # find the real and non-inplace wx-config
+ while( -l $wxc ) {
+ my $to = readlink $wxc;
+ my( $vol, $dir, $file ) = File::Spec->splitpath( $wxc );
+ $wxc = File::Spec->catfile( $dir, $to );
+ }
+ $wxc =~ s{/inplace-([^/]+)$}{/$1};
+ $ENV{WX_CONFIG} = $wxc;
+ }
+}
+
+sub install_wxwidgets { }
+
+sub install_system_wxwidgets {
+ my( $self ) = shift;
+
+ return unless $self->notes( 'build_wx' );
+
+ my $dir = $self->notes( 'build_data' )->{data}{directory};
+ my $old_dir = Cwd::cwd;
+ my $destdir = $self->destdir ? ' DESTDIR=' . $self->destdir : '';
+
+ chdir $dir;
+
+ chdir 'bld';
+ my $make = $self->awx_make;
+ $self->_system( "$make install" . $destdir );
+ if( $self->notes( 'build_data' )->{data}{version} !~ /^2.9/ ) {
+ chdir 'contrib/src/stc';
+ $self->_system( "$make install" . $destdir );
+ }
+
+ chdir $old_dir;
+}
+
+sub awx_build_toolkit { 'gtk' }
+
+1;
--- /dev/null
+package My::Build::Any_wx_config_Bakefile;
+
+use strict;
+our @ISA = qw(My::Build::Any_wx_config::Base);
+use Config;
+
+sub awx_wx_config_data {
+ my $self = shift;
+ return $self->{awx_data} if $self->{awx_data};
+
+ my %data;
+
+ foreach my $item ( qw(cxx ld cxxflags version libs basename prefix) ) {
+ $data{$item} = $self->_call_wx_config( $item );
+ }
+ $data{ld} =~ s/\-o\s*$/ /; # wxWidgets puts 'ld -o' into LD
+ $data{libs} =~ s/\-lwx\S+//g;
+
+ my @mono_libs = $self->_version_2_dec( $data{version} ) >= 2.009 ?
+ @My::Build::Any_wx_config::MONO_LIBRARIES_2_9 :
+ @My::Build::Any_wx_config::MONO_LIBRARIES_2_8;
+ my $arg = 'libs' . $My::Build::Any_wx_config::WX_CONFIG_LIBSEP .
+ join ',', grep { !m/base/ }
+ ( $self->awx_is_monolithic ?
+ @mono_libs :
+ @My::Build::Any_wx_config::LIBRARIES );
+ my $libraries = $self->_call_wx_config( $arg );
+
+ my( $libname_re, $libsuffix );
+ if( $^O eq 'openbsd' ) {
+ $libname_re = '-l(.*_(\w+))';
+ $libsuffix = '.1.0';
+ } else {
+ $libname_re = '-l(.*_(\w+)-.*)';
+ $libsuffix = '';
+ }
+ foreach my $lib ( grep { m/\-lwx/ } split ' ', $libraries ) {
+ $lib =~ m/$libname_re/ or die $lib;
+ my( $key, $name ) = ( $2, $1 );
+ $key = 'base' if $key =~ m/^base[ud]{0,2}/;
+ $key = 'base' if $key =~ m/^carbon|^cocoa/ && $name !~ /osx_/; # here for Mac
+ $key = 'core' if $key =~ m/^carbon|^cocoa/ && $name =~ /osx_/; # here for Mac
+ $key = 'core' if $key =~ m/^mac[ud]{0,2}/;
+ $key = 'core' if $key =~ m/^gtk2?[ud]{0,2}/
+ && $self->awx_is_monolithic
+ && $lib =~ m/(?:gtk2?|mac)[ud]{0,2}-/;
+ my $dll = "lib${name}." . $self->awx_dlext . $libsuffix;
+
+ $data{dlls}{$key} = { dll => $dll,
+ link => $lib };
+ }
+ if( $self->awx_is_monolithic ) {
+ $data{dlls}{mono} = delete $data{dlls}{core};
+ }
+
+ $self->{awx_data} = \%data;
+}
+
+1;
--- /dev/null
+package My::Build::Base;
+
+use strict;
+use base qw(Module::Build);
+use My::Build::Utility qw(awx_arch_file awx_touch);
+use Alien::wxWidgets::Utility qw(awx_sort_config awx_grep_config);
+use File::Path ();
+use File::Basename ();
+use Fatal qw(open close unlink);
+use Data::Dumper;
+use File::Glob qw(bsd_glob);
+
+sub ACTION_build {
+ my $self = shift;
+ # try to make "perl Makefile.PL && make test" work
+ # but avoid doubly building wxWidgets when doing
+ # "perl Makefile.PL && make && make test"
+ unlink 'configured' if -f 'configured';
+ $self->SUPER::ACTION_build;
+}
+
+sub ACTION_code {
+ my $self = shift;
+
+ $self->SUPER::ACTION_code;
+ # install_only is set when a wxWidgets build is already configured
+ # with Alien::wxWidgets
+ return if $self->notes( 'install_only' );
+ # see comment in ACTION_build for why 'configured' is used
+ return if -f 'configured';
+ $self->depends_on( 'build_wx' );
+ $self->create_config_file( awx_arch_file( 'Config/Config.pm' ) );
+ $self->install_wxwidgets;
+ # see comment in ACTION_build for why 'configured' is used
+ awx_touch( 'configured' );
+ $self->add_to_cleanup( 'configured' );
+}
+
+sub ACTION_build_wx {
+ my $self = shift;
+
+ if( $self->notes( 'build_wx' ) ) {
+ $self->fetch_wxwidgets;
+ $self->extract_wxwidgets;
+ $self->massage_environment;
+ $self->build_wxwidgets;
+ $self->massage_environment; # twice on purpose
+ }
+}
+
+sub ACTION_build_perl {
+ my $self = shift;
+
+ $self->SUPER::ACTION_build;
+ $self->massage_environment;
+ $self->create_config_file( awx_arch_file( 'Config/Config.pm' ) );
+}
+
+sub ACTION_install_wx {
+ my $self = shift;
+
+ $self->depends_on( 'build_perl' );
+ $self->install_wxwidgets;
+}
+
+sub ACTION_install {
+ my $self = shift;
+
+ $self->SUPER::ACTION_install;
+ $self->install_system_wxwidgets;
+}
+
+sub ACTION_distcheck {
+ my $self = shift;
+ my $data = $self->notes( 'build_data' );
+
+ foreach my $p ( qw(msw mac unix) ) {
+ next unless exists $data->{$p};
+
+ foreach my $c ( qw(unicode ansi) ) {
+ next unless exists $data->{$p}{$c};
+
+ foreach my $f ( @{$data->{$p}{$c}} ) {
+ my $file = File::Spec->catfile( 'patches', $f );
+
+ warn 'Missing patch file: ', $file, "\n" unless -f $file;
+ }
+ }
+ }
+
+ $self->SUPER::ACTION_distcheck;
+}
+
+sub awx_key {
+ my( $self ) = @_;
+
+ die unless $self->{awx_key};
+
+ return $self->{awx_key};
+}
+
+sub _version_2_dec {
+ my( $class, $ver ) = @_;
+ my $dec;
+
+ $ver =~ m/^(\d)(\d)$/ and
+ $dec = $1 + $2 / 1000;
+ $ver =~ m/^(\d)(\d)(\d+)$/ and
+ $dec = $1 + $2 / 1000 + $3 / 1000000;
+ $ver =~ m/^(\d)(\d+)_(\d+)$/ and
+ $dec = $1 + $2 / 1000 + $3 / 1000000;
+ $ver =~ m/^(\d+)\.(\d+)\.(\d+)$/ and
+ $dec = $1 + $2 / 1000 + $3 / 1000000;
+
+ return sprintf( "%.6f", $dec );
+}
+
+sub _init_config {
+ my( $self ) = @_;
+ my %config = $self->awx_configure;
+ my $ver = $self->awx_wx_config_data->{version};
+
+ $self->{awx_config} = \%config;
+
+ $config{version} = $self->_version_2_dec( $ver );
+
+ $config{compiler} = $ENV{CXX} || $self->awx_wx_config_data->{cxx};
+ $config{linker} = $self->awx_wx_config_data->{ld};
+ $config{config}{compiler_kind} = $self->notes( 'compiler_kind' ) ||
+ $self->awx_compiler_kind( $config{compiler} );
+ $config{config}{compiler_version} = $self->notes( 'compiler_version' ) ||
+ $self->awx_compiler_version( $config{compiler} );
+ $self->notes( 'compiler_kind' => $config{config}{compiler_kind} );
+ $self->notes( 'compiler_version' => $config{config}{compiler_version} );
+
+ my $base = $self->awx_get_name
+ ( toolkit => $config{config}{toolkit},
+ version => $config{version},
+ debug => $self->awx_is_debug,
+ unicode => $self->awx_is_unicode,
+ mslu => $self->awx_is_mslu,
+ compiler => $config{config}{compiler_kind},
+ compiler_version => $config{config}{compiler_version},
+ );
+
+ $self->{awx_key} = $base;
+
+ $config{wx_base_directory} = $self->awx_wx_config_data->{wxdir}
+ if $self->awx_wx_config_data->{wxdir};
+ $config{alien_base} = $self->{awx_base} = $base;
+ $config{alien_package} = "Alien::wxWidgets::Config::${base}";
+
+ return %config;
+}
+
+sub create_config_file {
+ my( $self, $file ) = @_;
+
+ my $directory = File::Basename::dirname( $file );
+ my %config = $self->_init_config;
+ my $base = $self->awx_key;
+
+ my $body = Data::Dumper->Dump( [ \%config ] );
+ $body =~ s/rEpLaCe/$base/g;
+
+ File::Path::mkpath( $directory ) or die "mkpath '$directory': $!"
+ unless -d $directory;
+ open my $fh, '> ' . File::Spec->catfile( $directory, $base . '.pm' );
+
+ print $fh <<"EOT";
+package $config{alien_package};
+
+EOT
+
+ print $fh <<'EOT';
+use strict;
+
+our %VALUES;
+
+{
+ no strict 'vars';
+ %VALUES = %{
+EOT
+
+ print $fh $body ;
+
+ print $fh <<'EOT';
+ };
+}
+
+my $key = substr __PACKAGE__, 1 + rindex __PACKAGE__, ':';
+EOT
+
+ print $fh <<'EOT' if $self->notes( 'mk_portable' ) && ( $^O =~ /^MSWin/ );
+
+my ($portablebase);
+my $wxwidgetspath = __PACKAGE__ . '.pm';
+$wxwidgetspath =~ s/::/\//g;
+
+for (@INC) {
+ if( -f qq($_/$wxwidgetspath ) ) {
+ $portablebase = qq($_/Alien/wxWidgets/$key);
+ last;
+ }
+}
+
+if( $portablebase ) {
+ $portablebase =~ s{/}{\\}g;
+ my $portablelibpath = qq($portablebase\\lib);
+ my $portableincpath = qq($portablebase\\include);
+
+ $VALUES{include_path} = qq{-I$portablelibpath -I$portableincpath};
+ $VALUES{link_libraries} =~ s{-L\S+\s}{-L$portablelibpath };
+ $VALUES{shared_library_path} = $portablelibpath;
+ $VALUES{wx_base_directory} = $portablebase;
+ $VALUES{prefix} = $portablebase;
+}
+EOT
+
+ print $fh <<'EOT';
+
+sub values { %VALUES, key => $key }
+
+sub config {
+ +{ %{$VALUES{config}},
+ package => __PACKAGE__,
+ key => $key,
+ version => $VALUES{version},
+ }
+}
+
+1;
+EOT
+
+ close $fh;
+}
+
+sub fetch_wxwidgets {
+ my $self = shift;
+
+ return if -f $self->notes( 'build_data' )->{data}{archive};
+ require File::Fetch;
+
+ print "Fetching wxWidgets...\n";
+ print "fetching from: ", $self->notes( 'build_data' )->{data}{url}, "\n";
+
+ my $path = File::Fetch->new
+ ( uri => $self->notes( 'build_data' )->{data}{url} )->fetch;
+ die 'Unable to fetch archive' unless $path;
+}
+
+sub extract_wxwidgets {
+ my $self = shift;
+
+ return if -d $self->notes( 'build_data' )->{data}{directory};
+ my $archive = $self->notes( 'build_data' )->{data}{archive};
+
+ print "Extracting wxWidgets...\n";
+
+ require Archive::Extract;
+ $Archive::Extract::PREFER_BIN = 1;
+ my $ae = Archive::Extract->new( archive => $archive );
+
+ die 'Error: ', $ae->error unless $ae->extract;
+
+ $self->patch_wxwidgets;
+}
+
+sub patch_wxwidgets {
+ my $self = shift;
+ my $old_dir = Cwd::cwd();
+ my @patches = $self->awx_wx_patches;
+
+ print "Patching wxWidgets...\n";
+
+ my $wx_dir = $self->notes( 'build_data' )->{data}{directory};
+ my $build_dir = File::Spec->rel2abs( $wx_dir );
+ chdir $wx_dir;
+
+ foreach my $i ( @patches ) {
+ print "Applying patch: ", $i, "\n";
+ my $cmd = $self->_patch_command( $build_dir, $i );
+ print $cmd, "\n";
+ system $cmd and die 'Error: ', $?;
+ }
+
+ chdir $old_dir;
+}
+
+sub _patch_command {
+ my( $self, $base_dir, $patch_file ) = @_;
+
+ $patch_file = File::Spec->abs2rel( $patch_file, $base_dir );
+ my $cmd = $^X . ' ' . File::Spec->catfile( File::Spec->updir,
+ qw(inc bin patch) )
+ . " -N -p0 -u -b .bak < $patch_file";
+
+ return $cmd;
+}
+
+sub build_wxwidgets {
+ die "Don't know how to build wxWidgets";
+}
+
+sub install_wxwidgets {
+ return unless $_[0]->notes( 'build_wx' );
+ die "Don't know how to build wxWidgets";
+}
+
+sub install_system_wxwidgets { }
+
+sub awx_configure {
+ my $self = shift;
+ return %{$self->{awx_config}} if $self->{awx_config};
+
+ my %config;
+
+ $config{config}{debug} = $self->awx_is_debug;
+ $config{config}{unicode} = $self->awx_is_unicode;
+ $config{config}{mslu} = $self->awx_is_mslu;
+ $config{config}{build} = $self->awx_is_monolithic ? 'mono' : 'multi';
+ $config{link_flags} = '';
+ $config{c_flags} = '';
+
+ return %config;
+}
+
+sub wx_config {
+ my $self = shift;
+ my $data = $self->awx_wx_config_data;
+
+ foreach ( @_ ) {
+ warn "Undefined key '", $_, "' in wx_config"
+ unless defined $data->{$_};
+ }
+
+ return @{$data}{@_};
+}
+
+sub awx_monolithic { $_[0]->args( 'wxWidgets-monolithic' ) ? 1 : 0 }
+sub awx_is_monolithic { $_[0]->awx_monolithic }
+sub awx_debug { $_[0]->args( 'wxWidgets-debug' ) ? 1 : 0 }
+sub awx_is_debug { $_[0]->awx_debug }
+sub awx_unicode { $_[0]->notes( 'build_wx_unicode' )
+ || $_[0]->args( 'wxWidgets-unicode' ) ? 1 : 0 }
+sub awx_is_unicode { $_[0]->awx_unicode }
+sub awx_mslu { 0 }
+sub awx_is_mslu { $_[0]->awx_mslu }
+sub awx_static { $_[0]->args( 'wxWidgets-static' ) ? 1 : 0 }
+sub awx_is_static { $_[0]->awx_static }
+sub awx_universal { $_[0]->args( 'wxWidgets-universal' ) ? 1 : 0 }
+sub awx_is_universal { $_[0]->awx_universal }
+sub awx_get_package { local $_ = $_[0]; s/^My::Build:://; return $_ }
+
+sub awx_wx_patches {
+ my $self = shift;
+ my $data = $self->notes( 'build_data' );
+ my $toolkit = $^O eq 'MSWin32' ? 'msw' :
+ $^O eq 'darwin' ? 'mac' :
+ 'unix';
+ my $unicode = $self->awx_unicode ? 'unicode' : 'ansi';
+
+ return unless exists $data->{$toolkit} and $data->{$toolkit}{$unicode};
+
+ return map { File::Spec->rel2abs( File::Spec->catfile( 'patches', $_ ) ) }
+ @{$data->{$toolkit}{$unicode}};
+}
+
+sub awx_get_name {
+ my( $self, %args ) = @_;
+ my $e = sub { defined $_[0] ? ( $_[0] ) : () };
+ my $pv = sub { join '.', map { 0 + ( $_ || 0 ) }
+ ( $_[0] =~ /(\d+)\.(\d{1,3})(\d{0,3})/ ) } ;
+ my $base = join '-', $args{toolkit}, $pv->( $args{version} ),
+ $e->( $args{debug} ? 'dbg' : undef ),
+ $e->( $args{unicode} ? 'uni' : undef ),
+ $e->( $args{mslu} ? 'mslu' : undef ),
+ $e->( $args{compiler} ),
+ $e->( $args{compiler_version} ),
+ ;
+
+ $base =~ s/\./_/g; $base =~ s/-/_/g;
+
+ return $base;
+}
+
+sub awx_compiler_kind { 'nc' } # as in 'No Clue'
+
+sub awx_compiler_version {
+ return Alien::wxWidgets::Utility::awx_cc_abi_version( $_[1] );
+}
+
+sub awx_path_search {
+ my( $self, $file ) = @_;
+
+ foreach my $d ( File::Spec->path ) {
+ my $full = File::Spec->catfile( $d, $file );
+ # we are gonna use glob() to accept wildcards
+ foreach my $f ( bsd_glob( $full ) ) {
+ return $f if -f $f;
+ }
+ }
+
+ return;
+}
+
+sub awx_uses_bakefile { 1 }
+
+sub ACTION_ppmdist {
+ my( $self ) = @_;
+
+ $self->awx_strip_dlls;
+ $self->_system( 'perl script/make_ppm.pl' );
+}
+
+sub _system {
+ shift;
+ my $ret;
+
+ $ret = @_ > 1 ? system @_ : system $_[0];
+ $ret and croak "system: @_: $?";
+}
+
+1;
--- /dev/null
+package My::Build::MacOSX_wx_config;
+
+use strict;
+use base qw(My::Build::Any_wx_config);
+
+use Config;
+
+sub awx_wx_config_data {
+ my $self = shift;
+ return $self->{awx_data} if $self->{awx_data};
+ my %data = ( linkflags => '', %{$self->SUPER::awx_wx_config_data} );
+
+ # MakeMaker does not like some options
+ $data{libs} =~ s{-framework\s+\w+}{}g;
+ $data{libs} =~ s{-isysroot\s+\S+}{}g;
+ $data{libs} =~ s{-L/usr/local/lib\s}{}g;
+
+ $data{libs} =~ s{\s(-arch\s+\w+)}
+ {$data{linkflags} .= " $1 ";
+ $data{cxxflags} .= " $1 ";
+ ' '}eg;
+
+ $data{cxx} =~ s{-isysroot\s+\S+}{}g;
+ $data{ld} = $data{cxx};
+ $data{cxxflags} .= ' -UWX_PRECOMP ';
+
+ $self->{awx_data} = \%data;
+}
+
+sub awx_configure {
+ my $self = shift;
+ my %config = $self->SUPER::awx_configure;
+
+ $config{link_flags} .= $self->wx_config( 'linkflags' );
+
+ return %config;
+}
+
+sub wxwidgets_configure_extra_flags {
+ my( $self ) = @_;
+ my $extra_flags = '';
+
+ # on Snow Leopard, force wxWidgets 2.8.x builds to be 32-bit;
+ if( $self->notes( 'build_data' )->{data}{version} =~ /^2.8/
+ && `uname -r` =~ /^10\./
+ && `sysctl hw.cpu64bit_capable` =~ /^hw.cpu64bit_capable: 1/ ) {
+ print "Forcing wxWidgets build to 32 bit\n";
+ $extra_flags = join ' ', map { qq{$_="-arch i386"} }
+ qw(CFLAGS CXXFLAGS LDFLAGS
+ OBJCFLAGS OBJCXXFLAGS);
+ }
+ # build fix for 2.9.0 on Snow Leopard
+ if( `uname -r` =~ /^10\./
+ && $self->notes( 'build_data' )->{data}{version} eq '2.9.0' ) {
+ $extra_flags .= ' --with-macosx-version-min=10.5';
+ }
+
+ return $extra_flags;
+}
+
+sub awx_build_toolkit {
+ # use Cocoa for OS X wxWidgets builds with 64 bit Perl
+ if( $Config{osname} =~ /darwin/
+ && $Config{ptrsize} == 8 ) {
+ return 'osx_cocoa';
+ } else {
+ return 'mac';
+ }
+}
+
+sub awx_dlext { 'dylib' }
+
+sub build_wxwidgets {
+ my( $self ) = @_;
+
+ # can't build wxWidgets 2.8.x with 64 bit Perl
+ if( $Config{ptrsize} == 8
+ && $self->notes( 'build_data' )->{data}{version} =~ /^2.8/ ) {
+ print <<EOT;
+=======================================================================
+The 2.8.x wxWidgets for OS X does not support 64-bit. In order to build
+wxPerl you will need to either recompile Perl as a 32-bit binary or (if
+using the Apple-provided Perl) force it to run in 32-bit mode (see "man
+perl"). Alpha 64-bit wx for OS X is in 2.9.x, but untested in wxPerl.
+=======================================================================
+EOT
+ exit 1;
+ }
+
+ $self->SUPER::build_wxwidgets;
+}
+
+1;
--- /dev/null
+package My::Build::Utility;
+
+use strict;
+use base qw(Exporter);
+use Config;
+use Fatal qw(open);
+
+our @EXPORT_OK = qw(awx_arch_file awx_install_arch_file
+ awx_install_arch_auto_file
+ awx_arch_dir awx_install_arch_dir awx_touch);
+
+sub awx_arch_file {
+ my( $vol, $dir, $file ) = File::Spec->splitpath( $_[0] || '' );
+ File::Spec->catfile( 'blib', 'arch', 'Alien', 'wxWidgets',
+ File::Spec->splitdir( $dir ), $file );
+}
+
+sub awx_arch_dir {
+ my( $vol, $dir, $file ) = File::Spec->splitpath( $_[0] || '' );
+ File::Spec->catdir( 'blib', 'arch', 'Alien', 'wxWidgets',
+ File::Spec->splitdir( $dir ), $file );
+}
+
+sub awx_install_arch_file {
+ my( $build, $p ) = @_;
+ my( $vol, $dir, $file ) = File::Spec->splitpath( $p || '' );
+ File::Spec->catfile( $build->install_destination( 'arch' ), 'Alien', 'wxWidgets',
+ File::Spec->splitdir( $dir ), $file );
+}
+
+sub awx_install_arch_dir {
+ my( $build, $p ) = @_;
+ my( $vol, $dir, $file ) = File::Spec->splitpath( $p || '' );
+ File::Spec->catdir( $build->install_destination( 'arch' ), 'Alien', 'wxWidgets',
+ File::Spec->splitdir( $dir ), $file );
+}
+
+sub awx_install_arch_auto_file {
+ my( $build, $p ) = @_;
+ my( $vol, $dir, $file ) = File::Spec->splitpath( $p || '' );
+ File::Spec->catfile( $build->install_destination( 'arch' ), 'auto', 'Alien', 'wxWidgets',
+ File::Spec->splitdir( $dir ), $file );
+}
+
+sub awx_touch {
+ require ExtUtils::Command;
+ local @ARGV = @_;
+ ExtUtils::Command::touch();
+}
+
+1;
--- /dev/null
+package My::Build::Win32;
+
+use strict;
+use base qw(My::Build::Base);
+use My::Build::Utility qw(awx_arch_file awx_install_arch_file
+ awx_install_arch_dir);
+use Config;
+use Fatal qw(open close);
+use Carp qw(cluck);
+use File::Glob qw(bsd_glob);
+
+my $initialized;
+
+sub _init {
+ return if $initialized;
+ $initialized = 1;
+
+ return if Module::Build->current->notes( 'build_wx' );
+ # install_only is set when a wxWidgets build is already configured
+ # with Alien::wxWidgets
+ return if Module::Build->current->notes( 'install_only' );
+
+ # check for WXDIR and WXWIN environment variables
+ unless( exists $ENV{WXDIR} or exists $ENV{WXWIN} ) {
+ cluck <<EOT;
+
+**********************************************************************
+WARNING!
+
+You need to set the WXDIR or WXWIN variables; refer to
+docs/install.txt for a detailed explanation
+**********************************************************************
+
+EOT
+ exit 1;
+ }
+
+ $ENV{WXDIR} = $ENV{WXWIN} unless exists $ENV{WXDIR};
+ $ENV{WXWIN} = $ENV{WXDIR} unless exists $ENV{WXWIN};
+}
+
+sub _patch_command {
+ my( $self, $base_dir, $patch_file ) = @_;
+ my $patch_exe = File::Spec->catfile( File::Spec->updir,
+ qw(inc bin patch.exe) );
+
+ my $cmd = qq{perl -pe "" -- $patch_file} .
+ qq{ | $patch_exe -N -p0 -u -b -z .bak};
+
+ return $cmd;
+}
+
+sub awx_grep_dlls {
+ my( $self, $libdir, $digits, $mono ) = @_;
+ my $ret = {};
+ my $suff = ( $self->awx_unicode ? 'u' : '' ) .
+ ( $self->awx_debug ? 'd' : '' );
+
+ my @dlls = grep { m/${digits}\d*${suff}_/ }
+ bsd_glob( File::Spec->catfile( $libdir, '*.dll' ) );
+ my @libs = grep { m/(?:lib)?wx(?:wince|msw|base)[\w\.]+$/ }
+ grep { m/${digits}\d*${suff}(_|\.)/ }
+ bsd_glob( File::Spec->catfile( $libdir, "*$Config{lib_ext}" ) );
+
+ foreach my $full ( @dlls, @libs ) {
+ my( $name, $type );
+ local $_ = File::Basename::basename( $full );
+ m/^[^_]+_([^_\.]+)/ and $name = $1;
+ $name = 'base' if !defined $name || $name =~ m/^(gcc|vc|evc)$/;
+ $type = m/$Config{lib_ext}$/i ? 'lib' : 'dll';
+ $ret->{$name}{$type} = $full;
+ }
+
+ if( $mono ) {
+ $ret->{mono} = delete $ret->{base};
+ }
+
+ die "Configuration error: could not find libraries for configuration: "
+ . join ' ', map "'$_'", $suff, $digits
+ unless ( exists $ret->{core}{dll} and exists $ret->{core}{lib} )
+ or ( exists $ret->{mono}{dll} and exists $ret->{mono}{lib} );
+
+ return $ret;
+}
+
+sub awx_wx_config_data {
+ my $self = shift;
+ my $wxdir_b = $ENV{WXDIR};
+ my $wxdir = $self->notes( 'build_wx' ) ?
+ awx_install_arch_dir( $self, 'rEpLaCe' ) : $wxdir_b;
+
+ return { 'wxdir' => $wxdir,
+ 'wxdir_build' => $wxdir_b,
+ 'wxinc' => File::Spec->catdir( $wxdir_b, 'include' ),
+ 'wxcontrinc' => File::Spec->catdir( $wxdir_b, 'contrib',
+ 'include' ),
+ };
+}
+
+sub awx_configure {
+ my $self = shift;
+ my %config = $self->SUPER::awx_configure;
+
+ $config{prefix} = $self->wx_config( 'wxdir' );
+ $config{config}{toolkit} = $self->is_wince ? 'wce' : 'msw';
+ $config{shared_library_path} = awx_install_arch_file( $self, "rEpLaCe/lib" );
+
+ die "Unable to find setup.h directory"
+ unless $self->wx_config( 'cxxflags' )
+ =~ m{[/-]I\s*(\S+lib[\\/][\w\\/]+)(?:\s|$)};
+ $self->{awx_setup_dir} = $1;
+
+ $self->{awx_data}{version} = $self->awx_w32_bakefile_version
+ if -f $self->awx_w32_build_cfg;
+
+ return %config;
+}
+
+sub awx_w32_bakefile_version {
+ my $self = shift;
+ my $build_cfg = $self->awx_w32_build_cfg;
+ my $in;
+
+ open $in, $build_cfg;
+ my %ver = map { split /=/ } grep /^WXVER_/, map { s/\s//g; $_ } <$in>;
+ close $in;
+
+ return join '.', @ver{qw(WXVER_MAJOR WXVER_MINOR WXVER_RELEASE)};
+}
+
+sub awx_w32_build_cfg {
+ my $self = shift;
+ File::Spec->catfile( $self->{awx_setup_dir}, 'build.cfg' )
+}
+
+sub files_to_install {
+ my $self = shift;
+ my $dlls = $self->awx_wx_config_data->{dlls};
+
+ my $setup_h = File::Spec->catfile( $self->{awx_setup_dir},
+ 'wx', 'setup.h' );
+ my $build_cfg = $self->awx_w32_build_cfg;
+ my %files;
+
+ $files{$build_cfg} = awx_arch_file( "rEpLaCe/lib/build.cfg" )
+ if -f $build_cfg;
+
+ $files{$setup_h} = awx_arch_file( "rEpLaCe/lib/wx/setup.h" );
+ foreach my $dll ( map { $_->{dll} } values %$dlls ) {
+ next unless defined $dll;
+ my $base = File::Basename::basename( $dll );
+ $files{$dll} = awx_arch_file( "rEpLaCe/lib/$base" );
+ }
+ foreach my $lib ( map { $_->{lib} } values %$dlls ) {
+ next unless defined $lib;
+ my $base = File::Basename::basename( $lib );
+ $files{$lib} = awx_arch_file( "rEpLaCe/lib/$base" );
+ }
+
+ if( $self->notes( 'build_wx' ) || $self->notes( 'mk_portable' ) ) {
+ require File::Find;
+ my $no_platform = join '|', qw(unix gtk x11 motif mac cocoa
+ os2 palmos univ mgl msdos gtk1
+ dfb);
+ my $wx_base = $self->awx_wx_config_data->{wxdir_build};
+ foreach my $find_base ( File::Spec->catdir( $wx_base, qw(include wx) ),
+ File::Spec->catdir( $wx_base, qw(contrib
+ include wx) ) ) {
+ next unless -d $find_base;
+ my $wanted = sub {
+ $File::Find::prune ||=
+ -d $_ && $_ =~ m{include[/\\]wx[/\\](?:$no_platform)$};
+ $File::Find::prune ||=
+ -d $_ && $_ =~ m{[/\\]\.svn$};
+ return unless -f $_;
+ my $rel = File::Spec->abs2rel( $_, $find_base );
+ $files{$_} = awx_arch_file( "rEpLaCe/include/wx/$rel" );
+ # print "$_ ==> $files{$_}\n";
+ };
+ File::Find::find
+ ( { wanted => $wanted,
+ no_chdir => 1,
+ },
+ $find_base
+ );
+ }
+ }
+
+ return %files;
+}
+
+sub copy_wxwidgets {
+ my $self = shift;
+ my %files = $self->files_to_install;
+
+ while( my( $from, $to ) = each %files ) {
+ $to =~ s/rEpLaCe/$self->{awx_key}/g;
+ $self->copy_if_modified( from => $from, to => $to, verbose => 1 );
+ }
+}
+
+sub install_wxwidgets {
+ my $self = shift;
+
+ $self->copy_wxwidgets;
+}
+
+sub awx_get_package {
+ My::Build::Win32::_init();
+
+ my $package;
+
+ return 'WinCE' if $INC{'Cross.pm'};
+
+ SWITCH: {
+ local $_ = $Config{ccname} || $Config{cc};
+
+ /^cl/i and $package = 'Win32_MSVC' and last SWITCH;
+ /^gcc/i and $package = 'Win32_MinGW' and last SWITCH;
+
+ # default
+ die "Your compiler is not currently supported on Win32"
+ };
+
+ return $package . '_Bakefile';
+}
+
+# MSLU is default when using Unicode *and* it has not
+# been explicitly disabled
+sub awx_mslu {
+ return $_[0]->args( 'wxWidgets-mslu' )
+ if defined $_[0]->args( 'wxWidgets-mslu' );
+ return $_[0]->args( 'wxWidgets-unicode' );
+}
+
+sub massage_environment {
+ my( $self ) = shift;
+
+ if( $self->notes( 'build_wx' ) ) {
+ $ENV{WXWIN} = $ENV{WXDIR} = File::Spec->rel2abs
+ ( $self->notes( 'build_data' )->{data}{directory} );
+ }
+}
+
+package My::Build::Win32_Bakefile;
+
+use strict;
+use Carp;
+# mixin: no use base
+
+sub build_wxwidgets {
+ my $self = shift;
+ my $old_dir = Cwd::cwd();
+
+ my $uni = $self->awx_unicode ? 'UNICODE=1' : 'UNICODE=0';
+ my $mslu = $self->awx_mslu ? 'MSLU=1' : 'MSLU=0';
+ my $dbg = $self->awx_debug ? 'BUILD=debug' : 'BUILD=release';
+ my $opt = join ' ', $uni, $mslu, $dbg, 'SHARED=1';
+
+ chdir File::Spec->catdir( $ENV{WXDIR}, 'build', 'msw' );
+ $self->_system( $self->_make_command . ' ' . $opt );
+ chdir File::Spec->catdir( $ENV{WXDIR}, 'contrib', 'build', 'stc' );
+ $self->_system( $self->_make_command . ' ' . $opt );
+
+ chdir $old_dir;
+}
+
+sub is_wince { 0 }
+
+1;
--- /dev/null
+package My::Build::Win32_MSVC;
+
+use strict;
+use base qw(My::Build::Win32);
+use My::Build::Utility qw(awx_install_arch_file awx_install_arch_dir);
+use Alien::wxWidgets::Utility qw(awx_cc_version);
+use Config;
+
+sub awx_configure {
+ my $self = shift;
+ my %config = $self->SUPER::awx_configure;
+
+ $config{c_flags} .= ' -GF -TP ';
+
+ if( $self->awx_debug ) {
+ $config{link_flags} .= ' -debug ';
+ }
+
+ my $cccflags = $self->wx_config( 'cxxflags' );
+ my $libs = $self->wx_config( 'libs' );
+ my $incdir = $self->awx_wx_config_data->{wxinc};
+ my $cincdir = $self->awx_wx_config_data->{wxcontrinc};
+ my $iincdir = awx_install_arch_dir( $self, 'rEpLaCe/include' );
+
+ foreach ( split /\s+/, $cccflags ) {
+ m(^-DSTRICT) && next;
+ m(^-I) && do {
+ next if m{(?:regex|zlib|jpeg|png|tiff|expat[\\/]lib)$};
+ if( $self->notes( 'build_wx' ) ) {
+ $_ =~ s{\Q$cincdir\E}{$iincdir};
+ $_ =~ s{\Q$incdir\E}{$iincdir};
+ }
+ if( $_ =~ /-I\Q$self->{awx_setup_dir}\E/ && !$self->is_wince ) {
+ $config{include_path} .=
+ '-I' . awx_install_arch_file( $self, 'rEpLaCe/lib' ) . ' ';
+ } else {
+ $config{include_path} .= "$_ ";
+ }
+ next;
+ };
+ m(^-D) && do { $config{defines} .= "$_ "; next; };
+ $config{c_flags} .= "$_ ";
+ }
+
+ foreach ( split /\s+/, $libs ) {
+ m(wx|unicows)i || next;
+ next if m{(?:(?:zlib|regexu?|expat|png|jpeg|tiff)[uhd]{0,2}\.lib)$};
+ $config{link_libraries} .= "$_ ";
+ }
+ $config{link_libraries} .= 'msvcprt.lib ' if awx_cc_version( 'cl' ) > 6;
+
+ my $dlls = $self->awx_wx_config_data->{dlls};
+ $config{_libraries} = {};
+
+ while( my( $key, $value ) = each %$dlls ) {
+ $config{_libraries}{$key} =
+ { map { $_ => File::Basename::basename( $value->{$_} ) }
+ keys %$value };
+ if( $value->{link} ) {
+ $config{_libraries}{$key}{link} = $value->{link};
+ } elsif( $value->{lib} ) {
+ $config{_libraries}{$key}{link} = $config{_libraries}{$key}{lib};
+ }
+ }
+
+ $config{config}{build} =
+ $self->awx_wx_config_data->{build_kind} || 'multi';
+
+ return %config;
+}
+
+sub awx_compiler_kind { 'cl' }
+
+sub awx_strip_dlls { }
+
+1;
--- /dev/null
+package My::Build::Win32_MSVC_Bakefile;
+
+use strict;
+use base qw(My::Build::Win32_MSVC My::Build::Win32_Bakefile);
+use My::Build::Utility qw(awx_install_arch_file awx_install_arch_auto_file);
+use Alien::wxWidgets::Utility qw(awx_capture);
+use Config;
+use Fatal qw(chdir);
+use Cwd ();
+
+sub _check_nmake {
+ my $out = awx_capture( 'nmake /?' );
+ unless( $out =~ m{/U\s}i ) {
+ die "Please use an NMAKE version supporting '-u', not the" .
+ " freely-available one\n";
+ }
+}
+
+sub awx_wx_config_data {
+ my $self = shift;
+
+ My::Build::Win32::_init();
+ $self->_check_nmake();
+
+ return $self->{awx_data} if $self->{awx_data};
+
+ my %data = ( %{$self->SUPER::awx_wx_config_data},
+ 'cxx' => 'cl',
+ 'ld' => 'link',
+ );
+
+ my $make = File::Basename::basename( lc $Config{make}, '.exe' );
+ die "PANIC: you are not using nmake!" unless $make eq 'nmake';
+
+ my $orig_libdir;
+ my $final = $self->awx_debug ? 'BUILD=debug DEBUG_RUNTIME_LIBS=0'
+ : 'BUILD=release DEBUG_RUNTIME_LIBS=0';
+ my $unicode = $self->awx_unicode ? 'UNICODE=1' : 'UNICODE=0';
+ $unicode .= ' MSLU=1' if $self->awx_mslu;
+
+ my $dir = Cwd::cwd;
+ chdir File::Spec->catdir( $ENV{WXDIR}, 'samples', 'minimal' );
+ my @t = qx(nmake /nologo /n /u /f makefile.vc $final $unicode SHARED=1);
+
+ my( $accu, $libdir, $digits );
+ foreach ( @t ) {
+ chomp;
+ m/^\s*echo\s+(.*)>\s*\S+\s*$/ and $accu .= ' ' . $1 and next;
+ s/\@\S+\s*$/$accu/ and undef $accu;
+
+ if( s/^\s*link\s+// ) {
+ m/\swxmsw(\d+)\S+\.lib/ and $digits = $1;
+ s/\s+\S+\.(exe|res|obj)/ /g;
+ s{[-/]LIBPATH:(\S+)}
+ {$orig_libdir = File::Spec->canonpath
+ ( File::Spec->rel2abs( $1 ) );
+ '-L' . ( $libdir = awx_install_arch_file( $self, 'rEpLaCe/lib' ) )}egi;
+ $data{libs} = $_;
+ } elsif( s/^\s*cl\s+// ) {
+ s/\s+\S+\.(cpp|pdb|obj)/ /g;
+ s{[-/]I(\S+)}{'-I' . File::Spec->canonpath
+ ( File::Spec->rel2abs( $1 ) )}egi;
+ s{[-/]I(\S+)[\\/]samples[\\/]minimal(\s|$)}{-I$1\\contrib\\include }i;
+ s{[-/]I(\S+)[\\/]samples(\s|$)}{ }i;
+ s{[-/]D(\S+)}{-D$1}g;
+ $data{cxxflags} = $_;
+ }
+ }
+
+ chdir $dir;
+ die 'Could not find wxWidgets lib directory' unless $libdir;
+
+ $data{dlls} = $self->awx_grep_dlls( $orig_libdir, $digits, $self->awx_is_monolithic );
+ $data{version} = $digits;
+
+ $self->{awx_data} = \%data;
+}
+
+sub _make_command { "nmake -f makefile.vc all " }
+
+sub build_wxwidgets {
+ my( $self ) = shift;
+ my $old_dir = Cwd::cwd();
+
+ $self->My::Build::Win32_Bakefile::build_wxwidgets( @_ );
+
+ # Compiling with MSVC 9 (VS 2008) and probably with VS 2005, the
+ # linker creates a manifest that must be embedded in the DLL to
+ # make it load correctly
+ chdir File::Spec->catdir( $ENV{WXDIR} );
+ foreach my $dll ( glob( 'lib/vc_dll*/*.dll' ) ) {
+ next unless -f "${dll}.manifest";
+ $self->_system( 'mt', '-nologo', '-manifest', "${dll}.manifest",
+ "-outputresource:${dll};2" );
+ unlink "${dll}.manifest";
+ }
+
+ chdir $old_dir;
+}
+
+1;
--- /dev/null
+package My::Build::Win32_MinGW;
+
+use strict;
+use base qw(My::Build::Win32);
+use My::Build::Utility qw(awx_arch_file awx_install_arch_file
+ awx_install_arch_dir awx_arch_dir);
+use Config;
+use File::Basename qw();
+use File::Glob qw(bsd_glob);
+
+sub _find_make {
+ my( @try ) = qw(mingw32-make gmake make);
+ push @try, $Config{gmake} if $Config{gmake};
+
+ foreach my $name ( @try ) {
+ foreach my $dir ( File::Spec->path ) {
+ my $abs = File::Spec->catfile( $dir, "$name.exe" );
+ return $name if -x $abs;
+ }
+ }
+
+ return 'make';
+}
+
+sub awx_configure {
+ my $self = shift;
+ my %config = $self->SUPER::awx_configure;
+
+ $config{c_flags} .= " -fvtable-thunks ";
+
+ if( $self->awx_debug ) {
+ $config{c_flags} .= ' -g ';
+ } else {
+ $config{link_flags} .= ' -s ';
+ }
+
+ my $cccflags = $self->wx_config( 'cxxflags' );
+ my $libs = $self->wx_config( 'libs' );
+ my $incdir = $self->awx_wx_config_data->{wxinc};
+ my $cincdir = $self->awx_wx_config_data->{wxcontrinc};
+ my $iincdir = awx_install_arch_dir( $self, 'rEpLaCe/include' );
+
+ foreach ( split /\s+/, $cccflags ) {
+ m(^-DSTRICT) && next;
+ m(^\.d$) && next; # broken makefile
+ m(^-W.*) && next; # under Win32 -Wall gives you TONS of warnings
+ m(^-I) && do {
+ next if m{(?:regex|zlib|jpeg|png|tiff)$};
+ if( $self->notes( 'build_wx' ) ) {
+ $_ =~ s{\Q$cincdir\E}{$iincdir};
+ $_ =~ s{\Q$incdir\E}{$iincdir};
+ }
+ if( $_ =~ /-I\Q$self->{awx_setup_dir}\E/ ) {
+ $config{include_path} .=
+ '-I' . awx_install_arch_file( $self, 'rEpLaCe/lib' ) . ' ';
+ } else {
+ $config{include_path} .= "$_ ";
+ }
+ next;
+ };
+ m(^-D) && do { $config{defines} .= "$_ "; next; };
+ $config{c_flags} .= "$_ ";
+ }
+
+ foreach ( split /\s+/, $libs ) {
+ m(wx|unicows)i || next;
+ next if m{(?:wx(?:zlib|regexu?|expat|png|jpeg|tiff)[ud]{0,2})$};
+ $config{link_libraries} .= "$_ ";
+ }
+
+ my $dlls = $self->awx_wx_config_data->{dlls};
+ $config{_libraries} = {};
+
+ while( my( $key, $value ) = each %$dlls ) {
+ $config{_libraries}{$key} =
+ { map { $_ => File::Basename::basename( $value->{$_} ) }
+ keys %$value };
+ if( $value->{link} ) {
+ $config{_libraries}{$key}{link} = $value->{link};
+ } elsif( $value->{lib} ) {
+ my $lib = $config{_libraries}{$key}{lib};
+ $lib =~ s/^lib(.*?)(?:\.dll)?\.a$/$1/;
+ $config{_libraries}{$key}{link} = '-l' . $lib;
+ }
+ }
+
+ return %config;
+}
+
+sub awx_compiler_kind { 'gcc' }
+
+sub files_to_install {
+ my $self = shift;
+ my( @try ) = qw(mingwm10.dll libgcc_*.dll);
+ my( $dll, $dll_from );
+
+ foreach my $d ( @try ) {
+ $dll_from = $self->awx_path_search( $d );
+ if( defined $dll_from ) {
+ $dll = File::Basename::basename( $dll_from );
+ last;
+ }
+ }
+
+ return ( $self->SUPER::files_to_install(),
+ ( $dll_from => awx_arch_file( "rEpLaCe/lib/$dll" ) ) );
+}
+
+sub awx_strip_dlls {
+ my( $self ) = @_;
+ my( $dir ) = grep !/Config/, bsd_glob( awx_arch_dir( '*' ) );
+
+ $self->_system( "attrib -r $dir\\lib\\*.dll" );
+ $self->_system( "strip $dir\\lib\\*.dll" );
+ $self->_system( "attrib +r $dir\\lib\\*.dll" );
+}
+
+1;
--- /dev/null
+package My::Build::Win32_MinGW_Bakefile;
+
+use strict;
+use base qw(My::Build::Win32_MinGW My::Build::Win32_Bakefile);
+use My::Build::Utility qw(awx_install_arch_file awx_install_arch_auto_file);
+use Config;
+use Fatal qw(chdir);
+
+sub awx_wx_config_data {
+ My::Build::Win32::_init();
+
+ my $self = shift;
+ return $self->{awx_data} if $self->{awx_data};
+
+ my %data = ( %{$self->SUPER::awx_wx_config_data},
+ 'cxx' => 'g++',
+ 'ld' => 'g++',
+ );
+
+ my $cflags = 'CXXFLAGS=" -Os -DNO_GCC_PRAGMA "';
+ my $final = $self->awx_debug ? 'BUILD=debug'
+ : 'BUILD=release';
+ my $unicode = $self->awx_unicode ? 'UNICODE=1' : 'UNICODE=0';
+ $unicode .= ' MSLU=1' if $self->awx_mslu;
+
+ my $dir = Cwd::cwd;
+ my $make = $self->_find_make;
+ chdir File::Spec->catdir( $ENV{WXDIR}, 'samples', 'minimal' );
+ my @t = qx($make -n -f makefile.gcc $final $unicode $cflags SHARED=1);
+
+ my( $orig_libdir, $libdir, $digits );
+ foreach ( @t ) {
+ chomp;
+
+ if( m/\s-l\w+/ ) {
+ m/-lwxbase(\d+)/ and $digits = $1;
+ s/^[cg]\+\+//;
+ s/(?:\s|^)-[co]//g;
+ s/\s+\S+\.(exe|o)/ /gi;
+ s{-L(\S+)}
+ {$orig_libdir = File::Spec->canonpath
+ ( File::Spec->rel2abs( $1 ) );
+ '-L' . ( $libdir = awx_install_arch_file( $self, 'rEpLaCe/lib' ) )}eg;
+ $data{libs} = $_;
+ } elsif( s/^\s*g\+\+\s+// ) {
+ s/\s+\S+\.(cpp|o|d)/ /g;
+ s/\s+-M[DP]\b/ /g;
+ s/(?:\s|^)-[co]//g;
+ s{[-/]I(\S+)}{'-I' . File::Spec->canonpath
+ ( File::Spec->rel2abs( $1 ) )}egi;
+ s{[-/]I(\S+)[\\/]samples[\\/]minimal(\s|$)}{-I$1\\contrib\\include }i;
+ s{[-/]I(\S+)[\\/]samples(\s|$)}{ }i;
+ $data{cxxflags} = $_;
+ }
+ }
+
+ chdir $dir;
+ die 'Could not find wxWidgets lib directory' unless $libdir;
+
+ $data{dlls} = $self->awx_grep_dlls( $orig_libdir, $digits, $self->awx_is_monolithic );
+ $data{version} = $digits;
+
+ $self->{awx_data} = \%data;
+}
+
+sub _make_command {
+ my $make = $_[0]->_find_make;
+ "$make -f makefile.gcc all "
+}
+
+sub build_wxwidgets {
+ my( $self ) = shift;
+
+ $self->My::Build::Win32_Bakefile::build_wxwidgets( @_ );
+}
+
+1;
--- /dev/null
+#############################################################################
+## Name: build/Wx/build/Config/gmake.mak
+## Purpose: extracts some flag information from makeg95.env
+## Author: Mattia Barbon
+## Modified by:
+## Created: 10/12/2000
+## RCS-ID: $Id: gmake.mak,v 1.1 2005/08/16 20:52:34 mbarbon Exp $
+## Copyright: (c) 2000 Mattia Barbon
+## Licence: This program is free software; you can redistribute it and/or
+## modify it under the same terms as Perl itself
+#############################################################################
+
+WXUSINGDLL=1
+
+include $(WXWIN)/src/makeg95.env
+
+version:
+ echo $(WXVERSION)$(wxRELEASE_NUMBER)
+
+wxdir:
+ echo $(WXWIN)
+
+# for 2.4.0 or less vs. 2.4.1 and 2.5.0
+cxxflags:
+ echo $(CPPFLAGS) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS)
+
+linkflags:
+ echo $(LINKFLAGS)
+
+libs:
+ echo $(LIBS)
+
+# this one is for import library ( not in wx-config )
+implib:
+ echo $(WXLIB)
--- /dev/null
+#############################################################################
+## Name: build/Wx/build/Config/nmake.mak
+## Purpose: extracts some flag information from makevc.env
+## Author: Mattia Barbon
+## Modified by:
+## Created: 29/10/2000
+## RCS-ID: $Id: nmake.mak,v 1.1 2005/08/16 20:52:34 mbarbon Exp $
+## Copyright: (c) 2000 Mattia Barbon
+## Licence: This program is free software; you can redistribute it and/or
+## modify it under the same terms as Perl itself
+#############################################################################
+
+NOPCH=1
+WXUSINGDLL=1
+
+!include $(WXWIN)\src\makevc.env
+
+version:
+ echo $(WXVERSION)$(wxRELEASE_NUMBER)
+
+wxdir:
+ echo $(WXWIN)
+
+cxxflags:
+ echo $(CPPFLAGS) -D__WXMSW__
+
+linkflags:
+ echo $(LINKFLAGS)
+
+libs:
+ echo $(LIBS)
+
+# this one is for import library ( not in wx-config )
+implib:
+ echo $(WXLIB)
--- /dev/null
+package Params::Check;
+
+use strict;
+
+use Carp qw[carp croak];
+use Locale::Maketext::Simple Style => 'gettext';
+
+use Data::Dumper;
+
+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
+ ];
+
+ @ISA = qw[ Exporter ];
+ @EXPORT_OK = qw[check allow last_error];
+
+ $VERSION = '0.25';
+ $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) = @_;
+
+ ### did we get the arguments we need? ###
+ return if !$utmpl or !$href;
+
+ ### sensible defaults ###
+ $verbose ||= $VERBOSE || 0;
+
+ ### clear the current error string ###
+ _clear_error();
+
+ ### 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 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, somethign 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-cicruit 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
+
+{ my $ErrorString = '';
+
+ 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;
+
+ $ErrorString .= $err . "\n";
+ }
+
+ sub _clear_error {
+ $ErrorString = '';
+ }
+
+ sub last_error { $ErrorString }
+}
+
+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-insensitivy 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 AUTHOR
+
+This module by
+Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 Acknowledgements
+
+Thanks to Richard Soderberg for his performance improvements.
+
+=head1 COPYRIGHT
+
+This module is
+copyright (c) 2003,2004 Jos Boumans E<lt>kane@cpan.orgE<gt>.
+All rights reserved.
+
+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:
--- /dev/null
+#!/usr/bin/perl
+package Text::Patch;
+use Exporter;
+our @ISA = qw( Exporter );
+our @EXPORT = qw( patch );
+our $VERSION = '1.1';
+use strict;
+use warnings;
+use Carp;
+
+sub patch
+{
+ my $text = shift;
+ my $diff = shift;
+ my %options;
+
+ if( ref $_[0] eq 'HASH' )
+ {
+ %options = %{ $_[0] };
+ }
+ else
+ {
+ %options = @_;
+ }
+
+ return patch_unified( $text, $diff ) if $options{ 'STYLE' } eq 'Unified';
+ croak "required STYLE option is missing";
+}
+
+sub patch_unified
+{
+ my $text = shift;
+ my $diff = shift;
+
+ my @text = split /^/m, $text;
+ my @diff = split /^/m, $diff;
+
+ my @hunks;
+ my %hunk;
+
+ for( @diff )
+ {
+ #print STDERR ">>> ... $_";
+ if( /^\@\@\s*-(\d+),(\d+)/ )
+ {
+ #print STDERR ">>> *** HUNK!\n";
+ push @hunks, { %hunk };
+ %hunk = ();
+ $hunk{ FROM } = $1 - 1; # diff is 1-based
+ $hunk{ LEN } = $2;
+ $hunk{ DATA } = [];
+ }
+ push @{ $hunk{ DATA } }, $_;
+ }
+ push @hunks, { %hunk }; # push last hunk
+ shift @hunks; # first is always empty
+
+ for my $hunk ( reverse @hunks )
+ {
+ #use Data::Dumper;
+ #print STDERR Dumper( $hunk );
+ my @pdata;
+ for( @{ $hunk->{ DATA } } )
+ {
+ next unless s/^([ \-\+])//;
+ #print STDERR ">>> ($1) $_";
+ next if $1 eq '-';
+ push @pdata, $_;
+ }
+ splice @text, $hunk->{ FROM }, $hunk->{ LEN }, @pdata;
+ }
+
+ return join '', @text;
+}
+
+=pod
+
+=head1 NAME
+
+Text::Patch - Patches text with given patch
+
+=head1 SYNOPSIS
+
+ use Text::Patch;
+
+ $output = patch( $source, $diff, STYLE => "Unified" );
+
+ use Text::Diff;
+
+ $src = ...
+ $dst = ...
+
+ $diff = diff( $src, $dst, { STYLE => 'Unified' } );
+
+ $out = patch( $src, $diff, { STYLE => 'Unified' } );
+
+ print "Patch successful" if $out eq $dst;
+
+=head1 DESCRIPTION
+
+Text::Patch combines source text with given diff (difference) data.
+Diff data is produced by Text::Diff module or by the standard diff
+utility (man diff, see -u option).
+
+=over 4
+
+=item patch( $source, $diff, options... )
+
+First argument is source (original) text. Second is the diff data.
+Third argument can be either hash reference with options or all the
+rest arguments will be considered patch options:
+
+ $output = patch( $source, $diff, STYLE => "Unified", ... );
+
+ $output = patch( $source, $diff, { STYLE => "Unified", ... } );
+
+Options are:
+
+ STYLE => 'Unified'
+
+Note that currently only 'Unified' diff format is supported!
+STYLE names are the same described in Text::Diff.
+
+The 'Unified' diff format looks like this:
+
+ @@ -1,7 +1,6 @@
+ -The Way that can be told of is not the eternal Way;
+ -The name that can be named is not the eternal name.
+ The Nameless is the origin of Heaven and Earth;
+ -The Named is the mother of all things.
+ +The named is the mother of all things.
+ +
+ Therefore let there always be non-being,
+ so we may see their subtlety,
+ And let there always be being,
+ @@ -9,3 +8,6 @@
+ The two are the same,
+ But after they are produced,
+ they have different names.
+ +They both may be called deep and profound.
+ +Deeper and more profound,
+ +The door of all subtleties!
+
+
+=back
+
+=head1 LIMITS
+
+ Only 'Unified' diff format is supported.
+
+=head1 TODO
+
+ Interfaces with files, arrays, etc.
+ Diff formats support: "Context", "OldStyle" (As noted in Text::Diff)
+
+=head1 AUTHOR
+
+ Vladi Belperchinov-Shabanski "Cade"
+
+ <cade@biscom.net> <cade@datamax.bg> <cade@cpan.org>
+
+ http://cade.datamax.bg
+
+=head1 VERSION
+
+ $Id: Patch.pm,v 1.2 2004/12/07 21:26:41 cade Exp $
+
+=cut
+
--- /dev/null
+#!/usr/bin/perl -w
+
+eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
+ if 0; # not running under some shell
+
+# patch - apply a diff file to an original
+#
+# mail tgy@chocobo.org < bug_reports
+#
+# Copyright (c) 1999 Moogle Stuffy Software. All rights reserved.
+#
+# You may play with this software in accordance with the Perl Artistic License.
+
+use strict;
+
+my $VERSION = '0.25';
+
+$|++;
+
+if (@ARGV && $ARGV[0] eq '-v') {
+ print split /^ /m, qq[
+ This is patch $VERSION written in Perl.
+
+ Copyright (c) 1999 Moogle Stuffy Software. All rights reserved.
+
+ You may play with this software in accordance with the
+ Perl Artistic License.
+ ];
+ exit;
+}
+
+my ($patchfile, @options);
+
+if (@ARGV) {
+ require Getopt::Long;
+ Getopt::Long::Configure(qw/
+ bundling
+ no_ignore_case
+ /);
+
+ # List of supported options and acceptable arguments.
+ my @desc = qw/
+ suffix|b=s force|f reject-file|r=s
+ prefix|B=s batch|t reverse|R
+ context|c fuzz|F=i silent|quiet|s
+ check|C ignore-whitespace|l skip|S
+ directory|d=s normal|n unified|u
+ ifdef|D=s forward|N version|v
+ ed|e output|o=s version-control|V=s
+ remove-empty-files|E strip|p=i debug|x=i
+ /;
+
+ # Each patch may have its own set of options. These are separated by
+ # a '+' on the command line.
+ my @opts;
+ for (@ARGV, '+') { # Now '+' terminated instead of separated...
+ if ($_ eq '+') {
+ push @options, [splice @opts, 0];
+ } else {
+ push @opts, $_;
+ }
+ }
+
+ # Parse each set of options into a hash.
+ my $next = 0;
+ for (@options) {
+ local @ARGV = @$_;
+ Getopt::Long::GetOptions(\my %opts, @desc);
+ $opts{origfile} = shift;
+ $_ = \%opts;
+ $patchfile = shift unless $next++;
+ }
+}
+
+$patchfile = '-' unless defined $patchfile;
+
+my $patch = Patch->new(@options);
+
+tie *PATCH, Pushback => $patchfile or die "Can't open '$patchfile': $!";
+
+# Extract patches from patchfile. We unread/pushback lines by printing to
+# the PATCH filehandle: 'print PATCH'
+PATCH:
+while (<PATCH>) {
+ if (/^(\s*)(\@\@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? \@\@\n)/) {
+ # UNIFIED DIFF
+ my ($space, $range, $i_start, $i_lines, $o_start, $o_lines) =
+ ($1, $2, $3, $4 || 1, $5, $6 || 1);
+ $patch->bless('unified') or next PATCH;
+ my @hunk;
+ my %saw = map {$_, 0} split //, ' +-';
+ my $re = qr/^$space([ +-])/;
+ while (<PATCH>) {
+ unless (s/$re/$1/) {
+ $patch->note("Short hunk ignored.\n");
+ $patch->reject($range, @hunk);
+ print PATCH;
+ next PATCH;
+ }
+ push @hunk, $_;
+ $saw{$1}++;
+ last if $saw{'-'} + $saw{' '} == $i_lines
+ && $saw{'+'} + $saw{' '} == $o_lines;
+ }
+ $patch->apply($i_start, $o_start, @hunk)
+ or $patch->reject($range, @hunk);
+ } elsif (/^(\s*)\*{15}$/) {
+ # CONTEXT DIFF
+ my $space = $1;
+ $_ = <PATCH>;
+ unless (/^$space(\*\*\* (\d+)(?:,(\d+))? \*\*\*\*\n)/) {
+ print PATCH;
+ next PATCH;
+ }
+ my ($i_range, $i_start, $i_end, @i_hunk) = ($1, $2, $3 || $2);
+ my ($o_range, $o_start, $o_end, @o_hunk);
+ $patch->bless('context') or next PATCH;
+ my $o_hunk = qr/^$space(--- (\d+)(?:,(\d+))? ----\n)/;
+ my $re = qr/^$space([ !-] )/;
+ $_ = <PATCH>;
+ if (/$o_hunk/) {
+ ($o_range, $o_start, $o_end) = ($1, $2, $3 || $2);
+ } else {
+ print PATCH;
+ for ($i_start..$i_end) {
+ $_ = <PATCH>;
+ unless (s/$re/$1/) {
+ $patch->note("Short hunk ignored.\n");
+ $patch->reject($i_range, @i_hunk);
+ print PATCH;
+ next PATCH;
+ }
+ push @i_hunk, $_;
+ }
+ $_ = <PATCH>;
+ unless (/$o_hunk/) {
+ $patch->note("Short hunk ignored...no second line range.\n");
+ $patch->reject($i_range, @i_hunk);
+ print PATCH;
+ next PATCH;
+ }
+ ($o_range, $o_start, $o_end) = ($1, $2, $3 || $2);
+ }
+ $re = qr/^$space([ !+] )/;
+ $_ = <PATCH>;
+ if (/^$space\*{15}$/) {
+ print PATCH;
+ } else {
+ print PATCH;
+ for ($o_start..$o_end) {
+ $_ = <PATCH>;
+ unless (s/$re/$1/) {
+ $patch->note("Short hunk ignored.\n");
+ $patch->reject($i_range, @i_hunk, $o_range, @o_hunk);
+ print PATCH;
+ next PATCH;
+ }
+ push @o_hunk, $_;
+ }
+ }
+ $patch->apply($i_start, $o_start, \@i_hunk, \@o_hunk)
+ or $patch->reject($i_range, @i_hunk, $o_range, @o_hunk);
+ } elsif (/^(\s*)((\d+)(?:,(\d+))?([acd])(\d+)(?:,(\d+))?\n)/) {
+ # NORMAL DIFF
+ my ($space, $range, $i_start, $i_end, $cmd, $o_start, $o_end) =
+ ($1, $2, $3, $4 || $3, $5, $6, $7 || $6);
+ $patch->bless('normal') or next PATCH;
+ my (@d_hunk, @a_hunk);
+ my $d_re = qr/^$space< /;
+ my $a_re = qr/^$space> /;
+ if ($cmd eq 'c' || $cmd eq 'd') {
+ for ($i_start..$i_end) {
+ $_ = <PATCH>;
+ unless (s/$d_re//) {
+ $patch->note("Short hunk ignored.\n");
+ $patch->reject($range, @d_hunk);
+ print PATCH;
+ next PATCH;
+ }
+ push @d_hunk, $_;
+ }
+ }
+ if ($cmd eq 'c') {
+ $_ = <PATCH>;
+ unless ($_ eq "---\n") {
+ $patch->note("Short hunk ignored...no '---' separator.\n");
+ $patch->reject($range, @d_hunk);
+ print PATCH;
+ next PATCH;
+ }
+ }
+ if ($cmd eq 'c' || $cmd eq 'a') {
+ for ($o_start..$o_end) {
+ $_ = <PATCH>;
+ unless (s/$a_re//) {
+ $patch->note("Short hunk ignored.\n");
+ $patch->reject($range, @d_hunk, "---\n", @a_hunk);
+ print PATCH;
+ next PATCH;
+ }
+ push @a_hunk, $_;
+ }
+ }
+ $patch->apply($i_start, $o_start, $cmd, \@d_hunk, \@a_hunk)
+ or $patch->reject($range, @d_hunk, "---\n", @a_hunk);
+ } elsif (/^(\s*)\d+(?:,\d+)?[acd]$/) {
+ # ED SCRIPT
+ my $space = qr/^$1/;
+ $patch->bless('ed') or next PATCH;
+ print PATCH;
+ my @cmd;
+ ED:
+ while (<PATCH>) {
+ unless (s/$space// && m!^\d+(?:,\d+)?([acd]|s\Q/^\.\././\E)$!) {
+ print PATCH;
+ last ED;
+ }
+ push @cmd, [$_];
+ $1 =~ /^[ac]$/ or next;
+ while (<PATCH>) {
+ unless (s/$space//) {
+ print PATCH;
+ last ED;
+ }
+ push @{$cmd[-1]}, $_;
+ last if /^\.$/;
+ }
+ }
+ $patch->apply(@cmd) or $patch->reject(map @$_, @cmd);
+ } else {
+ # GARBAGE
+ $patch->garbage($_);
+ }
+}
+
+close PATCH;
+
+if (ref $patch eq 'Patch') {
+ $patch->note("Hmm... I can't seem to find a patch in there anywhere.\n");
+} else {
+ $patch->end;
+}
+
+$patch->note("done\n");
+exit $patch->error ? 1 : 0;
+
+END {
+ close STDOUT || die "$0: can't close stdout: $!\n";
+ $? = 1 if $? == 255; # from die
+}
+
+
+
+
+
+package Patch;
+
+use vars qw/$ERROR/;
+
+# Class data.
+BEGIN {
+ $ERROR = 0;
+}
+
+sub import {
+ no strict 'refs';
+ *{caller() . '::throw'} = \&throw;
+ @{caller() . '::ISA'} = 'Patch';
+}
+
+# Simple throw/catch error handling.
+sub throw {
+ $@ = join '', @_;
+ $@ .= sprintf " at %s line %d\n", (caller)[1..2] unless $@ =~ /\n\z/;
+ goto CATCH;
+}
+
+# Prints a prompt message and returns response.
+sub prompt {
+ print @_;
+ local $_ = <STDIN>;
+ chomp;
+ $_;
+}
+
+# Constructs a Patch object.
+sub new {
+ my $class = shift;
+ my %copy = %{$_[0]} if ref $_[0];
+ bless {
+ %copy,
+ options => [@_],
+ garbage => [],
+ rejects => [],
+ }, $class;
+}
+
+# Blesses object into a subclass.
+sub bless {
+ my $type = pop;
+ my $class = "Patch::\u$type";
+
+ my ($options, $garbage) = @{$_[0]}{'options', 'garbage'};
+
+ # New hunk, same patch.
+ $_[0]{hunk}++, return 1 if $_[0]->isa($class) && ! @$garbage;
+
+ # Clean up previous Patch object first.
+ $_[0]->end;
+
+ # Get options/switches for new patch.
+ my $self = @$options > 1 ? shift @$options :
+ @$options == 1 ? { %{$options->[0]} } :
+ {};
+ bless $self, $class;
+
+ # 'options' and 'garbage' are probably better off as class
+ # data. Why didn't I do that before? But it's not broken
+ # so I'm not fixing it.
+ $self->{options} = $options; # @options
+ $self->{garbage} = []; # garbage lines
+ $self->{i_pos} = 0; # current position in 'in' file
+ $self->{o_pos} = 0; # just for symmetry
+ $self->{i_lines} = 0; # lines read in 'in' file
+ $self->{o_lines} = 0; # lines written to 'out' file
+ $self->{hunk} = 1; # current hunk number
+ $self->{rejects} = []; # save rejected hunks here
+ $self->{fuzz} = 2 unless defined $self->{fuzz} && $self->{fuzz} >= 0;
+ $self->{ifdef} = '' unless defined $self->{ifdef};
+
+ # Skip patch?
+ $self->{skip} and $self->skip;
+
+ # -c, -e, -n, -u
+ $self->{$_} and $type eq $_ || $self->skip("Not a $_ diff!\n")
+ for qw/context ed normal unified/;
+
+ # Speculate to user.
+ my $n = $type eq 'ed' ? 'n' : '';
+ $self->note("Hmm... Looks like a$n $type diff to me...\n");
+
+ # Change directories.
+ for ($self->{directory}) {
+ defined or last;
+ chdir $_ or $self->skip("Can't chdir '$_': $!\n");
+ }
+
+ # Get original file to patch...
+ my $orig = $self->{origfile}; # ...from -o
+
+ unless (defined $orig) {
+ $orig = $self->rummage($garbage); # ...from leading garbage
+ if (defined $orig) {
+ $self->note(
+ "The text leading up to this was:\n",
+ "--------------------------\n",
+ map("|$_", @$garbage),
+ "--------------------------\n",
+ );
+ } else {
+ $self->skip if $self->{force} || $self->{batch};
+ $orig = prompt ('File to patch: '); # ...from user
+ }
+ }
+
+ # Make sure original file exists.
+ if ($self->{force} || $self->{batch}) {
+ -e $orig or $self->skip;
+ } else {
+ until (-e $orig) {
+ $self->skip unless prompt (
+ 'No file found--skip this patch? [n] '
+ ) =~ /^[yY]/;
+ $orig = prompt (
+ 'File to patch: '
+ );
+ }
+ }
+
+ my ($in, $out);
+
+ # Create backup file. I have no clue what Plan A is really supposed to be.
+ if ($self->{check}) {
+ $self->note("Checking patch against file $orig using Plan C...\n");
+ ($in, $out) = ($orig, '');
+ } elsif (defined $self->{output}) {
+ $self->note("Patching file $orig using Plan T...\n");
+ local $_ = $self->{output};
+ $self->skip if -e && not rename $_, $self->backup($_) and
+ $self->{force} || $self->{batch} || prompt (
+ 'Failed to backup output file--skip this patch? [n] '
+ ) =~ /^[yY]/;
+ ($in, $out) = ($orig, $self->{output});
+ } else {
+ $self->note("Patching file $orig using Plan A...\n");
+ my $back = $self->backup($orig);
+ if (rename $orig, $back) {
+ ($in, $out) = ($back, $orig);
+ } else {
+ $self->skip unless $self->{force} || $self->{batch} or prompt (
+ 'Failed to backup original file--skip this patch? [n] '
+ ) !~ /^[yY]/;
+ ($in, $out) = ($orig, $orig);
+ }
+ }
+
+ # Open original file.
+ local *IN;
+ open IN, "< $in" or $self->skip("Couldn't open INFILE: $!\n");
+ binmode IN;
+ $self->{i_fh} = *IN; # input filehandle
+ $self->{i_file} = $in; # input filename
+
+ # Like /dev/null
+ local *NULL;
+ tie *NULL, 'Dev::Null';
+
+ # Open output file.
+ if ($self->{check}) {
+ $self->{o_fh} = \*NULL; # output filehandle
+ $self->{d_fh} = \*NULL; # ifdef filehandle
+ } else {
+ local *OUT;
+ open OUT, "+> $out" or $self->skip("Couldn't open OUTFILE: $!\n");
+ binmode OUT;
+ $|++, select $_ for select OUT;
+ $self->{o_fh} = *OUT;
+ $self->{o_file} = $out;
+ $self->{d_fh} = length $self->{ifdef} ? *OUT : \*NULL;
+ }
+
+ $self->{'reject-file'} = "$out.rej" unless defined $self->{'reject-file'};
+
+ # Check for 'Prereq:' line.
+ unless ($self->{force}) {
+ my $prereq = (map /^Prereq:\s*(\S+)/, @$garbage)[-1];
+ if (defined $prereq) {
+ $prereq = qr/\b$prereq\b/;
+ my $found;
+ while (<IN>) {
+ $found++, last if /$prereq/;
+ }
+ seek IN, 0, 0 or $self->skip("Couldn't seek INFILE: $!\n");
+ $self->skip if not $found and $self->{batch} || prompt (
+ 'File does not match "Prereq: $1"--skip this patch? [n] '
+ ) =~ /^[yY]/;
+ }
+ }
+
+ SKIP:
+ $_[0] = $self;
+}
+
+# Skip current patch.
+sub skip {
+ my $self = shift;
+ $self->note(@_) if @_;
+ $self->note("Skipping patch...\n");
+ $self->{skip}++;
+ goto SKIP;
+}
+
+# Let user know what's happening.
+sub note {
+ my $self = shift;
+ print @_ unless $self->{silent} || $self->{skip};
+}
+
+# Add to lines of leading garbage.
+sub garbage {
+ push @{shift->{garbage}}, @_;
+}
+
+# Add to rejected hunks.
+sub reject {
+ push @{shift->{rejects}}, [@_];
+}
+
+# Total number of hunks rejected.
+sub error {
+ $ERROR;
+}
+
+# End of patch clean up.
+sub end {
+ my $self = shift;
+
+ return if $self->{skip} || ref $self eq 'Patch';
+
+ $self->print_tail;
+ $self->print_rejects;
+ $self->remove_empty_files;
+}
+
+# Output any lines left in input handle.
+sub print_tail {
+ my $self = shift;
+ print {$self->{o_fh}} readline $self->{i_fh};
+}
+
+# Output rejected hunks to reject file.
+sub print_rejects {
+ my $self = shift;
+ my @rej = @{$self->{rejects}};
+
+ $ERROR += @rej;
+
+ @rej or return;
+
+ $self->note(
+ @rej . " out of $self->{hunk} hunks ignored--saving rejects to ",
+ "$self->{'reject-file'}\n\n"
+ );
+ if (open REJ, "> $self->{'reject-file'}") {
+ print REJ map @$_, @rej;
+ close REJ;
+ } else {
+ $self->note("Couldn't open reject file: $!\n");
+ }
+}
+
+# Remove empty files... d'uh
+sub remove_empty_files {
+ my $self = shift;
+ $self->{'remove-empty-files'} or return;
+ close $self->{o_fh};
+ defined && -z and $self->note(
+ unlink($_)
+ ? "Removed empty file '$_'.\n"
+ : "Can't remove empty file '$_': $!\n"
+ ) for $self->{o_file};
+}
+
+# Go through leading garbage looking for name of file to patch.
+sub rummage {
+ my ($self, $garbage) = @_;
+
+ for (reverse @$garbage) {
+ /^Index:\s*(\S+)/ or next;
+ my $file = $self->strip($1);
+ -e $file or next;
+ return $file;
+ }
+
+ return;
+}
+
+# Strip slashes from path.
+sub strip {
+ my $self = shift;
+ my $path = shift;
+ $path = $_ unless defined $path;
+
+ local $^W;
+ if (not exists $self->{strip}) {
+ unless ($path =~ m!^/!) {
+ $path =~ m!^(.*/)?(.+)$!;
+ $path = $2 unless -e $1;
+ }
+ } elsif ($self->{strip} > 0) {
+ my $i = $self->{strip};
+ $path =~ s![^/]*/!! while $i--;
+ }
+
+ $path;
+}
+
+# Create a backup file from options.
+sub backup {
+ my ($self, $file) = @_;
+ $file =
+ $self->{prefix} ? "$self->{prefix}$file" :
+ $self->{'version-control'} ? $self->version_control_backup(
+ $file, $self->{'version-control'}) :
+ $self->{suffix} ? "$file$self->{suffix}" :
+ $ENV{VERSION_CONTROL} ? $self->version_control_backup(
+ $file, $ENV{VERSION_CONTROL}) :
+ $ENV{SIMPLE_BACKUP_SUFFIX} ? "$file$ENV{SIMPLE_BACKUP_SUFFIX}" :
+ "$file.orig"; # long filename
+ my ($name, $extension) = $file =~ /^(.+)(?:\.([^.]+))?$/;
+ my $ext = $extension;
+ while (-e $file) {
+ if ($ext !~ s/[a-z]/\U$1/) {
+ $ext = $extension;
+ $name =~ s/.// or die "Couldn't create a good backup filename.\n";
+ }
+ $file = $name . $ext;
+ }
+ $file;
+}
+
+# Create a backup file using version control.
+sub version_control_backup {
+ my ($self, $file, $version) = @_;
+ if ($version =~ /^(?:ne|s)/) { # never|simple
+ $file .= $self->suffix_backup;
+ } else {
+ opendir DIR, '.' or die "Can't open dir '.': $!";
+ my $re = qr/^\Q$file\E\.~(\d+)~$/;
+ my @files = map /$re/, readdir DIR;
+ close DIR;
+ if (@files) { # version number already exists
+ my $next = 1 + (sort {$a <=> $b} @files)[-1];
+ $file .= ".~$next~";
+ } else { # t|numbered # nil|existing
+ $file .= $version =~ /^(?:t|nu)/ ? '.~1~' : $self->suffix_backup;
+ }
+ }
+ $file;
+}
+
+# Create a backup file using suffix.
+sub suffix_backup {
+ my $self = shift;
+ return $self->{suffix} if $self->{suffix};
+ return $ENV{SIMPLE_BACKUP_SUFFIX} if $ENV{SIMPLE_BACKUP_SUFFIX};
+ return '.orig';
+}
+
+# Apply a patch hunk. The default assumes a unified diff.
+sub apply {
+ my ($self, $i_start, $o_start, @hunk) = @_;
+
+ $self->{skip} and throw 'SKIP...ignore this patch';
+
+ if ($self->{reverse}) {
+ my $not = { qw/ + - - + / };
+ s/^([+-])/$not->{$1}/ for @hunk;
+ }
+
+ my @context = map /^[ -](.*)/s, @hunk;
+ my $position;
+ my $fuzz = 0;
+
+ if (@context) {
+ # Find a place to apply hunk where context matches.
+ for (0..$self->{fuzz}) {
+ my ($pos, $lines) = ($self->{i_pos}, 0);
+ while (1) {
+ ($pos, $lines) = $self->index(\@context, $pos, $lines) or last;
+ my $line = $self->{i_lines} + $lines + 1;
+ if ($line >= $i_start) {
+ my $off = $line - $i_start;
+ $position = [$lines, $off]
+ unless $position && $position->[-1] < $off;
+ last;
+ }
+ $position = [$lines, $i_start - $line];
+ $pos++, $lines = 1;
+ }
+ last if $position;
+ last unless $hunk[0] =~ /^ / && shift @hunk
+ or $hunk[-1] =~ /^ / && pop @hunk;
+ @context = map /^[ -](.*)/s, @hunk or last;
+ $fuzz++;
+ }
+ # If there's nowhere to apply the first hunk, we check if it is
+ # a reversed patch.
+ if ($self->{hunk} == 1) {
+ if ($self->{reverse_check}) {
+ $self->{reverse_check} = 0;
+ if ($position) {
+ unless ($self->{batch}) {
+ local $_ = prompt (
+ 'Reversed (or previously applied) patch detected!',
+ ' Assume -R? [y] '
+ );
+ if (/^[nN]/) {
+ $self->{reverse} = 0;
+ $position = 0;
+ prompt ('Apply anyway? [n] ') =~ /^[yY]/
+ or throw 'SKIP...ignore this patch';
+ }
+ }
+ } else {
+ throw 'SKIP...ignore this patch' if $self->{forward};
+ }
+ } else {
+ unless ($position || $self->{reverse} || $self->{force}) {
+ $self->{reverse_check} = 1;
+ $self->{reverse} = 1;
+ shift;
+ return $self->apply(@_);
+ }
+ }
+ }
+ $position or throw "Couldn't find anywhere to put hunk.\n";
+ } else {
+ # No context. Use given position.
+ $position = [$i_start - $self->{i_lines} - 1]
+ }
+
+ my $in = $self->{i_fh};
+ my $out = $self->{o_fh};
+ my $def = $self->{d_fh};
+ my $ifdef = $self->{ifdef};
+
+ # Make sure we're where we left off.
+ seek $in, $self->{i_pos}, 0 or throw "Couldn't seek INFILE: $!";
+
+ my $line = $self->{o_lines} + $position->[0] + 1;
+ my $off = $line - $o_start;
+
+ # Set to new position.
+ $self->{i_lines} += $position->[0];
+ $self->{o_lines} += $position->[0];
+
+ print $out scalar <$in> while $position->[0]--;
+
+ # Apply hunk.
+ my $was = ' ';
+ for (@hunk) {
+ /^([ +-])(.*)/s;
+ my $cmd = substr $_, 0, 1, '';
+ if ($cmd eq '-') {
+ $cmd eq $was or print $def "#ifndef $ifdef\n";
+ print $def scalar <$in>;
+ $self->{i_lines}++;
+ } elsif ($cmd eq '+') {
+ $cmd eq $was or print $def $was eq ' ' ?
+ "#ifdef $ifdef\n" :
+ "#else\n";
+ print $out $_;
+ $self->{o_lines}++;
+ } else {
+ $cmd eq $was or print $def "#endif /* $ifdef */\n";
+ print $out scalar <$in>;
+ $self->{i_lines}++;
+ $self->{o_lines}++;
+ }
+ $was = $cmd;
+ }
+ $was eq ' ' or print $def "#endif /* $ifdef */\n";
+
+ # Keep track of where we leave off.
+ $self->{i_pos} = tell $in;
+
+ # Report success to user.
+ $self->note("Hunk #$self->{hunk} succeeded at $line.\n");
+ $self->note(" Offset: $off\n") if $off;
+ $self->note(" Fuzz: $fuzz\n") if $fuzz;
+
+ return 1;
+
+ # Or report failure.
+ CATCH:
+ $self->{skip}++ if $@ =~ /^SKIP/;
+ $self->note( $self->{skip}
+ ? "Hunk #$self->{hunk} ignored at $o_start.\n"
+ : "Hunk #$self->{hunk} failed--$@"
+ );
+ return;
+}
+
+# Find where an array of lines matches in a file after a given position.
+# $match => [array of lines]
+# $pos => search after this position and...
+# $lines => ...after this many lines after $pos
+# Returns the position of the match and the number of lines between the
+# starting and matching positions.
+sub index {
+ my ($self, $match, $pos, $lines) = @_;
+ my $in = $self->{i_fh};
+
+ seek $in, $pos, 0 or throw "Couldn't seek INFILE [$in, 0, $pos]: $!";
+ <$in> while $lines--;
+
+ if ($self->{'ignore-whitespace'}) {
+ s/\s+/ /g for @$match;
+ }
+
+ my $tell = tell $in;
+ my $line = 0;
+
+ while (<$in>) {
+ s/\s+/ /g if $self->{'ignore-whitespace'};
+ if ($_ eq $match->[0]) {
+ my $fail;
+ for (1..$#$match) {
+ my $line = <$in>;
+ $line =~ s/\s+/ /g if $self->{'ignore-whitespace'};
+ $line eq $match->[$_] or $fail++, last;
+ }
+ if ($fail) {
+ seek $in, $tell, 0 or throw "Couldn't seek INFILE: $!";
+ <$in>;
+ } else {
+ return ($tell, $line);
+ }
+ }
+ $line++;
+ $tell = tell $in;
+ }
+
+ return;
+
+ CATCH: $self->note($@), return;
+}
+
+
+
+
+package Patch::Context;
+
+BEGIN { Patch->import }
+
+# Convert hunk to unified diff, then apply.
+sub apply {
+ my ($self, $i_start, $o_start, $i_hunk, $o_hunk) = @_;
+
+ my @hunk;
+ my @i_hunk = @$i_hunk;
+ my @o_hunk = @$o_hunk;
+
+ s/^(.) /$1/ for @i_hunk, @o_hunk;
+
+ while (@i_hunk and @o_hunk) {
+ my ($i, $o) = (shift @i_hunk, shift @o_hunk);
+ if ($i eq $o) {
+ push @hunk, $i;
+ next;
+ }
+ while ($i =~ s/^[!-]/-/) {
+ push @hunk, $i;
+ $i = shift @i_hunk;
+ }
+ while ($o =~ s/^[!+]/+/) {
+ push @hunk, $o;
+ $o = shift @o_hunk;
+ }
+ push @hunk, $i;
+ }
+ push @hunk, @i_hunk, @o_hunk;
+
+ $self->SUPER::apply($i_start, $o_start, @hunk);
+}
+
+# Check for filename in diff header, then in 'Index:' line.
+sub rummage {
+ my ($self, $garbage) = @_;
+
+ my @files = grep -e, map $self->strip,
+ map /^\s*(?:\*\*\*|---) (\S+)/, @$garbage[-1, -2];
+
+ my $file =
+ @files == 1 ? $files[0] :
+ @files == 2 ? $files[length $files[0] > length $files[1]] :
+ $self->SUPER::rummage($garbage);
+
+ return $file;
+}
+
+
+
+
+package Patch::Ed;
+
+BEGIN { Patch->import }
+
+# Pipe ed script to ed or try to manually process.
+sub apply {
+ my ($self, @cmd) = @_;
+
+ $self->{skip} and throw 'SKIP...ignore this patch';
+
+ my $out = $self->{o_fh};
+
+ $self->{check} and goto PLAN_J;
+
+ # We start out by adding a magic line to our output. If this line
+ # is still there after piping to ed, then ed failed. We do this
+ # because win32 will silently fail if there is no ed program.
+ my $magic = "#!/i/want/a/moogle/stuffy\n";
+ print $out $magic;
+
+ # Pipe to ed.
+ eval {
+ local $SIG{PIPE} = sub { die 'Pipe broke...' };
+ local $SIG{CHLD} = sub { die 'Bad child...' };
+ open ED, "| ed - -s $self->{i_file}" or die "Couldn't fork ed: $!";
+ print ED map @$_, @cmd or die "Couldn't print ed: $!";
+ print ED "1,\$w $self->{o_file}" or die "Couldn't print ed: $!";
+ close ED or die "Couldn't close ed: $?";
+ };
+
+ # Did pipe to ed work?
+ unless ($@ or <$out> ne $magic) {
+ $self->note("Hunk #$self->{hunk} succeeded at 1.\n");
+ return 1;
+ }
+
+ # Erase any trace of magic line.
+ truncate $out, 0 or throw "Couldn't truncate OUT: $!";
+ seek $out, 0, 0 or throw "Couldn't seek OUT: $!";
+
+ # Try to apply ed script by hand.
+ $self->note("Pipe to ed failed. Switching to Plan J...\n");
+
+ PLAN_J:
+
+ # Pre-process each ed command. Ed diffs are reversed (so that each
+ # command doesn't end up changing the line numbers of subsequent
+ # commands). But we need to apply diffs in a forward direction because
+ # our filehandles are oriented that way. So we calculate the @offset
+ # in line number that this will cause as we go.
+ my @offset;
+ for (my $i = 0; $i < @cmd; $i++) {
+ my @hunk = @{$cmd[$i]};
+
+ shift(@hunk) =~ m!^(\d+)(?:,(\d+))?([acds])!
+ or throw "Unable to parse ed script.";
+
+ my ($start, $end, $cmd) = ($1, $2 || $1, $3);
+
+ # We don't parse substitution commands and assume they all mean
+ # s/\.\././ even if they really mean s/\s+// or such. And we
+ # blindly apply the command to the previous hunk.
+ if ($cmd eq 's') {
+ $cmd[$i] = '';
+ s/\.\././ for @{$cmd[$i-1][3]};
+ next;
+ }
+
+ # Remove '.' line used to terminate hunks.
+ pop @hunk if $cmd =~ /^[ac]/;
+
+ # Calculate where we actually start and end by removing any offsets.
+ my ($s, $e) = ($start, $end);
+ for (@offset) {
+ $start > $_->[0] or next;
+ $s -= $_->[1];
+ $e -= $_->[1];
+ }
+
+ # Add to the total offset.
+ push @offset, [$start, map {
+ /^c/ ? scalar @hunk - ($end + 1 - $start) :
+ /^a/ ? scalar @hunk :
+ /^d/ ? $end + 1 - $start :
+ 0
+ } $cmd];
+
+ # Post-processed command.
+ $cmd[$i] = [$s, $e, $cmd, \@hunk, $i];
+ }
+
+ # Sort based on calculated start positions or on original order.
+ # Substitution commands have already been applied and are ignored.
+ @cmd = sort {
+ $a->[0] <=> $b->[0] || $a->[-1] <=> $b->[-1]
+ } grep ref, @cmd;
+
+ my $in = $self->{i_fh};
+ my $def = $self->{d_fh};
+ my $ifdef = $self->{ifdef};
+
+ # Apply each command.
+ for (@cmd) {
+ my ($start, $end, $cmd, $hunk) = @$_;
+ if ($cmd eq 'a') {
+ my $diff = $start - $self->{i_lines};
+ print $out scalar <$in> while $diff--;
+ print $def "#ifdef $ifdef\n";
+ print $out @$hunk;
+ $self->{i_lines} = $start;
+ } elsif ($cmd eq 'd') {
+ my $diff = $start - $self->{i_lines} - 1;
+ print $out scalar <$in> while $diff--;
+ print $def "#ifndef $ifdef\n";
+ print $def scalar <$in> for $start..$end;
+ $self->{i_lines} = $end;
+ } elsif ($cmd eq 'c') {
+ my $diff = $start - $self->{i_lines} - 1;
+ print $out scalar <$in> while $diff--;
+ print $def "#ifndef $ifdef\n";
+ print $def scalar <$in> for $start..$end;
+ print $def "#else\n";
+ print $out @$hunk;
+ $self->{i_lines} = $end;
+ }
+ print $def "#endif /* $ifdef */\n";
+ }
+
+ # Output any lines left in input handle.
+ print $out readline $in;
+
+ # Report success to user.
+ for (my $i = 0; $i < @cmd; $i++) {
+ $self->note(
+ 'Hunk #', $i+1, ' succeeded at ',
+ $cmd[$i - not ref $cmd[$i]][0], "\n",
+ );
+ }
+
+ return 1;
+
+ # Or report failure.
+ CATCH:
+ $self->{skip}++ if $@ =~ /^SKIP/;
+ $self->note( $self->{skip}
+ ? "Hunk #$self->{hunk} ignored at 1.\n"
+ : "Hunk #$self->{hunk} failed--$@"
+ );
+ return;
+}
+
+# End of patch clean up. $self->print_tail is omitted because ed diffs are
+# applied all at once rather than one hunk at a time.
+sub end {
+ my $self = shift;
+
+ return if $self->{skip};
+
+ $self->print_rejects;
+ $self->remove_empty_files;
+}
+
+
+
+
+package Patch::Normal;
+
+BEGIN { Patch->import }
+
+# Convert hunk to unified diff, then apply.
+sub apply {
+ my ($self, $i_start, $o_start, $cmd, $d_hunk, $a_hunk) = @_;
+
+ $i_start++ if $cmd eq 'a';
+ $o_start++ if $cmd eq 'd';
+ my @hunk;
+ push @hunk, map "-$_", @$d_hunk;
+ push @hunk, map "+$_", @$a_hunk;
+
+ $self->SUPER::apply($i_start, $o_start, @hunk);
+}
+
+
+
+
+package Patch::Unified;
+
+BEGIN { Patch->import }
+
+# Check for filename in diff header, then in 'Index:' line.
+sub rummage {
+ my ($self, $garbage) = @_;
+
+ my @files = grep -e, map $self->strip,
+ map /^\s*(?:---|\+\+\+) (\S+)/, @$garbage[-1, -2];
+
+ my $file =
+ @files == 1 ? $files[0] :
+ @files == 2 ? $files[length $files[0] > length $files[1]] :
+ $self->SUPER::rummage($garbage);
+
+ return $file;
+}
+
+
+
+
+package Pushback;
+
+# Create filehandles that can unread or push lines back into queue.
+
+sub TIEHANDLE {
+ my ($class, $file) = @_;
+ local *FH;
+ open *FH, "< $file" or return;
+ binmode FH;
+ bless [*FH], $class;
+}
+
+sub READLINE {
+ my $self = shift;
+ @$self == 1 ? readline $self->[0] : pop @$self;
+}
+
+sub PRINT {
+ my $self = shift;
+ $self->[1] = shift;
+}
+
+sub CLOSE {
+ my $self = shift;
+ $self = undef;
+}
+
+
+
+
+package Dev::Null;
+
+# Create filehandles that go nowhere.
+
+sub TIEHANDLE { bless \my $null }
+sub PRINT {}
+sub PRINTF {}
+sub WRITE {}
+sub READLINE {''}
+sub READ {''}
+sub GETC {''}
+
+
+
+
+__END__
+
+=head1 NAME
+
+patch - apply a diff file to an original
+
+=head1 SYNOPSIS
+
+B<patch> [options] [origfile [patchfile]] [+ [options] [origfile]]...
+
+but usually just
+
+B<patch> E<lt>patchfile
+
+=head1 DESCRIPTION
+
+I<Patch> will take a patch file containing any of the four
+forms of difference listing produced by the I<diff> program
+and apply those differences to an original file, producing
+a patched version. By default, the patched version is put
+in place of the original, with the original file backed up
+to the same name with the extension ".orig" [see L<"note 1">],
+or as specified
+by the B<-b>, B<-B>, or B<-V> switches. The extension used for
+making backup files may also be specified in the B<SIMPLE>I<_>B<BACKUP>I<_>B<SUFFIX> environment variable, which is overridden by above switches.
+
+If the backup file already exists, B<patch> creates a new
+backup file name by changing the first lowercase letter in
+the last component of the file's name into uppercase. If
+there are no more lowercase letters in the name, it
+removes the first character from the name. It repeats
+this process until it comes up with a backup file that
+does not already exist.
+
+You may also specify where you want the output to go with
+a B<-o> switch; if that file already exists, it is backed up
+first.
+
+If I<patchfile> is omitted, or is a hyphen, the patch will be
+read from standard input.
+
+Upon startup, patch will attempt to determine the type of
+the diff listing, unless over-ruled by a B<-c>, B<-e>, B<-n>, or B<-u>
+switch. Context diffs [see L<"note 2">], unified diffs,
+and normal diffs are applied by the I<patch> program itself,
+while ed diffs are simply fed to the I<ed> editor via a pipe [see L<"note 3">].
+
+I<Patch> will try to skip any leading garbage, apply the
+diff, and then skip any trailing garbage. Thus you could
+feed an article or message containing a diff listing to
+I<patch>, and it should work. If the entire diff is indented
+by a consistent amount, this will be taken into account.
+
+With context diffs, and to a lesser extent with normal
+diffs, I<patch> can detect when the line numbers mentioned in
+the patch are incorrect, and will attempt to find the
+correct place to apply each hunk of the patch. A linear search is made for a
+place where all lines of the context match.
+The hunk is applied at the place nearest the line number mentioned in the
+diff [see L<"note 4">].
+If no such
+place is found, and it's a context diff, and the maximum
+fuzz factor is set to 1 or more, then another scan takes
+place ignoring the first and last line of context. If
+that fails, and the maximum fuzz factor is set to 2 or
+more, the first two and last two lines of context are
+ignored, and another scan is made. (The default maximum
+fuzz factor is 2.) If I<patch> cannot find a place to
+install that hunk of the patch, it will put the hunk out
+to a reject file, which normally is the name of the output
+file plus ".rej" [see L<"note 1">]. The format of the
+rejected hunk remains unchanged [see L<"note 5">].
+
+As each hunk is completed, you will be told whether the
+hunk succeeded or failed, and which line (in the new file)
+I<patch> thought the hunk should go on. If this is different
+from the line number specified in the diff you will be
+told the offset. A single large offset MAY be an indication that a hunk was installed in the wrong place. You
+will also be told if a fuzz factor was used to make the
+match, in which case you should also be slightly suspicious.
+
+If no original file is specified on the command line,
+I<patch> will try to figure out from the leading garbage what
+the name of the file to edit is. In the header of a context diff, the filename is found from lines beginning with
+"***" or "---", with the shortest name of an existing file
+winning. Only context diffs have lines like that, but if
+there is an "Index:" line in the leading garbage, I<patch>
+will try to use the filename from that line. The context
+diff header takes precedence over an Index line. If no
+filename can be intuited from the leading garbage, you
+will be asked for the name of the file to patch.
+
+No attempt is made to look up SCCS or RCS files [see L<"note 6">].
+
+Additionally, if the leading garbage contains a "Prereq: "
+line, I<patch> will take the first word from the
+prerequisites line (normally a version number) and check
+the input file to see if that word can be found. If not,
+I<patch> will ask for confirmation before proceeding.
+
+The upshot of all this is that you should be able to say,
+while in a news interface, the following:
+
+ | patch -d /usr/src/local/blurfl
+
+and patch a file in the blurfl directory directly from the
+article containing the patch.
+
+If the patch file contains more than one patch, I<patch> will
+try to apply each of them as if they came from separate
+patch files. This means, among other things, that it is
+assumed that the name of the file to patch must be determined for each diff listing, and that the garbage before
+each diff listing will be examined for interesting things
+such as filenames and revision level, as mentioned previously. You can give switches (and another original file
+name) for the second and subsequent patches by separating
+the corresponding argument lists by a '+'. (The argument
+list for a second or subsequent patch may not specify a
+new patch file, however.)
+
+I<Patch> recognizes the following switches:
+
+=over
+
+=item -b or --suffix
+
+causes the next argument to be interpreted as the
+backup extension, to be used in place of ".orig" [see L<"note 1">].
+
+=item -B or --prefix
+
+causes the next argument to be interpreted as a prefix to the backup file name. If this argument is
+specified any argument from -b will be ignored.
+
+=item -c or --context
+
+forces I<patch> to interpret the patch file as a context
+diff.
+
+=item -C or --check
+
+checks that the patch would apply cleanly, but does
+not modify anything.
+
+=item -d or --directory
+
+causes I<patch> to interpret the next argument as a
+directory, and cd to it before doing anything else.
+
+=item -D or --ifdef
+
+causes I<patch> to use the "#ifdef...#endif" construct
+to mark changes. The argument following will be used
+as the differentiating symbol. [see L<"note 7">]
+
+=item -e or --ed
+
+forces I<patch> to interpret the patch file as an ed
+script.
+
+=item -E or --remove-empty-files
+
+causes I<patch> to remove output files that are empty
+after the patches have been applied.
+
+=item -f or --force
+
+forces I<patch> to assume that the user knows exactly
+what he or she is doing, and to not ask any questions. It assumes the following: skip patches for
+which a file to patch can't be found; patch files
+even though they have the wrong version for the
+``Prereq:'' line in the patch; and assume that
+patches are not reversed even if they look like they
+are. This option does not suppress commentary; use
+B<-s> for that.
+
+=item -t or --batch
+
+similar to B<-f>, in that it suppresses questions, but
+makes some different assumptions: skip patches for
+which a file to patch can't be found (the same as
+B<-f>); skip patches for which the file has the wrong
+version for the ``Prereq:'' line in the patch; and
+assume that patches are reversed if they look like
+they are.
+
+=item -Fnumber or --fuzz number
+
+sets the maximum fuzz factor. This switch only
+applies to context diffs, and causes I<patch> to ignore
+up to that many lines in looking for places to
+install a hunk. Note that a larger fuzz factor
+increases the odds of a faulty patch. The default
+fuzz factor is 2, and it may not be set to more than
+the number of lines of context in the context diff,
+ordinarily 3.
+
+=item -l or --ignore-whitespace
+
+causes the pattern matching to be done loosely, in
+case the tabs and spaces have been munged in your
+input file. Any sequence of whitespace in the pattern line will match any sequence in the input file.
+Normal characters must still match exactly. Each
+line of the context must still match a line in the
+input file.
+
+=item -n or --normal
+
+forces I<patch> to interpret the patch file as a normal
+diff.
+
+=item -N or --forward
+
+causes I<patch> to ignore patches that it thinks are
+reversed or already applied. See also B<-R .>
+
+=item -o or --output
+
+causes the next argument to be interpreted as the
+output file name.
+
+=item -pnumber or --strip number
+
+sets the pathname strip count, which controls how
+pathnames found in the patch file are treated, in
+case the you keep your files in a different directory
+than the person who sent out the patch. The strip
+count specifies how many slashes are to be stripped
+from the front of the pathname. (Any intervening
+directory names also go away.) For example, supposing the filename in the patch file was
+
+ /i/want/a/moogle/stuffy
+
+setting B<-p> or B<-p0> gives the entire pathname unmodified, B<-p1> gives
+
+ i/want/a/moogle/stuff
+
+without the leading slash, B<-p4> gives
+
+ moogle/stuffy
+
+and not specifying B<-p> at all just gives you
+"stuffy", unless all of the directories in the
+leading path (i/want/a/moogle) exist and that
+path is relative, in which case you get the entire
+pathname unmodified. Whatever you end up with is
+looked for either in the current directory, or the
+directory specified by the B<-d> switch.
+
+=item -r or --reject-file
+
+causes the next argument to be interpreted as the
+reject file name.
+
+=item -R or --reverse
+
+tells I<patch> that this patch was created with the old
+and new files swapped. (Yes, I'm afraid that does
+happen occasionally, human nature being what it is.)
+I<Patch> will attempt to swap each hunk around before
+applying it. Rejects will come out in the swapped
+format. The B<-R> switch will not work with ed diff
+scripts because there is too little information to
+reconstruct the reverse operation.
+
+If the first hunk of a patch fails, I<patch> will
+reverse the hunk to see if it can be applied that
+way. If it can, you will be asked if you want to
+have the B<-R> switch set. If it can't, the patch will
+continue to be applied normally. (Note: this method
+cannot detect a reversed patch if it is a normal diff
+and if the first command is an append (i.e. it should
+have been a delete) since appends always succeed, due
+to the fact that a null context will match anywhere.
+Luckily, most patches add or change lines rather than
+delete them, so most reversed normal diffs will begin
+with a delete, which will fail, triggering the
+heuristic.)
+
+=item -s or --quiet or --silent
+
+makes I<patch> do its work silently, unless an error
+occurs.
+
+=item -S or --skip
+
+causes I<patch> to ignore this patch from the patch
+file, but continue on looking for the next patch in
+the file. Thus
+
+ patch -S + -S + < patchfile
+
+will ignore the first and second of three patches.
+
+=item -u or --unified
+
+forces I<patch> to interpret the patch file as a unified
+context diff (a unidiff).
+
+=item -v or --version
+
+causes I<patch> to print out its revision header and
+patch level.
+
+=item -V or --version-control
+
+causes the next argument to be interpreted as a
+method for creating backup file names. The type of
+backups made can also be given in the B<VERSION>I<_>B<CONTROL>
+environment variable, which is overridden by this
+option. The B<-B> option overrides this option, causing
+the prefix to always be used for making backup file
+names. The value of the B<VERSION>I<_>B<CONTROL> environment
+variable and the argument to the B<-V> option are like
+the GNU Emacs `version-control' variable; they also
+recognize synonyms that are more descriptive. The
+valid values are (unique abbreviations are accepted):
+
+=over
+
+=item `t' or `numbered'
+
+Always make numbered backups.
+
+=item `nil' or `existing'
+
+Make numbered backups of files that already
+have them, simple backups of the others. This
+is the default.
+
+=item `never' or `simple'
+
+Always make simple backups.
+
+=back
+
+=item -xnumber or --debug number
+
+sets internal debugging flags,
+and is of no interest to I<patch> patchers [see L<"note 8">].
+
+=back
+
+=head1 ENVIRONMENT
+
+B<SIMPLE>I<_>B<BACKUP>I<_>B<SUFFIX>
+Extension to use for backup file names instead of
+".orig" or "~".
+
+B<VERSION>I<_>B<CONTROL>
+Selects when numbered backup files are made.
+
+=head1 SEE ALSO
+
+diff(1), ed(1)
+
+=head1 NOTES FOR PATCH SENDERS
+
+There are several things you should bear in mind if you
+are going to be sending out patches. First, you can save
+people a lot of grief by keeping a patchlevel.h file which
+is patched to increment the patch level as the first diff
+in the patch file you send out. If you put a Prereq: line
+in with the patch, it won't let them apply patches out of
+order without some warning. Second, make sure you've
+specified the filenames right, either in a context diff
+header, or with an Index: line. If you are patching something in a subdirectory, be sure to tell the patch user to
+specify a B<-p> switch as needed. Third, you can create a
+file by sending out a diff that compares a null file to
+the file you want to create. This will only work if the
+file you want to create doesn't exist already in the target directory. Fourth, take care not to send out reversed
+patches, since it makes people wonder whether they already
+applied the patch. Fifth, while you may be able to get
+away with putting 582 diff listings into one file, it is
+probably wiser to group related patches into separate
+files in case something goes haywire.
+
+=head1 DIAGNOSTICS
+
+Too many to list here, but generally indicative that I<patch>
+couldn't parse your patch file.
+
+The message "Hmm..." indicates that there is unprocessed
+text in the patch file and that I<patch> is attempting to
+intuit whether there is a patch in that text and, if so,
+what kind of patch it is.
+
+I<Patch> will exit with a non-zero status if any reject files
+were created. When applying a set of patches in a loop it
+behooves you to check this exit status so you don't apply
+a later patch to a partially patched file.
+
+=head1 CAVEATS
+
+I<Patch> cannot tell if the line numbers are off in an ed
+script, and can only detect bad line numbers in a normal
+diff when it finds a "change" or a "delete" command. A
+context diff using fuzz factor 3 may have the same problem. Until a suitable interactive interface is added, you
+should probably do a context diff in these cases to see if
+the changes made sense. Of course, compiling without
+errors is a pretty good indication that the patch worked,
+but not always.
+
+I<Patch> usually produces the correct results, even when it
+has to do a lot of guessing. However, the results are
+guaranteed to be correct only when the patch is applied to
+exactly the same version of the file that the patch was
+generated from.
+
+=head1 BUGS
+
+Could be smarter about partial matches, excessively
+deviant offsets and swapped code, but that would take an
+extra pass.
+
+Check patch mode ( B<-C>) will fail if you try to check several patches in succession that build on each other. The
+whole code of I<patch> would have to be restructured to keep
+temporary files around so that it can handle this situation.
+
+If code has been duplicated (for instance with #ifdef OLDCODE ... #else ... #endif), I<patch> is incapable of patch-
+ing both versions, and, if it works at all, will likely
+patch the wrong one, and tell you that it succeeded to
+boot.
+
+If you apply a patch you've already applied, I<patch> will
+think it is a reversed patch, and offer to un-apply the
+patch. This could be construed as a feature.
+
+=head1 COMPATIBILITY
+
+The perl implementation of patch is based on but not entire compatible with the
+documentation for GNU patch version 2.1:
+
+=head2 note 1
+
+On systems that do not support long filenames,
+GNU patch uses the extension "~" for backup files and the extension "#" for
+reject files.
+How to know if a system support long filenames?
+
+=head2 note 2
+
+Only new-style context diffs are supported.
+What does old-style context diff look like?
+
+=head2 note 3
+
+If the pipe to ed fails, B<patch> will attempt to apply the ed script on its
+own.
+
+=head2 note 4
+
+This algorithm differs from the one described in the documentation for GNU
+patch, which scans forwards and backwards from the line number mentioned in the
+diff (plus any offset used in applying the previous hunk).
+
+=head2 note 5
+
+Rejected hunks in GNU patch all come out as context diffs regardless of the
+input diff, and the lines numbers reflect the approximate location GNU patch
+thinks the failed hunks belong in the new file rather than the old one.
+
+=head2 note 6
+
+If the original file cannot be found or is read-only, but a suitable SCCS or RCS
+file is handy, GNU patch will attempt to get or check out the file.
+
+=head2 note 7
+
+GNU patch requires a space between the B<-D> and the argument. This has been
+made optional.
+
+=head2 note 8
+
+There are currently no debugging flags to go along with B<-x>.
+
+=head1 AUTHOR
+
+Fuzzy | tgy@chocobo.org | Will hack Perl for a moogle stuffy! =^.^=
+
+=head1 COPYRIGHT
+
+Copyright (c) 1999 Moogle Stuffy Software. All rights reserved.
+
+You may play with this software in accordance with the Perl Artistic License.
+
+You may use this documentation under the auspices of the GNU General Public
+License.
+
+=cut
+
--- /dev/null
+#!perl -w
+package version;
+
+use 5.005_04;
+use strict;
+
+use vars qw(@ISA $VERSION $CLASS *qv);
+
+$VERSION = 0.74;
+
+$CLASS = 'version';
+
+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";
+ *version::qv = \&version::vpp::qv;
+}
+else { # use XS module
+ push @ISA, "version::vxs";
+ *version::qv = \&version::vxs::qv;
+}
+
+# Preloaded methods go here.
+sub import {
+ my ($class) = shift;
+ my $callpkg = caller();
+ no strict 'refs';
+
+ *{$callpkg."::qv"} =
+ sub {return bless version::qv(shift), $class }
+ unless defined(&{"$callpkg\::qv"});
+
+# if (@_) { # must have initialization on the use line
+# if ( defined $_[2] ) { # CVS style
+# $_[0] = version::qv($_[2]);
+# }
+# else {
+# $_[0] = version->new($_[1]);
+# }
+# }
+}
+
+1;
--- /dev/null
+package version::vpp;
+use strict;
+
+use locale;
+use vars qw ($VERSION @ISA @REGEXS);
+$VERSION = 0.74;
+
+push @REGEXS, qr/
+ ^v? # optional leading 'v'
+ (\d*) # major revision not required
+ \. # requires at least one decimal
+ (?:(\d+)\.?){1,}
+ /x;
+
+use overload (
+ '""' => \&stringify,
+ '0+' => \&numify,
+ 'cmp' => \&vcmp,
+ '<=>' => \&vcmp,
+ 'bool' => \&vbool,
+ 'nomethod' => \&vnoop,
+);
+
+my $VERSION_MAX = 0x7FFFFFFF;
+
+eval "use warnings";
+if ($@) {
+ eval '
+ package warnings;
+ sub enabled {return $^W;}
+ 1;
+ ';
+}
+
+sub new
+{
+ my ($class, $value) = @_;
+ my $self = bless ({}, ref ($class) || $class);
+
+ if ( ref($value) && eval("$value->isa('version')") ) {
+ # Can copy the elements directly
+ $self->{version} = [ @{$value->{version} } ];
+ $self->{qv} = 1 if $value->{qv};
+ $self->{alpha} = 1 if $value->{alpha};
+ $self->{original} = ''.$value->{original};
+ return $self;
+ }
+
+ require POSIX;
+ my $currlocale = POSIX::setlocale(&POSIX::LC_ALL);
+ my $radix_comma = ( POSIX::localeconv()->{decimal_point} eq ',' );
+
+ if ( not defined $value or $value =~ /^undef$/ ) {
+ # RT #19517 - special case for undef comparison
+ # or someone forgot to pass a value
+ push @{$self->{version}}, 0;
+ $self->{original} = "0";
+ return ($self);
+ }
+
+ if ( $#_ == 2 ) { # must be CVS-style
+ $value = 'v'.$_[2];
+ }
+
+ $value = _un_vstring($value);
+
+ # exponential notation
+ if ( $value =~ /\d+.?\d*e-?\d+/ ) {
+ $value = sprintf("%.9f",$value);
+ $value =~ s/(0+)$//;
+ }
+
+ # if the original locale used commas for decimal points, we
+ # just replace commas with decimal places, rather than changing
+ # locales
+ if ( $radix_comma ) {
+ $value =~ tr/,/./;
+ }
+
+ # This is not very efficient, but it is morally equivalent
+ # to the XS code (as that is the reference implementation).
+ # See vutil/vutil.c for details
+ my $qv = 0;
+ my $alpha = 0;
+ my $width = 3;
+ my $saw_period = 0;
+ my $vinf = 0;
+ my ($start, $last, $pos, $s);
+ $s = 0;
+
+ while ( substr($value,$s,1) =~ /\s/ ) { # leading whitespace is OK
+ $s++;
+ }
+
+ if (substr($value,$s,1) eq 'v') {
+ $s++; # get past 'v'
+ $qv = 1; # force quoted version processing
+ }
+
+ $start = $last = $pos = $s;
+
+ # pre-scan the input string to check for decimals/underbars
+ while ( substr($value,$pos,1) =~ /[._\d]/ ) {
+ if ( substr($value,$pos,1) eq '.' ) {
+ if ($alpha) {
+ Carp::croak("Invalid version format ".
+ "(underscores before decimal)");
+ }
+ $saw_period++;
+ $last = $pos;
+ }
+ elsif ( substr($value,$pos,1) eq '_' ) {
+ if ($alpha) {
+ require Carp;
+ Carp::croak("Invalid version format ".
+ "(multiple underscores)");
+ }
+ $alpha = 1;
+ $width = $pos - $last - 1; # natural width of sub-version
+ }
+ $pos++;
+ }
+
+ if ( $alpha && !$saw_period ) {
+ require Carp;
+ Carp::croak("Invalid version format ".
+ "(alpha without decimal)");
+ }
+
+ if ( $alpha && $saw_period && $width == 0 ) {
+ require Carp;
+ Carp::croak("Invalid version format ".
+ "(misplaced _ in number)");
+ }
+
+ if ( $saw_period > 1 ) {
+ $qv = 1; # force quoted version processing
+ }
+
+ $last = $pos;
+ $pos = $s;
+
+ if ( $qv ) {
+ $self->{qv} = 1;
+ }
+
+ if ( $alpha ) {
+ $self->{alpha} = 1;
+ }
+
+ if ( !$qv && $width < 3 ) {
+ $self->{width} = $width;
+ }
+
+ while ( substr($value,$pos,1) =~ /\d/ ) {
+ $pos++;
+ }
+
+ if ( substr($value,$pos,1) !~ /[a-z]/ ) { ### FIX THIS ###
+ my $rev;
+
+ while (1) {
+ $rev = 0;
+ {
+
+ # this is atoi() that delimits on underscores
+ my $end = $pos;
+ my $mult = 1;
+ my $orev;
+
+ # the following if() will only be true after the decimal
+ # point of a version originally created with a bare
+ # floating point number, i.e. not quoted in any way
+ if ( !$qv && $s > $start && $saw_period == 1 ) {
+ $mult *= 100;
+ while ( $s < $end ) {
+ $orev = $rev;
+ $rev += substr($value,$s,1) * $mult;
+ $mult /= 10;
+ if ( abs($orev) > abs($rev)
+ || abs($rev) > abs($VERSION_MAX) ) {
+ if ( warnings::enabled("overflow") ) {
+ require Carp;
+ Carp::carp("Integer overflow in version");
+ }
+ $s = $end - 1;
+ $rev = $VERSION_MAX;
+ }
+ $s++;
+ if ( substr($value,$s,1) eq '_' ) {
+ $s++;
+ }
+ }
+ }
+ else {
+ while (--$end >= $s) {
+ $orev = $rev;
+ $rev += substr($value,$end,1) * $mult;
+ $mult *= 10;
+ if ( abs($orev) > abs($rev)
+ || abs($rev) > abs($VERSION_MAX) ) {
+ if ( warnings::enabled("overflow") ) {
+ require Carp;
+ Carp::carp("Integer overflow in version");
+ }
+ $end = $s - 1;
+ $rev = $VERSION_MAX;
+ }
+ }
+ }
+ }
+
+ # Append revision
+ push @{$self->{version}}, $rev;
+ if ( substr($value,$pos,1) eq '.'
+ && substr($value,$pos+1,1) =~ /\d/ ) {
+ $s = ++$pos;
+ }
+ elsif ( substr($value,$pos,1) eq '_'
+ && substr($value,$pos+1,1) =~ /\d/ ) {
+ $s = ++$pos;
+ }
+ elsif ( substr($value,$pos,1) =~ /\d/ ) {
+ $s = $pos;
+ }
+ else {
+ $s = $pos;
+ last;
+ }
+ if ( $qv ) {
+ while ( substr($value,$pos,1) =~ /\d/ ) {
+ $pos++;
+ }
+ }
+ else {
+ my $digits = 0;
+ while (substr($value,$pos,1) =~ /[\d_]/ && $digits < 3) {
+ if ( substr($value,$pos,1) ne '_' ) {
+ $digits++;
+ }
+ $pos++;
+ }
+ }
+ }
+ }
+ if ( $qv ) { # quoted versions always get at least three terms
+ my $len = scalar @{$self->{version}};
+ $len = 3 - $len;
+ while ($len-- > 0) {
+ push @{$self->{version}}, 0;
+ }
+ }
+
+ if ( substr($value,$pos) ) { # any remaining text
+ if ( warnings::enabled("misc") ) {
+ require Carp;
+ Carp::carp("Version string '$value' contains invalid data; ".
+ "ignoring: '".substr($value,$pos)."'");
+ }
+ }
+
+ # cache the original value for use when stringification
+ if ( $vinf ) {
+ $self->{vinf} = 1;
+ $self->{original} = 'v.Inf';
+ }
+ else {
+ $self->{original} = substr($value,0,$pos);
+ }
+
+ return ($self);
+}
+
+sub numify
+{
+ my ($self) = @_;
+ unless (_verify($self)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ my $width = $self->{width} || 3;
+ my $alpha = $self->{alpha} || "";
+ my $len = $#{$self->{version}};
+ my $digit = $self->{version}[0];
+ my $string = sprintf("%d.", $digit );
+
+ for ( my $i = 1 ; $i < $len ; $i++ ) {
+ $digit = $self->{version}[$i];
+ if ( $width < 3 ) {
+ my $denom = 10**(3-$width);
+ my $quot = int($digit/$denom);
+ my $rem = $digit - ($quot * $denom);
+ $string .= sprintf("%0".$width."d_%d", $quot, $rem);
+ }
+ else {
+ $string .= sprintf("%03d", $digit);
+ }
+ }
+
+ if ( $len > 0 ) {
+ $digit = $self->{version}[$len];
+ if ( $alpha && $width == 3 ) {
+ $string .= "_";
+ }
+ $string .= sprintf("%0".$width."d", $digit);
+ }
+ else # $len = 0
+ {
+ $string .= sprintf("000");
+ }
+
+ return $string;
+}
+
+sub normal
+{
+ my ($self) = @_;
+ unless (_verify($self)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ my $alpha = $self->{alpha} || "";
+ my $len = $#{$self->{version}};
+ my $digit = $self->{version}[0];
+ my $string = sprintf("v%d", $digit );
+
+ for ( my $i = 1 ; $i < $len ; $i++ ) {
+ $digit = $self->{version}[$i];
+ $string .= sprintf(".%d", $digit);
+ }
+
+ if ( $len > 0 ) {
+ $digit = $self->{version}[$len];
+ if ( $alpha ) {
+ $string .= sprintf("_%0d", $digit);
+ }
+ else {
+ $string .= sprintf(".%0d", $digit);
+ }
+ }
+
+ if ( $len <= 2 ) {
+ for ( $len = 2 - $len; $len != 0; $len-- ) {
+ $string .= sprintf(".%0d", 0);
+ }
+ }
+
+ return $string;
+}
+
+sub stringify
+{
+ my ($self) = @_;
+ unless (_verify($self)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ return $self->{original};
+}
+
+sub vcmp
+{
+ require UNIVERSAL;
+ my ($left,$right,$swap) = @_;
+ my $class = ref($left);
+ unless ( UNIVERSAL::isa($right, $class) ) {
+ $right = $class->new($right);
+ }
+
+ if ( $swap ) {
+ ($left, $right) = ($right, $left);
+ }
+ unless (_verify($left)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ unless (_verify($right)) {
+ require Carp;
+ Carp::croak("Invalid version object");
+ }
+ my $l = $#{$left->{version}};
+ my $r = $#{$right->{version}};
+ my $m = $l < $r ? $l : $r;
+ my $lalpha = $left->is_alpha;
+ my $ralpha = $right->is_alpha;
+ my $retval = 0;
+ my $i = 0;
+ while ( $i <= $m && $retval == 0 ) {
+ $retval = $left->{version}[$i] <=> $right->{version}[$i];
+ $i++;
+ }
+
+ # tiebreaker for alpha with identical terms
+ if ( $retval == 0
+ && $l == $r
+ && $left->{version}[$m] == $right->{version}[$m]
+ && ( $lalpha || $ralpha ) ) {
+
+ if ( $lalpha && !$ralpha ) {
+ $retval = -1;
+ }
+ elsif ( $ralpha && !$lalpha) {
+ $retval = +1;
+ }
+ }
+
+ # possible match except for trailing 0's
+ if ( $retval == 0 && $l != $r ) {
+ if ( $l < $r ) {
+ while ( $i <= $r && $retval == 0 ) {
+ if ( $right->{version}[$i] != 0 ) {
+ $retval = -1; # not a match after all
+ }
+ $i++;
+ }
+ }
+ else {
+ while ( $i <= $l && $retval == 0 ) {
+ if ( $left->{version}[$i] != 0 ) {
+ $retval = +1; # not a match after all
+ }
+ $i++;
+ }
+ }
+ }
+
+ return $retval;
+}
+
+sub vbool {
+ my ($self) = @_;
+ return vcmp($self,$self->new("0"),1);
+}
+
+sub vnoop {
+ require Carp;
+ Carp::croak("operation not supported with version object");
+}
+
+sub is_alpha {
+ my ($self) = @_;
+ return (exists $self->{alpha});
+}
+
+sub qv {
+ my ($value) = @_;
+
+ $value = _un_vstring($value);
+ $value = 'v'.$value unless $value =~ /(^v|\d+\.\d+\.\d)/;
+ my $version = version->new($value); # always use base class
+ return $version;
+}
+
+sub is_qv {
+ my ($self) = @_;
+ return (exists $self->{qv});
+}
+
+
+sub _verify {
+ my ($self) = @_;
+ if ( ref($self)
+ && eval { exists $self->{version} }
+ && ref($self->{version}) eq 'ARRAY'
+ ) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+sub _un_vstring {
+ my $value = shift;
+ # may be a v-string
+ if ( $] >= 5.006_000 && length($value) >= 3 && $value !~ /[._]/ ) {
+ my $tvalue = sprintf("v%vd",$value);
+ if ( $tvalue =~ /^v\d+\.\d+\.\d+$/ ) {
+ # must be a v-string
+ $value = $tvalue;
+ }
+ }
+ return $value;
+}
+
+# Thanks to Yitzchak Scott-Thoennes for this mode of operation
+{
+ local $^W;
+ *UNIVERSAL::VERSION = sub {
+ my ($obj, $req) = @_;
+ my $class = ref($obj) || $obj;
+
+ no strict 'refs';
+ eval "require $class" unless %{"$class\::"}; # already existing
+ return undef if $@ =~ /Can't locate/ and not defined $req;
+
+ if ( not %{"$class\::"} and $] >= 5.008) { # file but no package
+ require Carp;
+ Carp::croak( "$class defines neither package nor VERSION"
+ ."--version check failed");
+ }
+
+ my $version = eval "\$$class\::VERSION";
+ if ( defined $version ) {
+ local $^W if $] <= 5.008;
+ $version = version::vpp->new($version);
+ }
+
+ if ( defined $req ) {
+ unless ( defined $version ) {
+ require Carp;
+ my $msg = $] < 5.006
+ ? "$class version $req required--this is only version "
+ : "$class does not define \$$class\::VERSION"
+ ."--version check failed";
+
+ if ( $ENV{VERSION_DEBUG} ) {
+ Carp::confess($msg);
+ }
+ else {
+ Carp::croak($msg);
+ }
+ }
+
+ $req = version::vpp->new($req);
+
+ if ( $req > $version ) {
+ require Carp;
+ if ( $req->is_qv ) {
+ Carp::croak(
+ sprintf ("%s version %s required--".
+ "this is only version %s", $class,
+ $req->normal, $version->normal)
+ );
+ }
+ else {
+ Carp::croak(
+ sprintf ("%s version %s required--".
+ "this is only version %s", $class,
+ $req->stringify, $version->stringify)
+ );
+ }
+ }
+ }
+
+ return defined $version ? $version->stringify : undef;
+ };
+}
+
+1; #this line is important and will help the module return a true value
--- /dev/null
+package Alien::wxWidgets;
+
+=head1 NAME
+
+Alien::wxWidgets - building, finding and using wxWidgets binaries
+
+=head1 SYNOPSIS
+
+ use Alien::wxWidgets <options>;
+
+ my $version = Alien::wxWidgets->version;
+ my $config = Alien::wxWidgets->config;
+ my $compiler = Alien::wxWidgets->compiler;
+ my $linker = Alien::wxWidgets->linker;
+ my $include_path = Alien::wxWidgets->include_path;
+ my $defines = Alien::wxWidgets->defines;
+ my $cflags = Alien::wxWidgets->c_flags;
+ my $linkflags = Alien::wxWidgets->link_flags;
+ my $libraries = Alien::wxWidgets->libraries( qw(gl adv core base) );
+ my @libraries = Alien::wxWidgets->link_libraries( qw(gl adv core base) );
+ my @implib = Alien::wxWidgets->import_libraries( qw(gl adv core base) );
+ my @shrlib = Alien::wxWidgets->shared_libraries( qw(gl adv core base) );
+ my @keys = Alien::wxWidgets->library_keys; # 'gl', 'adv', ...
+ my $library_path = Alien::wxWidgets->shared_library_path;
+ my $key = Alien::wxWidgets->key;
+ my $prefix = Alien::wxWidgets->prefix;
+
+=head1 DESCRIPTION
+
+Please see L<Alien> for the manifesto of the Alien namespace.
+
+In short C<Alien::wxWidgets> can be used to detect and get
+configuration settings from an installed wxWidgets.
+
+=cut
+
+use strict;
+use Carp;
+use Alien::wxWidgets::Utility qw(awx_sort_config awx_grep_config
+ awx_smart_config);
+use Module::Pluggable sub_name => '_list',
+ search_path => 'Alien::wxWidgets::Config',
+ instantiate => 'config';
+
+our $AUTOLOAD;
+our $VERSION = '0.50';
+our %VALUES;
+our $dont_remap;
+
+*_remap = \&Alien::wxWidgets::Utility::_awx_remap;
+
+sub AUTOLOAD {
+ my $name = $AUTOLOAD;
+
+ $name =~ s/.*:://;
+ croak "Can not use '", $name, "'" unless exists $VALUES{$name};
+
+ return _remap( $VALUES{$name} );
+}
+
+sub import {
+ my $class = shift;
+ if( @_ == 1 ) {
+ $class->dump_configurations if $_[0] eq ':dump';
+ $class->show_configurations if $_[0] eq ':show';
+ return;
+ }
+
+ $class->load( @_ );
+}
+
+sub load {
+ my $class = shift;
+ my %crit = awx_smart_config @_;
+
+ my @configs = awx_sort_config awx_grep_config [ $class->_list ], %crit ;
+
+ unless( @configs ) {
+ my @all_configs = $class->get_configurations;
+
+ my $message = "Searching configuration for:\n";
+ $message .= _pretty_print_criteria( \%crit );
+ $message .= "\nAvailable configurations:\n";
+ if( @all_configs ) {
+ $message .= _pretty_print_configuration( $_ ) foreach @all_configs;
+ } else {
+ $message .= "No wxWidgets build found\n";
+ }
+
+ die $message;
+ }
+
+ %VALUES = $configs[0]->{package}->values;
+}
+
+sub _pretty_print_criteria {
+ my $criteria = shift;
+ my %display = %$criteria;
+
+ $display{version} = join '-', @{$display{version}} if ref $display{version};
+ $display{version} = '(any version)' unless $display{version};
+ $display{toolkit} = '(any toolkit)' unless $display{toolkit};
+ $display{compiler_kind} = '(any compiler)' unless $display{compiler_kind};
+ $display{compiler_version} = '(any version)' unless $display{compiler_version};
+
+ return _pretty_print_configuration( \%display );
+}
+
+sub _pretty_print_configuration {
+ my $config = shift;
+ my @options = map { !defined $config->{$_} ? () :
+ $config->{$_} ? ( $_ ) :
+ ( "no $_" ) }
+ qw(debug unicode mslu);
+
+ return "wxWidgets $config->{version} for $config->{toolkit}; " .
+ "compiler compatibility: $config->{compiler_kind} " .
+ $config->{compiler_version} . '; ' .
+ ( @options ? 'options: ' . join( ', ', @options ) : '' ) .
+ "\n";
+}
+
+sub show_configurations {
+ my $class = shift;
+ my @configs = $class->get_configurations( @_ );
+
+ print _pretty_print_configuration( $_ ) foreach @configs;
+}
+
+sub dump_configurations {
+ my $class = shift;
+ my @configs = $class->get_configurations( @_ );
+
+ require Data::Dumper;
+ print Data::Dumper->Dump( \@configs );
+}
+
+sub get_configurations {
+ my $class = shift;
+
+ return awx_sort_config awx_grep_config [ $class->_list ], @_;
+}
+
+my $lib_nok = 'adv|base|html|net|xml|media';
+my $lib_mono_28 = 'adv|base|html|net|xml|xrc|media|aui|richtext';
+my $lib_mono_29 = 'adv|base|html|net|xml|xrc|media|aui|richtext|stc';
+
+sub _grep_libraries {
+ my $lib_filter = $VALUES{version} >= 2.005001 ? qr/(?!a)a/ : # no match
+ $^O =~ /MSWin32/ ? qr/^(?:$lib_nok|gl)$/ :
+ qr/^(?:$lib_nok)$/;
+
+ my( $type, @libs ) = @_;
+
+ my $dlls = $VALUES{_libraries};
+
+ @libs = keys %$dlls unless @libs;
+ push @libs, 'core', 'base' unless grep /^core|mono$/, @libs;
+
+ my $lib_mono = $VALUES{version} >= 2.009 ? $lib_mono_29 : $lib_mono_28;
+ if( ( $VALUES{config}{build} || '' ) eq 'mono' ) {
+ @libs = map { $_ eq 'core' ? ( 'mono' ) :
+ $_ =~ /^(?:$lib_mono)$/ ? () :
+ $_ } @libs;
+ @libs = qw(mono) unless @libs;
+ }
+
+ return map { _remap( $_ ) }
+ map { defined( $dlls->{$_}{$type} ) ? $dlls->{$_}{$type} :
+ croak "No such '$type' library: '$_'" }
+ grep !/$lib_filter/, @libs;
+}
+
+sub link_libraries { shift; return _grep_libraries( 'link', @_ ) }
+sub shared_libraries { shift; return _grep_libraries( 'dll', @_ ) }
+sub import_libraries { shift; return _grep_libraries( 'lib', @_ ) }
+sub library_keys { shift; return keys %{$VALUES{_libraries}} }
+
+sub libraries {
+ my $class = shift;
+
+ return ( _remap( $VALUES{link_libraries} ) || '' ) . ' ' .
+ join ' ', map { _remap( $_ ) }
+ $class->link_libraries( @_ );
+}
+
+1;
+
+__END__
+
+=head1 METHODS
+
+=head2 load/import
+
+ use Alien::wxWidgets version => 2.004 | [ 2.004, 2.005 ],
+ compiler_kind => 'gcc' | 'cl', # Windows only
+ compiler_version => '3.3', # only GCC for now
+ toolkit => 'gtk2',
+ debug => 0 | 1,
+ unicode => 0 | 1,
+ mslu => 0 | 1,
+ key => $key,
+ ;
+
+ Alien::wxWidgets->load( <same as the above> );
+
+Using C<Alien::wxWidgets> without parameters will load a default
+configuration (for most people this will be the only installed
+confiuration). Additional parameters allow to be more selective.
+
+If there is no matching configuration the method will C<die()>.
+
+In case no arguments are passed in the C<use>, C<Alien::wxWidgets>
+will try to find a reasonable default configuration.
+
+Please note that when the version is pecified as C<version => 2.004>
+it means "any version >= 2.004" while when specified as
+C<version => [ 2.004, 2.005 ]> it means "any version => 2.004 and < 2.005".
+
+=head2 key
+
+ my $key = Alien::wxWidgets key;
+
+Returns an unique key that can be used to reload the
+currently-loaded configuration.
+
+=head2 version
+
+ my $version = Alien::wxWidgets->version;
+
+Returns the wxWidgets version for this C<Alien::wxWidgets>
+installation in the form MAJOR + MINOR / 1_000 + RELEASE / 1_000_000
+e.g. 2.006002 for wxWidgets 2.6.2 and 2.004 for wxWidgets 2.4.0.
+
+=head2 config
+
+ my $config = Alien::wxWidgets->config;
+
+Returns some miscellaneous configuration informations for wxWidgets
+in the form
+
+ { toolkit => 'msw' | 'gtk' | 'motif' | 'x11' | 'cocoa' | 'mac',
+ debug => 1 | 0,
+ unicode => 1 | 0,
+ mslu => 1 | 0,
+ }
+
+=head2 include_path
+
+ my $include_path = Alien::wxWidgets->include_path;
+
+Returns the include paths to be used in a format suitable for the
+compiler (usually something like "-I/usr/local/include -I/opt/wx/include").
+
+=head2 defines
+
+ my $defines = Alien::wxWidgets->defines;
+
+Returns the compiler defines to be used in a format suitable for the
+compiler (usually something like "-D__WXDEBUG__ -DFOO=bar").
+
+=head2 c_flags
+
+ my $cflags = Alien::wxWidgets->c_flags;
+
+Returns additional compiler flags to be used.
+
+=head2 compiler
+
+ my $compiler = Alien::wxWidgets->compiler;
+
+Returns the (C++) compiler used for compiling wxWidgets.
+
+=head2 linker
+
+ my $linker = Alien::wxWidgets->linker;
+
+Returns a linker suitable for linking C++ binaries.
+
+=head2 link_flags
+
+ my $linkflags = Alien::wxWidgets->link_flags;
+
+Returns additional link flags.
+
+=head2 libraries
+
+ my $libraries = Alien::wxWidgets->libraries( qw(gl adv core base) );
+
+Returns link flags for linking the libraries passed as arguments. This
+usually includes some search path specification in addition to the
+libraries themselves. The caller is responsible for the correct order
+of the libraries.
+
+=head2 link_libraries
+
+ my @libraries = Alien::wxWidgets->link_libraries( qw(gl adv core base) );
+
+Returns a list of linker flags that can be used to link the libraries
+passed as arguments.
+
+=head2 import_libraries
+
+ my @implib = Alien::wxWidgets->import_libraries( qw(gl adv core base) );
+
+Windows specific. Returns a list of import libraries corresponding to
+the libraries passed as arguments.
+
+=head2 shared_libraries
+
+ my @shrlib = Alien::wxWidgets->shared_libraries( qw(gl adv core base) );
+
+Returns a list of shared libraries corresponding to the libraries
+passed as arguments.
+
+=head2 library_keys
+
+ my @keys = Alien::wxWidgets->library_keys;
+
+Returns a list of keys that can be passed to C<shared_libraries>,
+C<import_libraries> and C<link_libraries>.
+
+=head2 library_path
+
+ my $library_path = Alien::wxWidgets->shared_library_path;
+
+Windows specific. Returns the path at which the private copy
+of wxWidgets libraries has been installed.
+
+=head2 prefix
+
+ my $prefix = Alien::wxWidgets->prefix;
+
+Returns the install prefix for wxWidgets.
+
+=head2 dump_configurations
+
+ Alien::wxWidgets->dump_configurations( %filters );
+
+Prints a list of available configurations (mainly useful for
+interactive use/debugging).
+
+=head2 show_configurations
+
+ Alien::wxWidgets->show_configurations( %filters );
+
+Prints a human-readable list of available configurations (mainly
+useful for interactive use/debugging).
+
+=head2 get_configurations
+
+ my $configs = Alien::wxWidgets->get_configurations( %filters );
+
+Returns a list of configurations matching the given filters.
+
+=head1 AUTHOR
+
+Mattia Barbon <mbarbon@cpan.org>
+
+=head1 LICENSE
+
+=over 4
+
+=item Alien::wxWidgets
+
+Copyright (c) 2005-2009 Mattia Barbon <mbarbon@cpan.org>
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself
+
+=item inc/bin/patch
+
+was taken from the Perl Power Tools distributions
+
+Copyright (c) 1999 Moogle Stuffy Software <tgy@chocobo.org>
+
+You may play with this software in accordance with the Perl Artistic License.
+
+You may use this documentation under the auspices of the GNU General Public
+License.
+
+=item inc/bin/patch.exe
+
+was downloaded from http://gnuwin32.sourceforge.net/packages/patch.htm
+ad is copyrighted by its authors, sources are included inside the
+inc/src directory.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+=item bundled files from CPAN
+
+ inc/File/Fetch/Item.pm
+ inc/File/Fetch.pm
+ inc/File/Spec/Unix.pm
+ inc/IPC/Cmd.pm
+ inc/Locale/Maketext/Simple.pm
+ inc/Module/Load/Conditional.pm
+ inc/Module/Load.pm
+ inc/Params/Check.pm
+ inc/Archive/Extract.pm
+
+Are copyright their respective authors an can be used according
+to the license specified in their CPAN distributions.
+
+=back
+
+=cut
--- /dev/null
+package Alien::wxWidgets::Utility;
+
+=head1 NAME
+
+Alien::wxWidgets::Utility - INTERNAL: do not use
+
+=cut
+
+use strict;
+use base qw(Exporter);
+use Config;
+use File::Basename qw();
+
+BEGIN {
+ if( $^O eq 'MSWin32' && $Config{_a} ne $Config{lib_ext} ) {
+ print STDERR <<EOT;
+
+\$Config{_a} is '$Config{_a}' and \$Config{lib_ext} is '$Config{lib_ext}':
+they need to be equal for the build to succeed. If you are using ActivePerl
+with MinGW/GCC, please:
+
+- install ExtUtils::FakeConfig
+- set PERL5OPT=-MConfig_m
+- rerun Build.PL
+
+EOT
+ exit 1;
+ }
+}
+
+our @EXPORT_OK = qw(awx_capture awx_cc_is_gcc awx_cc_version awx_cc_abi_version
+ awx_sort_config awx_grep_config awx_smart_config);
+
+my $quotes = $^O =~ /MSWin32/ ? '"' : "'";
+my $compiler_checked = '';
+
+sub _exename {
+ return File::Basename::basename( lc $_[0], '.exe' );
+}
+
+sub _warn_nonworking_compiler {
+ my( $cc ) = @_;
+
+ return if $compiler_checked eq $cc;
+
+ eval { require ExtUtils::CBuilder; };
+ return if $@; # avoid failing when called a Build.PL time
+
+ # a C++ compiler can act as a linker, except for MS cl.exe
+ my $ld = _exename( $Config{cc} ) eq 'cl' ? 'link' : $cc;
+ my $b = ExtUtils::CBuilder->new( config => { cc => $cc, ld => $ld },
+ quiet => 1,
+ );
+
+ if( !$b->have_compiler ) {
+ print STDERR <<EOT;
+
+ATTENTION: It apperars '$cc' is not a working compiler, please make
+sure all necessary packages are installed.
+
+EOT
+ sleep 5;
+ }
+
+ $compiler_checked = $cc;
+}
+
+sub awx_capture {
+ qx!$^X -e ${quotes}open STDERR, q[>&STDOUT]; exec \@ARGV${quotes} -- $_[0]!;
+}
+
+sub awx_cc_is_msvc {
+ my( $cc ) = @_;
+
+ return $^O =~ /MSWin32/ and $cc =~ /^cl/i;
+}
+
+sub awx_cc_is_gcc {
+ my( $cc ) = @_;
+
+ return scalar( awx_capture( "$cc --version" ) =~ m/g(cc|\+\+)/i ) # 3.x
+ || scalar( awx_capture( "$cc" ) =~ m/gcc/i ); # 2.95
+}
+
+sub awx_cc_abi_version {
+ my( $cc ) = @_;
+
+ _warn_nonworking_compiler( $cc );
+
+ my $is_gcc = awx_cc_is_gcc( $cc );
+ my $is_msvc = awx_cc_is_msvc( $cc );
+ return 0 unless $is_gcc || $is_msvc;
+ my $ver = awx_cc_version( $cc );
+ if( $is_gcc ) {
+ return 0 unless $ver > 0;
+ return '3.4' if $ver >= 3.4;
+ return '3.2' if $ver >= 3.2;
+ return $ver;
+ } elsif( $is_msvc ) {
+ return 0 if $ver < 7;
+ return $ver;
+ }
+}
+
+sub awx_cc_version {
+ my( $cc ) = @_;
+
+ _warn_nonworking_compiler( $cc );
+
+ my $is_gcc = awx_cc_is_gcc( $cc );
+ my $is_msvc = awx_cc_is_msvc( $cc );
+ return 0 unless $is_gcc || $is_msvc;
+
+ if( $is_gcc ) {
+ my $ver = awx_capture( "$cc --version" );
+ $ver =~ m/(\d+\.\d+)(?:\.\d+)?/ or return 0;
+ return $1;
+ } elsif( $is_msvc ) {
+ my $ver = awx_capture( $cc );
+ $ver =~ m/(\d+\.\d+)\.\d+/ or return 0;
+ return 8.0 if $1 >= 14;
+ return 7.1 if $1 >= 13.10;
+ return 7.0 if $1 >= 13;
+ return 6.0 if $1 >= 12;
+ return 5.0 if $1 >= 11;
+ return 0;
+ }
+}
+
+sub awx_compiler_kind {
+ my( $cc ) = @_;
+
+ _warn_nonworking_compiler( $cc );
+
+ return 'gcc' if awx_cc_is_gcc( $cc );
+ return 'cl' if awx_cc_is_msvc( $cc );
+
+ return 'nc'; # as in 'No Clue'
+}
+
+# sort a list of configurations by version, debug/release, unicode/ansi, mslu
+sub awx_sort_config {
+ # comparison functions treating undef as 0 or ''
+ # numerico comparison
+ my $make_cmpn = sub {
+ my $k = shift;
+ sub { exists $a->{$k} && exists $b->{$k} ? $a->{$k} <=> $b->{$k} :
+ exists $a->{$k} ? 1 :
+ exists $b->{$k} ? -1 :
+ 0 }
+ };
+ # string comparison
+ my $make_cmps = sub {
+ my $k = shift;
+ sub { exists $a->{$k} && exists $b->{$k} ? $a->{$k} cmp $b->{$k} :
+ exists $a->{$k} ? 1 :
+ exists $b->{$k} ? -1 :
+ 0 }
+ };
+ # reverse comparison
+ my $rev = sub { my $cmp = shift; sub { -1 * &$cmp } };
+ # compare by different criteria, using the first nonzero as tie-breaker
+ my $crit_sort = sub {
+ my @crit = @_;
+ sub {
+ foreach ( @crit ) {
+ my $cmp = &$_;
+ return $cmp if $cmp;
+ }
+
+ return 0;
+ }
+ };
+
+ my $cmp = $crit_sort->( $make_cmpn->( 'version' ),
+ $rev->( $make_cmpn->( 'debug' ) ),
+ $make_cmpn->( 'unicode' ),
+ $make_cmpn->( 'mslu' ) );
+
+ return reverse sort $cmp @_;
+}
+
+sub awx_grep_config {
+ my( $cfgs ) = shift;
+ my( %a ) = @_;
+ # compare to a numeric range or value
+ # low extreme included, high extreme excluded
+ # if $a{key} = [ lo, hi ] then range else low extreme
+ my $make_cmpr = sub {
+ my $k = shift;
+ sub {
+ return 1 unless exists $a{$k};
+ ref $a{$k} ? $a{$k}[0] <= $_->{$k} && $_->{$k} < $a{$k}[1] :
+ $a{$k} <= $_->{$k};
+ }
+ };
+ # compare for numeric equality
+ my $make_cmpn = sub {
+ my $k = shift;
+ sub { exists $a{$k} ? $a{$k} == $_->{$k} : 1 }
+ };
+ # compare for string equality
+ my $make_cmps = sub {
+ my $k = shift;
+ sub { exists $a{$k} ? $a{$k} eq $_->{$k} : 1 }
+ };
+ my $compare_tk = sub {
+ return 1 unless exists $a{toolkit};
+ my $atk = $a{toolkit} eq 'mac' ? 'osx_carbon' :
+ $a{toolkit};
+ my $btk = $_->{toolkit} eq 'mac' ? 'osx_carbon' :
+ $_->{toolkit};
+ return $atk eq $btk;
+ };
+
+ # note tha if the criteria was not supplied, the comparison is a noop
+ my $wver = $make_cmpr->( 'version' );
+ my $ckind = $make_cmps->( 'compiler_kind' );
+ my $cver = $make_cmpn->( 'compiler_version' );
+ my $tkit = $compare_tk;
+ my $deb = $make_cmpn->( 'debug' );
+ my $uni = $make_cmpn->( 'unicode' );
+ my $mslu = $make_cmpn->( 'mslu' );
+ my $key = $make_cmps->( 'key' );
+
+ grep { &$wver } grep { &$ckind } grep { &$cver }
+ grep { &$tkit } grep { &$deb } grep { &$uni }
+ grep { &$mslu } grep { &$key }
+ @{$cfgs}
+}
+
+# automatically add compiler data unless the key was supplied
+sub awx_smart_config {
+ my( %args ) = @_;
+ # the key already identifies the configuration
+ return %args if $args{key};
+
+ my $cc = $ENV{CXX} || $ENV{CC} || $Config{ccname} || $Config{cc};
+ my $kind = awx_compiler_kind( $cc );
+ my $version = awx_cc_abi_version( $cc );
+
+ $args{compiler_kind} ||= $kind;
+ $args{compiler_version} ||= $version;
+
+ return %args;
+}
+
+# allow to remap srings in the configuration; useful when building
+# archives
+my @prefixes;
+
+BEGIN {
+ if( $ENV{ALIEN_WX_PREFIXES} ) {
+ my @kv = split /,\s*/, $ENV{ALIEN_WX_PREFIXES};
+
+ while( @kv ) {
+ my( $match, $repl ) = ( shift( @kv ) || '', shift( @kv ) || '' );
+
+ push @prefixes, [ $match, $^O eq 'MSWin32' ?
+ qr/\Q$match\E/i :
+ qr/\Q$match\E/, $repl ];
+ }
+ }
+}
+
+sub _awx_remap {
+ my( $string ) = @_;
+ return $string if ref $string;
+ return $string if $Alien::wxWidgets::dont_remap;
+
+ foreach my $prefix ( @prefixes ) {
+ my( $str, $rx, $repl ) = @$prefix;
+
+ $string =~ s{$rx(\S*)}{$repl$1}g;
+ }
+
+ return $string;
+}
+
+1;
--- /dev/null
+my $VERSION = '2.8.10';
+ $URL ||= "http://prdownloads.sourceforge.net/wxwindows";
+my $BASE = 'wxWidgets';
+# $TYPE from Build.PL
+
+my @common = qw(wxWidgets-2.8.0-magic.patch);
+
+{ msw => { unicode => [ qw(
+wxMSW-2.8.0-setup_u.patch
+wxMSW-2.8.10-config.patch
+wxMSW-2.8.0-makefiles.patch
+wxMSW-2.8.10-version.patch
+wxMSW-2.8.10-mingw64.patch
+ ), @common ],
+ ansi => [ qw(
+wxMSW-2.8.0-setup.patch
+wxMSW-2.8.10-config.patch
+wxMSW-2.8.0-makefiles.patch
+wxMSW-2.8.10-version.patch
+wxMSW-2.8.10-mingw64.patch
+ ), @common ],
+ },
+ mac => { unicode => [ qw(
+wxMac-2.8.3-brokengcc.patch
+ ), @common ],
+ ansi => [ qw(
+wxMac-2.8.3-brokengcc.patch
+ ), @common ],
+ },
+ unix => { unicode => [ qw(
+wxWidgets-2.8.10-gsocket.patch
+ ), @common ],
+ ansi => [ qw(
+wxWidgets-2.8.10-gsocket.patch
+ ), @common ],
+ },
+ data => { url => ( sprintf '%s/%s-%s.%s', $URL, $BASE, $VERSION, $TYPE ),
+ directory => ( sprintf '%s-%s', $BASE, $VERSION ),
+ archive => ( sprintf '%s-%s.%s', $BASE, $VERSION, $TYPE ),
+ version => $VERSION,
+ },
+ };
--- /dev/null
+my $VERSION = '2.9.0';
+ $URL ||= "http://prdownloads.sourceforge.net/wxwindows";
+my $BASE = 'wxWidgets';
+# $TYPE from Build.PL
+
+my @common = qw(wxWidgets-2.9.0-magic.patch
+ wxWidgets-2.9.0-msgdlg.patch);
+
+{ msw => { unicode => [ qw(
+wxMSW-2.9.0-setup.patch
+wxMSW-2.9.0-config.patch
+wxMSW-2.9.0-makefiles.patch
+wxMSW-2.9.0-version.patch
+wxMSW-2.8.10-mingw64.patch
+ ), @common ],
+ },
+ mac => { unicode => [ qw(wxMac-2.9.0-textctrl.patch
+ ), @common ],
+ },
+ unix => { unicode => [ @common ],
+ },
+ data => { url => ( sprintf '%s/%s-%s.%s', $URL, $BASE, $VERSION, $TYPE ),
+ directory => ( sprintf '%s-%s', $BASE, $VERSION ),
+ archive => ( sprintf '%s-%s.%s', $BASE, $VERSION, $TYPE ),
+ version => $VERSION,
+ },
+ };
--- /dev/null
+diff -u build/msw/makefile.gcc build/msw/makefile.gcc
+--- build/msw/makefile.gcc 2006-12-11 22:50:33.000000000 +0100
++++ build/msw/makefile.gcc 2007-02-25 20:02:22.000000000 +0100
+@@ -173,14 +173,14 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DwxUSE_BASE=1 -DWXMAKINGDLL $(CPPFLAGS) $(CFLAGS)
+ MONODLL_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__THREADSFLAG) \
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_BASE=1 -DWXMAKINGDLL $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -294,14 +294,14 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DwxUSE_BASE=1 $(CPPFLAGS) $(CFLAGS)
+ MONOLIB_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__THREADSFLAG) \
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_BASE=1 $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -414,14 +414,14 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DwxUSE_GUI=0 -DWXMAKINGDLL_BASE -DwxUSE_BASE=1 $(CPPFLAGS) $(CFLAGS)
+ BASEDLL_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__THREADSFLAG) \
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 -DWXMAKINGDLL_BASE -DwxUSE_BASE=1 \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -521,14 +521,14 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DwxUSE_GUI=0 -DwxUSE_BASE=1 $(CPPFLAGS) $(CFLAGS)
+ BASELIB_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__THREADSFLAG) \
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 -DwxUSE_BASE=1 $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -626,7 +626,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DwxUSE_GUI=0 -DWXUSINGDLL -DWXMAKINGDLL_NET $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -649,7 +649,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DwxUSE_GUI=0 $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy \
+ $(CPPFLAGS) $(CXXFLAGS)
+@@ -671,7 +671,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_CORE -DwxUSE_BASE=0 \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -691,7 +691,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_BASE=0 $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -709,7 +709,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DWXUSINGDLL -DWXMAKINGDLL_ADV $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -721,7 +721,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+ $(CXXFLAGS)
+@@ -732,7 +732,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_MEDIA $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -748,7 +748,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -763,7 +763,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 -DWXUSINGDLL -DWXMAKINGDLL_ODBC \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -777,7 +777,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -789,7 +789,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_DBGRID $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -801,7 +801,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -812,7 +812,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_HTML $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -847,7 +847,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -881,7 +881,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DWXUSINGDLL -DWXMAKINGDLL_QA $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -894,7 +894,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+ $(CXXFLAGS)
+@@ -906,7 +906,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DwxUSE_GUI=0 -DWXUSINGDLL -DWXMAKINGDLL_XML $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -919,7 +919,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DwxUSE_GUI=0 $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy \
+ $(CPPFLAGS) $(CXXFLAGS)
+@@ -931,7 +931,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DWXUSINGDLL -DWXMAKINGDLL_XRC $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -997,7 +997,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+ $(CXXFLAGS)
+@@ -1062,7 +1062,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DWXUSINGDLL -DWXMAKINGDLL_AUI $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1078,7 +1078,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+ $(CXXFLAGS)
+@@ -1093,7 +1093,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_RICHTEXT $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1113,7 +1113,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1132,7 +1132,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ -DWXUSINGDLL -DWXMAKINGDLL_GL $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1144,7 +1144,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -I..\..\src\tiff -I..\..\src\jpeg \
++ -I$(SETUPHDIR) -I..\..\include -Wall -I..\..\src\tiff -I..\..\src\jpeg \
+ -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex -I..\..\src\expat\lib \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+ $(CXXFLAGS)
+diff -u contrib/build/stc/makefile.gcc contrib/build/stc/makefile.gcc
+--- contrib/build/stc/makefile.gcc 2006-12-11 22:50:27.000000000 +0100
++++ contrib/build/stc/makefile.gcc 2007-02-25 20:02:20.000000000 +0100
+@@ -23,7 +23,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\src\stc\..\..\..\include -W -Wall \
++ -I$(SETUPHDIR) -I..\..\src\stc\..\..\..\include -Wall \
+ -I..\..\src\stc\..\..\include -I..\..\src\stc\scintilla\include \
+ -I..\..\src\stc\scintilla\src -D__WX__ -DSCI_LEXER -DLINK_LEXERS \
+ -DWXUSINGDLL -DWXMAKINGDLL_STC $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+@@ -118,7 +118,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\src\stc\..\..\..\include -W -Wall \
++ -I$(SETUPHDIR) -I..\..\src\stc\..\..\..\include -Wall \
+ -I..\..\src\stc\..\..\include -I..\..\src\stc\scintilla\include \
+ -I..\..\src\stc\scintilla\src -D__WX__ -DSCI_LEXER -DLINK_LEXERS \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
--- /dev/null
+diff -r -u include/wx/msw/setup.h include/wx/msw/setup.h
+--- include/wx/msw/setup.h 2006-12-11 22:50:35.000000000 +0100
++++ include/wx/msw/setup.h 2007-02-25 19:39:56.000000000 +0100
+@@ -43,7 +43,7 @@
+ // in the version after it completely.
+ //
+ // Recommended setting: 0 (please update your code)
+-#define WXWIN_COMPATIBILITY_2_6 1
++#define WXWIN_COMPATIBILITY_2_6 0
+
+ // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
+ // default system font is used for wxWindow::GetCharWidth/Height() instead of
+@@ -157,7 +157,7 @@
+ //
+ // Recommended setting: 0 (unless you only plan to use Windows NT/2000/XP)
+ #ifndef wxUSE_UNICODE
+- #define wxUSE_UNICODE 0
++ #define wxUSE_UNICODE 0
+ #endif
+
+ // Setting wxUSE_WCHAR_T to 1 gives you some degree of Unicode support without
+@@ -335,7 +335,7 @@
+ // Default is 1
+ //
+ // Recommended setting: 1 (but may be safely disabled if you don't use it)
+-#define wxUSE_FSVOLUME 1
++#define wxUSE_FSVOLUME 0
+
+ // Use wxStandardPaths class which allows to retrieve some standard locations
+ // in the file system
+@@ -444,7 +444,7 @@
+ #define wxUSE_FS_ARCHIVE 1
+
+ // Set to 1 to enable virtual Internet filesystem (requires wxUSE_FILESYSTEM)
+-#define wxUSE_FS_INET 1
++#define wxUSE_FS_INET 0
+
+ // wxArchive classes for accessing archives such as zip and tar
+ #define wxUSE_ARCHIVE_STREAMS 1
+@@ -487,8 +487,8 @@
+
+ // The settings for the individual URL schemes
+ #define wxUSE_PROTOCOL_FILE 1
+-#define wxUSE_PROTOCOL_FTP 1
+-#define wxUSE_PROTOCOL_HTTP 1
++#define wxUSE_PROTOCOL_FTP 0
++#define wxUSE_PROTOCOL_HTTP 0
+
+ // Define this to use wxURL class.
+ #define wxUSE_URL 1
+@@ -990,7 +990,7 @@
+ // Default is 0.
+ //
+ // Recommended setting: 1 if you intend to use OpenGL, 0 otherwise
+-#define wxUSE_GLCANVAS 0
++#define wxUSE_GLCANVAS 1
+
+ // wxRichTextCtrl allows editing of styled text.
+ //
+@@ -1051,7 +1051,7 @@
+
+ #define wxUSE_DRAGIMAGE 1
+
+-#define wxUSE_IPC 1
++#define wxUSE_IPC 0
+ // 0 for no interprocess comms
+ #define wxUSE_HELP 1
+ // 0 for no help facility
+@@ -1172,7 +1172,7 @@
+ #define wxUSE_PCX 1
+
+ // Set to 1 for IFF format support (Amiga format)
+-#define wxUSE_IFF 0
++#define wxUSE_IFF 1
+
+ // Set to 1 for XPM format support
+ #define wxUSE_XPM 1
+@@ -1220,7 +1220,7 @@
+ //
+ // Recommended setting: 0 (1 if you want to deploy Unicode apps on 9x systems)
+ #ifndef wxUSE_UNICODE_MSLU
+- #define wxUSE_UNICODE_MSLU 0
++ #define wxUSE_UNICODE_MSLU 0
+ #endif
+
+ // Set this to 1 if you want to use wxWidgets and MFC in the same program. This
--- /dev/null
+diff -r -u include/wx/msw/setup.h include/wx/msw/setup.h
+--- include/wx/msw/setup.h 2006-12-11 22:50:35.000000000 +0100
++++ include/wx/msw/setup.h 2007-02-25 19:39:56.000000000 +0100
+@@ -43,7 +43,7 @@
+ // in the version after it completely.
+ //
+ // Recommended setting: 0 (please update your code)
+-#define WXWIN_COMPATIBILITY_2_6 1
++#define WXWIN_COMPATIBILITY_2_6 0
+
+ // MSW-only: Set to 0 for accurate dialog units, else 1 for old behaviour when
+ // default system font is used for wxWindow::GetCharWidth/Height() instead of
+@@ -157,7 +157,7 @@
+ //
+ // Recommended setting: 0 (unless you only plan to use Windows NT/2000/XP)
+ #ifndef wxUSE_UNICODE
+- #define wxUSE_UNICODE 0
++ #define wxUSE_UNICODE 1
+ #endif
+
+ // Setting wxUSE_WCHAR_T to 1 gives you some degree of Unicode support without
+@@ -335,7 +335,7 @@
+ // Default is 1
+ //
+ // Recommended setting: 1 (but may be safely disabled if you don't use it)
+-#define wxUSE_FSVOLUME 1
++#define wxUSE_FSVOLUME 0
+
+ // Use wxStandardPaths class which allows to retrieve some standard locations
+ // in the file system
+@@ -444,7 +444,7 @@
+ #define wxUSE_FS_ARCHIVE 1
+
+ // Set to 1 to enable virtual Internet filesystem (requires wxUSE_FILESYSTEM)
+-#define wxUSE_FS_INET 1
++#define wxUSE_FS_INET 0
+
+ // wxArchive classes for accessing archives such as zip and tar
+ #define wxUSE_ARCHIVE_STREAMS 1
+@@ -487,8 +487,8 @@
+
+ // The settings for the individual URL schemes
+ #define wxUSE_PROTOCOL_FILE 1
+-#define wxUSE_PROTOCOL_FTP 1
+-#define wxUSE_PROTOCOL_HTTP 1
++#define wxUSE_PROTOCOL_FTP 0
++#define wxUSE_PROTOCOL_HTTP 0
+
+ // Define this to use wxURL class.
+ #define wxUSE_URL 1
+@@ -990,7 +990,7 @@
+ // Default is 0.
+ //
+ // Recommended setting: 1 if you intend to use OpenGL, 0 otherwise
+-#define wxUSE_GLCANVAS 0
++#define wxUSE_GLCANVAS 1
+
+ // wxRichTextCtrl allows editing of styled text.
+ //
+@@ -1051,7 +1051,7 @@
+
+ #define wxUSE_DRAGIMAGE 1
+
+-#define wxUSE_IPC 1
++#define wxUSE_IPC 0
+ // 0 for no interprocess comms
+ #define wxUSE_HELP 1
+ // 0 for no help facility
+@@ -1172,7 +1172,7 @@
+ #define wxUSE_PCX 1
+
+ // Set to 1 for IFF format support (Amiga format)
+-#define wxUSE_IFF 0
++#define wxUSE_IFF 1
+
+ // Set to 1 for XPM format support
+ #define wxUSE_XPM 1
+@@ -1220,7 +1220,7 @@
+ //
+ // Recommended setting: 0 (1 if you want to deploy Unicode apps on 9x systems)
+ #ifndef wxUSE_UNICODE_MSLU
+- #define wxUSE_UNICODE_MSLU 0
++ #define wxUSE_UNICODE_MSLU 1
+ #endif
+
+ // Set this to 1 if you want to use wxWidgets and MFC in the same program. This
--- /dev/null
+diff -r -u build/msw/config.gcc build/msw/config.gcc
+--- build/msw/config.gcc 2006-12-11 22:50:33.000000000 +0100
++++ build/msw/config.gcc 2007-02-25 19:52:55.000000000 +0100
+@@ -77,7 +77,7 @@
+ USE_RICHTEXT := 1
+
+ # Build OpenGL canvas library (USE_GUI must be 1)? [0,1]
+-USE_OPENGL ?= 0
++USE_OPENGL ?= 1
+
+ # Build ODBC database classes (USE_GUI must be 1)? [0,1]
+ USE_ODBC := 0
--- /dev/null
+--- src/msw/mslu.cpp 2010-01-07 22:38:40.000000000 +0100
++++ src/msw/mslu.cpp 2010-01-07 22:39:45.000000000 +0100
+@@ -61,7 +61,7 @@
+ #include <io.h>
+ #include <sys/stat.h>
+
+-#ifdef __VISUALC__
++#if defined(__VISUALC__) || defined(__MINGW64_VERSION_MAJOR)
+ #include <direct.h>
+ #endif
+
--- /dev/null
+--- src/msw/version.rc 2009-03-06 05:11:24.000000000 -0700
++++ src/msw/version.rc 2009-11-09 11:27:26.874723200 -0700
+@@ -4,7 +4,7 @@
+ // Author: Vadim Zeitlin
+ // Modified by:
+ // Created: 09.07.00
+-// RCS-ID: $Id: version.rc 41690 2006-10-08 10:59:16Z VZ $
++// RCS-ID: $Id$
+ // Copyright: (c) 2000 Vadim Zeitlin
+ // Licence: wxWidgets license
+ ///////////////////////////////////////////////////////////////////////////////
+@@ -25,10 +25,16 @@
+ #define DLL_FLAGS 0x0L
+ #endif
+
++// 0x0409 is US English, 0x04b0 is Unicode and 0x0000 is 7 bit ASCII. see
++// http://msdn.microsoft.com/en-us/library/aa381049(VS.85).aspx for the full
++// list of languages and charsets
++#define LANG 0x0409
+ #ifdef _UNICODE
+- #define LANG "04090000"
++ #define CHARSET 0x4b0
++ #define LANG_WITH_CHARSET "040904b0"
+ #else
+- #define LANG "040904b0"
++ #define CHARSET 0
++ #define LANG_WITH_CHARSET "04090000"
+ #endif
+
+ 1 VERSIONINFO
+@@ -42,15 +48,14 @@
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+- // US English Ascii; see http://msdn.microsoft.com/library/psdk/winui/rc_3rxn.htm for codes
+- BLOCK LANG
++ BLOCK LANG_WITH_CHARSET
+ BEGIN
+ VALUE "Comments", "wxWidgets cross-platform GUI framework\0"
+ VALUE "CompanyName", "wxWidgets development team\0"
+ VALUE "FileDescription", "wxWidgets for MSW\0"
+ VALUE "FileVersion", "wxWidgets Library " wxVERSION_NUM_DOT_STRING "\0"
+ VALUE "InternalName", "wxMSW\0"
+- VALUE "LegalCopyright", "Copyright © 1993-2006 wxWidgets development team\0"
++ VALUE "LegalCopyright", "Copyright 1993-2009 wxWidgets development team\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", wxSTRINGIZE(WXDLLNAME) ".dll\0"
+ VALUE "PrivateBuild", "\0"
+@@ -59,4 +64,8 @@
+ VALUE "SpecialBuild", "\0"
+ END
+ END
++ BLOCK "VarFileInfo"
++ BEGIN
++ VALUE "Translation", LANG, CHARSET
++ END
+ END
--- /dev/null
+diff -r -u build/msw/config.gcc build/msw/config.gcc
+--- build/msw/config.gcc 2006-12-11 22:50:33.000000000 +0100
++++ build/msw/config.gcc 2007-02-25 19:52:55.000000000 +0100
+@@ -77,7 +77,7 @@
+ USE_RICHTEXT := 1
+
+ # Build OpenGL canvas library (USE_GUI must be 1)? [0,1]
+-USE_OPENGL ?= 0
++USE_OPENGL ?= 1
+
+ # Build ODBC database classes (USE_GUI must be 1)? [0,1]
+ USE_ODBC := 0
--- /dev/null
+--- build/msw/makefile.gcc 2009-09-04 06:51:41.000000000 +0200
++++ build/msw/makefile.gcc 2009-10-18 14:58:05.000000000 +0200
+@@ -276,7 +276,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_BASE=1 -DWXMAKINGDLL \
+ -I..\..\src\stc\scintilla\include -I..\..\src\stc\scintilla\src -D__WX__ \
+@@ -285,7 +285,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DwxUSE_BASE=1 -DWXMAKINGDLL \
+ -I..\..\src\stc\scintilla\include -I..\..\src\stc\scintilla\src -D__WX__ \
+@@ -416,7 +416,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_BASE=1 -I..\..\src\stc\scintilla\include \
+ -I..\..\src\stc\scintilla\src -D__WX__ -DSCI_LEXER -DLINK_LEXERS $(CPPFLAGS) \
+@@ -425,7 +425,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DwxUSE_BASE=1 \
+ -I..\..\src\stc\scintilla\include -I..\..\src\stc\scintilla\src -D__WX__ \
+@@ -555,7 +555,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 -DWXMAKINGDLL_BASE -DwxUSE_BASE=1 \
+ $(CPPFLAGS) $(CFLAGS)
+@@ -563,7 +563,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DwxUSE_GUI=0 -DWXMAKINGDLL_BASE \
+ -DwxUSE_BASE=1 $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy \
+@@ -678,14 +678,14 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 -DwxUSE_BASE=1 $(CPPFLAGS) $(CFLAGS)
+ BASELIB_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__THREADSFLAG) \
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DwxUSE_GUI=0 -DwxUSE_BASE=1 \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -799,7 +799,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 -DWXUSINGDLL -DWXMAKINGDLL_NET \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -823,7 +823,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -845,7 +845,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_CORE \
+ -DwxUSE_BASE=0 $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy \
+@@ -866,7 +866,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DwxUSE_BASE=0 $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -885,7 +885,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_ADV $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -897,7 +897,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -908,7 +908,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_MEDIA \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -924,7 +924,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -938,7 +938,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_HTML \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -974,7 +974,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1008,7 +1008,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_QA $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1021,7 +1021,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1033,7 +1033,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 -DWXUSINGDLL -DWXMAKINGDLL_XML \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -1047,7 +1047,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DwxUSE_GUI=0 $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1059,7 +1059,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_XRC $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1129,7 +1129,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1198,7 +1198,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_AUI $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1215,7 +1215,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1231,7 +1231,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_PROPGRID \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -1251,7 +1251,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1269,7 +1269,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_RICHTEXT \
+ $(__RTTIFLAG) $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) \
+@@ -1290,7 +1290,7 @@
+ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \
+ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \
+ $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) \
+- $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING \
++ $(__GFXCTX_DEFINE_p) -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING \
+ -I..\..\src\tiff\libtiff -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib \
+ -I..\..\src\regex -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1309,7 +1309,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -I..\..\src\stc\scintilla\include \
+ -I..\..\src\stc\scintilla\src -D__WX__ -DSCI_LEXER -DLINK_LEXERS \
+@@ -1325,7 +1325,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -I..\..\src\stc\scintilla\include \
+ -I..\..\src\stc\scintilla\src -D__WX__ -DSCI_LEXER -DLINK_LEXERS \
+@@ -1340,7 +1340,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib -DWXUSINGDLL -DWXMAKINGDLL_GL $(__RTTIFLAG) \
+ $(__EXCEPTIONSFLAG) -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
+@@ -1353,7 +1353,7 @@
+ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \
+ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \
+ $(__UNICODE_DEFINE_p) $(__MSLU_DEFINE_p) $(__GFXCTX_DEFINE_p) \
+- -I$(SETUPHDIR) -I..\..\include -W -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
++ -I$(SETUPHDIR) -I..\..\include -Wall -DWXBUILDING -I..\..\src\tiff\libtiff \
+ -I..\..\src\jpeg -I..\..\src\png -I..\..\src\zlib -I..\..\src\regex \
+ -I..\..\src\expat\lib $(__RTTIFLAG) $(__EXCEPTIONSFLAG) \
+ -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
--- /dev/null
+--- include/wx/msw/setup.h 2009-09-04 06:53:17.000000000 +0200
++++ include/wx/msw/setup.h 2009-10-18 14:52:51.000000000 +0200
+@@ -361,7 +361,7 @@
+ // Default is 1
+ //
+ // Recommended setting: 1 (but may be safely disabled if you don't use it)
+-#define wxUSE_FSVOLUME 1
++#define wxUSE_FSVOLUME 0
+
+ // Use wxStandardPaths class which allows to retrieve some standard locations
+ // in the file system
+@@ -496,7 +496,7 @@
+ #define wxUSE_FS_ARCHIVE 1
+
+ // Set to 1 to enable virtual Internet filesystem (requires wxUSE_FILESYSTEM)
+-#define wxUSE_FS_INET 1
++#define wxUSE_FS_INET 0
+
+ // wxArchive classes for accessing archives such as zip and tar
+ #define wxUSE_ARCHIVE_STREAMS 1
+@@ -542,8 +542,8 @@
+
+ // The settings for the individual URL schemes
+ #define wxUSE_PROTOCOL_FILE 1
+-#define wxUSE_PROTOCOL_FTP 1
+-#define wxUSE_PROTOCOL_HTTP 1
++#define wxUSE_PROTOCOL_FTP 0
++#define wxUSE_PROTOCOL_HTTP 0
+
+ // Define this to use wxURL class.
+ #define wxUSE_URL 1
+@@ -1098,7 +1098,7 @@
+ // Default is 0.
+ //
+ // Recommended setting: 1 if you intend to use OpenGL, 0 otherwise
+-#define wxUSE_GLCANVAS 0
++#define wxUSE_GLCANVAS 1
+
+ // wxRichTextCtrl allows editing of styled text.
+ //
+@@ -1159,7 +1159,7 @@
+
+ #define wxUSE_DRAGIMAGE 1
+
+-#define wxUSE_IPC 1
++#define wxUSE_IPC 0
+ // 0 for no interprocess comms
+ #define wxUSE_HELP 1
+ // 0 for no help facility
+@@ -1260,7 +1260,7 @@
+ #define wxUSE_PCX 1
+
+ // Set to 1 for IFF format support (Amiga format)
+-#define wxUSE_IFF 0
++#define wxUSE_IFF 1
+
+ // Set to 1 for XPM format support
+ #define wxUSE_XPM 1
+@@ -1309,7 +1309,7 @@
+ //
+ // Recommended setting: 0 (1 if you want to deploy Unicode apps on 9x systems)
+ #ifndef wxUSE_UNICODE_MSLU
+- #define wxUSE_UNICODE_MSLU 0
++ #define wxUSE_UNICODE_MSLU 1
+ #endif
+
+ // Set this to 1 if you want to use wxWidgets and MFC in the same program. This
--- /dev/null
+--- src/msw/version.rc 2009-09-03 23:52:55.000000000 -0600
++++ src/msw/version.rc 2009-11-09 11:13:37.070976000 -0700
+@@ -4,7 +4,7 @@
+ // Author: Vadim Zeitlin
+ // Modified by:
+ // Created: 09.07.00
+-// RCS-ID: $Id: version.rc 49081 2007-10-07 19:49:09Z VZ $
++// RCS-ID: $Id$
+ // Copyright: (c) 2000 Vadim Zeitlin
+ // Licence: wxWidgets license
+ ///////////////////////////////////////////////////////////////////////////////
+@@ -25,10 +25,16 @@
+ #define DLL_FLAGS 0x0L
+ #endif
+
++// 0x0409 is US English, 0x04b0 is Unicode and 0x0000 is 7 bit ASCII. see
++// http://msdn.microsoft.com/en-us/library/aa381049(VS.85).aspx for the full
++// list of languages and charsets
++#define LANG 0x0409
+ #ifdef _UNICODE
+- #define LANG "04090000"
++ #define CHARSET 0x4b0
++ #define LANG_WITH_CHARSET "040904b0"
+ #else
+- #define LANG "040904b0"
++ #define CHARSET 0
++ #define LANG_WITH_CHARSET "04090000"
+ #endif
+
+ 1 VERSIONINFO
+@@ -42,15 +48,14 @@
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+- // US English Ascii; see http://msdn.microsoft.com/library/psdk/winui/rc_3rxn.htm for codes
+- BLOCK LANG
++ BLOCK LANG_WITH_CHARSET
+ BEGIN
+ VALUE "Comments", "wxWidgets cross-platform GUI framework\0"
+ VALUE "CompanyName", "wxWidgets development team\0"
+ VALUE "FileDescription", "wxWidgets for MSW\0"
+ VALUE "FileVersion", "wxWidgets Library " wxVERSION_NUM_DOT_STRING "\0"
+ VALUE "InternalName", "wxMSW\0"
+- VALUE "LegalCopyright", "Copyright © 1993-2007 wxWidgets development team\0"
++ VALUE "LegalCopyright", "Copyright 1993-2009 wxWidgets development team\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", wxSTRINGIZE(WXDLLNAME) ".dll\0"
+ VALUE "PrivateBuild", "\0"
+@@ -59,4 +64,8 @@
+ VALUE "SpecialBuild", "\0"
+ END
+ END
++ BLOCK "VarFileInfo"
++ BEGIN
++ VALUE "Translation", LANG, CHARSET
++ END
+ END
--- /dev/null
+diff -u include/wx/scopeguard.h include/wx/scopeguard.h
+--- include/wx/scopeguard.h 2007-11-21 21:17:54.000000000 +0100
++++ include/wx/scopeguard.h 2007-11-21 21:16:43.000000000 +0100
+@@ -108,7 +108,7 @@
+ // for OnScopeExit() only (we can't make it friend, unfortunately)!
+ bool WasDismissed() const { return m_wasDismissed; }
+
+-protected:
++public:
+ ~wxScopeGuardImplBase() { }
+
+ wxScopeGuardImplBase(const wxScopeGuardImplBase& other)
--- /dev/null
+--- src/osx/cocoa/textctrl.mm 2009-09-04 06:53:00.000000000 +0200
++++ src/osx/cocoa/textctrl.mm 2009-10-18 20:47:57.000000000 +0200
+@@ -141,7 +141,7 @@
+
+ - (void) keyDown:(NSEvent*) event
+ {
+- wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( [self delegate] );
++ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
+ lastKeyDownEvent = event;
+ if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
+ [super keyDown:event];
+@@ -150,14 +150,14 @@
+
+ - (void) keyUp:(NSEvent*) event
+ {
+- wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( [self delegate] );
++ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
+ if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
+ [super keyUp:event];
+ }
+
+ - (void) flagsChanged:(NSEvent*) event
+ {
+- wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( [self delegate] );
++ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
+ if ( impl == NULL || !impl->DoHandleKeyEvent(event) )
+ [super flagsChanged:event];
+ }
+@@ -170,7 +170,7 @@
+
+ - (void) insertText:(id) str
+ {
+- wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( [self delegate] );
++ wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( (WXWidget) [self delegate] );
+ if ( impl == NULL || lastKeyDownEvent==nil || !impl->DoHandleCharEvent(lastKeyDownEvent, str) )
+ {
+ [super insertText:str];
+@@ -318,7 +318,7 @@
+
+ [m_scrollView setDocumentView: tv];
+
+- [tv setDelegate: w];
++ [tv setDelegate: (WXWidget) w];
+
+ InstallEventHandler(tv);
+ }
+@@ -433,7 +433,7 @@
+ wxNSTextFieldControl::wxNSTextFieldControl( wxTextCtrl *wxPeer, WXWidget w ) : wxWidgetCocoaImpl(wxPeer, w)
+ {
+ m_textField = (NSTextField*) w;
+- [m_textField setDelegate: w];
++ [m_textField setDelegate: (WXWidget) w];
+ m_selStart = m_selEnd = 0;
+ m_hasEditor = [w isKindOfClass:[NSTextField class]];
+ }
--- /dev/null
+diff -r -u src/generic/grid.cpp src/generic/grid.cpp
+--- src/generic/grid.cpp 2006-12-11 22:49:47.000000000 +0100
++++ src/generic/grid.cpp 2007-02-25 19:58:45.000000000 +0100
+@@ -8045,7 +8045,7 @@
+ break;
+ }
+
+- if ( textOrientation == wxHORIZONTAL )
++ if ( textOrientation != wxVERTICAL )
+ {
+ dc.DrawText( line, x, y );
+ y += lineHeight;
--- /dev/null
+diff -r -u src/gtk/gsockgtk.cpp src/gtk/gsockgtk.cpp
+--- src/gtk/gsockgtk.cpp 2009-10-12 12:31:05.852113325 +0200
++++ src/gtk/gsockgtk.cpp 2009-10-12 12:31:30.832115248 +0200
+@@ -15,8 +15,10 @@
+ #include <stdlib.h>
+ #include <stdio.h>
+
++#define GSocket GlibGSocket
+ #include <gdk/gdk.h>
+ #include <glib.h>
++#undef GSocket
+
+ #include "wx/gsocket.h"
+ #include "wx/unix/gsockunx.h"
--- /dev/null
+--- src/generic/grid.cpp 2009-09-04 06:52:48.000000000 +0200
++++ src/generic/grid.cpp 2009-10-18 14:43:42.000000000 +0200
+@@ -5597,7 +5597,7 @@
+ break;
+ }
+
+- if ( textOrientation == wxHORIZONTAL )
++ if ( textOrientation != wxVERTICAL )
+ {
+ dc.DrawText( line, x, y );
+ y += lineHeight;
--- /dev/null
+--- include/wx/msgdlg.h 2009-09-04 06:51:55.000000000 +0200
++++ include/wx/msgdlg.h 2009-10-18 23:06:17.000000000 +0200
+@@ -276,10 +276,10 @@
+ private:
+ // these functions may be overridden to provide different defaults for the
+ // default button labels (this is used by wxGTK)
+- virtual wxString GetDefaultYesLabel() const { return _("Yes"); }
+- virtual wxString GetDefaultNoLabel() const { return _("No"); }
+- virtual wxString GetDefaultOKLabel() const { return _("OK"); }
+- virtual wxString GetDefaultCancelLabel() const { return _("Cancel"); }
++ virtual wxString GetDefaultYesLabel() const { return wxGetTranslation("Yes"); }
++ virtual wxString GetDefaultNoLabel() const { return wxGetTranslation("No"); }
++ virtual wxString GetDefaultOKLabel() const { return wxGetTranslation("OK"); }
++ virtual wxString GetDefaultCancelLabel() const { return wxGetTranslation("Cancel"); }
+
+ // labels for the buttons, initially empty meaning that the defaults should
+ // be used, use GetYes/No/OK/CancelLabel() to access them
--- /dev/null
+#!/usr/bin/perl -w
+#############################################################################
+## Name: script/make_ppm.pl
+## Purpose: builds the Alien-wxWidgets and Alien-wxWidgets-dev PPMs
+## Author: Mattia Barbon
+## Modified by:
+## Created: 25/08/2003
+## RCS-ID: $Id: make_ppm.pl,v 1.1 2006/03/15 18:42:21 mbarbon Exp $
+## Copyright: (c) 2003, 2006 Mattia Barbon
+## Licence: This program is free software; you can redistribute it and/or
+## modify it under the same terms as Perl itself
+#############################################################################
+
+use strict;
+use File::Find;
+use Archive::Tar 0.23;
+use Module::Info;
+use Config;
+
+find( { wanted => \&wanted,
+ },
+ 'blib' );
+
+my @files;
+
+sub wanted {
+ return unless -f $_;
+ push @files, $File::Find::name;
+}
+
+my( @dev, @bin );
+
+foreach ( @files ) {
+ if( m[\.(?:lib|a|h)$]i
+ ) {
+ push @dev, $_;
+ next;
+ }
+
+ push @bin, $_;
+}
+
+my $auth = 'Mattia Barbon <mbarbon@cpan.org>';
+my $wx_ver = Module::Info->new_from_file( 'lib/Alien/wxWidgets.pm' )->version;
+
+my @ppms =
+ ( { files => [ @bin ],
+ package => 'Alien-wxWidgets',
+ version => $wx_ver,
+ abstract => 'get information about a wxWidgets build',
+ author => $auth,
+ },
+ { files => [ @dev ],
+ package => 'Alien-wxWidgets-dev',
+ version => $wx_ver,
+ abstract => 'developement files for Alien-wxWidgets',
+ author => $auth,
+ },
+ );
+
+foreach my $ppm ( @ppms ) {
+ make_ppm( %$ppm );
+}
+
+sub make_ppm {
+ my %data = @_;
+ my $tar = Archive::Tar->new;
+ my $pack_ver = join ",", (split (/\./, $data{version}), (0) x 4) [0 .. 3];
+ my $author = $data{author}; $author =~ s/</</g; $author =~ s/>/>/g;
+ my $arch = $Config{archname} . ( $] >= 5.008 ? '-5.8' : '' );
+ my $base = $data{package} . '-' . $data{version};
+ my $tarfile = "$base-ppm.tar.gz";
+ my $ppdfile = "$base.ppd";
+ my $ppd = <<EOT;
+<SOFTPKG NAME="$data{package}" VERSION="$pack_ver">
+ <TITLE>$data{package}</TITLE>
+ <ABSTRACT>$data{abstract}</ABSTRACT>
+ <AUTHOR>$author</AUTHOR>
+ <IMPLEMENTATION>
+ <OS NAME="$^O" />
+ <ARCHITECTURE NAME="$arch" />
+ <CODEBASE HREF="$tarfile" />
+ </IMPLEMENTATION>
+</SOFTPKG>
+EOT
+
+ $tar->add_files( @{$data{files}} );
+ $tar->write( $tarfile, 9 );
+
+ local *PPD;
+ open PPD, "> $ppdfile" or die "open '$ppdfile': $!";
+ binmode PPD;
+ print PPD $ppd;
+ close PPD;
+}
+
+exit 0;
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+use Test::More tests => 1;
+
+use_ok( 'Alien::wxWidgets' );
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+use Test::More;
+eval "use Test::Pod::Coverage 1.00";
+plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage"
+ if $@;
+plan( tests => 1 );
+pod_coverage_ok( 'Alien::wxWidgets' );
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+use Test::More;
+eval "use Test::Pod 1.00";
+
+plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
+Test::Pod::all_pod_files_ok( Test::Pod::all_pod_files( qw(lib inc/My) ) );
--- /dev/null
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+Format: 1.0
+Source: libalien-wxwidgets-perl
+Binary: libalien-wxwidgets-perl
+Architecture: any
+Version: 0.50+dfsg-1
+Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
+Uploaders: Roberto C. Sanchez <roberto@connexer.com>, Damyan Ivanov <dmn@debian.org>, Jonathan Yu <jawnsy@cpan.org>, Ryan Niebur <ryan@debian.org>
+Homepage: http://search.cpan.org/dist/Alien-wxWidgets/
+Standards-Version: 3.8.3
+Vcs-Browser: http://svn.debian.org/viewsvn/pkg-perl/trunk/libalien-wxwidgets-perl/
+Vcs-Svn: svn://svn.debian.org/pkg-perl/trunk/libalien-wxwidgets-perl/
+Build-Depends: debhelper (>= 7.0.50~), quilt (>= 0.46-7), perl (>= 5.10.1), libmodule-pluggable-perl, libwxgtk2.8-dev (>= 2.8.10.1), libtest-pod-perl, libtest-pod-coverage-perl
+Checksums-Sha1:
+ ada19ce2aca5a7034d031d96449600f49177c51e 98670 libalien-wxwidgets-perl_0.50+dfsg.orig.tar.gz
+ e10890810796a72825b22a76c0900e7215e69c25 5853 libalien-wxwidgets-perl_0.50+dfsg-1.diff.gz
+Checksums-Sha256:
+ 1579dfb263d27423d71fd5d86ec6bd2bb8a2ca0952f4ce6b0cdfe762a5bf3386 98670 libalien-wxwidgets-perl_0.50+dfsg.orig.tar.gz
+ 488f456a64bfed89db5adc46ab03ba757dd41c316c2758caae5f3f90b8715ef3 5853 libalien-wxwidgets-perl_0.50+dfsg-1.diff.gz
+Files:
+ b1e3c1ac9fe4f27d51b0982d7796d6b3 98670 libalien-wxwidgets-perl_0.50+dfsg.orig.tar.gz
+ 5818d400cf10c8f5a54d982e1ae17e45 5853 libalien-wxwidgets-perl_0.50+dfsg-1.diff.gz
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.9 (GNU/Linux)
+
+iEYEARECAAYFAktf8Z4ACgkQMihv+PacasW+SACgnJZkkWxeN3GihfkdFTAO7Mx3
+ue4An2uhZ7ytsG/DT8Bv8A8pUFpbQxNb
+=bjLh
+-----END PGP SIGNATURE-----
--- /dev/null
+Format: 1.0
+Source: libalien-wxwidgets-perl
+Version: 0.50-1maemo1
+Binary: libalien-wxwidgets-perl
+Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
+Architecture: any
+Standards-Version: 3.8.3
+Build-Depends: debhelper7, quilt, perl (>= 5.8.3), libmodule-pluggable-perl, libwxgtk2.8-dev (>= 2.8.10.1), libtest-pod-perl, libtest-pod-coverage-perl
+Uploaders: Roberto C. Sanchez <roberto@connexer.com>, Damyan Ivanov <dmn@debian.org>, Jonathan Yu <jawnsy@cpan.org>, Ryan Niebur <ryan@debian.org>
+Files:
+ 08da04b75bdcacda93c50b67e44e4a4c 105969 libalien-wxwidgets-perl_0.50-1maemo1.tar.gz
--- /dev/null
+Format: 1.7
+Date: Fri, 16 Apr 2010 06:53:44 +0100
+Source: libalien-wxwidgets-perl
+Binary: libalien-wxwidgets-perl
+Architecture: source armel
+Version: 0.50-1maemo1
+Distribution: fremantle
+Urgency: low
+Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
+Changed-By: Nito Martinez <Nito@Qindel.ES>
+Description:
+ libalien-wxwidgets-perl - Perl module for locating wxWidgets binaries
+Changes:
+ libalien-wxwidgets-perl (0.50-1maemo1) fremantle; urgency=low
+ .
+ * New Maemo packaging
+Files:
+ 0b8579162da0c9dddf2811676843f0ca 610 perl optional libalien-wxwidgets-perl_0.50-1maemo1.dsc
+ 08da04b75bdcacda93c50b67e44e4a4c 105969 perl optional libalien-wxwidgets-perl_0.50-1maemo1.tar.gz
+ 435a2f31f51f4518dafb37095ca22a02 9020 perl optional libalien-wxwidgets-perl_0.50-1maemo1_armel.deb
--- /dev/null
+Format: 1.7
+Date: Fri, 16 Apr 2010 06:53:44 +0100
+Source: libalien-wxwidgets-perl
+Binary: libalien-wxwidgets-perl
+Architecture: source i386
+Version: 0.50-1maemo1
+Distribution: fremantle
+Urgency: low
+Maintainer: Debian Perl Group <pkg-perl-maintainers@lists.alioth.debian.org>
+Changed-By: Nito Martinez <Nito@Qindel.ES>
+Description:
+ libalien-wxwidgets-perl - Perl module for locating wxWidgets binaries
+Changes:
+ libalien-wxwidgets-perl (0.50-1maemo1) fremantle; urgency=low
+ .
+ * New Maemo packaging
+Files:
+ 21717726aa8a32331394571c4d0f7626 610 perl optional libalien-wxwidgets-perl_0.50-1maemo1.dsc
+ 68c4ee64a3e7a103380c676f8518f809 105967 perl optional libalien-wxwidgets-perl_0.50-1maemo1.tar.gz
+ 11a8495e04c9e3927dd93ecad5043f34 9044 perl optional libalien-wxwidgets-perl_0.50-1maemo1_i386.deb