Stumped by eval and scoping problem

Discussion in 'Perl Misc' started by shanx, Mar 17, 2005.

  1. shanx

    shanx Guest

    I am not a perl newbie, but I am really stumped by this eval problem.
    I cannot change a lot of the existing code since it is legacy stuff, so
    any solution to redo this in a totally different manner won't work for
    me.

    The Problem:

    A perl program called bug_find includes a test-suite library called
    foo.pl using 'do'. bug_find has 'use strict' declaration and it passes
    a perl -c, (we're using perl 5.6), but foo.pl doesn't have a 'use
    strict' declaration. The relevant parts of the code from both files are
    shown below:

    ####bug_find####
    ...
    sub run_test {
    my ($ref) = @_;

    my $command = $ref->{cmd};
    local $results = {};

    open(FH, "$command 2>&1 |") or die $!;

    my @output = <FH>;
    $results->{output} = @output;

    if (exists($ref->{post}) and defined($ref->{post}) {
    eval $ref->{post};
    }

    return $results;
    }

    ...

    # What follows is main part of bug_find.
    {
    do $suite; # let us say $suite is foo.pl

    foreach $i (@tests) {
    $result = run_test($i);
    }
    }

    ####end of bug_find####


    ####start of foo.pl (or whatever $suite is)####


    @specific_tests = (
    {
    'cmd' => "cleartool $blah $blah", # This is some shell
    command
    'post' => "$gotit = $1 if ($results->{output} =~ m/success
    (\w+)/); print \"Value of gotit is $gotit\n\"",
    },
    {
    'cmd' => 'cd /var/tmp/$gotit; ./do_something.sh',
    }
    );

    @tests = (@specific_tests);

    ###end of foo.pl####

    Note that the variable @tests in foo.pl is being used by bug_find after
    'do'.

    My problem is that when I run bug_find, I see the correct value of
    $gotit in the print statement but when I try to read the value of
    $gotit (just before do_something.sh), the variable seems to be unset
    and it is empty.

    What is going on?

    -Shanker
     
    shanx, Mar 17, 2005
    #1
    1. Advertising

  2. shanx

    shanx Guest

    Let me correct a little typo.
    ...
    {
    'cmd' => "cd /var/tmp/$gotit; ./do_something.sh",
    }
    ...
    The hash value is within double quotes, not single quotes.
     
    shanx, Mar 17, 2005
    #2
    1. Advertising

  3. shanx

    Bob Walton Guest

    shanx wrote:

    > I am not a perl newbie, but I am really stumped by this eval problem.
    > I cannot change a lot of the existing code since it is legacy stuff, so

    ----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Huh? Why not? It's Perl code and you've got the source. And
    besides, that stuff can't be legacy code -- there's no way it
    could ever have worked. See below.

    > any solution to redo this in a totally different manner won't work for
    > me.
    >
    > The Problem:
    >
    > A perl program called bug_find includes a test-suite library called
    > foo.pl using 'do'. bug_find has 'use strict' declaration and it passes
    > a perl -c, (we're using perl 5.6), but foo.pl doesn't have a 'use
    > strict' declaration. The relevant parts of the code from both files are
    > shown below:
    >
    > ####bug_find####
    > ..


    Some comments below...

    > sub run_test {
    > my ($ref) = @_;
    >
    > my $command = $ref->{cmd};
    > local $results = {};
    >
    > open(FH, "$command 2>&1 |") or die $!;
    >
    > my @output = <FH>;
    > $results->{output} = @output;

    In the above statement, the left-hand-side is a scalar lvalue;
    hence, the thing that will get store will be the number of
    elements in array @output. Is that what you want? I doubt it
    since you are trying to match against a string that is
    non-numeric later on (starting with 'success').
    >
    > if (exists($ref->{post}) and defined($ref->{post}) {
    > eval $ref->{post};

    You should test the results of eval to see if the eval compiled
    and ran. The results of that test should be quite revealing, as
    would printing what you are about to eval just before you eval
    it. Or running it in the debugger. Did you try that??
    > }
    >
    > return $results;
    > }
    >
    > ..
    >
    > # What follows is main part of bug_find.
    > {
    > do $suite; # let us say $suite is foo.pl
    >
    > foreach $i (@tests) {
    > $result = run_test($i);
    > }
    > }
    >
    > ####end of bug_find####
    >
    >
    > ####start of foo.pl (or whatever $suite is)####
    >
    >
    > @specific_tests = (
    > {
    > 'cmd' => "cleartool $blah $blah", # This is some shell
    > command
    > 'post' => "$gotit = $1 if ($results->{output} =~ m/success
    > (\w+)/); print \"Value of gotit is $gotit\n\"",

    When the above statement is executed by Perl, the values of
    $gotit, $1 and $results->{output} are all interpolated into the
    double-quoted string, which is then stored in
    $specifictests[0]->{post}. The code you give doesn't clue us in
    to what is in those variables, but note that if $gotit contained
    'foo', $1 contained 'bar', and $results->{output} contained
    'baz', then @specifictests[0]->{post} will contain:

    foo = bar if(baz =~m/success
    (\w+)/); print "Value of gotit is foo
    "

    Since that isn't legal Perl, the eval back in your other code
    will fail. But you didn't test for that. And this makes me
    amazed at your statement below that the print statement revealed
    a correct value for $gotit, since the print never even compiled.
    Or perhaps $gotit etc actually contained value which, when
    interpolated into the string, made up something the Perl could
    compile and execute? It seems very unlikely that $1 would
    contain such a value at that point.

    > },
    > {
    > 'cmd' => 'cd /var/tmp/$gotit; ./do_something.sh',

    You mention in a followup note that the ' above are actually ",
    so $gotit is substituted at the time @specifictests[1] is
    defined. That probably isn't what you wanted -- you probably
    *do* want the apostrophe string so the $gotit is preserved until
    eval time. Use the debugger to see what you actually have in
    your data structures at various times during execution.

    And, BTW, if you're retyping your code (otherwise how would you
    have made that "mistake"?), *don't* *do* *that*. Copy/paste
    tested code into your posts so we don't have fight typos. Read
    the posting guidelines.
    > }
    > );
    >
    > @tests = (@specific_tests);
    >
    > ###end of foo.pl####
    >
    > Note that the variable @tests in foo.pl is being used by bug_find after
    > 'do'.
    >
    > My problem is that when I run bug_find, I see the correct value of

    ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^
    I doubt it. The print statement would never have even compiled.
    Can you post concice but complete code that anyone can
    copy/paste/execute which demonstrates this (per the posting
    guidelines, BTW), please?
    > $gotit in the print statement but when I try to read the value of
    > $gotit (just before do_something.sh), the variable seems to be unset
    > and it is empty.
    >
    > What is going on?


    Run your code in the debugger (perl -d filename.pl) and see for
    yourself.

    >
    > -Shanker
    >

    --
    Bob Walton
    Email: http://bwalton.com/cgi-bin/emailbob.pl
     
    Bob Walton, Mar 19, 2005
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eric Newton
    Replies:
    3
    Views:
    9,612
    Brock Allen
    Apr 4, 2005
  2. DataBinder.Eval and Eval.

    , Jun 16, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    581
    Karl Seguin [MVP]
    Jun 16, 2006
  3. Alex van der Spek

    eval('07') works, eval('08') fails, why?

    Alex van der Spek, Jan 8, 2009, in forum: Python
    Replies:
    6
    Views:
    1,553
    Bruno Desthuilliers
    Jan 8, 2009
  4. Stephen Waits

    hack to work around eval scoping?

    Stephen Waits, Mar 7, 2006, in forum: Ruby
    Replies:
    1
    Views:
    110
    Robert Klemme
    Mar 7, 2006
  5. Liang Wang
    Replies:
    8
    Views:
    156
    Ben Morrow
    Feb 2, 2008
Loading...

Share This Page