diff options
Diffstat (limited to 'org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model')
11 files changed, 1815 insertions, 0 deletions
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 + } + +} |