1
0
Fork 0
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:
Pawel Piech 2008-06-10 16:33:27 +00:00
parent ce33d6a9cf
commit a69b4955f0
8 changed files with 846 additions and 1170 deletions

View file

@ -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"/>

View file

@ -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;
}
}
}

View file

@ -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";
}
}

View file

@ -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";

View file

@ -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);
}
/**

View file

@ -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");

View file

@ -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");

View file

@ -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);