Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Identifying a location with finer granularity than a line number

by rockyb (Scribe)
on Aug 14, 2012 at 05:51 UTC ( #987268=perlquestion: print w/replies, xml ) Need Help??
rockyb has asked for the wisdom of the Perl Monks concerning the following question:

O great Monks— with elation from the last encounter, I have come for more enlightenment.

I seek a means to express a location in a Perl program with more than simply a line number in a file. No doubt you are aware of the Obfuscated Perl and JAPH koans whose mysteries contains several Perl statements on a single line. I have come to believe that mere journeyman programmers are wont to emulate such behavior and sometimes place more than one statement on a line.

I am not so naive to imagine that it easy or likely that, for example, column number information would stored somewhere; although I'd welcome that. Straining my feeble brain, the only other possibility I can come up with is to obtain a COP address by giving a trace location. By trace location, I mean a location that is called in single stepping; or it could be the location the caller was at before making a call. Consider introspecting inside fn when the calling source line looks like:

 fn(); fn(); fn();

Although COP is low-level, perhaps even in the untouchable caste, let me attempt motivate to why even that might be useful for the purpose of obtaining a more detailed understanding of a location inside a program.

Suppose one could figure out the cardinal number of the COP of those that have the same line number and file name. That gives a hint whether the program was situated at towards the first statement or the towards the last statement of the line in question. The first statement is a no brainer. In the presence of conditional code, subsequent COP addresses may be hard.

The second reason why this might be useful is really for a somewhat limited situation. Suppose one were stopped in debugger (or a handler for a profiler, or code coverage analyzer) and the debugged/traced/profiled program was somewhere in multi-statement line. In the case of a debugger, supposed one wanted to set a breakpoint at the same point again. I understand that Perl's breakpoint mechanism works only on a line bases at the level of support from the runtime. However, if one could get a COP address or some other unique identifier for the location of the program — something equivalent to program counter — the debugger could sort out whether the detailed location was obtained if it could query, say, the COP address.

But beggars can't be choosers and perhaps there are other possibilities unimaginable by me. So I seek your wisdom


  • Comment on Identifying a location with finer granularity than a line number

Replies are listed 'Best First'.
Re: Identifying a location with finer granularity than a line number
by Anonymous Monk on Aug 14, 2012 at 06:34 UTC


    I understand that Perl's breakpoint mechanism works only on a line bases at the level of support from the runtime.

    Nope. From perldebug

    b Sets breakpoint on current line b [line] [condition] Set a breakpoint before the given line. If a condition is specified, it's evaluated each time the statement is reached: a breakpoint is taken only if the condition is true. Breakpoints may only be set on lines that begin an executable statement. Conditions don't use "if": b 237 $x > 30 b 237 ++$count237 < 11 b 33 /pattern/i b subname [condition] Set a breakpoint before the first line of the named subroutine. *subname* may be a variable containing a code reference (in this case *condition* is not supported). b postpone subname [condition] Set a breakpoint at first line of subroutine after it is compiled. b load filename Set a breakpoint before the first executed line of the *filename*, which should be a full pathname found amongst the %INC values. b compile subname Sets a breakpoint before the first statement executed afte +r the specified subroutine is compiled.
    Subname can be Some::Package::Name::subname

      The sneaky operative word is "at the level of support from the runtime" by which I mean below the level of what can be done in Perl. On top of this run-time level, one can suppliment this in Perl to add what you see above (and more).

      Having said this though it is also true that one can hook into calls and returns. But it so happens in perl5db which is what you are citing above that is not done. Rather, when you specify a function name in a breakpoint, that gets translated into a file and line number and then a breakpoint is set on that, I believe. And as for hooking into the point of return which would be useful, that opportunity is also lost

Re: Identifying a location with finer granularity than a line number
by BillKSmith (Vicar) on Aug 14, 2012 at 13:04 UTC
    It would probably help to 'fix' the code with CPAN utility perltidy before trying to examine or debug it.

      I think haven't been doing a good job at explaining the problem. I am looking for a way to identify in a Perl program more precisely — generally more precise than a line and filename — where the program was at a "trace" point: which could be a call, place where an exception can occur, or a statement boundary.

      If the runtime system kept line and column numbers associated with some of the opcodes passed from the parser, that would work. But realistically, this adds overhead and would be a fair bit of rewriting of the Perl interpreter. Another way to get more precise location information might be to rewrite the program to put each Perl token on a line. I doubt most people would be interested in such a solution, but a little more on this later.

      Another solution would be to be able to get something like a program counter (PC) or opcode/opnode location and disassembly of some of the tree around that location.

      There may be other possibilities as well. And if no solution comes up, I guess that's okay too.

      Although perltidy might ameliorate the problem a little, to see why a program pretty-printer isn't going to always help (short of putting one token on a line), consider this code:

      ($a/$b, $c/$d);

      If an "Illegal division by 0" occurs, was the division in the first entry of the array or the second?

      Lastly, let me come back to what sounds like a crazy idea of putting one Perl token per line. In a Perl debugger I have been writing, there is a module for caching source-code lines and remapping locations in one file and line to another file and line. I don't have the front-end interface to that in yet like I do in some other debuggers. However with this, one could split the program up and then with this translation mechanism remap one position in the file with more lines back to a position in the original source text. But there would still need to be be some additional work to add in the column position though.

        I'd likely first pursue the idea of dumping the opnodes for that line along with which opnode was active. See the likes of B::Terse or B::Concise for examples of dumping a tree of opnodes.

        I'm not sure the best place to point you about the possibility of finding the currently active opnode in the call stack. Perhaps the guts of App::Stacktrace know how to answer that in one way.

        - tye        

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://987268]
Front-paged by Corion
[choroba]: Hasn't someone forgot to tell the weather about it?

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (6)
As of 2018-03-21 08:05 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (265 votes). Check out past polls.