AnyEvent-GDB
view release on metacpan or search on metacpan
$r
} elsif (/\G\[/gc) { # list
my @r;
until (/\G\]/gc) {
# if GDB outputs "result" in lists, let me know and uncomment the following lines
# # list might also contain key value pairs, but apparently
# # those are supposed to be ordered, so we use an array in perl.
# push @r, $1
# if /\G([^=,\[\]\{\}]+)=/gc;
push @r, &_parse_value;
/\G,/gc
or last;
}
/\G\]/gc
or die "list does not end with ']'\n";
\@r
} else {
die "value expected\n";
}
}
sub _parse_results {
my %r;
# syntax for string is undocumented
while (/\G([^=,\[\]\{\}]+)=/gc) {
my $k = $1;
$k =~ y/-/_/;
$r{$k} = &_parse_value;
/\G,/gc
or last;
}
\%r
}
my %type_map = qw(
* exec
+ status
= notify
);
sub feed {
my ($self, $line) = @_;
print "< $line\n"
if $self->{trace};
for ($line) {
if (/^\(gdb\)\s*$/gc) { # docs say "(gdb)", but reality says "(gdb) "
# nop
} else {
/^([0-9]*)/gc; # [token], actually ([0-9]+)?
my $token = $1;
eval {
if (/\G\^(done|running|connected|error|exit)/gc) { # result
my $class = $1 eq "running" ? "done" : $1;
# documented for error is an incompatible format, but in reality it is sane
my $results = /\G,/gc ? &_parse_results : {};
if (my $cb = delete $self->{cb}{$token}) {
# unfortunately, gdb sometimes outputs multiple result records for one command
$cb->($class, $results, delete $self->{console});
}
} elsif (/\G([*+=])([^,]+)/gc) { # *exec-async, +status-async, =notify-async
my ($type, $class) = ($type_map{$1}, $2);
my $results = /\G,/gc ? &_parse_results : {};
$class =~ y/-/_/;
$self->event ($type => $class, $results);
$self->event ("$type\_$class" => $results);
} elsif (/\G~"/gc) {
push @{ $self->{console} }, &_parse_c_string;
} elsif (/\G&"/gc) {
my $log = &_parse_c_string;
chomp $log;
print "$log\n" if $self->{verbose};
$self->event (log => $log);
} elsif (/\G\@"/gc) {
$self->event (target => &_parse_c_string);
}
};
/\G(.{0,16})/gcs;
$@ = "extra data\n" if !$@ and length $1;
if ($@) {
chop $@;
warn "AnyEvent::GDB: parse error: $@, at ...$1\n";
$self->eof;
}
}
}
}
sub _q($) {
return $_[0]
if $_[0] =~ /^[A-Za-z0-9_]+$/; # we are a lot more strict than the spec
local $_ = shift;
utf8::encode $_; # just in case
s/([^\x20-\x21\x23-\x5b\x5d-\x7e])/sprintf "\\x%02x", ord $1/ge;
"\"$_\""
}
( run in 0.482 second using v1.01-cache-2.11-cpan-96521ef73a4 )