diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml index 7c086021cc0..9c9576c9076 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml @@ -162,6 +162,11 @@ + + + diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbRunToLineAdapterFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbRunToLineAdapterFactory.java new file mode 100644 index 00000000000..577fe1927fe --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbRunToLineAdapterFactory.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui; + +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbRunToLine; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.ISuspendResume; + +/** + * @since 2.0 + */ +public class GdbRunToLineAdapterFactory implements IAdapterFactory { + + static class GdbSuspendResume implements ISuspendResume, IAdaptable { + + private final GdbRunToLine fRunToLine; + + GdbSuspendResume(IExecutionDMContext execCtx) { + fRunToLine = new GdbRunToLine(execCtx); + } + + public Object getAdapter(Class adapter) { + if (adapter.isInstance(fRunToLine)) { + return fRunToLine; + } + return null; + } + + public boolean canResume() { return false; } + public boolean canSuspend() { return false; } + public boolean isSuspended() { return false; } + public void resume() throws DebugException {} + public void suspend() throws DebugException {} + } + + public Object getAdapter(Object adaptableObject, Class adapterType) { + if (ISuspendResume.class.equals(adapterType)) { + if (adaptableObject instanceof IDMVMContext) { + IExecutionDMContext execDmc = DMContexts.getAncestorOfType( + ((IDMVMContext)adaptableObject).getDMContext(), + IExecutionDMContext.class); + // It only makes sense to RunToLine if we are dealing with a thread, not a container + if (execDmc != null && !(execDmc instanceof IContainerDMContext)) { + return new GdbSuspendResume(execDmc); + } + } + } + return null; + } + + public Class[] getAdapterList() { + return new Class[] { ISuspendResume.class }; + } +} \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRunToLine.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRunToLine.java new file mode 100644 index 00000000000..047c6a85aaa --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRunToLine.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.actions; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; + +import org.eclipse.cdt.debug.core.model.IRunToLine; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.mi.service.IMIRunControl; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.ui.actions.IRunToLineTarget; + +/** + * Implements the CDT's run to line interface. This interface is called by CDT's + * {@link IRunToLineTarget} implementation. + * + * @since 2.0 + */ +public class GdbRunToLine implements IRunToLine { + + private final IExecutionDMContext fContext; + + public GdbRunToLine(IExecutionDMContext context) { + fContext = context; + } + + public boolean canRunToLine(IFile file, int lineNumber) { + return canRunToLine(); + } + + public boolean canRunToLine(String fileName, int lineNumber) { + return canRunToLine(); + } + + private boolean canRunToLine() { + DsfSession session = DsfSession.getSession(fContext.getSessionId()); + if (session != null && session.isActive()) { + try { + Query query = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + DsfServicesTracker tracker = + new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fContext.getSessionId()); + + IRunControl runControl = tracker.getService(IRunControl.class); + if (runControl != null) { + runControl.canResume(fContext, rm); + } else { + rm.setData(false); + rm.done(); + } + tracker.dispose(); + } + }; + session.getExecutor().execute(query); + return query.get(); + } catch (RejectedExecutionException e) { + } catch (InterruptedException e) { + } catch (ExecutionException e) { + } + } + return false; + } + + public void runToLine(IFile file, int lineNumber, boolean skipBreakpoints) throws DebugException { + runToLine(file.getLocation().makeAbsolute().toOSString(), lineNumber, skipBreakpoints); + } + + public void runToLine(final String fileName, final int lineNumber, final boolean skipBreakpoints) throws DebugException { + DsfSession session = DsfSession.getSession(fContext.getSessionId()); + if (session != null && session.isActive()) { + Throwable exception = null; + try { + Query query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + DsfServicesTracker tracker = + new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fContext.getSessionId()); + + IMIRunControl miRunControl = tracker.getService(IMIRunControl.class); + if (miRunControl != null) { + miRunControl.runToLine( + fContext, fileName, Integer.toString(lineNumber), skipBreakpoints, + new DataRequestMonitor(ImmediateExecutor.getInstance(), rm) { + @Override + protected void handleSuccess() { + rm.setData(new Object()); + rm.done(); + }; + }); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "MIRunControl service not available", null)); //$NON-NLS-1$ + rm.done(); + } + tracker.dispose(); + } + }; + session.getExecutor().execute(query); + query.get(); + } catch (RejectedExecutionException e) { + exception = e; + } catch (InterruptedException e) { + exception = e; + } catch (ExecutionException e) { + exception = e; + } + if (exception != null) { + new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Faild executing run to line", exception)); //$NON-NLS-1$ + } + } else { + new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Debug session is not active", null)); //$NON-NLS-1$ + } + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java index 9c261ad877b..b4705963f90 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java @@ -24,26 +24,60 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIProcesses; +import org.eclipse.cdt.dsf.mi.service.IMIRunControl; import org.eclipse.cdt.dsf.mi.service.MIRunControl; import org.eclipse.cdt.dsf.mi.service.MIStack; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue; +import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent; +import org.eclipse.cdt.dsf.mi.service.command.events.MIInferiorExitEvent; +import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadExitEvent; +import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; +import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; public class GDBRunControl extends MIRunControl { + + private static class RunToLineActiveOperation { + private IMIExecutionDMContext fThreadContext; + private int fBpId; + private String fLocation; + private boolean fSkipBreakpoints; + + public RunToLineActiveOperation(IMIExecutionDMContext threadContext, + int bpId, String location, boolean skipBreakpoints) { + fThreadContext = threadContext; + fBpId = bpId; + fLocation = location; + fSkipBreakpoints = skipBreakpoints; + } + + public IMIExecutionDMContext getThreadContext() { return fThreadContext; } + public int getBreakointId() { return fBpId; } + public String getLocation() { return fLocation; } + public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; } + } + private IGDBBackend fGdb; private IMIProcesses fProcService; // Record list of execution contexts private IExecutionDMContext[] fOldExecutionCtxts; + private RunToLineActiveOperation fRunToLineActiveOperation = null; + public GDBRunControl(DsfSession session) { super(session); @@ -65,6 +99,7 @@ public class GDBRunControl extends MIRunControl { fProcService = getServicesTracker().getService(IMIProcesses.class); register(new String[]{IRunControl.class.getName(), + IMIRunControl.class.getName(), MIRunControl.class.getName(), GDBRunControl.class.getName()}, new Hashtable()); requestMonitor.done(); @@ -210,4 +245,108 @@ public class GDBRunControl extends MIRunControl { canResume(context, rm); } + /** @since 2.0 */ + @Override + public void runToLine(final IExecutionDMContext context, String fileName, String lineNo, final boolean skipBreakpoints, final DataRequestMonitor rm){ + // Later add support for Address and function. + + assert context != null; + + final IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); + if (dmc == null){ + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Given context: " + context + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$ + rm.done(); + return; + } + + if (doCanResume(context)) { + final String location = fileName + ":" + lineNo; //$NON-NLS-1$ + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class); + getConnection().queueCommand( + new MIBreakInsert(bpDmc, true, false, null, 0, + location, dmc.getThreadId()), + new DataRequestMonitor(getExecutor(), rm) { + @Override + public void handleSuccess() { + // We must set are RunToLineActiveOperation *before* we do the resume + // or else we may get the stopped event, before we have set this variable. + int bpId = getData().getMIBreakpoints()[0].getNumber(); + fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, location, skipBreakpoints); + + resume(context, new RequestMonitor(getExecutor(), rm) { + @Override + public void handleFailure() { + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), + IBreakpointsTargetDMContext.class); + int bpId = fRunToLineActiveOperation.getBreakointId(); + + getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + new DataRequestMonitor(getExecutor(), null)); + fRunToLineActiveOperation = null; + + super.handleFailure(); + } + }); + } + }); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, + "Cannot resume given DMC.", null)); //$NON-NLS-1$ + rm.done(); + } + } + + /** + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + * + * @since 2.0 + */ + @DsfServiceEventHandler + public void eventDispatched(MIInferiorExitEvent e) { + if (fRunToLineActiveOperation != null) { + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), + IBreakpointsTargetDMContext.class); + int bpId = fRunToLineActiveOperation.getBreakointId(); + + getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + new DataRequestMonitor(getExecutor(), null)); + fRunToLineActiveOperation = null; + } + } + + /** @since 2.0 */ + @Override + @DsfServiceEventHandler + public void eventDispatched(final MIStoppedEvent e) { + if (fRunToLineActiveOperation != null) { + String location = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$ + if (location.equals(fRunToLineActiveOperation.getLocation())) { + // We stopped on our temporary breakpoint. All is well. + fRunToLineActiveOperation = null; + } else { + // Didn't stop at the right line yet + if (fRunToLineActiveOperation.shouldSkipBreakpoints() && e instanceof MIBreakpointHitEvent) { + getConnection().queueCommand( + new MIExecContinue(fRunToLineActiveOperation.getThreadContext()), + new DataRequestMonitor(getExecutor(), null)); + + // Don't send the stop event since we are resuming again. + return; + } else { + // Stopped at another breakpoint or not a breakpoint at all. Just remove our temporary one + // since we don't want it to hit later + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), + IBreakpointsTargetDMContext.class); + int bpId = fRunToLineActiveOperation.getBreakointId(); + + getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + new DataRequestMonitor(getExecutor(), null)); + fRunToLineActiveOperation = null; + } + } + } + + super.eventDispatched(e); + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java index 362b433da1f..cd443748e11 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java @@ -23,6 +23,7 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; @@ -30,9 +31,13 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommand import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIProcesses; +import org.eclipse.cdt.dsf.mi.service.IMIRunControl; import org.eclipse.cdt.dsf.mi.service.MIRunControl; import org.eclipse.cdt.dsf.mi.service.MIStack; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert; import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseContinue; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseNext; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseNextInstruction; @@ -40,18 +45,46 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseStep; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseStepInstruction; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecUncall; import org.eclipse.cdt.dsf.mi.service.command.commands.RawCommand; +import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent; +import org.eclipse.cdt.dsf.mi.service.command.events.MIInferiorExitEvent; +import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; +import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo; import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; +import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunControl { + + private static class RunToLineActiveOperation { + private IMIExecutionDMContext fThreadContext; + private int fBpId; + private String fLocation; + private boolean fSkipBreakpoints; + + public RunToLineActiveOperation(IMIExecutionDMContext threadContext, + int bpId, String location, boolean skipBreakpoints) { + fThreadContext = threadContext; + fBpId = bpId; + fLocation = location; + fSkipBreakpoints = skipBreakpoints; + } + + public IMIExecutionDMContext getThreadContext() { return fThreadContext; } + public int getBreakointId() { return fBpId; } + public String getLocation() { return fLocation; } + public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; } + } + private IGDBBackend fGdb; private IMIProcesses fProcService; private boolean fReverseSupported = true; private boolean fReverseStepping = false; private boolean fReverseModeEnabled = false; + private RunToLineActiveOperation fRunToLineActiveOperation = null; + public GDBRunControl_7_0(DsfSession session) { super(session); } @@ -76,7 +109,9 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro fReverseSupported = false; } - register(new String[]{IRunControl.class.getName(), MIRunControl.class.getName(), + register(new String[]{IRunControl.class.getName(), + IMIRunControl.class.getName(), + MIRunControl.class.getName(), IReverseRunControl.class.getName()}, new Hashtable()); requestMonitor.done(); @@ -400,6 +435,111 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro } } + /** @since 2.0 */ + @Override + public void runToLine(final IExecutionDMContext context, String fileName, String lineNo, final boolean skipBreakpoints, final DataRequestMonitor rm){ + // Later add support for Address and function. + + assert context != null; + + final IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); + if (dmc == null){ + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Given context: " + context + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$ + rm.done(); + return; + } + + if (doCanResume(context)) { + final String location = fileName + ":" + lineNo; //$NON-NLS-1$ + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class); + getConnection().queueCommand( + new MIBreakInsert(bpDmc, true, false, null, 0, + location, dmc.getThreadId()), + new DataRequestMonitor(getExecutor(), rm) { + @Override + public void handleSuccess() { + // We must set are RunToLineActiveOperation *before* we do the resume + // or else we may get the stopped event, before we have set this variable. + int bpId = getData().getMIBreakpoints()[0].getNumber(); + fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, location, skipBreakpoints); + + resume(context, new RequestMonitor(getExecutor(), rm) { + @Override + public void handleFailure() { + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), + IBreakpointsTargetDMContext.class); + int bpId = fRunToLineActiveOperation.getBreakointId(); + + getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + new DataRequestMonitor(getExecutor(), null)); + fRunToLineActiveOperation = null; + + super.handleFailure(); + } + }); + } + }); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, + "Cannot resume given DMC.", null)); //$NON-NLS-1$ + rm.done(); + } + } + + /** + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + * + * @since 2.0 + */ + @DsfServiceEventHandler + public void eventDispatched(MIInferiorExitEvent e) { + if (fRunToLineActiveOperation != null) { + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), + IBreakpointsTargetDMContext.class); + int bpId = fRunToLineActiveOperation.getBreakointId(); + + getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + new DataRequestMonitor(getExecutor(), null)); + fRunToLineActiveOperation = null; + } + } + + /** @since 2.0 */ + @Override + @DsfServiceEventHandler + public void eventDispatched(final MIStoppedEvent e) { + if (fRunToLineActiveOperation != null) { + String location = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$ + if (location.equals(fRunToLineActiveOperation.getLocation())) { + // We stopped on our temporary breakpoint. All is well. + fRunToLineActiveOperation = null; + } else { + // Didn't stop at the right line yet + if (fRunToLineActiveOperation.shouldSkipBreakpoints() && e instanceof MIBreakpointHitEvent) { + getConnection().queueCommand( + new MIExecContinue(fRunToLineActiveOperation.getThreadContext()), + new DataRequestMonitor(getExecutor(), null)); + + // Don't send the stop event since we are resuming again. + return; + } else { + // Stopped at another breakpoint. Just remove our temporary one + // since we don't want it to hit later + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), + IBreakpointsTargetDMContext.class); + int bpId = fRunToLineActiveOperation.getBreakointId(); + + getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + new DataRequestMonitor(getExecutor(), null)); + fRunToLineActiveOperation = null; + } + } + } + + super.eventDispatched(e); + } + /** @since 2.0 */ public void setReverseModeEnabled(boolean enabled) { fReverseModeEnabled = enabled; diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java index f2e38630626..327bccbe6fa 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java @@ -25,6 +25,7 @@ import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.datamodel.IDMEvent; import org.eclipse.cdt.dsf.debug.service.ICachingService; import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; @@ -33,8 +34,11 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommand import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIProcesses; +import org.eclipse.cdt.dsf.mi.service.IMIRunControl; import org.eclipse.cdt.dsf.mi.service.MIRunControl; import org.eclipse.cdt.dsf.mi.service.MIStack; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecFinish; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecInterrupt; @@ -42,11 +46,11 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecNext; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecNextInstruction; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStep; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStepInstruction; -import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecUntil; import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIErrorEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent; +import org.eclipse.cdt.dsf.mi.service.command.events.MIInferiorExitEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIRunningEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MISharedLibEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MISignalEvent; @@ -55,6 +59,7 @@ import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadCreatedEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadExitEvent; import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent; +import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo; import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; import org.eclipse.cdt.dsf.service.AbstractDsfService; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; @@ -75,7 +80,7 @@ import org.osgi.framework.BundleContext; * sync with the service state. * @since 1.1 */ -public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunControl, ICachingService +public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunControl, ICachingService { @Immutable private static class ExecutionData implements IExecutionDMData { @@ -192,6 +197,26 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont StateChangeReason fStateChangeReason; } + private static class RunToLineActiveOperation { + private IMIExecutionDMContext fThreadContext; + private int fBpId; + private String fLocation; + private boolean fSkipBreakpoints; + + public RunToLineActiveOperation(IMIExecutionDMContext threadContext, + int bpId, String location, boolean skipBreakpoints) { + fThreadContext = threadContext; + fBpId = bpId; + fLocation = location; + fSkipBreakpoints = skipBreakpoints; + } + + public IMIExecutionDMContext getThreadContext() { return fThreadContext; } + public int getBreakointId() { return fBpId; } + public String getLocation() { return fLocation; } + public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; } + } + /////////////////////////////////////////////////////////////////////////// // MIRunControlNS /////////////////////////////////////////////////////////////////////////// @@ -203,6 +228,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont // ThreadStates indexed by the execution context protected Map fThreadRunStates = new HashMap(); + private RunToLineActiveOperation fRunToLineActiveOperation = null; + /////////////////////////////////////////////////////////////////////////// // Initialization and shutdown /////////////////////////////////////////////////////////////////////////// @@ -222,7 +249,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont } private void doInitialize(final RequestMonitor rm) { - register(new String[]{IRunControl.class.getName()}, new Hashtable()); + register(new String[]{IRunControl.class.getName(), IMIRunControl.class.getName()}, new Hashtable()); fConnection = getServicesTracker().getService(ICommandControlService.class); getSession().addServiceEventListener(this, null); rm.done(); @@ -539,13 +566,11 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont // Run to line // ------------------------------------------------------------------------ - // Later add support for Address and function. - // skipBreakpoints is not used at the moment. Implement later - public void runToLine(IExecutionDMContext context, String fileName, String lineNo, boolean skipBreakpoints, final DataRequestMonitor rm) { + public void runToLine(IExecutionDMContext context, String fileName, String lineNo, final boolean skipBreakpoints, final DataRequestMonitor rm) { assert context != null; - IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); + final IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); if (dmc == null) { rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$ @@ -568,9 +593,44 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont return; } - threadState.fResumePending = true; - fConnection.queueCommand(new MIExecUntil(dmc, fileName + ":" + lineNo), //$NON-NLS-1$ - new DataRequestMonitor(getExecutor(), rm)); + final String location = fileName + ":" + lineNo; //$NON-NLS-1$ + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class); + fConnection.queueCommand( + new MIBreakInsert(bpDmc, true, false, null, 0, + location, dmc.getThreadId()), + new DataRequestMonitor(getExecutor(), rm) { + @Override + public void handleSuccess() { + // We must set are RunToLineActiveOperation *before* we do the resume + // or else we may get the stopped event, before we have set this variable. + int bpId = getData().getMIBreakpoints()[0].getNumber(); + + // It would have been nice to use the address returned by the break-insert as our location, + // but that does not always work because sometimes the address is + // + // Also, we could have used the breakpoint id to know if we hit the proper breakpoint, + // but that also doesn't always work because if there are many bp at that location, + // GDB will report hitting one of them but not all of them (although GDB does consider + // that all those bps did hit.) + fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, location, skipBreakpoints); + + resume(dmc, new RequestMonitor(getExecutor(), rm) { + @Override + public void handleFailure() { + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), + IBreakpointsTargetDMContext.class); + int bpId = fRunToLineActiveOperation.getBreakointId(); + + fConnection.queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + new DataRequestMonitor(getExecutor(), null)); + fRunToLineActiveOperation = null; + + super.handleFailure(); + } + }); + } + }); + } // ------------------------------------------------------------------------ @@ -673,6 +733,37 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont */ @DsfServiceEventHandler public void eventDispatched(final MIStoppedEvent e) { + if (fRunToLineActiveOperation != null) { + // First check if it is the right thread that stopped + IMIExecutionDMContext threadDmc = DMContexts.getAncestorOfType(e.getDMContext(), IMIExecutionDMContext.class); + if (fRunToLineActiveOperation.getThreadContext().equals(threadDmc)) { + String location = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$ + if (location.equals(fRunToLineActiveOperation.getLocation())) { + // We stopped on our temporary breakpoint. All is well. + fRunToLineActiveOperation = null; + } else { + // The right thread stopped but not at the right place yet + if (fRunToLineActiveOperation.shouldSkipBreakpoints() && e instanceof MIBreakpointHitEvent) { + fConnection.queueCommand( + new MIExecContinue(fRunToLineActiveOperation.getThreadContext()), + new DataRequestMonitor(getExecutor(), null)); + + // Don't send the stop event since we are resuming again. + return; + } else { + // Stopped for any other reasons. Just remove our temporary one + // since we don't want it to hit later + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), + IBreakpointsTargetDMContext.class); + int bpId = fRunToLineActiveOperation.getBreakointId(); + + fConnection.queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + new DataRequestMonitor(getExecutor(), null)); + fRunToLineActiveOperation = null; + } + } + } + } getSession().dispatchEvent(new SuspendedEvent(e.getDMContext(), e), getProperties()); } @@ -761,6 +852,26 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont fTerminated = true; } + + /** + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + * + * @since 2.0 + */ + @DsfServiceEventHandler + public void eventDispatched(MIInferiorExitEvent e) { + if (fRunToLineActiveOperation != null) { + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), + IBreakpointsTargetDMContext.class); + int bpId = fRunToLineActiveOperation.getBreakointId(); + + fConnection.queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + new DataRequestMonitor(getExecutor(), null)); + fRunToLineActiveOperation = null; + } + } + public void flushCache(IDMContext context) { } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/IMIRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/IMIRunControl.java new file mode 100644 index 00000000000..f949621b60f --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/IMIRunControl.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2009 Ericsson 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: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; + +/** + * This interface provides methods for RunControl that are not + * part of the standard DSF IRunControl + * + * @since 2.0 + */ +public interface IMIRunControl extends IRunControl +{ + /** + * Request to run the program up to the specified location. + * If skipBreakpoints is false, any other breakpoint will stop this + * command; while if skipBreakpoints is true, the operation will ignore + * other breakpoints and continue until the specified location. + */ + void runToLine(IExecutionDMContext context, String fileName, String lineNo, + boolean skipBreakpoints, DataRequestMonitor rm); +} + diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java index dd5b5833ff5..0d53fa48d70 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java @@ -20,7 +20,6 @@ import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.datamodel.IDMEvent; import org.eclipse.cdt.dsf.debug.service.ICachingService; -import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.debug.service.command.CommandCache; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; @@ -73,7 +72,7 @@ import org.osgi.framework.BundleContext; * events and track service state, to be perfectly in sync with the service * state. */ -public class MIRunControl extends AbstractDsfService implements IRunControl, ICachingService +public class MIRunControl extends AbstractDsfService implements IMIRunControl, ICachingService { private static class MIExecutionDMC extends AbstractDMContext implements IMIExecutionDMContext { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor_7_0.java index 0045d085787..151105843b8 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor_7_0.java @@ -242,87 +242,91 @@ public class MIRunControlEventProcessor_7_0 } protected MIEvent createEvent(String reason, MIExecAsyncOutput exec) { - String threadId = null; - String groupId = null; - - MIResult[] results = exec.getMIResults(); - for (int i = 0; i < results.length; i++) { - String var = results[i].getVariable(); - MIValue val = results[i].getMIValue(); - - if (var.equals("thread-id")) { //$NON-NLS-1$ - if (val instanceof MIConst) { - threadId = ((MIConst)val).getString(); - } - } else if (var.equals("group-id")) { //$NON-NLS-1$ - if (val instanceof MIConst) { - groupId = ((MIConst)val).getString(); - } - } - } - - IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class); - if (procService == null) { - return null; - } - - IProcessDMContext procDmc = null; - IContainerDMContext containerDmc = null; - if (groupId == null) { - // MI does not currently provide the group-id in these events - if (threadId != null) { - containerDmc = procService.createContainerContextFromThreadId(fControlDmc, threadId); - procDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class); - } - } else { - // This code would only trigger if the groupId was provided by MI - procDmc = procService.createProcessContext(fControlDmc, groupId); - containerDmc = procService.createContainerContext(procDmc, groupId); - } - - IExecutionDMContext execDmc = containerDmc; - if (threadId != null) { - IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId); - execDmc = procService.createExecutionContext(containerDmc, threadDmc, threadId); - } - - if (execDmc == null) { - // Badly formatted event - return null; - } - MIEvent event = null; - if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$ - event = MIBreakpointHitEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); - } else if ( - "watchpoint-trigger".equals(reason) //$NON-NLS-1$ - || "read-watchpoint-trigger".equals(reason) //$NON-NLS-1$ - || "access-watchpoint-trigger".equals(reason)) { //$NON-NLS-1$ - event = MIWatchpointTriggerEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); - } else if ("watchpoint-scope".equals(reason)) { //$NON-NLS-1$ - event = MIWatchpointScopeEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); - } else if ("end-stepping-range".equals(reason)) { //$NON-NLS-1$ - event = MISteppingRangeEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); - } else if ("signal-received".equals(reason)) { //$NON-NLS-1$ - event = MISignalEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); - } else if ("location-reached".equals(reason)) { //$NON-NLS-1$ - event = MILocationReachedEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); - } else if ("function-finished".equals(reason)) { //$NON-NLS-1$ - event = MIFunctionFinishedEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); - } else if ("exited-normally".equals(reason) || "exited".equals(reason)) { //$NON-NLS-1$ //$NON-NLS-2$ + + if ("exited-normally".equals(reason) || "exited".equals(reason)) { //$NON-NLS-1$ //$NON-NLS-2$ event = MIInferiorExitEvent.parse(fCommandControl.getContext(), exec.getToken(), exec.getMIResults()); } else if ("exited-signalled".equals(reason)) { //$NON-NLS-1$ event = MIInferiorSignalExitEvent.parse(fCommandControl.getContext(), exec.getToken(), exec.getMIResults()); - } else if (STOPPED_REASON.equals(reason)) { - event = MIStoppedEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); - } else if (RUNNING_REASON.equals(reason)) { - // Retrieve the type of command from what we last stored - int type = MIRunningEvent.CONTINUE; - if (fLastRunningCmdType != null) { - type = fLastRunningCmdType; - fLastRunningCmdType = null; + } else { + + String threadId = null; + String groupId = null; + + MIResult[] results = exec.getMIResults(); + for (int i = 0; i < results.length; i++) { + String var = results[i].getVariable(); + MIValue val = results[i].getMIValue(); + + if (var.equals("thread-id")) { //$NON-NLS-1$ + if (val instanceof MIConst) { + threadId = ((MIConst)val).getString(); + } + } else if (var.equals("group-id")) { //$NON-NLS-1$ + if (val instanceof MIConst) { + groupId = ((MIConst)val).getString(); + } + } + } + + IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class); + if (procService == null) { + return null; + } + + IProcessDMContext procDmc = null; + IContainerDMContext containerDmc = null; + if (groupId == null) { + // MI does not currently provide the group-id in these events + if (threadId != null) { + containerDmc = procService.createContainerContextFromThreadId(fControlDmc, threadId); + procDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class); + } + } else { + // This code would only trigger if the groupId was provided by MI + procDmc = procService.createProcessContext(fControlDmc, groupId); + containerDmc = procService.createContainerContext(procDmc, groupId); + } + + IExecutionDMContext execDmc = containerDmc; + if (threadId != null) { + IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId); + execDmc = procService.createExecutionContext(containerDmc, threadDmc, threadId); + } + + if (execDmc == null) { + // Badly formatted event + return null; + } + + if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$ + event = MIBreakpointHitEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); + } else if ( + "watchpoint-trigger".equals(reason) //$NON-NLS-1$ + || "read-watchpoint-trigger".equals(reason) //$NON-NLS-1$ + || "access-watchpoint-trigger".equals(reason)) { //$NON-NLS-1$ + event = MIWatchpointTriggerEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); + } else if ("watchpoint-scope".equals(reason)) { //$NON-NLS-1$ + event = MIWatchpointScopeEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); + } else if ("end-stepping-range".equals(reason)) { //$NON-NLS-1$ + event = MISteppingRangeEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); + } else if ("signal-received".equals(reason)) { //$NON-NLS-1$ + event = MISignalEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); + } else if ("location-reached".equals(reason)) { //$NON-NLS-1$ + event = MILocationReachedEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); + } else if ("function-finished".equals(reason)) { //$NON-NLS-1$ + event = MIFunctionFinishedEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); + } else if (STOPPED_REASON.equals(reason)) { + event = MIStoppedEvent.parse(execDmc, exec.getToken(), exec.getMIResults()); + } else if (RUNNING_REASON.equals(reason)) { + // Retrieve the type of command from what we last stored + int type = MIRunningEvent.CONTINUE; + if (fLastRunningCmdType != null) { + type = fLastRunningCmdType; + fLastRunningCmdType = null; + } + event = new MIRunningEvent(execDmc, exec.getToken(), type); } - event = new MIRunningEvent(execDmc, exec.getToken(), type); } return event; }