mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-01 06:05:24 +02:00
[236461] - [pda] Port PDA Virtual Machine implementation to Java
This commit is contained in:
parent
ce33d6a9cf
commit
a69b4955f0
8 changed files with 846 additions and 1170 deletions
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="pdavm/src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
|
|
|
@ -1,673 +0,0 @@
|
|||
#!perl.exe
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use IO::Socket;
|
||||
|
||||
#####################################################################
|
||||
# Copyright (c) 2005 IBM Corporation and others.
|
||||
# All rights reserved. This program and the accompanying materials
|
||||
# are made available under the terms of the Eclipse Public License v1.0
|
||||
# which accompanies this distribution, and is available at
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
# Contributors:
|
||||
# Bjorn Freeman-Benson - initial API and implementation
|
||||
#####################################################################
|
||||
|
||||
#####################################################################
|
||||
# #
|
||||
# I N I T I A L I Z A T I O N A N D V A R I A B L E S #
|
||||
# #
|
||||
#####################################################################
|
||||
#
|
||||
# The push down automata stack (the data stack)
|
||||
#
|
||||
my @stack;
|
||||
#
|
||||
# Load all the code into memory
|
||||
# The code is stored as an array of strings, each line of
|
||||
# the source file being one entry in the array.
|
||||
#
|
||||
my $filename = shift;
|
||||
open INFILE, $filename or die $!;
|
||||
my @code = <INFILE>;
|
||||
close INFILE;
|
||||
|
||||
my %labels;
|
||||
sub map_labels {
|
||||
#
|
||||
# A mapping of labels to indicies in the code array
|
||||
#
|
||||
%labels = ( );
|
||||
my $idx = 0;
|
||||
while( $idx <= $#code ) {
|
||||
if( length $code[$idx] > 0 ) {
|
||||
$code[$idx] =~ /^\s*(.+?)\s*$/;
|
||||
$code[$idx] = $1;
|
||||
$labels{$1} = $idx if( $code[$idx] =~ /^:(\S+)/ );
|
||||
} else {
|
||||
$code[$idx] = "\n";
|
||||
}
|
||||
$idx ++;
|
||||
}
|
||||
}
|
||||
map_labels();
|
||||
#
|
||||
# The stack of stack frames (the control stack)
|
||||
# Each stack frame is a mapping of variable names to values.
|
||||
# There are a number of special variable names:
|
||||
# _pc_ is the current program counter in the frame
|
||||
# the pc points to the next instruction to be executed
|
||||
# _func_ is the name of the function in this frame
|
||||
#
|
||||
my @frames;
|
||||
my $currentframe;
|
||||
$currentframe = {
|
||||
_pc_ => 0,
|
||||
_func_ => 'main'
|
||||
};
|
||||
|
||||
#
|
||||
# The command line argument to start a debug session.
|
||||
#
|
||||
my $debugflag = shift;
|
||||
#
|
||||
# The port to listen for debug commands on
|
||||
# and the port to send debug events to
|
||||
#
|
||||
my $debugport;
|
||||
my $debugport2;
|
||||
#
|
||||
# The socket to listen for debug commands on
|
||||
# and the socket to send debug events on
|
||||
#
|
||||
my $debugsock;
|
||||
my $debugsock2;
|
||||
#
|
||||
# An input buffer
|
||||
#
|
||||
my $debugbuf;
|
||||
#
|
||||
# Breakpoint array
|
||||
# breakpoints are stored as a boolean for each line of code
|
||||
# if the boolean is true, there is a breakpoint on that line
|
||||
#
|
||||
my @breakpoints;
|
||||
#
|
||||
# Mapping of debugger commands to functions that evaluate them
|
||||
#
|
||||
my %debug_commands = (
|
||||
clear => \&debug_clear_breakpoint,
|
||||
data => \&debug_data,
|
||||
drop => \&debug_drop_frame,
|
||||
eval => \&debug_eval,
|
||||
eventstop => \&debug_event_stop,
|
||||
exit => \&debug_exit,
|
||||
popdata => \&debug_pop,
|
||||
pushdata => \&debug_push,
|
||||
resume => \&debug_resume,
|
||||
set => \&debug_set_breakpoint,
|
||||
setdata => \&debug_set_data,
|
||||
setvar => \&debug_set_variable,
|
||||
stack => \&debug_stack,
|
||||
step => \&debug_step,
|
||||
stepreturn => \&debug_step_return,
|
||||
suspend => \&debug_suspend,
|
||||
var => \&debug_var,
|
||||
watch => \&debug_watch
|
||||
);
|
||||
|
||||
#
|
||||
# The run flag is true if the VM is running.
|
||||
# If the run flag is false, the VM exits the
|
||||
# next time the main instruction loop runs.
|
||||
#
|
||||
my $run = 1;
|
||||
#
|
||||
# The suspend flag is true if the VM should suspend
|
||||
# running the program and just listen for debug commands.
|
||||
#
|
||||
my $suspend = 0;
|
||||
my $started = 1;
|
||||
$suspend = "client" if( $debugflag );
|
||||
#
|
||||
# The step flag is used to control single-stepping.
|
||||
# See the implementation of the "step" debug command.
|
||||
# The stepreturn flag is used to control step-return.
|
||||
# The eventstops table holds which events cause suspends and which do not.
|
||||
# The watchpoints table holds watchpoint information.
|
||||
# variablename_stackframedepth => N
|
||||
# N = 0 is no watch
|
||||
# N = 1 is read watch
|
||||
# N = 2 is write watch
|
||||
# N = 3 is both, etc.
|
||||
#
|
||||
my $step = 0;
|
||||
my $stepreturn = 0;
|
||||
my %eventstops = ( "unimpinstr" => 0,
|
||||
"nosuchlabel" => 0,
|
||||
);
|
||||
my %watchpoints = ( );
|
||||
|
||||
#
|
||||
# Mapping of the names of the instructions to the functions that evaluate them
|
||||
#
|
||||
my %instructions = (
|
||||
add => \&add,
|
||||
branch_not_zero => \&branch_not_zero,
|
||||
call => \&call,
|
||||
dec => \&dec,
|
||||
dup => \&dup,
|
||||
halt => \&halt,
|
||||
output => \&output,
|
||||
pop => \&ipop,
|
||||
push => \&ipush,
|
||||
return => \&ireturn,
|
||||
var => \&var,
|
||||
xyzzy => \&internal_end_eval,
|
||||
);
|
||||
|
||||
#####################################################################
|
||||
# #
|
||||
# M A I N I N T E R P R E T E R #
|
||||
# #
|
||||
#####################################################################
|
||||
#
|
||||
# Open a debug session if the command line argument is given.
|
||||
#
|
||||
start_debugger();
|
||||
send_debug_event( "started", 0 );
|
||||
debug_ui() if( $suspend );
|
||||
#
|
||||
# The main run loop
|
||||
#
|
||||
while( $run ) {
|
||||
check_for_breakpoint();
|
||||
debug_ui() if( $suspend );
|
||||
yield_to_debug();
|
||||
my $instruction = fetch_instruction();
|
||||
increment_pc();
|
||||
do_one_instruction($instruction);
|
||||
if( $$currentframe{_pc_} > $#code ) {
|
||||
$run = 0;
|
||||
} elsif( $stepreturn ) {
|
||||
$instruction = fetch_instruction();
|
||||
$suspend = "step" if( is_return_instruction($instruction) );
|
||||
}
|
||||
}
|
||||
send_debug_event( "terminated", 0 );
|
||||
|
||||
sub fetch_instruction {
|
||||
my $pc = $$currentframe{_pc_};
|
||||
my $theinstruction = $code[$pc];
|
||||
return $theinstruction;
|
||||
}
|
||||
sub is_return_instruction {
|
||||
my $theinstruction = shift;
|
||||
if( $theinstruction =~ /^:/ ) {
|
||||
return 0;
|
||||
} elsif( $theinstruction =~ /^#/ ) {
|
||||
return 0;
|
||||
} else {
|
||||
$theinstruction =~ /^(\S+)\s*(.*)/;
|
||||
return $1 eq "return";
|
||||
}
|
||||
}
|
||||
sub increment_pc {
|
||||
my $pc = $$currentframe{_pc_};
|
||||
$pc++;
|
||||
$$currentframe{_pc_} = $pc;
|
||||
}
|
||||
sub decrement_pc {
|
||||
my $pc = $$currentframe{_pc_};
|
||||
$pc--;
|
||||
$$currentframe{_pc_} = $pc;
|
||||
}
|
||||
sub do_one_instruction {
|
||||
my $theinstruction = shift;
|
||||
if( $theinstruction =~ /^:/ ) {
|
||||
# label
|
||||
$suspend = "step" if( $step );
|
||||
} elsif( $theinstruction =~ /^#/ ) {
|
||||
# comment
|
||||
} else {
|
||||
$theinstruction =~ /^(\S+)\s*(.*)/;
|
||||
my $op = $1;
|
||||
my $instr = $instructions{$op};
|
||||
if( $instr ) {
|
||||
&$instr( $theinstruction, $2 );
|
||||
$suspend = "step" if( $step );
|
||||
} else {
|
||||
send_debug_event( "unimplemented instruction $op", 1 );
|
||||
if( $eventstops{"unimpinstr"} ) {
|
||||
$suspend = "event unimpinstr";
|
||||
decrement_pc();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# #
|
||||
# I N S T R U C T I O N S #
|
||||
# #
|
||||
#####################################################################
|
||||
sub add {
|
||||
my $val1 = pop @stack;
|
||||
my $val2 = pop @stack;
|
||||
my $val = $val1 + $val2;
|
||||
push @stack, $val;
|
||||
}
|
||||
|
||||
sub branch_not_zero {
|
||||
my $val = pop @stack;
|
||||
if( $val ) {
|
||||
shift;
|
||||
my $label = shift;
|
||||
my $dest = $labels{$label};
|
||||
if( !defined $dest ) {
|
||||
send_debug_event( "no such label $label", 1 );
|
||||
if( $eventstops{"nosuchlabel"} ) {
|
||||
$suspend = "event nosuchlabel";
|
||||
push @stack, $val;
|
||||
decrement_pc();
|
||||
}
|
||||
} else {
|
||||
$$currentframe{_pc_} = $dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub call {
|
||||
shift;
|
||||
my $label = shift;
|
||||
my $dest = $labels{$label};
|
||||
if( !defined $dest ) {
|
||||
send_debug_event( "no such label $label", 1 );
|
||||
if( $eventstops{"nosuchlabel"} ) {
|
||||
$suspend = "event nosuchlabel";
|
||||
decrement_pc();
|
||||
}
|
||||
} else {
|
||||
push @frames, $currentframe;
|
||||
$currentframe = {
|
||||
_pc_ => $dest,
|
||||
_func_ => $label
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
sub dec {
|
||||
my $val = pop @stack;
|
||||
$val--;
|
||||
push @stack, $val;
|
||||
}
|
||||
|
||||
sub dup {
|
||||
my $val = pop @stack;
|
||||
push @stack, $val;
|
||||
push @stack, $val;
|
||||
}
|
||||
|
||||
sub halt {
|
||||
$run = 0;
|
||||
}
|
||||
|
||||
sub output {
|
||||
my $val = pop @stack;
|
||||
print "$val\n";
|
||||
}
|
||||
|
||||
sub ipop {
|
||||
shift;
|
||||
my $arg = shift;
|
||||
if( $arg =~ /^\$(.*)/ ) {
|
||||
$$currentframe{$1} = pop @stack;
|
||||
my $key = "$$currentframe{_func_}\:\:$1";
|
||||
if( defined $watchpoints{$key} ) {
|
||||
if( $watchpoints{$key} & 2 ) {
|
||||
$suspend = "watch write $key";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pop @stack;
|
||||
}
|
||||
}
|
||||
|
||||
sub ipush {
|
||||
shift;
|
||||
my $arg = shift;
|
||||
if( $arg =~ /^\$(.*)/ ) {
|
||||
my $val = $$currentframe{$1};
|
||||
push @stack, $val;
|
||||
my $key = "$$currentframe{_func_}\:\:$1";
|
||||
if( defined $watchpoints{$key} ) {
|
||||
if( $watchpoints{$key} & 1 ) {
|
||||
$suspend = "watch read $key";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
push @stack, $arg;
|
||||
}
|
||||
}
|
||||
|
||||
sub ireturn {
|
||||
$currentframe = pop @frames;
|
||||
}
|
||||
|
||||
sub var {
|
||||
shift;
|
||||
my $name = shift;
|
||||
$$currentframe{$name} = 0;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# #
|
||||
# D E B U G G E R I N T E R F A C E #
|
||||
# #
|
||||
#####################################################################
|
||||
|
||||
sub check_for_breakpoint {
|
||||
if( $debugflag ) {
|
||||
my $pc = $$currentframe{_pc_};
|
||||
if( $breakpoints[$pc] ) {
|
||||
$suspend = "breakpoint $pc" unless $suspend eq "eval";
|
||||
}
|
||||
}
|
||||
}
|
||||
#
|
||||
# For each instruction, we check the debug co-routine for
|
||||
# control input. If there is input, we process it.
|
||||
#
|
||||
sub yield_to_debug {
|
||||
if( $debugflag ) {
|
||||
my $bytes_to_read = 1024;
|
||||
my $bytes_read = sysread($debugsock, $debugbuf, $bytes_to_read);
|
||||
if( defined($bytes_read) ) {
|
||||
#print "read $bytes_to_read\n";
|
||||
my $rin = '';
|
||||
my $win = '';
|
||||
my $ein = '';
|
||||
vec($rin,fileno($debugsock),1) = 1;
|
||||
$ein = $rin | $win;
|
||||
my $debugline = $debugbuf;
|
||||
while( !($debugline =~ /\n/) ) {
|
||||
select($rin, undef, undef, undef);
|
||||
my $bytes_to_read = 1024;
|
||||
my $bytes_read = sysread($debugsock, $debugbuf, $bytes_to_read);
|
||||
$debugline .= $debugbuf;
|
||||
}
|
||||
#print "read: $debugline";
|
||||
process_debug_command($debugline);
|
||||
$debugline = '';
|
||||
} else {
|
||||
# no bytes read
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# If the execution is suspended, then we go into the debug
|
||||
# ui loop, reading and processing instructions.
|
||||
#
|
||||
sub debug_ui {
|
||||
return unless( $suspend );
|
||||
my $pc = $$currentframe{_pc_};
|
||||
if (!$started) {
|
||||
send_debug_event( "suspended $suspend", 0 );
|
||||
} else {
|
||||
$started = 0;
|
||||
}
|
||||
$step = 0;
|
||||
$stepreturn = 0;
|
||||
my $rin = '';
|
||||
my $win = '';
|
||||
my $ein = '';
|
||||
vec($rin,fileno($debugsock),1) = 1;
|
||||
$ein = $rin | $win;
|
||||
my $debugline = '';
|
||||
while( $suspend ) {
|
||||
select($rin, undef, undef, undef);
|
||||
my $bytes_to_read = 1024;
|
||||
my $bytes_read = sysread($debugsock, $debugbuf, $bytes_to_read);
|
||||
$debugline .= $debugbuf;
|
||||
if( $debugline =~ /\n/ ) {
|
||||
#print "read: $debugline";
|
||||
process_debug_command($debugline);
|
||||
$debugline = '';
|
||||
}
|
||||
}
|
||||
send_debug_event( "resumed step", 0 ) if( $step );
|
||||
send_debug_event( "resumed client", 0 ) unless( $step );
|
||||
}
|
||||
|
||||
sub process_debug_command {
|
||||
my $line = shift;
|
||||
return if( length $line < 2 );
|
||||
my @words = split /\s/, $line;
|
||||
my $command = lc($words[0]);
|
||||
my $dfunc = $debug_commands{$words[0]};
|
||||
if( $dfunc ) {
|
||||
&$dfunc( @words );
|
||||
}
|
||||
}
|
||||
|
||||
sub debug_clear_breakpoint {
|
||||
shift;
|
||||
my $line = shift;
|
||||
$breakpoints[$line] = 0;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
my @saved_code;
|
||||
my %saved_labels;
|
||||
my $saved_pc;
|
||||
sub debug_eval {
|
||||
shift;
|
||||
my $code = shift;
|
||||
my @lines = split /\|/, $code;
|
||||
my $newpc = scalar @code;
|
||||
@saved_code = @code;
|
||||
%saved_labels = %labels;
|
||||
foreach my $line ( @lines ) {
|
||||
$line =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
|
||||
push @code, $line;
|
||||
}
|
||||
push @code, "xyzzy";
|
||||
map_labels();
|
||||
$saved_pc = $$currentframe{_pc_};
|
||||
$$currentframe{_pc_} = $newpc;
|
||||
print $debugsock "ok\n";
|
||||
$suspend = 0;
|
||||
}
|
||||
sub internal_end_eval {
|
||||
my $result = pop @stack;
|
||||
@code = @saved_code;
|
||||
%labels = %saved_labels;
|
||||
$$currentframe{_pc_} = $saved_pc;
|
||||
send_debug_event( "evalresult $result", 0 );
|
||||
$suspend = "eval";
|
||||
}
|
||||
|
||||
sub debug_data {
|
||||
my $result = '';
|
||||
foreach my $d ( @stack ) {
|
||||
$result .= $d . '|';
|
||||
}
|
||||
print $debugsock "$result\n";
|
||||
}
|
||||
sub debug_drop_frame {
|
||||
ireturn();
|
||||
decrement_pc();
|
||||
print $debugsock "ok\n";
|
||||
send_debug_event( "resumed drop", 0 );
|
||||
send_debug_event( "suspended drop", 0 );
|
||||
}
|
||||
sub debug_event_stop {
|
||||
shift;
|
||||
my $event = shift;
|
||||
my $bool = shift;
|
||||
$eventstops{$event} = $bool;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_exit {
|
||||
print $debugsock "ok\n";
|
||||
send_debug_event( "terminated", 0 );
|
||||
exit 0;
|
||||
}
|
||||
sub debug_pop {
|
||||
pop @stack;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_push {
|
||||
shift;
|
||||
my $value = shift;
|
||||
push @stack, $value;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_resume {
|
||||
$suspend = 0;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_set_breakpoint {
|
||||
shift;
|
||||
my $line = shift;
|
||||
$breakpoints[$line] = 1;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_set_data {
|
||||
shift;
|
||||
my $offset = shift;
|
||||
my $value = shift;
|
||||
$stack[$offset] = $value;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_set_variable {
|
||||
shift;
|
||||
my $sfnumber = shift;
|
||||
my $var = shift;
|
||||
my $value = shift;
|
||||
if( $sfnumber > $#frames ) {
|
||||
$$currentframe{$var} = $value;
|
||||
} else {
|
||||
my $theframe = $frames[$sfnumber];
|
||||
$$theframe{$var} = $value;
|
||||
}
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_stack {
|
||||
my $result = '';
|
||||
foreach my $frame ( @frames ) {
|
||||
$result .= print_frame($frame);
|
||||
$result .= '#';
|
||||
}
|
||||
$result .= print_frame($currentframe);
|
||||
print $debugsock "$result\n";
|
||||
}
|
||||
sub debug_step {
|
||||
# set suspend to 0 to allow the debug loop to exit back to
|
||||
# the instruction loop and thus run an instruction. However,
|
||||
# we want to come back to the debug loop right away, so the
|
||||
# step flag is set to true which will cause the suspend flag
|
||||
# to get set to true when we get to the next instruction.
|
||||
$step = 1;
|
||||
$suspend = 0;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_step_return {
|
||||
$stepreturn = 1;
|
||||
$suspend = 0;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_suspend {
|
||||
$suspend = "client";
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
sub debug_var {
|
||||
shift;
|
||||
my $sfnumber = shift;
|
||||
my $var = shift;
|
||||
if( $sfnumber > $#frames ) {
|
||||
print $debugsock "$$currentframe{$var}\n";
|
||||
} else {
|
||||
my $theframe = $frames[$sfnumber];
|
||||
print $debugsock "$$theframe{$var}\n";
|
||||
}
|
||||
}
|
||||
sub debug_watch {
|
||||
shift;
|
||||
my $key = shift;
|
||||
my $value = shift;
|
||||
$watchpoints{$key} = $value;
|
||||
print $debugsock "ok\n";
|
||||
}
|
||||
#
|
||||
# Some event has happened so notify the debugger.
|
||||
# If there is no debugger, we may still want to report the
|
||||
# event (such as if it is an error).
|
||||
#
|
||||
sub send_debug_event {
|
||||
my $event = shift;
|
||||
if( $debugflag ) {
|
||||
print $debugsock2 "$event\n";
|
||||
} else {
|
||||
my $use_stderr = shift;
|
||||
print "Error: $event\n" if $use_stderr;
|
||||
}
|
||||
}
|
||||
#
|
||||
# The stack frame output is:
|
||||
# frame # frame # frame ...
|
||||
# where each frame is:
|
||||
# filename | line number | function name | var | var | var | var ...
|
||||
#
|
||||
sub print_frame {
|
||||
my $frame = shift;
|
||||
my $result = $filename;
|
||||
$result .= '|' . $$frame{_pc_};
|
||||
$result .= '|' . $$frame{_func_};
|
||||
for my $var ( keys %$frame ) {
|
||||
$result .= '|' . $var unless( substr($var,0,1) eq '_');
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub start_debugger {
|
||||
if( defined($debugflag) ) {
|
||||
if( $debugflag eq "-debug" ) {
|
||||
{ # make STDOUT unbuffered
|
||||
my $ofh = select STDOUT;
|
||||
$| = 1;
|
||||
select $ofh;
|
||||
}
|
||||
$debugflag = 1;
|
||||
$debugport = shift @ARGV;
|
||||
$debugport2 = shift @ARGV;
|
||||
print "-debug $debugport $debugport2\n";
|
||||
|
||||
my $mainsock = new IO::Socket::INET (LocalHost => '127.0.0.1',
|
||||
LocalPort => $debugport,
|
||||
Listen => 1,
|
||||
Proto => 'tcp',
|
||||
Reuse => 1,
|
||||
);
|
||||
$debugsock = $mainsock->accept();
|
||||
my $set_it = "1";
|
||||
my $ioctl_val = 0x80000000 | (4 << 16) | (ord('f') << 8) | 126;
|
||||
ioctl($debugsock, $ioctl_val, $set_it); #or die "couldn't set nonblocking: $^E";
|
||||
$debugsock->blocking(0);
|
||||
|
||||
my $mainsock2 = new IO::Socket::INET (LocalHost => '127.0.0.1',
|
||||
LocalPort => $debugport2,
|
||||
Listen => 1,
|
||||
Proto => 'tcp',
|
||||
Reuse => 1,
|
||||
);
|
||||
$debugsock2 = $mainsock2->accept();
|
||||
|
||||
print "debug connection accepted\n";
|
||||
} else {
|
||||
$debugflag = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,809 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 Wind River Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.dd.examples.pdavm;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.StringWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PDAVirtualMachine {
|
||||
|
||||
class Stack extends LinkedList<Object> {
|
||||
public Object pop() {
|
||||
return isEmpty() ? 0 : remove(size() - 1);
|
||||
}
|
||||
|
||||
public void push(Object value) {
|
||||
add(value);
|
||||
}
|
||||
}
|
||||
|
||||
class Args {
|
||||
private final String[] fArgs;
|
||||
int next = 0;
|
||||
Args(String[] args) {
|
||||
fArgs = args;
|
||||
}
|
||||
|
||||
String getNextStringArg() {
|
||||
if (fArgs.length > next) {
|
||||
return fArgs[next++];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int getNextIntArg() {
|
||||
String arg = getNextStringArg();
|
||||
try {
|
||||
return Integer.parseInt(arg);
|
||||
} catch (NumberFormatException e) {}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Object getNextIntOrStringArg() {
|
||||
String arg = getNextStringArg();
|
||||
try {
|
||||
return Integer.parseInt(arg);
|
||||
} catch (NumberFormatException e) {}
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
|
||||
/** The push down automata data stack (the data stack). */
|
||||
private final Stack fStack = new Stack();
|
||||
|
||||
/**
|
||||
* The code is stored as an array of strings, each line of
|
||||
* the source file being one entry in the array.
|
||||
*/
|
||||
private String[] fCode;
|
||||
|
||||
/** A mapping of labels to indicies in the code array */
|
||||
private Map<String,Integer> fLabels = new HashMap<String, Integer>();
|
||||
|
||||
/** Each stack frame is a mapping of variable names to values. */
|
||||
class Frame extends LinkedHashMap<String, Object> {
|
||||
/**
|
||||
* The name of the function in this frame
|
||||
*/
|
||||
final String fFunction;
|
||||
|
||||
/**
|
||||
* The current program counter in the frame
|
||||
* the pc points to the next instruction to be executed
|
||||
*/
|
||||
int fPC;
|
||||
|
||||
public Frame(String function, int pc) {
|
||||
fFunction = function;
|
||||
fPC = pc;
|
||||
}
|
||||
}
|
||||
|
||||
/** The stack of stack frames (the control stack) */
|
||||
private final List<Frame> fFrames = new LinkedList<Frame>();
|
||||
|
||||
/** Current stack frame (not includced in fFrames) */
|
||||
private Frame fCurrentFrame = new Frame("main", 0);
|
||||
|
||||
/**
|
||||
* Breakpoints are stored as a boolean for each line of code
|
||||
* if the boolean is true, there is a breakpoint on that line
|
||||
*/
|
||||
private final Map<Integer, Boolean> fBreakpoints = new HashMap<Integer, Boolean>();
|
||||
|
||||
/**
|
||||
* The run flag is true if the VM is running.
|
||||
* If the run flag is false, the VM exits the
|
||||
* next time the main instruction loop runs.
|
||||
*/
|
||||
private boolean fRun = true;
|
||||
|
||||
/**
|
||||
* The suspend flag is true if the VM should suspend
|
||||
* running the program and just listen for debug commands.
|
||||
*/
|
||||
private String fSuspend;
|
||||
|
||||
/** Flag indicating whether the debugger is performing a step. */
|
||||
private boolean fStep = false;
|
||||
|
||||
/** Flag indicating whether the debugger is performing a step return */
|
||||
private boolean fStepReturn = false;
|
||||
|
||||
/** Flag indicating whether the started event was sent. */
|
||||
private boolean fStarted = true;
|
||||
|
||||
/** Name of the pda program being debugged */
|
||||
private final String fFilename;
|
||||
|
||||
/**The command line argument to start a debug session. */
|
||||
private final boolean fDebug;
|
||||
|
||||
/** The port to listen for debug commands on */
|
||||
private final int fCommandPort;
|
||||
|
||||
/** Command socket for receiving debug commands and sending command responses */
|
||||
private Socket fCommandSocket;
|
||||
|
||||
/** Command socket reader */
|
||||
private BufferedReader fCommandReceiveStream;
|
||||
|
||||
/** Command socket write stream. */
|
||||
private OutputStream fCommandResponseStream;
|
||||
|
||||
/** The port to send debug events to */
|
||||
private final int fEventPort;
|
||||
|
||||
/** Event socket */
|
||||
private Socket fEventSocket;
|
||||
|
||||
/** Event socket and write stream. */
|
||||
private OutputStream fEventStream;
|
||||
|
||||
/** The eventstops table holds which events cause suspends and which do not. */
|
||||
private final Map<String, Boolean> fEventStops = new HashMap<String, Boolean>();
|
||||
{
|
||||
fEventStops.put("unimpinstr", false);
|
||||
fEventStops.put("nosuchlabel", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The watchpoints table holds watchpoint information.
|
||||
* variablename_stackframedepth => N
|
||||
* N = 0 is no watch
|
||||
* N = 1 is read watch
|
||||
* N = 2 is write watch
|
||||
* N = 3 is both, etc.
|
||||
*/
|
||||
private final Map<String, Integer> fWatchpoints = new HashMap<String, Integer>();
|
||||
|
||||
public String[] fSavedCode;
|
||||
public Map<String, Integer> fSavedLables;
|
||||
public int fSavedPC;
|
||||
|
||||
public static void main(String[] args) {
|
||||
String programFile = args.length >= 1 ? args[0] : null;
|
||||
if (programFile == null) {
|
||||
System.err.println("Error: No program specified");
|
||||
return;
|
||||
}
|
||||
|
||||
String debugFlag = args.length >= 2 ? args[1] : "";
|
||||
boolean debug = "-debug".equals(debugFlag);
|
||||
int commandPort = 0;
|
||||
int eventPort = 0;
|
||||
|
||||
if (debug) {
|
||||
String commandPortStr = args.length >= 3 ? args[2] : "";
|
||||
try {
|
||||
commandPort = Integer.parseInt(commandPortStr);
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Error: Invalid command port");
|
||||
return;
|
||||
}
|
||||
|
||||
String eventPortStr = args.length >= 4 ? args[3] : "";
|
||||
try {
|
||||
eventPort = Integer.parseInt(eventPortStr);
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Error: Invalid event port");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PDAVirtualMachine pdaVM = null;
|
||||
try {
|
||||
pdaVM = new PDAVirtualMachine(programFile, debug, commandPort, eventPort);
|
||||
pdaVM.startDebugger();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e.toString());
|
||||
return;
|
||||
}
|
||||
pdaVM.run();
|
||||
}
|
||||
|
||||
public PDAVirtualMachine(String inputFile, boolean debug, int commandPort, int eventPort) throws IOException{
|
||||
fFilename = inputFile;
|
||||
|
||||
// Load all the code into memory
|
||||
FileReader fileReader = new FileReader(inputFile);
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
List<String> code = new LinkedList<String>();
|
||||
int c = fileReader.read();
|
||||
while (c != -1) {
|
||||
if (c == '\n') {
|
||||
code.add(stringWriter.toString().trim());
|
||||
stringWriter = new StringWriter();
|
||||
} else {
|
||||
stringWriter.write(c);
|
||||
}
|
||||
c = fileReader.read();
|
||||
}
|
||||
code.add(stringWriter.toString().trim());
|
||||
fCode = code.toArray(new String[code.size()]);
|
||||
|
||||
mapLabels();
|
||||
|
||||
fDebug = debug;
|
||||
fCommandPort = commandPort;
|
||||
fEventPort = eventPort;
|
||||
if (fDebug) {
|
||||
fSuspend = "client";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the labels map
|
||||
*/
|
||||
private void mapLabels() {
|
||||
fLabels = new HashMap<String, Integer>();
|
||||
for (int i = 0; i < fCode.length; i++) {
|
||||
if (fCode[i].length() != 0 && fCode[i].charAt(0) == ':') {
|
||||
fLabels.put(fCode[i].substring(1), i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sendCommandResponse(String response) {
|
||||
try {
|
||||
fCommandResponseStream.write(response.getBytes());
|
||||
fCommandResponseStream.flush();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
private void sendDebugEvent(String event, boolean error) {
|
||||
if (fDebug) {
|
||||
try {
|
||||
fEventStream.write(event.getBytes());
|
||||
fEventStream.write('\n');
|
||||
fEventStream.flush();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e);
|
||||
fRun = false;
|
||||
}
|
||||
} else if (error) {
|
||||
System.err.println("Error: " + event);
|
||||
}
|
||||
}
|
||||
|
||||
private void startDebugger() throws IOException {
|
||||
if (fDebug) {
|
||||
System.out.println("-debug " + fCommandPort + " " + fEventPort);
|
||||
}
|
||||
|
||||
ServerSocket commandServerSocket = new ServerSocket(fCommandPort);
|
||||
fCommandSocket = commandServerSocket.accept();
|
||||
fCommandReceiveStream = new BufferedReader(new InputStreamReader(fCommandSocket.getInputStream()));
|
||||
fCommandResponseStream = new PrintStream(fCommandSocket.getOutputStream());
|
||||
commandServerSocket.close();
|
||||
|
||||
ServerSocket eventServerSocket = new ServerSocket(fEventPort);
|
||||
fEventSocket = eventServerSocket.accept();
|
||||
fEventStream = new PrintStream(fEventSocket.getOutputStream());
|
||||
eventServerSocket.close();
|
||||
|
||||
System.out.println("debug connection accepted");
|
||||
|
||||
fSuspend = "client";
|
||||
sendDebugEvent("started", false);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (fRun) {
|
||||
checkForBreakpoint();
|
||||
if (fSuspend != null) {
|
||||
debugUI();
|
||||
}
|
||||
yieldToDebug();
|
||||
String instruction = fCode[fCurrentFrame.fPC];
|
||||
fCurrentFrame.fPC++;
|
||||
doOneInstruction(instruction);
|
||||
if (fCurrentFrame.fPC > fCode.length) {
|
||||
fRun = false;
|
||||
} else if (fStepReturn) {
|
||||
instruction = fCode[fCurrentFrame.fPC];
|
||||
if ("return".equals(instruction)) {
|
||||
fSuspend = "step";
|
||||
}
|
||||
}
|
||||
}
|
||||
sendDebugEvent("terminated", false);
|
||||
if (fDebug) {
|
||||
try {
|
||||
fCommandReceiveStream.close();
|
||||
fCommandResponseStream.close();
|
||||
fCommandSocket.close();
|
||||
fEventStream.close();
|
||||
fEventSocket.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void doOneInstruction(String instr) {
|
||||
if (instr.startsWith(":")) {
|
||||
// label
|
||||
if (fStep) {
|
||||
fSuspend = "step";
|
||||
}
|
||||
} else if (instr.startsWith("#")) {
|
||||
// comment
|
||||
} else {
|
||||
StringTokenizer tokenizer = new StringTokenizer(instr);
|
||||
String op = tokenizer.nextToken();
|
||||
List<String> tokens = new LinkedList<String>();
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
tokens.add(tokenizer.nextToken());
|
||||
}
|
||||
Args args = new Args(tokens.toArray(new String[tokens.size()]));
|
||||
|
||||
boolean opValid = true;
|
||||
if (op.equals("add")) iAdd(args);
|
||||
else if (op.equals("branch_not_zero")) iBranchNotZero(args);
|
||||
else if (op.equals("call")) iCall(args);
|
||||
else if (op.equals("dec")) iDec(args);
|
||||
else if (op.equals("dup")) iDup(args);
|
||||
else if (op.equals("halt")) iHalt(args);
|
||||
else if (op.equals("output")) iOutput(args);
|
||||
else if (op.equals("pop")) iPop(args);
|
||||
else if (op.equals("push")) iPush(args);
|
||||
else if (op.equals("return")) iReturn(args);
|
||||
else if (op.equals("var")) iVar(args);
|
||||
else if (op.equals("xyzzy")) iInternalEndEval(args);
|
||||
else {
|
||||
opValid = false;
|
||||
}
|
||||
|
||||
if (!opValid) {
|
||||
sendDebugEvent("unimplemented instruction " + op, true);
|
||||
if (fEventStops.get("unimpinstr")) {
|
||||
fSuspend = "event unimpinstr";
|
||||
fCurrentFrame.fPC--;
|
||||
}
|
||||
} else if (fStep) {
|
||||
fSuspend = "step";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForBreakpoint() {
|
||||
if (fDebug) {
|
||||
int pc = fCurrentFrame.fPC;
|
||||
if (!"eval".equals(fSuspend) && fBreakpoints.containsKey(pc) && fBreakpoints.get(pc)) {
|
||||
fSuspend = "breakpoint " + pc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For each instruction, we check the debug co-routine for
|
||||
* control input. If there is input, we process it.
|
||||
*/
|
||||
private void yieldToDebug() {
|
||||
if (fDebug) {
|
||||
String line = "";
|
||||
try {
|
||||
if (fCommandReceiveStream.ready()) {
|
||||
line = fCommandReceiveStream.readLine();
|
||||
processDebugCommand(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e);
|
||||
fRun = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void debugUI() {
|
||||
if (fSuspend == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fStarted) {
|
||||
sendDebugEvent("suspended " + fSuspend, false);
|
||||
} else {
|
||||
fStarted = false;
|
||||
}
|
||||
|
||||
fStep = false;
|
||||
fStepReturn = false;
|
||||
|
||||
while (fSuspend != null) {
|
||||
String line = "";
|
||||
try {
|
||||
line = fCommandReceiveStream.readLine();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error: " + e);
|
||||
fRun = false;
|
||||
return;
|
||||
}
|
||||
processDebugCommand(line);
|
||||
}
|
||||
if (fStep) {
|
||||
sendDebugEvent("resumed step", false);
|
||||
} else {
|
||||
sendDebugEvent("resumed client", false);
|
||||
}
|
||||
}
|
||||
|
||||
private void processDebugCommand(String line) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(line.trim());
|
||||
if (line.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String command = tokenizer.nextToken();
|
||||
List<String> tokens = new LinkedList<String>();
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
tokens.add(tokenizer.nextToken());
|
||||
}
|
||||
Args args = new Args(tokens.toArray(new String[tokens.size()]));
|
||||
|
||||
if ("clear".equals(command)) debugClearBreakpoint(args);
|
||||
else if ("data".equals(command)) debugData();
|
||||
else if ("drop".equals(command)) debugDropFrame();
|
||||
else if ("eval".equals(command)) debugEval(args);
|
||||
else if ("eventstop".equals(command)) debugEventStop(args);
|
||||
else if ("exit".equals(command)) debugExit();
|
||||
else if ("popdata".equals(command)) debugPop();
|
||||
else if ("pushdata".equals(command)) debugPush(args);
|
||||
else if ("resume".equals(command)) debugResume();
|
||||
else if ("set".equals(command)) debugSetBreakpoint(args);
|
||||
else if ("setdata".equals(command)) debugSetData(args);
|
||||
else if ("setvar".equals(command)) debugSetVariable(args);
|
||||
else if ("stack".equals(command)) debugStack();
|
||||
else if ("step".equals(command)) debugStep();
|
||||
else if ("stepreturn".equals(command)) debugStepReturn();
|
||||
else if ("suspend".equals(command)) debugSuspend();
|
||||
else if ("var".equals(command)) debugVar(args);
|
||||
else if ("watch".equals(command)) debugWatch(args);
|
||||
}
|
||||
|
||||
private void debugClearBreakpoint(Args args) {
|
||||
int line = args.getNextIntArg();
|
||||
|
||||
fBreakpoints.put(line, false);
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private static Pattern fPackPattern = Pattern.compile("%([a-fA-F0-9][a-fA-F0-9])");
|
||||
private void debugEval(Args args) {
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(args.getNextStringArg(), "|");
|
||||
tokenizer.countTokens();
|
||||
|
||||
fSavedCode = fCode;
|
||||
int numEvalLines = tokenizer.countTokens();
|
||||
fCode = new String[fSavedCode.length + numEvalLines + 1];
|
||||
System.arraycopy(fSavedCode, 0, fCode, 0, fSavedCode.length);
|
||||
for (int i = 0; i < numEvalLines; i++) {
|
||||
String line = tokenizer.nextToken();
|
||||
StringBuffer lineBuf = new StringBuffer(line.length());
|
||||
Matcher matcher = fPackPattern.matcher(line);
|
||||
int lastMatchEnd = 0;
|
||||
while (matcher.find()) {
|
||||
lineBuf.append(line.substring(lastMatchEnd, matcher.start()));
|
||||
String charCode = line.substring(matcher.start() + 1, matcher.start() + 3);
|
||||
try {
|
||||
lineBuf.append((char)Integer.parseInt(charCode, 16));
|
||||
} catch (NumberFormatException e) {}
|
||||
lastMatchEnd = matcher.end();
|
||||
}
|
||||
if (lastMatchEnd < line.length()) {
|
||||
lineBuf.append(line.substring(lastMatchEnd));
|
||||
}
|
||||
fCode[fSavedCode.length + i] = lineBuf.toString();
|
||||
}
|
||||
fCode[fSavedCode.length + numEvalLines] = "xyzzy";
|
||||
mapLabels();
|
||||
|
||||
fSavedPC = fCurrentFrame.fPC;
|
||||
fCurrentFrame.fPC = fSavedCode.length;
|
||||
|
||||
sendCommandResponse("ok\n");
|
||||
|
||||
fSuspend = null;
|
||||
}
|
||||
|
||||
private void debugData() {
|
||||
StringBuffer result = new StringBuffer();
|
||||
for (Object val : fStack) {
|
||||
result.append(val);
|
||||
result.append('|');
|
||||
}
|
||||
result.append('\n');
|
||||
sendCommandResponse(result.toString());
|
||||
}
|
||||
|
||||
private void debugDropFrame() {
|
||||
if (!fFrames.isEmpty()) {
|
||||
fCurrentFrame = fFrames.remove(fFrames.size() - 1);
|
||||
}
|
||||
fCurrentFrame.fPC--;
|
||||
sendCommandResponse("ok\n");
|
||||
sendDebugEvent( "resumed drop", false );
|
||||
sendDebugEvent( "suspended drop", false );
|
||||
}
|
||||
|
||||
private void debugEventStop(Args args) {
|
||||
String event = args.getNextStringArg();
|
||||
int stop = args.getNextIntArg();
|
||||
fEventStops.put(event, stop > 0);
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugExit() {
|
||||
sendCommandResponse("ok\n");
|
||||
sendDebugEvent( "terminated", false );
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private void debugPop() {
|
||||
fStack.pop();
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugPush(Args args) {
|
||||
Object val = args.getNextIntOrStringArg();
|
||||
fStack.push(val);
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugResume() {
|
||||
fSuspend = null;
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugSetBreakpoint(Args args) {
|
||||
int line = args.getNextIntArg();
|
||||
|
||||
fBreakpoints.put(line, true);
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugSetData(Args args) {
|
||||
int offset = args.getNextIntArg();
|
||||
Object val = args.getNextIntOrStringArg();
|
||||
|
||||
if (offset < fStack.size()) {
|
||||
fStack.set(offset, val);
|
||||
} else {
|
||||
fStack.add(0, val);
|
||||
}
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugSetVariable(Args args) {
|
||||
int sfnumber = args.getNextIntArg();
|
||||
String var = args.getNextStringArg();
|
||||
Object val = args.getNextIntOrStringArg();
|
||||
|
||||
if (sfnumber > fFrames.size()) {
|
||||
fCurrentFrame.put(var, val);
|
||||
} else {
|
||||
fFrames.get(sfnumber).put(var, val);
|
||||
}
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugStack() {
|
||||
StringBuffer result = new StringBuffer();
|
||||
for (Frame frame : fFrames) {
|
||||
result.append(printFrame(frame));
|
||||
result.append('#');
|
||||
}
|
||||
result.append(printFrame(fCurrentFrame));
|
||||
result.append('\n');
|
||||
sendCommandResponse(result.toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The stack frame output is:
|
||||
* frame # frame # frame ...
|
||||
* where each frame is:
|
||||
* filename | line number | function name | var | var | var | var ...
|
||||
*/
|
||||
private String printFrame(Frame frame) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(fFilename);
|
||||
buf.append('|');
|
||||
buf.append(frame.fPC);
|
||||
buf.append('|');
|
||||
buf.append(frame.fFunction);
|
||||
for (String var : frame.keySet()) {
|
||||
buf.append('|');
|
||||
buf.append(var);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void debugStep() {
|
||||
// set suspend to 0 to allow the debug loop to exit back to
|
||||
// the instruction loop and thus run an instruction. However,
|
||||
// we want to come back to the debug loop right away, so the
|
||||
// step flag is set to true which will cause the suspend flag
|
||||
// to get set to true when we get to the next instruction.
|
||||
fStep = true;
|
||||
fSuspend = null;
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugStepReturn() {
|
||||
fStepReturn = true;
|
||||
fSuspend = null;
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugSuspend() {
|
||||
fSuspend = "client";
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void debugVar(Args args) {
|
||||
int sfnumber = args.getNextIntArg();
|
||||
String var = args.getNextStringArg();
|
||||
|
||||
if (sfnumber >= fFrames.size()) {
|
||||
sendCommandResponse(fCurrentFrame.get(var).toString() + "\n");
|
||||
} else {
|
||||
sendCommandResponse(fFrames.get(sfnumber).get(var).toString() + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
private void debugWatch(Args args) {
|
||||
String funcAndVar = args.getNextStringArg();
|
||||
int flags = args.getNextIntArg();
|
||||
fWatchpoints.put(funcAndVar, flags);
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
private void iAdd(Args args) {
|
||||
Object val1 = fStack.pop();
|
||||
Object val2 = fStack.pop();
|
||||
if (val1 instanceof Integer && val2 instanceof Integer) {
|
||||
int intVal1 = ((Integer)val1).intValue();
|
||||
int intVal2 = ((Integer)val2).intValue();
|
||||
fStack.push(intVal1 + intVal2);
|
||||
} else {
|
||||
fStack.push(-1);
|
||||
}
|
||||
}
|
||||
|
||||
private void iBranchNotZero(Args args) {
|
||||
Object val = fStack.pop();
|
||||
if( val instanceof Integer && ((Integer)val).intValue() != 0 ) {
|
||||
String label = args.getNextStringArg();
|
||||
if (fLabels.containsKey(label)) {
|
||||
fCurrentFrame.fPC = fLabels.get(label);
|
||||
} else {
|
||||
sendDebugEvent("no such label " + label, true);
|
||||
if( fEventStops.get("nosuchlabel") ) {
|
||||
fSuspend = "event nosuchlabel";
|
||||
fStack.push(val);
|
||||
fCurrentFrame.fPC--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void iCall(Args args) {
|
||||
String label = args.getNextStringArg();
|
||||
if (fLabels.containsKey(label)) {
|
||||
fFrames.add(fCurrentFrame);
|
||||
fCurrentFrame = new Frame(label, fLabels.get(label));
|
||||
} else {
|
||||
sendDebugEvent("no such label " + label, true);
|
||||
if( fEventStops.get("nosuchlabel") ) {
|
||||
fSuspend = "event nosuchlabel";
|
||||
fCurrentFrame.fPC--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void iDec(Args args) {
|
||||
Object val = fStack.pop();
|
||||
if (val instanceof Integer) {
|
||||
val = new Integer( ((Integer)val).intValue() - 1 );
|
||||
}
|
||||
fStack.push(val);
|
||||
}
|
||||
|
||||
private void iDup(Args args) {
|
||||
Object val = fStack.pop();
|
||||
fStack.push(val);
|
||||
fStack.push(val);
|
||||
}
|
||||
|
||||
private void iHalt(Args args) {
|
||||
fRun = false;
|
||||
}
|
||||
|
||||
private void iOutput(Args args) {
|
||||
System.out.println(fStack.pop());
|
||||
}
|
||||
|
||||
private void iPop(Args args) {
|
||||
String arg = args.getNextStringArg();
|
||||
if (arg.startsWith("$")) {
|
||||
String var = arg.substring(1);
|
||||
fCurrentFrame.put(var, fStack.pop());
|
||||
String key = fCurrentFrame.fFunction + "::" + var;
|
||||
if (fWatchpoints.containsKey(key) && (fWatchpoints.get(key) & 2) != 0) {
|
||||
fSuspend = "watch write " + key;
|
||||
}
|
||||
} else {
|
||||
fStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private void iPush(Args args) {
|
||||
String arg = args.getNextStringArg();
|
||||
if (arg.startsWith("$")) {
|
||||
String var = arg.substring(1);
|
||||
Object val = fCurrentFrame.containsKey(var) ? fCurrentFrame.get(var) : "<undefined>";
|
||||
fStack.push(val);
|
||||
String key = fCurrentFrame.fFunction + "::" + var;
|
||||
if (fWatchpoints.containsKey(key) && (fWatchpoints.get(key) & 1) != 0) {
|
||||
fSuspend = "watch read " + key;
|
||||
}
|
||||
} else {
|
||||
Object val = arg;
|
||||
try {
|
||||
val = Integer.parseInt(arg);
|
||||
} catch (NumberFormatException e) {}
|
||||
fStack.push(val);
|
||||
}
|
||||
}
|
||||
private void iReturn(Args args) {
|
||||
if (!fFrames.isEmpty()) {
|
||||
fCurrentFrame = fFrames.remove(fFrames.size() - 1);
|
||||
}
|
||||
}
|
||||
private void iVar(Args args) {
|
||||
String var = args.getNextStringArg();
|
||||
fCurrentFrame.put(var, 0);
|
||||
}
|
||||
|
||||
private void iInternalEndEval(Args args) {
|
||||
Object result = fStack.pop();
|
||||
fCode = fSavedCode;
|
||||
fLabels = fSavedLables;
|
||||
fCurrentFrame.fPC = fSavedPC;
|
||||
sendDebugEvent("evalresult " + result, false);
|
||||
fSuspend = "eval";
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,448 +0,0 @@
|
|||
#!perl.exe
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use IO::Socket;
|
||||
|
||||
#####################################################################
|
||||
# Copyright (c) 2004-2005 IBM Corporation and others.
|
||||
# All rights reserved. This program and the accompanying materials
|
||||
# are made available under the terms of the Eclipse Public License v1.0
|
||||
# which accompanies this distribution, and is available at
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
# Contributors:
|
||||
# Bjorn Freeman-Benson - initial API and implementation
|
||||
#####################################################################
|
||||
#
|
||||
# This test is designed to run on Windows:
|
||||
#
|
||||
# cd c:\eclipse\workspace\org.eclipse.debug.examples.core
|
||||
# perl pdavm\tests\vmtests.pl
|
||||
#
|
||||
# If the tests fail, they often indicate that by hanging in an
|
||||
# infinite loop. Additionally, the vm under test often becomes
|
||||
# a 100% CPU usage zombie. Use the task manager to kill them.
|
||||
#
|
||||
my $socket1;
|
||||
my $socket2;
|
||||
|
||||
sub expect_output {
|
||||
my $expect = shift;
|
||||
my $line = <PROGRAM_OUTPUT>;
|
||||
chomp($line);
|
||||
return if( $line eq $expect );
|
||||
die "expected output: $expect\nSaw output: $line";
|
||||
}
|
||||
sub expect_output_eof {
|
||||
my $line = <PROGRAM_OUTPUT>;
|
||||
return if( !defined $line );
|
||||
die "expected: EOF on output";
|
||||
}
|
||||
sub send_command {
|
||||
my $string = shift;
|
||||
my $expect = shift;
|
||||
$expect = "ok" if( !defined $expect );
|
||||
#print STDERR "SEND: $string\n";
|
||||
print $socket1 "$string\n";
|
||||
my $result = <$socket1>;
|
||||
chomp($result);
|
||||
#print STDERR "RESULT: $result\n";
|
||||
die "sent: $string\nexpected: $expect\nsaw: $result" if( !($result eq $expect) );
|
||||
}
|
||||
sub expect_event {
|
||||
my $string = shift;
|
||||
my $event = <$socket2>;
|
||||
chomp($event);
|
||||
#print STDERR "EVENT: $event\n";
|
||||
die "expected event: $string\nsaw event: $event" if( !($string eq $event) );
|
||||
}
|
||||
sub setup_sockets {
|
||||
#print STDERR "calling socket 12345\n";
|
||||
$socket1 = IO::Socket::INET->new(
|
||||
Proto => "tcp",
|
||||
PeerAddr => "localhost",
|
||||
PeerPort => "12345",
|
||||
Timeout => 10,
|
||||
)
|
||||
or die "cannot connect to debug socket 12345";
|
||||
#print STDERR "calling socket 12346\n";
|
||||
$socket2 = IO::Socket::INET->new(
|
||||
Proto => "tcp",
|
||||
PeerAddr => "localhost",
|
||||
PeerPort => "12346",
|
||||
Timeout => 10,
|
||||
)
|
||||
or die "cannot connect to debug socket 12346";
|
||||
#print STDERR "done calling sockets\n";
|
||||
}
|
||||
|
||||
sub test2 {
|
||||
print "test2 (common debug commands)..\n";
|
||||
|
||||
my $kidpid;
|
||||
die "can't fork: $!" unless defined($kidpid = fork());
|
||||
if( $kidpid ) {
|
||||
#print STDERR "starting program\n";
|
||||
open PROGRAM_OUTPUT, "perl pdavm/pda.pl pdavm/tests/vmtest2.pda -debug 12345 12346 |";
|
||||
#print STDERR "done starting program\n";
|
||||
expect_output("-debug 12345 12346");
|
||||
expect_output("debug connection accepted");
|
||||
expect_output("10");
|
||||
expect_output_eof();
|
||||
exit 0;
|
||||
} else {
|
||||
setup_sockets();
|
||||
expect_event("started");
|
||||
# test step
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
# test breakpoint
|
||||
send_command("set 4");
|
||||
send_command("data", "6|");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended breakpoint 4");
|
||||
# test data stack
|
||||
send_command("data", "6|7|8|9|");
|
||||
send_command("popdata");
|
||||
send_command("data", "6|7|8|");
|
||||
send_command("pushdata 11");
|
||||
send_command("data", "6|7|8|11|");
|
||||
send_command("setdata 1 2");
|
||||
send_command("data", "6|2|8|11|");
|
||||
# test call stack
|
||||
send_command("set 12");
|
||||
send_command("set 19");
|
||||
send_command("stepreturn");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended breakpoint 12");
|
||||
send_command("clear 19");
|
||||
send_command("stack", "pdavm\\tests\\vmtest2.pda|6|main#pdavm\\tests\\vmtest2.pda|18|sub1|m|n#pdavm\\tests\\vmtest2.pda|12|sub2" );
|
||||
send_command("stepreturn");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended step");
|
||||
send_command("stack", "pdavm\\tests\\vmtest2.pda|6|main#pdavm\\tests\\vmtest2.pda|18|sub1|m|n#pdavm\\tests\\vmtest2.pda|13|sub2" );
|
||||
send_command("stepreturn");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended step");
|
||||
send_command("stack", "pdavm\\tests\\vmtest2.pda|6|main#pdavm\\tests\\vmtest2.pda|22|sub1|m|n" );
|
||||
send_command("set 6");
|
||||
send_command("stepreturn");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended breakpoint 6");
|
||||
# test set and clear
|
||||
send_command("set 27");
|
||||
send_command("set 29");
|
||||
send_command("set 33");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended breakpoint 33");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended breakpoint 27");
|
||||
send_command("clear 33");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended breakpoint 29");
|
||||
# test var and setvar
|
||||
send_command("set 47");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended breakpoint 47");
|
||||
send_command("var 1 b", "4");
|
||||
send_command("var 2 b", "2");
|
||||
send_command("var 1 a", "0");
|
||||
send_command("setvar 1 a 99");
|
||||
send_command("data", "6|2|8|11|27|1|4|");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("var 1 a", "99");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("data", "6|2|8|11|27|1|4|99|");
|
||||
# test exit
|
||||
send_command("exit");
|
||||
expect_event("terminated");
|
||||
}
|
||||
#print STDERR "waiting for child\n";
|
||||
wait();
|
||||
#print STDERR "child joined\n";
|
||||
close PROGRAM_OUTPUT;
|
||||
print "test2..SUCCESS\n";
|
||||
}
|
||||
|
||||
sub test3 {
|
||||
print "test3 (uncaught events)..\n";
|
||||
|
||||
my $kidpid;
|
||||
die "can't fork: $!" unless defined($kidpid = fork());
|
||||
if( $kidpid ) {
|
||||
#print STDERR "starting program\n";
|
||||
open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest3.pda -debug 12345 12346 |";
|
||||
#print STDERR "done starting program\n";
|
||||
expect_output("-debug 12345 12346");
|
||||
expect_output("debug connection accepted");
|
||||
expect_output("10");
|
||||
expect_output_eof();
|
||||
exit 0;
|
||||
} else {
|
||||
setup_sockets();
|
||||
expect_event("started");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("unimplemented instruction foobar");
|
||||
expect_event("no such label zippy");
|
||||
expect_event("terminated");
|
||||
}
|
||||
#print STDERR "waiting for child\n";
|
||||
wait();
|
||||
#print STDERR "child joined\n";
|
||||
close PROGRAM_OUTPUT;
|
||||
print "test3..SUCCESS\n";
|
||||
}
|
||||
sub test4 {
|
||||
print "test4 (caught events)..\n";
|
||||
|
||||
my $kidpid;
|
||||
die "can't fork: $!" unless defined($kidpid = fork());
|
||||
if( $kidpid ) {
|
||||
#print STDERR "starting program\n";
|
||||
open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest3.pda -debug 12345 12346 |";
|
||||
#print STDERR "done starting program\n";
|
||||
expect_output("-debug 12345 12346");
|
||||
expect_output("debug connection accepted");
|
||||
expect_output("10");
|
||||
expect_output_eof();
|
||||
exit 0;
|
||||
} else {
|
||||
setup_sockets();
|
||||
expect_event("started");
|
||||
send_command("eventstop unimpinstr 1");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("unimplemented instruction foobar");
|
||||
expect_event("suspended event unimpinstr");
|
||||
send_command("eventstop unimpinstr 0");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("unimplemented instruction foobar");
|
||||
expect_event("no such label zippy");
|
||||
expect_event("terminated");
|
||||
}
|
||||
#print STDERR "waiting for child\n";
|
||||
wait();
|
||||
#print STDERR "child joined\n";
|
||||
close PROGRAM_OUTPUT;
|
||||
print "test4..SUCCESS\n";
|
||||
}
|
||||
sub test5 {
|
||||
print "test5 (caught events)..\n";
|
||||
|
||||
my $kidpid;
|
||||
die "can't fork: $!" unless defined($kidpid = fork());
|
||||
if( $kidpid ) {
|
||||
#print STDERR "starting program\n";
|
||||
open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest3.pda -debug 12345 12346 |";
|
||||
#print STDERR "done starting program\n";
|
||||
expect_output("-debug 12345 12346");
|
||||
expect_output("debug connection accepted");
|
||||
expect_output("10");
|
||||
expect_output_eof();
|
||||
exit 0;
|
||||
} else {
|
||||
setup_sockets();
|
||||
expect_event("started");
|
||||
send_command("eventstop nosuchlabel 1");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("unimplemented instruction foobar");
|
||||
expect_event("no such label zippy");
|
||||
expect_event("suspended event nosuchlabel");
|
||||
send_command("eventstop nosuchlabel 0");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("no such label zippy");
|
||||
expect_event("terminated");
|
||||
}
|
||||
#print STDERR "waiting for child\n";
|
||||
wait();
|
||||
#print STDERR "child joined\n";
|
||||
close PROGRAM_OUTPUT;
|
||||
print "test5..SUCCESS\n";
|
||||
}
|
||||
sub test6 {
|
||||
print "test6 (watch points)..\n";
|
||||
|
||||
my $kidpid;
|
||||
die "can't fork: $!" unless defined($kidpid = fork());
|
||||
if( $kidpid ) {
|
||||
#print STDERR "starting program\n";
|
||||
open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest6.pda -debug 12345 12346 |";
|
||||
#print STDERR "done starting program\n";
|
||||
expect_output("-debug 12345 12346");
|
||||
expect_output("debug connection accepted");
|
||||
expect_output("8");
|
||||
expect_output_eof();
|
||||
exit 0;
|
||||
} else {
|
||||
setup_sockets();
|
||||
expect_event("started");
|
||||
send_command("watch inner::a 1");
|
||||
send_command("watch main::a 2");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended watch write main::a");
|
||||
send_command("stack", "pdavm\\tests\\vmtest6.pda|4|main|a|b");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended watch read inner::a");
|
||||
send_command("stack", "pdavm\\tests\\vmtest6.pda|10|main|a|b#pdavm\\tests\\vmtest6.pda|25|inner|a|c");
|
||||
send_command("watch inner::a 0");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("terminated");
|
||||
}
|
||||
#print STDERR "waiting for child\n";
|
||||
wait();
|
||||
#print STDERR "child joined\n";
|
||||
close PROGRAM_OUTPUT;
|
||||
print "test6..SUCCESS\n";
|
||||
}
|
||||
sub test7 {
|
||||
print "test7 (eval)..\n";
|
||||
|
||||
my $kidpid;
|
||||
die "can't fork: $!" unless defined($kidpid = fork());
|
||||
if( $kidpid ) {
|
||||
#print STDERR "starting program\n";
|
||||
open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest6.pda -debug 12345 12346 |";
|
||||
#print STDERR "done starting program\n";
|
||||
expect_output("-debug 12345 12346");
|
||||
expect_output("debug connection accepted");
|
||||
expect_output("8");
|
||||
expect_output_eof();
|
||||
exit 0;
|
||||
} else {
|
||||
setup_sockets();
|
||||
expect_event("started");
|
||||
send_command("set 25");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("suspended breakpoint 25");
|
||||
#
|
||||
send_command("eval push%204|push%205|add");
|
||||
expect_event("resumed client");
|
||||
expect_event("evalresult 9");
|
||||
expect_event("suspended eval");
|
||||
#
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("stack", "pdavm\\tests\\vmtest6.pda|10|main|a|b#pdavm\\tests\\vmtest6.pda|26|inner|a|c");
|
||||
send_command("data", "4|4|");
|
||||
send_command("eval call%20other");
|
||||
expect_event("resumed client");
|
||||
expect_event("evalresult 15");
|
||||
expect_event("suspended eval");
|
||||
send_command("stack", "pdavm\\tests\\vmtest6.pda|10|main|a|b#pdavm\\tests\\vmtest6.pda|26|inner|a|c");
|
||||
send_command("data", "4|4|");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("terminated");
|
||||
}
|
||||
#print STDERR "waiting for child\n";
|
||||
wait();
|
||||
#print STDERR "child joined\n";
|
||||
close PROGRAM_OUTPUT;
|
||||
print "test7..SUCCESS\n";
|
||||
}
|
||||
sub test1 {
|
||||
print "test1 (normal run mode)..\n";
|
||||
open PROGRAM_OUTPUT, "perl pdavm/pda.pl samples/example.pda |" or die $!;
|
||||
expect_output("\"hello\"");
|
||||
expect_output("\"barfoo\"");
|
||||
expect_output("\"first\"");
|
||||
expect_output("\"second\"");
|
||||
expect_output("12");
|
||||
expect_output("11");
|
||||
expect_output("10");
|
||||
expect_output("\"barfoo\"");
|
||||
expect_output("\"first\"");
|
||||
expect_output("\"second\"");
|
||||
expect_output("\"end\"");
|
||||
expect_output_eof();
|
||||
print "test1..SUCCESS\n";
|
||||
}
|
||||
sub test8 {
|
||||
print "test8 (drop to frame)..\n";
|
||||
|
||||
my $kidpid;
|
||||
die "can't fork: $!" unless defined($kidpid = fork());
|
||||
if( $kidpid ) {
|
||||
#print STDERR "starting program\n";
|
||||
open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest8.pda -debug 12345 12346 |";
|
||||
#print STDERR "done starting program\n";
|
||||
expect_output("-debug 12345 12346");
|
||||
expect_output("debug connection accepted");
|
||||
expect_output("1");
|
||||
expect_output_eof();
|
||||
exit 0;
|
||||
} else {
|
||||
setup_sockets();
|
||||
expect_event("started");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("stack", "pdavm\\tests\\vmtest8.pda|2|main|a#pdavm\\tests\\vmtest8.pda|8|inner|b#pdavm\\tests\\vmtest8.pda|12|inner2|c");
|
||||
send_command("drop");
|
||||
expect_event("suspended drop");
|
||||
send_command("stack", "pdavm\\tests\\vmtest8.pda|2|main|a#pdavm\\tests\\vmtest8.pda|7|inner|b");
|
||||
send_command("step");
|
||||
expect_event("resumed step");
|
||||
expect_event("suspended step");
|
||||
send_command("stack", "pdavm\\tests\\vmtest8.pda|2|main|a#pdavm\\tests\\vmtest8.pda|8|inner|b#pdavm\\tests\\vmtest8.pda|10|inner2");
|
||||
send_command("resume");
|
||||
expect_event("resumed client");
|
||||
expect_event("terminated");
|
||||
}
|
||||
#print STDERR "waiting for child\n";
|
||||
wait();
|
||||
#print STDERR "child joined\n";
|
||||
close PROGRAM_OUTPUT;
|
||||
print "test8..SUCCESS\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Run the tests
|
||||
#
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
test7();
|
||||
test8();
|
||||
print "All tests complete\n";
|
|
@ -27,8 +27,6 @@ import org.eclipse.core.runtime.IProgressMonitor;
|
|||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.variables.IValueVariable;
|
||||
import org.eclipse.core.variables.VariablesPlugin;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.Query;
|
||||
import org.eclipse.dd.examples.pda.PDAPlugin;
|
||||
|
@ -118,32 +116,24 @@ public class PDALaunchDelegate extends LaunchConfigurationDelegate {
|
|||
private void launchProcess(ILaunch launch, String program, int requestPort, int eventPort) throws CoreException {
|
||||
List<String> commandList = new ArrayList<String>();
|
||||
|
||||
// Find Perl executable
|
||||
IValueVariable perl = VariablesPlugin.getDefault().getStringVariableManager().getValueVariable(PDAPlugin.VARIALBE_PERL_EXECUTABLE);
|
||||
if (perl == null) {
|
||||
abort("Perl executable location undefined. Check value of ${dsfPerlExecutable}.", null);
|
||||
}
|
||||
String path = perl.getValue();
|
||||
if (path == null) {
|
||||
abort("Perl executable location unspecified. Check value of ${dsfPerlExecutable}.", null);
|
||||
}
|
||||
File exe = new File(path);
|
||||
// Get Java VM path
|
||||
String javaVMHome = System.getProperty("java.home");
|
||||
String javaVMExec = javaVMHome + File.separatorChar + "bin" + File.separatorChar + "java";
|
||||
File exe = new File(javaVMExec);
|
||||
if (!exe.exists()) {
|
||||
abort(MessageFormat.format("Specified Perl executable {0} does not exist. Check value of $dsfPerlExecutable.", new Object[]{path}), null);
|
||||
abort(MessageFormat.format("Specified java VM executable {0} does not exist.", new Object[]{javaVMExec}), null);
|
||||
}
|
||||
commandList.add(path);
|
||||
|
||||
// Add PDA VM
|
||||
File vm = PDAPlugin.getFileInPlugin(new Path("pdavm/pda.pl"));
|
||||
if (vm == null) {
|
||||
abort("Missing PDA VM", null);
|
||||
}
|
||||
commandList.add(vm.getAbsolutePath());
|
||||
commandList.add(javaVMExec);
|
||||
|
||||
commandList.add("-cp");
|
||||
commandList.add(File.pathSeparator + PDAPlugin.getFileInPlugin(new Path("bin")));
|
||||
|
||||
commandList.add("org.eclipse.dd.examples.pdavm.PDAVirtualMachine");
|
||||
|
||||
// Add PDA program
|
||||
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(program));
|
||||
if (!file.exists()) {
|
||||
abort(MessageFormat.format("Perl program {0} does not exist.", new Object[] {file.getFullPath().toString()}), null);
|
||||
abort(MessageFormat.format("PDA program {0} does not exist.", new Object[] {file.getFullPath().toString()}), null);
|
||||
}
|
||||
|
||||
commandList.add(file.getLocation().toOSString());
|
||||
|
@ -158,7 +148,7 @@ public class PDALaunchDelegate extends LaunchConfigurationDelegate {
|
|||
Process process = DebugPlugin.exec(commandLine, null);
|
||||
|
||||
// Create a debug platform process object and add it to the launch.
|
||||
DebugPlugin.newProcess(launch, process, path);
|
||||
DebugPlugin.newProcess(launch, process, javaVMHome);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,15 +57,15 @@ public class Test2 extends CommandControlTestsBase {
|
|||
expectEvent("resumed client");
|
||||
expectEvent("suspended breakpoint 12");
|
||||
sendCommand("clear 19");
|
||||
sendCommand("stack", fProgram + "|6|main#" + fProgram + "|18|sub1|n|m#" + fProgram + "|12|sub2" );
|
||||
sendCommand("stack", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|12|sub2" );
|
||||
sendCommand("stepreturn");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("stack", fProgram + "|6|main#" + fProgram + "|18|sub1|n|m#" + fProgram + "|13|sub2" );
|
||||
sendCommand("stack", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|13|sub2" );
|
||||
sendCommand("stepreturn");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("stack", fProgram + "|6|main#" + fProgram + "|22|sub1|n|m" );
|
||||
sendCommand("stack", fProgram + "|6|main#" + fProgram + "|22|sub1|m|n" );
|
||||
sendCommand("set 6");
|
||||
sendCommand("stepreturn");
|
||||
expectEvent("resumed client");
|
||||
|
|
|
@ -41,7 +41,7 @@ public class Test6 extends CommandControlTestsBase {
|
|||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended watch read inner::a");
|
||||
sendCommand("stack", fProgram + "|10|main|a|b#" + fProgram + "|25|inner|c|a");
|
||||
sendCommand("stack", fProgram + "|10|main|a|b#" + fProgram + "|25|inner|a|c");
|
||||
sendCommand("watch inner::a 0");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
|
@ -64,13 +64,13 @@ public class Test6 extends CommandControlTestsBase {
|
|||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("stack", fProgram + "|10|main|a|b#" + fProgram + "|26|inner|c|a");
|
||||
sendCommand("stack", fProgram + "|10|main|a|b#" + fProgram + "|26|inner|a|c");
|
||||
sendCommand("data", "4|4|");
|
||||
sendCommand("eval call%20other");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("evalresult 15");
|
||||
expectEvent("suspended eval");
|
||||
sendCommand("stack", fProgram + "|10|main|a|b#" + fProgram + "|26|inner|c|a");
|
||||
sendCommand("stack", fProgram + "|10|main|a|b#" + fProgram + "|26|inner|a|c");
|
||||
sendCommand("data", "4|4|");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
|
|
|
@ -20,9 +20,9 @@ import java.util.List;
|
|||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.core.variables.IValueVariable;
|
||||
import org.eclipse.core.variables.VariablesPlugin;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.examples.pda.PDAPlugin;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
|
||||
|
@ -30,19 +30,6 @@ import org.eclipse.debug.core.DebugPlugin;
|
|||
*
|
||||
*/
|
||||
public class Launching {
|
||||
public static String getPerlPath() {
|
||||
// Perl executable
|
||||
IValueVariable perl = VariablesPlugin.getDefault().getStringVariableManager().getValueVariable(PDAPlugin.VARIALBE_PERL_EXECUTABLE);
|
||||
Assert.assertNotNull("Perl executable location undefined. Check value of ${dsfPerlExecutable}.", perl);
|
||||
|
||||
String path = perl.getValue();
|
||||
Assert.assertNotNull("Perl executable location undefined. Check value of ${dsfPerlExecutable}.", path);
|
||||
Assert.assertTrue(
|
||||
MessageFormat.format("Specified Perl executable {0} does not exist. Check value of $dsfPerlExecutable.", new Object[]{path}),
|
||||
new File(path).exists());
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static Process launchPDA(String pdaProgram, int requestPort, int eventPort) throws CoreException {
|
||||
Assert.assertTrue("Invalid request port", requestPort > 0);
|
||||
|
@ -50,11 +37,21 @@ public class Launching {
|
|||
|
||||
List<String> commandList = new ArrayList<String>();
|
||||
|
||||
commandList.add(getPerlPath());
|
||||
|
||||
File pdaVM = PDAPlugin.getFileInPlugin(new Path("pdavm/pda.pl"));
|
||||
Assert.assertNotNull("File " + pdaVM + " not found in plugin.", pdaVM);
|
||||
commandList.add(pdaVM.getAbsolutePath());
|
||||
// Get Java VM path
|
||||
String javaVMHome = System.getProperty("java.home");
|
||||
String javaVMExec = javaVMHome + File.separatorChar + "bin" + File.separatorChar + "java";
|
||||
File exe = new File(javaVMExec);
|
||||
if (!exe.exists()) {
|
||||
throw new CoreException(new Status(
|
||||
IStatus.ERROR, PDAPlugin.PLUGIN_ID, 0,
|
||||
MessageFormat.format("Specified java VM executable {0} does not exist.", new Object[]{javaVMExec}), null));
|
||||
}
|
||||
commandList.add(javaVMExec);
|
||||
|
||||
commandList.add("-cp");
|
||||
commandList.add(File.pathSeparator + PDAPlugin.getFileInPlugin(new Path("bin")));
|
||||
|
||||
commandList.add("org.eclipse.dd.examples.pdavm.PDAVirtualMachine");
|
||||
|
||||
commandList.add(pdaProgram);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue