/*******************************************************************************
* Copyright (c) 2004, 2009 QNX Software 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:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.internal.core.model;
import java.math.BigInteger;
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.core.IAddressFactory;
import org.eclipse.cdt.debug.core.cdi.CDIException;
import org.eclipse.cdt.debug.core.cdi.ICDILocation;
import org.eclipse.cdt.debug.core.cdi.ICDILocator;
import org.eclipse.cdt.debug.core.cdi.event.ICDIEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDIEventListener;
import org.eclipse.cdt.debug.core.cdi.model.ICDIDisposable;
import org.eclipse.cdt.debug.core.cdi.model.ICDIExecuteMoveInstructionPointer;
import org.eclipse.cdt.debug.core.cdi.model.ICDIExecuteResume;
import org.eclipse.cdt.debug.core.cdi.model.ICDIExpression;
import org.eclipse.cdt.debug.core.cdi.model.ICDIStackFrame;
import org.eclipse.cdt.debug.core.cdi.model.ICDIThread;
import org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor;
import org.eclipse.cdt.debug.core.model.ICGlobalVariable;
import org.eclipse.cdt.debug.core.model.ICStackFrame;
import org.eclipse.cdt.debug.core.model.IMoveToAddress;
import org.eclipse.cdt.debug.core.model.IMoveToLine;
import org.eclipse.cdt.debug.core.model.IRestart;
import org.eclipse.cdt.debug.core.model.IResumeAtAddress;
import org.eclipse.cdt.debug.core.model.IResumeAtLine;
import org.eclipse.cdt.debug.core.model.IResumeWithoutSignal;
import org.eclipse.cdt.debug.core.model.IRunToAddress;
import org.eclipse.cdt.debug.core.model.IRunToLine;
import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocator;
import org.eclipse.cdt.debug.internal.core.CGlobalVariableManager;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.IRegisterGroup;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IVariable;
/**
* Proxy to a stack frame on the target.
*/
public class CStackFrame extends CDebugElement implements ICStackFrame, IRestart, IResumeWithoutSignal, IMoveToAddress, IMoveToLine, ICDIEventListener {
/**
* Underlying CDI stack frame.
*/
private ICDIStackFrame fCDIStackFrame;
/**
* The last (previous) CDI stack frame.
*/
private ICDIStackFrame fLastCDIStackFrame;
/**
* Containing thread.
*/
private CThread fThread;
/**
* List of visible variable (includes arguments).
*/
private List fVariables;
/**
* Whether the variables need refreshing
*/
private boolean fRefreshVariables = true;
/**
* List of watch expressions evaluating in the context of this frame.
*/
private List fExpressions;
/**
* Need this flag to prevent evaluations on disposed frames.
*/
private boolean fIsDisposed = false;
/**
* Constructor for CStackFrame.
*/
public CStackFrame( CThread thread, ICDIStackFrame cdiFrame ) {
super( (CDebugTarget)thread.getDebugTarget() );
setCDIStackFrame( cdiFrame );
setThread( thread );
getCDISession().getEventManager().addEventListener( this );
}
/* (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 {
if ( isDisposed() ) {
return new IVariable[0];
}
ICGlobalVariable[] globals = getGlobals();
List vars = getVariables0();
List all = new ArrayList( globals.length + vars.size() );
all.addAll( Arrays.asList( globals ) );
all.addAll( vars );
return (IVariable[])all.toArray( new IVariable[all.size()] );
}
protected synchronized List getVariables0() throws DebugException {
if ( isDisposed() ) {
return Collections.EMPTY_LIST;
}
CThread thread = (CThread)getThread();
if ( thread.isSuspended() ) {
if ( fVariables == null ) {
List vars = getAllCDIVariableObjects();
fVariables = new ArrayList( vars.size() );
Iterator it = vars.iterator();
while( it.hasNext() ) {
fVariables.add( CVariableFactory.createLocalVariable( this, (ICDIVariableDescriptor)it.next() ) );
}
}
else if ( refreshVariables() ) {
updateVariables();
}
setRefreshVariables( false );
}
return ( fVariables != null ) ? fVariables : Collections.EMPTY_LIST;
}
/**
* Incrementally updates this stack frame's variables.
*/
protected void updateVariables() throws DebugException {
List locals = getAllCDIVariableObjects();
Iterator<CVariable> it = fVariables.iterator();
while (it.hasNext()) {
CVariable var = it.next();
ICDIVariableDescriptor varObject = findVariable(locals, var);
if (varObject != null && !var.isDisposed())
locals.remove(varObject);
else {
// ensure variable is unregistered from event listener
var.dispose();
it.remove();
}
}
// add any new locals
Iterator newOnes = locals.iterator();
while( newOnes.hasNext() ) {
fVariables.add( CVariableFactory.createLocalVariable( this, (ICDIVariableDescriptor)newOnes.next() ) );
}
}
/**
* Sets the containing thread.
*
* @param thread the containing thread
*/
protected void setThread( CThread thread ) {
fThread = thread;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#hasVariables()
*/
public boolean hasVariables() throws DebugException {
return ( isDisposed() ) ? false : (getVariables0().size() > 0 || getGlobals().length > 0);
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#getLineNumber()
*/
public int getLineNumber() throws DebugException {
if ( isSuspended() ) {
ISourceLocator locator = ((CDebugTarget)getDebugTarget()).getSourceLocator();
if ( locator != null && locator instanceof IAdaptable && ((IAdaptable)locator).getAdapter( ICSourceLocator.class ) != null )
return ((ICSourceLocator)((IAdaptable)locator).getAdapter( ICSourceLocator.class )).getLineNumber( this );
final ICDIStackFrame cdiFrame = getCDIStackFrame();
if ( cdiFrame != null && cdiFrame.getLocator() != null )
return cdiFrame.getLocator().getLineNumber();
}
return -1;
}
/* (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 {
final ICDIStackFrame cdiFrame = getCDIStackFrame();
if (cdiFrame == null) {
return ""; //$NON-NLS-1$
}
ICDILocator locator = cdiFrame.getLocator();
String func = ""; //$NON-NLS-1$
String file = ""; //$NON-NLS-1$
String line = ""; //$NON-NLS-1$
if ( locator.getFunction() != null && locator.getFunction().trim().length() > 0 )
func += locator.getFunction() + "() "; //$NON-NLS-1$
if ( locator.getFile() != null && locator.getFile().trim().length() > 0 ) {
file = locator.getFile();
if ( locator.getLineNumber() != 0 ) {
line = NumberFormat.getInstance().format( new Integer( locator.getLineNumber() ) );
}
}
else {
return func;
}
return MessageFormat.format( CoreModelMessages.getString( "CStackFrame.0" ), new String[]{ func, file, line } ); //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#getRegisterGroups()
*/
public IRegisterGroup[] getRegisterGroups() throws DebugException {
return ( isDisposed() ) ? new IRegisterGroup[0] : ((CDebugTarget)getDebugTarget()).getRegisterGroups( this );
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStackFrame#hasRegisterGroups()
*/
public boolean hasRegisterGroups() throws DebugException {
return ( isDisposed() ) ? false : ((CDebugTarget)getDebugTarget()).getRegisterGroups( this ).length > 0;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.cdi.event.ICDIEventListener#handleDebugEvents(org.eclipse.cdt.debug.core.cdi.event.ICDIEvent[])
*/
public void handleDebugEvents( ICDIEvent[] events ) {
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepInto()
*/
public boolean canStepInto() {
try {
return exists() /*&& isTopStackFrame()*/ && getThread().canStepInto();
}
catch( DebugException e ) {
logError( e );
return false;
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepOver()
*/
public boolean canStepOver() {
try {
return exists() && getThread().canStepOver();
}
catch( DebugException e ) {
logError( e );
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#canStepReturn()
*/
public boolean canStepReturn() {
try {
if ( !exists() ) {
return false;
}
List frames = ((CThread)getThread()).computeStackFrames();
if ( frames != null && !frames.isEmpty() ) {
boolean bottomFrame = this.equals( frames.get( frames.size() - 1 ) );
return !bottomFrame && getThread().canStepReturn();
}
}
catch( DebugException e ) {
logError( e );
}
return false;
}
/* (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 {
if ( canStepInto() ) {
getThread().stepInto();
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#stepOver()
*/
public void stepOver() throws DebugException {
if ( canStepOver() ) {
getThread().stepOver();
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.IStep#stepReturn()
*/
public void stepReturn() throws DebugException {
if ( canStepReturn() ) {
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() {
boolean exists = false;
try {
exists = exists();
}
catch( DebugException e ) {
logError( e );
}
return exists && getThread().canTerminate() || getDebugTarget().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 {
if ( getThread().canTerminate() ) {
getThread().terminate();
}
else {
getDebugTarget().terminate();
}
}
/**
* Returns the underlying CDI stack frame that this model object is a proxy to.
*
* @return the underlying CDI stack frame
*/
protected ICDIStackFrame getCDIStackFrame() {
return fCDIStackFrame;
}
/**
* Sets the underlying CDI stack frame. Called by a thread when incrementally updating after a step has completed.
*
* @param frame the underlying stack frame
*/
protected void setCDIStackFrame( ICDIStackFrame frame ) {
if ( frame != null ) {
fLastCDIStackFrame = frame;
}
else {
fLastCDIStackFrame = fCDIStackFrame;
}
fCDIStackFrame = frame;
setRefreshVariables( true );
}
/**
* The underlying stack frame that existed before the current underlying stack frame. Used only so that equality can be checked on stack frame after the new
* one has been set.
*/
protected ICDIStackFrame getLastCDIStackFrame() {
return fLastCDIStackFrame;
}
/**
* Helper method for computeStackFrames(). For the purposes of detecting if an underlying stack frame needs to be disposed, stack frames are equal if the
* frames are equal and the locations are equal.
*/
protected static boolean equalFrame( ICDIStackFrame frameOne, ICDIStackFrame frameTwo ) {
if ( frameOne == null || frameTwo == null )
return false;
ICDILocator loc1 = frameOne.getLocator();
ICDILocator loc2 = frameTwo.getLocator();
if ( loc1 == null || loc2 == null )
return false;
if ( loc1.getFile() != null && loc1.getFile().length() > 0 && loc2.getFile() != null && loc2.getFile().length() > 0 && loc1.getFile().equals( loc2.getFile() ) ) {
if ( loc1.getFunction() != null && loc1.getFunction().length() > 0 && loc2.getFunction() != null && loc2.getFunction().length() > 0 && loc1.getFunction().equals( loc2.getFunction() ) )
return true;
}
if ( (loc1.getFile() == null || loc1.getFile().length() < 1) && (loc2.getFile() == null || loc2.getFile().length() < 1) ) {
if ( loc1.getFunction() != null && loc1.getFunction().length() > 0 && loc2.getFunction() != null && loc2.getFunction().length() > 0 && loc1.getFunction().equals( loc2.getFunction() ) )
return true;
}
if ( (loc1.getFile() == null || loc1.getFile().length() < 1) && (loc2.getFile() == null || loc2.getFile().length() < 1) && (loc1.getFunction() == null || loc1.getFunction().length() < 1) && (loc2.getFunction() == null || loc2.getFunction().length() < 1) ) {
if ( loc1.getAddress() == loc2.getAddress() )
return true;
}
return false;
}
protected boolean exists() throws DebugException {
return ((CThread)getThread()).computeStackFrames().indexOf( this ) != -1;
}
/**
* @see IAdaptable#getAdapter(Class)
*/
public Object getAdapter( Class adapter ) {
if ( adapter == IRunToLine.class ) {
return this;
}
if ( adapter == IRunToAddress.class ) {
return this;
}
if ( adapter == IResumeAtLine.class ) {
return this;
}
if ( adapter == IResumeAtAddress.class ) {
return this;
}
if ( adapter == IMoveToLine.class ) {
return this;
}
if ( adapter == IMoveToAddress.class ) {
return this;
}
if ( adapter == CStackFrame.class ) {
return this;
}
if ( adapter == ICStackFrame.class ) {
return this;
}
if ( adapter == IStackFrame.class ) {
return this;
}
if ( adapter == ICDIStackFrame.class ) {
return getCDIStackFrame();
}
if ( adapter == IMemoryBlockRetrieval.class ) {
return getDebugTarget().getAdapter( adapter );
}
return super.getAdapter( adapter );
}
protected void dispose() {
setDisposed( true );
getCDISession().getEventManager().removeEventListener( this );
disposeAllVariables();
disposeExpressions();
final ICDIStackFrame cdiFrame = getCDIStackFrame();
setCDIStackFrame(null);
if (cdiFrame instanceof ICDIDisposable) {
((ICDIDisposable)cdiFrame).dispose();
}
}
/**
* Retrieves local variables in this stack frame. Returns an empty list if there are no local variables.
*
*/
protected List getCDILocalVariableObjects() throws DebugException {
List list = new ArrayList();
try {
final ICDIStackFrame cdiFrame = getCDIStackFrame();
if (cdiFrame != null) {
list.addAll( Arrays.asList( cdiFrame.getLocalVariableDescriptors( ) ) );
}
}
catch( CDIException e ) {
targetRequestFailed( e.getMessage(), null );
}
return list;
}
/**
* Retrieves arguments in this stack frame. Returns an empty list if there are no arguments.
*
*/
protected List getCDIArgumentObjects() throws DebugException {
List list = new ArrayList();
try {
final ICDIStackFrame cdiFrame = getCDIStackFrame();
if (cdiFrame != null) {
list.addAll( Arrays.asList( cdiFrame.getArgumentDescriptors() ) );
}
}
catch( CDIException e ) {
targetRequestFailed( e.getMessage(), null );
}
return list;
}
protected List getAllCDIVariableObjects() throws DebugException {
List list = new ArrayList();
list.addAll( getCDIArgumentObjects() );
list.addAll( getCDILocalVariableObjects() );
return list;
}
protected boolean isTopStackFrame() throws DebugException {
IStackFrame tos = getThread().getTopStackFrame();
return tos != null && tos.equals( this );
}
protected void disposeAllVariables() {
if ( fVariables == null )
return;
Iterator it = fVariables.iterator();
while( it.hasNext() ) {
((CVariable)it.next()).dispose();
}
fVariables.clear();
fVariables = null;
}
protected void disposeExpressions() {
if ( fExpressions != null ) {
Iterator it = fExpressions.iterator();
while( it.hasNext() ) {
((CExpression)it.next()).dispose();
}
fExpressions.clear();
}
fExpressions = null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICStackFrame#getAddress()
*/
public IAddress getAddress() {
IAddressFactory factory = ((CDebugTarget)getDebugTarget()).getAddressFactory();
final ICDIStackFrame cdiFrame = getCDIStackFrame();
return cdiFrame != null ? factory.createAddress( cdiFrame.getLocator().getAddress() ) : null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICStackFrame#getFile()
*/
public String getFile() {
final ICDIStackFrame cdiFrame = getCDIStackFrame();
return cdiFrame != null ? cdiFrame.getLocator().getFile() : ""; //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICStackFrame#getFunction()
*/
public String getFunction() {
final ICDIStackFrame cdiFrame = getCDIStackFrame();
return cdiFrame != null ? cdiFrame.getLocator().getFunction() : ""; //$NON-NLS-1$
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICStackFrame#getLevel()
*/
public int getLevel() {
final ICDIStackFrame cdiFrame = getCDIStackFrame();
return cdiFrame != null ? cdiFrame.getLevel() : -1;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICStackFrame#getFrameLineNumber()
*/
public int getFrameLineNumber() {
final ICDIStackFrame cdiFrame = getCDIStackFrame();
return cdiFrame != null ? cdiFrame.getLocator().getLineNumber() : -1;
}
protected synchronized void preserve() {
preserveVariables();
preserveExpressions();
}
private void preserveVariables() {
if ( fVariables == null )
return;
Iterator it = fVariables.iterator();
while( it.hasNext() ) {
AbstractCVariable av = (AbstractCVariable)it.next();
av.preserve();
}
}
private void preserveExpressions() {
if ( fExpressions == null )
return;
Iterator it = fExpressions.iterator();
while( it.hasNext() ) {
CExpression exp = (CExpression)it.next();
exp.preserve();
}
}
protected ICDIVariableDescriptor findVariable( List list, CVariable var ) {
Iterator it = list.iterator();
while( it.hasNext() ) {
ICDIVariableDescriptor newVarObject = (ICDIVariableDescriptor)it.next();
if ( var.sameVariable( newVarObject ) )
return newVarObject;
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRestart#canRestart()
*/
public boolean canRestart() {
return getDebugTarget() instanceof IRestart && ((IRestart)getDebugTarget()).canRestart();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRestart#restart()
*/
public void restart() throws DebugException {
if ( canRestart() ) {
((IRestart)getDebugTarget()).restart();
}
}
public void setRefreshVariables( boolean refresh ) {
fRefreshVariables = refresh;
}
private boolean refreshVariables() {
return fRefreshVariables;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeWithoutSignal#canResumeWithoutSignal()
*/
public boolean canResumeWithoutSignal() {
return (getDebugTarget() instanceof IResumeWithoutSignal && ((IResumeWithoutSignal)getDebugTarget()).canResumeWithoutSignal());
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeWithoutSignal#resumeWithoutSignal()
*/
public void resumeWithoutSignal() throws DebugException {
if ( canResumeWithoutSignal() ) {
((IResumeWithoutSignal)getDebugTarget()).resumeWithoutSignal();
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICStackFrame#evaluateExpression(java.lang.String)
*/
public IValue evaluateExpression( String expressionText ) throws DebugException {
if ( !isDisposed() ) {
CExpression expression = getExpression( expressionText );
if ( expression != null ) {
return expression.getValue( this );
}
}
return null;
}
private ICGlobalVariable[] getGlobals() {
CGlobalVariableManager gvm = ((CDebugTarget)getDebugTarget()).getGlobalVariableManager();
if ( gvm != null ) {
return gvm.getGlobals();
}
return new ICGlobalVariable[0];
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
try {
return getName();
}
catch( DebugException e ) {
return e.getLocalizedMessage();
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICStackFrame#evaluateExpressionToString(java.lang.String)
*/
public String evaluateExpressionToString( String expression ) throws DebugException {
try {
final ICDIStackFrame cdiFrame = getCDIStackFrame();
if (cdiFrame != null) {
return getCDITarget().evaluateExpressionToString( cdiFrame, expression );
}
}
catch( CDIException e ) {
targetRequestFailed( e.getMessage(), null );
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICStackFrame#canEvaluate()
*/
public boolean canEvaluate() {
CDebugTarget target = ((CDebugTarget)getDebugTarget());
return target.supportsExpressionEvaluation() && isSuspended();
}
protected void doStepReturn() throws DebugException {
try {
final ICDIStackFrame cdiFrame = getCDIStackFrame();
if (cdiFrame != null) {
cdiFrame.stepReturn();
}
}
catch( CDIException e ) {
targetRequestFailed( e.getMessage(), null );
}
}
private synchronized CExpression getExpression( String expressionText ) throws DebugException {
if ( isDisposed() ) {
return null;
}
if ( fExpressions == null ) {
fExpressions = new ArrayList( 5 );
}
CExpression expression = null;
Iterator it = fExpressions.iterator();
while( it.hasNext() ) {
expression = (CExpression)it.next();
if ( expression.getExpressionText().compareTo( expressionText ) == 0 ) {
return expression;
}
}
try {
ICDIExpression cdiExpression = ((CDebugTarget)getDebugTarget()).getCDITarget().createExpression( expressionText );
expression = new CExpression( this, cdiExpression, null );
fExpressions.add( expression );
}
catch( CDIException e ) {
targetRequestFailed( e.getMessage(), null );
}
return expression;
}
protected boolean isDisposed() {
return fIsDisposed;
}
private synchronized void setDisposed( boolean isDisposed ) {
fIsDisposed = isDisposed;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRunToLine#canRunToLine(org.eclipse.core.resources.IFile, int)
*/
public boolean canRunToLine( IFile file, int lineNumber ) {
return ((CThread)getThread()).canRunToLine( file, lineNumber );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRunToLine#runToLine(org.eclipse.core.resources.IFile, int, boolean)
*/
public void runToLine( IFile file, int lineNumber, boolean skipBreakpoints ) throws DebugException {
if ( !canRunToLine( file, lineNumber ) )
return;
((CThread)getThread()).runToLine( file, lineNumber, skipBreakpoints );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRunToLine#canRunToLine(java.lang.String, int)
*/
public boolean canRunToLine( String fileName, int lineNumber ) {
return ((CThread)getThread()).canRunToLine( fileName, lineNumber );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRunToLine#runToLine(java.lang.String, int, boolean)
*/
public void runToLine( String fileName, int lineNumber, boolean skipBreakpoints ) throws DebugException {
if ( !canRunToLine( fileName, lineNumber ) )
return;
((CThread)getThread()).runToLine( fileName, lineNumber, skipBreakpoints );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRunToAddress#canRunToAddress(org.eclipse.cdt.core.IAddress)
*/
public boolean canRunToAddress( IAddress address ) {
return getThread().canResume();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IRunToAddress#runToAddress(org.eclipse.cdt.core.IAddress, boolean)
*/
public void runToAddress( IAddress address, boolean skipBreakpoints ) throws DebugException {
if ( !canRunToAddress( address ) )
return;
if ( skipBreakpoints ) {
((CDebugTarget)getDebugTarget()).skipBreakpoints( true );
}
ICDILocation location = getCDITarget().createAddressLocation( new BigInteger( address.toString() ) );
try {
getCDIThread().stepUntil( location );
}
catch( CDIException e ) {
if ( skipBreakpoints ) {
((CDebugTarget)getDebugTarget()).skipBreakpoints( false );
}
targetRequestFailed( e.getMessage(), e );
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeAtLine#canResumeAtLine(org.eclipse.core.resources.IFile, int)
*/
public boolean canResumeAtLine( IFile file, int lineNumber ) {
return getThread().canResume();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeAtLine#resumeAtLine(org.eclipse.core.resources.IFile, int)
*/
public void resumeAtLine( IFile file, int lineNumber ) throws DebugException {
if ( !canResumeAtLine( file, lineNumber ) )
return;
resumeAtLine( file.getLocation().lastSegment(), lineNumber );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeAtLine#canResumeAtLine(java.lang.String, int)
*/
public boolean canResumeAtLine( String fileName, int lineNumber ) {
return getThread().canResume();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeAtLine#resumeAtLine(java.lang.String, int)
*/
public void resumeAtLine( String fileName, int lineNumber ) throws DebugException {
if ( !canResumeAtLine( fileName, lineNumber ) )
return;
ICDILocation location = getCDITarget().createLineLocation( fileName, lineNumber );
try {
ICDIExecuteResume resumer = getCDIThread();
resumer.resume(location);
}
catch( CDIException e ) {
targetRequestFailed( e.getMessage(), e );
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeAtAddress#canResumeAtAddress(org.eclipse.cdt.core.IAddress)
*/
public boolean canResumeAtAddress( IAddress address ) {
return getThread().canResume();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IResumeAtAddress#resumeAtAddress(org.eclipse.cdt.core.IAddress)
*/
public void resumeAtAddress( IAddress address ) throws DebugException {
if ( !canResumeAtAddress( address ) )
return;
ICDILocation location = getCDITarget().createAddressLocation( new BigInteger( address.toString() ) );
try {
getCDIThread().resume( location );
}
catch( CDIException e ) {
targetRequestFailed( e.getMessage(), e );
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IMoveToAddress#canMoveToAddress(org.eclipse.cdt.core.IAddress)
*/
public boolean canMoveToAddress(IAddress address) {
return getThread().isSuspended() && (getCDIThread() instanceof ICDIExecuteMoveInstructionPointer);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IMoveToAddress#moveToAddress(org.eclipse.cdt.core.IAddress)
*/
public void moveToAddress(IAddress address) throws DebugException {
if ( !canMoveToAddress( address ) )
return;
ICDILocation location = getCDITarget().createAddressLocation( new BigInteger( address.toString() ) );
ICDIExecuteMoveInstructionPointer mover = (ICDIExecuteMoveInstructionPointer)getCDIThread();
try {
mover.moveInstructionPointer( location);
}
catch( CDIException e ) {
targetRequestFailed( e.getMessage(), e );
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IMoveToLine#canMoveToLine(java.lang.String, int)
*/
public boolean canMoveToLine(String fileName, int lineNumber) {
return getThread().isSuspended() && (getCDIThread() instanceof ICDIExecuteMoveInstructionPointer);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.IMoveToLine#moveToLine(java.lang.String, int)
*/
public void moveToLine(String fileName, int lineNumber) throws DebugException {
if ( !canMoveToLine( fileName, lineNumber ) )
return;
ICDILocation location= getCDITarget().createLineLocation( fileName, lineNumber );
ICDIExecuteMoveInstructionPointer mover = (ICDIExecuteMoveInstructionPointer)getCDIThread();
try {
mover.moveInstructionPointer( location );
}
catch( CDIException e ) {
targetRequestFailed( e.getMessage(), e );
}
}
private ICDIThread getCDIThread() {
return ((CThread)getThread()).getCDIThread();
}
}