[comp.lang.perl] knowing your current context

tchrist@convex.com (Tom Christiansen) (10/12/90)

If I 'do' a file to get some subroutines defined, later call one of the
subroutines, and that routine uses a warn or die with out a trailing
\n, it is wrong claims that I was in my original calling file (the one
who 'did' the library file) not the library file.  This is perhaps
arguably correct, but I wouldn't argue that way.  Of course, the best
of all worlds would somehow tell me both.  It also botches the line
number.  I can't figure out where it's pulling that one from.

Anybody know how to pull out the current file, line, package, and
subroutine from within a perl script?  

Also, are there any hazards from saying:
    eval "package $some_package";

--tom
--
 "UNIX was never designed to keep people from doing stupid things, because 
  that policy would also keep them from doing clever things." [Doug Gwyn]

tchrist@convex.COM (Tom Christiansen) (10/13/90)

In article <107126@convex.convex.com> I, myself, wrote:

>Anybody know how to pull out the current file, line, package, and
>subroutine from within a perl script?  

I keep forgetting the new functions from pl>18 -- __LINE__ and __FILE__
should do for those, although I'm still looking for package and subroutine.

--tom
--
 "UNIX was never designed to keep people from doing stupid things, because 
  that policy would also keep them from doing clever things." [Doug Gwyn]

merlyn@iwarp.intel.com (Randal Schwartz) (10/13/90)

In article <107138@convex.convex.com>, tchrist@convex (Tom Christiansen) writes:
| In article <107126@convex.convex.com> I, myself, wrote:
| >Anybody know how to pull out the current file, line, package, and
| >subroutine from within a perl script?  
| I keep forgetting the new functions from pl>18 -- __LINE__ and __FILE__
| should do for those, although I'm still looking for package and subroutine.

Done in Perl 4.0 (no kidding), as in "the version described by The
Book".  It's called "caller".  Here's the doc (vaguely -ms like with
the .P/.Ps/.Pe macros for "printout" font):

| .NH 2
| .P caller
| .Ps
| caller(EXPR)
| caller EXPR
| caller
| .Pe
| .PP
| Returns information about the subroutine call stack.  Without an argument
| it returns the package name, file name and line number that currently
| executing subroutine was called from:
| .Ps
| ($package, $filename, $line) = caller;
| .Pe
| With an argument it evaluates EXPR as the number of stack frames to go back
| before the current one.  It also reports some additional information, and
| magically sets
| .P @DB\'args
| to the arguments passed in that stack frame.  It's primarily used by the
| debugger to print out stack traces.
| .Ps
| $i = 0;
| while (($pack, $file, $line, $subname, $hasargs, $wantarray)
|   = caller($i++)) {
|     .\|.\|.
| }
| .Pe

Coming "Real Soon Now" to a source distribution near you.

(Dare I say that the book has already gone to the publisher for
production?  Naaaah, I dare not. :-)

print 'Just another ', ('a'..'z','A'..'Z')[41,4,17,11], ' hacker,'
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (10/14/90)

In article <107126@convex.convex.com> tchrist@convex.com (Tom Christiansen) writes:
: If I 'do' a file to get some subroutines defined, later call one of the
: subroutines, and that routine uses a warn or die with out a trailing
: \n, it is wrong claims that I was in my original calling file (the one
: who 'did' the library file) not the library file.  This is perhaps
: arguably correct, but I wouldn't argue that way.  Of course, the best
: of all worlds would somehow tell me both.  It also botches the line
: number.  I can't figure out where it's pulling that one from.

This has been fixed already as part of implementing the caller function
and making the debugger work for packages and evals.

: Anybody know how to pull out the current file, line, package, and
: subroutine from within a perl script?  

As you pointed out in your followup, __FILE__ and __LINE__ are available.
But everything you want is available from the new caller function.
It comes in two forms:

	($package,$filename,$line) = caller;

This just gives you where the current subroutine was called from.  The other
form is used in the debugger to print stack traces, more or less like this:

	local($p,$f,$l,$s,$h,$a,@a,@sub);
	for ($i = 1; ($p,$f,$l,$s,$h,$w) = caller($i); $i++) {
	    @a = @args;
	    for (@a) {
		if (/^StB\000/ && length($_) == length($_main{'_main'}))
{
		    $_ = sprintf("%s",$_);
		}
		else {
		    s/'/\\'/g;
		    s/([^\0]*)/'$1'/ unless /^-?[\d.]+$/;
		    s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg;
		    s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
		}
	    }
	    $w = $w ? '@ = ' : '$ = ';
	    $a = $h ? '(' . join(', ', @a) . ')' : '';
	    print OUT "$w&$s$a from file $f line $l\n";
	}

The parameter to caller specifies how many stack frames to go back, and
it returns the package, filename, line, subroutine name, whether the
subroutine has arguments, and the value of wantarray for that subroutine.
(It also magically sets @DB'args to be references to the arguments for
that function.  This form of the function is primarily for the debugger.
Don't try this at home, kids.)

: Also, are there any hazards from saying:
:     eval "package $some_package";

'Tis a fancy no-op.  Remember that packages are lexically scoped, so your
new package name extends only to the end of the eval.

Saying

     eval "package $some_package;" . '$foo = $bar';

makes better sense, and in fact the new debugger uses that sort of construct
to make sure it references the variables in the package you're currently
debugging.  So you see how it all ties in.

Larry