/*******************************************************************************
* Copyright (c) 2004, 2010 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 com.ibm.icu.text.MessageFormat;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.core.ICDebugConstants;
import org.eclipse.cdt.debug.core.cdi.event.ICDIChangedEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDIDestroyedEvent;
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.event.ICDIMemoryChangedEvent;
import org.eclipse.cdt.debug.core.cdi.event.ICDIResumedEvent;
import org.eclipse.cdt.debug.core.cdi.model.ICDIObject;
import org.eclipse.cdt.debug.core.cdi.model.ICDITarget;
import org.eclipse.cdt.debug.core.cdi.model.ICDITargetConfiguration;
import org.eclipse.cdt.debug.core.cdi.model.ICDITargetConfiguration2;
import org.eclipse.cdt.debug.core.cdi.model.ICDITargetConfiguration3;
import org.eclipse.cdt.debug.core.cdi.model.ICDIVariable;
import org.eclipse.cdt.debug.core.cdi.model.ICDIVariableDescriptor;
import org.eclipse.cdt.debug.core.model.CVariableFormat;
import org.eclipse.cdt.debug.core.model.ICDebugElementStatus;
import org.eclipse.cdt.debug.core.model.ICType;
import org.eclipse.cdt.debug.core.model.ICValue;
import org.eclipse.cdt.debug.internal.core.CSettingsManager;
import org.eclipse.cdt.debug.internal.core.ICWatchpointTarget;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IValue;
/**
* A thin wrapper over the CVariable for injection into the CDI event manager's
* listener collection. We used to directly inject the CVariable, but that's
* problematic since CVariable overrides the equals() method to base the
* decision on the internal variable object. So if two CVariables were added to
* the listener list for the same underlying value, trying to later remove one
* of the listeners had a 50/50 chance of removing the wrong one.
*
* How can you end up with two CVariables for the same internal variable on the
* listener list? Easy.
* 1. View a register in the Registers view.
* 2. Create a custom register group that contains the same register.
* 3. Expand the custom register group
* 4. Remove the custom register group
* Step 4 removed the wrong CVariable from the listener list.
*
*/
class VariableEventListener implements ICDIEventListener {
private CVariable fVar;
public VariableEventListener(CVariable var) {
fVar = var;
}
/* (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) {
fVar.handleDebugEvents(events);
}
}
/**
* Represents a variable in the CDI model.
*/
public abstract class CVariable extends AbstractCVariable implements ICDIEventListener, ICWatchpointTarget {
interface IInternalVariable {
IInternalVariable createShadow( int start, int length ) throws DebugException;
IInternalVariable createShadow( String type ) throws DebugException;
CType getType() throws DebugException;
String getQualifiedName() throws DebugException;
ICValue getValue() throws DebugException;
void setValue( String expression ) throws DebugException;
boolean isChanged();
void setChanged( boolean changed );
void dispose( boolean destroy );
boolean isSameDescriptor( ICDIVariableDescriptor desc );
boolean isSameVariable( ICDIVariable cdiVar );
void resetValue();
boolean isEditable() throws DebugException;
boolean isArgument();
int sizeof();
void invalidateValue();
void preserve();
// Note: the CDI object association can change; e.g., if a "Cast to Type"
// or "Display as Array" is done on the element.
ICDIObject getCdiObject();
}
/**
* Whether this variable is currently enabled.
*/
private boolean fIsEnabled = true;
/**
* The original internal variable.
*/
private IInternalVariable fOriginal;
/**
* The shadow internal variable used for casting.
*/
private IInternalVariable fShadow;
/**
* The name of this variable.
*/
private String fName;
/**
* The current format of this variable.
*/
private CVariableFormat fFormat = CVariableFormat.getFormat( CDebugCorePlugin.getDefault().getPluginPreferences().getInt( ICDebugConstants.PREF_DEFAULT_VARIABLE_FORMAT ) );
/**
* Whether this variable has been disposed.
*/
private boolean fIsDisposed = false;
/**
* Thin wrapper for instertion into the CDI event manager's listener list
*/
private VariableEventListener fEventListenerWrapper;
/**
* Constructor for CVariable.
*/
protected CVariable( CDebugElement parent, ICDIVariableDescriptor cdiVariableObject ) {
super( parent );
fEventListenerWrapper = new VariableEventListener(this);
if ( cdiVariableObject != null ) {
setName( cdiVariableObject.getName() );
createOriginal( cdiVariableObject );
}
fIsEnabled = ( parent instanceof AbstractCValue ) ? ((AbstractCValue)parent).getParentVariable().isEnabled() : !isBookkeepingEnabled();
getCDISession().getEventManager().addEventListener( fEventListenerWrapper );
if ( cdiVariableObject != null ) {
setInitialFormat();
}
}
/**
* Constructor for CVariable.
*/
protected CVariable( CDebugElement parent, ICDIVariableDescriptor cdiVariableObject, String errorMessage ) {
super( parent );
fEventListenerWrapper = new VariableEventListener(this);
if ( cdiVariableObject != null ) {
setName( cdiVariableObject.getName() );
createOriginal( cdiVariableObject );
}
fIsEnabled = !isBookkeepingEnabled();
setStatus( ICDebugElementStatus.ERROR, MessageFormat.format( CoreModelMessages.getString( "CVariable.1" ), new String[]{ errorMessage } ) ); //$NON-NLS-1$
getCDISession().getEventManager().addEventListener( fEventListenerWrapper );
if ( cdiVariableObject != null ) {
setInitialFormat();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICVariable#getType()
*/
public ICType getType() throws DebugException {
if ( isDisposed() )
return null;
IInternalVariable iv = getCurrentInternalVariable();
return ( iv != null ) ? iv.getType() : null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICVariable#isEnabled()
*/
public boolean isEnabled() {
return fIsEnabled;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICVariable#setEnabled(boolean)
*/
public void setEnabled( boolean enabled ) throws DebugException {
// Debugger engines that use active variable objects will benefit
// performance-wise if we dispose the internal variable when it's
// disabled by the user (it will automatically get lazily recreated if
// it's ever needed again). Engines using passive variables probably
// won't, so we can defer the dispose until we have no use for the
// variable altogether.
boolean disposeVariable = true;
ICDITargetConfiguration configuration = getParent().getCDITarget().getConfiguration();
if (configuration instanceof ICDITargetConfiguration2) {
disposeVariable = !((ICDITargetConfiguration2)configuration).supportsPassiveVariableUpdate();
}
if (disposeVariable) {
IInternalVariable iv = getOriginal();
if ( iv != null )
iv.dispose( true );
iv = getShadow();
if ( iv != null )
iv.dispose( true );
}
fIsEnabled = enabled;
fireChangeEvent( DebugEvent.STATE );
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICVariable#canEnableDisable()
*/
public boolean canEnableDisable() {
return !( getParent() instanceof IValue );
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICVariable#isArgument()
*/
public boolean isArgument() {
IInternalVariable iv = getOriginal();
return ( iv != null ) ? iv.isArgument() : false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.model.IVariable#getValue()
*/
public IValue getValue() throws DebugException {
if ( !isDisposed() && isEnabled() ) {
IInternalVariable iv = getCurrentInternalVariable();
if ( iv != null ) {
try {
return iv.getValue();
}
catch( DebugException e ) {
setStatus( ICDebugElementStatus.ERROR, e.getMessage() );
}
}
}
return CValueFactory.NULL_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 {
ICType type = getType();
return ( type != null ) ? type.getName() : ""; //$NON-NLS-1$
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.model.IVariable#hasValueChanged()
*/
public boolean hasValueChanged() throws DebugException {
if ( isDisposed() )
return false;
IInternalVariable iv = getCurrentInternalVariable();
return ( iv != null ) ? iv.isChanged() : false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.IFormatSupport#supportsFormatting()
*/
public boolean supportsFormatting() {
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.IFormatSupport#getFormat()
*/
public CVariableFormat getFormat() {
return fFormat;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.IFormatSupport#changeFormat(org.eclipse.cdt.debug.core.model.CVariableFormat)
*/
public void changeFormat( CVariableFormat format ) throws DebugException {
setFormat( format );
storeFormat( format );
resetValue();
}
/*
* (non-Javadoc)
* Allow this operation only for the pointer types (???).
*
* @see org.eclipse.cdt.debug.core.model.ICastToArray#canCastToArray()
*/
public boolean canCastToArray() {
ICType type;
try {
type = getType();
return ( getOriginal() != null && isEnabled() && type != null && type.isPointer() );
}
catch( DebugException e ) {
}
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICastToArray#castToArray(int, int)
*/
public void castToArray( int startIndex, int length ) throws DebugException {
IInternalVariable current = getCurrentInternalVariable();
if ( current != null ) {
IInternalVariable newVar = current.createShadow( startIndex, length );
if ( getShadow() != null )
getShadow().dispose( true );
setShadow( newVar );
// If casting of variable to a type or array causes an error, the status
// of the variable is set to "error" and it can't be reset by subsequent castings.
resetValue();
storeCastToArray( startIndex, length );
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.model.IValueModification#setValue(java.lang.String)
*/
public void setValue( String expression ) throws DebugException {
IInternalVariable iv = getCurrentInternalVariable();
if ( iv != null ) {
String newExpression = processExpression( expression );
iv.setValue( newExpression );
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.model.IValueModification#setValue(org.eclipse.debug.core.model.IValue)
*/
public void setValue( IValue value ) throws DebugException {
notSupported( CoreModelMessages.getString( "CVariable.3" ) ); //$NON-NLS-1$
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.model.IValueModification#supportsValueModification()
*/
public boolean supportsValueModification() {
try {
return fIsEnabled ? getCurrentInternalVariable().isEditable() : false;
}
catch( DebugException e ) {
}
return false;
}
/*
* (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 value.getDebugTarget().equals( getDebugTarget() );
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICastToType#canCast()
*/
public boolean canCast() {
return ( getOriginal() != null && isEnabled() );
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICastToType#getCurrentType()
*/
public String getCurrentType() {
String typeName = ""; //$NON-NLS-1$
try {
typeName = getReferenceTypeName();
}
catch( DebugException e ) {
}
return typeName;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICastToType#cast(java.lang.String)
*/
public void cast( String type ) throws DebugException {
IInternalVariable current = getCurrentInternalVariable();
if ( current != null ) {
IInternalVariable newVar = current.createShadow( type );
if ( getShadow() != null )
getShadow().dispose( true );
setShadow( newVar );
// If casting of variable to a type or array causes an error, the status
// of the variable is set to "error" and it can't be reset by subsequent castings.
resetValue();
storeCast(type);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICastToType#restoreOriginal()
*/
public void restoreOriginal() throws DebugException {
IInternalVariable oldVar = getShadow();
setShadow( null );
if ( oldVar != null )
oldVar.dispose( true );
IInternalVariable iv = getOriginal();
if ( iv != null )
iv.invalidateValue();
// If casting of variable to a type or array causes an error, the status
// of the variable is set to "error" and it can't be reset by subsequent castings.
resetValue();
forgetCast();
forgetCastToArray();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.debug.core.model.ICastToType#isCasted()
*/
public boolean isCasted() {
return ( getShadow() != null );
}
/*
* (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 ) {
IInternalVariable iv = getCurrentInternalVariable();
if ( iv == null )
return;
for( int i = 0; i < events.length; i++ ) {
ICDIEvent event = events[i];
ICDIObject source = event.getSource();
if ( source == null )
continue;
ICDITarget target = source.getTarget();
if ( target.equals( getCDITarget() ) ) {
if ( event instanceof ICDIMemoryChangedEvent &&
target.getConfiguration() instanceof ICDITargetConfiguration3 &&
((ICDITargetConfiguration3)target.getConfiguration()).needsVariablesUpdated(event)) {
resetValue();
}
else if ( event instanceof ICDIChangedEvent ) {
if ( source instanceof ICDIVariable && iv.isSameVariable( (ICDIVariable)source ) ) {
handleChangedEvent( (ICDIChangedEvent)event );
}
}
else if ( event instanceof ICDIResumedEvent ) {
handleResumedEvent( (ICDIResumedEvent)event );
}
else if (event instanceof ICDIDestroyedEvent
&& iv.getCdiObject() == source) {
dispose();
fireChangeEvent(DebugEvent.STATE);
}
}
}
}
private void handleResumedEvent( ICDIResumedEvent event ) {
boolean changed = false;
if ( hasErrors() ) {
resetStatus();
changed = true;
IInternalVariable iv = getCurrentInternalVariable();
if ( iv != null )
iv.invalidateValue();
}
if ( changed )
fireChangeEvent( DebugEvent.STATE );
}
private void handleChangedEvent( ICDIChangedEvent event ) {
IInternalVariable iv = getCurrentInternalVariable();
if ( iv != null ) {
iv.setChanged( true );
fireChangeEvent( DebugEvent.STATE );
}
}
private IInternalVariable getCurrentInternalVariable() {
if ( getShadow() != null )
return getShadow();
return getOriginal();
}
private IInternalVariable getOriginal() {
return fOriginal;
}
protected void setOriginal( IInternalVariable original ) {
fOriginal = original;
}
private IInternalVariable getShadow() {
return fShadow;
}
private void setShadow( IInternalVariable shadow ) {
fShadow = shadow;
}
protected boolean isBookkeepingEnabled() {
boolean result = false;
try {
result = getLaunch().getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ENABLE_VARIABLE_BOOKKEEPING, false );
}
catch( CoreException e ) {
}
return result;
}
abstract protected void createOriginal( ICDIVariableDescriptor vo );
protected boolean hasErrors() {
return !isOK();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.core.model.AbstractCVariable#setChanged(boolean)
*/
@Override
protected void setChanged( boolean changed ) {
IInternalVariable iv = getCurrentInternalVariable();
if ( iv != null ) {
iv.setChanged( changed );
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.core.model.AbstractCVariable#resetValue()
*/
@Override
protected void resetValue() {
IInternalVariable iv = getCurrentInternalVariable();
if ( iv != null ) {
resetStatus();
iv.resetValue();
fireChangeEvent( DebugEvent.STATE );
}
}
private String processExpression( String oldExpression ) {
return oldExpression;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.core.model.AbstractCVariable#dispose()
*/
@Override
public void dispose() {
// Hack: do not destroy local variables
internalDispose( false );
setDisposed( true );
}
public int sizeof() {
IInternalVariable iv = getCurrentInternalVariable();
return ( iv != null ) ? iv.sizeof() : -1;
}
/**
* Compares the original internal variables.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals( Object obj ) {
if ( obj instanceof CVariable ) {
// A disposed copy can be stored in the viewer.
// false should be returned to force the viewer to
// replace it by a new variable. See bug #115385
if ( isDisposed() != ((CVariable)obj).isDisposed() )
return false;
IInternalVariable iv = getOriginal();
return ( iv != null ) ? iv.equals( ((CVariable)obj).getOriginal() ) : false;
}
return false;
}
protected boolean sameVariable( ICDIVariableDescriptor vo ) {
IInternalVariable iv = getOriginal();
return ( iv != null && iv.isSameDescriptor( vo ) );
}
protected void setFormat( CVariableFormat format ) {
fFormat = format;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.core.model.ICVariable#getExpressionString()
*/
public String getExpressionString() throws DebugException {
IInternalVariable iv = getCurrentInternalVariable();
return ( iv != null ) ? iv.getQualifiedName() : null;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.core.model.AbstractCVariable#preserve()
*/
@Override
protected void preserve() {
resetStatus();
IInternalVariable iv = getCurrentInternalVariable();
if ( iv != null )
iv.preserve();
}
protected void internalDispose( boolean destroy ) {
getCDISession().getEventManager().removeEventListener( fEventListenerWrapper );
IInternalVariable iv = getOriginal();
if ( iv != null )
iv.dispose( destroy );
iv = getShadow();
if ( iv != null )
iv.dispose( destroy );
}
protected boolean isDisposed() {
return fIsDisposed;
}
protected void setDisposed( boolean isDisposed ) {
fIsDisposed = isDisposed;
}
protected void invalidateValue() {
resetStatus();
IInternalVariable iv = getCurrentInternalVariable();
if ( iv != null )
iv.invalidateValue();
}
protected void setName( String name ) {
fName = name;
}
public ICDIObject getCdiObject() {
IInternalVariable iv = getCurrentInternalVariable();
if ( iv != null ) {
return iv.getCdiObject();
}
return null;
}
protected CSettingsManager getFormatManager() {
return ((CDebugTarget) getDebugTarget()).getFormatManager();
}
/**
* used to concatenate multiple names to a single identifier
*/
private final static String NAME_PART_SEPARATOR = "-"; //$NON-NLS-1$
/**
* suffix used to identify format informations
*/
private final static String FORMAT_SUFFIX = NAME_PART_SEPARATOR + "(format)"; //$NON-NLS-1$
/**
* suffix used to identify cast settings
*/
private final static String CAST_SUFFIX = NAME_PART_SEPARATOR + "(cast)"; //$NON-NLS-1$
/**
* suffix used to identify cast to array settings
*/
private final static String CAST_TO_ARRAY_SUFFIX = NAME_PART_SEPARATOR + "(cast_to_array)"; //$NON-NLS-1$
/** retrieve the identification for this variable.
* @return a string identifying this variable, to be used to store settings
* @throws DebugException
*/
String getVariableID() throws DebugException {
return getName(); // TODO: better identification if multiple variables have the same name
}
/** helper to generate a string id used to persist the settings.
* @param next_obj next object to encode into the id
* @param buf contains the id of the part encoded so far.
* @throws DebugException
*/
static private void buildPesistID( CDebugElement next_obj, StringBuffer buf ) throws DebugException {
if ( next_obj instanceof CVariable ) {
CVariable cVariableParent = (CVariable) next_obj;
buf.append( NAME_PART_SEPARATOR );
buf.append( cVariableParent.getVariableID() );
buildPesistID( cVariableParent.getParent(), buf );
} else if ( next_obj instanceof CStackFrame ) {
buf.append(NAME_PART_SEPARATOR);
// TODO: better identification if multiple functions have the same name (say for static functions)
buf.append( ((CStackFrame)next_obj ).getFunction() );
} else if ( next_obj instanceof CDebugTarget ) {
// global, we use a root NAME_PART_SEPARATOR as indicator of that
buf.append( NAME_PART_SEPARATOR );
} else if ( next_obj instanceof AbstractCValue ) {
// index or indirection.
AbstractCValue av = (AbstractCValue) next_obj;
buildPesistID( av.getParentVariable(), buf );
}
}
/** returns an string used to identify this variable
* @return
* @throws DebugException
*/
private final String getPersistID() throws DebugException {
StringBuffer id = new StringBuffer();
id.append( getVariableID() );
buildPesistID( getParent(), id );
return id.toString();
}
/** stores the given format
* @param format the format to be used for this variable
*/
protected void storeFormat( CVariableFormat format ) {
try {
String formatString = Integer.toString( format.getFormatNumber() );
getFormatManager().putValue( getPersistID() + FORMAT_SUFFIX, formatString );
} catch ( DebugException e ) {
// if we do not get the name, we use the default format, no reason for the creation to fail too.
DebugPlugin.log( e );
}
}
/** stores the cast information.
* @param type the type to be displayed instead
*/
protected void storeCast( String type ) {
try {
String id = getPersistID() + CAST_SUFFIX;
getFormatManager().putValue( id, type );
} catch ( DebugException e ) {
DebugPlugin.log( e );
}
}
/** drops the cast information.
*/
protected void forgetCast() {
try {
String id = getPersistID() + CAST_SUFFIX;
getFormatManager().removeValue( id );
} catch ( DebugException e ) {
DebugPlugin.log( e );
}
}
/** stores the cast array information.
* @param startIndex the first item to be displayed in the cast array operation
* @param length the number of elements to display
*/
protected void storeCastToArray(int startIndex, int length) {
try {
// we persist the information in a (startIndex):(Length) format.
String content = Integer.toString( startIndex ) + ":" + Integer.toString( length ); //$NON-NLS-1$
getFormatManager().putValue( getPersistID() + CAST_TO_ARRAY_SUFFIX, content );
} catch ( DebugException e ) {
DebugPlugin.log( e );
}
}
/** drops previously stored cast array information.
*/
protected void forgetCastToArray() {
try {
String id = getPersistID() + CAST_TO_ARRAY_SUFFIX;
getFormatManager().removeValue( id );
} catch ( DebugException e ) {
DebugPlugin.log( e );
}
}
/**
* restore the format stored previously for this variable.
* Only sets explicitly retrieved formats in order to maintain defaults.
*/
protected void setInitialFormat() {
try {
String persistID= getPersistID();
String stringFormat = getFormatManager().getValue( persistID + FORMAT_SUFFIX );
if ( stringFormat != null ) {
try {
CVariableFormat format = CVariableFormat.getFormat( Integer.parseInt( stringFormat ) );
setFormat( format );
} catch ( NumberFormatException e ) {
DebugPlugin.log( e );
}
}
if ( canCast() ) {
String castString = getFormatManager().getValue( persistID + CAST_SUFFIX );
if ( castString != null ) {
cast( castString );
}
}
if ( canCastToArray() ) {
String castToArrayString = getFormatManager().getValue( persistID + CAST_TO_ARRAY_SUFFIX );
if (castToArrayString != null) {
int index = castToArrayString.indexOf( ':' );
if ( index > 0 ) {
try {
int beg = Integer.parseInt( castToArrayString.substring( 0, index ) );
int num = Integer.parseInt( castToArrayString.substring( index + 1 ) );
castToArray( beg, num );
} catch ( NumberFormatException e ) {
DebugPlugin.log( e );
}
} else {
DebugPlugin.logMessage( "did not find expected : for cast to array", null ); //$NON-NLS-1$
}
}
}
} catch ( DebugException e ) {
DebugPlugin.log( e );
// we drop (and log) the exception here.
// even if the initial setup fails, we still want the complete creation to be successful
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.core.IWatchpointTarget#getExpression()
*/
public String getExpression() {
try {
return getExpressionString();
} catch (DebugException e) {
return ""; //$NON-NLS-1$
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.core.IWatchpointTarget#getSize()
*/
public void getSize(ICWatchpointTarget.GetSizeRequest request) {
// CDI has synchronous APIs, so this is easy...
request.setSize(sizeof());
request.done();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.debug.internal.core.IWatchpointTarget#canCreateWatchpoint(org.eclipse.cdt.debug.internal.core.IWatchpointTarget.CanCreateWatchpointRequest)
*/
public void canSetWatchpoint(ICWatchpointTarget.CanCreateWatchpointRequest request) {
// CDI has synchronous APIs, so this is easy...
request.setCanCreate(sizeof() > 0);
request.done();
}
}