diff options
77 files changed, 6953 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 ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). 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, "Program" 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 ("Redistributor") 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}; + } +} diff --git a/org.eclipse.debug.examples.ui/.classpath b/org.eclipse.debug.examples.ui/.classpath new file mode 100644 index 000000000..b7464f3ca --- /dev/null +++ b/org.eclipse.debug.examples.ui/.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.ui/.cvsignore b/org.eclipse.debug.examples.ui/.cvsignore new file mode 100644 index 000000000..ba077a403 --- /dev/null +++ b/org.eclipse.debug.examples.ui/.cvsignore @@ -0,0 +1 @@ +bin diff --git a/org.eclipse.debug.examples.ui/.project b/org.eclipse.debug.examples.ui/.project new file mode 100644 index 000000000..6b2c66f6d --- /dev/null +++ b/org.eclipse.debug.examples.ui/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>example.debug.ui</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.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.debug.examples.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..14a594160 --- /dev/null +++ b/org.eclipse.debug.examples.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,37 @@ +#Mon Jan 24 20:23:44 CST 2005 +eclipse.preferences.version=1 +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.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 diff --git a/org.eclipse.debug.examples.ui/META-INF/MANIFEST.MF b/org.eclipse.debug.examples.ui/META-INF/MANIFEST.MF new file mode 100644 index 000000000..0b61b2dbd --- /dev/null +++ b/org.eclipse.debug.examples.ui/META-INF/MANIFEST.MF @@ -0,0 +1,25 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Example Debug UI Plug-in +Bundle-SymbolicName: org.eclipse.debug.examples.ui;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Activator: org.eclipse.debug.examples.ui.pda.DebugUIPlugin +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.debug.core, + org.eclipse.ui, + org.eclipse.debug.ui, + org.eclipse.jface.text, + org.eclipse.ui.editors, + org.eclipse.ui.workbench.texteditor, + org.eclipse.ui.ide, + org.eclipse.debug.examples.core +Eclipse-LazyStart: true +Export-Package: org.eclipse.debug.examples.ui.pda, + org.eclipse.debug.examples.ui.pda.adapters, + org.eclipse.debug.examples.ui.pda.breakpoints, + org.eclipse.debug.examples.ui.pda.editor, + org.eclipse.debug.examples.ui.pda.launcher, + org.eclipse.debug.examples.ui.pda.presentation, + org.eclipse.debug.examples.ui.pda.views +Bundle-RequiredExecutionEnvironment: J2SE-1.4 diff --git a/org.eclipse.debug.examples.ui/about.html b/org.eclipse.debug.examples.ui/about.html new file mode 100644 index 000000000..460233046 --- /dev/null +++ b/org.eclipse.debug.examples.ui/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 ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). 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, "Program" 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 ("Redistributor") 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.ui/build.properties b/org.eclipse.debug.examples.ui/build.properties new file mode 100644 index 000000000..3b3d36c80 --- /dev/null +++ b/org.eclipse.debug.examples.ui/build.properties @@ -0,0 +1,8 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + bin/,\ + about.html,\ + META-INF/,\ + . +src.includes = src/ diff --git a/org.eclipse.debug.examples.ui/icons/full/dlcl16/pop.gif b/org.eclipse.debug.examples.ui/icons/full/dlcl16/pop.gif Binary files differnew file mode 100644 index 000000000..559e46298 --- /dev/null +++ b/org.eclipse.debug.examples.ui/icons/full/dlcl16/pop.gif diff --git a/org.eclipse.debug.examples.ui/icons/full/dlcl16/push.gif b/org.eclipse.debug.examples.ui/icons/full/dlcl16/push.gif Binary files differnew file mode 100644 index 000000000..f7e6cc089 --- /dev/null +++ b/org.eclipse.debug.examples.ui/icons/full/dlcl16/push.gif diff --git a/org.eclipse.debug.examples.ui/icons/full/elcl16/pop.gif b/org.eclipse.debug.examples.ui/icons/full/elcl16/pop.gif Binary files differnew file mode 100644 index 000000000..2cd9c5444 --- /dev/null +++ b/org.eclipse.debug.examples.ui/icons/full/elcl16/pop.gif diff --git a/org.eclipse.debug.examples.ui/icons/full/elcl16/push.gif b/org.eclipse.debug.examples.ui/icons/full/elcl16/push.gif Binary files differnew file mode 100644 index 000000000..a5ac28d4c --- /dev/null +++ b/org.eclipse.debug.examples.ui/icons/full/elcl16/push.gif diff --git a/org.eclipse.debug.examples.ui/icons/full/obj16/pda.gif b/org.eclipse.debug.examples.ui/icons/full/obj16/pda.gif Binary files differnew file mode 100644 index 000000000..04c5052b2 --- /dev/null +++ b/org.eclipse.debug.examples.ui/icons/full/obj16/pda.gif diff --git a/org.eclipse.debug.examples.ui/plugin.xml b/org.eclipse.debug.examples.ui/plugin.xml new file mode 100644 index 000000000..3cc918c18 --- /dev/null +++ b/org.eclipse.debug.examples.ui/plugin.xml @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.0"?> +<plugin> +<!--#ifdef ex1 --> +<!--#else --> + <extension + point="org.eclipse.debug.ui.launchConfigurationTabGroups"> + <launchConfigurationTabGroup + class="org.eclipse.debug.examples.ui.pda.launcher.PDATabGroup" + description="Specify and launch a PDA program" + id="pda.tabGroup" + type="pda.launchType"/> + </extension> + <extension + point="org.eclipse.debug.ui.launchConfigurationTypeImages"> + <launchConfigurationTypeImage + icon="icons/full/obj16/pda.gif" + configTypeID="pda.launchType" + id="pda.typeImage"/> + </extension> + <extension + point="org.eclipse.debug.ui.launchShortcuts"> + <shortcut + label="PDA Application" + icon="icons/full/obj16/pda.gif" + class="org.eclipse.debug.examples.ui.pda.launcher.PDALaunchShortcut" + modes="run, debug" + id="pda.launchShortcut"> + <contextualLaunch> + <enablement> + <with variable="selection"> + <count value="1"/> + <iterate> + <instanceof value="org.eclipse.core.resources.IFile"/> + <test + value="*.pda" + property="org.eclipse.debug.ui.matchesPattern"/> + </iterate> + </with> + </enablement> + </contextualLaunch> + </shortcut> + </extension> +<!--#endif --> + <extension + point="org.eclipse.debug.ui.debugModelPresentations"> + <debugModelPresentation + class="org.eclipse.debug.examples.ui.pda.presentation.PDAModelPresentation" + id="pda.debugModel"/> + </extension> + <extension + point="org.eclipse.ui.editors"> + <editor + filenames="*.pda" + class="org.eclipse.debug.examples.ui.pda.editor.PDAEditor" + icon="icons/full/obj16/pda.gif" + default="true" + name="PDA Editor" + id="pda.editor" + extensions="pda"/> + </extension> + <extension + point="org.eclipse.ui.editorActions"> + <editorContribution + targetID="pda.editor" + id="pda.rulerActions"> + <action + label="Not Used" + class="org.eclipse.debug.ui.actions.RulerToggleBreakpointActionDelegate" + style="push" + actionID="RulerDoubleClick" + id="pda.doubleClickBreakpointAction"/> + </editorContribution> + </extension> + <extension + point="org.eclipse.ui.views"> + <view + icon="icons/full/obj16/pda.gif" + class="org.eclipse.debug.examples.ui.pda.views.DataStackView" + name="PDA Data Stack" + id="pda.dataStackView"/> + </extension> + + <extension + point="org.eclipse.ui.perspectiveExtensions"> + <perspectiveExtension targetID="org.eclipse.debug.ui.DebugPerspective"> + <view + visible="false" + relative="org.eclipse.debug.ui.VariableView" + relationship="stack" + id="pda.dataStackView"/> + </perspectiveExtension> + </extension> + <extension + point="org.eclipse.ui.contexts"> + <context + parentId="org.eclipse.debug.ui.debugging" + description="Debugging PDA Programs" + name="Debugging PDA Programs" + id="pda.debugging"/> + </extension> + <extension + point="org.eclipse.debug.ui.debugModelContextBindings"> + <modelContextBinding + contextId="pda.debugging" + debugModelId="pda.debugModel"/> + </extension> + <extension + point="org.eclipse.debug.ui.contextViewBindings"> + <contextViewBinding + contextId="pda.debugging" + viewId="pda.dataStackView"/> + </extension> + + <extension + point="org.eclipse.ui.popupMenus"> + <viewerContribution + targetID="pda.editor.rulerMenu" + id="pda.editor.rulerActions"> + <action + label="Toggle Breakpoint" + class="org.eclipse.debug.ui.actions.RulerToggleBreakpointActionDelegate" + menubarPath="debug" + id="pda.editor.ruler.toggleBreakpointAction"/> + </viewerContribution> + <viewerContribution + targetID="pda.editor.contextMenu" + id="pda.editor.menuActions"> + <action + label="Run to Line" + definitionId="org.eclipse.debug.ui.commands.RunToLine" + class="org.eclipse.debug.ui.actions.RunToLineActionDelegate" + menubarPath="additions" + id="pda.editor.context.runToLineAction"/> + </viewerContribution> +<!--#ifdef ex5 --> +<!--#else --> + <objectContribution + adaptable="false" + id="pda.dropToFrame" + objectClass="org.eclipse.debug.examples.core.pda.model.PDAStackFrame"> + <action + class="org.eclipse.debug.examples.ui.pda.editor.PopFrameActionDelegate" + id="pda.dropToFrame" + label="Pop Frame"/> + </objectContribution> +<!--#endif --> + </extension> + + <extension + point="org.eclipse.core.runtime.adapters"> + <factory + class="org.eclipse.debug.examples.ui.pda.breakpoints.PDAEditorAdapterFactory" + adaptableType="org.eclipse.debug.examples.ui.pda.editor.PDAEditor"> + <adapter type="org.eclipse.debug.ui.actions.IToggleBreakpointsTarget"/> +<!--#ifdef ex7 --> +<!--#else --> + <adapter type="org.eclipse.debug.ui.actions.IRunToLineTarget"/> +<!--#endif --> + </factory> +<!-- FLEXIBLE HIERARCHY EXAMPLE + <factory + adaptableType="org.eclipse.debug.examples.core.pda.model.PDADebugTarget" + class="example.debug.ui.adapters.AdapterFactory"> + <adapter + type="org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider"> + </adapter> + <adapter + type="org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory"> + </adapter> + </factory> +--> + </extension> +</plugin> diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/DebugUIPlugin.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/DebugUIPlugin.java new file mode 100644 index 000000000..ba635acb7 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/DebugUIPlugin.java @@ -0,0 +1,182 @@ +/******************************************************************************* + * 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.ui.pda; + +import java.net.URL; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.Map.Entry; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.internal.util.BundleUtility; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The main plugin class to be used in the desktop. + */ +public class DebugUIPlugin extends AbstractUIPlugin { + //The shared instance. + private static DebugUIPlugin plugin; + //Resource bundle. + private ResourceBundle resourceBundle; + + private final static String ICONS_PATH = "icons/full/";//$NON-NLS-1$ + private final static String PATH_OBJECT = ICONS_PATH + "obj16/"; //Model object icons //$NON-NLS-1$ + private final static String PATH_ELOCALTOOL = ICONS_PATH + "elcl16/"; //Enabled local toolbar icons //$NON-NLS-1$ + private final static String PATH_DLOCALTOOL = ICONS_PATH + "dlcl16/"; //Disabled local toolbar icons //$NON-NLS-1$ + + /** + * Toolbar action to pop data stack + */ + public final static String IMG_ELCL_POP = "IMG_ELCL_POP"; + public final static String IMG_DLCL_POP = "IMG_DLCL_POP"; + + /** + * Toolbar action to push onto data stack + */ + public final static String IMG_ELCL_PUSH = "IMG_ELCL_PUSH"; + public final static String IMG_DLCL_PUSH = "IMG_DLCL_PUSH"; + + /** + * PDA program image + */ + public final static String IMG_OBJ_PDA = "IMB_OBJ_PDA"; + + /** + * Keyword color + */ + public final static RGB KEYWORD = new RGB(0,0,255); + public final static RGB LABEL = new RGB(128, 128, 0); + + /** + * Managed colors + */ + private Map fColors = new HashMap(); + + /** + * The constructor. + */ + public DebugUIPlugin() { + super(); + plugin = this; + } + + /** + * This method is called upon plug-in activation + */ + public void start(BundleContext context) throws Exception { + super.start(context); +// Toggles single threaded adapter example +// IAdapterManager adapterManager = Platform.getAdapterManager(); +// IAdapterFactory factory = new AdapterFactory(); +// adapterManager.registerAdapters(factory, PDADebugTarget.class); + } + + /** + * This method is called when the plug-in is stopped + */ + public void stop(BundleContext context) throws Exception { + super.stop(context); + plugin = null; + resourceBundle = null; + Iterator colors = fColors.entrySet().iterator(); + while (colors.hasNext()) { + Map.Entry entry = (Entry) colors.next(); + ((Color)entry.getValue()).dispose(); + } + } + + /** + * Returns the shared instance. + */ + public static DebugUIPlugin 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 = DebugUIPlugin.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.ui.pda.DebugUIPluginResources"); + } catch (MissingResourceException x) { + resourceBundle = null; + } + return resourceBundle; + } + + + /* (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#initializeImageRegistry(org.eclipse.jface.resource.ImageRegistry) + */ + protected void initializeImageRegistry(ImageRegistry reg) { + declareImage(IMG_OBJ_PDA, PATH_OBJECT + "pda.gif"); + declareImage(IMG_ELCL_POP, PATH_ELOCALTOOL + "pop.gif"); + declareImage(IMG_DLCL_POP, PATH_DLOCALTOOL + "pop.gif"); + declareImage(IMG_ELCL_PUSH, PATH_ELOCALTOOL + "push.gif"); + declareImage(IMG_DLCL_PUSH, PATH_DLOCALTOOL + "push.gif"); + } + + /** + * Declares a workbench image given the path of the image file (relative to + * the workbench plug-in). This is a helper method that creates the image + * descriptor and passes it to the main <code>declareImage</code> method. + * + * @param symbolicName the symbolic name of the image + * @param path the path of the image file relative to the base of the workbench + * plug-ins install directory + * <code>false</code> if this is not a shared image + */ + private void declareImage(String key, String path) { + URL url = BundleUtility.find("org.eclipse.debug.examples.ui.pda", path); + ImageDescriptor desc = ImageDescriptor.createFromURL(url); + getImageRegistry().put(key, desc); + } + + /** + * Returns the color described by the given RGB. + * + * @param rgb + * @return color + */ + public Color getColor(RGB rgb) { + Color color = (Color) fColors.get(rgb); + if (color == null) { + color= new Color(Display.getCurrent(), rgb); + fColors.put(rgb, color); + } + return color; + } + + } diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/AdapterFactory.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/AdapterFactory.java new file mode 100644 index 000000000..3e4153fd5 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/AdapterFactory.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2006, 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.ui.pda.adapters; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; + + +/** + * + * @since 3.2 + * + */ +public class AdapterFactory implements IAdapterFactory { + + private static IElementContentProvider fgTargetAdapter = new PDADebugTargetContentProvider(); + private static IModelProxyFactory fgFactory = new ModelProxyFactory(); + + public Object getAdapter(Object adaptableObject, Class adapterType) { + if (IElementContentProvider.class.equals(adapterType)) { + if (adaptableObject instanceof PDADebugTarget) { + return fgTargetAdapter; + } + } + if (IModelProxyFactory.class.equals(adapterType)) { + if (adaptableObject instanceof PDADebugTarget) { + return fgFactory; + } + } + return null; + } + + public Class[] getAdapterList() { + return new Class[]{IElementContentProvider.class, IModelProxyFactory.class}; + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/ModelProxyFactory.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/ModelProxyFactory.java new file mode 100644 index 000000000..a8e5959f1 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/ModelProxyFactory.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2006, 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 + *******************************************************************************/ +package org.eclipse.debug.examples.ui.pda.adapters; + +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.debug.ui.IDebugUIConstants; + + +public class ModelProxyFactory implements IModelProxyFactory { + + public IModelProxy createModelProxy(Object element, IPresentationContext context) { + if (IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId())) { + if (element instanceof PDADebugTarget){ + return new PDADebugTargetProxy((IDebugTarget) element); + } + } + return null; + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetContentProvider.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetContentProvider.java new file mode 100644 index 000000000..ab33ae4f2 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetContentProvider.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 + *******************************************************************************/ + +package org.eclipse.debug.examples.ui.pda.adapters; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.pda.model.PDAThread; +import org.eclipse.debug.internal.ui.model.elements.ElementContentProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; +import org.eclipse.debug.ui.IDebugUIConstants; + + +public class PDADebugTargetContentProvider extends ElementContentProvider { + + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.model.elements.ElementContentProvider#getChildCount(java.lang.Object, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate) + */ + protected int getChildCount(Object element, IPresentationContext context, IViewerUpdate monitor) throws CoreException { + PDAThread thread = ((PDADebugTarget) element).getThread(); + if (thread != null) { + if (thread.hasStackFrames()) { + return thread.getStackFrames().length; + } + } + return 0; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.model.elements.ElementContentProvider#hasChildren(java.lang.Object, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate) + */ + protected boolean hasChildren(Object element, IPresentationContext context, IViewerUpdate monitor) throws CoreException { + PDAThread thread = ((PDADebugTarget) element).getThread(); + if (thread != null) { + return thread.hasStackFrames(); + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.model.elements.ElementContentProvider#getChildren(java.lang.Object, int, int, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate) + */ + protected Object[] getChildren(Object parent, int index, int length, IPresentationContext context, IViewerUpdate monitor) throws CoreException { + if (context.getId().equals(IDebugUIConstants.ID_DEBUG_VIEW)) { + PDAThread thread = ((PDADebugTarget) parent).getThread(); + if (thread != null) { + return getElements(thread.getStackFrames(), index, length); + } + } + return EMPTY; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.model.elements.ElementContentProvider#supportsContextId(java.lang.String) + */ + protected boolean supportsContextId(String id) { + return IDebugUIConstants.ID_DEBUG_VIEW.equals(id); + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetProxy.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetProxy.java new file mode 100644 index 000000000..e905e12fe --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetProxy.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2006, 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 + *******************************************************************************/ +package org.eclipse.debug.examples.ui.pda.adapters; + +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.internal.ui.viewers.update.DebugEventHandler; +import org.eclipse.debug.internal.ui.viewers.update.DebugTargetEventHandler; +import org.eclipse.debug.internal.ui.viewers.update.DebugTargetProxy; + +/** + * @since 3.2 + * + */ +public class PDADebugTargetProxy extends DebugTargetProxy { + + /** + * @param target + */ + public PDADebugTargetProxy(IDebugTarget target) { + super(target); + } + + /* (non-Javadoc) + * @see org.eclipse.debug.internal.ui.viewers.update.DebugTargetProxy#createEventHandlers() + */ + protected DebugEventHandler[] createEventHandlers() { + return new DebugEventHandler[] { new DebugTargetEventHandler(this), new PDAThreadEventHandler(this) }; + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDAThreadEventHandler.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDAThreadEventHandler.java new file mode 100644 index 000000000..2af58c7e6 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDAThreadEventHandler.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.debug.examples.ui.pda.adapters; + +import org.eclipse.debug.core.DebugEvent; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.core.model.IStackFrame; +import org.eclipse.debug.core.model.IThread; +import org.eclipse.debug.examples.core.pda.model.PDAThread; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy; +import org.eclipse.debug.internal.ui.viewers.update.DebugEventHandler; + + +/** + * @since 3.2 + */ +public class PDAThreadEventHandler extends DebugEventHandler { + + private IStackFrame fPrev = null; + + /** + * Constructs and event handler for a threads in the given viewer. + * + * @param viewer + */ + public PDAThreadEventHandler(AbstractModelProxy proxy) { + super(proxy); + } + + protected void handleSuspend(DebugEvent event) { + IThread thread = (IThread) event.getSource(); + int extras = IModelDelta.STATE; + if (event.getDetail() == DebugEvent.BREAKPOINT | event.getDetail() == DebugEvent.CLIENT_REQUEST) { + extras = IModelDelta.EXPAND; + } + fireDeltaUpdatingTopFrame(thread, IModelDelta.NO_CHANGE | extras); + } + + private boolean isEqual(Object o1, Object o2) { + if (o1 == o2) { + return true; + } + if (o1 == null) { + return false; + } + return o1.equals(o2); + } + + protected void handleResume(DebugEvent event) { + IThread thread = (IThread) event.getSource(); + fireDeltaAndClearTopFrame(thread, IModelDelta.STATE | IModelDelta.CONTENT); + } + + protected void handleCreate(DebugEvent event) { + fireDeltaAndClearTopFrame((IThread) event.getSource(), IModelDelta.ADDED); + } + + protected void handleTerminate(DebugEvent event) { + fireDeltaAndClearTopFrame((IThread) event.getSource(), IModelDelta.REMOVED); + } + + protected void handleChange(DebugEvent event) { + fireDeltaUpdatingTopFrame((IThread) event.getSource(), IModelDelta.STATE); + } + + protected void handleLateSuspend(DebugEvent suspend, DebugEvent resume) { + IThread thread = (IThread) suspend.getSource(); + fireDeltaUpdatingTopFrame(thread, IModelDelta.CONTENT | IModelDelta.EXPAND); + } + + protected void handleSuspendTimeout(DebugEvent event) { + IThread thread = (IThread) event.getSource(); + fireDeltaAndClearTopFrame(thread, IModelDelta.CONTENT); + } + + private ModelDelta buildRootDelta() { + return new ModelDelta(getLaunchManager(), IModelDelta.NO_CHANGE); + } + + private ILaunchManager getLaunchManager() { + return DebugPlugin.getDefault().getLaunchManager(); + } + + protected ModelDelta addTarget(ModelDelta delta, IThread thread) { + ILaunch launch = thread.getLaunch(); + Object[] children = launch.getChildren(); + delta = delta.addNode(launch, indexOf(getLaunchManager().getLaunches(), launch), IModelDelta.NO_CHANGE, children.length); + IDebugTarget debugTarget = thread.getDebugTarget(); + int numFrames = -1; + try { + numFrames = thread.getStackFrames().length; + } catch (DebugException e) { + } + return delta.addNode(debugTarget, indexOf(children, debugTarget), IModelDelta.NO_CHANGE, numFrames); + } + + private void fireDeltaAndClearTopFrame(IThread thread, int flags) { + ModelDelta delta = buildRootDelta(); + ModelDelta node = addTarget(delta, thread); + synchronized (this) { + fPrev = null; + } + fireDelta(delta); + } + + private void fireDeltaUpdatingTopFrame(IThread thread, int flags) { + ModelDelta delta = buildRootDelta(); + ModelDelta node = addTarget(delta, thread); + synchronized (this) { + IStackFrame prev = fPrev; + IStackFrame frame = null; + try { + frame = thread.getTopStackFrame(); + } catch (DebugException e) { + } + if (isEqual(frame, prev)) { + node.setFlags(flags); + } else { + node.setFlags(flags | IModelDelta.CONTENT); + } + if (frame != null) { + node.addNode(frame, 0, IModelDelta.STATE | IModelDelta.SELECT, 0); + } + fPrev = frame; + } + fireDelta(delta); + } + + protected boolean handlesEvent(DebugEvent event) { + return event.getSource() instanceof PDAThread; + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDABreakpointAdapter.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDABreakpointAdapter.java new file mode 100644 index 000000000..38e8f8525 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDABreakpointAdapter.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * 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.ui.pda.breakpoints; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.debug.core.model.ILineBreakpoint; +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.PDAWatchpoint; +import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; + + +/** + * Adapter to create breakpoints in PDA files. + */ +public class PDABreakpointAdapter implements IToggleBreakpointsTargetExtension { + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public void toggleLineBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { + ITextEditor textEditor = getEditor(part); + if (textEditor != null) { + IResource resource = (IResource) textEditor.getEditorInput().getAdapter(IResource.class); + ITextSelection textSelection = (ITextSelection) selection; + int lineNumber = textSelection.getStartLine(); + IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DebugCorePlugin.ID_PDA_DEBUG_MODEL); + for (int i = 0; i < breakpoints.length; i++) { + IBreakpoint breakpoint = breakpoints[i]; + if (breakpoint instanceof ILineBreakpoint && resource.equals(breakpoint.getMarker().getResource())) { + if (((ILineBreakpoint)breakpoint).getLineNumber() == (lineNumber + 1)) { + // remove + breakpoint.delete(); + return; + } + } + } + // create line breakpoint (doc line numbers start at 0) + PDALineBreakpoint lineBreakpoint = new PDALineBreakpoint(resource, lineNumber + 1); + DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(lineBreakpoint); + } + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleLineBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public boolean canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection) { + return getEditor(part) != null; + } + + /** + * Returns the editor being used to edit a PDA file, associated with the + * given part, or <code>null</code> if none. + * + * @param part workbench part + * @return the editor being used to edit a PDA file, associated with the + * given part, or <code>null</code> if none + */ + private ITextEditor getEditor(IWorkbenchPart part) { + if (part instanceof ITextEditor) { + ITextEditor editorPart = (ITextEditor) part; + IResource resource = (IResource) editorPart.getEditorInput().getAdapter(IResource.class); + if (resource != null) { + String extension = resource.getFileExtension(); + if (extension != null && extension.equals("pda")) { + return editorPart; + } + } + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public void toggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleMethodBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public boolean canToggleMethodBreakpoints(IWorkbenchPart part, ISelection selection) { + return false; + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleWatchpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public void toggleWatchpoints(IWorkbenchPart part, ISelection selection) throws CoreException { + String[] variableAndFunctionName = getVariableAndFunctionName(part, selection); + if (variableAndFunctionName != null && part instanceof ITextEditor && selection instanceof ITextSelection) { + ITextEditor editorPart = (ITextEditor)part; + int lineNumber = ((ITextSelection)selection).getStartLine(); + IResource resource = (IResource) editorPart.getEditorInput().getAdapter(IResource.class); + String var = variableAndFunctionName[0]; + String fcn = variableAndFunctionName[1]; + // look for existing watchpoint to delete + IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DebugCorePlugin.ID_PDA_DEBUG_MODEL); + for (int i = 0; i < breakpoints.length; i++) { + IBreakpoint breakpoint = breakpoints[i]; + if (breakpoint instanceof PDAWatchpoint && resource.equals(breakpoint.getMarker().getResource())) { + PDAWatchpoint watchpoint = (PDAWatchpoint)breakpoint; + String otherVar = watchpoint.getVariableName(); + String otherFcn = watchpoint.getFunctionName(); + if (otherVar.equals(var) && otherFcn.equals(fcn)) { + breakpoint.delete(); + return; + } + } + } + // create watchpoint + PDAWatchpoint watchpoint = new PDAWatchpoint(resource, lineNumber + 1, fcn, var, true, true); + DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(watchpoint); + } + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#canToggleWatchpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public boolean canToggleWatchpoints(IWorkbenchPart part, ISelection selection) { + return getVariableAndFunctionName(part, selection) != null; + } + + /** + * Returns the variable and function names at the current line, or <code>null</code> if none. + * + * @param part text editor + * @param selection text selection + * @return the variable and function names at the current line, or <code>null</code> if none. + * The array has two elements, the first is the variable name, the second is the function name. + */ + private String[] getVariableAndFunctionName(IWorkbenchPart part, ISelection selection) { + ITextEditor editor = getEditor(part); + if (editor != null && selection instanceof ITextSelection) { + ITextSelection textSelection = (ITextSelection) selection; + IDocumentProvider documentProvider = editor.getDocumentProvider(); + try { + documentProvider.connect(this); + IDocument document = documentProvider.getDocument(editor.getEditorInput()); + IRegion region = document.getLineInformationOfOffset(textSelection.getOffset()); + String string = document.get(region.getOffset(), region.getLength()).trim(); + if (string.startsWith("var ")) { + String varName = string.substring(4).trim(); + String fcnName = getFunctionName(document, varName, document.getLineOfOffset(textSelection.getOffset())); + return new String[] {varName, fcnName}; + } + } catch (CoreException e) { + } catch (BadLocationException e) { + } finally { + documentProvider.disconnect(this); + } + } + return null; + } + + /** + * Returns the name of the function containing the given variable defined at the given + * line number in the specified document. + * + * @param document PDA source file + * @param varName variable name + * @param line line numbner at which the variable is defined + * @return name of function defining the variable + */ + private String getFunctionName(IDocument document, String varName, int line) { + // This is a simple guess at the function name - look for the labels preceeding + // the variable definition, and then see if there are any 'calls' to that + // label. If none, assumet the variable is in the "_main_" function + String source = document.get(); + int lineIndex = line - 1; + while (lineIndex >= 0) { + try { + IRegion information = document.getLineInformation(lineIndex); + String lineText = document.get(information.getOffset(), information.getLength()); + if (lineText.startsWith(":")) { + String label = lineText.substring(1); + if (source.indexOf("call " + label) >= 0) { + return label; + } + } + lineIndex--; + } catch (BadLocationException e) { + } + } + return "_main_"; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#toggleBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public void toggleBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { + if (canToggleWatchpoints(part, selection)) { + toggleWatchpoints(part, selection); + } else { + toggleLineBreakpoints(part, selection); + } + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#canToggleBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public boolean canToggleBreakpoints(IWorkbenchPart part, ISelection selection) { + return canToggleLineBreakpoints(part, selection) || canToggleWatchpoints(part, selection); + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDAEditorAdapterFactory.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDAEditorAdapterFactory.java new file mode 100644 index 000000000..c67200a40 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDAEditorAdapterFactory.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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.ui.pda.breakpoints; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.debug.examples.ui.pda.editor.PDAEditor; +import org.eclipse.debug.ui.actions.IRunToLineTarget; +import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget; +import org.eclipse.ui.texteditor.ITextEditor; + + +/** + * Creates a toggle breakpoint adapter + */ +public class PDAEditorAdapterFactory implements IAdapterFactory { + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class) + */ + public Object getAdapter(Object adaptableObject, Class adapterType) { + if (adaptableObject instanceof PDAEditor) { + ITextEditor editorPart = (ITextEditor) adaptableObject; + IResource resource = (IResource) editorPart.getEditorInput().getAdapter(IResource.class); + if (resource != null) { + String extension = resource.getFileExtension(); + if (extension != null && extension.equals("pda")) { + if (adapterType.equals(IToggleBreakpointsTarget.class)) { + return new PDABreakpointAdapter(); + } + //#ifdef ex7 +//# // TODO: Exercise 7 - create run to line adapter + //#else + if (adapterType.equals(IRunToLineTarget.class)) { + return new PDARunToLineAdapter(); + } + //#endif + } + } + } + return null; + } + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList() + */ + public Class[] getAdapterList() { + return new Class[]{IToggleBreakpointsTarget.class}; + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDARunToLineAdapter.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDARunToLineAdapter.java new file mode 100644 index 000000000..3d5fa42d0 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDARunToLineAdapter.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * 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.ui.pda.breakpoints; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.debug.core.model.IDebugElement; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.core.model.ISuspendResume; +import org.eclipse.debug.examples.core.pda.DebugCorePlugin; +import org.eclipse.debug.examples.core.pda.breakpoints.PDARunToLineBreakpoint; +import org.eclipse.debug.ui.actions.IRunToLineTarget; +import org.eclipse.debug.ui.actions.RunToLineHandler; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.texteditor.ITextEditor; + + +/** + * Run to line target for the Java debugger + */ +public class PDARunToLineAdapter implements IRunToLineTarget { + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IRunToLineTarget#runToLine(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection, org.eclipse.debug.core.model.ISuspendResume) + */ + public void runToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target) throws CoreException { + IEditorPart editorPart = (IEditorPart)part; + ITextEditor textEditor = (ITextEditor)editorPart; + ITextSelection textSelection = (ITextSelection) selection; + int lineNumber = textSelection.getStartLine() + 1; + if (lineNumber > 0) { + if (target instanceof IAdaptable) { + IDebugTarget debugTarget = (IDebugTarget) ((IAdaptable)target).getAdapter(IDebugTarget.class); + if (debugTarget != null) { + //#ifdef ex7 +//# // TODO: Exercise 7 - perform the run-to-line with a run-to-line breakpoint and handler + //#else + IFile resource = (IFile) textEditor.getEditorInput().getAdapter(IResource.class); + IBreakpoint breakpoint= new PDARunToLineBreakpoint(resource, lineNumber); + RunToLineHandler handler = new RunToLineHandler(debugTarget, target, breakpoint); + handler.run(new NullProgressMonitor()); + //#endif + } + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IRunToLineTarget#canRunToLine(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection, org.eclipse.debug.core.model.ISuspendResume) + */ + public boolean canRunToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target) { + //#ifdef ex7 +//# // TODO: Exercise 7 - ensure the target is a PDA target +//# return false; + //#else + return target instanceof IDebugElement && + ((IDebugElement)target).getModelIdentifier().equals(DebugCorePlugin.ID_PDA_DEBUG_MODEL); + //#endif + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/AnnotationHover.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/AnnotationHover.java new file mode 100644 index 000000000..6b79056b7 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/AnnotationHover.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * 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.ui.pda.editor; + +import java.util.Iterator; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; + +/** + * Returns hover for breakpoints. + */ +public class AnnotationHover implements IAnnotationHover { + + public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) { + IAnnotationModel annotationModel = sourceViewer.getAnnotationModel(); + Iterator iterator = annotationModel.getAnnotationIterator(); + while (iterator.hasNext()) { + Annotation annotation = (Annotation) iterator.next(); + Position position = annotationModel.getPosition(annotation); + try { + int lineOfAnnotation = sourceViewer.getDocument().getLineOfOffset(position.getOffset()); + if (lineNumber == lineOfAnnotation) { + return annotation.getText(); + } + } catch (BadLocationException e) { + } + } + return null; + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAContentAssistProcessor.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAContentAssistProcessor.java new file mode 100644 index 000000000..5d7089472 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAContentAssistProcessor.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * 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.ui.pda.editor; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.contentassist.CompletionProposal; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.jface.text.contentassist.IContextInformationValidator; + +public class PDAContentAssistProcessor implements IContentAssistProcessor { + + public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { + int index = offset - 1; + StringBuffer prefix = new StringBuffer(); + IDocument document = viewer.getDocument(); + while (index > 0) { + try { + char prev = document.getChar(index); + if (Character.isWhitespace(prev)) { + break; + } + prefix.insert(0, prev); + index--; + } catch (BadLocationException e) { + } + } + + List proposals = new ArrayList(); + String[] keywords = PDAScanner.fgKeywords; + if (prefix.length() > 0) { + String word = prefix.toString(); + for (int i = 0; i < keywords.length; i++) { + String keyword = keywords[i]; + if (keyword.startsWith(word) && word.length() < keyword.length()) { + proposals.add(new CompletionProposal(keyword + " ", index + 1, offset - (index + 1), keyword.length() + 1)); + } + } + } else { + // propose all keywords + for (int i = 0; i < keywords.length; i++) { + String keyword = keywords[i]; + proposals.add(new CompletionProposal(keyword + " ", offset, 0, keyword.length() + 1)); + } + } + if (!proposals.isEmpty()) { + return (ICompletionProposal[]) proposals.toArray(new ICompletionProposal[proposals.size()]); + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int) + */ + public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters() + */ + public char[] getCompletionProposalAutoActivationCharacters() { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters() + */ + public char[] getContextInformationAutoActivationCharacters() { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage() + */ + public String getErrorMessage() { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator() + */ + public IContextInformationValidator getContextInformationValidator() { + return null; + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAContentAssistant.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAContentAssistant.java new file mode 100644 index 000000000..01f71928e --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAContentAssistant.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * 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.ui.pda.editor; + +import org.eclipse.jface.text.DefaultInformationControl; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IInformationControl; +import org.eclipse.jface.text.IInformationControlCreator; +import org.eclipse.jface.text.contentassist.ContentAssistant; +import org.eclipse.swt.widgets.Shell; + +public class PDAContentAssistant extends ContentAssistant { + + public PDAContentAssistant() { + super(); + + PDAContentAssistProcessor processor= new PDAContentAssistProcessor(); + setContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE); + + enableAutoActivation(false); + enableAutoInsert(false); + + setInformationControlCreator(getInformationControlCreator()); + } + + private IInformationControlCreator getInformationControlCreator() { + return new IInformationControlCreator() { + public IInformationControl createInformationControl(Shell parent) { + return new DefaultInformationControl(parent); + } + }; + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAEditor.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAEditor.java new file mode 100644 index 000000000..3617cb172 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAEditor.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * 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.ui.pda.editor; + +import java.util.ResourceBundle; + +import org.eclipse.jface.action.IAction; +import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor; +import org.eclipse.ui.texteditor.ContentAssistAction; +import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; + +/** + * PDA editor + */ +public class PDAEditor extends AbstractDecoratedTextEditor { + + /** + * Creates a PDE editor + */ + public PDAEditor() { + super(); + setSourceViewerConfiguration(new PDASourceViewerConfiguration()); + setRulerContextMenuId("pda.editor.rulerMenu"); + setEditorContextMenuId("pda.editor.editorMenu"); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions() + */ + protected void createActions() { + super.createActions(); + ResourceBundle bundle = ResourceBundle.getBundle("org.eclipse.debug.examples.ui.pda.editor.PDAEditorMessages"); //$NON-NLS-1$ + IAction action = new ContentAssistAction(bundle, "ContentAssistProposal.", this); //$NON-NLS-1$ + action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); + setAction("ContentAssistProposal", action); //$NON-NLS-1$ + } + + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAEditorMessages.properties b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAEditorMessages.properties new file mode 100644 index 000000000..3215e8892 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAEditorMessages.properties @@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2000, 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 +############################################################################### + +ContentAssistProposal.label=Content &Assist +ContentAssistProposal.tooltip=Content Assist +ContentAssistProposal.image= +ContentAssistProposal.description=Content Assist
\ No newline at end of file diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAScanner.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAScanner.java new file mode 100644 index 000000000..b62d0ba45 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDAScanner.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * 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.ui.pda.editor; + +import org.eclipse.debug.examples.ui.pda.DebugUIPlugin; +import org.eclipse.jface.text.TextAttribute; +import org.eclipse.jface.text.rules.BufferedRuleBasedScanner; +import org.eclipse.jface.text.rules.IRule; +import org.eclipse.jface.text.rules.IWordDetector; +import org.eclipse.jface.text.rules.Token; +import org.eclipse.jface.text.rules.WordRule; + + +/** + * PDA editor keyword scanner. + */ +public class PDAScanner extends BufferedRuleBasedScanner { + + /** + * PDA keywods + */ + public static final String[] fgKeywords = new String[] { + "add", "branch_not_zero", "call", "dec", "dup", + "halt", "output", "pop", "push", "return", "var" + }; + + /** + * Detects potential keywords + */ + class PDAWordDetector implements IWordDetector { + + /* (non-Javadoc) + * @see org.eclipse.jface.text.rules.IWordDetector#isWordStart(char) + */ + public boolean isWordStart(char c) { + return Character.isLetter(c); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.rules.IWordDetector#isWordPart(char) + */ + public boolean isWordPart(char c) { + return Character.isLetter(c) || c == '_'; + } + } + + /** + * Detects PDA branch labels + */ + class PDALabelDetector extends PDAWordDetector { + + /* (non-Javadoc) + * @see org.eclipse.jface.text.rules.IWordDetector#isWordStart(char) + */ + public boolean isWordStart(char c) { + return c == ':'; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.rules.IWordDetector#isWordPart(char) + */ + public boolean isWordPart(char c) { + return super.isWordPart(c) || Character.isDigit(c); + } + } + + /** + * Constructs a scanner that identifies PDA keywords. + */ + public PDAScanner() { + // keywords + Token token = new Token(new TextAttribute(DebugUIPlugin.getDefault().getColor(DebugUIPlugin.KEYWORD))); + WordRule keywords = new WordRule(new PDAWordDetector()); + for (int i = 0; i < fgKeywords.length; i++) { + String keyword = fgKeywords[i]; + keywords.addWord(keyword, token); + } + // labels + token = new Token(new TextAttribute(DebugUIPlugin.getDefault().getColor(DebugUIPlugin.LABEL))); + WordRule labels = new WordRule(new PDALabelDetector(), token); + setRules(new IRule[]{keywords, labels}); + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDASourceViewerConfiguration.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDASourceViewerConfiguration.java new file mode 100644 index 000000000..6c24c36a0 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PDASourceViewerConfiguration.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * 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.ui.pda.editor; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.contentassist.IContentAssistant; +import org.eclipse.jface.text.presentation.IPresentationReconciler; +import org.eclipse.jface.text.presentation.PresentationReconciler; +import org.eclipse.jface.text.rules.DefaultDamagerRepairer; +import org.eclipse.jface.text.source.IAnnotationHover; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; + +/** + * Source view configuration for the PDA editor + */ +public class PDASourceViewerConfiguration extends TextSourceViewerConfiguration { + + /* (non-Javadoc) + * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getTextHover(org.eclipse.jface.text.source.ISourceViewer, java.lang.String) + */ + public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) { + return new TextHover(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getAnnotationHover(org.eclipse.jface.text.source.ISourceViewer) + */ + public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) { + return new AnnotationHover(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getPresentationReconciler(org.eclipse.jface.text.source.ISourceViewer) + */ + public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) { + PresentationReconciler reconciler = new PresentationReconciler(); + reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); + DefaultDamagerRepairer dr = new DefaultDamagerRepairer(new PDAScanner()); + reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); + reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); + return reconciler; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.source.SourceViewerConfiguration#getContentAssistant(org.eclipse.jface.text.source.ISourceViewer) + */ + public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) { + return new PDAContentAssistant(); + } + + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PopFrameActionDelegate.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PopFrameActionDelegate.java new file mode 100644 index 000000000..1c13bac19 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PopFrameActionDelegate.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * 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.ui.pda.editor; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.examples.core.pda.model.PDAStackFrame; +import org.eclipse.debug.examples.core.pda.model.PDAThread; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Event; +import org.eclipse.ui.IActionDelegate2; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + + +public class PopFrameActionDelegate implements IObjectActionDelegate, IActionDelegate2 { + + private PDAThread fThread = null; + + /* (non-Javadoc) + * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart) + */ + public void setActivePart(IAction action, IWorkbenchPart targetPart) { + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) + */ + public void run(IAction action) { + //#ifdef ex5 +//# // TODO: Exercise 5 - pop the top frame + //#else + try { + fThread.pop(); + } catch (DebugException e) { + } + //#endif + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) { + if (selection instanceof IStructuredSelection) { + IStructuredSelection ss = (IStructuredSelection) selection; + Object element = ss.getFirstElement(); + if (element instanceof PDAStackFrame) { + PDAStackFrame frame = (PDAStackFrame) element; + //#ifdef ex5 +//# // TODO: Exercise 5 - enable the action if the frame's thread supports it + //#else + fThread = (PDAThread) frame.getThread(); + try { + action.setEnabled(fThread.canPop() && fThread.getTopStackFrame().equals(frame)); + } catch (DebugException e) { + } + return; + //#endif + } + + } + action.setEnabled(false); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate2#init(org.eclipse.jface.action.IAction) + */ + public void init(IAction action) { + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate2#dispose() + */ + public void dispose() { + fThread = null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionDelegate2#runWithEvent(org.eclipse.jface.action.IAction, org.eclipse.swt.widgets.Event) + */ + public void runWithEvent(IAction action, Event event) { + run(action); + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/TextHover.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/TextHover.java new file mode 100644 index 000000000..6b14e4c74 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/TextHover.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * 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.ui.pda.editor; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IThread; +import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.pda.model.PDAStackFrame; +import org.eclipse.debug.examples.core.pda.model.PDAThread; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextHover; +import org.eclipse.jface.text.ITextViewer; + + +/** + * Produces debug hover for the PDA debugger. + */ +public class TextHover implements ITextHover { + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion) + */ + public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) { + String varName = null; + try { + varName = textViewer.getDocument().get(hoverRegion.getOffset(), hoverRegion.getLength()); + } catch (BadLocationException e) { + return null; + } + if (varName.startsWith("$") && varName.length() > 1) { + varName = varName.substring(1); + } + + PDAStackFrame frame = null; + IAdaptable debugContext = DebugUITools.getDebugContext(); + if (debugContext instanceof PDAStackFrame) { + frame = (PDAStackFrame) debugContext; + } else if (debugContext instanceof PDAThread) { + PDAThread thread = (PDAThread) debugContext; + try { + frame = (PDAStackFrame) thread.getTopStackFrame(); + } catch (DebugException e) { + return null; + } + } else if (debugContext instanceof PDADebugTarget) { + PDADebugTarget target = (PDADebugTarget) debugContext; + try { + IThread[] threads = target.getThreads(); + if (threads.length > 0) { + frame = (PDAStackFrame) threads[0].getTopStackFrame(); + } + } catch (DebugException e) { + return null; + } + } + if (frame != null) { + try { + IVariable[] variables = frame.getVariables(); + for (int i = 0; i < variables.length; i++) { + IVariable variable = variables[i]; + if (variable.getName().equals(varName)) { + return varName + " = " + variable.getValue().getValueString(); + } + } + } catch (DebugException e) { + } + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.ITextHover#getHoverRegion(org.eclipse.jface.text.ITextViewer, int) + */ + public IRegion getHoverRegion(ITextViewer textViewer, int offset) { + return WordFinder.findWord(textViewer.getDocument(), offset); + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/WordFinder.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/WordFinder.java new file mode 100644 index 000000000..e60d98203 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/WordFinder.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.ui.pda.editor; + + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Region; + +/** + * Looks for an identifier in a source file + */ +public class WordFinder { + + /** + * Returns the region in the given document that contains an identifier, or + * <code>null</code> if none. + * + * @param document document to search + * @param offset offset at which to look for an identifier + * @return region containing an identifier, or <code>null</code> + */ + public static IRegion findWord(IDocument document, int offset) { + + int start= -1; + int end= -1; + + + try { + + int pos= offset; + char c; + + while (pos >= 0) { + c= document.getChar(pos); + if (!Character.isJavaIdentifierPart(c)) + break; + --pos; + } + + start= pos; + + pos= offset; + int length= document.getLength(); + + while (pos < length) { + c= document.getChar(pos); + if (!Character.isJavaIdentifierPart(c)) + break; + ++pos; + } + + end= pos; + + } catch (BadLocationException x) { + } + + if (start > -1 && end > -1) { + if (start == offset && end == offset) + return new Region(offset, 0); + else if (start == offset) + return new Region(start, end - start); + else + return new Region(start + 1, end - start - 1); + } + + return null; + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/launcher/PDALaunchShortcut.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/launcher/PDALaunchShortcut.java new file mode 100644 index 000000000..2bbf75ee2 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/launcher/PDALaunchShortcut.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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.ui.pda.launcher; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.examples.core.pda.DebugCorePlugin; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.ILaunchShortcut; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IEditorPart; + + +/** + * Launches a PDA file + */ +public class PDALaunchShortcut implements ILaunchShortcut { + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.jface.viewers.ISelection, java.lang.String) + */ + public void launch(ISelection selection, String mode) { + // must be a structured selection with one file selected + IFile file = (IFile) ((IStructuredSelection)selection).getFirstElement(); + + // check for an existing launch config for the pda file + String path = file.getFullPath().toString(); + ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); + ILaunchConfigurationType type = launchManager.getLaunchConfigurationType(DebugCorePlugin.ID_PDA_LAUNCH_CONFIGURATION_TYPE); + try { + ILaunchConfiguration[] configurations = launchManager.getLaunchConfigurations(type); + for (int i = 0; i < configurations.length; i++) { + ILaunchConfiguration configuration = configurations[i]; + String attribute = configuration.getAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, (String)null); + if (path.equals(attribute)) { + DebugUITools.launch(configuration, mode); + return; + } + } + } catch (CoreException e) { + return; + } + + try { + // create a new configuration for the pda file + ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null, file.getName()); + workingCopy.setAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, path); + ILaunchConfiguration configuration = workingCopy.doSave(); + DebugUITools.launch(configuration, mode); + } catch (CoreException e1) { + } + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.ui.IEditorPart, java.lang.String) + */ + public void launch(IEditorPart editor, String mode) { + } + +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/launcher/PDAMainTab.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/launcher/PDAMainTab.java new file mode 100644 index 000000000..59217fb54 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/launcher/PDAMainTab.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * 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.ui.pda.launcher; + + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.examples.core.pda.DebugCorePlugin; +import org.eclipse.debug.examples.ui.pda.DebugUIPlugin; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.dialogs.ResourceListSelectionDialog; + + +/** + * Tab to specify the PDA program to run/debug. + */ +public class PDAMainTab extends AbstractLaunchConfigurationTab { + + private Text fProgramText; + private Button fProgramButton; + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite) + */ + public void createControl(Composite parent) { + Font font = parent.getFont(); + + Composite comp = new Composite(parent, SWT.NONE); + setControl(comp); + GridLayout topLayout = new GridLayout(); + topLayout.verticalSpacing = 0; + topLayout.numColumns = 3; + comp.setLayout(topLayout); + comp.setFont(font); + + createVerticalSpacer(comp, 3); + + Label programLabel = new Label(comp, SWT.NONE); + programLabel.setText("&Program:"); + GridData gd = new GridData(GridData.BEGINNING); + programLabel.setLayoutData(gd); + programLabel.setFont(font); + + fProgramText = new Text(comp, SWT.SINGLE | SWT.BORDER); + gd = new GridData(GridData.FILL_HORIZONTAL); + fProgramText.setLayoutData(gd); + fProgramText.setFont(font); + fProgramText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateLaunchConfigurationDialog(); + } + }); + + fProgramButton = createPushButton(comp, "&Browse...", null); //$NON-NLS-1$ + fProgramButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + browsePDAFiles(); + } + }); + } + + /** + * Open a resource chooser to select a PDA program + */ + protected void browsePDAFiles() { + ResourceListSelectionDialog dialog = new ResourceListSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(), IResource.FILE); + dialog.setTitle("PDA Program"); + dialog.setMessage("Select PDA Program"); + if (dialog.open() == Window.OK) { + Object[] files = dialog.getResult(); + IFile file = (IFile) files[0]; + fProgramText.setText(file.getFullPath().toString()); + } + + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) + */ + public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration) + */ + public void initializeFrom(ILaunchConfiguration configuration) { + //#ifdef ex1 +//# // TODO: Exercise 1 - retrieve the program path attribute from the launch configuration +//# String program = null; +//# if (program != null) { +//# fProgramText.setText(program); +//# } + //#else + try { + String program = null; + program = configuration.getAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, (String)null); + if (program != null) { + fProgramText.setText(program); + } + } catch (CoreException e) { + setErrorMessage(e.getMessage()); + } + //#endif + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) + */ + public void performApply(ILaunchConfigurationWorkingCopy configuration) { + String program = fProgramText.getText().trim(); + if (program.length() == 0) { + program = null; + } + //#ifdef ex1 +//# // TODO: Exercise 1 - update the launch configuration with the path to +//# // currently specified program + //#else + configuration.setAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, program); + //#endif + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName() + */ + public String getName() { + return "Main"; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration) + */ + public boolean isValid(ILaunchConfiguration launchConfig) { + setErrorMessage(null); + setMessage(null); + String text = fProgramText.getText(); + //#ifdef ex1 +//# // TODO: Exercise 1 - validate the currently specified program exists and is not +//# // empty, providing the user with feedback. + //#else + if (text.length() > 0) { + IPath path = new Path(text); + if (ResourcesPlugin.getWorkspace().getRoot().findMember(path) == null) { + setErrorMessage("Specified program does not exist"); + return false; + } + } else { + setMessage("Specify a program"); + } + //#endif + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getImage() + */ + public Image getImage() { + return DebugUIPlugin.getDefault().getImageRegistry().get(DebugUIPlugin.IMG_OBJ_PDA); + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/launcher/PDATabGroup.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/launcher/PDATabGroup.java new file mode 100644 index 000000000..6f1753c45 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/launcher/PDATabGroup.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * 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.ui.pda.launcher; + +import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup; +import org.eclipse.debug.ui.CommonTab; +import org.eclipse.debug.ui.ILaunchConfigurationDialog; +import org.eclipse.debug.ui.ILaunchConfigurationTab; +import org.eclipse.debug.ui.sourcelookup.SourceLookupTab; + +/** + * Tab group for a PDA application + */ +public class PDATabGroup extends AbstractLaunchConfigurationTabGroup { + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ILaunchConfigurationTabGroup#createTabs(org.eclipse.debug.ui.ILaunchConfigurationDialog, java.lang.String) + */ + public void createTabs(ILaunchConfigurationDialog dialog, String mode) { + //#ifdef ex1 +//# // TODO: Exercise 1 - add the PDA main tab, source lookup tab and common +//# // tab to the tab group + //#else + setTabs(new ILaunchConfigurationTab[] { + new PDAMainTab(), + new SourceLookupTab(), + new CommonTab() + }); + //#endif + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/presentation/PDAModelPresentation.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/presentation/PDAModelPresentation.java new file mode 100644 index 000000000..7d5d3ba91 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/presentation/PDAModelPresentation.java @@ -0,0 +1,192 @@ +/******************************************************************************* + * 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.ui.pda.presentation; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.debug.core.model.ILineBreakpoint; +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.PDAWatchpoint; +import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.pda.model.PDAStackFrame; +import org.eclipse.debug.examples.core.pda.model.PDAThread; +import org.eclipse.debug.ui.IDebugModelPresentation; +import org.eclipse.debug.ui.IValueDetailListener; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.part.FileEditorInput; + + +/** + * Renders PDA debug elements + */ +public class PDAModelPresentation extends LabelProvider implements IDebugModelPresentation { + /* (non-Javadoc) + * @see org.eclipse.debug.ui.IDebugModelPresentation#setAttribute(java.lang.String, java.lang.Object) + */ + public void setAttribute(String attribute, Object value) { + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object) + */ + public String getText(Object element) { + if (element instanceof PDADebugTarget) { + return getTargetText((PDADebugTarget)element); + } else if (element instanceof PDAThread) { + return getThreadText((PDAThread)element); + } else if (element instanceof PDAStackFrame) { + return getStackFrameText((PDAStackFrame)element); + } else if (element instanceof PDAWatchpoint) { + return getWatchpointText((PDAWatchpoint)element); + } + return null; + } + + /** + * Returns a label for the given watchpoint. + * + * @param watchpoint + * @return a label for the given watchpoint + */ + private String getWatchpointText(PDAWatchpoint watchpoint) { + try { + String label = watchpoint.getVariableName() + " (" + watchpoint.getFunctionName() + ")"; + if (watchpoint.isAccess()) { + label += " [read]"; + } + if (watchpoint.isModification()) { + label += " [write]"; + } + return label; + } catch (CoreException e) { + return null; + } + } + /** + * Returns a label for the given debug target + * + * @param target debug target + * @return a label for the given debug target + */ + private String getTargetText(PDADebugTarget target) { + try { + String pgmPath = target.getLaunch().getLaunchConfiguration().getAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, (String)null); + if (pgmPath != null) { + IPath path = new Path(pgmPath); + String label = ""; + if (target.isTerminated()) { + label = "<terminated>"; + } + return label + "PDA [" + path.lastSegment() + "]"; + } + } catch (CoreException e) { + } + return "PDA"; + + } + + /** + * Returns a label for the given stack frame + * + * @param frame a stack frame + * @return a label for the given stack frame + */ + private String getStackFrameText(PDAStackFrame frame) { + try { + return frame.getName() + " (line: " + frame.getLineNumber() + ")"; + } catch (DebugException e) { + } + return null; + + } + + /** + * Returns a label for the given thread + * + * @param thread a thread + * @return a label for the given thread + */ + private String getThreadText(PDAThread thread) { + String label = thread.getName(); + if (thread.isStepping()) { + label += " (stepping)"; + } else if (thread.isSuspended()) { + IBreakpoint[] breakpoints = thread.getBreakpoints(); + if (breakpoints.length == 0) { + if (thread.getError() == null) { + label += " (suspended)"; + } else { + label += " (" + thread.getError() + ")"; + } + } else { + IBreakpoint breakpoint = breakpoints[0]; // there can only be one in PDA + if (breakpoint instanceof PDALineBreakpoint) { + PDALineBreakpoint pdaBreakpoint = (PDALineBreakpoint) breakpoint; + if (pdaBreakpoint instanceof PDAWatchpoint) { + try { + PDAWatchpoint watchpoint = (PDAWatchpoint)pdaBreakpoint; + label += " (watchpoint: " + watchpoint.getSuspendType() + " " + watchpoint.getVariableName() + ")"; + } catch (CoreException e) { + } + } else if (pdaBreakpoint.isRunToLineBreakpoint()) { + label += " (run to line)"; + } else { + label += " (suspended at line breakpoint)"; + } + } + } + } else if (thread.isTerminated()) { + label = "<terminated> " + label; + } + return label; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.IDebugModelPresentation#computeDetail(org.eclipse.debug.core.model.IValue, org.eclipse.debug.ui.IValueDetailListener) + */ + public void computeDetail(IValue value, IValueDetailListener listener) { + String detail = ""; + try { + detail = value.getValueString(); + } catch (DebugException e) { + } + listener.detailComputed(value, detail); + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ISourcePresentation#getEditorInput(java.lang.Object) + */ + public IEditorInput getEditorInput(Object element) { + if (element instanceof IFile) { + return new FileEditorInput((IFile)element); + } + if (element instanceof ILineBreakpoint) { + return new FileEditorInput((IFile)((ILineBreakpoint)element).getMarker().getResource()); + } + return null; + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.ISourcePresentation#getEditorId(org.eclipse.ui.IEditorInput, java.lang.Object) + */ + public String getEditorId(IEditorInput input, Object element) { + if (element instanceof IFile || element instanceof ILineBreakpoint) { + return "pda.editor"; + } + return null; + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/DataStackView.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/DataStackView.java new file mode 100644 index 000000000..234fe30ec --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/DataStackView.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * 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.ui.pda.views; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IDebugElement; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.examples.core.pda.DebugCorePlugin; +import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.ui.AbstractDebugView; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchActionConstants; +import org.eclipse.ui.IWorkbenchPart; + + +/** + * View of the PDA VM data stack + */ +public class DataStackView extends AbstractDebugView implements ISelectionListener { + + private PDADebugTarget fTarget; + private PopAction fPopAction; + private PushAction fPushAction; + + class StackViewContentProvider implements ITreeContentProvider { + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof PDADebugTarget) { + try { + return ((PDADebugTarget)parentElement).getDataStack(); + } catch (DebugException e) { + } + } + return new Object[0]; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) + */ + public Object getParent(Object element) { + if (element instanceof IDebugTarget) { + return null; + } else { + return ((IDebugElement)element).getDebugTarget(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) + */ + public boolean hasChildren(Object element) { + if (element instanceof IDebugElement) { + return getChildren(element).length > 0; + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.AbstractDebugView#createViewer(org.eclipse.swt.widgets.Composite) + */ + protected Viewer createViewer(Composite parent) { + TreeViewer viewer = new TreeViewer(parent); + viewer.setLabelProvider(DebugUITools.newDebugModelPresentation()); + viewer.setContentProvider(new StackViewContentProvider()); + getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this); + getSite().setSelectionProvider(viewer); + return viewer; + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.AbstractDebugView#createActions() + */ + protected void createActions() { + fPopAction = new PopAction(this); + fPushAction = new PushAction(this); + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.AbstractDebugView#getHelpContextId() + */ + protected String getHelpContextId() { + return null; + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.AbstractDebugView#fillContextMenu(org.eclipse.jface.action.IMenuManager) + */ + protected void fillContextMenu(IMenuManager menu) { + menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); + menu.add(fPopAction); + menu.add(fPushAction); + } + /* (non-Javadoc) + * @see org.eclipse.debug.ui.AbstractDebugView#configureToolBar(org.eclipse.jface.action.IToolBarManager) + */ + protected void configureToolBar(IToolBarManager tbm) { + tbm.add(fPopAction); + tbm.add(fPushAction); + } + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPart#dispose() + */ + public void dispose() { + getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this); + super.dispose(); + } + /* (non-Javadoc) + * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + update(); + } + + /** + * Updates the view for the selected target (if suspended) + */ + private synchronized void update() { + IAdaptable adaptable = DebugUITools.getDebugContext(); + fTarget = null; + if (adaptable != null) { + IDebugElement element = (IDebugElement) adaptable.getAdapter(IDebugElement.class); + if (element != null) { + if (element.getModelIdentifier().equals(DebugCorePlugin.ID_PDA_DEBUG_MODEL)) { + fTarget = (PDADebugTarget) element.getDebugTarget(); + } + } + } + Object input = null; + if (fTarget != null && fTarget.isSuspended()) { + input = fTarget; + } + getViewer().setInput(input); + fPushAction.setDebugTarget(fTarget); + getViewer().refresh(); + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PopAction.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PopAction.java new file mode 100644 index 000000000..af21fbcc6 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PopAction.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * 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.ui.pda.views; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IValue; +import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.ui.pda.DebugUIPlugin; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeViewer; + + +/** + * Pops a selected value off the data stack. The selection does <b>not</b> have to be + * the top element on the stack. + */ +public class PopAction extends Action implements ISelectionChangedListener { + + private DataStackView fView; + + /** + * Constructs an action to pop values off the stack + */ + protected PopAction(DataStackView view) { + super("Pop"); + ImageRegistry imageRegistry = DebugUIPlugin.getDefault().getImageRegistry(); + setImageDescriptor(imageRegistry.getDescriptor(DebugUIPlugin.IMG_ELCL_POP)); + setDisabledImageDescriptor(imageRegistry.getDescriptor(DebugUIPlugin.IMG_DLCL_POP)); + setToolTipText("Pop"); + setEnabled(false); + view.getSite().getSelectionProvider().addSelectionChangedListener(this); + fView = view; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) + */ + public void selectionChanged(SelectionChangedEvent event) { + if (event.getSelection().isEmpty()) { + setEnabled(false); + } else { + setEnabled(getDebugTarget().canPop()); + } + } + + public void run() { + TreeViewer viewer = (TreeViewer)fView.getViewer(); + IStructuredSelection selection = (IStructuredSelection)viewer.getSelection(); + Object popee = selection.getFirstElement(); + try { + PDADebugTarget target = getDebugTarget(); + IValue[] stack = target.getDataStack(); + List restore = new ArrayList(); + for (int i = 0; i < stack.length; i++) { + Object value = stack[i]; + if (popee.equals(value)) { + // pop & stop + target.pop(); + break; + } else { + // remember value to push back on + restore.add(target.pop()); + } + } + while (!restore.isEmpty()) { + IValue value = (IValue) restore.remove(restore.size() - 1); + target.push(value.getValueString()); + } + } catch (DebugException e) { + } + viewer.refresh(); + } + + /** + * Returns the debug target assocaited with the data view. + * + * @return the debug target assocaited with the data view + */ + protected PDADebugTarget getDebugTarget() { + TreeViewer viewer = (TreeViewer)fView.getViewer(); + return (PDADebugTarget) viewer.getInput(); + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PushAction.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PushAction.java new file mode 100644 index 000000000..8764cf3bc --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PushAction.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * 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.ui.pda.views; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.ui.pda.DebugUIPlugin; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.dialogs.InputDialog; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.window.Window; + + +/** + * Pushes a value onto the data stack. + */ +public class PushAction extends Action { + + private PDADebugTarget fTarget; + private DataStackView fView; + + /** + * Constructs an action to pop values off the stack + */ + protected PushAction(DataStackView view) { + super("Push"); + ImageRegistry imageRegistry = DebugUIPlugin.getDefault().getImageRegistry(); + setImageDescriptor(imageRegistry.getDescriptor(DebugUIPlugin.IMG_ELCL_PUSH)); + setDisabledImageDescriptor(imageRegistry.getDescriptor(DebugUIPlugin.IMG_DLCL_PUSH)); + setToolTipText("Push"); + setEnabled(false); + fView = view; + } + + public void run() { + InputDialog dialog = new InputDialog(fView.getSite().getShell(), "Specify Value", "Enter value to push", null, null); + if (dialog.open() == Window.OK) { + try { + fTarget.push(dialog.getValue()); + } catch (DebugException e) { + } + } + fView.getViewer().refresh(); + } + + protected void setDebugTarget(PDADebugTarget target) { + fTarget = target; + setEnabled(fTarget != null && fTarget.canPush()); + } + + +} |