📄 perl5db.pl
字号:
=head4 C<$trace>Controls the output of trace information. =over 4=item * 1 - The C<t> command was entered to turn on tracing (every line executed is printed)=item * 2 - watch expressions are active=item * 4 - user defined a C<watchfunction()> in C<afterinit()>=back=head4 C<$slave_editor>1 if C<LINEINFO> was directed to a pipe; 0 otherwise.=head4 C<@cmdfhs>Stack of filehandles that C<DB::readline()> will read commands from.Manipulated by the debugger's C<source> command and C<DB::readline()> itself.=head4 C<@dbline>Local alias to the magical line array, C<@{$main::{'_<'.$filename}}> , supplied by the Perl interpreter to the debugger. Contains the source.=head4 C<@old_watch>Previous values of watch expressions. First set when the expression isentered; reset whenever the watch expression changes.=head4 C<@saved>Saves important globals (C<$@>, C<$!>, C<$^E>, C<$,>, C<$/>, C<$\>, C<$^W>)so that the debugger can substitute safe values while it's running, andrestore them when it returns control.=head4 C<@stack>Saves the current value of C<$single> on entry to a subroutine.Manipulated by the C<c> command to turn off tracing in all subs above thecurrent one.=head4 C<@to_watch>The 'watch' expressions: to be evaluated before each line is executed.=head4 C<@typeahead>The typeahead buffer, used by C<DB::readline>.=head4 C<%alias>Command aliases. Stored as character strings to be substituted for a commandentered.=head4 C<%break_on_load>Keys are file names, values are 1 (break when this file is loaded) or undef(don't break when it is loaded).=head4 C<%dbline>Keys are line numbers, values are C<condition\0action>. If used in numericcontext, values are 0 if not breakable, 1 if breakable, no matter what isin the actual hash entry.=head4 C<%had_breakpoints>Keys are file names; values are bitfields:=over 4 =item * 1 - file has a breakpoint in it.=item * 2 - file has an action in it.=backA zero or undefined value means this file has neither.=head4 C<%option>Stores the debugger options. These are character string values.=head4 C<%postponed>Saves breakpoints for code that hasn't been compiled yet.Keys are subroutine names, values are:=over 4=item * C<compile> - break when this sub is compiled=item * C<< break +0 if <condition> >> - break (conditionally) at the start of this routine. The condition will be '1' if no condition was specified.=back=head4 C<%postponed_file>This hash keeps track of breakpoints that need to be set for files that havenot yet been compiled. Keys are filenames; values are references to hashes.Each of these hashes is keyed by line number, and its values are breakpointdefinitions (C<condition\0action>).=head1 DEBUGGER INITIALIZATIONThe debugger's initialization actually jumps all over the place inside thispackage. This is because there are several BEGIN blocks (which of course execute immediately) spread through the code. Why is that? The debugger needs to be able to change some things and set some things up before the debugger code is compiled; most notably, the C<$deep> variable thatC<DB::sub> uses to tell when a program has recursed deeply. In addition, thedebugger has to turn off warnings while the debugger code is compiled, but thenrestore them to their original setting before the program being debugged beginsexecuting.The first C<BEGIN> block simply turns off warnings by saving the currentsetting of C<$^W> and then setting it to zero. The second one initializesthe debugger variables that are needed before the debugger begins executing.The third one puts C<$^X> back to its former value. We'll detail the second C<BEGIN> block later; just remember that if you needto initialize something before the debugger starts really executing, that'swhere it has to go.=cutpackage DB;BEGIN {eval 'use IO::Handle'}; # Needed for flush only? breaks under miniperl# Debugger for Perl 5.00x; perl5db.pl patch level:$VERSION = 1.30;$header = "perl5db.pl version $VERSION";=head1 DEBUGGER ROUTINES=head2 C<DB::eval()>This function replaces straight C<eval()> inside the debugger; it simplifiesthe process of evaluating code in the user's context.The code to be evaluated is passed via the package global variable C<$DB::evalarg>; this is done to avoid fiddling with the contents of C<@_>.Before we do the C<eval()>, we preserve the current settings of C<$trace>,C<$single>, C<$^D> and C<$usercontext>. The latter contains thepreserved values of C<$@>, C<$!>, C<$^E>, C<$,>, C<$/>, C<$\>, C<$^W> and theuser's current package, grabbed when C<DB::DB> got control. This causes theproper context to be used when the eval is actually done. Afterward, werestore C<$trace>, C<$single>, and C<$^D>.Next we need to handle C<$@> without getting confused. We save C<$@> in alocal lexical, localize C<$saved[0]> (which is where C<save()> will put C<$@>), and then call C<save()> to capture C<$@>, C<$!>, C<$^E>, C<$,>, C<$/>, C<$\>, and C<$^W>) and set C<$,>, C<$/>, C<$\>, and C<$^W> to valuesconsidered sane by the debugger. If there was an C<eval()> error, we print it on the debugger's output. If C<$onetimedump> is defined, we call C<dumpit> if it's set to 'dump', or C<methods> if it's set to 'methods'. Setting it to something else causes the debugger to do the eval but not print the result - handy if you want to do something else with it (the "watch expressions" code does this to get the value of the watchexpression but not show it unless it matters).In any case, we then return the list of output from C<eval> to the caller, and unwinding restores the former version of C<$@> in C<@saved> as well (the localization of C<$saved[0]> goes away at the end of this scope).=head3 Parameters and variables influencing execution of DB::eval()C<DB::eval> isn't parameterized in the standard way; this is to keep thedebugger's calls to C<DB::eval()> from mucking with C<@_>, among other things.The variables listed below influence C<DB::eval()>'s execution directly. =over 4=item C<$evalarg> - the thing to actually be eval'ed=item C<$trace> - Current state of execution tracing=item C<$single> - Current state of single-stepping=item C<$onetimeDump> - what is to be displayed after the evaluation =item C<$onetimeDumpDepth> - how deep C<dumpit()> should go when dumping results=backThe following variables are altered by C<DB::eval()> during its execution. Theyare "stacked" via C<local()>, enabling recursive calls to C<DB::eval()>. =over 4=item C<@res> - used to capture output from actual C<eval>.=item C<$otrace> - saved value of C<$trace>.=item C<$osingle> - saved value of C<$single>. =item C<$od> - saved value of C<$^D>.=item C<$saved[0]> - saved value of C<$@>.=item $\ - for output of C<$@> if there is an evaluation error. =back=head3 The problem of lexicalsThe context of C<DB::eval()> presents us with some problems. Obviously,we want to be 'sandboxed' away from the debugger's internals when we dothe eval, but we need some way to control how punctuation variables anddebugger globals are used. We can't use local, because the code inside C<DB::eval> can see localizedvariables; and we can't use C<my> either for the same reason. The codein this routine compromises and uses C<my>.After this routine is over, we don't have user code executing in the debugger'scontext, so we can use C<my> freely.=cut############################################## Begin lexical danger zone# 'my' variables used here could leak into (that is, be visible in)# the context that the code being evaluated is executing in. This means that# the code could modify the debugger's variables.## Fiddling with the debugger's context could be Bad. We insulate things as# much as we can.sub eval { # 'my' would make it visible from user code # but so does local! --tchrist # Remember: this localizes @DB::res, not @main::res. local @res; { # Try to keep the user code from messing with us. Save these so that # even if the eval'ed code changes them, we can put them back again. # Needed because the user could refer directly to the debugger's # package globals (and any 'my' variables in this containing scope) # inside the eval(), and we want to try to stay safe. local $otrace = $trace; local $osingle = $single; local $od = $^D; # Untaint the incoming eval() argument. { ($evalarg) = $evalarg =~ /(.*)/s; } # $usercontext built in DB::DB near the comment # "set up the context for DB::eval ..." # Evaluate and save any results. @res = eval "$usercontext $evalarg;\n"; # '\n' for nice recursive debug # Restore those old values. $trace = $otrace; $single = $osingle; $^D = $od; } # Save the current value of $@, and preserve it in the debugger's copy # of the saved precious globals. my $at = $@; # Since we're only saving $@, we only have to localize the array element # that it will be stored in. local $saved[0]; # Preserve the old value of $@ eval { &DB::save }; # Now see whether we need to report an error back to the user. if ($at) { local $\ = ''; print $OUT $at; } # Display as required by the caller. $onetimeDump and $onetimedumpDepth # are package globals. elsif ($onetimeDump) { if ( $onetimeDump eq 'dump' ) { local $option{dumpDepth} = $onetimedumpDepth if defined $onetimedumpDepth; dumpit( $OUT, \@res ); } elsif ( $onetimeDump eq 'methods' ) { methods( $res[0] ); } } ## end elsif ($onetimeDump) @res;} ## end sub eval############################################## End lexical danger zone# After this point it is safe to introduce lexicals.# The code being debugged will be executing in its own context, and# can't see the inside of the debugger.## However, one should not overdo it: leave as much control from outside as# possible. If you make something a lexical, it's not going to be addressable# from outside the debugger even if you know its name.# This file is automatically included if you do perl -d.# It's probably not useful to include this yourself.## Before venturing further into these twisty passages, it is# wise to read the perldebguts man page or risk the ire of dragons.## (It should be noted that perldebguts will tell you a lot about# the underlying mechanics of how the debugger interfaces into the# Perl interpreter, but not a lot about the debugger itself. The new# comments in this code try to address this problem.)# Note that no subroutine call is possible until &DB::sub is defined# (for subroutines defined outside of the package DB). In fact the same is# true if $deep is not defined.# Enhanced by ilya@math.ohio-state.edu (Ilya Zakharevich)# modified Perl debugger, to be run from Emacs in perldb-mode# Ray Lischner (uunet!mntgfx!lisch) as of 5 Nov 1990# Johan Vromans -- upgrade to 4.0 pl 10# Ilya Zakharevich -- patches after 5.001 (and some before ;-)# (We have made efforts to clarify the comments in the change log# in other places; some of them may seem somewhat obscure as they# were originally written, and explaining them away from the code# in question seems conterproductive.. -JM)######################################################################### Changes: 0.94# + A lot of things changed after 0.94. First of all, core now informs# debugger about entry into XSUBs, overloaded operators, tied operations,# BEGIN and END. Handy with `O f=2'.# + This can make debugger a little bit too verbose, please be patient# and report your problems promptly.# + Now the option frame has 3 values: 0,1,2. XXX Document!# + Note that if DESTROY returns a reference to the object (or object),# the deletion of data may be postponed until the next function call,# due to the need to examine the return value.## Changes: 0.95# + `v' command shows versions.## Changes: 0.96# + `v' command shows version of readline.# primitive completion works (dynamic variables, subs for `b' and `l',# options). Can `p %var'# + Better help (`h <' now works). New commands <<, >>, {, {{.# {dump|print}_trace() coded (to be able to do it from <<cmd).# + `c sub' documented.# + At last enough magic combined to stop after the end of debuggee.# + !! should work now (thanks to Emacs bracket matching an extra# `]' in a regexp is caught).# + `L', `D' and `A' span files now (as documented).# + Breakpoints in `require'd code are possible (used in `R').# + Some additional words on internal work of debugger.# + `b load filename' implemented.# + `b postpone subr' implemented.# + now only `q' exits debugger (overwritable on $inhibit_exit).# + When restarting debugger breakpoints/actions persist.# + Buglet: When restarting debugger only one breakpoint/action per# autoloaded function persists.## Changes: 0.97: NonStop will not stop in at_exit().# + Option AutoTrace implemented.# + Trace printed differently if frames are printed too.# + new `inhibitExit' option.# + printing of a very long statement interruptible.# Changes: 0.98: New command `m' for printing possible methods# + 'l -' is a synonym for `-'.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -