1# 2# Documentation is at the __END__ 3# 4 5package DB; 6 7# "private" globals 8 9my ($running, $ready, $deep, $usrctxt, $evalarg, 10 @stack, @saved, @skippkg, @clients); 11my $preeval = {}; 12my $posteval = {}; 13my $ineval = {}; 14 15#### 16# 17# Globals - must be defined at startup so that clients can refer to 18# them right after a C<require DB;> 19# 20#### 21 22BEGIN { 23 24 # these are hardcoded in perl source (some are magical) 25 26 $DB::sub = ''; # name of current subroutine 27 %DB::sub = (); # "filename:fromline-toline" for every known sub 28 $DB::single = 0; # single-step flag (set it to 1 to enable stops in BEGIN/use) 29 $DB::signal = 0; # signal flag (will cause a stop at the next line) 30 $DB::trace = 0; # are we tracing through subroutine calls? 31 @DB::args = (); # arguments of current subroutine or @ARGV array 32 @DB::dbline = (); # list of lines in currently loaded file 33 %DB::dbline = (); # actions in current file (keyed by line number) 34 @DB::ret = (); # return value of last sub executed in list context 35 $DB::ret = ''; # return value of last sub executed in scalar context 36 37 # other "public" globals 38 39 $DB::package = ''; # current package space 40 $DB::filename = ''; # current filename 41 $DB::subname = ''; # currently executing sub (fullly qualified name) 42 $DB::lineno = ''; # current line number 43 44 $DB::VERSION = $DB::VERSION = '1.02'; 45 46 # initialize private globals to avoid warnings 47 48 $running = 1; # are we running, or are we stopped? 49 @stack = (0); 50 @clients = (); 51 $deep = 100; 52 $ready = 0; 53 @saved = (); 54 @skippkg = (); 55 $usrctxt = ''; 56 $evalarg = ''; 57} 58 59#### 60# entry point for all subroutine calls 61# 62sub sub { 63 push(@stack, $DB::single); 64 $DB::single &= 1; 65 $DB::single |= 4 if $#stack == $deep; 66 if ($DB::sub eq 'DESTROY' or substr($DB::sub, -9) eq '::DESTROY' or not defined wantarray) { 67 &$DB::sub; 68 $DB::single |= pop(@stack); 69 $DB::ret = undef; 70 } 71 elsif (wantarray) { 72 @DB::ret = &$DB::sub; 73 $DB::single |= pop(@stack); 74 @DB::ret; 75 } 76 else { 77 $DB::ret = &$DB::sub; 78 $DB::single |= pop(@stack); 79 $DB::ret; 80 } 81} 82 83#### 84# this is called by perl for every statement 85# 86sub DB { 87 return unless $ready; 88 &save; 89 ($DB::package, $DB::filename, $DB::lineno) = caller; 90 91 return if @skippkg and grep { $_ eq $DB::package } @skippkg; 92 93 $usrctxt = "package $DB::package;"; # this won't let them modify, alas 94 local(*DB::dbline) = "::_<$DB::filename"; 95 96 # we need to check for pseudofiles on Mac OS (these are files 97 # not attached to a filename, but instead stored in Dev:Pseudo) 98 # since this is done late, $DB::filename will be "wrong" after 99 # skippkg 100 if ($^O eq 'MacOS' && $#DB::dbline < 0) { 101 $DB::filename = 'Dev:Pseudo'; 102 *DB::dbline = "::_<$DB::filename"; 103 } 104 105 my ($stop, $action); 106 if (($stop,$action) = split(/\0/,$DB::dbline{$DB::lineno})) { 107 if ($stop eq '1') { 108 $DB::signal |= 1; 109 } 110 else { 111 $stop = 0 unless $stop; # avoid un_init warning 112 $evalarg = "\$DB::signal |= do { $stop; }"; &eval; 113 $DB::dbline{$DB::lineno} =~ s/;9($|\0)/$1/; # clear any temp breakpt 114 } 115 } 116 if ($DB::single || $DB::trace || $DB::signal) { 117 $DB::subname = ($DB::sub =~ /\'|::/) ? $DB::sub : "${DB::package}::$DB::sub"; #'; 118 DB->loadfile($DB::filename, $DB::lineno); 119 } 120 $evalarg = $action, &eval if $action; 121 if ($DB::single || $DB::signal) { 122 _outputall($#stack . " levels deep in subroutine calls.\n") if $DB::single & 4; 123 $DB::single = 0; 124 $DB::signal = 0; 125 $running = 0; 126 127 &eval if ($evalarg = DB->prestop); 128 my $c; 129 for $c (@clients) { 130 # perform any client-specific prestop actions 131 &eval if ($evalarg = $c->cprestop); 132 133 # Now sit in an event loop until something sets $running 134 do { 135 $c->idle; # call client event loop; must not block 136 if ($running == 2) { # client wants something eval-ed 137 &eval if ($evalarg = $c->evalcode); 138 $running = 0; 139 } 140 } until $running; 141 142 # perform any client-specific poststop actions 143 &eval if ($evalarg = $c->cpoststop); 144 } 145 &eval if ($evalarg = DB->poststop); 146 } 147 ($@, $!, $,, $/, $\, $^W) = @saved; 148 (); 149} 150 151#### 152# this takes its argument via $evalarg to preserve current @_ 153# 154sub eval { 155 ($@, $!, $,, $/, $\, $^W) = @saved; 156 eval "$usrctxt $evalarg; &DB::save"; 157 _outputall($@) if $@; 158} 159 160############################################################################### 161# no compile-time subroutine call allowed before this point # 162############################################################################### 163 164use strict; # this can run only after DB() and sub() are defined 165 166sub save { 167 @saved = ($@, $!, $,, $/, $\, $^W); 168 $, = ""; $/ = "\n"; $\ = ""; $^W = 0; 169} 170 171sub catch { 172 for (@clients) { $_->awaken; } 173 $DB::signal = 1; 174 $ready = 1; 175} 176 177#### 178# 179# Client callable (read inheritable) methods defined after this point 180# 181#### 182 183sub register { 184 my $s = shift; 185 $s = _clientname($s) if ref($s); 186 push @clients, $s; 187} 188 189sub done { 190 my $s = shift; 191 $s = _clientname($s) if ref($s); 192 @clients = grep {$_ ne $s} @clients; 193 $s->cleanup; 194# $running = 3 unless @clients; 195 exit(0) unless @clients; 196} 197 198sub _clientname { 199 my $name = shift; 200 "$name" =~ /^(.+)=[A-Z]+\(.+\)$/; 201 return $1; 202} 203 204sub next { 205 my $s = shift; 206 $DB::single = 2; 207 $running = 1; 208} 209 210sub step { 211 my $s = shift; 212 $DB::single = 1; 213 $running = 1; 214} 215 216sub cont { 217 my $s = shift; 218 my $i = shift; 219 $s->set_tbreak($i) if $i; 220 for ($i = 0; $i <= $#stack;) { 221 $stack[$i++] &= ~1; 222 } 223 $DB::single = 0; 224 $running = 1; 225} 226 227#### 228# XXX caller must experimentally determine $i (since it depends 229# on how many client call frames are between this call and the DB call). 230# Such is life. 231# 232sub ret { 233 my $s = shift; 234 my $i = shift; # how many levels to get to DB sub 235 $i = 0 unless defined $i; 236 $stack[$#stack-$i] |= 1; 237 $DB::single = 0; 238 $running = 1; 239} 240 241#### 242# XXX caller must experimentally determine $start (since it depends 243# on how many client call frames are between this call and the DB call). 244# Such is life. 245# 246sub backtrace { 247 my $self = shift; 248 my $start = shift; 249 my($p,$f,$l,$s,$h,$w,$e,$r,$a, @a, @ret,$i); 250 $start = 1 unless $start; 251 for ($i = $start; ($p,$f,$l,$s,$h,$w,$e,$r) = caller($i); $i++) { 252 @a = @DB::args; 253 for (@a) { 254 s/'/\\'/g; 255 s/([^\0]*)/'$1'/ unless /^-?[\d.]+$/; 256 s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg; 257 s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg; 258 } 259 $w = $w ? '@ = ' : '$ = '; 260 $a = $h ? '(' . join(', ', @a) . ')' : ''; 261 $e =~ s/\n\s*\;\s*\Z// if $e; 262 $e =~ s/[\\\']/\\$1/g if $e; 263 if ($r) { 264 $s = "require '$e'"; 265 } elsif (defined $r) { 266 $s = "eval '$e'"; 267 } elsif ($s eq '(eval)') { 268 $s = "eval {...}"; 269 } 270 $f = "file `$f'" unless $f eq '-e'; 271 push @ret, "$w&$s$a from $f line $l"; 272 last if $DB::signal; 273 } 274 return @ret; 275} 276 277sub _outputall { 278 my $c; 279 for $c (@clients) { 280 $c->output(@_); 281 } 282} 283 284sub trace_toggle { 285 my $s = shift; 286 $DB::trace = !$DB::trace; 287} 288 289 290#### 291# without args: returns all defined subroutine names 292# with subname args: returns a listref [file, start, end] 293# 294sub subs { 295 my $s = shift; 296 if (@_) { 297 my(@ret) = (); 298 while (@_) { 299 my $name = shift; 300 push @ret, [$DB::sub{$name} =~ /^(.*)\:(\d+)-(\d+)$/] 301 if exists $DB::sub{$name}; 302 } 303 return @ret; 304 } 305 return keys %DB::sub; 306} 307 308#### 309# first argument is a filename whose subs will be returned 310# if a filename is not supplied, all subs in the current 311# filename are returned. 312# 313sub filesubs { 314 my $s = shift; 315 my $fname = shift; 316 $fname = $DB::filename unless $fname; 317 return grep { $DB::sub{$_} =~ /^$fname/ } keys %DB::sub; 318} 319 320#### 321# returns a list of all filenames that DB knows about 322# 323sub files { 324 my $s = shift; 325 my(@f) = grep(m|^_<|, keys %main::); 326 return map { substr($_,2) } @f; 327} 328 329#### 330# returns reference to an array holding the lines in currently 331# loaded file 332# 333sub lines { 334 my $s = shift; 335 return \@DB::dbline; 336} 337 338#### 339# loadfile($file, $line) 340# 341sub loadfile { 342 my $s = shift; 343 my($file, $line) = @_; 344 if (!defined $main::{'_<' . $file}) { 345 my $try; 346 if (($try) = grep(m|^_<.*$file|, keys %main::)) { 347 $file = substr($try,2); 348 } 349 } 350 if (defined($main::{'_<' . $file})) { 351 my $c; 352# _outputall("Loading file $file.."); 353 *DB::dbline = "::_<$file"; 354 $DB::filename = $file; 355 for $c (@clients) { 356# print "2 ", $file, '|', $line, "\n"; 357 $c->showfile($file, $line); 358 } 359 return $file; 360 } 361 return undef; 362} 363 364sub lineevents { 365 my $s = shift; 366 my $fname = shift; 367 my(%ret) = (); 368 my $i; 369 $fname = $DB::filename unless $fname; 370 local(*DB::dbline) = "::_<$fname"; 371 for ($i = 1; $i <= $#DB::dbline; $i++) { 372 $ret{$i} = [$DB::dbline[$i], split(/\0/, $DB::dbline{$i})] 373 if defined $DB::dbline{$i}; 374 } 375 return %ret; 376} 377 378sub set_break { 379 my $s = shift; 380 my $i = shift; 381 my $cond = shift; 382 $i ||= $DB::lineno; 383 $cond ||= '1'; 384 $i = _find_subline($i) if ($i =~ /\D/); 385 $s->output("Subroutine not found.\n") unless $i; 386 if ($i) { 387 if ($DB::dbline[$i] == 0) { 388 $s->output("Line $i not breakable.\n"); 389 } 390 else { 391 $DB::dbline{$i} =~ s/^[^\0]*/$cond/; 392 } 393 } 394} 395 396sub set_tbreak { 397 my $s = shift; 398 my $i = shift; 399 $i = _find_subline($i) if ($i =~ /\D/); 400 $s->output("Subroutine not found.\n") unless $i; 401 if ($i) { 402 if ($DB::dbline[$i] == 0) { 403 $s->output("Line $i not breakable.\n"); 404 } 405 else { 406 $DB::dbline{$i} =~ s/($|\0)/;9$1/; # add one-time-only b.p. 407 } 408 } 409} 410 411sub _find_subline { 412 my $name = shift; 413 $name =~ s/\'/::/; 414 $name = "${DB::package}\:\:" . $name if $name !~ /::/; 415 $name = "main" . $name if substr($name,0,2) eq "::"; 416 my($fname, $from, $to) = ($DB::sub{$name} =~ /^(.*):(\d+)-(\d+)$/); 417 if ($from) { 418 local *DB::dbline = "::_<$fname"; 419 ++$from while $DB::dbline[$from] == 0 && $from < $to; 420 return $from; 421 } 422 return undef; 423} 424 425sub clr_breaks { 426 my $s = shift; 427 my $i; 428 if (@_) { 429 while (@_) { 430 $i = shift; 431 $i = _find_subline($i) if ($i =~ /\D/); 432 $s->output("Subroutine not found.\n") unless $i; 433 if (defined $DB::dbline{$i}) { 434 $DB::dbline{$i} =~ s/^[^\0]+//; 435 if ($DB::dbline{$i} =~ s/^\0?$//) { 436 delete $DB::dbline{$i}; 437 } 438 } 439 } 440 } 441 else { 442 for ($i = 1; $i <= $#DB::dbline ; $i++) { 443 if (defined $DB::dbline{$i}) { 444 $DB::dbline{$i} =~ s/^[^\0]+//; 445 if ($DB::dbline{$i} =~ s/^\0?$//) { 446 delete $DB::dbline{$i}; 447 } 448 } 449 } 450 } 451} 452 453sub set_action { 454 my $s = shift; 455 my $i = shift; 456 my $act = shift; 457 $i = _find_subline($i) if ($i =~ /\D/); 458 $s->output("Subroutine not found.\n") unless $i; 459 if ($i) { 460 if ($DB::dbline[$i] == 0) { 461 $s->output("Line $i not actionable.\n"); 462 } 463 else { 464 $DB::dbline{$i} =~ s/\0[^\0]*//; 465 $DB::dbline{$i} .= "\0" . $act; 466 } 467 } 468} 469 470sub clr_actions { 471 my $s = shift; 472 my $i; 473 if (@_) { 474 while (@_) { 475 my $i = shift; 476 $i = _find_subline($i) if ($i =~ /\D/); 477 $s->output("Subroutine not found.\n") unless $i; 478 if ($i && $DB::dbline[$i] != 0) { 479 $DB::dbline{$i} =~ s/\0[^\0]*//; 480 delete $DB::dbline{$i} if $DB::dbline{$i} =~ s/^\0?$//; 481 } 482 } 483 } 484 else { 485 for ($i = 1; $i <= $#DB::dbline ; $i++) { 486 if (defined $DB::dbline{$i}) { 487 $DB::dbline{$i} =~ s/\0[^\0]*//; 488 delete $DB::dbline{$i} if $DB::dbline{$i} =~ s/^\0?$//; 489 } 490 } 491 } 492} 493 494sub prestop { 495 my ($client, $val) = @_; 496 return defined($val) ? $preeval->{$client} = $val : $preeval->{$client}; 497} 498 499sub poststop { 500 my ($client, $val) = @_; 501 return defined($val) ? $posteval->{$client} = $val : $posteval->{$client}; 502} 503 504# 505# "pure virtual" methods 506# 507 508# client-specific pre/post-stop actions. 509sub cprestop {} 510sub cpoststop {} 511 512# client complete startup 513sub awaken {} 514 515sub skippkg { 516 my $s = shift; 517 push @skippkg, @_ if @_; 518} 519 520sub evalcode { 521 my ($client, $val) = @_; 522 if (defined $val) { 523 $running = 2; # hand over to DB() to evaluate in its context 524 $ineval->{$client} = $val; 525 } 526 return $ineval->{$client}; 527} 528 529sub ready { 530 my $s = shift; 531 return $ready = 1; 532} 533 534# stubs 535 536sub init {} 537sub stop {} 538sub idle {} 539sub cleanup {} 540sub output {} 541 542# 543# client init 544# 545for (@clients) { $_->init } 546 547$SIG{'INT'} = \&DB::catch; 548 549# disable this if stepping through END blocks is desired 550# (looks scary and deconstructivist with Swat) 551END { $ready = 0 } 552 5531; 554__END__ 555 556=head1 NAME 557 558DB - programmatic interface to the Perl debugging API 559 560=head1 SYNOPSIS 561 562 package CLIENT; 563 use DB; 564 @ISA = qw(DB); 565 566 # these (inherited) methods can be called by the client 567 568 CLIENT->register() # register a client package name 569 CLIENT->done() # de-register from the debugging API 570 CLIENT->skippkg('hide::hide') # ask DB not to stop in this package 571 CLIENT->cont([WHERE]) # run some more (until BREAK or another breakpt) 572 CLIENT->step() # single step 573 CLIENT->next() # step over 574 CLIENT->ret() # return from current subroutine 575 CLIENT->backtrace() # return the call stack description 576 CLIENT->ready() # call when client setup is done 577 CLIENT->trace_toggle() # toggle subroutine call trace mode 578 CLIENT->subs([SUBS]) # return subroutine information 579 CLIENT->files() # return list of all files known to DB 580 CLIENT->lines() # return lines in currently loaded file 581 CLIENT->loadfile(FILE,LINE) # load a file and let other clients know 582 CLIENT->lineevents() # return info on lines with actions 583 CLIENT->set_break([WHERE],[COND]) 584 CLIENT->set_tbreak([WHERE]) 585 CLIENT->clr_breaks([LIST]) 586 CLIENT->set_action(WHERE,ACTION) 587 CLIENT->clr_actions([LIST]) 588 CLIENT->evalcode(STRING) # eval STRING in executing code's context 589 CLIENT->prestop([STRING]) # execute in code context before stopping 590 CLIENT->poststop([STRING])# execute in code context before resuming 591 592 # These methods will be called at the appropriate times. 593 # Stub versions provided do nothing. 594 # None of these can block. 595 596 CLIENT->init() # called when debug API inits itself 597 CLIENT->stop(FILE,LINE) # when execution stops 598 CLIENT->idle() # while stopped (can be a client event loop) 599 CLIENT->cleanup() # just before exit 600 CLIENT->output(LIST) # called to print any output that API must show 601 602=head1 DESCRIPTION 603 604Perl debug information is frequently required not just by debuggers, 605but also by modules that need some "special" information to do their 606job properly, like profilers. 607 608This module abstracts and provides all of the hooks into Perl internal 609debugging functionality, so that various implementations of Perl debuggers 610(or packages that want to simply get at the "privileged" debugging data) 611can all benefit from the development of this common code. Currently used 612by Swat, the perl/Tk GUI debugger. 613 614Note that multiple "front-ends" can latch into this debugging API 615simultaneously. This is intended to facilitate things like 616debugging with a command line and GUI at the same time, debugging 617debuggers etc. [Sounds nice, but this needs some serious support -- GSAR] 618 619In particular, this API does B<not> provide the following functions: 620 621=over 4 622 623=item * 624 625data display 626 627=item * 628 629command processing 630 631=item * 632 633command alias management 634 635=item * 636 637user interface (tty or graphical) 638 639=back 640 641These are intended to be services performed by the clients of this API. 642 643This module attempts to be squeaky clean w.r.t C<use strict;> and when 644warnings are enabled. 645 646 647=head2 Global Variables 648 649The following "public" global names can be read by clients of this API. 650Beware that these should be considered "readonly". 651 652=over 8 653 654=item $DB::sub 655 656Name of current executing subroutine. 657 658=item %DB::sub 659 660The keys of this hash are the names of all the known subroutines. Each value 661is an encoded string that has the sprintf(3) format 662C<("%s:%d-%d", filename, fromline, toline)>. 663 664=item $DB::single 665 666Single-step flag. Will be true if the API will stop at the next statement. 667 668=item $DB::signal 669 670Signal flag. Will be set to a true value if a signal was caught. Clients may 671check for this flag to abort time-consuming operations. 672 673=item $DB::trace 674 675This flag is set to true if the API is tracing through subroutine calls. 676 677=item @DB::args 678 679Contains the arguments of current subroutine, or the C<@ARGV> array if in the 680toplevel context. 681 682=item @DB::dbline 683 684List of lines in currently loaded file. 685 686=item %DB::dbline 687 688Actions in current file (keys are line numbers). The values are strings that 689have the sprintf(3) format C<("%s\000%s", breakcondition, actioncode)>. 690 691=item $DB::package 692 693Package namespace of currently executing code. 694 695=item $DB::filename 696 697Currently loaded filename. 698 699=item $DB::subname 700 701Fully qualified name of currently executing subroutine. 702 703=item $DB::lineno 704 705Line number that will be executed next. 706 707=back 708 709=head2 API Methods 710 711The following are methods in the DB base class. A client must 712access these methods by inheritance (*not* by calling them directly), 713since the API keeps track of clients through the inheritance 714mechanism. 715 716=over 8 717 718=item CLIENT->register() 719 720register a client object/package 721 722=item CLIENT->evalcode(STRING) 723 724eval STRING in executing code context 725 726=item CLIENT->skippkg('D::hide') 727 728ask DB not to stop in these packages 729 730=item CLIENT->run() 731 732run some more (until a breakpt is reached) 733 734=item CLIENT->step() 735 736single step 737 738=item CLIENT->next() 739 740step over 741 742=item CLIENT->done() 743 744de-register from the debugging API 745 746=back 747 748=head2 Client Callback Methods 749 750The following "virtual" methods can be defined by the client. They will 751be called by the API at appropriate points. Note that unless specified 752otherwise, the debug API only defines empty, non-functional default versions 753of these methods. 754 755=over 8 756 757=item CLIENT->init() 758 759Called after debug API inits itself. 760 761=item CLIENT->prestop([STRING]) 762 763Usually inherited from DB package. If no arguments are passed, 764returns the prestop action string. 765 766=item CLIENT->stop() 767 768Called when execution stops (w/ args file, line). 769 770=item CLIENT->idle() 771 772Called while stopped (can be a client event loop). 773 774=item CLIENT->poststop([STRING]) 775 776Usually inherited from DB package. If no arguments are passed, 777returns the poststop action string. 778 779=item CLIENT->evalcode(STRING) 780 781Usually inherited from DB package. Ask for a STRING to be C<eval>-ed 782in executing code context. 783 784=item CLIENT->cleanup() 785 786Called just before exit. 787 788=item CLIENT->output(LIST) 789 790Called when API must show a message (warnings, errors etc.). 791 792 793=back 794 795 796=head1 BUGS 797 798The interface defined by this module is missing some of the later additions 799to perl's debugging functionality. As such, this interface should be considered 800highly experimental and subject to change. 801 802=head1 AUTHOR 803 804Gurusamy Sarathy gsar@activestate.com 805 806This code heavily adapted from an early version of perl5db.pl attributable 807to Larry Wall and the Perl Porters. 808 809=cut 810