Perl load module BEGIN - perl

I have this code
print "Starting\n";
BEGIN {
$module='Data::Dumper';
$module_available=1;
eval "use $module; 1" or $module_available = 0;
}
$var=1;
print "Module=$module_available\n";
print Dumper $var if ($module_available==1);
and the output is
Starting
Module=1
$VAR1 = 1;
and this
print "Starting\n";
$module='Data::Dumper';
$module_available=1;
eval "use $module; 1" or $module_available = 0;
$var=1;
print "Module=$module_available\n";
print Dumper $var if ($module_available==1);
and the output
Starting
Module=1
Why on the first scenario the variable is printed

You should always
use strict;
use warnings;
In your second example, when your code is compiled, Dumper is not known as a function. So perl treats it as a bareword filehandle. If you use warnings, you get
print() on unopened filehandle Dumper at file.pl line 10.
In the first example you wrap the eval in a BEGIN block. So Dumperis already imported when the line of its usage gets compiled.
You can read more about BEGIN blocks here: perlmod

Related

Perl, how to read from stdin outside a loop?

There is something I don't understand :
say in is a file containing :
1
2
3
and foo.pl :
use strict;
<>;
print;
<>;
print;
<>;
print;
and then run :
perl foo.pl < in
Why this programm doesn't output anything ?
...While this one :
use strinct;
while(<>) {
print;
}
output the whole file
Because
while(<>)
Is shorthand for
while($_ = <>)
Which means the line is assigned to the default variable $_. Which is also used by print.
What you wrote:
<>;
Does not assign anything to $_. It is just a readline in void context, which means the value is discarded and not stored anywhere. Hence $_ is empty. If you use warnings, Perl will tell you what is going on.
Use of uninitialized value $_ in print
If you do the assignment manually it will work:
$_ = <>;
Note also that you do not have to redirect the file content, you can just supply the file name as an argument:
perl foo.pl in

Avoid redefining a perl format in an eval

I've got a subroutine that delares a format in an eval expression. If this subroutine gets called more than once, perl warns that a format has been redefined.
This code:
use warnings;
routine();
routine();
sub routine{
my $s = "FAIL";
my $def = "format =\n#<<<<#>>>>\n\$s, \$s\n.";
eval $def;
write;
}
prints
FAIL FAIL
Format STDOUT redefined at (eval 2) line 1.
FAIL FAIL
Is it possible to delete the format declaration at the end of the subroutine?
Here is a simple solution that uses a flag to avoid redefining the format.
use strict;
use warnings;
routine();
routine();
my $format_defined;
sub routine{
my $s = "FAIL";
if (!$format_defined) {
my $def = "format =\n#<<<<#>>>>\n\$s, \$s\n.";
eval $def;
$format_defined = 1;
}
write;
}
Here is a more sophisticated solution that allows for the format to be redefined for each call. It uses a temporary filehandle in place of STDOUT that redirects the output to a scalar, which you can then print to STDOUT.
routine('FAIL');
routine('PASS');
sub routine{
my $s = shift;
format REPORT =
#<<<<#>>>>
$s, $s
.
my $report;
open my $fh, '>', \$report;
select $fh;
$~ = 'REPORT';
write;
close $fh;
select STDOUT;
print $report;
}

Breakpoint in function in different file

I have two Perl files like this. Using perl5db.pl I am trying to set a breakpoint at line 7 in file2.pl but sadly it doesn't let me. I looked for answers, and found that I can use modules, but file2.pl isn't using modules. What can I do?
#file.pl is
#!/usr/bin/perl
use strict;
use warnings;
require "file2.pl";
# This file is a test file to run the debugger on.
hello();
my $var = 1;
my $var2 = 2;
makeEqual();
sub main {
if($var == $var2){
print "they are equal\n";
}
else {
print "they are not equal\n";
makeEqual();
}
my $value =2;
print "the value is $value\n";
}
sub makeEqual {
$var = $var2;
my $str = " this is crazy";
$str =~ s/\s+/ /g;
print "$str is done \n";
}
main();
#file2.pl is
#!/usr/bin/perl
use strict;
use warnings;
sub hello {
print "I am in hello";
}
1;
Just after init your debugger set a breakpoint to stop after compiling your function of file2.pl, and when the debugger stops at that point, the return statement (instruction 1;) you will be able to see the hello function of that file.
Execute the debugger:
perl -d file.pl
Stop when function hello is compiled:
DB<1> b compile hello
Continue:
DB<2> c
Now function hello exists so set a breakpoint in it and continue:
DB<2> b hello
DB<3> c
Now you are there:
main::hello(file2.pl:7): print "I am in hello";

"no warnings;" in a Safe compartment

I am using reval from Perl's Safe module and I want to prevent it from generating warnings if the string being eval'ed can't be parsed (actually, I want to prevent it from generating any warnings at all).
For example, the following code:
use strict; use warnings;
use Safe;
use feature qw/say/;
my $cft = Safe->new;
my $x = $cft->reval(') 1' );
my $y = $cft->reval('2' );
say "x: $x";
say "y: $y";
results in:
Number found where operator expected at (eval 5) line 1, near ") 1"
(Missing operator before 1?)
Use of uninitialized value $x in concatenation (.) or string at ./test line 12.
x:
y: 2
What I'm trying to achieve is to have $x = undef and $y = 2, and no warnings.
I tried to put a "no warnings;" inside a new scope, but it has no effect on the warnings produced from within the reval (although, as pointed out by #DavidO, it silences the 'uninitialized value' warning):
use strict; use warnings;
use Safe;
use feature qw/say/;
my $cft = Safe->new;
{
no warnings;
my $x = $cft->reval(') 1' );
my $y = $cft->reval('2' );
say "x: $x";
say "y: $y";
}
I guess that somehow the 'no warnings' has to be inside the Safe compartment, so I also tried to prepend "no warnings;" to the strings being eval'ed:
use strict; use warnings;
use Safe;
use feature qw/say/;
my $cft = Safe->new;
{
my $x = $cft->reval( 'no warnings;' . ') 1' );
my $y = $cft->reval( 'no warnings;' . '2' );
say "x: $x";
say "y: $y";
}
This way reval does not issue any warnings, but both variables are undef:
Use of uninitialized value $x in concatenation (.) or string at ./test line 10.
x:
Use of uninitialized value $y in concatenation (.) or string at ./test line 11.
y:
I don't know what else to try, and I hope that the problem description was clear enough.
If you check $# you'll see that $cft->reval( 'no warnings;' . ') 1' ); failed. 'require' trapped by operation mask at (eval 5) line 1.. In other words, Safe is doing its job and preventing that code from trying to load a library.
$cft->reval( 'BEGIN { warnings->unimport; } ) 1' ); would work, presuming warnings is already loaded outside the compartment. However, that won't quiet compile time errors. Unlike eval, reval seems to let them through. Use amon's technique of quieting STDERR.
no warnings suppresses all the warnings the use warnings pragma generates. You would probably want to remove any strictures as well. But severe parsing errors will pop up any way.
If you want to execute any code, no matter how pathological, without any output to STDERR, you should locally modify the signal handler:
{
# I know what I'm doing!
local $SIG{__WARN__} = sub {}; # locally ignore any warnings
eval $code; # catches all "die"
}
or we could reopen STDERR to /dev/null:
{
# I know what I'm doing!
open my $oldSTDERR, '>&' \*STDERR or die;
close STDERR or die;
open STDERR, '>', '/dev/null' or die;
eval $code;
close STDERR or die;
open STDERR, '>&', $oldSTDERR or die;
close $oldSTDERR;
}

Initializing Perl variables using eval

I'm guessing this should be something obvious to those knowing Perl, but I simply don't get it... I also guess it has to do with problems described in Perl scoping « darkness - but I cannot apply any of that in my case.
Anyway, here's the code:
#!/usr/bin/env perl
# call with:
# ./test.pl
use strict;
my $tvars = "my \$varA = 1;
my \$varB = 2;
my \$varC = 3;
";
my #lines = split /\n/, $tvars;
foreach my $line (#lines) {
print "$line\n";
eval $line; warn $# if $#;
}
#~ print "$varA\n"; # Global symbol "$varA" requires explicit package name at ./test.pl line 18.
#~ print "$varB\n"; # Global symbol "$varB" requires explicit package name at ./test.pl line 19.
#~ print "$varC\n"; # Global symbol "$varC" requires explicit package name at ./test.pl line 20.
$tvars = "our \$varA = 1;
our \$varB = 2;
our \$varC = 3;
";
#lines = split /\n/, $tvars;
foreach my $line (#lines) {
print "$line\n";
eval $line; warn $# if $#;
}
print "$varA\n"; # Global symbol "$varA" requires explicit package name at ./test.pl line 33.
print "$varB\n"; # Global symbol "$varB" requires explicit package name at ./test.pl line 34.
print "$varC\n"; # Global symbol "$varC" requires explicit package name at ./test.pl line 35.
Simply speaking, I'd like to have something like "$varA = 1;" written as a string (text file); and I'd like perl to eval it, so that afterwards I have access to variable "$varA" in the same script - the errors I get when I try to access those after an eval are in the comments of the code above (however, no warnings are reported during the eval). (I'm guessing, what I'd need is something like "global" variables, if the eval runs in a different context than the main script?)
How would I go about doing that? Do I have to go through all of that package definition business, even for a simple script like the above?
It has everything to do with scoping. The variables are declared with my inside the eval expression. This makes them local to the eval statement and not accessible once the eval statement exits. You can declare them first, though:
my ($varA, $varB, $varC); # declare outside the eval statement
my $tvars = "\$varA = 1;
\$varB = 2;
\$varC = 3;
";
eval $tvars;
# local $varA, $varB, $varC variables are now initialized
or as you suggest, you can use global variables. The easiest (though not necessarily the "best" way) is to prepend :: to all variable names and get them in the main package.
my $tvars = "\$::varA = 1;
\$::varB = 2;
\$::varC = 3;
";
eval $tvars;
print "A=$::varA, B=$::varB, C=$::varC\n";
Now when you tried our variables in your example, you actually were initializing package (global) variables. But outside the eval statement, you still need to qualify (i.e., specify the package name) them in order to access them:
$tvar = "our \$foo = 5";
eval $tvar;
print $main::foo; # ==> 5
The problem is that when you do eval $string, $string is evaluated as its own subroutine which has its own lexical scope. From perldoc -f eval:
In the first form [in which the argument is a string], the return value of EXPR is parsed and
executed as if it were a little Perl program. The value of the expression (which is itself
determined within scalar context) is first parsed, and if there were no errors, executed in the
lexical context of the current Perl program, so that any variable settings or subroutine and format
definitions remain afterwards.
So, in other words, if you have:
use strict;
use warnings;
eval "my $foo=5;";
print "$foo\n";
you'll get an error:
Global symbol "$foo" requires explicit package name at -e line 3.
Global symbol "$foo" requires explicit package name at -e line 4.
However, if you initialize your variables first, you're fine.
use strict;
use warnings;
my $foo;
eval "\$foo=5;";
print "$foo\n"; #prints out 5, as expected.