# PerlCode; allow arbitrary perl code be embedded in a WebMake file. package HTML::WebMake::PerlCode; use Carp; use strict; use HTML::WebMake::Main; use HTML::WebMake::PerlCodeLibrary; use vars qw{ @ISA $CAN_USE_IO_STRING $GlobalSelf @PrevSelves %SORT_SUBS }; @ISA = qw(); ########################################################################### sub new ($$) { my $class = shift; $class = ref($class) || $class; my ($main) = @_; my $self = { 'main' => $main, }; bless ($self, $class); $self; } sub can_use_io_string { if (defined $CAN_USE_IO_STRING) { return $CAN_USE_IO_STRING; } $CAN_USE_IO_STRING = 0; eval q{ require IO::String; $CAN_USE_IO_STRING = 1; 1; }; return $CAN_USE_IO_STRING; } sub new_io_string { eval q{ return new IO::String (); }; } sub dbg { HTML::WebMake::Main::dbg (@_); } # ------------------------------------------------------------------------- sub interpret { my ($self, $type, $str, $defunderscoreval) = @_; my ($ret); local ($_) = $defunderscoreval; if (!defined ($_)) { $_ = ''; } if ($self->{main}->{paranoid}) { return "\n(Paranoid mode on - perl code evaluation prohibited.)\n"; } # note that both $self and $_ are available from within evaluated # perl code. $self->enter_perl_call(); if ($type ne "perlout") { $ret = eval 'package main; '.$str; } else { if (!can_use_io_string()) { warn "<{perlout}> code failed: IO::String module not available\n"; } else { my $outhandle = new_io_string(); $ret = eval 'package main; select $outhandle; '.$str; if (defined($ret)) { $ret = ${$outhandle->string_ref()}; chomp $ret; } select STDOUT; $outhandle = undef; } } $self->exit_perl_call(); if (!defined $ret) { warn "<{perl}> code failed: $@\nCode: $str\n"; $ret = ''; } $ret; } sub enter_perl_call { my ($self) = @_; push (@PrevSelves, $GlobalSelf); $GlobalSelf = $self; } sub exit_perl_call { my ($self) = @_; $GlobalSelf = pop (@PrevSelves); } # ------------------------------------------------------------------------- # get and eval() a sort subroutine for the given sorting criteria. # stores cached sort sub { } refs in the %SORT_SUBS global array to # avoid re-evaluating the same piece of perl code repeatedly. # sub get_sort_sub { my ($self, $sortstr) = @_; if (!defined $SORT_SUBS{$sortstr}) { my $sortsubstr = $self->{main}->{metadata}->string_to_sort_sub ($sortstr); my $sortsub = eval $sortsubstr; $SORT_SUBS{$sortstr} = $sortsub; } $SORT_SUBS{$sortstr}; } # ------------------------------------------------------------------------- 1;