Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarin Wright2007-10-09 21:03:43 +0000
committerDarin Wright2007-10-09 21:03:43 +0000
commit07f1e796ae8a43d56d3010bd3e85063b318a0ad3 (patch)
tree35f7610d1674c644f814f9a8b8bb8a858feffd39 /org.eclipse.debug.examples.core
parent50371b66ac350e9f64991048058ad251a191c90d (diff)
downloadeclipse.platform.debug-07f1e796ae8a43d56d3010bd3e85063b318a0ad3.tar.gz
eclipse.platform.debug-07f1e796ae8a43d56d3010bd3e85063b318a0ad3.tar.xz
eclipse.platform.debug-07f1e796ae8a43d56d3010bd3e85063b318a0ad3.zip
release of original PDA code base
Diffstat (limited to 'org.eclipse.debug.examples.core')
-rw-r--r--org.eclipse.debug.examples.core/.classpath7
-rw-r--r--org.eclipse.debug.examples.core/.cvsignore1
-rw-r--r--org.eclipse.debug.examples.core/.project28
-rw-r--r--org.eclipse.debug.examples.core/.settings/org.eclipse.jdt.core.prefs47
-rw-r--r--org.eclipse.debug.examples.core/META-INF/MANIFEST.MF17
-rw-r--r--org.eclipse.debug.examples.core/about.html28
-rw-r--r--org.eclipse.debug.examples.core/build.properties18
-rw-r--r--org.eclipse.debug.examples.core/pdavm/pda.pl672
-rw-r--r--org.eclipse.debug.examples.core/pdavm/tests/vmtest2.pda48
-rw-r--r--org.eclipse.debug.examples.core/pdavm/tests/vmtest3.pda11
-rw-r--r--org.eclipse.debug.examples.core/pdavm/tests/vmtest6.pda31
-rw-r--r--org.eclipse.debug.examples.core/pdavm/tests/vmtest8.pda14
-rw-r--r--org.eclipse.debug.examples.core/pdavm/tests/vmtests.pl448
-rw-r--r--org.eclipse.debug.examples.core/plugin.xml84
-rw-r--r--org.eclipse.debug.examples.core/samples/counter.pda11
-rw-r--r--org.eclipse.debug.examples.core/samples/drop.pda12
-rw-r--r--org.eclipse.debug.examples.core/samples/example.pda35
-rw-r--r--org.eclipse.debug.examples.core/samples/fibonacci.pda32
-rw-r--r--org.eclipse.debug.examples.core/samples/structures.pda8
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/DebugCorePlugin.java128
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java202
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDARunToLineBreakpoint.java70
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java222
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java151
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java62
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java50
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArrayEntry.java98
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java117
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java525
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java251
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java47
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java426
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java79
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java107
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/WordStructureDelegate.java53
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourceLookupDirector.java32
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourceLookupParticipant.java38
-rw-r--r--org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourcePathComputerDelegate.java65
38 files changed, 4275 insertions, 0 deletions
diff --git a/org.eclipse.debug.examples.core/.classpath b/org.eclipse.debug.examples.core/.classpath
new file mode 100644
index 000000000..b7464f3ca
--- /dev/null
+++ b/org.eclipse.debug.examples.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.debug.examples.core/.cvsignore b/org.eclipse.debug.examples.core/.cvsignore
new file mode 100644
index 000000000..ba077a403
--- /dev/null
+++ b/org.eclipse.debug.examples.core/.cvsignore
@@ -0,0 +1 @@
+bin
diff --git a/org.eclipse.debug.examples.core/.project b/org.eclipse.debug.examples.core/.project
new file mode 100644
index 000000000..99d835c1a
--- /dev/null
+++ b/org.eclipse.debug.examples.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>example.debug.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.debug.examples.core/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.debug.examples.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..d6de6c150
--- /dev/null
+++ b/org.eclipse.debug.examples.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,47 @@
+#Mon Jan 24 20:23:34 CST 2005
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.3
diff --git a/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF b/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..0de72ed97
--- /dev/null
+++ b/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF
@@ -0,0 +1,17 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Example Debug Core Plug-in
+Bundle-SymbolicName: org.eclipse.debug.examples.core;singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.debug.examples.core.pda.DebugCorePlugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.core.variables,
+ org.eclipse.debug.core
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.debug.examples.core.pda,
+ org.eclipse.debug.examples.core.pda.breakpoints,
+ org.eclipse.debug.examples.core.pda.launcher,
+ org.eclipse.debug.examples.core.pda.model,
+ org.eclipse.debug.examples.core.pda.sourcelookup
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/org.eclipse.debug.examples.core/about.html b/org.eclipse.debug.examples.core/about.html
new file mode 100644
index 000000000..460233046
--- /dev/null
+++ b/org.eclipse.debug.examples.core/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 2, 2006</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.debug.examples.core/build.properties b/org.eclipse.debug.examples.core/build.properties
new file mode 100644
index 000000000..bc583f953
--- /dev/null
+++ b/org.eclipse.debug.examples.core/build.properties
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright (c) 2005, 2007 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:
+# IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+ pdavm/,\
+ examples/,\
+ META-INF/,\
+ about.html,\
+ .
diff --git a/org.eclipse.debug.examples.core/pdavm/pda.pl b/org.eclipse.debug.examples.core/pdavm/pda.pl
new file mode 100644
index 000000000..82829e460
--- /dev/null
+++ b/org.eclipse.debug.examples.core/pdavm/pda.pl
@@ -0,0 +1,672 @@
+#!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";
+
+ 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;
+ }
+ }
+}
diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtest2.pda b/org.eclipse.debug.examples.core/pdavm/tests/vmtest2.pda
new file mode 100644
index 000000000..95a35f04f
--- /dev/null
+++ b/org.eclipse.debug.examples.core/pdavm/tests/vmtest2.pda
@@ -0,0 +1,48 @@
+push 6
+push 7
+push 8
+push 9
+push 10
+call sub1
+output
+call sub3
+call sub5
+push 3
+halt
+:sub2
+push 27
+return
+:sub1
+var m
+var n
+call sub2
+pop $n
+pop $m
+push $n
+push $m
+return
+# zero-based line 23
+:sub3
+push 1
+call sub4
+push 2
+call sub4
+push 3
+return
+:sub4
+push 4
+return
+# zero-based line 34
+:sub5
+var a
+var b
+var c
+pop $c
+pop $b
+call sub6
+push $a
+return
+:sub6
+var b
+pop $b
+return
diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtest3.pda b/org.eclipse.debug.examples.core/pdavm/tests/vmtest3.pda
new file mode 100644
index 000000000..a9fcfc2a8
--- /dev/null
+++ b/org.eclipse.debug.examples.core/pdavm/tests/vmtest3.pda
@@ -0,0 +1,11 @@
+push 1
+push 2
+push 3
+foobar swish
+push 4
+add
+add
+call zippy
+add
+output
+halt
diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtest6.pda b/org.eclipse.debug.examples.core/pdavm/tests/vmtest6.pda
new file mode 100644
index 000000000..d90a960cf
--- /dev/null
+++ b/org.eclipse.debug.examples.core/pdavm/tests/vmtest6.pda
@@ -0,0 +1,31 @@
+var a
+var b
+push 1
+pop $a
+push 2
+pop $b
+push 3
+push 4
+#
+call inner
+#
+push $a
+push 2
+add
+pop $b
+output
+#
+halt
+#
+:inner
+var a
+var c
+pop $a
+pop $c
+push $a
+push $a
+add
+return
+:other
+push 15
+return \ No newline at end of file
diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtest8.pda b/org.eclipse.debug.examples.core/pdavm/tests/vmtest8.pda
new file mode 100644
index 000000000..7729409c2
--- /dev/null
+++ b/org.eclipse.debug.examples.core/pdavm/tests/vmtest8.pda
@@ -0,0 +1,14 @@
+var a
+call inner
+push 1
+output
+halt
+:inner
+var b
+call inner2
+push 2
+return
+:inner2
+var c
+push 3
+return
diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtests.pl b/org.eclipse.debug.examples.core/pdavm/tests/vmtests.pl
new file mode 100644
index 000000000..0e2f8a358
--- /dev/null
+++ b/org.eclipse.debug.examples.core/pdavm/tests/vmtests.pl
@@ -0,0 +1,448 @@
+#!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 examples\\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"; \ No newline at end of file
diff --git a/org.eclipse.debug.examples.core/plugin.xml b/org.eclipse.debug.examples.core/plugin.xml
new file mode 100644
index 000000000..0133be329
--- /dev/null
+++ b/org.eclipse.debug.examples.core/plugin.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension
+ point="org.eclipse.core.variables.valueVariables">
+ <variable
+ description="Path to Perl executable in the local file system"
+ name="perlExecutable"
+ initialValue="c:\perl\bin\perl.exe"/>
+ </extension>
+<!--#ifdef ex1-->
+<!--#else-->
+ <extension
+ point="org.eclipse.debug.core.launchConfigurationTypes">
+ <launchConfigurationType
+ sourceLocatorId="pda.sourceLocator"
+ delegate="org.eclipse.debug.examples.core.pda.launcher.PDALaunchDelegate"
+ sourcePathComputerId="pda.sourcePathComputer"
+ name="PDA Application"
+ id="pda.launchType"
+ modes="run, debug"/>
+ </extension>
+<!--#endif-->
+
+<!--#ifdef ex4-->
+<!--#else-->
+ <extension
+ point="org.eclipse.debug.core.sourceLocators">
+ <sourceLocator
+ class="org.eclipse.debug.examples.core.pda.sourcelookup.PDASourceLookupDirector"
+ name="PDA Source Locator"
+ id="pda.sourceLocator"/>
+ </extension>
+ <extension
+ point="org.eclipse.debug.core.sourcePathComputers">
+ <sourcePathComputer
+ class="org.eclipse.debug.examples.core.pda.sourcelookup.PDASourcePathComputerDelegate"
+ id="pda.sourcePathComputer"/>
+ </extension>
+<!--#endif-->
+
+<!--#ifdef ex3-->
+<!--#else-->
+ <extension
+ point="org.eclipse.debug.core.breakpoints">
+ <breakpoint
+ class="org.eclipse.debug.examples.core.pda.breakpoints.PDALineBreakpoint"
+ name="PDA Line Breakpoints"
+ markerType="org.eclipse.debug.examples.core.pda.markerType.lineBreakpoint"
+ id="pda.lineBreakpoint"/>
+ <breakpoint
+ class="org.eclipse.debug.examples.core.pda.breakpoints.PDAWatchpoint"
+ name="PDA Watchpoints"
+ markerType="org.eclipse.debug.examples.core.pda.markerType.watchpoint"
+ id="pda.watchpoint"/>
+ </extension>
+ <extension
+ id="pda.markerType.lineBreakpoint"
+ name="PDA Line Breakpoint Marker"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.debug.core.lineBreakpointMarker"/>
+ <persistent value="true"/>
+ </extension>
+ <extension
+ id="pda.markerType.watchpoint"
+ name="PDA Watchpoint Marker"
+ point="org.eclipse.core.resources.markers">
+ <super type="org.eclipse.debug.examples.core.pda.markerType.lineBreakpoint"/>
+ <persistent value="true"/>
+ </extension>
+<!--#endif-->
+
+<!--#ifdef ex6-->
+<!--#else-->
+ <extension
+ point="org.eclipse.debug.core.logicalStructureTypes">
+ <logicalStructureType
+ class="org.eclipse.debug.examples.core.pda.model.WordStructureDelegate"
+ description="Words"
+ id="pda.wordStructure"
+ modelIdentifier="pda.debugModel"/>
+ </extension>
+<!--#endif-->
+</plugin>
diff --git a/org.eclipse.debug.examples.core/samples/counter.pda b/org.eclipse.debug.examples.core/samples/counter.pda
new file mode 100644
index 000000000..9b2b73100
--- /dev/null
+++ b/org.eclipse.debug.examples.core/samples/counter.pda
@@ -0,0 +1,11 @@
+push 0
+:main
+var n
+pop $n
+push $n
+push 1
+add
+dup
+push $n
+output
+branch_not_zero main \ No newline at end of file
diff --git a/org.eclipse.debug.examples.core/samples/drop.pda b/org.eclipse.debug.examples.core/samples/drop.pda
new file mode 100644
index 000000000..84f60fee0
--- /dev/null
+++ b/org.eclipse.debug.examples.core/samples/drop.pda
@@ -0,0 +1,12 @@
+call one
+:one
+call two
+:two
+call three
+:three
+call four
+:four
+push DONE
+output
+
+
diff --git a/org.eclipse.debug.examples.core/samples/example.pda b/org.eclipse.debug.examples.core/samples/example.pda
new file mode 100644
index 000000000..a95886358
--- /dev/null
+++ b/org.eclipse.debug.examples.core/samples/example.pda
@@ -0,0 +1,35 @@
+push "hello"
+output
+call foobar
+push 3
+:label
+dup
+push 4
+push 5
+add
+add
+output
+dec
+dup
+branch_not_zero label
+call foobar
+push "end"
+output
+halt
+:foobar
+var a
+var b
+call barfoo
+push "first"
+push "second"
+pop $a
+pop $b
+push $a
+push $b
+output
+output
+return
+:barfoo
+push "barfoo"
+output
+return
diff --git a/org.eclipse.debug.examples.core/samples/fibonacci.pda b/org.eclipse.debug.examples.core/samples/fibonacci.pda
new file mode 100644
index 000000000..e39595a98
--- /dev/null
+++ b/org.eclipse.debug.examples.core/samples/fibonacci.pda
@@ -0,0 +1,32 @@
+push 6
+call fibonacci
+output
+halt
+#
+# f(n) = f(n-1) + f(n-2)
+# f(0) = 1
+# f(1) = 1
+#
+:fibonacci
+var n
+pop $n
+push $n
+branch_not_zero gt0
+push 1
+return
+:gt0
+push $n
+dec
+branch_not_zero gt1
+push 1
+return
+:gt1
+push $n
+dec
+call fibonacci
+push $n
+dec
+dec
+call fibonacci
+add
+return
diff --git a/org.eclipse.debug.examples.core/samples/structures.pda b/org.eclipse.debug.examples.core/samples/structures.pda
new file mode 100644
index 000000000..97858b079
--- /dev/null
+++ b/org.eclipse.debug.examples.core/samples/structures.pda
@@ -0,0 +1,8 @@
+push one two three
+push 1 2 3
+var x
+var y
+pop $x
+pop $y
+push Done
+output \ No newline at end of file
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/DebugCorePlugin.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/DebugCorePlugin.java
new file mode 100644
index 000000000..f58fe8613
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/DebugCorePlugin.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class DebugCorePlugin extends Plugin {
+ //The shared instance.
+ private static DebugCorePlugin plugin;
+ //Resource bundle.
+ private ResourceBundle resourceBundle;
+
+ /**
+ * Unique identifier for the PDA debug model (value
+ * <code>pda.debugModel</code>).
+ */
+ public static final String ID_PDA_DEBUG_MODEL = "pda.debugModel";
+
+ /**
+ * Name of the string substitution variable that resolves to the
+ * location of a local Perl executable (value <code>perlExecutable</code>).
+ */
+ public static final String VARIALBE_PERL_EXECUTABLE = "perlExecutable";
+ /**
+ * Launch configuration attribute key. Value is a path to a perl
+ * program. The path is a string representing a full path
+ * to a perl program in the workspace.
+ */
+ public static final String ATTR_PDA_PROGRAM = ID_PDA_DEBUG_MODEL + ".ATTR_PDA_PROGRAM";
+
+ /**
+ * Identifier for the PDA launch configuration type
+ * (value <code>pda.launchType</code>)
+ */
+ public static final String ID_PDA_LAUNCH_CONFIGURATION_TYPE = "pda.launchType";
+
+ /**
+ * The constructor.
+ */
+ public DebugCorePlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * This method is called upon plug-in activation
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /**
+ * This method is called when the plug-in is stopped
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ resourceBundle = null;
+ }
+
+ /**
+ * Returns the shared instance.
+ */
+ public static DebugCorePlugin getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns the string from the plugin's resource bundle,
+ * or 'key' if not found.
+ */
+ public static String getResourceString(String key) {
+ ResourceBundle bundle = DebugCorePlugin.getDefault().getResourceBundle();
+ try {
+ return (bundle != null) ? bundle.getString(key) : key;
+ } catch (MissingResourceException e) {
+ return key;
+ }
+ }
+
+ /**
+ * Returns the plugin's resource bundle,
+ */
+ public ResourceBundle getResourceBundle() {
+ try {
+ if (resourceBundle == null)
+ resourceBundle = ResourceBundle.getBundle("org.eclipse.debug.examples.core.pda.DebugCorePluginResources");
+ } catch (MissingResourceException x) {
+ resourceBundle = null;
+ }
+ return resourceBundle;
+ }
+
+ /**
+ * Return a <code>java.io.File</code> object that corresponds to the specified
+ * <code>IPath</code> in the plugin directory, or <code>null</code> if none.
+ */
+ public static File getFileInPlugin(IPath path) {
+ try {
+ URL installURL =
+ new URL(getDefault().getDescriptor().getInstallURL(), path.toString());
+ URL localURL = Platform.asLocalURL(installURL);
+ return new File(localURL.getFile());
+ } catch (IOException ioe) {
+ return null;
+ }
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java
new file mode 100644
index 000000000..24062b0b5
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.breakpoints;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.LineBreakpoint;
+import org.eclipse.debug.examples.core.pda.DebugCorePlugin;
+import org.eclipse.debug.examples.core.pda.model.IPDAEventListener;
+import org.eclipse.debug.examples.core.pda.model.PDADebugTarget;
+import org.eclipse.debug.examples.core.pda.model.PDAThread;
+
+
+/**
+ * PDA line breakpoint
+ */
+public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListener {
+
+ // target currently installed in
+ private PDADebugTarget fTarget;
+
+ /**
+ * Default constructor is required for the breakpoint manager
+ * to re-create persisted breakpoints. After instantiating a breakpoint,
+ * the <code>setMarker(...)</code> method is called to restore
+ * this breakpoint's attributes.
+ */
+ public PDALineBreakpoint() {
+ }
+
+ /**
+ * Constructs a line breakpoint on the given resource at the given
+ * line number. The line number is 1-based (i.e. the first line of a
+ * file is line number 1). The PDA VM uses 0-based line numbers,
+ * so this line number translation is done at breakpoint install time.
+ *
+ * @param resource file on which to set the breakpoint
+ * @param lineNumber 1-based line number of the breakpoint
+ * @throws CoreException if unable to create the breakpoint
+ */
+ public PDALineBreakpoint(final IResource resource, final int lineNumber) throws CoreException {
+ IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IMarker marker = resource.createMarker("org.eclipse.debug.examples.core.pda.markerType.lineBreakpoint");
+ setMarker(marker);
+ marker.setAttribute(IBreakpoint.ENABLED, Boolean.TRUE);
+ marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+ marker.setAttribute(IBreakpoint.ID, getModelIdentifier());
+ marker.setAttribute(IMarker.MESSAGE, "Line Breakpoint: " + resource.getName() + " [line: " + lineNumber + "]");
+ }
+ };
+ run(getMarkerRule(resource), runnable);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IBreakpoint#getModelIdentifier()
+ */
+ public String getModelIdentifier() {
+ return DebugCorePlugin.ID_PDA_DEBUG_MODEL;
+ }
+
+ /**
+ * Returns whether this breakpoint is a run-to-line breakpoint
+ *
+ * @return whether this breakpoint is a run-to-line breakpoint
+ */
+ public boolean isRunToLineBreakpoint() {
+ return false;
+ }
+
+ /**
+ * Installs this breakpoint in the given interprettor.
+ * Registeres this breakpoint as an event listener in the
+ * given target and creates the breakpoint specific request.
+ *
+ * @param target PDA interprettor
+ * @throws CoreException if installation fails
+ */
+ public void install(PDADebugTarget target) throws CoreException {
+ fTarget = target;
+ target.addEventListener(this);
+ createRequest(target);
+ }
+
+ /**
+ * Create the breakpoint specific request in the target. Subclasses
+ * should override.
+ *
+ * @param target PDA interprettor
+ * @throws CoreException if request creation fails
+ */
+ protected void createRequest(PDADebugTarget target) throws CoreException {
+ //#ifdef ex3
+//# // TODO: Exercise 3 - create breakpoint request in interpreter
+ //#else
+ target.sendRequest("set " + (getLineNumber() - 1));
+ //#endif
+ }
+
+ /**
+ * Removes this breakpoint's event request from the target. Subclasses
+ * should override.
+ *
+ * @param target PDA interprettor
+ * @throws CoreException if clearing the request fails
+ */
+ protected void clearRequest(PDADebugTarget target) throws CoreException {
+ //#ifdef ex3
+//# // TODO: Exercise 3 - clear breakpoint request in interpreter
+ //#else
+ target.sendRequest("clear " + (getLineNumber() - 1));
+ //#endif
+ }
+
+ /**
+ * Removes this breakpoint from the given interprettor.
+ * Removes this breakpoint as an event listener and clears
+ * the request for the interprettor.
+ *
+ * @param target PDA interprettor
+ * @throws CoreException if removal fails
+ */
+ public void remove(PDADebugTarget target) throws CoreException {
+ target.removeEventListener(this);
+ clearRequest(target);
+ fTarget = null;
+
+ }
+
+ /**
+ * Returns the target this breakpoint is installed in or <code>null</code>.
+ *
+ * @return the target this breakpoint is installed in or <code>null</code>
+ */
+ protected PDADebugTarget getDebugTarget() {
+ return fTarget;
+ }
+
+ /**
+ * Notify's the PDA interprettor that this breakpoint has been hit.
+ */
+ protected void notifyThread() {
+ if (fTarget != null) {
+ try {
+ IThread[] threads = fTarget.getThreads();
+ if (threads.length == 1) {
+ PDAThread thread = (PDAThread)threads[0];
+ thread.suspendedBy(this);
+ }
+ } catch (DebugException e) {
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ *
+ * Subclasses should override to handle their breakpoint specific event.
+ *
+ * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String)
+ */
+ public void handleEvent(String event) {
+ if (event.startsWith("suspended breakpoint")) {
+ handleHit(event);
+ }
+ }
+
+ /**
+ * Determines if this breakpoint was hit and notifies the thread.
+ *
+ * @param event breakpoint event
+ */
+ private void handleHit(String event) {
+ int lastSpace = event.lastIndexOf(' ');
+ if (lastSpace > 0) {
+ String line = event.substring(lastSpace + 1);
+ int lineNumber = Integer.parseInt(line);
+ // breakpoints event line numbers are 0 based, model objects are 1 based
+ lineNumber++;
+ try {
+ if (getLineNumber() == lineNumber) {
+ notifyThread();
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDARunToLineBreakpoint.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDARunToLineBreakpoint.java
new file mode 100644
index 000000000..b861fff20
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDARunToLineBreakpoint.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.breakpoints;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IBreakpoint;
+
+/**
+ * A run to line breakpoint.
+ */
+public class PDARunToLineBreakpoint extends PDALineBreakpoint {
+
+ private IFile fSourceFile;
+
+ /**
+ * Constructs a run-to-line breakpoint in the given PDA program.
+ *
+ * @param resource PDA source file
+ * @param lineNumber line to run to
+ * @exception DebugException if unable to create the breakpoint
+ */
+ public PDARunToLineBreakpoint(final IFile resource, final int lineNumber) throws DebugException {
+ IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ // associate with workspace root to avoid drawing in editor ruler
+ IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker("org.eclipse.debug.examples.core.pda.markerType.lineBreakpoint");
+ setMarker(marker);
+ marker.setAttribute(IBreakpoint.ENABLED, Boolean.TRUE);
+ marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+ marker.setAttribute(IBreakpoint.ID, getModelIdentifier());
+ setRegistered(false);
+ fSourceFile = resource;
+ }
+ };
+ run(getMarkerRule(resource), runnable);
+ }
+
+ /**
+ * Returns whether this breakpoint is a run-to-line breakpoint
+ *
+ * @return whether this breakpoint is a run-to-line breakpoint
+ */
+ public boolean isRunToLineBreakpoint() {
+ return true;
+ }
+
+ /**
+ * Returns the source file this breakpoint is contained in.
+ *
+ * @return the source file this breakpoint is contained in
+ */
+ public IFile getSourceFile() {
+ return fSourceFile;
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java
new file mode 100644
index 000000000..ab819d0b5
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.breakpoints;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IWatchpoint;
+import org.eclipse.debug.examples.core.pda.model.PDADebugTarget;
+
+
+/**
+ * A watchpoint.
+ */
+public class PDAWatchpoint extends PDALineBreakpoint implements IWatchpoint {
+
+ // 'read' or 'write' depending on what caused the last suspend for this watchpoint
+ private String fLastSuspendType;
+
+ // marker attributes
+ public static final String ACCESS = "ACCESS";
+ public static final String MODIFICATION = "MODIFICATION";
+ public static final String FUNCTION_NAME = "FUNCTION_NAME";
+ public static final String VAR_NAME = "VAR_NAME";
+
+ /**
+ * Default constructor is required for the breakpoint manager
+ * to re-create persisted breakpoints. After instantiating a breakpoint,
+ * the <code>setMarker(...)</code> method is called to restore
+ * this breakpoint's attributes.
+ */
+ public PDAWatchpoint() {
+ }
+ /**
+ * Constructs a line breakpoint on the given resource at the given
+ * line number. The line number is 1-based (i.e. the first line of a
+ * file is line number 1). The PDA VM uses 0-based line numbers,
+ * so this line number translation is done at breakpoint install time.
+ *
+ * @param resource file on which to set the breakpoint
+ * @param lineNumber 1-based line number of the breakpoint
+ * @param functionName function name the variable is defined in
+ * @param varName variable name that watchpoint is set on
+ * @param access whether this is an access watchpoint
+ * @param modification whether this in a modification watchpoint
+ * @throws CoreException if unable to create the watchpoint
+ */
+ public PDAWatchpoint(final IResource resource, final int lineNumber, final String functionName, final String varName, final boolean access, final boolean modification) throws CoreException {
+ IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IMarker marker = resource.createMarker("org.eclipse.debug.examples.core.pda.markerType.watchpoint");
+ setMarker(marker);
+ setEnabled(true);
+ ensureMarker().setAttribute(IMarker.LINE_NUMBER, lineNumber);
+ ensureMarker().setAttribute(IBreakpoint.ID, getModelIdentifier());
+ setAccess(access);
+ setModification(modification);
+ setVariable(functionName, varName);
+ marker.setAttribute(IMarker.MESSAGE, "Watchpoint: " + resource.getName() + " [line: " + lineNumber + "]");
+ }
+ };
+ run(getMarkerRule(resource), runnable);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IWatchpoint#isAccess()
+ */
+ public boolean isAccess() throws CoreException {
+ return getMarker().getAttribute(ACCESS, true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IWatchpoint#setAccess(boolean)
+ */
+ public void setAccess(boolean access) throws CoreException {
+ setAttribute(ACCESS, access);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IWatchpoint#isModification()
+ */
+ public boolean isModification() throws CoreException {
+ return getMarker().getAttribute(MODIFICATION, true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IWatchpoint#setModification(boolean)
+ */
+ public void setModification(boolean modification) throws CoreException {
+ setAttribute(MODIFICATION, modification);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IWatchpoint#supportsAccess()
+ */
+ public boolean supportsAccess() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IWatchpoint#supportsModification()
+ */
+ public boolean supportsModification() {
+ return true;
+ }
+
+ /**
+ * Sets the variable and function names the watchpoint is set on.
+ *
+ * @param functionName function name
+ * @param variableName variable name
+ * @throws CoreException if an exception occurrs setting marker attribtues
+ */
+ protected void setVariable(String functionName, String variableName) throws CoreException {
+ setAttribute(VAR_NAME, variableName);
+ setAttribute(FUNCTION_NAME, functionName);
+ }
+
+ /**
+ * Returns the name of the variable this watchpoint is set on.
+ *
+ * @return the name of the variable this watchpoint is set on
+ * @throws CoreException if unable to access the attribute
+ */
+ public String getVariableName() throws CoreException {
+ return getMarker().getAttribute(VAR_NAME, (String)null);
+ }
+
+ /**
+ * Returns the name of the function the variable associted with this watchpoint is defined in.
+ *
+ * @return the name of the function the variable associted with this watchpoint is defined in
+ * @throws CoreException if unable to access the attribute
+ */
+ public String getFunctionName() throws CoreException {
+ return getMarker().getAttribute(FUNCTION_NAME, (String)null);
+ }
+
+ /**
+ * Sets the type of event that causes the last suspend event.
+ *
+ * @param description one of 'read' or 'write'
+ */
+ public void setSuspendType(String description) {
+ fLastSuspendType = description;
+ }
+
+ /**
+ * Returns the type of event that caused the last suspend.
+ *
+ * @return 'read', 'write', or <code>null</code> if undefined
+ */
+ public String getSuspendType() {
+ return fLastSuspendType;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.examples.core.pda.breakpoints.PDALineBreakpoint#createRequest(org.eclipse.debug.examples.core.pda.model.PDADebugTarget)
+ */
+ protected void createRequest(PDADebugTarget target) throws CoreException {
+ int flag = 0;
+ if (isAccess()) {
+ flag = flag | 1;
+ }
+ if (isModification()) {
+ flag = flag | 2;
+ }
+ target.sendRequest("watch " + getFunctionName() + "::" + getVariableName() + " " + flag);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.examples.core.pda.breakpoints.PDALineBreakpoint#clearRequest(org.eclipse.debug.examples.core.pda.model.PDADebugTarget)
+ */
+ protected void clearRequest(PDADebugTarget target) throws CoreException {
+ target.sendRequest("watch " + getFunctionName() + "::" + getVariableName() + " " + 0);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String)
+ */
+ public void handleEvent(String event) {
+ if (event.startsWith("suspended watch")) {
+ handleHit(event);
+ }
+ }
+
+ /**
+ * Determines if this breakpoint was hit and notifies the thread.
+ *
+ * @param event breakpoint event
+ */
+ private void handleHit(String event) {
+ String[] strings = event.split(" ");
+ if (strings.length == 4) {
+ String fv = strings[3];
+ int j = fv.indexOf("::");
+ if (j > 0) {
+ String fcn = fv.substring(0, j);
+ String var = fv.substring(j + 2);
+ try {
+ if (getVariableName().equals(var) && getFunctionName().equals(fcn)) {
+ setSuspendType(strings[2]);
+ notifyThread();
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java
new file mode 100644
index 000000000..e78fc56b6
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.launcher;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+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.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
+import org.eclipse.debug.examples.core.pda.DebugCorePlugin;
+import org.eclipse.debug.examples.core.pda.model.PDADebugTarget;
+
+
+/**
+ * Launches PDA program on a PDA interpretter written in Perl
+ */
+public class PDALaunchDelegate extends LaunchConfigurationDelegate {
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ILaunchConfigurationDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
+ //#ifdef ex1
+//# // TODO: Exercise 1 - Launch a command shell as a system process to echo "foo"
+ //#elseif ex1_answer
+//# Process process = DebugPlugin.exec(new String[]{"cmd", "/C", "\"echo foo\""}, null);
+//# new RuntimeProcess(launch, process, "Hello", null);
+ //#else
+
+ List commandList = new ArrayList();
+
+ // Perl executable
+ IValueVariable perl = VariablesPlugin.getDefault().getStringVariableManager().getValueVariable(DebugCorePlugin.VARIALBE_PERL_EXECUTABLE);
+ if (perl == null) {
+ abort("Perl executable location undefined. Check value of ${perlExecutable}.", null);
+ }
+ String path = perl.getValue();
+ if (path == null) {
+ abort("Perl executable location unspecified. Check value of ${perlExecutable}.", null);
+ }
+ File exe = new File(path);
+ if (!exe.exists()) {
+ abort(MessageFormat.format("Specified Perl executable {0} does not exist. Check value of $perlExecutable.", new String[]{path}), null);
+ }
+ commandList.add(path);
+
+ // Add PDA VM
+ File vm = DebugCorePlugin.getFileInPlugin(new Path("pdavm/pda.pl"));
+ if (vm == null) {
+ abort("Missing PDA VM", null);
+ }
+ commandList.add(vm.getAbsolutePath());
+
+ // program name
+ String program = configuration.getAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, (String)null);
+ if (program == null) {
+ abort("Perl program unspecified.", null);
+ }
+
+ IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(program));
+ if (!file.exists()) {
+ abort(MessageFormat.format("Perl program {0} does not exist.", new String[] {file.getFullPath().toString()}), null);
+ }
+
+ commandList.add(file.getLocation().toOSString());
+
+ // if in debug mode, add debug arguments - i.e. '-debug requestPort eventPort'
+ int requestPort = -1;
+ int eventPort = -1;
+ if (mode.equals(ILaunchManager.DEBUG_MODE)) {
+ requestPort = findFreePort();
+ eventPort = findFreePort();
+ if (requestPort == -1 || eventPort == -1) {
+ abort("Unable to find free port", null);
+ }
+ commandList.add("-debug");
+ commandList.add("" + requestPort);
+ commandList.add("" + eventPort);
+ }
+
+ String[] commandLine = (String[]) commandList.toArray(new String[commandList.size()]);
+ Process process = DebugPlugin.exec(commandLine, null);
+ IProcess p = DebugPlugin.newProcess(launch, process, path);
+ // if in debug mode, create a debug target
+ if (mode.equals(ILaunchManager.DEBUG_MODE)) {
+ IDebugTarget target = new PDADebugTarget(launch, p, requestPort, eventPort);
+ launch.addDebugTarget(target);
+ }
+ //#endif
+ }
+
+ /**
+ * Throws an exception with a new status containing the given
+ * message and optional exception.
+ *
+ * @param message error message
+ * @param e underlying exception
+ * @throws CoreException
+ */
+ private void abort(String message, Throwable e) throws CoreException {
+ throw new CoreException(new Status(IStatus.ERROR, DebugCorePlugin.getDefault().getDescriptor().getUniqueIdentifier(), 0, message, e));
+ }
+
+ /**
+ * Returns a free port number on localhost, or -1 if unable to find a free port.
+ *
+ * @return a free port number on localhost, or -1 if unable to find a free port
+ */
+ public static int findFreePort() {
+ ServerSocket socket= null;
+ try {
+ socket= new ServerSocket(0);
+ return socket.getLocalPort();
+ } catch (IOException e) {
+ } finally {
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return -1;
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java
new file mode 100644
index 000000000..6935ad32b
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+/**
+ * Listeners are notified of events occurring in a PDA program
+ * being interpreted.
+ * <p>
+ * The events generated by the interpreter are:
+ * <ul>
+ * <li><code>started</code> - the interpreter has started (guaranteed to be the
+ * first event sent)</li>
+ * <li><code>terminated</code> - the interpreter has terminated (guaranteed to be
+ * the last event sent)</li>
+ * <li><code>suspended X</code> - the interpreter has suspended and entered debug mode;
+ * <code>X</code> is the cause of the suspension:
+ * <ul>
+ * <li><code>breakpoint N</code> - a breakpoint at line <code>N</code> was hit</li>
+ * <li><code>client</code> - a client request to suspend has completed</li>
+ * <li><code>drop</code> - a client request to drop a frame has completed</li>
+ * <li><code>event E</code> - an error was encountered, where <code>E</code> is one
+ * of <code>unimpinstr</code> or <code>nosuchlabel</code></li>
+ * <li><code>step</code> - a step request has completed</li>
+ * <li><code>watch A F::V</code> - a watchpoint was hit for reason <code>A</code>
+ * (<code>read</code> or <code>write</code>), on variable <code>V</code> in
+ * function <code>F</code></li>
+ * </ul>
+ * </li>
+ * <li><code>resumed X</code> - the interpreter has resumed execution in run mode;
+ * <code>X</code> is the cause of the resume:
+ * <ul>
+ * <li><code>step</code> - a step request has been initiated</li>
+ * <li><code>client</code> - a client request to resume has been initiated</li>
+ * </ul>
+ * </li>
+ * <li><code>unimplemented instruction X</code> - an unimplemented instruction <code>X</code>
+ * was encountered</li>
+ * <li><code>no such label X</code> - a branch or call to an unknown label <code>X</code>
+ * was encountered</li>
+ * </ul>
+ * </p>
+ */
+public interface IPDAEventListener {
+
+ /**
+ * Notification the given event occurred in the target program
+ * being interpreted.
+ *
+ * @param event the event
+ */
+ public void handleEvent(String event);
+
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java
new file mode 100644
index 000000000..e27e1bad1
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IVariable;
+
+public class PDAArray extends PDAValue {
+
+ /**
+ * An array splits a value into its words
+ *
+ * @param value existing value
+ * @throws DebugException
+ */
+ public PDAArray(PDAValue value) throws DebugException {
+ super(value.getPDADebugTarget(), value.getValueString());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValue#hasVariables()
+ */
+ public boolean hasVariables() throws DebugException {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValue#getVariables()
+ */
+ public IVariable[] getVariables() throws DebugException {
+ String string = getValueString();
+ String[] words = string.split("\\W+");
+ IVariable[] variables = new IVariable[words.length];
+ for (int i = 0; i < words.length; i++) {
+ String word = words[i];
+ variables[i] = new PDAArrayEntry(getPDADebugTarget(), i, new PDAValue(getPDADebugTarget(), word));
+ }
+ return variables;
+ }
+
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArrayEntry.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArrayEntry.java
new file mode 100644
index 000000000..9ff3ca74e
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArrayEntry.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IVariable;
+
+public class PDAArrayEntry extends PDADebugElement implements IVariable {
+
+ private IValue fValue;
+ private int fIndex;
+
+ /**
+ * Constructs a new array entry
+ *
+ * @param target debug target
+ * @param index index in the array
+ * @param value value of the entry
+ */
+ public PDAArrayEntry(IDebugTarget target, int index, IValue value) {
+ super(target);
+ fValue = value;
+ fIndex = index;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IVariable#getValue()
+ */
+ public IValue getValue() throws DebugException {
+ return fValue;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IVariable#getName()
+ */
+ public String getName() throws DebugException {
+ return "[" + fIndex + "]";
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IVariable#getReferenceTypeName()
+ */
+ public String getReferenceTypeName() throws DebugException {
+ return "String";
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IVariable#hasValueChanged()
+ */
+ public boolean hasValueChanged() throws DebugException {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#setValue(java.lang.String)
+ */
+ public void setValue(String expression) throws DebugException {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#setValue(org.eclipse.debug.core.model.IValue)
+ */
+ public void setValue(IValue value) throws DebugException {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#supportsValueModification()
+ */
+ public boolean supportsValueModification() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#verifyValue(java.lang.String)
+ */
+ public boolean verifyValue(String expression) throws DebugException {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#verifyValue(org.eclipse.debug.core.model.IValue)
+ */
+ public boolean verifyValue(IValue value) throws DebugException {
+ return false;
+ }
+
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java
new file mode 100644
index 000000000..e64f22050
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.model.DebugElement;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.examples.core.pda.DebugCorePlugin;
+
+
+/**
+ * Common function for PDA debug elements.
+ */
+public class PDADebugElement extends DebugElement {
+
+ /**
+ * Constructs a new debug element in the given target.
+ *
+ * @param target debug target
+ */
+ public PDADebugElement(IDebugTarget target) {
+ super(target);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDebugElement#getModelIdentifier()
+ */
+ public String getModelIdentifier() {
+ return DebugCorePlugin.ID_PDA_DEBUG_MODEL;
+ }
+
+ /**
+ * Sends a request to the PDA interpreter, waits for and returns the reply.
+ * <p>
+ * Interpreter commands and replies are as follows:
+ * <ul>
+ * <li><code>clear N</code> - clear the breakpoint on line <code>N</code>;
+ * reply is <code>ok</code></li>
+ * <li><code>data</code> - return the contents of the data stack; reply is the data
+ * from oldest to newest as a single string <code>"value|value|value|...|value|"</code></li>
+ * <li><code>drop</code> - pops the top stack frame off the call stack setting the
+ * instruction pointer to the calling statement in the calling frame</li>
+ * <li><code>eventstop E B</code> - optionally stop the interpreter when an error event
+ * <code>E</code> is encountered; <code>B</code> specifies stop (<code>1</code>) or
+ * continue (<code>0</code>). The possible events are <code>unimpinstr</code> and
+ * <code>nosuchlabel</code>. Reply is <code>ok</code>. When an event is encountered,
+ * the interpreter sends the error event (for example <code>unimlpemented instruction foo</code>)
+ * and corresponding suspend event (for example <code>suspended event unimpinstr</code>).</li>
+ * <li><code>exit</code> - end the interpreter; reply is <code>ok</code></li>
+ * <li><code>popdata</code> - pop the top value off the data stack; reply is the value</li>
+ * <li><code>pushdata V</code> - push the value <code>V</code> onto the data stack; reply is
+ * <code>ok</code></li>
+ * <li><code>resume</code> - resume execution of the program; reply is <code>ok</code></li>
+ * <li><code>set N</code> - set a line breakpoint on line <code>N</code> (lines are indexed
+ * from 0); reply is <code>ok</code></li>
+ * <li><code>setdata N V</code> - set the contents of data stack element <code>N</code> to
+ * value <code>V</code> (the data stack is indexed from 0, 0 being the oldest); reply
+ * is <code>ok</code></li>
+ * <li><code>setvar N M V</code> - set the contents of variable <code>M</code> from the control
+ * stack <code>N</code> to value <code>V</code> (the control stack is indexed from 0,
+ * 0 being the oldest); reply is <code>ok</code></li>
+ * <li><code>stack</code> - return the contents of the control stack (program counters, function and
+ * variable names); reply is control stack from oldest to newest as a single string
+ * <code>frame#frame#frame...#frame</code> where each frame is a string
+ * <code>"filename|pc|function name|variable name|variable name|...|variable name"</code></li>
+ * <li><code>step</code> - single step forward; reply is <code>ok</code></li>
+ * <li><code>stepreturn</code> - single step forward until the next <code>return</code> op code;
+ * stop before executing the <code>return</code> ; reply is <code>ok</code></li>
+ * <li><code>suspend</code> - suspend execution of the program and listen for debug commands;
+ * reply is <code>ok</code></li>
+ * <li><code>watch F::V M</code> - set a watchpoint on variable <code>V</code> in function
+ * <code>F</code> to magic value <code>M</code>; the magic value is a bit flag corresponding
+ * to read access (1), write access (2), or both (3); the magic value 0 clears the watchpoint;
+ * reply is <code>ok</code></li>
+ * <li><code>var N M</code> - return the contents of variable <code>M</code> in the control
+ * stack frame <code>N</code> (stack frames are indexed from 0, 0 being the oldest);
+ * reply is variable value</li>
+ * </ul>
+ * </p>
+ *
+ * @param request command
+ * @return reply
+ * @throws DebugException if the request fails
+ */
+ public String sendRequest(String request) throws DebugException {
+ return getPDADebugTarget().sendRequest(request);
+ }
+
+ /**
+ * Returns the debug target as a PDA target.
+ *
+ * @return PDA debug target
+ */
+ protected PDADebugTarget getPDADebugTarget() {
+ return (PDADebugTarget) getDebugTarget();
+ }
+
+ /**
+ * Returns the breakpoint manager
+ *
+ * @return the breakpoint manager
+ */
+ protected IBreakpointManager getBreakpointManager() {
+ return DebugPlugin.getDefault().getBreakpointManager();
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java
new file mode 100644
index 000000000..6df9fad76
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java
@@ -0,0 +1,525 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.Vector;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+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.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.IBreakpointManagerListener;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IMemoryBlock;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.examples.core.pda.DebugCorePlugin;
+import org.eclipse.debug.examples.core.pda.breakpoints.PDALineBreakpoint;
+import org.eclipse.debug.examples.core.pda.breakpoints.PDARunToLineBreakpoint;
+
+
+/**
+ * PDA Debug Target
+ */
+public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBreakpointManagerListener, IPDAEventListener {
+
+ // associated system process (VM)
+ private IProcess fProcess;
+
+ // containing launch object
+ private ILaunch fLaunch;
+
+ // sockets to communicate with VM
+ private Socket fRequestSocket;
+ private PrintWriter fRequestWriter;
+ private BufferedReader fRequestReader;
+ private Socket fEventSocket;
+ private BufferedReader fEventReader;
+
+ // terminated state
+ private boolean fTerminated = false;
+
+ // threads
+ private IThread[] fThreads;
+ private PDAThread fThread;
+
+ // event dispatch job
+ private EventDispatchJob fEventDispatch;
+ // event listeners
+ private Vector fEventListeners = new Vector();
+
+ /**
+ * Listens to events from the PDA VM and fires corresponding
+ * debug events.
+ */
+ class EventDispatchJob extends Job {
+
+ public EventDispatchJob() {
+ super("PDA Event Dispatch");
+ setSystem(true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IStatus run(IProgressMonitor monitor) {
+ String event = "";
+ while (!isTerminated() && event != null) {
+ try {
+ event = fEventReader.readLine();
+ if (event != null) {
+ Object[] listeners = fEventListeners.toArray();
+ for (int i = 0; i < listeners.length; i++) {
+ ((IPDAEventListener)listeners[i]).handleEvent(event);
+ }
+ }
+ } catch (IOException e) {
+ terminated();
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ }
+
+ /**
+ * Registers the given event listener. The listener will be notified of
+ * events in the program being interpretted. Has no effect if the listener
+ * is already registered.
+ *
+ * @param listener event listener
+ */
+ public void addEventListener(IPDAEventListener listener) {
+ if (!fEventListeners.contains(listener)) {
+ fEventListeners.add(listener);
+ }
+ }
+
+ /**
+ * Deregisters the given event listener. Has no effect if the listener is
+ * not currently registered.
+ *
+ * @param listener event listener
+ */
+ public void removeEventListener(IPDAEventListener listener) {
+ fEventListeners.remove(listener);
+ }
+
+ /**
+ * Constructs a new debug target in the given launch for the
+ * associated PDA VM process.
+ *
+ * @param launch containing launch
+ * @param process PDA VM
+ * @param requestPort port to send requests to the VM
+ * @param eventPort port to read events from
+ * @exception CoreException if unable to connect to host
+ */
+ public PDADebugTarget(ILaunch launch, IProcess process, int requestPort, int eventPort) throws CoreException {
+ super(null);
+ fLaunch = launch;
+ fProcess = process;
+ addEventListener(this);
+ try {
+ // give interpreter a chance to start
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ fRequestSocket = new Socket("localhost", requestPort);
+ fRequestWriter = new PrintWriter(fRequestSocket.getOutputStream());
+ fRequestReader = new BufferedReader(new InputStreamReader(fRequestSocket.getInputStream()));
+ // give interpreter a chance to open next socket
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ fEventSocket = new Socket("localhost", eventPort);
+ fEventReader = new BufferedReader(new InputStreamReader(fEventSocket.getInputStream()));
+ } catch (UnknownHostException e) {
+ requestFailed("Unable to connect to PDA VM", e);
+ } catch (IOException e) {
+ requestFailed("Unable to connect to PDA VM", e);
+ }
+ fThread = new PDAThread(this);
+ fThreads = new IThread[] {fThread};
+ fEventDispatch = new EventDispatchJob();
+ fEventDispatch.schedule();
+ IBreakpointManager breakpointManager = getBreakpointManager();
+ breakpointManager.addBreakpointListener(this);
+ breakpointManager.addBreakpointManagerListener(this);
+ // initialize error hanlding to suspend on 'unimplemented instructions'
+ // and 'no such label' errors
+ sendRequest("eventstop unimpinstr 1");
+ sendRequest("eventstop nosuchlabel 1");
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDebugTarget#getProcess()
+ */
+ public IProcess getProcess() {
+ return fProcess;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDebugTarget#getThreads()
+ */
+ public IThread[] getThreads() throws DebugException {
+ return fThreads;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDebugTarget#hasThreads()
+ */
+ public boolean hasThreads() throws DebugException {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDebugTarget#getName()
+ */
+ public String getName() throws DebugException {
+ return "PDA";
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
+ */
+ public boolean supportsBreakpoint(IBreakpoint breakpoint) {
+ if (!isTerminated() && breakpoint.getModelIdentifier().equals(getModelIdentifier())) {
+ try {
+ String program = getLaunch().getLaunchConfiguration().getAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, (String)null);
+ if (program != null) {
+ IResource resource = null;
+ if (breakpoint instanceof PDARunToLineBreakpoint) {
+ PDARunToLineBreakpoint rtl = (PDARunToLineBreakpoint) breakpoint;
+ resource = rtl.getSourceFile();
+ } else {
+ IMarker marker = breakpoint.getMarker();
+ if (marker != null) {
+ resource = marker.getResource();
+ }
+ }
+ if (resource != null) {
+ IPath p = new Path(program);
+ return resource.getFullPath().equals(p);
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
+ */
+ public IDebugTarget getDebugTarget() {
+ return this;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
+ */
+ public ILaunch getLaunch() {
+ return fLaunch;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
+ */
+ public boolean canTerminate() {
+ return getProcess().canTerminate();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
+ */
+ public boolean isTerminated() {
+ return fTerminated || getProcess().isTerminated();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#terminate()
+ */
+ public void terminate() throws DebugException {
+ getThread().terminate();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
+ */
+ public boolean canResume() {
+ return !isTerminated() && isSuspended();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
+ */
+ public boolean canSuspend() {
+ return !isTerminated() && !isSuspended();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
+ */
+ public boolean isSuspended() {
+ return !isTerminated() && getThread().isSuspended();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#resume()
+ */
+ public void resume() throws DebugException {
+ getThread().resume();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
+ */
+ public void suspend() throws DebugException {
+ getThread().suspend();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
+ */
+ public void breakpointAdded(IBreakpoint breakpoint) {
+ if (supportsBreakpoint(breakpoint)) {
+ try {
+ if ((breakpoint.isEnabled() && getBreakpointManager().isEnabled()) || !breakpoint.isRegistered()) {
+ PDALineBreakpoint pdaBreakpoint = (PDALineBreakpoint)breakpoint;
+ pdaBreakpoint.install(this);
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
+ */
+ public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
+ if (supportsBreakpoint(breakpoint)) {
+ try {
+ PDALineBreakpoint pdaBreakpoint = (PDALineBreakpoint)breakpoint;
+ pdaBreakpoint.remove(this);
+ } catch (CoreException e) {
+ }
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
+ */
+ public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
+ if (supportsBreakpoint(breakpoint)) {
+ try {
+ if (breakpoint.isEnabled() && getBreakpointManager().isEnabled()) {
+ breakpointAdded(breakpoint);
+ } else {
+ breakpointRemoved(breakpoint, null);
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDisconnect#canDisconnect()
+ */
+ public boolean canDisconnect() {
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDisconnect#disconnect()
+ */
+ public void disconnect() throws DebugException {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IDisconnect#isDisconnected()
+ */
+ public boolean isDisconnected() {
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
+ */
+ public boolean supportsStorageRetrieval() {
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long, long)
+ */
+ public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
+ return null;
+ }
+
+ /**
+ * Notification we have connected to the VM and it has started.
+ * Resume the VM.
+ */
+ private void started() {
+ fireCreationEvent();
+ installDeferredBreakpoints();
+ try {
+ resume();
+ } catch (DebugException e) {
+ }
+ }
+
+ /**
+ * Install breakpoints that are already registered with the breakpoint
+ * manager.
+ */
+ private void installDeferredBreakpoints() {
+ IBreakpoint[] breakpoints = getBreakpointManager().getBreakpoints(getModelIdentifier());
+ for (int i = 0; i < breakpoints.length; i++) {
+ breakpointAdded(breakpoints[i]);
+ }
+ }
+
+ /**
+ * Called when this debug target terminates.
+ */
+ private synchronized void terminated() {
+ fTerminated = true;
+ fThread = null;
+ fThreads = new IThread[0];
+ IBreakpointManager breakpointManager = getBreakpointManager();
+ breakpointManager.removeBreakpointListener(this);
+ breakpointManager.removeBreakpointManagerListener(this);
+ fireTerminateEvent();
+ removeEventListener(this);
+ }
+
+ /**
+ * Returns the values on the data stack (top down)
+ *
+ * @return the values on the data stack (top down)
+ */
+ public IValue[] getDataStack() throws DebugException {
+ String dataStack = sendRequest("data");
+ if (dataStack != null && dataStack.length() > 0) {
+ String[] values = dataStack.split("\\|");
+ IValue[] theValues = new IValue[values.length];
+ for (int i = 0; i < values.length; i++) {
+ String value = values[values.length - i - 1];
+ theValues[i] = new PDAStackValue(this, value, i);
+ }
+ return theValues;
+ }
+ return new IValue[0];
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.examples.core.pda.model.PDADebugElement#sendRequest(java.lang.String)
+ */
+ public String sendRequest(String request) throws DebugException {
+ synchronized (fRequestSocket) {
+ fRequestWriter.println(request);
+ fRequestWriter.flush();
+ try {
+ // wait for reply
+ return fRequestReader.readLine();
+ } catch (IOException e) {
+ requestFailed("Request failed: " + request, e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * When the breakpoint manager disables, remove all registered breakpoints
+ * requests from the VM. When it enables, reinstall them.
+ */
+ public void breakpointManagerEnablementChanged(boolean enabled) {
+ IBreakpoint[] breakpoints = getBreakpointManager().getBreakpoints(getModelIdentifier());
+ for (int i = 0; i < breakpoints.length; i++) {
+ if (enabled) {
+ breakpointAdded(breakpoints[i]);
+ } else {
+ breakpointRemoved(breakpoints[i], null);
+ }
+ }
+ }
+
+ /**
+ * Returns whether popping the data stack is currently permitted
+ *
+ * @return whether popping the data stack is currently permitted
+ */
+ public boolean canPop() {
+ try {
+ return !isTerminated() && isSuspended() && getDataStack().length > 0;
+ } catch (DebugException e) {
+ }
+ return false;
+ }
+
+ /**
+ * Pops and returns the top of the data stack
+ *
+ * @return the top value on the stack
+ * @throws DebugException if the stack is empty or the request fails
+ */
+ public IValue pop() throws DebugException {
+ IValue[] dataStack = getDataStack();
+ if (dataStack.length > 0) {
+ sendRequest("popdata");
+ return dataStack[0];
+ }
+ requestFailed("Empty stack", null);
+ return null;
+ }
+
+ /**
+ * Returns whether pushing a value is currently supported.
+ *
+ * @return whether pushing a value is currently supported
+ */
+ public boolean canPush() {
+ return !isTerminated() && isSuspended();
+ }
+
+ /**
+ * Pushes a value onto the stack.
+ *
+ * @param value value to push
+ * @throws DebugException on failure
+ */
+ public void push(String value) throws DebugException {
+ sendRequest("pushdata " + value);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String)
+ */
+ public void handleEvent(String event) {
+ if (event.equals("started")) {
+ started();
+ } else if (event.equals("terminated")) {
+ terminated();
+ }
+ }
+
+ /**
+ * Returns this debug target's single thread, or <code>null</code>
+ * if terminated.
+ *
+ * @return this debug target's single thread, or <code>null</code>
+ * if terminated
+ */
+ public synchronized PDAThread getThread() {
+ return fThread;
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java
new file mode 100644
index 000000000..a3cbe43c8
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java
@@ -0,0 +1,251 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IRegisterGroup;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IVariable;
+
+/**
+ * PDA stack frame.
+ */
+public class PDAStackFrame extends PDADebugElement implements IStackFrame {
+
+ private PDAThread fThread;
+ private String fName;
+ private int fPC;
+ private String fFileName;
+ private int fId;
+
+ /**
+ * Constructs a stack frame in the given thread with the given
+ * frame data.
+ *
+ * @param thread
+ * @param data frame data
+ * @param id stack frame id (0 is the bottom of the stack)
+ */
+ public PDAStackFrame(PDAThread thread, String data, int id) {
+ super(thread.getPDADebugTarget());
+ fId = id;
+ fThread = thread;
+ init(data);
+ }
+
+ /**
+ * Initializes this frame based on its data
+ *
+ * @param data
+ */
+ private void init(String data) {
+ String[] strings = data.split("\\|");
+ String fileName = strings[0];
+ fFileName = (new Path(fileName)).lastSegment();
+ String pc = strings[1];
+ fPC = Integer.parseInt(pc) + 1;
+ fName = strings[2];
+ int numVars = strings.length - 3;
+ IVariable[] vars = new IVariable[numVars];
+ for (int i = 0; i < numVars; i++) {
+ vars[i] = new PDAVariable(this, strings[i + 3]);
+ }
+ fThread.setVariables(this, vars);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStackFrame#getThread()
+ */
+ public IThread getThread() {
+ return fThread;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStackFrame#getVariables()
+ */
+ public IVariable[] getVariables() throws DebugException {
+ return fThread.getVariables(this);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStackFrame#hasVariables()
+ */
+ public boolean hasVariables() throws DebugException {
+ return getVariables().length > 0;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStackFrame#getLineNumber()
+ */
+ public int getLineNumber() throws DebugException {
+ return fPC;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStackFrame#getCharStart()
+ */
+ public int getCharStart() throws DebugException {
+ return -1;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStackFrame#getCharEnd()
+ */
+ public int getCharEnd() throws DebugException {
+ return -1;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStackFrame#getName()
+ */
+ public String getName() throws DebugException {
+ return fName;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStackFrame#getRegisterGroups()
+ */
+ public IRegisterGroup[] getRegisterGroups() throws DebugException {
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStackFrame#hasRegisterGroups()
+ */
+ public boolean hasRegisterGroups() throws DebugException {
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#canStepInto()
+ */
+ public boolean canStepInto() {
+ return getThread().canStepInto();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#canStepOver()
+ */
+ public boolean canStepOver() {
+ return getThread().canStepOver();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#canStepReturn()
+ */
+ public boolean canStepReturn() {
+ return getThread().canStepReturn();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#isStepping()
+ */
+ public boolean isStepping() {
+ return getThread().isStepping();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#stepInto()
+ */
+ public void stepInto() throws DebugException {
+ getThread().stepInto();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#stepOver()
+ */
+ public void stepOver() throws DebugException {
+ getThread().stepOver();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#stepReturn()
+ */
+ public void stepReturn() throws DebugException {
+ getThread().stepReturn();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
+ */
+ public boolean canResume() {
+ return getThread().canResume();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
+ */
+ public boolean canSuspend() {
+ return getThread().canSuspend();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
+ */
+ public boolean isSuspended() {
+ return getThread().isSuspended();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#resume()
+ */
+ public void resume() throws DebugException {
+ getThread().resume();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
+ */
+ public void suspend() throws DebugException {
+ getThread().suspend();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
+ */
+ public boolean canTerminate() {
+ return getThread().canTerminate();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
+ */
+ public boolean isTerminated() {
+ return getThread().isTerminated();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#terminate()
+ */
+ public void terminate() throws DebugException {
+ getThread().terminate();
+ }
+
+ /**
+ * Returns the name of the source file this stack frame is associated
+ * with.
+ *
+ * @return the name of the source file this stack frame is associated
+ * with
+ */
+ public String getSourceName() {
+ return fFileName;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof PDAStackFrame) {
+ PDAStackFrame sf = (PDAStackFrame)obj;
+ return sf.getThread().equals(getThread()) &&
+ sf.getSourceName().equals(getSourceName()) &&
+ sf.fId == fId;
+ }
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return getSourceName().hashCode() + fId;
+ }
+
+ /**
+ * Returns this stack frame's unique identifier within its thread
+ *
+ * @return this stack frame's unique identifier within its thread
+ */
+ protected int getIdentifier() {
+ return fId;
+ }
+
+
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java
new file mode 100644
index 000000000..2f13211f4
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+/**
+ * A value on the data stack
+ */
+public class PDAStackValue extends PDAValue {
+
+ private int fIndex;
+
+ /**
+ * Constructs a value that appears on the data stack
+ *
+ * @param target debug target
+ * @param value value on the stack
+ * @param index index on the stack
+ */
+ public PDAStackValue(PDADebugTarget target, String value, int index) {
+ super(target, value);
+ fIndex = index;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ return super.equals(obj) && ((PDAStackValue)obj).fIndex == fIndex;
+ }
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return super.hashCode() + fIndex;
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java
new file mode 100644
index 000000000..6a4102ac3
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java
@@ -0,0 +1,426 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IVariable;
+
+/**
+ * A PDA thread. A PDA VM is single threaded.
+ */
+public class PDAThread extends PDADebugElement implements IThread, IPDAEventListener {
+
+ /**
+ * Breakpoint this thread is suspended at or <code>null</code>
+ * if none.
+ */
+ private IBreakpoint fBreakpoint;
+
+ /**
+ * Whether this thread is stepping
+ */
+ private boolean fStepping = false;
+
+ /**
+ * Wether this thread is suspended
+ */
+ private boolean fSuspended = false;
+
+ /**
+ * Most recent error event or <code>null</code>
+ */
+ private String fErrorEvent;
+
+ /**
+ * Table mapping stack frames to current variables
+ */
+ private Map fVariables = new HashMap();
+
+ /**
+ * Constructs a new thread for the given target
+ *
+ * @param target VM
+ */
+ public PDAThread(PDADebugTarget target) {
+ super(target);
+ getPDADebugTarget().addEventListener(this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IThread#getStackFrames()
+ */
+ public IStackFrame[] getStackFrames() throws DebugException {
+ if (isSuspended()) {
+ String framesData = sendRequest("stack");
+ if (framesData != null) {
+ String[] frames = framesData.split("#");
+ IStackFrame[] theFrames = new IStackFrame[frames.length];
+ for (int i = 0; i < frames.length; i++) {
+ String data = frames[i];
+ theFrames[frames.length - i - 1] = new PDAStackFrame(this, data, i);
+ }
+ return theFrames;
+ }
+ }
+ return new IStackFrame[0];
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IThread#hasStackFrames()
+ */
+ public boolean hasStackFrames() throws DebugException {
+ return isSuspended();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IThread#getPriority()
+ */
+ public int getPriority() throws DebugException {
+ return 0;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IThread#getTopStackFrame()
+ */
+ public IStackFrame getTopStackFrame() throws DebugException {
+ IStackFrame[] frames = getStackFrames();
+ if (frames.length > 0) {
+ return frames[0];
+ }
+ return null;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IThread#getName()
+ */
+ public String getName() {
+ return "Main thread";
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IThread#getBreakpoints()
+ */
+ public IBreakpoint[] getBreakpoints() {
+ if (fBreakpoint == null) {
+ return new IBreakpoint[0];
+ }
+ return new IBreakpoint[]{fBreakpoint};
+ }
+
+ /**
+ * Notifies this thread it has been suspended by the given breakpoint.
+ *
+ * @param breakpoint breakpoint
+ */
+ public void suspendedBy(IBreakpoint breakpoint) {
+ fBreakpoint = breakpoint;
+ suspended(DebugEvent.BREAKPOINT);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
+ */
+ public boolean canResume() {
+ return isSuspended();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
+ */
+ public boolean canSuspend() {
+ return !isSuspended();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
+ */
+ public boolean isSuspended() {
+ return fSuspended && !isTerminated();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#resume()
+ */
+ public void resume() throws DebugException {
+ //#ifdef ex2
+//# // TODO: Exercise 2 - send resume request to interpreter
+ //#else
+ sendRequest("resume");
+ //#endif
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
+ */
+ public void suspend() throws DebugException {
+ //#ifdef ex2
+//# // TODO: Exercise 2 - send suspend request to interpreter
+ //#else
+ sendRequest("suspend");
+ //#endif
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#canStepInto()
+ */
+ public boolean canStepInto() {
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#canStepOver()
+ */
+ public boolean canStepOver() {
+ return isSuspended();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#canStepReturn()
+ */
+ public boolean canStepReturn() {
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#isStepping()
+ */
+ public boolean isStepping() {
+ return fStepping;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#stepInto()
+ */
+ public void stepInto() throws DebugException {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#stepOver()
+ */
+ public void stepOver() throws DebugException {
+ sendRequest("step");
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IStep#stepReturn()
+ */
+ public void stepReturn() throws DebugException {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
+ */
+ public boolean canTerminate() {
+ return !isTerminated();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
+ */
+ public boolean isTerminated() {
+ return getDebugTarget().isTerminated();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ITerminate#terminate()
+ */
+ public void terminate() throws DebugException {
+ //#ifdef ex2
+//# // TODO: Exercise 2 - send termination request to interpreter
+ //#else
+ sendRequest("exit");
+ //#endif
+ }
+
+ /**
+ * Sets whether this thread is stepping
+ *
+ * @param stepping whether stepping
+ */
+ private void setStepping(boolean stepping) {
+ fStepping = stepping;
+ }
+
+ /**
+ * Sets whether this thread is suspended
+ *
+ * @param suspended whether suspended
+ */
+ private void setSuspended(boolean suspended) {
+ fSuspended = suspended;
+ }
+
+ /**
+ * Sets the most recent error event encountered, or <code>null</code>
+ * to clear the most recent error
+ *
+ * @param event one of 'unimpinstr' or 'nosuchlabel' or <code>null</code>
+ */
+ private void setError(String event) {
+ fErrorEvent = event;
+ }
+
+ /**
+ * Returns the most revent error event encountered since the last
+ * suspend, or <code>null</code> if none.
+ *
+ * @return the most revent error event encountered since the last
+ * suspend, or <code>null</code> if none
+ */
+ public Object getError() {
+ return fErrorEvent;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String)
+ */
+ public void handleEvent(String event) {
+ // clear previous state
+ fBreakpoint = null;
+ setStepping(false);
+
+ // handle events
+ if (event.startsWith("resumed")) {
+ setSuspended(false);
+ if (event.endsWith("step")) {
+ setStepping(true);
+ resumed(DebugEvent.STEP_OVER);
+ //#ifdef ex2
+//# }
+//# // TODO: Exercise 2 - handle/fire "client" resume event
+ //#else
+ } else if (event.endsWith("client")) {
+ resumed(DebugEvent.CLIENT_REQUEST);
+ }
+ //#endif
+ //#ifdef ex5
+//# // TODO: Exercise 5 - handle start of drop event
+ //#else
+ else if (event.endsWith("drop")) {
+ resumed(DebugEvent.STEP_RETURN);
+ }
+ //#endif
+ } else if (event.startsWith("suspended")) {
+ setSuspended(true);
+ //#ifdef ex2
+//# // TODO: Exercise 2 - handle/fire "client" suspend event
+//# if (event.endsWith("step")) {
+//# suspended(DebugEvent.STEP_END);
+//# } else if (event.startsWith("suspended event") && getError() != null) {
+//# exceptionHit();
+//# }
+ //#else
+ if (event.endsWith("client")) {
+ suspended(DebugEvent.CLIENT_REQUEST);
+ } else if (event.endsWith("step")) {
+ suspended(DebugEvent.STEP_END);
+ } else if (event.startsWith("suspended event") && getError() != null) {
+ exceptionHit();
+ }
+ //#endif
+ //#ifdef ex5
+//# // TODO: Exercise 5 - handle end of drop event
+ //#else
+ else if (event.endsWith("drop")) {
+ suspended(DebugEvent.STEP_END);
+ }
+ //#endif
+ } else if (event.equals("started")) {
+ fireCreationEvent();
+ } else {
+ setError(event);
+ }
+
+ }
+
+ /**
+ * Notification the target has resumed for the given reason.
+ * Clears any error condition that was last encountered and
+ * fires a resume event, and clears all cached variables
+ * for stack frames.
+ *
+ * @param detail reason for the resume
+ */
+ private void resumed(int detail) {
+ setError(null);
+ synchronized (fVariables) {
+ fVariables.clear();
+ }
+ fireResumeEvent(detail);
+ }
+
+ /**
+ * Notification the target has suspended for the given reason
+ *
+ * @param detail reason for the suspend
+ */
+ private void suspended(int detail) {
+ fireSuspendEvent(detail);
+ }
+
+ /**
+ * Notification an error was encountered. Fires a breakpoint
+ * suspend event.
+ */
+ private void exceptionHit() {
+ suspended(DebugEvent.BREAKPOINT);
+ }
+
+ /**
+ * Sets the current variables for the given stack frame. Called
+ * by PDA stack frame when it is created.
+ *
+ * @param frame
+ * @param variables
+ */
+ protected void setVariables(IStackFrame frame, IVariable[] variables) {
+ synchronized (fVariables) {
+ fVariables.put(frame, variables);
+ }
+ }
+
+ /**
+ * Returns the current variables for the given stack frame, or
+ * <code>null</code> if none.
+ *
+ * @param frame stack frame
+ * @return variables or <code>null</code>
+ */
+ protected IVariable[] getVariables(IStackFrame frame) {
+ synchronized (fVariables) {
+ IVariable[] variables = (IVariable[]) fVariables.get(frame);
+ if (variables == null) {
+ return new IVariable[0];
+ }
+ return variables;
+ }
+ }
+
+ /**
+ * Pops the top frame off the callstack.
+ *
+ * @throws DebugException
+ */
+ public void pop() throws DebugException {
+ //#ifdef ex5
+//# // TODO: Exercise 5 - send drop request
+ //#else
+ sendRequest("drop");
+ //#endif
+ }
+
+ /**
+ * Returns whether this thread can pop the top stack frame.
+ *
+ * @return whether this thread can pop the top stack frame
+ */
+ public boolean canPop() {
+ //#ifdef ex5
+//# // TODO: Exercise 5 - allow pop if there is more than 1 frame on the stack
+ //#else
+ try {
+ return getStackFrames().length > 1;
+ } catch (DebugException e) {
+ }
+ //#endif
+ return false;
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java
new file mode 100644
index 000000000..e871004af
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IVariable;
+
+/**
+ * Value of a PDA variable.
+ */
+public class PDAValue extends PDADebugElement implements IValue {
+
+ private String fValue;
+
+ public PDAValue(PDADebugTarget target, String value) {
+ super(target);
+ fValue = value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValue#getReferenceTypeName()
+ */
+ public String getReferenceTypeName() throws DebugException {
+ try {
+ Integer.parseInt(fValue);
+ } catch (NumberFormatException e) {
+ return "text";
+ }
+ return "integer";
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValue#getValueString()
+ */
+ public String getValueString() throws DebugException {
+ return fValue;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValue#isAllocated()
+ */
+ public boolean isAllocated() throws DebugException {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValue#getVariables()
+ */
+ public IVariable[] getVariables() throws DebugException {
+ return new IVariable[0];
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValue#hasVariables()
+ */
+ public boolean hasVariables() throws DebugException {
+ return fValue.split("\\W+").length > 1;
+ }
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ return obj instanceof PDAValue && ((PDAValue)obj).fValue.equals(fValue);
+ }
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return fValue.hashCode();
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java
new file mode 100644
index 000000000..c57a9d24a
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IVariable;
+
+/**
+ * A variable in a PDA stack frame
+ */
+public class PDAVariable extends PDADebugElement implements IVariable {
+
+ // name & stack frmae
+ private String fName;
+ private PDAStackFrame fFrame;
+
+ /**
+ * Constructs a variable contained in the given stack frame
+ * with the given name.
+ *
+ * @param frame owning stack frame
+ * @param name variable name
+ */
+ public PDAVariable(PDAStackFrame frame, String name) {
+ super(frame.getPDADebugTarget());
+ fFrame = frame;
+ fName = name;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IVariable#getValue()
+ */
+ public IValue getValue() throws DebugException {
+ String value = sendRequest("var " + getStackFrame().getIdentifier() + " " + getName());
+ return new PDAValue(this.getPDADebugTarget(), value);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IVariable#getName()
+ */
+ public String getName() throws DebugException {
+ return fName;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IVariable#getReferenceTypeName()
+ */
+ public String getReferenceTypeName() throws DebugException {
+ return "Thing";
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IVariable#hasValueChanged()
+ */
+ public boolean hasValueChanged() throws DebugException {
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#setValue(java.lang.String)
+ */
+ public void setValue(String expression) throws DebugException {
+ sendRequest("setvar " + getStackFrame().getIdentifier() + " " + getName() + " " + expression);
+ fireChangeEvent(DebugEvent.CONTENT);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#setValue(org.eclipse.debug.core.model.IValue)
+ */
+ public void setValue(IValue value) throws DebugException {
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#supportsValueModification()
+ */
+ public boolean supportsValueModification() {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#verifyValue(java.lang.String)
+ */
+ public boolean verifyValue(String expression) throws DebugException {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.IValueModification#verifyValue(org.eclipse.debug.core.model.IValue)
+ */
+ public boolean verifyValue(IValue value) throws DebugException {
+ return false;
+ }
+
+ /**
+ * Returns the stack frame owning this variable.
+ *
+ * @return the stack frame owning this variable
+ */
+ protected PDAStackFrame getStackFrame() {
+ return fFrame;
+ }
+
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/WordStructureDelegate.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/WordStructureDelegate.java
new file mode 100644
index 000000000..dbb06cb22
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/WordStructureDelegate.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.model;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.ILogicalStructureTypeDelegate;
+import org.eclipse.debug.core.model.IValue;
+
+/**
+ * Logical stucture to translate a string into its words.
+ */
+public class WordStructureDelegate implements ILogicalStructureTypeDelegate {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ILogicalStructureTypeDelegate#providesLogicalStructure(org.eclipse.debug.core.model.IValue)
+ */
+ public boolean providesLogicalStructure(IValue value) {
+ //#ifdef ex6
+//# // TODO: Exercise 6 - provide logical structures if the value has multiple words
+ //#else
+ try {
+ String string = value.getValueString();
+ String[] words = string.split("\\W+");
+ return words.length > 1;
+ } catch (DebugException e) {
+ }
+ //#endif
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.model.ILogicalStructureTypeDelegate#getLogicalStructure(org.eclipse.debug.core.model.IValue)
+ */
+ public IValue getLogicalStructure(IValue value) throws CoreException {
+ //#ifdef ex6
+//# // TODO: Exercise 6 - create an array from the given value
+//# return null;
+ //#else
+ return new PDAArray((PDAValue)value);
+ //#endif
+ }
+
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourceLookupDirector.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourceLookupDirector.java
new file mode 100644
index 000000000..f975cf7c3
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourceLookupDirector.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.sourcelookup;
+
+import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
+
+/**
+ * PDA source lookup director. For PDA source lookup there is one source
+ * lookup participant.
+ */
+public class PDASourceLookupDirector extends AbstractSourceLookupDirector {
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.sourcelookup.ISourceLookupDirector#initializeParticipants()
+ */
+ public void initializeParticipants() {
+ //#ifdef ex4
+//# // TODO: Exercise 4 - add our participant to this director
+ //#else
+ addParticipants(new ISourceLookupParticipant[]{new PDASourceLookupParticipant()});
+ //#endif
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourceLookupParticipant.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourceLookupParticipant.java
new file mode 100644
index 000000000..0d07ce78d
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourceLookupParticipant.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.sourcelookup;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant;
+import org.eclipse.debug.examples.core.pda.model.PDAStackFrame;
+
+
+/**
+ * The PDA source lookup participant knows how to translate a
+ * PDA stack frame into a source file name
+ */
+public class PDASourceLookupParticipant extends AbstractSourceLookupParticipant {
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.sourcelookup.ISourceLookupParticipant#getSourceName(java.lang.Object)
+ */
+ public String getSourceName(Object object) throws CoreException {
+ //#ifdef ex4
+//# // TODO: Exercise 4 - return the name of the source file for the given stack frame
+//# return null;
+ //#else
+ if (object instanceof PDAStackFrame) {
+ return ((PDAStackFrame)object).getSourceName();
+ }
+ return null;
+ //#endif
+ }
+}
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourcePathComputerDelegate.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourcePathComputerDelegate.java
new file mode 100644
index 000000000..d91b3f245
--- /dev/null
+++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/sourcelookup/PDASourcePathComputerDelegate.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 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:
+ * IBM Corporation - initial API and implementation
+ * Bjorn Freeman-Benson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.examples.core.pda.sourcelookup;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.debug.core.sourcelookup.ISourcePathComputerDelegate;
+import org.eclipse.debug.core.sourcelookup.containers.FolderSourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.ProjectSourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.WorkspaceSourceContainer;
+import org.eclipse.debug.examples.core.pda.DebugCorePlugin;
+
+
+/**
+ * Computes the default source lookup path for a PDA launch configuration.
+ * The default source lookup path is the folder or project containing
+ * the PDA program being launched. If the program is not specified, the workspace
+ * is searched by default.
+ */
+public class PDASourcePathComputerDelegate implements ISourcePathComputerDelegate {
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.sourcelookup.ISourcePathComputerDelegate#computeSourceContainers(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public ISourceContainer[] computeSourceContainers(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException {
+ String path = configuration.getAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, (String)null);
+ ISourceContainer sourceContainer = null;
+ if (path != null) {
+ IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(path));
+ if (resource != null) {
+ //#ifdef ex4
+//# // TODO: Exercise 4 - seed the source lookup path
+ //#else
+ IContainer container = resource.getParent();
+ if (container.getType() == IResource.PROJECT) {
+ sourceContainer = new ProjectSourceContainer((IProject)container, false);
+ } else if (container.getType() == IResource.FOLDER) {
+ sourceContainer = new FolderSourceContainer(container, false);
+ }
+ //#endif
+ }
+ }
+ if (sourceContainer == null) {
+ sourceContainer = new WorkspaceSourceContainer();
+ }
+ return new ISourceContainer[]{sourceContainer};
+ }
+}

Back to the top