Devel-ebug-0.56/0000755000175000017500000000000012323642033013255 5ustar awwaiidawwaiidDevel-ebug-0.56/lib/0000755000175000017500000000000012323642033014023 5ustar awwaiidawwaiidDevel-ebug-0.56/lib/Devel/0000755000175000017500000000000012323642033015062 5ustar awwaiidawwaiidDevel-ebug-0.56/lib/Devel/ebug/0000755000175000017500000000000012323642033016004 5ustar awwaiidawwaiidDevel-ebug-0.56/lib/Devel/ebug/Backend/0000755000175000017500000000000012323642033017333 5ustar awwaiidawwaiidDevel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/0000755000175000017500000000000012323642033020571 5ustar awwaiidawwaiidDevel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/ActionPoints.pm0000644000175000017500000000715512323642033023551 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::ActionPoints; $Devel::ebug::Backend::Plugin::ActionPoints::VERSION = '0.56'; use strict; use warnings; use File::Spec; sub register_commands { return ( break_point => { sub => \&break_point, record => 1 }, break_points => { sub => \&break_points }, break_points_with_condition => { sub => \&break_points_with_condition }, all_break_points_with_condition => { sub => \&all_break_points_with_condition }, break_point_delete => { sub => \&break_point_delete, record => 1 }, break_point_subroutine => { sub => \&break_point_subroutine, record => 1 }, watch_point => { sub => \&watch_point, record => 1 }, break_on_load => { sub => \&break_on_load }, ); } sub break_point { my($req, $context) = @_; my $line = set_break_point($req->{filename}, $req->{line}, $req->{condition}); return $line ? { line => $line } : {}; } sub break_points { my($req, $context) = @_; use vars qw(@dbline %dbline); my $filename = $req->{filename} || $context->{filename}; *DB::dbline = $main::{ '_<' . $filename }; my $break_points = [ sort { $a <=> $b } grep { $DB::dbline{$_} } keys %DB::dbline ]; return { break_points => $break_points }; } sub break_points_with_condition { my($req, $context) = @_; use vars qw(@dbline %dbline); my $filename = $req->{filename} || $context->{filename}; *DB::dbline = $main::{ '_<' . $filename }; my $break_points = [ map { my $c = $DB::dbline{$_}; { filename => $filename, line => $_, ( $c && $c != 1 ) ? ( condition => $c ) : () } } sort { $a <=> $b } grep { $DB::dbline{$_} } keys %DB::dbline ]; return { break_points => $break_points }; } sub all_break_points_with_condition { my($req, $context) = @_; use vars qw(@dbline %dbline); my $files = Devel::ebug::Backend::Plugin::Filenames::filenames ( $req, $context ); # breaks encapsulation my @break_points; foreach my $file ( sort @{$files->{filenames}} ) { *DB::dbline = $main::{ '_<' . $file }; push @break_points, map { my $c = $DB::dbline{$_}; { filename => $file, line => $_, ( $c && $c != 1 ) ? ( condition => $c ) : () } } sort { $a <=> $b } grep { $DB::dbline{$_} } keys %DB::dbline; } return { break_points => \@break_points }; } sub break_point_delete { my($req, $context) = @_; use vars qw(@dbline %dbline); *DB::dbline = $main::{ '_<' . $req->{filename} }; $DB::dbline{$req->{line}} = 0; return {}; } sub break_point_subroutine { my($req, $context) = @_; my($filename, $start, $end) = $DB::sub{$req->{subroutine}} =~ m/^(.+):(\d+)-(\d+)$/; my $line = set_break_point($filename, $start); return $line ? { line => $line } : {}; } sub watch_point { my($req, $context) = @_; my $watch_point = $req->{watch_point}; push @{$context->{watch_points}}, $watch_point; return {}; } # set a break point sub set_break_point { my($filename, $line, $condition) = @_; $condition ||= 1; *DB::dbline = $main::{ '_<' . $filename }; # move forward until a line we can actually break on while (1) { return 0 if not defined $DB::dbline[$line]; # end of code last unless $DB::dbline[$line] == 0; # not breakable $line++; } $DB::dbline{$line} = $condition; return $line; } #set a break point on file loading sub break_on_load{ my($req, $context) = @_; my $filename = $req->{filename}; $DB::break_on_load{$filename} = 1; if (!File::Spec->file_name_is_absolute( $filename )){ #add the absolute path $filename = File::Spec->rel2abs( $filename); $DB::break_on_load{$filename} = 1; } return {}; } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/StackTrace.pm0000644000175000017500000000074612323642033023162 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::StackTrace; $Devel::ebug::Backend::Plugin::StackTrace::VERSION = '0.56'; use strict; use warnings; use Devel::StackTrace; sub register_commands { return ( stack_trace => { sub => \&stack_trace } ); } sub stack_trace { my($req, $context) = @_; my $trace = Devel::StackTrace->new; my @frames = $trace->frames; # remove our internal frames shift @frames; shift @frames; shift @frames; return { stack_trace => \@frames }; } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/Filenames.pm0000644000175000017500000000100112323642033023022 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::Filenames; $Devel::ebug::Backend::Plugin::Filenames::VERSION = '0.56'; use strict; use warnings; sub register_commands { return ( filenames => { sub => \&filenames } ); } sub filenames { my($req, $context) = @_; my %filenames; foreach my $sub (keys %DB::sub) { my($filename, $start, $end) = $DB::sub{$sub} =~ m/^(.+):(\d+)-(\d+)$/; next if $filename =~ /^\(eval/; $filenames{$filename}++; } return { filenames => [sort keys %filenames] }; } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/Codelines.pm0000644000175000017500000000062712323642033023041 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::Codelines; $Devel::ebug::Backend::Plugin::Codelines::VERSION = '0.56'; use strict; use warnings; sub register_commands { return ( codelines => { sub => \&codelines } ); } sub codelines { my($req, $context) = @_; my $filename = $req->{filename}; my @lines = @{$req->{lines}}; return { codelines => [ DB::fetch_codelines($filename, @lines)] }; } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/Commands.pm0000644000175000017500000000046312323642033022673 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::Commands; $Devel::ebug::Backend::Plugin::Commands::VERSION = '0.56'; use strict; use warnings; sub register_commands { return ( commands => { sub => \&commands }, ); } sub commands { my($req, $context) = @_; return { commands => $context->{history} }; } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/Output.pm0000644000175000017500000000116412323642033022431 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::Output; $Devel::ebug::Backend::Plugin::Output::VERSION = '0.56'; use strict; use warnings; my $stdout = ""; my $stderr = ""; if ($ENV{PERL_DEBUG_DONT_RELAY_IO}) { open NULL, ">/dev/null"; open NULL, '>', \$stdout; open NULL, '>', \$stderr; } else { close STDOUT; open STDOUT, '>', \$stdout or die "Can't open STDOUT: $!"; close STDERR; open STDERR, '>', \$stderr or die "Can't open STDOUT: $!"; } sub register_commands { return (output => { sub => \&output }); } sub output { my($req, $context) = @_; return { stdout => $stdout, stderr => $stderr, }; } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/Basic.pm0000644000175000017500000000145712323642033022157 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::Basic; $Devel::ebug::Backend::Plugin::Basic::VERSION = '0.56'; use strict; use warnings; sub register_commands { return (basic => { sub => \&basic }); } sub basic { my ($req, $context) = @_; return { codeline => $context->{codeline}, filename => $context->{filename}, finished => $context->{finished}, line => $context->{line}, package => $context->{package}, subroutine => subroutine($req, $context), }; } sub subroutine { my ($req, $context) = @_; foreach my $sub (keys %DB::sub) { my ($filename, $start, $end) = $DB::sub{$sub} =~ m/^(.+):(\d+)-(\d+)$/; next if $filename ne $context->{filename}; next unless $context->{line} >= $start && $context->{line} <= $end; return $sub; } return 'main'; } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/Eval.pm0000644000175000017500000000164312323642033022022 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::Eval; $Devel::ebug::Backend::Plugin::Eval::VERSION = '0.56'; use strict; use warnings; sub register_commands { return ( eval => { sub => \&DB::eval, record => 1 }, yaml => { sub => \&DB::yaml }, ); } package DB; $DB::VERSION = '0.56'; # there appears to be something semi-magical about the DB # namespace that makes this eval only work when it's in it sub eval { my($req, $context) = @_; my $eval = $req->{eval}; local $SIG{__WARN__} = sub {}; my $v = eval "package $context->{package}; $eval"; if ($@) { return { eval => $@, exception => 1 }; } else { return { eval => $v, exception => 0 }; } } sub yaml { my($req, $context) = @_; my $eval = $req->{yaml}; local $SIG{__WARN__} = sub {}; my $v = eval "package $context->{package}; use YAML; Dump($eval)"; if ($@) { return { yaml => $@ }; } else { return { yaml => $v }; } } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/Ping.pm0000644000175000017500000000061512323642033022026 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::Ping; $Devel::ebug::Backend::Plugin::Ping::VERSION = '0.56'; use strict; use warnings; sub register_commands { return ( ping => { sub => \&ping } ); } sub ping { my($req, $context) = @_; my $secret = $ENV{SECRET}; die "Did not pass secret" unless $req->{secret} eq $secret; $ENV{SECRET} = ""; return { version => $DB::VERSION, } } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/Run.pm0000644000175000017500000000301012323642033021665 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::Run; $Devel::ebug::Backend::Plugin::Run::VERSION = '0.56'; use strict; use warnings; sub register_commands { return ( next => { sub => \&next, record => 1 }, return => { sub => \&return, record => 1 }, run => { sub => \&run, record => 1 }, step => { sub => \&step, record => 1 }, ); } sub next { my($req, $context) = @_; $context->{mode} = "next"; # single step (but over subroutines) $context->{last} = 1; # and out of the loop return {}; } sub return { my($req, $context) = @_; if ($req->{values}) { $context->{stack}->[0]->{return} = $req->{values}; } $context->{mode} = "return"; # run until returned from subroutine $DB::single = 0; # run if ($context->{stack}->[-1]) { $context->{stack}->[-1]->{single} = 1; # single step higher up } $context->{last} = 1; # and out of the loop return {}; } sub run { my($req, $context) = @_; $context->{mode} = "run"; # run until break point if (@{$context->{watch_points}}) { # watch points, let's go slow $context->{watch_single} = 0; } else { # no watch points? let's go fast! $DB::single = 0; # run until next break point } $context->{last} = 1; # and out of the loop return {}; } sub step { my($req, $context) = @_; $DB::single = 1; # single step $context->{mode} = "step"; # single step (into subroutines) $context->{last} = 1; # and out of the loop, onto the next command return {}; } 1; Devel-ebug-0.56/lib/Devel/ebug/Backend/Plugin/Pad.pm0000644000175000017500000000134712323642033021640 0ustar awwaiidawwaiidpackage Devel::ebug::Backend::Plugin::Pad; $Devel::ebug::Backend::Plugin::Pad::VERSION = '0.56'; use strict; use warnings; use PadWalker; sub register_commands { return ( pad => { sub => \&DB::pad } ) } package DB; $DB::VERSION = '0.56'; use Scalar::Util qw(blessed reftype); sub pad { my($req, $context) = @_; my $pad; my $h = eval { PadWalker::peek_my(2) }; foreach my $k (sort keys %$h) { if ($k =~ /^@/) { my @v = eval "package $context->{package}; ($k)"; $pad->{$k} = \@v; } else { my $v = eval "package $context->{package}; $k"; $pad->{$k} = $v; # workaround for blessed globs $pad->{$k} = "".$v if blessed $v and reftype $v eq "GLOB"; } } return { pad => $pad }; } 1; Devel-ebug-0.56/lib/Devel/ebug/Plugin/0000755000175000017500000000000012323642033017242 5ustar awwaiidawwaiidDevel-ebug-0.56/lib/Devel/ebug/Plugin/ActionPoints.pm0000644000175000017500000000474712323642033022226 0ustar awwaiidawwaiidpackage Devel::ebug::Plugin::ActionPoints; $Devel::ebug::Plugin::ActionPoints::VERSION = '0.56'; use strict; use warnings; use base qw(Exporter); our @EXPORT = qw(break_point break_point_delete break_point_subroutine break_points break_points_with_condition all_break_points_with_condition watch_point break_on_load); # set a break point (by default in the current file) sub break_point { my $self = shift; my($filename, $line, $condition); if ($_[0] =~ /^\d+$/) { $filename = $self->filename; } else { $filename = shift; } ($line, $condition) = @_; my $response = $self->talk({ command => "break_point", filename => $filename, line => $line, condition => $condition, }); return $response->{line}; } # delete a break point (by default in the current file) sub break_point_delete { my $self = shift; my($filename, $line); my $first = shift; if ($first =~ /^\d+$/) { $line = $first; $filename = $self->filename; } else { $filename = $first; $line = shift; } my $response = $self->talk({ command => "break_point_delete", filename => $filename, line => $line, }); } # set a break point sub break_point_subroutine { my($self, $subroutine) = @_; my $response = $self->talk({ command => "break_point_subroutine", subroutine => $subroutine, }); return $response->{line}; } # list break points sub break_points { my($self, $filename) = @_; my $response = $self->talk({ command => "break_points", filename => $filename, }); return @{$response->{break_points}}; } # list break points with condition sub break_points_with_condition { my($self, $filename) = @_; my $response = $self->talk({ command => "break_points_with_condition", filename => $filename, }); return @{$response->{break_points}}; } # list break points with condition for the whole program sub all_break_points_with_condition { my($self, $filename) = @_; my $response = $self->talk({ command => "all_break_points_with_condition", filename => $filename, }); return @{$response->{break_points}}; } # set a watch point sub watch_point { my($self, $watch_point) = @_; my $response = $self->talk({ command => "watch_point", watch_point => $watch_point, }); } # set a break point on file loading sub break_on_load { my $self = shift; my($filename) = @_; my $response = $self->talk({ command => "break_on_load", filename => $filename, }); return $response->{line}; } 1; Devel-ebug-0.56/lib/Devel/ebug/Plugin/StackTrace.pm0000644000175000017500000000501112323642033021621 0ustar awwaiidawwaiidpackage Devel::ebug::Plugin::StackTrace; $Devel::ebug::Plugin::StackTrace::VERSION = '0.56'; use strict; use warnings; use Scalar::Util qw(blessed); use base qw(Exporter); our @EXPORT = qw(stack_trace stack_trace_human stack_trace_human_args); # return the stack trace sub stack_trace { my($self) = @_; my $response = $self->talk({ command => "stack_trace" }); return @{$response->{stack_trace}||[]}; } # return the stack trace in a human-readable format sub stack_trace_human { my($self) = @_; my @human; my @stack = $self->stack_trace; foreach my $frame (@stack) { my $subroutine = $frame->subroutine; my $package = $frame->package; my @args = $frame->args; my $first = $args[0]; my $first_class = ref($first); my($subroutine_class, $subroutine_method) = $subroutine =~ /^(.+)::([^:])+?$/; # warn "first: $first, first class: $first_class, package: $package, subroutine: $subroutine ($subroutine_class :: $subroutine_method)\n"; if (defined $first && blessed($first) && $subroutine =~ /^${first_class}::/ && $subroutine =~ /^$package/) { $subroutine =~ s/^${first_class}:://; shift @args; push @human, "\$self->$subroutine" . $self->stack_trace_human_args(@args); } elsif (defined $first && blessed($first) && $subroutine =~ /^${first_class}::/) { $subroutine =~ s/^${first_class}:://; shift @args; my($name) = $first_class =~ /([^:]+)$/; $first = '$' . lc($name); push @human, "$first->$subroutine" . $self->stack_trace_human_args(@args); } elsif ($subroutine =~ s/^${package}:://) { push @human, "$subroutine" . $self->stack_trace_human_args(@args); } elsif (defined $first && $subroutine_class eq $first) { shift @args; push @human, "$first->new" . $self->stack_trace_human_args(@args); } else { push @human, "$subroutine" . $self->stack_trace_human_args(@args); } } return @human; } sub stack_trace_human_args { my($self, @args) = @_; foreach my $arg (@args) { if (not defined $arg) { $arg = "undef"; } elsif (ref($arg) eq 'ARRAY') { $arg = "[...]"; } elsif (ref($arg) eq 'HASH') { $arg = "{...}"; } elsif (ref($arg)) { my($name) = ref($arg) =~ /([^:]+)$/; $arg = '$' . lc($name); } elsif ($arg =~ /^-?[\d.]+$/) { # number, do nothing } elsif ($arg =~ /^[\w:]*$/) { $arg =~ s/([\'\\])/\\$1/g; $arg = qq{'$arg'}; } else { $arg =~ s/([\'\\])/\\$1/g; $arg = qq{"$arg"}; } } return '(' . join(", ", @args) . ')'; } 1; Devel-ebug-0.56/lib/Devel/ebug/Plugin/Filenames.pm0000644000175000017500000000050212323642033021500 0ustar awwaiidawwaiidpackage Devel::ebug::Plugin::Filenames; $Devel::ebug::Plugin::Filenames::VERSION = '0.56'; use strict; use warnings; use base qw(Exporter); our @EXPORT = qw(filenames); # list filenames sub filenames { my($self) = @_; my $response = $self->talk({ command => "filenames" }); return @{$response->{filenames}}; } 1; Devel-ebug-0.56/lib/Devel/ebug/Plugin/Codelines.pm0000644000175000017500000000106512323642033021507 0ustar awwaiidawwaiidpackage Devel::ebug::Plugin::Codelines; $Devel::ebug::Plugin::Codelines::VERSION = '0.56'; use strict; use warnings; use base qw(Exporter); our @EXPORT = qw(codelines); # return some lines of code sub codelines { my($self) = shift; my($filename, @lines); if (!defined($_[0]) || $_[0] =~ /^\d+$/) { $filename = $self->filename; } else { $filename = shift; } @lines = map { $_ -1 } @_; my $response = $self->talk({ command => "codelines", filename => $filename, lines => \@lines, }); return @{$response->{codelines}}; } 1; Devel-ebug-0.56/lib/Devel/ebug/Plugin/Output.pm0000644000175000017500000000051312323642033021077 0ustar awwaiidawwaiidpackage Devel::ebug::Plugin::Output; $Devel::ebug::Plugin::Output::VERSION = '0.56'; use strict; use warnings; use base qw(Exporter); our @EXPORT = qw(output); # return stdout, stderr sub output { my($self) = @_; my $response = $self->talk({ command => "output" }); return ($response->{stdout}, $response->{stderr}); } 1; Devel-ebug-0.56/lib/Devel/ebug/Plugin/Basic.pm0000644000175000017500000000102112323642033020613 0ustar awwaiidawwaiidpackage Devel::ebug::Plugin::Basic; $Devel::ebug::Plugin::Basic::VERSION = '0.56'; use strict; use warnings; use base qw(Exporter); our @EXPORT = qw(basic); # get basic debugging information sub basic { my ($self) = @_; my $response = $self->talk({ command => "basic" }); $self->codeline($response->{codeline}); $self->filename($response->{filename}); $self->finished($response->{finished}); $self->line($response->{line}); $self->package($response->{package}); $self->subroutine($response->{subroutine}); } 1; Devel-ebug-0.56/lib/Devel/ebug/Plugin/Eval.pm0000644000175000017500000000105412323642033020467 0ustar awwaiidawwaiidpackage Devel::ebug::Plugin::Eval; $Devel::ebug::Plugin::Eval::VERSION = '0.56'; use strict; use warnings; use base qw(Exporter); our @EXPORT = qw(eval yaml); # eval sub eval { my($self, $eval) = @_; my $response = $self->talk({ command => "eval", eval => $eval, }); return wantarray ? ( $response->{eval}, $response->{exception} ) : $response->{eval}; } # yaml sub yaml { my($self, $yaml) = @_; my $response = $self->talk({ command => "yaml", yaml => $yaml, }); return $response->{yaml}; } 1; Devel-ebug-0.56/lib/Devel/ebug/Plugin/Run.pm0000644000175000017500000000247012323642033020347 0ustar awwaiidawwaiidpackage Devel::ebug::Plugin::Run; $Devel::ebug::Plugin::Run::VERSION = '0.56'; use strict; use warnings; use base qw(Exporter); our @EXPORT = qw(undo run return step next); # undo sub undo { my($self, $levels) = @_; $levels ||= 1; my $response = $self->talk({ command => "commands" }); my @commands = @{$response->{commands}}; pop @commands foreach 1..$levels; # use YAML; warn Dump \@commands; my $proc = $self->proc; $proc->die; $self->load; $self->talk($_) foreach @commands; $self->basic; } # run until a breakpoint sub run { my($self) = @_; my $response = $self->talk({ command => "run" }); $self->basic; # get basic information for the new line } # return from a subroutine sub return { my($self, @values) = @_; my $values; $values = \@values if @values; my $response = $self->talk({ command => "return", values => $values, }); $self->basic; # get basic information for the new line } # step onto the next line (going into subroutines) sub step { my($self) = @_; my $response = $self->talk({ command => "step" }); $self->basic; # get basic information for the new line } # step onto the next line (going over subroutines) sub next { my($self) = @_; my $response = $self->talk({ command => "next" }); $self->basic; # get basic information for the new line } 1; Devel-ebug-0.56/lib/Devel/ebug/Plugin/Pad.pm0000644000175000017500000000145612323642033020312 0ustar awwaiidawwaiidpackage Devel::ebug::Plugin::Pad; $Devel::ebug::Plugin::Pad::VERSION = '0.56'; use strict; use warnings; use base qw(Exporter); our @EXPORT = qw(pad pad_human); # find the pad sub pad { my($self) = @_; my $response = $self->talk({ command => "pad" }); return $response->{pad}; } # human-readable pad sub pad_human { my($self) = @_; my $pad = $self->pad; foreach my $var (keys %$pad) { if ($var =~ /^@/) { my @values = @{$pad->{$var}}; my $value = $self->stack_trace_human_args(@values); $pad->{$var} = $value; } elsif ($var =~ /^%/) { $pad->{$var} = '(...)'; } else { my $value = $pad->{$var}; $value = $self->stack_trace_human_args($value); $value =~ s/^\(//; $value =~ s/\)$//; $pad->{$var} = $value; } } return $pad; } 1; Devel-ebug-0.56/lib/Devel/ebug/Console.pm0000644000175000017500000001414112323642033017745 0ustar awwaiidawwaiidpackage Devel::ebug::Console; $Devel::ebug::Console::VERSION = '0.56'; use strict; use warnings; use lib 'lib'; use Carp; use Class::Accessor::Chained::Fast; use Devel::ebug; use Term::ReadLine; use base qw(Class::Accessor::Chained::Fast); sub run { my $self = shift; my $backend = shift; $SIG{INT} = sub { die "INT"; }; my $filename = join " ", @ARGV; unless ($filename) { $filename = '-e "Interactive ebugging shell"'; } my $ebug = Devel::ebug->new; $ebug->program($filename); $ebug->backend($backend); $ebug->load; my $codelines; print "* Welcome to Devel::ebug $Devel::ebug::VERSION\n"; my $term = Term::ReadLine->new('ebug'); my $attribs = $term->Attribs; $attribs->{completion_function} = sub { my ($text, $line, $start) = @_; my $pad = $ebug->pad || {}; return unless $line =~ s/^x //; my @result = grep { /^\Q$line/ } keys %$pad; if ($line =~ /^[\$\@]/) { @result = map { s/^[\$\@]//; $_ } @result; } return @result; }; my $last_command = "s"; my $list_always = 0; my $list_lines_count = 9; while (1) { if ($ebug->finished) { print "ebug: Program finished. Enter 'restart' or 'q'\n"; } else { if ($list_always) { show_codelines($codelines, $ebug, $list_lines_count) if($list_always); } else { print $ebug->subroutine . "(" . $ebug->filename . "#" . $ebug->line . "):\n" . $ebug->codeline, "\n"; } } my $command = $term->readline("ebug: "); $command = "q" if not defined $command; $command = $last_command if ($command eq ""); if ($command =~ /^\s*[?h](elp)?\s*$/) { print 'Commands: b Set break point at a line number (eg: b 6, b code.pl 6, b code.pl 6 $x > 7, b Calc::fib) bf break on file loading (eg: bf Calc.pm) d Delete a break point (d 6, d code.pl 6) e Eval Perl code and print the result (eg: e $x+$y) f Show all the filenames loaded l List codelines or set number of codelines to list (eg: l, l 20) L List codelines always (toggle) n Next (steps over subroutine calls) o Output (show STDOUT, STDERR) p Show pad r Run until next break point or watch point ret Return from subroutine (eg: ret, ret 3.141) restart Restart the program s Step (steps into subroutine calls) T Show a stack trace u Undo (eg: u, u 4) w Set a watchpoint (eg: w $t > 10) x Dump a variable using YAML (eg: x $object) q Quit '; } elsif ($command eq 'l') { show_codelines($codelines, $ebug, $list_lines_count); } elsif ($command =~ /^ l \s+ (\d+) $/x) { $list_lines_count = $1 if $1 > 0; show_codelines($codelines, $ebug, $list_lines_count); } elsif ($command eq 'L') { $list_always = !$list_always; } elsif ($command eq 'p') { my $pad = $ebug->pad_human; foreach my $k (sort keys %$pad) { my $v = $pad->{$k}; print " $k = $v;\n"; } } elsif ($command eq 's') { $ebug->step; } elsif ($command eq 'n') { $ebug->next; } elsif ($command eq 'o') { my($stdout, $stderr) = $ebug->output; print "STDOUT:\n$stdout\n"; print "STDERR:\n$stderr\n"; } elsif ($command eq 'r') { $ebug->run; # TODO: Consider using this instead: # eval { $ebug->run }; } elsif ($command eq 'restart') { $ebug->load; } elsif ($command =~ /^ret ?(.*)/) { $ebug->return($1); } elsif ($command eq 'T') { my @trace = $ebug->stack_trace_human; foreach my $frame (@trace) { print "$frame\n"; } } elsif ($command eq 'f') { print "$_\n" foreach $ebug->filenames; } elsif (my($line, $condition) = $command =~ /^b (\d+) ?(.*)/) { undef $condition unless $condition; $ebug->break_point($line, $condition); } elsif ($command =~ /^b (.+?) (\d+) ?(.*)/) { $ebug->break_point($1, $2, $3); } elsif ($command =~ /^b (.+)/) { $ebug->break_point_subroutine($1); } elsif ($command =~ /^bf (.+)/) { $ebug->break_on_load($1); } elsif ($command =~ /^d (.+?) (\d+)/) { $ebug->break_point_delete($1, $2); } elsif ($command =~ /^d (\d+)/) { $ebug->break_point_delete($1); } elsif ($command =~ /^w (.+)/) { my($watch_point) = $command =~ /^w (.+)/; $ebug->watch_point($watch_point); } elsif ($command =~ /^u ?(.*)/) { $ebug->undo($1); } elsif ($command eq 'q') { exit; } elsif ($command =~ /^x (.+)/) { my $v = $ebug->eval("use YAML; Dump($1)") || ""; print "$v\n"; } elsif ($command =~ /^e (.+)/) { my $v = $ebug->eval($1) || ""; print "$v\n"; } elsif ($command) { my $v = $ebug->eval($command) || ""; print "$v\n"; } $last_command = $command; } } sub show_codelines { my ($codelines, $ebug, $list_lines_count) = @_; my $line_count = int($list_lines_count / 2); if (not exists $codelines->{$ebug->filename}) { $codelines->{$ebug->filename} = [$ebug->codelines]; } my @span = ($ebug->line-$line_count .. $ebug->line+$line_count); @span = grep { $_ > 0 } @span; my @codelines = @{$codelines->{$ebug->filename}}; my @break_points = $ebug->break_points(); my %break_points; $break_points{$_}++ foreach @break_points; foreach my $s (@span) { my $codeline = $codelines[$s -1 ]; next unless defined $codeline; if ($s == $ebug->line) { print "*"; } elsif ($break_points{$s}) { print "b"; } else { print " "; } print "$s:$codeline\n"; } } 1; __END__ =head1 NAME Devel::ebug::Console - Console front end to Devel::ebug =head1 SYNOPSIS # it's easier to use the 'ebug' script use Devel::ebug::Console; my $console = Devel::ebug::Console->new(); $console->run(); =head1 DESCRIPTION L is an interactive commmand-line front end to L. It is a simple Perl debugger, much like perl5db.pl. =head1 SEE ALSO L, L =head1 AUTHOR Leon Brocard, C<< >> =head1 COPYRIGHT Copyright (C) 2005, Leon Brocard This program is free software; you can redistribute it or modify it under the same terms as Perl itself. Devel-ebug-0.56/lib/Devel/ebug/Backend.pm0000644000175000017500000001370012323642033017672 0ustar awwaiidawwaiidpackage DB; $DB::VERSION = '0.56'; use strict; use warnings; use IO::Socket::INET; use String::Koremutake; # use YAML::Syck; use YAML; use Module::Pluggable search_path => 'Devel::ebug::Backend::Plugin', require => 1; use vars qw(@dbline %dbline); # Let's catch INT signals and set a flag when they occur $SIG{INT} = sub { $DB::signal = 1; return; }; my $context = { finished => 0, initialise => 1, mode => "step", stack => [], watch_points => [], }; # Commands that the back end can respond to # Set record if the command changes start and should thus be recorded # in order for undo to work properly my %commands = (); sub DB { my ($package, $filename, $line) = caller; ($context->{package}, $context->{filename}, $context->{line}) = ($package, $filename, $line); initialise() if $context->{initialise}; # we're here because of a signal, reset the flag if ($DB::signal) { $DB::signal = 0; } # single step my $old_single = $DB::single; $DB::single = 1; if (@{ $context->{watch_points} }) { my %delete; foreach my $watch_point (@{ $context->{watch_points} }) { local $SIG{__WARN__} = sub { }; my $v = eval "package $package; $watch_point"; if ($v) { $context->{watch_single} = 1; $delete{$watch_point} = 1; } } if ($context->{watch_single} == 0) { return; } else { @{ $context->{watch_points} } = grep { !$delete{$_} } @{ $context->{watch_points} }; } } # we're here because of a break point, test the condition if ($old_single == 0) { my $condition = break_point_condition($filename, $line); if ($condition) { local $SIG{__WARN__} = sub { }; my $v = eval "package $package; $condition"; unless ($v) { # condition not true, go back to running $DB::single = 0; return; } } } $context->{watch_single} = 1; $context->{codeline} = (fetch_codelines($filename, $line - 1))[0]; chomp $context->{codeline}; while (1) { my $req = get(); my $command = $req->{command}; my $sub = $commands{$command}->{sub}; if (defined $sub) { put($sub->($req, $context)); if ($context->{last}) { delete $context->{last}; last; } } else { die "unknown command $command"; } } } sub initialise { my $k = String::Koremutake->new; my $int = $k->koremutake_to_integer($ENV{SECRET}); my $port = 3141 + ($int % 1024); my $server = IO::Socket::INET->new( Listen => 5, LocalAddr => 'localhost', LocalPort => $port, Proto => 'tcp', ReuseAddr => 1, Reuse => 1, ) || die $!; $context->{socket} = $server->accept; foreach my $plugin (__PACKAGE__->plugins) { my $sub = $plugin->can("register_commands"); next unless $sub; my %new = &$sub; foreach my $command (keys %new) { $commands{$command} = $new{$command}; } } $context->{initialise} = 0; } sub put { my ($res) = @_; my $data = unpack("h*", Dump($res)); $context->{socket}->print($data . "\n"); } sub get { exit unless $context->{socket}; my $data = $context->{socket}->getline; my $req = Load(pack("h*", $data)); push @{ $context->{history} }, $req if exists $commands{ $req->{command} }->{record}; return $req; } sub sub { my (@args) = @_; my $sub = $DB::sub; my $frame = { single => $DB::single, sub => $sub }; push @{ $context->{stack} }, $frame; # If we are in 'next' mode, then skip all the lines in the sub $DB::single = 0 if defined $context->{mode} && $context->{mode} eq 'next'; no strict 'refs'; if (wantarray) { my @ret = &$sub; my $frame = pop @{ $context->{stack} }; $DB::single = $frame->{single}; $DB::single = 0 if defined $context->{mode} && $context->{mode} eq 'run' && !@{$context->{watch_points}}; if ($frame->{return}) { return @{ $frame->{return} }; } else { return @ret; } } else { my $ret = &$sub; my $frame = pop @{ $context->{stack} }; $DB::single = $frame->{single}; $DB::single = 0 if defined $context->{mode} && $context->{mode} eq 'run' && !@{$context->{watch_points}}; if ($frame->{return}) { return $frame->{return}->[0]; } else { return $ret; } } } sub DB::postponed { # If this is a subroutine, let postponed_sub() deal with it. return &postponed_sub unless ref \$_[0] eq 'GLOB'; my ($filePath) = @_; $filePath =~ s/^.*_splitpath( $filePath ); #test if the file name match with relative path/absolute path/single file name if (exists $DB::break_on_load{$filePath} || exists $DB::break_on_load{File::Spec->rel2abs( $filePath)} || exists $DB::break_on_load{$fileName}){ $DB::single = 1; } } sub fetch_codelines { my ($filename, @lines) = @_; #use vars qw(@dbline %dbline); *dbline = $main::{ '_<' . $filename }; my @codelines = @dbline; # for modules, not sure why shift @codelines if not defined $codelines[0]; # defined! @codelines = map { defined($_) ? $_ : "" } @codelines; # remove newlines @codelines = map { $_ =~ s/\s+$//; $_ } @codelines; # we run it with -d:ebug::Backend, so remove this extra line @codelines = grep { $_ ne 'use Devel::ebug::Backend;' } @codelines; # for some reasons, the perl internals leave the opening POD line # around but strip the rest. so let's strip the opening POD line @codelines = map { $_ =~ /^=(head|over|item|back|over|cut|pod|begin|end|for)/ ? "" : $_ } @codelines; if (@lines) { @codelines = @codelines[@lines]; } return @codelines; } sub break_point_condition { my ($filename, $line) = @_; *dbline = $main::{ '_<' . $filename }; return $dbline{$line}; } sub END { $context->{finished} = 1; $DB::single = 1; DB::fake::at_exit(); } package DB::fake; $DB::fake::VERSION = '0.56'; sub at_exit { 1; } package DB; # Do not trace this 1; below! 1; Devel-ebug-0.56/lib/Devel/ebug.pm0000644000175000017500000003357612323642033016360 0ustar awwaiidawwaiidpackage Devel::ebug; $Devel::ebug::VERSION = '0.56'; use strict; use warnings; use Carp; use Class::Accessor::Chained::Fast; use Devel::StackTrace; use IO::Socket::INET; use Proc::Background; use String::Koremutake; # use YAML::Syck; use YAML; use Module::Pluggable require => 1; use FindBin qw($Bin); use base qw(Class::Accessor::Chained::Fast); __PACKAGE__->mk_accessors(qw( backend port program socket proc package filename line codeline subroutine finished)); # let's run the code under our debugger and connect to the server it # starts up sub load { my $self = shift; my $program = $self->program; # import all the plugins into our namespace do { eval "use $_ " } for $self->plugins; my $k = String::Koremutake->new; my $rand = int(rand(100_000)); my $secret = $k->integer_to_koremutake($rand); my $port = 3141 + ($rand % 1024); $ENV{SECRET} = $secret; my $backend = $self->backend || "$Bin/ebug_backend_perl"; my $command = "$backend $program";; my $proc = Proc::Background->new( {'die_upon_destroy' => 1}, $command ); croak(qq{Devel::ebug: Failed to start up "$program" in load()}) unless $proc->alive; $self->proc($proc); $ENV{SECRET} = ""; $self->attach($port, $secret); } sub attach { my ($self, $port, $key) = @_; # import all the plugins into our namespace do { eval "use $_ " } for $self->plugins; # try and connect to the server my $socket; foreach ( 1 .. 10 ) { $socket = IO::Socket::INET->new( PeerAddr => "localhost", PeerPort => $port, Proto => 'tcp', Reuse => 1, ReuserAddr => 1, ); last if $socket; sleep 1; } die "Could not connect: $!" unless $socket; $self->socket($socket); my $response = $self->talk( { command => "ping", version => $Devel::ebug::VERSION, secret => $key, } ); my $version = $response->{version}; die "Client version $version != our version $Devel::ebug::VERSION" unless $version eq $Devel::ebug::VERSION; $self->basic; # get basic information for the first line } # # FIXME : this would mean that plugin writers don't need to Export stuff # #sub load_plugins { # my $self = shift; # my $obj = Devel::Symdump->new($self->plugins); # # for ($obj->functions) { # my $name = (split /::/)[-1]; # next if substr($name,0,1) eq '_'; # *basic = \&$_; # } # #} # at the moment, we talk hex-encoded YAML serialisation # don't worry about this too much sub talk { my($self, $req) = @_; my $socket = $self->socket; my $data = unpack("h*", Dump($req)); $socket->print($data . "\n"); $data = <$socket>; if ($data) { my $res = Load(pack("h*", $data)); return $res; } } 1; __END__ =head1 NAME Devel::ebug - A simple, extensible Perl debugger =head1 SYNOPSIS use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("calc.pl"); $ebug->load; print "At line: " . $ebug->line . "\n"; print "In subroutine: " . $ebug->subroutine . "\n"; print "In package: " . $ebug->package . "\n"; print "In filename: " . $ebug->filename . "\n"; print "Code: " . $ebug->codeline . "\n"; $ebug->step; $ebug->step; $ebug->next; my($stdout, $stderr) = $ebug->output; my $actual_line = $ebug->break_point(6); $ebug->break_point(6, '$e == 4'); $ebug->break_point("t/Calc.pm", 29); $ebug->break_point("t/Calc.pm", 29, '$i == 2'); $ebug->break_on_load("t/Calc.pm"); my $actual_line = $ebug->break_point_subroutine("main::add"); $ebug->break_point_delete(29); $ebug->break_point_delete("t/Calc.pm", 29); my @filenames = $ebug->filenames(); my @break_points = $ebug->break_points(); my @break_points = $ebug->break_points("t/Calc.pm"); my @break_points = $ebug->break_points_with_condition(); my @break_points = $ebug->break_points_with_condition("t/Calc.pm"); my @break_points = $ebug->all_break_points_with_condition(); $ebug->watch_point('$x > 100'); my $codelines = $ebug->codelines(@span); $ebug->run; my $pad = $ebug->pad; foreach my $k (sort keys %$pad) { my $v = $pad->{$k}; print "Variable: $k = $v\n"; } my $v = $ebug->eval('2 ** $exp'); my( $v, $is_exception ) = $ebug->eval('die 123'); my $y = $ebug->yaml('$z'); my @frames = $ebug->stack_trace; my @frames2 = $ebug->stack_trace_human; $ebug->undo; $ebug->return; print "Finished!\n" if $ebug->finished; =head1 DESCRIPTION A debugger is a computer program that is used to debug other programs. L is a simple, extensible Perl debugger with a clean API. Using this module, you may easily write a Perl debugger to debug your programs. Alternatively, it comes with an interactive debugger, L. perl5db.pl, Perl's current debugger is currently 2,600 lines of magic and special cases. The code is nearly unreadable: fixing bugs and adding new features is fraught with difficulties. The debugger has no test suite which has caused breakage with changes that couldn't be properly tested. It will also not debug regexes. L is aimed at fixing these problems and delivering a replacement debugger which provides a well-tested simple programmatic interface to debugging programs. This makes it easier to build debuggers on top of L, be they console-, curses-, GUI- or Ajax-based. There are currently two user interfaces to L, L and L. L is a console-based interface to debugging programs, much like perl5db.pl. L is an innovative web-based interface to debugging programs. Note that if you're debugging a program, you can invoke the debugger in the program itself by using the INT signal: kill 2, $$ if $square > 100; L is a work in progress. Internally, L consists of two parts. The frontend is L, which you interact with. The frontend starts the code you are debugging in the background under the backend (running it under perl -d:ebug code.pl). The backend starts a TCP server, which the frontend then connects to, and uses this to drive the backend. This adds some flexibilty in the debugger. There is some minor security in the client/server startup (a secret word), and a random port is used from 3141-4165 so that multiple debugging sessions can happen concurrently. =head1 CONSTRUCTOR =head2 new The constructor creats a Devel::ebug object: my $ebug = Devel::ebug->new; =head2 program The program method selects which program to load: $ebug->program("calc.pl"); =head2 load The load method loads the program and gets ready to debug it: $ebug->load; =head1 METHODS =head2 break_point The break_point method sets a break point in a program. If you are run-ing through a program, the execution will stop at a break point. Break points can be set in a few ways. A break point can be set at a line number in the current file: my $actual_line = $ebug->break_point(6); A break point can be set at a line number in the current file with a condition that must be true for execution to stop at the break point: my $actual_line = $ebug->break_point(6, '$e = 4'); A break point can be set at a line number in a file: my $actual_line = $ebug->break_point("t/Calc.pm", 29); A break point can be set at a line number in a file with a condition that must be true for execution to stop at the break point: my $actual_line = $ebug->break_point("t/Calc.pm", 29, '$i == 2'); Breakpoints can not be set on some lines (for example comments); in this case a breakpoint will be set at the next breakable line, and the line number will be returned. If no such line exists, no breakpoint is set and the function returns C. =head2 break_on_load Set a breakpoint on file loading, the file name can be relative or absolute. =head2 break_point_delete The break_point_delete method deletes an existing break point. A break point at a line number in the current file can be deleted: $ebug->break_point_delete(29); A break point at a line number in a file can be deleted: $ebug->break_point_delete("t/Calc.pm", 29); =head2 break_point_subroutine The break_point_subroutine method sets a break point in a program right at the beginning of the subroutine. The subroutine is specified with the full package name: my $line = $ebug->break_point_subroutine("main::add"); $ebug->break_point_subroutine("Calc::fib"); The return value is the line at which the break point is set. =head2 break_points The break_points method returns a list of all the line numbers in a given file that have a break point set. Return the list of breakpoints in the current file: my @break_points = $ebug->break_points(); Return the list of breakpoints in a given file: my @break_points = $ebug->break_points("t/Calc.pm"); =head2 break_points_with_condition The break_points method returns a list of break points for a given file. Return the list of breakpoints in the current file: my @break_points = $ebug->break_points_with_condition(); Return the list of breakpoints in a given file: my @break_points = $ebug->break_points_with_condition("t/Calc.pm"); Each element of the list has the form { filename => "t/Calc.pm", line => 29, condition => "$foo > 12", } where C might not be present. =head2 all_break_points_with_condition Like C but returns a list of break points for the whole program. =head2 codeline The codeline method returns the line of code that is just about to be executed: print "Code: " . $ebug->codeline . "\n"; =head2 codelines The codelines method returns lines of code. It can return all the code lines in the current file: my @codelines = $ebug->codelines(); It can return a span of code lines from the current file: my @codelines = $ebug->codelines(1, 3, 4, 5); It can return all the code lines in a file: my @codelines = $ebug->codelines("t/Calc.pm"); It can return a span of code lines in a file: my @codelines = $ebug->codelines("t/Calc.pm", 5, 6); =head2 eval The eval method evaluates Perl code in the current program and returns the result. If the evalutation results in an exception, C<$@> is returned. my $v = $ebug->eval('2 ** $exp'); In list context, eval also returns a flag indicating if the evalutation resulted in an exception. my( $v, $is_exception ) = $ebug->eval('die 123'); =head2 filename The filename method returns the filename of the currently running code: print "In filename: " . $ebug->filename . "\n"; =head2 filenames The filenames method returns a list of the filenames of all the files currently loaded: my @filenames = $ebug->filenames(); =head2 finished The finished method returns whether the program has finished running: print "Finished!\n" if $ebug->finished; =head2 line The line method returns the line number of the statement about to be executed: print "At line: " . $ebug->line . "\n"; =head2 next The next method steps onto the next line in the program. It executes any subroutine calls but does not step through them. $ebug->next; =head2 output The output method returns any content the program has output to either standard output or standard error: my($stdout, $stderr) = $ebug->output; =head2 package The package method returns the package of the currently running code: print "In package: " . $ebug->package . "\n"; =head2 pad my $pad = $ebug->pad; foreach my $k (sort keys %$pad) { my $v = $pad->{$k}; print "Variable: $k = $v\n"; } =head2 return The return subroutine returns from a subroutine. It continues running the subroutine, then single steps when the program flow has exited the subroutine: $ebug->return; It can also return your own values from a subroutine, for testing purposes: $ebug->return(3.141); =head2 run The run subroutine starts executing the code. It will only stop on a break point or watch point. $ebug->run; =head2 step The step method steps onto the next line in the program. It steps through into any subroutine calls. $ebug->step; =head2 subroutine The subroutine method returns the subroutine of the currently working code: print "In subroutine: " . $ebug->subroutine . "\n"; =head2 stack_trace The stack_trace method returns the current stack trace, using L. It returns a list of L methods: my @traces = $ebug->stack_trace; foreach my $trace (@traces) { print $trace->package, "->",$trace->subroutine, "(", $trace->filename, "#", $trace->line, ")\n"; } =head2 stack_trace_human The stack_trace_human method returns the current stack trace in a human-readable format: my @traces = $ebug->stack_trace_human; foreach my $trace (@traces) { print "$trace\n"; } =head2 undo The undo method undos the last action. It accomplishes this by restarting the process and passing (almost) all the previous commands to it. Note that commands which do not change state are ignored. Commands that change state are: break_point, break_point_delete, break_point_subroutine, eval, next, step, return, run and watch_point. $ebug->undo; It can also undo multiple commands: $ebug->undo(3); =head2 watch_point The watch point method sets a watch point. A watch point has a condition, and the debugger will stop run-ing as soon as this condition is true: $ebug->watch_point('$x > 100'); =head2 yaml The eval method evaluates Perl code in the current program and returns the result of YAML's Dump() method: my $y = $ebug->yaml('$z'); =head1 SEE ALSO L =head1 BUGS Devel::ebug does not quite work under 5.8.0. Devel::ebug does not handle signals under Windows. =head1 AUTHOR Latest releases by Brock Wilcox, C<< >> Leon Brocard, C<< >> =head1 COPYRIGHT Copyright (C) 2005-2008, Leon Brocard Copyright (C) 2011-NOW, Brock Wilcox =head1 LICENSE This module is free software; you can redistribute it or modify it under the same terms as Perl itself. Devel-ebug-0.56/Makefile.PL0000644000175000017500000000375312323642033015237 0ustar awwaiidawwaiid # This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.015. use strict; use warnings; use ExtUtils::MakeMaker 6.30; my %WriteMakefileArgs = ( "ABSTRACT" => "A simple, extensible Perl debugger", "AUTHOR" => "Brock Wilcox ", "BUILD_REQUIRES" => {}, "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => "6.30" }, "DISTNAME" => "Devel-ebug", "EXE_FILES" => [ "bin/ebug", "bin/ebug_client", "bin/ebug_backend_perl", "bin/ebug_server" ], "LICENSE" => "perl", "NAME" => "Devel::ebug", "PREREQ_PM" => { "Carp" => 0, "Class::Accessor::Chained::Fast" => 0, "Devel::StackTrace" => 0, "Exporter" => 0, "File::Spec" => 0, "FindBin" => 0, "Getopt::Long" => 0, "IO::Socket::INET" => 0, "Module::Pluggable" => 0, "PadWalker" => 0, "Proc::Background" => 0, "Scalar::Util" => 0, "String::Koremutake" => 0, "Term::ReadLine" => 0, "YAML" => 0, "base" => 0, "lib" => 0, "strict" => 0, "vars" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "Test::More" => 0 }, "VERSION" => "0.56", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "Class::Accessor::Chained::Fast" => 0, "Devel::StackTrace" => 0, "Exporter" => 0, "File::Spec" => 0, "FindBin" => 0, "Getopt::Long" => 0, "IO::Socket::INET" => 0, "Module::Pluggable" => 0, "PadWalker" => 0, "Proc::Background" => 0, "Scalar::Util" => 0, "String::Koremutake" => 0, "Term::ReadLine" => 0, "Test::More" => 0, "YAML" => 0, "base" => 0, "lib" => 0, "strict" => 0, "vars" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); Devel-ebug-0.56/bin/0000755000175000017500000000000012323642033014025 5ustar awwaiidawwaiidDevel-ebug-0.56/bin/ebug_backend_perl0000755000175000017500000000020112323642033017357 0ustar awwaiidawwaiid#!/usr/bin/env perl use strict; use warnings; use lib 'lib'; my $program = "@ARGV"; exec("$^X -Ilib -d:ebug::Backend $program"); Devel-ebug-0.56/bin/ebug_server0000755000175000017500000000324512323642033016267 0ustar awwaiidawwaiid#!/usr/bin/perl =head1 NAME ebug-server - Debugger server for remote debugging Perl script =head1 SYNOPSIS ebug-server [-keepio][-port port] -- script args... =head1 DESCRIPTION ebug-server is an debugger server for remote debugging Perl script, using ebug-client. When invoked, it will show you how to invoke ebug-client. =head1 EXAMPLE # Run hello.pl and wait for "ebug-client" to attach $ ebug-server -- hello.pl # Same as above, but keep I/O happen on server side $ ebug-server -keepio -- hello.pl =head1 NOTE You can't specify secret key - it must be generated automatically. Also, you can't specify port below 3141. Since Devel::ebug::Backend listens to "localhost" socket, you will need to relay I/O using tool like socat for true remote debugging. =head1 SEE ALSO L, L, L =head1 AUTHOR Taisuke Yamada, =cut use String::Koremutake; use Getopt::Long; use strict; use warnings; GetOptions( my $OPT = {}, 'help', 'port=i', 'keepio' ) || help(); help() if $OPT->{help} || !@ARGV; help() if $OPT->{port} && $OPT->{port} < 3141; my $cmd = "$^X -d:ebug::Backend @ARGV"; my $gen = String::Koremutake->new; my $rand = $OPT->{port} ? $OPT->{port} - 3141 : int( rand(100_000) ); my $key = $gen->integer_to_koremutake($rand); my $port = 3141 + ( $rand % 1024 ); $ENV{PERL_DEBUG_DONT_RELAY_IO} = 1 if $OPT->{keepio}; $ENV{SECRET} = $key; print STDERR <] -- debuggee args... Note: - Listening port must be >= 3141 EOF exit(1); } Devel-ebug-0.56/bin/ebug_client0000755000175000017500000000336612323642033016243 0ustar awwaiidawwaiid#!/usr/bin/perl =head1 NAME ebug-client - Debugger client for remote debugging Perl script =head1 SYNOPSIS ebug-client -key -port =head1 DESCRIPTION ebug-client is an debugger front end for attaching to remotely executing perl script, running on ebug-server. To invoke ebug-client, you must first invoke ebug-server to run debuggee and generate "key" and "port" needed for connection. When ebug-server is invoked, it will show exact command-line to invoke ebug-client. =head1 EXAMPLE # Attach to ebug-server running on port 4023, with key "begripra" $ ebug-client -key begripra -port 4023 =head1 NOTE Currently, you cannot "restart" debuggee. You'll need to restart one manually by re-invoking both ebug-server and ebug-client. Since Devel::ebug::Backend listens to "localhost" socket, you will need to relay I/O using tool like socat for true remote debugging. Internally, thanks for it being free software, it is almost a complete ripoff of Devel::ebug source. =head1 SEE ALSO L, L, L =head1 AUTHOR Taisuke Yamada, =cut package Devel::ebug; use Devel::ebug; use IO::Socket::INET; use strict; use warnings; our $VERSION = $Devel::ebug::VERSION; our $ARG = {}; # Replace 'load' with one that just attaches sub load { my $self = shift; $self->attach($ARG->{port}, $ARG->{key}); } package main; use Devel::ebug::Console; use Getopt::Long; use strict; use warnings; GetOptions( my $OPT = {}, 'help', 'port=i', 'key=s' ) || help(); help() if $OPT->{help}; $Devel::ebug::ARG = $OPT; my $console = Devel::ebug::Console->new(); $console->run(); exit(0); sub help { print STDERR < -port -- debuggee args... EOF exit(1); } Devel-ebug-0.56/bin/ebug0000755000175000017500000000141212323642033014673 0ustar awwaiidawwaiid#!/usr/bin/env perl use strict; use warnings; use lib 'lib'; use Devel::ebug::Console; my $backend; if ($ARGV[0] eq '--backend') { $backend = $ARGV[1]; shift(@ARGV); shift(@ARGV); } my $console = Devel::ebug::Console->new(); $console->run($backend); __END__ =head1 NAME ebug - A simple, extensible console Perl debugger =head1 SYNOPSIS % ebug calc.pl % ebug "add.pl 3 4" =head1 DESCRIPTION ebug is an interactive commmand-line front end to L. It is a simple Perl debugger, much like perl5db.pl. =head1 SEE ALSO L =head1 AUTHOR Leon Brocard, C<< >> =head1 COPYRIGHT Copyright (C) 2005, Leon Brocard This program is free software; you can redistribute it or modify it under the same terms as Perl itself. Devel-ebug-0.56/dist.ini0000644000175000017500000000075612323642033014731 0ustar awwaiidawwaiidname = Devel-ebug author = Brock Wilcox license = Perl_5 copyright_holder = Brock Wilcox copyright_year = 2014 [@Filter] -bundle = @Basic -remove = Readme -remove = GatherDir [Git::NextVersion] [PkgVersion] [AutoPrereqs] [ContributorsFromGit] [ReadmeFromPod] [CPANFile] [GatherDir] exclude_match = Makefile.PL|cpanfile|META.json|README [CopyFilesFromBuild] copy = Makefile.PL copy = cpanfile copy = META.json copy = README Devel-ebug-0.56/cpanfile0000644000175000017500000000135212323642033014762 0ustar awwaiidawwaiidrequires "Carp" => "0"; requires "Class::Accessor::Chained::Fast" => "0"; requires "Devel::StackTrace" => "0"; requires "Exporter" => "0"; requires "File::Spec" => "0"; requires "FindBin" => "0"; requires "Getopt::Long" => "0"; requires "IO::Socket::INET" => "0"; requires "Module::Pluggable" => "0"; requires "PadWalker" => "0"; requires "Proc::Background" => "0"; requires "Scalar::Util" => "0"; requires "String::Koremutake" => "0"; requires "Term::ReadLine" => "0"; requires "YAML" => "0"; requires "base" => "0"; requires "lib" => "0"; requires "strict" => "0"; requires "vars" => "0"; requires "warnings" => "0"; on 'test' => sub { requires "Test::More" => "0"; }; on 'configure' => sub { requires "ExtUtils::MakeMaker" => "6.30"; }; Devel-ebug-0.56/MANIFEST0000644000175000017500000000257712323642033014421 0ustar awwaiidawwaiid# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.015. CHANGES LICENSE MANIFEST META.yml Makefile.PL README TODO bin/ebug bin/ebug_backend_perl bin/ebug_client bin/ebug_server cpanfile dist.ini lib/Devel/ebug.pm lib/Devel/ebug/Backend.pm lib/Devel/ebug/Backend/Plugin/ActionPoints.pm lib/Devel/ebug/Backend/Plugin/Basic.pm lib/Devel/ebug/Backend/Plugin/Codelines.pm lib/Devel/ebug/Backend/Plugin/Commands.pm lib/Devel/ebug/Backend/Plugin/Eval.pm lib/Devel/ebug/Backend/Plugin/Filenames.pm lib/Devel/ebug/Backend/Plugin/Output.pm lib/Devel/ebug/Backend/Plugin/Pad.pm lib/Devel/ebug/Backend/Plugin/Ping.pm lib/Devel/ebug/Backend/Plugin/Run.pm lib/Devel/ebug/Backend/Plugin/StackTrace.pm lib/Devel/ebug/Console.pm lib/Devel/ebug/Plugin/ActionPoints.pm lib/Devel/ebug/Plugin/Basic.pm lib/Devel/ebug/Plugin/Codelines.pm lib/Devel/ebug/Plugin/Eval.pm lib/Devel/ebug/Plugin/Filenames.pm lib/Devel/ebug/Plugin/Output.pm lib/Devel/ebug/Plugin/Pad.pm lib/Devel/ebug/Plugin/Run.pm lib/Devel/ebug/Plugin/StackTrace.pm t/Calc.pm t/basic.t t/breakOnLoad.t t/break_point.t t/calc.pl t/calc_oo.pl t/calc_subref.pl t/carp.pl t/codelines.t t/ebug.t t/eval.t t/filenames.t t/finished.t t/koremutake.pl t/koremutake.t t/load_calc.pl t/oo.t t/output.t t/pad.t t/pod.pl t/pod.t t/return.t t/run.t t/signal.pl t/signal.t t/stack.pl t/stack.t t/subrefs.t t/subroutine.t t/undo.t t/watch_point.t t/yaml.pl Devel-ebug-0.56/META.yml0000644000175000017500000000161512323642033014531 0ustar awwaiidawwaiid--- abstract: 'A simple, extensible Perl debugger' author: - 'Brock Wilcox ' build_requires: Test::More: 0 configure_requires: ExtUtils::MakeMaker: 6.30 dynamic_config: 0 generated_by: 'Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Devel-ebug requires: Carp: 0 Class::Accessor::Chained::Fast: 0 Devel::StackTrace: 0 Exporter: 0 File::Spec: 0 FindBin: 0 Getopt::Long: 0 IO::Socket::INET: 0 Module::Pluggable: 0 PadWalker: 0 Proc::Background: 0 Scalar::Util: 0 String::Koremutake: 0 Term::ReadLine: 0 YAML: 0 base: 0 lib: 0 strict: 0 vars: 0 warnings: 0 version: 0.56 x_contributors: - 'Hobbestigrou ' - 'Paweł Murias ' - 'jchassler ' Devel-ebug-0.56/CHANGES0000644000175000017500000002452012323642033014253 0ustar awwaiidawwaiidRevision history for Perl module Devel::ebug 0.56 2014.04.16 - Converted to Dist::Zilla - Minor fixes (thanks hobbestigrou!) 0.55 2013.03.19 - Extra version to add missing files :) 0.54 2013.03.19 - Add 'break on file loading' feature (thanks jchassler!) - Fix commands starting with ^h 0.53 2012.02.29 - Add tests for codeline tracking and subrefs - Fix YAML vs YAML::Syck (dunno) - Had to disable return-value-override feature - Fix tests to work with new Carp - Use findbin to load backend - Improve argument param handling 0.52 2011.11.08 - Oops, forgot to update CHANGES for 0.51 :) - Slight refactor of backend executable by pmurias (thanks!) - Extract backend connection code into separate method - Shuffle executables into bin/ - Fix wantarray test for older perls - Fix some windows path usage 0.50 Thu Oct 20 20:15:05 EDT 2011 - Fix failing tests - Add YAML build dependency 0.49 Thu Oct 16 20:07:34 BST 2008 - Add a human-readable license to the documentation 0.48 Mon Apr 30 20:37:06 CEST 2007 - Added ebug-server(1), a remote debugger server - Added ebug-client(1), a remote debugger client - Fixed [?h] input handling so Perl expression with 'h' or '?' won't wrongly invoke help - Added check for PERL_DEBUG_DONT_RELAY_IO environment variable to keep STDOUT/STDERR on server side, instead of relaying to debugger frontend - Switched YAML.pm to YAML::Syck for performance reasons - All patches by Taisuke Yamada 0.47 Mon Mar 19 19:43:35 GMT 2007 - add break_points_with_condition and all_break_points_with_condition, make break_point and break_point_subroutine return a line number, make break_points optionally take a filename, make eval return whether there was an exception (patch by Mattia Barbon) 0.46 Mon Mar 6 20:52:22 GMT 2006 - workaround for bless globs (thanks to SAMV) 0.45 Fri Sep 2 15:01:42 BST 2005 - moved subroutine into basic information - moved ebug_http into its own distribution (patch by Jesse Vincent) 0.44 Wed Aug 31 16:36:03 BST 2005 - require PPI 1.003 (and work with new API) - update ebug_http to new Catalyst (removes warning) - fix bug with "run" stopping after returning back to main:: - new run.t 0.43 Mon May 16 18:55:37 BST 2005 - document that we don't quite work under 5.8.0 (thanks Simon) - Devel::ebug does not handle signals under Windows atm, so skip the tests for now (spotted by LTjake) - updated to Prototype 1.2.0 - try and find our templates a little harder - you can set set break points in ebug_http by clicking on a line number (and delete them by clickling on the little stop sign icon) - you can now evaluate Perl expressions in the web interface - major attempt to make the web interface prettier (icons!) - make some attempt at caching static files - interactive evaluation is now the default in ebug(1) (patch by Jesse Vincent) - ebug(1) now ships with an interactive console mode (patch by Jesse Vincent) 0.42 Thu Apr 28 17:42:00 BST 2005 - fix ebug_http error message - fix bug in ebug_http where the pretty printing was getting confused if the debugged program had inline POD (spotted by sri) - HTML tooltips are now in monospace, have a sensible "Not defined" error message, and show lists or hashes depending on the type. Scalars no longer have a --- prefix - fixed a bug with a missing 'Devel::ebug::Build' (spotted by obra) - use Catalyst 5.10 and its new template bundling (completely obsoleting the above change) - removed obsolete "examine" code from Devel::ebug::HTTP and template 0.41 Tue Apr 19 21:04:18 BST 2005 - remove "work around" as it is fixed in Catalyst 5.03 - fix small HTML bug (spotted by LTjake) - new xmlns + language declarations (thanks to LTjake) - minor tweak to generate valid HTML 0.40 Tue Apr 19 17:13:44 BST 2005 - whoops, we were depending on Catalyst 4 to still be around - "work around" Catalyst bug with external hostnames - updated prereqs - update docs for ebug_http 0.39 Tue Apr 19 13:16:51 BST 2005 - major refactoring of ebug_http to now use Catalyst 5.0 - we now capture STDOUT, STDERR - their contents are available using the new output method - ebug now shows STDOUT, STDERR - ebug_http now shows STDOUT, STDERR - no longer stop processing as the program exits - tab completion of variables in ebug (x $var), as suggested by Autrijus - in ebug_http, new dynamic tooltips to show the value of variables on the current line, using prototype and overlib - "return" not in a subroutine is now the same as "run" instead of giving an error (spotted by clkao) - documented that ebug and ebug_http can run programs with arguments by quoting them (spotted by clkao) - minor output patch for ebug.t - tweaked the test to skip Test::Expect under Windows - new yaml method to return the YAML representation of a variable - improved undo tests - better use of PPI (spotted by Alias) - install the templates / JavaScript / CSS / images to sitelib 0.38 Tue Apr 12 14:47:24 BST 2005 - optimisation: only scan for plugins on start of backend - be sure to use strict and warnings in the plugins - in ebug and ebug_http, allow examining a variable using YAML 0.37 Tue Apr 5 22:55:18 CST 2005 - moved ebug code into Devel::ebug::Console - moved the backend into Devel::ebug::Backend - major refactoring of Devel::ebug::Backend: move everything to subroutines, pass the context around - major refactoring to place functionality in plugins (patch by Simon Wistow) - fix a problem with code references (spotted by nadim) - we now use YAML instead of Storable - make stack_trace_human deal with undef strings, list refs, hash refs, and objects in arguments - new pad_human method for a human-readable pad view - in ebug_http, allow you to set simple break points and run - be sure to produce valid XHTML - added support for invoking the debugger by sending a signal (requested by Sam Vilain) 0.36 Sun Apr 3 20:56:56 CST 2005 - total rearrange of Devel::ebug::HTTP and increase in documentation (thanks to Mark Fowler) - create valid XML no matter what the variables or code contains (thanks to Mark Fowler) - correct the =head1 NAME of ebug and ebug_http (spotted by Smylers) - stack_trace_human is now more robust - Test::Expect doesn't work under Windows, so don't require or use it in Windows environments - this means we now require Module::Build (spotted by Johan Lindstrom) - make codelines() remove DOS as well as UNIX newlines (spotted by Johan Lindstrom) - in ebug, l 40 will to set the number of lines to list (patch by Johan Lindstrom) 0.35 Sat Apr 2 23:34:56 CST 2005 - added undo method which undos the last action - in ebug_http, using the back button in the browser actually steps backwards in the program (suggested by autrijus) - in ebug_http, use monikers for blessed objects and make the stack trace use a smaller font - in ebug, restart the program instead of exiting at the end of the program (suggested by obra) - in ebug_http, restart the program instead of stopping the webserver at the end of the program - added stack_trace_human method for a human-readable stack trace - pointed out ebug and ebug_http in the docs 0.34 Sat Apr 2 15:39:25 CST 2005 - give ebug_http a hashbang line (spotted by obra, who complains all the time ;-) - make Devel::ebug::HTTP return full HTTP requests - basic docs for ebug and ebug_http - ebug_http now opens the browser for you under Mac OS X and Windows (patch by Johan Lindstrom) - ebug now has the ability to always list the lines around the IP - L toggles (patch by Johan Lindstrom) - fix a problem where we were displaying the wrong codelines in modules with POD - now use the environment instead of the command line to pass the secret for portability (patch by Johan Lindstrom) - in ebug_http, we now jump to the current line (patch by Johan Lindstrom) - in ebug_http, make our actions POSTs, for they change state - in ebug_http, cache the call to PPI::HTML - in ebug_http, link module names to search.cpan.org - in ebug_http, syntax highlight single and double-quoted strings - tweak Devel::ebug's introductory docs - added break_point_delete method which deletes a break point - added stack_trace method which provides basic stack trace information using Devel::StackTrace - in ebug_http, added a slightly ugly stack trace - added return(@values) method to return your own values from a subroutine, instead of what the subroutine would have returned 0.33 Fri Apr 1 16:40:43 CST 2005 - update the manifest, doh (it's been a long week) 0.32 Fri Apr 1 14:09:00 CST 2005 - added "ebug_http" to script_files so that it will get installed 0.31 Fri Apr 1 13:36:00 CST 2005 - added return(), which returns from a subroutine - fix bug with 'l' showing inaccurate lines in ebug - added filenames() method which returns a list of the filenames of all the files currently loaded - added a String::Koremutake test - added a new finished() method to return whether the program has finished running (spotted by clkao) - added ebug_http, which presents a web interface to debugging 0.30 Thu Mar 31 00:13:13 CST 2005 - autrijus noticed that 0.29 shipped with a broken ebug. to keep me from embarassing myself in future, there is now an ebug.t which uses the newly-released Test::Expect - codelines() now returns an array - codelines() now returns the whole file if no line numbers are passed - codelines() can now return the source code of files other than the currently executing program - added some security to the TCP connection (port, secret) - added a new "y" to ebug, which YAML::Dump's variables - minor code cleanups 0.29 Tue Mar 29 21:02:59 CST 2005 - initial release Devel-ebug-0.56/LICENSE0000644000175000017500000004365312323642033014275 0ustar awwaiidawwaiidThis software is copyright (c) 2014 by Brock Wilcox. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2014 by Brock Wilcox. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2014 by Brock Wilcox. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End Devel-ebug-0.56/README0000644000175000017500000002720012323642033014136 0ustar awwaiidawwaiidNAME Devel::ebug - A simple, extensible Perl debugger SYNOPSIS use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("calc.pl"); $ebug->load; print "At line: " . $ebug->line . "\n"; print "In subroutine: " . $ebug->subroutine . "\n"; print "In package: " . $ebug->package . "\n"; print "In filename: " . $ebug->filename . "\n"; print "Code: " . $ebug->codeline . "\n"; $ebug->step; $ebug->step; $ebug->next; my($stdout, $stderr) = $ebug->output; my $actual_line = $ebug->break_point(6); $ebug->break_point(6, '$e == 4'); $ebug->break_point("t/Calc.pm", 29); $ebug->break_point("t/Calc.pm", 29, '$i == 2'); $ebug->break_on_load("t/Calc.pm"); my $actual_line = $ebug->break_point_subroutine("main::add"); $ebug->break_point_delete(29); $ebug->break_point_delete("t/Calc.pm", 29); my @filenames = $ebug->filenames(); my @break_points = $ebug->break_points(); my @break_points = $ebug->break_points("t/Calc.pm"); my @break_points = $ebug->break_points_with_condition(); my @break_points = $ebug->break_points_with_condition("t/Calc.pm"); my @break_points = $ebug->all_break_points_with_condition(); $ebug->watch_point('$x > 100'); my $codelines = $ebug->codelines(@span); $ebug->run; my $pad = $ebug->pad; foreach my $k (sort keys %$pad) { my $v = $pad->{$k}; print "Variable: $k = $v\n"; } my $v = $ebug->eval('2 ** $exp'); my( $v, $is_exception ) = $ebug->eval('die 123'); my $y = $ebug->yaml('$z'); my @frames = $ebug->stack_trace; my @frames2 = $ebug->stack_trace_human; $ebug->undo; $ebug->return; print "Finished!\n" if $ebug->finished; DESCRIPTION A debugger is a computer program that is used to debug other programs. Devel::ebug is a simple, extensible Perl debugger with a clean API. Using this module, you may easily write a Perl debugger to debug your programs. Alternatively, it comes with an interactive debugger, ebug. perl5db.pl, Perl's current debugger is currently 2,600 lines of magic and special cases. The code is nearly unreadable: fixing bugs and adding new features is fraught with difficulties. The debugger has no test suite which has caused breakage with changes that couldn't be properly tested. It will also not debug regexes. Devel::ebug is aimed at fixing these problems and delivering a replacement debugger which provides a well-tested simple programmatic interface to debugging programs. This makes it easier to build debuggers on top of Devel::ebug, be they console-, curses-, GUI- or Ajax-based. There are currently two user interfaces to Devel::debug, ebug and ebug_http. ebug is a console-based interface to debugging programs, much like perl5db.pl. ebug_http is an innovative web-based interface to debugging programs. Note that if you're debugging a program, you can invoke the debugger in the program itself by using the INT signal: kill 2, $$ if $square > 100; Devel::ebug is a work in progress. Internally, Devel::ebug consists of two parts. The frontend is Devel::ebug, which you interact with. The frontend starts the code you are debugging in the background under the backend (running it under perl -d:ebug code.pl). The backend starts a TCP server, which the frontend then connects to, and uses this to drive the backend. This adds some flexibilty in the debugger. There is some minor security in the client/server startup (a secret word), and a random port is used from 3141-4165 so that multiple debugging sessions can happen concurrently. CONSTRUCTOR new The constructor creats a Devel::ebug object: my $ebug = Devel::ebug->new; program The program method selects which program to load: $ebug->program("calc.pl"); load The load method loads the program and gets ready to debug it: $ebug->load; METHODS break_point The break_point method sets a break point in a program. If you are run-ing through a program, the execution will stop at a break point. Break points can be set in a few ways. A break point can be set at a line number in the current file: my $actual_line = $ebug->break_point(6); A break point can be set at a line number in the current file with a condition that must be true for execution to stop at the break point: my $actual_line = $ebug->break_point(6, '$e = 4'); A break point can be set at a line number in a file: my $actual_line = $ebug->break_point("t/Calc.pm", 29); A break point can be set at a line number in a file with a condition that must be true for execution to stop at the break point: my $actual_line = $ebug->break_point("t/Calc.pm", 29, '$i == 2'); Breakpoints can not be set on some lines (for example comments); in this case a breakpoint will be set at the next breakable line, and the line number will be returned. If no such line exists, no breakpoint is set and the function returns "undef". break_on_load Set a breakpoint on file loading, the file name can be relative or absolute. break_point_delete The break_point_delete method deletes an existing break point. A break point at a line number in the current file can be deleted: $ebug->break_point_delete(29); A break point at a line number in a file can be deleted: $ebug->break_point_delete("t/Calc.pm", 29); break_point_subroutine The break_point_subroutine method sets a break point in a program right at the beginning of the subroutine. The subroutine is specified with the full package name: my $line = $ebug->break_point_subroutine("main::add"); $ebug->break_point_subroutine("Calc::fib"); The return value is the line at which the break point is set. break_points The break_points method returns a list of all the line numbers in a given file that have a break point set. Return the list of breakpoints in the current file: my @break_points = $ebug->break_points(); Return the list of breakpoints in a given file: my @break_points = $ebug->break_points("t/Calc.pm"); break_points_with_condition The break_points method returns a list of break points for a given file. Return the list of breakpoints in the current file: my @break_points = $ebug->break_points_with_condition(); Return the list of breakpoints in a given file: my @break_points = $ebug->break_points_with_condition("t/Calc.pm"); Each element of the list has the form { filename => "t/Calc.pm", line => 29, condition => "$foo > 12", } where "condition" might not be present. all_break_points_with_condition Like "break_points_with_condition" but returns a list of break points for the whole program. codeline The codeline method returns the line of code that is just about to be executed: print "Code: " . $ebug->codeline . "\n"; codelines The codelines method returns lines of code. It can return all the code lines in the current file: my @codelines = $ebug->codelines(); It can return a span of code lines from the current file: my @codelines = $ebug->codelines(1, 3, 4, 5); It can return all the code lines in a file: my @codelines = $ebug->codelines("t/Calc.pm"); It can return a span of code lines in a file: my @codelines = $ebug->codelines("t/Calc.pm", 5, 6); eval The eval method evaluates Perl code in the current program and returns the result. If the evalutation results in an exception, $@ is returned. my $v = $ebug->eval('2 ** $exp'); In list context, eval also returns a flag indicating if the evalutation resulted in an exception. my( $v, $is_exception ) = $ebug->eval('die 123'); filename The filename method returns the filename of the currently running code: print "In filename: " . $ebug->filename . "\n"; filenames The filenames method returns a list of the filenames of all the files currently loaded: my @filenames = $ebug->filenames(); finished The finished method returns whether the program has finished running: print "Finished!\n" if $ebug->finished; line The line method returns the line number of the statement about to be executed: print "At line: " . $ebug->line . "\n"; next The next method steps onto the next line in the program. It executes any subroutine calls but does not step through them. $ebug->next; output The output method returns any content the program has output to either standard output or standard error: my($stdout, $stderr) = $ebug->output; package The package method returns the package of the currently running code: print "In package: " . $ebug->package . "\n"; pad my $pad = $ebug->pad; foreach my $k (sort keys %$pad) { my $v = $pad->{$k}; print "Variable: $k = $v\n"; } return The return subroutine returns from a subroutine. It continues running the subroutine, then single steps when the program flow has exited the subroutine: $ebug->return; It can also return your own values from a subroutine, for testing purposes: $ebug->return(3.141); run The run subroutine starts executing the code. It will only stop on a break point or watch point. $ebug->run; step The step method steps onto the next line in the program. It steps through into any subroutine calls. $ebug->step; subroutine The subroutine method returns the subroutine of the currently working code: print "In subroutine: " . $ebug->subroutine . "\n"; stack_trace The stack_trace method returns the current stack trace, using Devel::StackTrace. It returns a list of Devel::StackTraceFrame methods: my @traces = $ebug->stack_trace; foreach my $trace (@traces) { print $trace->package, "->",$trace->subroutine, "(", $trace->filename, "#", $trace->line, ")\n"; } stack_trace_human The stack_trace_human method returns the current stack trace in a human-readable format: my @traces = $ebug->stack_trace_human; foreach my $trace (@traces) { print "$trace\n"; } undo The undo method undos the last action. It accomplishes this by restarting the process and passing (almost) all the previous commands to it. Note that commands which do not change state are ignored. Commands that change state are: break_point, break_point_delete, break_point_subroutine, eval, next, step, return, run and watch_point. $ebug->undo; It can also undo multiple commands: $ebug->undo(3); watch_point The watch point method sets a watch point. A watch point has a condition, and the debugger will stop run-ing as soon as this condition is true: $ebug->watch_point('$x > 100'); yaml The eval method evaluates Perl code in the current program and returns the result of YAML's Dump() method: my $y = $ebug->yaml('$z'); SEE ALSO perldebguts BUGS Devel::ebug does not quite work under 5.8.0. Devel::ebug does not handle signals under Windows. AUTHOR Latest releases by Brock Wilcox, "" Leon Brocard, "" COPYRIGHT Copyright (C) 2005-2008, Leon Brocard Copyright (C) 2011-NOW, Brock Wilcox LICENSE This module is free software; you can redistribute it or modify it under the same terms as Perl itself. Devel-ebug-0.56/t/0000755000175000017500000000000012323642033013520 5ustar awwaiidawwaiidDevel-ebug-0.56/t/calc_subref.pl0000644000175000017500000000033512323642033016326 0ustar awwaiidawwaiid#!perl my $add = sub { my($z, $x) = @_; my $c = $z + $x; return $c; }; my $q = 1; my $w = 2; my $e = $add->($q, $w); $e++; $e++; print "$e\n"; # unbreakable line my $breakable_line = 1; # other unbreakable line Devel-ebug-0.56/t/watch_point.t0000644000175000017500000000136012323642033016224 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 8; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; # just one watch point $ebug->watch_point('$e == 4'); $ebug->run; is($ebug->line, 7); is($ebug->pad->{'$e'}, 4); $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; # multiple watch points - they disappear $ebug->watch_point('$e == 4'); $ebug->watch_point('$w > 0'); $ebug->watch_point('defined $c'); $ebug->run; is($ebug->line, 5); is($ebug->pad->{'$w'}, 2); $ebug->run; is($ebug->line, 14); is($ebug->pad->{'$c'}, 3); $ebug->run; is($ebug->line, 7); is($ebug->pad->{'$e'}, 4); Devel-ebug-0.56/t/break_point.t0000644000175000017500000000506312323642033016206 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 27; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; # set break points at line numbers is( $ebug->break_point(6), 6 ); is( $ebug->break_point(12), 12 ); $ebug->break_point(9); is( $ebug->break_point(17), 18 ); # break on next breakable line is( $ebug->break_point(19), undef ); # no more breakable lines is_deeply([$ebug->break_points], [6, 9, 12, 18]); $ebug->run; is($ebug->line, 12); $ebug->run; is($ebug->line, 6); $ebug->run; is($ebug->line, 9); is($ebug->pad->{'$e'}, 5); $ebug->step; # set break point at add() $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; is( $ebug->break_point_subroutine("main::add"), 12 ); $ebug->run; is($ebug->line, 12); # set break point at fib2() $ebug = Devel::ebug->new; $ebug->program("t/calc_oo.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point("t/Calc.pm", 29); is_deeply([$ebug->break_points], []); is_deeply([$ebug->break_points("t/Calc.pm")], [29]); $ebug->run; is($ebug->line, 29); is($ebug->eval('$i'), 1); # set break point at add() $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point(6, '$e == 4'); $ebug->break_point(7, '$e == 4'); $ebug->run; is($ebug->line, 7); is($ebug->eval('$e'), 4); # set break point at fib2() $ebug = Devel::ebug->new; $ebug->program("t/calc_oo.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point("t/Calc.pm", 29, '$i == 2'); is_deeply([$ebug->break_points_with_condition], []); $ebug->break_point(11); is_deeply([$ebug->break_points_with_condition("t/Calc.pm")], [{filename => "t/Calc.pm", line => 29, condition => '$i == 2'}]); is_deeply([$ebug->all_break_points_with_condition], [{filename => "t/Calc.pm", line => 29, condition => '$i == 2'}, {filename => "t/calc_oo.pl", line => 11}, ]); $ebug->run; is($ebug->line, 29); is($ebug->eval('$i'), 2); is($ebug->eval('$x1'), 1); is($ebug->eval('$x2'), 2); # set break points at line numbers and delete one $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point(6); $ebug->break_point(12); $ebug->break_point(9); $ebug->break_point_delete(6); $ebug->break_point_delete("t/calc.pl", 12); is_deeply([$ebug->break_points], [9]); $ebug->run; is($ebug->line, 9); is($ebug->pad->{'$e'}, 5); $ebug->step; Devel-ebug-0.56/t/koremutake.pl0000644000175000017500000000026512323642033016227 0ustar awwaiidawwaiiduse String::Koremutake; my $k = String::Koremutake->new; my $s = $k->integer_to_koremutake(65535); # botretre my $i = $k->koremutake_to_integer('koremutake'); # 10610353957 Devel-ebug-0.56/t/breakOnLoad.t0000644000175000017500000000122112323642033016062 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 5; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/load_calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_on_load("t/Calc.pm"); $ebug->run; is($ebug->line, 6); is($ebug->filename, "t/Calc.pm"); $ebug->run; is($ebug->finished, 1); #now same test only the filename without path $ebug = Devel::ebug->new; $ebug->program("t/load_calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_on_load("Calc.pm"); #just provide fileName without path $ebug->run; is($ebug->line, 6); is($ebug->filename, "t/Calc.pm"); Devel-ebug-0.56/t/load_calc.pl0000644000175000017500000000017012323642033015754 0ustar awwaiidawwaiid#!perl my $q = 1; my $w = 2; use lib "t"; eval "use Calc"; print "after Calc.pm is loaded"; eval "Calc::add(1,2)"; Devel-ebug-0.56/t/koremutake.t0000644000175000017500000000116412323642033016056 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 3; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/koremutake.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->run; $ebug = Devel::ebug->new; $ebug->program("t/koremutake.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; my $filename = (grep { $_ =~ /Koremutake/ } $ebug->filenames)[0]; ok($filename); $ebug->break_point_subroutine("String::Koremutake::integer_to_koremutake"); $ebug->run; is($ebug->subroutine, "String::Koremutake::integer_to_koremutake"); is($ebug->filename, $filename); $ebug->run; Devel-ebug-0.56/t/subroutine.t0000644000175000017500000000105212323642033016102 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 9; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; # Let's step through the program, and check that we get the # correct subroutine for each line foreach (1..9) { my $line = $ebug->line; my $sub = $ebug->subroutine; my $want_sub = 'main'; # sub add { ... } is lines 11 to 15 if ($line > 11 && $line < 15) { $want_sub = 'main::add'; } is($sub, $want_sub); $ebug->step; } Devel-ebug-0.56/t/filenames.t0000644000175000017500000000051312323642033015647 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 2; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc_oo.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; my %filenames; $filenames{$_}++ foreach $ebug->filenames; ok($filenames{'t/calc_oo.pl'}); ok($filenames{'t/Calc.pm'}); Devel-ebug-0.56/t/codelines.t0000644000175000017500000000353512323642033015660 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 20; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; # Let's get some lines of code SKIP: { my @codelines = $ebug->codelines(); skip "Don't try lining up codelines because of sitecustomize", 20 if $codelines[0] =~ /sitecustomize/; my @calc = ( '#!perl', '', 'my $q = 1;', 'my $w = 2;', 'my $e = add($q, $w);', '$e++;', '$e++;', '', 'print "$e\\n";', '', 'sub add {', ' my($z, $x) = @_;', ' my $c = $z + $x;', ' return $c;', '}', '', '# unbreakable line', 'my $breakable_line = 1;', '# other unbreakable line', ); is_deeply(\@codelines, \@calc); @codelines = $ebug->codelines(1, 3, 4, 5); is_deeply(\@codelines, [ '#!perl', 'my $q = 1;', 'my $w = 2;', 'my $e = add($q, $w);', ]); # Let's step through the program, and check that codeline is correct my @lines = (3, 4, 5, 12, 13, 14, 6, 7, 9); foreach my $l (@lines) { is($ebug->codeline, $calc[$l-1]); $ebug->step; } $ebug = Devel::ebug->new; $ebug->program("t/calc_oo.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; @codelines = $ebug->codelines("t/calc_oo.pl", 7, 8); is_deeply(\@codelines, [ 'my $calc = Calc->new;', 'my $r = $calc->add(5, 10); # 15', ]); @codelines = $ebug->codelines("t/Calc.pm", 5, 6); is_deeply(\@codelines, [ 'use base qw(Class::Accessor::Chained::Fast);', 'our $VERSION = "0.29";', ]); @codelines = $ebug->codelines("t/Calc.pm"); is(scalar(@codelines), 34); $ebug->program("t/pod.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; @codelines = $ebug->codelines(); is($codelines[0], '#!perl'); is($codelines[8], 'print "Result is $zz!\n";'); is($codelines[9], ''); is($codelines[10], ''); is($codelines[11], ''); is($codelines[31], 'sub add {'); } Devel-ebug-0.56/t/calc_oo.pl0000644000175000017500000000031312323642033015451 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib "t"; use Calc; my $calc = Calc->new; my $r = $calc->add(5, 10); # 15 my $f = $calc->fib1($r); # 987 my $f2 = $calc->fib2($r); # 987 my $f3 = 1; # breakable line Devel-ebug-0.56/t/finished.t0000644000175000017500000000076612323642033015507 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 10; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/yaml.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; is($ebug->finished, 0); is($ebug->line, 3); is($ebug->subroutine, "main"); $ebug->next; is($ebug->finished, 0); is($ebug->line, 4); is($ebug->subroutine, "main"); $ebug->next; is($ebug->finished, 0); is($ebug->line, 5); is($ebug->subroutine, "main"); $ebug->next; is($ebug->finished, 1); Devel-ebug-0.56/t/signal.pl0000644000175000017500000000021012323642033015323 0ustar awwaiidawwaiid#!perl use strict; use warnings; foreach my $i (1..50) { my $square = $i * $i; kill 2, $$ if $square > 100; print "$square\n"; } Devel-ebug-0.56/t/subrefs.t0000644000175000017500000000477312323642033015371 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 30; use Devel::ebug; note "First we'll step over the subref"; my $ebug = Devel::ebug->new; $ebug->program("t/calc_subref.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; # Let's step through the program, and check that we step through the # lines in the right order is($ebug->line, 7, "Next line is 7"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->next; is($ebug->line, 9, "Next line is 9"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->next; is($ebug->line, 10, "Next line is 10"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->next; is($ebug->line, 11, "Next line is 11"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->next; is($ebug->line, 12, "Next line is 12"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->next; is($ebug->line, 13, "Next line is 13"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->next; is($ebug->line, 15, "Next line is 15"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->next; note "Now testing stepping into the subref"; $ebug = Devel::ebug->new; $ebug->program("t/calc_subref.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; is($ebug->line, 7, "Next line is 7"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->step; is($ebug->line, 9, "Next line is 9"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->step; is($ebug->line, 10, "Next line is 10"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->step; is($ebug->line, 11, "Next line is 11"); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); $ebug->step; is($ebug->line, 4, 'Inside of subref'); is($ebug->package, 'main', 'Still package main'); is($ebug->subroutine, 'main::__ANON__[t/calc_subref.pl:7]', 'ANON subref'); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); note "Try a breakpoint in the subref"; $ebug = Devel::ebug->new; $ebug->program("t/calc_subref.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point("t/calc_subref.pl", 4); $ebug->run; is($ebug->line, 4, 'Inside of subref'); is($ebug->package, 'main', 'Still package main'); is($ebug->subroutine, 'main::__ANON__[t/calc_subref.pl:7]', 'ANON subref'); is($ebug->filename, 't/calc_subref.pl', 'Still in t/calc_subref.pl'); Devel-ebug-0.56/t/output.t0000644000175000017500000000422212323642033015245 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 28; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/carp.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; is($ebug->line, 6); my($stdout, $stderr) = $ebug->output; is($stdout, ""); is($stderr, ""); $ebug->step; is($ebug->line, 7); ($stdout, $stderr) = $ebug->output; is($stdout, ""); is($stderr, ""); $ebug->step; is($ebug->line, 8); ($stdout, $stderr) = $ebug->output; is($stdout, "Hi!\nAbout to get square_root(-4)\n"); is($stderr, ""); $ebug->step; is($ebug->line, 9); ($stdout, $stderr) = $ebug->output; is($stdout, "Hi!\nAbout to get square_root(-4)\n"); is($stderr, "\$x is -4 at t/carp.pl line 8, line 10.\n"); $ebug->step; is($ebug->line, 13); ($stdout, $stderr) = $ebug->output; is($stdout, "Hi!\nAbout to get square_root(-4)\n"); is($stderr, "\$x is -4 at t/carp.pl line 8, line 10.\n"); $ebug->step; is($ebug->line, 14); ($stdout, $stderr) = $ebug->output; is($stdout, "Hi!\nAbout to get square_root(-4)\n"); is($stderr, "\$x is -4 at t/carp.pl line 8, line 10.\n"); $ebug->next; is($ebug->line, 15); ($stdout, $stderr) = $ebug->output; is($stdout, "Hi!\nAbout to get square_root(-4)\n"); like($stderr, qr{ \Qx is -4 at t/carp.pl line 8\E .* \Qdebug: In square_root, -4 is -4 at t/carp.pl line 14\E .* \Qmain::square_root(-4) called at t/carp.pl line 9\E }msx); $ebug->next; is($ebug->line, 16); ($stdout, $stderr) = $ebug->output; is($stdout, "Hi!\nAbout to get square_root(-4)\n"); like($stderr, qr{ \Qx is -4 at t/carp.pl line 8\E .* \Qdebug: In square_root, -4 is -4 at t/carp.pl line 14\E .* \Qmain::square_root(-4) called at t/carp.pl line 9\E }msx); $ebug->next; ok($ebug->finished); is($ebug->package, "DB::fake"); # bit of a side effect ($stdout, $stderr) = $ebug->output; is($stdout, "Hi!\nAbout to get square_root(-4)\n"); like($stderr, qr{ \Qx is -4 at t/carp.pl line 8\E .* \Qdebug: In square_root, -4 is -4 at t/carp.pl line 14\E .* \Qmain::square_root(-4) called at t/carp.pl line 9\E .* \Qsquare_root of negative number: -4 at t/carp.pl line 16\E .* \Qmain::square_root(-4) called at t/carp.pl line 9\E }msx); Devel-ebug-0.56/t/signal.t0000644000175000017500000000107112323642033015161 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Devel::ebug; use Test::More; plan skip_all => "Devel::ebug does not handle signals under Windows atm" if $^O =~ /mswin32/i; plan tests => 8; my $ebug = Devel::ebug->new; $ebug->program("t/signal.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->run; is($ebug->finished, 0); is($ebug->line, 8); my $pad = $ebug->pad; is($pad->{'$i'}, 11); is($pad->{'$square'}, 121); $ebug->run; is($ebug->finished, 0); is($ebug->line, 8); $pad = $ebug->pad; is($pad->{'$i'}, 12); is($pad->{'$square'}, 144); Devel-ebug-0.56/t/return.t0000644000175000017500000000163612323642033015232 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 13; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc_oo.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point_subroutine("Calc::add"); $ebug->run; is($ebug->line, 9); is($ebug->subroutine, 'Calc::add'); is($ebug->filename, 't/Calc.pm'); $ebug->return(); is($ebug->pad->{'$r'}, 15); is($ebug->line, 9); is($ebug->subroutine, 'main'); is($ebug->filename, 't/calc_oo.pl'); $ebug = Devel::ebug->new; $ebug->program("t/calc_oo.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point_subroutine("Calc::add"); $ebug->run; is($ebug->line, 9); is($ebug->subroutine, 'Calc::add'); $ebug->return(3.141); TODO: { local $TODO = 'Hmm... I broke the return...'; is($ebug->pad->{'$r'}, 3.141); } is($ebug->line, 9); is($ebug->subroutine, 'main'); is($ebug->filename, 't/calc_oo.pl'); Devel-ebug-0.56/t/stack.pl0000644000175000017500000000046712323642033015171 0ustar awwaiidawwaiid#!perl use strict; use warnings; use String::Koremutake; my $k = String::Koremutake->new; my %hash = ('a' => 1); show(); show(1, undef, 2); show(123); show(-0.3); show('a'); show('orange o rama'); show([]); show({}); show($k); sub show { my($first, @rest) = @_; print $first, @rest, "\n"; my $n = 1; } Devel-ebug-0.56/t/stack.t0000644000175000017500000000517012323642033015015 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 29; use Devel::ebug; use File::Spec; my $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; my @trace = $ebug->stack_trace; is(scalar(@trace), 0); $ebug->break_point(12); $ebug->run; @trace = $ebug->stack_trace; is(scalar(@trace), 1); # use YAML; warn Dump \@trace; my $trace = $trace[0]; is($trace->package , "main"); is($trace->filename , File::Spec->catfile('t','calc.pl'), "trace is on correct file name"); is($trace->subroutine, "main::add"); ok(! $trace->wantarray ); # Forced boolean context is($trace->line , 5); is_deeply([$trace->args], [1, 2]); @trace = $ebug->stack_trace_human; is(scalar(@trace), 1); is($trace[0], 'add(1, 2)'); $ebug = Devel::ebug->new; $ebug->program("t/calc_oo.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point("t/Calc.pm", 19); $ebug->run; @trace = $ebug->stack_trace_human; is(scalar(@trace), 1); is($trace[0], '$calc->fib1(15)'); $ebug->run; @trace = $ebug->stack_trace_human; is(scalar(@trace), 2); is($trace[1], '$calc->fib1(15)'); is($trace[0], '$self->fib1(14)'); $ebug = Devel::ebug->new; $ebug->program("t/koremutake.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->step; @trace = $ebug->stack_trace_human; is(scalar(@trace), 1); is($trace[0], 'String::Koremutake->new()'); $ebug = Devel::ebug->new; $ebug->program("t/koremutake.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point_subroutine("String::Koremutake::integer_to_koremutake"); $ebug->run; @trace = $ebug->stack_trace_human; is(scalar(@trace), 1); is($trace[0], '$koremutake->integer_to_koremutake(65535)'); $ebug = Devel::ebug->new; $ebug->program("t/stack.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point_subroutine("main::show"); $ebug->run; @trace = $ebug->stack_trace_human; is(scalar(@trace), 1); is($trace[0], 'show()'); $ebug->run; @trace = $ebug->stack_trace_human; is($trace[0], 'show(1, undef, 2)'); $ebug->run; @trace = $ebug->stack_trace_human; is($trace[0], 'show(123)'); $ebug->run; @trace = $ebug->stack_trace_human; is($trace[0], 'show(-0.3)'); $ebug->run; @trace = $ebug->stack_trace_human; is($trace[0], "show('a')"); $ebug->run; @trace = $ebug->stack_trace_human; is($trace[0], 'show("orange o rama")'); $ebug->run; @trace = $ebug->stack_trace_human; is($trace[0], 'show([...])'); $ebug->run; @trace = $ebug->stack_trace_human; is($trace[0], 'show({...})'); $ebug->run; @trace = $ebug->stack_trace_human; is($trace[0], 'show($koremutake)'); # use YAML; warn Dump \@trace; Devel-ebug-0.56/t/calc.pl0000644000175000017500000000032312323642033014755 0ustar awwaiidawwaiid#!perl my $q = 1; my $w = 2; my $e = add($q, $w); $e++; $e++; print "$e\n"; sub add { my($z, $x) = @_; my $c = $z + $x; return $c; } # unbreakable line my $breakable_line = 1; # other unbreakable line Devel-ebug-0.56/t/Calc.pm0000644000175000017500000000100612323642033014715 0ustar awwaiidawwaiidpackage Calc; use strict; use warnings; use Class::Accessor::Chained::Fast; use base qw(Class::Accessor::Chained::Fast); our $VERSION = "0.29"; sub add { my($self, $l, $r) = @_; return $l + $r; } sub fib1 { my($self, $n) = @_; if ($n < 2) { return 1; } else { return $self->fib1($n - 1) + $self->fib1($n - 2); } } sub fib2 { my($self, $n) = @_; my $x1 = 1; my $x2 = 1; my $tmp = 0; foreach my $i (1..$n) { $tmp = $x1 + $x2; $x1 = $x2; $x2 = $tmp; } return $x1; } Devel-ebug-0.56/t/carp.pl0000644000175000017500000000053312323642033015003 0ustar awwaiidawwaiid#!perl use strict; use warnings; use Carp; my $x = -4; print "Hi!\nAbout to get square_root($x)\n"; warn "\$x is -4"; my $result = square_root($x); print "$result\n"; sub square_root { my $arg = shift; carp "debug: In square_root, $arg is $arg"; if ($arg < 0) { croak "square_root of negative number: $arg"; } return sqrt($arg); } Devel-ebug-0.56/t/basic.t0000644000175000017500000000077312323642033014775 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 36; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->program("t/calc.pl"); $ebug->load; # Let's step through the program, and check that we step through the # lines in the right order my @lines = (3, 4, 5, 12, 13, 14, 6, 7, 9); foreach my $l (@lines) { is($ebug->line, $l); is($ebug->package, 'main'); is($ebug->filename, 't/calc.pl'); ok($ebug->codeline); $ebug->step; } Devel-ebug-0.56/t/yaml.pl0000644000175000017500000000020212323642033015011 0ustar awwaiidawwaiiduse YAML; my $hash = { '/foo/foo- hate' => 'bz' }; print YAML::Dump ($hash); print YAML::Dump (YAML::Load (YAML::Dump ($hash))); Devel-ebug-0.56/t/ebug.t0000644000175000017500000000365212323642033014635 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Devel::ebug; use Test::More; eval "use Test::Expect"; plan skip_all => "Test::Expect required for testing ebug: $@" if $@; eval "use Expect::Simple"; plan skip_all => "Expect::Simple required for testing ebug: $@" if $@; plan tests => 19; expect_run( command => "PERL_RL=\"o=0\" $^X bin/ebug --backend \"$^X bin/ebug_backend_perl\" t/calc.pl", prompt => 'ebug: ', quit => 'q', ); my $version = $Devel::ebug::VERSION; expect_like(qr/Welcome to Devel::ebug $version/, 'Got welcome'); expect_like(qr{main\(t/calc.pl#3\):\nmy \$q = 1;}, 'Got initial lines'); expect("h", 'Commands: b Set break point at a line number (eg: b 6, b code.pl 6, b code.pl 6 $x > 7, b Calc::fib) bf break on file loading (eg: bf Calc.pm) d Delete a break point (d 6, d code.pl 6) e Eval Perl code and print the result (eg: e $x+$y) f Show all the filenames loaded l List codelines or set number of codelines to list (eg: l, l 20) L List codelines always (toggle) n Next (steps over subroutine calls) o Output (show STDOUT, STDERR) p Show pad r Run until next break point or watch point ret Return from subroutine (eg: ret, ret 3.141) restart Restart the program s Step (steps into subroutine calls) T Show a stack trace u Undo (eg: u, u 4) w Set a watchpoint (eg: w $t > 10) x Dump a variable using YAML (eg: x $object) q Quit main(t/calc.pl#3): my $q = 1;', 'Got help'); expect("b 9", "main(t/calc.pl#3):\nmy \$q = 1;", 'set breakpoint'); expect("s", "main(t/calc.pl#4):\nmy \$w = 2;", 'step'); expect("", "main(t/calc.pl#5):\nmy \$e = add(\$q, \$w);", 'step again'); expect("n", "main(t/calc.pl#6):\n\$e++;", 'next'); expect("r", qq{main(t/calc.pl#9):\nprint "\$e\\n";}, 'run'); expect("r", qq{}, 'run to end'); expect("r", qq{Program finished. Enter 'restart' or 'q'}, 'run to end'); expect_quit(); exit; Devel-ebug-0.56/t/pod.pl0000644000175000017500000000114012323642033014633 0ustar awwaiidawwaiid#!perl use strict; use warnings; my $x = 1; my $y = 2; my $z = add(1, 2); my $zz = subtract($x, $z); print "Result is $zz!\n"; =head1 NAME pod.pl - An example program with POD =head1 SYNOPSIS # none =head1 DESCRIPTION No usage really, it's just to check out any embedded POD issues with Devel::ebug. =head1 SUBROUTINES =head2 add Add two integers together. =cut sub add { my($z, $x) = @_; my $c = $z + $x; return $c; } =head2 subtract Subtract one number from another. =cut sub subtract { my($z, $x) = @_; my $c = $z - $x; return $c; } 1; __END__ =head2 AUTHOR Me! =cut Devel-ebug-0.56/t/undo.t0000644000175000017500000000171112323642033014652 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 21; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; is($ebug->line, 3); is($ebug->subroutine, "main"); is($ebug->package, "main"); is($ebug->filename, "t/calc.pl"); $ebug->step; is($ebug->line, 4); $ebug->step; is($ebug->line, 5); $ebug->undo; is($ebug->line, 4); $ebug->undo; is($ebug->line, 3); $ebug->break_point(6); $ebug->break_point(12); $ebug->break_point(9); $ebug->undo; is_deeply([$ebug->break_points], [6, 12]); is($ebug->line, 3); is($ebug->subroutine, "main"); is($ebug->package, "main"); is($ebug->filename, "t/calc.pl"); $ebug->run; is($ebug->line, 12); $ebug->run; is($ebug->line, 6); $ebug->step; $ebug->step; is($ebug->pad->{'$e'}, 5); $ebug->undo; is($ebug->line, 7); is($ebug->subroutine, "main"); is($ebug->package, "main"); is($ebug->filename, "t/calc.pl"); is($ebug->pad->{'$e'}, 4); Devel-ebug-0.56/t/eval.t0000644000175000017500000000121412323642033014632 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 9; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point(6); $ebug->run; is($ebug->line, 6); is($ebug->eval('$e'), 3); is_deeply([$ebug->eval('$e')], [3, 0]); my $exception = $ebug->eval('die 123'); like($exception, qr/^123 at \(eval \d+\)/); my @exception = $ebug->eval('die 123'); is($exception[1], 1); # no like_deeply like($exception[0], qr/^123 at \(eval \d+\)/); $ebug->step; is($ebug->eval('$e'), 4); $ebug->step; is($ebug->eval('$e'), 5); is($ebug->yaml('$e'), "--- 5\n"); Devel-ebug-0.56/t/run.t0000644000175000017500000000055112323642033014512 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 3; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; is($ebug->line, 3); $ebug->step; $ebug->step; $ebug->step; is($ebug->line, 12); $ebug->run; ok($ebug->finished); my($stdout, $stderr) = $ebug->output; Devel-ebug-0.56/t/pad.t0000644000175000017500000000336412323642033014457 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 22; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; # Let's step through the program, and check that we get the # lexical variables for each line my $want_vars = { 3 => '', 4 => '$q=1', 5 => '$q=1,$w=2', 12 => '$e=undef,$q=1,$w=2', 13 => '$e=undef,$q=1,$w=2,$x=2,$z=1', 14 => '$c=3,$e=undef,$q=1,$w=2,$x=2,$z=1', 6 => '$e=3,$q=1,$w=2', 7 => '$e=4,$q=1,$w=2', 9 => '$e=5,$q=1,$w=2', }; foreach (1..9) { my $line = $ebug->line; my $pad = $ebug->pad; my @vars; foreach my $k (sort keys %$pad) { my $v = $pad->{$k} || 'undef'; push @vars, "$k=$v"; } my $vars = join ',', @vars; $vars ||= ''; is($vars, $want_vars->{$line}, "$line has $vars"); $ebug->step; } $ebug = Devel::ebug->new; $ebug->program("t/stack.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point(22); $ebug->run; my $pad = $ebug->pad_human; is($pad->{'$first'}, 'undef'); is($pad->{'%hash'}, '(...)'); $ebug->run; $pad = $ebug->pad; is($pad->{'$first'}, '1'); is_deeply($pad->{'@rest'}, [undef, 2]); $pad = $ebug->pad_human; is($pad->{'$first'}, '1'); is($pad->{'@rest'}, "(undef, 2)"); $ebug->run; $pad = $ebug->pad_human; is($pad->{'$first'}, '123'); $ebug->run; $pad = $ebug->pad_human; is($pad->{'$first'}, '-0.3'); $ebug->run; $pad = $ebug->pad_human; is($pad->{'$first'}, "'a'"); $ebug->run; $pad = $ebug->pad_human; is($pad->{'$first'}, '"orange o rama"'); $ebug->run; $pad = $ebug->pad_human; is($pad->{'$first'}, '[...]'); $ebug->run; $pad = $ebug->pad_human; is($pad->{'$first'}, '{...}'); $ebug->run; $pad = $ebug->pad_human; is($pad->{'$first'}, '$koremutake'); Devel-ebug-0.56/t/pod.t0000644000175000017500000000022012323642033014461 0ustar awwaiidawwaiid#!perl -T use Test::More; eval "use Test::Pod 1.14"; plan skip_all => "Test::Pod 1.14 required for testing POD: $@" if $@; all_pod_files_ok(); Devel-ebug-0.56/t/oo.t0000644000175000017500000000156412323642033014330 0ustar awwaiidawwaiid#!perl use strict; use warnings; use lib 'lib'; use Test::More tests => 12; use Devel::ebug; my $ebug = Devel::ebug->new; $ebug->program("t/calc_oo.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; # Let's step through the program, and check that we step through the # lines in the right order is($ebug->line, 7); is($ebug->filename, 't/calc_oo.pl'); $ebug->next; is($ebug->line, 8); is($ebug->filename, 't/calc_oo.pl'); $ebug->next; is($ebug->line, 9); is($ebug->filename, 't/calc_oo.pl'); $ebug->next; is($ebug->line, 10); is($ebug->filename, 't/calc_oo.pl'); $ebug->next; $ebug = Devel::ebug->new; $ebug->program("t/calc_oo.pl"); $ebug->backend("$^X bin/ebug_backend_perl"); $ebug->load; $ebug->break_point_subroutine("Calc::add"); $ebug->run; is($ebug->line, 9); is($ebug->package, 'Calc'); is($ebug->subroutine, 'Calc::add'); is($ebug->filename, 't/Calc.pm'); Devel-ebug-0.56/TODO0000644000175000017500000000271412323642033013751 0ustar awwaiidawwaiidThings it would be good to have in Devel::ebug: Add more Ajax to ebug_http Add more features to ebug_http Allow debugging of regexes Better error message for when server goes away (storable) Better action point setting in ebug_http Command line arguments Document keyboard shortcuts Edit program in place while still debugging using Module::Refresh Emacs Devel::ebug mode Forks: when the program being debugged forks, follow the child in ebug_http Forks: when the program being debugged forks, open a new window in ebug_http If you mouseover a variable declaration, every use of that variable is highlighted - Alias Jump to stack frame in ebug_http Localise ebug, ebug_http Make break_points able to return break points in other filenames Make break_point_subroutine take a condition Merge watch points and break points Online documentation for ebug_http (tutorial?) Optimise ebug (make timing graphs and see if we can add pipelining) PPI failures with weird characters - cope Return list/listrefs and hash/hashrefs depending on context Smart::Comments for debugging Test coverage Test ebug more Test ebug_http Test minicpan Test with bigger examples Tidy up code Use Class::ISA to show inheritance Interesting discussions about debuggers: http://blogs.msdn.com/ricksp/archive/2004/03/29/101410.aspx http://www.codeproject.com/csharp/DebuggerVisualizers.asp http://msdn.microsoft.com/msdnmag/issues/04/05/VisualStudio2005Debugging/ http://www.daimi.au.dk/~beta/ooli/Debugging.html