CGI-Compile
view release on metacpan or search on metacpan
lib/CGI/Compile.pm view on Meta::CPAN
use File::Basename;
use File::Spec::Functions;
use File::pushd;
use File::Temp;
use File::Spec;
use File::Path;
use Sub::Name 'subname';
our $RETURN_EXIT_VAL = undef;
sub new {
my ($class, %opts) = @_;
$opts{namespace_root} ||= 'CGI::Compile::ROOT';
bless \%opts, $class;
}
our $USE_REAL_EXIT;
BEGIN {
$USE_REAL_EXIT = 1;
my $orig = *CORE::GLOBAL::exit{CODE};
my $proto = $orig ? prototype $orig : prototype 'CORE::exit';
$proto = $proto ? "($proto)" : '';
$orig ||= sub {
my $exit_code = shift;
CORE::exit(defined $exit_code ? $exit_code : 0);
};
no warnings 'redefine';
*CORE::GLOBAL::exit = eval qq{
sub $proto {
my \$exit_code = shift;
\$orig->(\$exit_code) if \$USE_REAL_EXIT;
die [ "EXIT\n", \$exit_code || 0 ]
};
};
die $@ if $@;
}
my %anon;
sub compile {
my($class, $script, $package) = @_;
my $self = ref $class ? $class : $class->new;
my($code, $path, $dir, $subname);
if (ref $script eq 'SCALAR') {
$code = $$script;
$package ||= (caller)[0];
$subname = '__CGI' . $anon{$package}++ . '__';
} else {
$code = $self->_read_source($script);
$path = Cwd::abs_path($script);
$dir = File::Basename::dirname($path);
my $genned_package;
($genned_package, $subname) = $self->_build_subname($path || $script);
$package ||= $genned_package;
}
my $warnings = $code =~ /^#!.*\s-w\b/ ? 1 : 0;
$code =~ s/^__END__\r?\n.*//ms;
$code =~ s/^__DATA__\r?\n(.*)//ms;
my $data = defined $1 ? $1 : '';
# TODO handle nph and command line switches?
my $eval = join '',
"package $package;",
'sub {',
'local $CGI::Compile::USE_REAL_EXIT = 0;',
"\nCGI::initialize_globals() if defined &CGI::initialize_globals;",
'local ($0, $CGI::Compile::_dir, *DATA);',
'{ my ($data, $path, $dir) = @_[1..3];',
($path ? '$0 = $path;' : ''),
($dir ? '$CGI::Compile::_dir = File::pushd::pushd $dir;' : ''),
q{open DATA, '<', \$data;},
'}',
# NOTE: this is a workaround to fix a problem in Perl 5.10
q(local @SIG{keys %SIG} = do { no warnings 'uninitialized'; @{[]} = values %SIG };),
"local \$^W = $warnings;",
'my $rv = eval {',
'local @ARGV = @{ $_[4] };', # args to @ARGV
'local @_ = @{ $_[4] };', # args to @_ as well
($path ? "\n#line 1 $path\n" : ''),
$code,
"\n};",
q{
{
no warnings qw(uninitialized numeric pack);
my $self = shift;
my $exit_val = unpack('C', pack('C', sprintf('%.0f', $rv)));
if ($@) {
die $@ unless (
ref($@) eq 'ARRAY' and
$@->[0] eq "EXIT\n"
);
my $exit_param = unpack('C', pack('C', sprintf('%.0f', $@->[1])));
if ($exit_param != 0 && !$CGI::Compile::RETURN_EXIT_VAL && !$self->{return_exit_val}) {
die "exited nonzero: $exit_param";
}
$exit_val = $exit_param;
}
( run in 2.262 seconds using v1.01-cache-2.11-cpan-e1769b4cff6 )