Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm wondering if anyone knows a way to do the equivalent of a "perl -c" on some code that will be eval'ed from within a running perl. I don't want to run the code, just check its syntax.

Of course, I could do

open (FILE, ">$file");
print FILE $code;
system ("perl -c $file");

But that is monsterously ugly.

Replies are listed 'Best First'.
Re: syntax check from within perl
by Zaxo (Archbishop) on Mar 02, 2002 at 05:26 UTC

    The eval function with quoted argument traps compile errors. You can examine the error messages in the perlvar $@. No other special magic is needed. This is not true of eval BLOCK.

    Update: <shrug>If you want to avoid runtime on your eval string, just wrap it in a conditional:

    $ $ perl -Mstrict -e'$_="printed\n";my$foo=q(print);eval"if(\$^C){$foo}" +;print $@ if $@' -- #no compile or run error $ $ perl -Mstrict -e'$_="printed\n";my$foo=q(quux);eval"if(\$^C){$foo}"; +print $@ if $@' -- # compile error Bareword "quux" not allowed while "strict subs" in use at (eval 1) lin +e 1. $ $ perl -Mstrict -e'$_="printed\n";my$foo=q(&quux);eval"if(\$^C){$foo}" +;print $@ if $@' -- # runtime error $ $ perl -Mstrict -e '$_="printed\n";my$foo=q(print);eval"$foo";print $@ + if $@' -- # conditional removed, no errors printed $
    I used $^C, the compile-time flag, for cli convenience, but some $debug would do as well.

    After Compline,
    Zaxo

      the only difference is perl will execute whatever code, thus creating any files, emailing /etc/passwd to somebody, or anything else. the dude just ought to run perl -c on the file without reading it.

        Consider:

        #!/usr/bin/perl BEGIN { print "rm -rf /" }

        Guess what happens when you run perl -c on this.

        Now just imagine if that weren't just a print statement...

        Update: I thought it was discussed here before, but I can't seem to find where. IIRC, the verdict was, basically, that there's just not a way to get arbitrary code syntax checked w/o (at least the possbility of) running some of it.

        bbfu
        Seasons don't fear The Reaper.
        Nor do the wind, the sun, and the rain.
        We can be like they are.

Re: syntax check from within perl
by Matts (Deacon) on Mar 02, 2002 at 17:17 UTC
    Just do exactly what perl -c does:

    eval "return; $code";

      But see discussion elsewhere in the thread.

      The reader did not realize that perl -c does not provide a safe way to test syntactical correctness. There is no way to do that in Perl.

      For instance suppose that it does a use. There is no way to know if later code is syntactically correct without running the used module. (For instance what functions are exported? This affects what will be trapped as a bareword under strict, and what will not.) But when you do that, the module could do absolutely anything it wanted to.

        But safety wasn't the question - merely how to emulate perl -c...

        If you want it safe from malicious intent, we all know you're basically screwed with Perl. You can't not have it execute use bits, because many imports affect the compilation, like use constant. So either you test the compilation or you don't. I believe the author asked to do so.

Re: syntax check from within perl
by derby (Abbot) on Mar 02, 2002 at 12:02 UTC
    AM,

    Just a wild thought but couldn't you eval the creation of an anonymous subroutine, check the $@ for errors and if none, invoke the subroutine - for example -

    $cmd = "sub{ prin 'Howdy'; }"; $sub = eval $cmd; print "Error: ", $@, "\n" if $@; &$sub unless $@;

    -derby

Re: syntax check from within perl
by shotgunefx (Parson) on Mar 03, 2002 at 11:17 UTC
    What about using the ops pragma?
    Description: Perl pragma to restrict unsafe operations when compiling
    Don't know if it will work or not. (No hands-on with it).

    -Lee

    "To be civilized is to deny one's nature."
Re: syntax check from within perl
by ajwans (Scribe) on Mar 05, 2002 at 21:52 UTC
    Thankyou,
    eval "return; $code";
    was __exactly__ what I needed.
Re: syntax check from within perl
by cyocum (Curate) on Mar 02, 2002 at 21:45 UTC
    Well, this might not be the solution you are looking for but you could use the `` operator with something like `perl -c $code` then trap the output to see if there is a systax error. I know this is not a really elegant soluation but I think it would work.
Re: syntax check from within perl
by Juerd (Abbot) on Mar 03, 2002 at 11:23 UTC
    Try using Safe.pm and B::Deparse. (I haven't tried)

    ++ vs lbh qrpbqrq guvf hfvat n ge va Crey :)
    Nabgure bar vs lbh qvq fb jvgubhg ernqvat n znahny svefg.
    -- vs lbh hfrq OFQ pnrfne ;)
        - Whreq