[comp.lang.perl] Silent Bomb

dglo@deimos.ads.com (Dave Glowacki) (03/14/90)

I converted a shell script to a perl script and spent a couple hours
trying to track down the following sort of error.  Is there any way
to get error messages from a file included via 'do'?

--------% cat stupid.pl
sub ShellCatenate {
  local($a, $b) = ('z', 'A');

  $a$b;	# supposed to be $a . $b
}
--------% perl stupid.pl
syntax error in file stupid.pl at line 4, next 2 tokens "$a$b"
Execution aborted due to compilation errors.
--------% cat mystery.pl
do 'stupid.pl';

$tmpname = &ShellCatenate;
print "TMPNAME='",$tmpname,"'\n";
print "TMPNAME='",&ShellCatenate,"'\n";
--------% perl mystery.pl
TMPNAME='2'
TMPNAME='zA'

&ShellCatenate is apparently returning the list ($a, $b).  Is this
perl's guess at what I really wanted or is it some sort of parse tree
remnant?

tchrist@convex.COM (Tom Christiansen) (03/14/90)

In article <11238@deimos.ADS.COM> dglo@deimos.ads.com (Dave Glowacki) writes:
>I converted a shell script to a perl script and spent a couple hours
>trying to track down the following sort of error.  Is there any way
>to get error messages from a file included via 'do'?

I use this:

% cat source.pl
###########################################################################
sub source {
    local($file) = @_;
    local($return) = 0;

    $return = do $file;
    die "couldn't parse $file: $@" if $@;
    die "couldn't do $file: $!" unless defined $return;
    die "couldn't run $file" unless $return;
    $return;
}

1;
###########################################################################

I haven't entirely decided yet whether I want the $@ check
before the $! check, but I've recently switched them around
to the state you now see.

--tom
--

    Tom Christiansen                       {uunet,uiucdcs,sun}!convex!tchrist 
    Convex Computer Corporation                            tchrist@convex.COM
		 "EMACS belongs in <sys/errno.h>: Editor too big!"

hakanson@ogicse.ogi.edu (Marion Hakanson) (03/15/90)

In article <11238@deimos.ADS.COM> dglo@deimos.ads.com (Dave Glowacki) writes:
>I converted a shell script to a perl script and spent a couple hours
>trying to track down the following sort of error.  Is there any way
>to get error messages from a file included via 'do'?

Many people suggest:

  do 'sub.pl' || die 'error in sub.pl';

but this does not provide informative error messages.  E.g. it will not
distinguish between the file being missing and it containing a syntax
error.  So then I tried:

  do 'sub.pl' || die "Cannot load sub.pl: $!, aborted";
  die "$@aborted" if $@;

Unfortunately, the first "die" takes effect if the file exists but
contains an error, and the "$!" is gibberish in that case (the second
"die" never gets to live).  My current approach, though verbose, works
well and prints meaningful messages:

unless ( do 'sub.pl' ) {
  die "$@aborted" if $@;
  die "Cannot load sub.pl: $!, aborted";
}

I'm sure someone will convert it to a one-liner....

-- 
Marion Hakanson         Domain: hakanson@cse.ogi.edu
                        UUCP  : {hp-pcd,tektronix}!ogicse!hakanson

schaefer@ogicse.ogi.edu (Barton E. Schaefer) (03/15/90)

In article <7997@ogicse.ogi.edu> hakanson@ogicse.ogi.edu (Marion Hakanson) writes:
} 
} unless ( do 'sub.pl' ) {
}   die "$@aborted" if $@;
}   die "Cannot load sub.pl: $!, aborted";
} }
} 
} I'm sure someone will convert it to a one-liner....

How about

do 'sub.pl' || ($@ ne "" && die "$@aborted") || die "Can't load sub.pl: $!";

Now the only thing I can't figure out is why the parentheses are necessary.
Doesn't && "bind tighter" than || ?  If not, why not?  I thought this was
supposed to act like C ...
-- 
Bart Schaefer          "EARTH: Surrender IMMEDIATELY or we PICKLE DAN QUAYLE"

                                                                    "THPPFT!"
schaefer@cse.ogi.edu (used to be cse.ogc.edu)

schaefer@ogicse.ogi.edu (Barton E. Schaefer) (03/15/90)

In article <8005@ogicse.ogi.edu> schaefer@ogicse.ogi.edu (That's Me) writes:
} 
} do 'sub.pl' || ($@ ne "" && die "$@aborted") || die "Can't load sub.pl: $!";

Before someone else points it out, of course it could be

do 'sub.pl' || die ($@ ne "" ? "$@aborted" : "Can't load sub.pl: $!");

but that didn't show the "problem" with && and ||.
-- 
Bart Schaefer          "EARTH: Surrender IMMEDIATELY or we PICKLE DAN QUAYLE"

                                                                    "THPPFT!"
schaefer@cse.ogi.edu (used to be cse.ogc.edu)

jgreely@giza.cis.ohio-state.edu (J Greely) (03/15/90)

In article <8006@ogicse.ogi.edu> schaefer@ogicse.ogi.edu
 (Barton E. Schaefer) writes:
>do 'sub.pl' || die ($@ ne "" ? "$@aborted" : "Can't load sub.pl: $!");

I Like Tom's solution (which sits in the archive in
perl/scripts/tchrist/source.pl):

sub source {
    local($file) = @_;
    local($return) = 0;

    $return = do $file;
    die "couldn't do \"$file\": $!" unless defined $return;
    die "couldn't parse \"$file\": $@" if $@;
    die "couldn't run \"$file\"" unless $return;
} 
1;

Not one line, but quite effective (it of course uses the "trailing-1"
convention for sourced files (is this documented yet?)).

Here's my contribution:

die "$file: " . ($! > 0 ? $! : $@ ne '' ? $@ : "couldn't run")
	unless do $file > 0;

(no, it doesn't print "Just another Perl hacker,")
--
J Greely (jgreely@cis.ohio-state.edu; osu-cis!jgreely)

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (03/15/90)

In article <8005@ogicse.ogi.edu> schaefer@ogicse.ogi.edu (Barton E. Schaefer) writes:
: How about
: 
: do 'sub.pl' || ($@ ne "" && die "$@aborted") || die "Can't load sub.pl: $!";
: 
: Now the only thing I can't figure out is why the parentheses are necessary.
: Doesn't && "bind tighter" than || ?  If not, why not?  I thought this was
: supposed to act like C ...

Remember that die is a LIST operator, and that LIST operators gobble up
all arguments to their right.  You can do what you want if you say

do 'sub.pl' || $@ ne "" && die("$@aborted") || die "Can't load sub.pl: $!";

Though I'd probably say that as

do 'sub.pl' || die $@ ? "$@aborted" : "Can't load sub.pl: $!";

Larry

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (03/16/90)

In article <100570@convex.convex.com> tchrist@convex.COM (Tom Christiansen) writes:
: ###########################################################################
: sub source {
:     local($file) = @_;
:     local($return) = 0;
: 
:     $return = do $file;
:     die "couldn't parse $file: $@" if $@;
:     die "couldn't do $file: $!" unless defined $return;
:     die "couldn't run $file" unless $return;
:     $return;
: }
: 
: 1;
: ###########################################################################
: 
: I haven't entirely decided yet whether I want the $@ check
: before the $! check, but I've recently switched them around
: to the state you now see.

The message "couldn't parse..." isn't quite accurate, since $@ can be
set by run-time errors as well as compile-time errors.  It might parse
fine, but suppose you divide by 0...

It might even be that the 3rd condition will never be met unless they
leave the 1; off the end.

Larry

tony@oha.UUCP (Tony Olekshy) (03/18/90)

In message <7997@ogicse.ogi.edu>, hakanson@ogicse.ogi.edu (Marion Hakanson)
writes:
>                             My current approach, though verbose, works
> well and prints meaningful messages:
> 
> unless ( do 'sub.pl' ) {
>   die "$@aborted" if $@;
>   die "Cannot load sub.pl: $!, aborted";
> }
> 
> I'm sure someone will convert it to a one-liner....

Yes, many have, but I have been doing it this way too:

	do ($_="somefile.pl") || die "$0: can't load $_:\n".($@?$@:$!);

--
Yours, etc., Tony Olekshy (...!alberta!oha!tony or tony@oha.UUCP).